@manfred-kunze-dev/backbone-mcp-server 2.6.0-dev.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +19 -0
- package/README.md +311 -0
- package/dist/client.d.ts +8 -0
- package/dist/client.js +38 -0
- package/dist/errors.d.ts +15 -0
- package/dist/errors.js +22 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +75 -0
- package/dist/mime.d.ts +2 -0
- package/dist/mime.js +53 -0
- package/dist/schema-compat.d.ts +11 -0
- package/dist/schema-compat.js +51 -0
- package/dist/tools/ai-gateway.d.ts +4 -0
- package/dist/tools/ai-gateway.js +107 -0
- package/dist/tools/conversion.d.ts +4 -0
- package/dist/tools/conversion.js +197 -0
- package/dist/tools/docs.d.ts +4 -0
- package/dist/tools/docs.js +171 -0
- package/dist/tools/extraction.d.ts +4 -0
- package/dist/tools/extraction.js +252 -0
- package/dist/tools/projects.d.ts +4 -0
- package/dist/tools/projects.js +129 -0
- package/dist/tools/schema-testing.d.ts +4 -0
- package/dist/tools/schema-testing.js +102 -0
- package/dist/tools/schema-versions.d.ts +4 -0
- package/dist/tools/schema-versions.js +129 -0
- package/dist/tools/schemas.d.ts +4 -0
- package/dist/tools/schemas.js +138 -0
- package/dist/tools/transcription.d.ts +4 -0
- package/dist/tools/transcription.js +76 -0
- package/package.json +48 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Copyright (c) 2025-present Manfred Kunze Dev
|
|
2
|
+
|
|
3
|
+
All rights reserved.
|
|
4
|
+
|
|
5
|
+
This software and associated documentation files (the "Software") are proprietary
|
|
6
|
+
and confidential. No part of the Software may be reproduced, distributed, or
|
|
7
|
+
transmitted in any form or by any means, including photocopying, recording, or
|
|
8
|
+
other electronic or mechanical methods, without the prior written permission of
|
|
9
|
+
the copyright holder.
|
|
10
|
+
|
|
11
|
+
The Software is provided "as is", without warranty of any kind, express or implied,
|
|
12
|
+
including but not limited to the warranties of merchantability, fitness for a
|
|
13
|
+
particular purpose, and noninfringement. In no event shall the authors or copyright
|
|
14
|
+
holders be liable for any claim, damages, or other liability, whether in an action
|
|
15
|
+
of contract, tort, or otherwise, arising from, out of, or in connection with the
|
|
16
|
+
Software or the use or other dealings in the Software.
|
|
17
|
+
|
|
18
|
+
Usage of this Software is permitted only in accordance with the terms and conditions
|
|
19
|
+
set forth by Manfred Kunze Dev.
|
package/README.md
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
# Backbone MCP Server
|
|
2
|
+
|
|
3
|
+
An [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) server that exposes the Backbone AI platform as tools for LLMs. It lets AI assistants manage projects, define schemas, run extractions, convert documents, transcribe audio, and more — all through a standardized tool interface.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
### Prerequisites
|
|
8
|
+
|
|
9
|
+
- **Node.js** >= 18.0.0
|
|
10
|
+
- **Backbone backend** running and accessible (local or remote)
|
|
11
|
+
- A valid **API key** for the Backbone backend
|
|
12
|
+
|
|
13
|
+
### Install Dependencies
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
cd mcp
|
|
17
|
+
npm install
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Build
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm run build
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
This compiles TypeScript from `src/` into `dist/`.
|
|
27
|
+
|
|
28
|
+
### Environment Variables
|
|
29
|
+
|
|
30
|
+
| Variable | Required | Default | Description |
|
|
31
|
+
|---|---|---|---|
|
|
32
|
+
| `BACKBONE_API_KEY` | Yes | — | API key for authenticating with the Backbone backend |
|
|
33
|
+
| `BACKBONE_BASE_URL` | No | `https://backbone.manfred-kunze.dev/api` | Base URL of the Backbone backend including the API prefix. Override for local development (e.g. `http://localhost:8080/api`) |
|
|
34
|
+
| `MCP_TRANSPORT` | No | `stdio` | Transport mode: `stdio` or `http` |
|
|
35
|
+
| `MCP_HTTP_PORT` | No | `3100` | Port for the HTTP transport (only used when `MCP_TRANSPORT=http`) |
|
|
36
|
+
|
|
37
|
+
### Running the Server
|
|
38
|
+
|
|
39
|
+
**Stdio transport** (default — for use with Claude Code, Cursor, etc.):
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
BACKBONE_API_KEY=your-key BACKBONE_BASE_URL=http://localhost:8080/api npm start
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**HTTP transport** (for network-accessible deployments):
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
BACKBONE_API_KEY=your-key BACKBONE_BASE_URL=http://localhost:8080/api MCP_TRANSPORT=http npm start
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The HTTP server exposes:
|
|
52
|
+
- `POST /mcp` — MCP Streamable HTTP endpoint
|
|
53
|
+
- `GET /health` — Health check
|
|
54
|
+
|
|
55
|
+
**Development mode** (auto-recompile on changes):
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm run dev
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Connecting to Claude Code
|
|
62
|
+
|
|
63
|
+
Add the server to your Claude Code MCP configuration (`.claude/settings.local.json` or similar):
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"mcpServers": {
|
|
68
|
+
"backbone": {
|
|
69
|
+
"command": "npx",
|
|
70
|
+
"args": ["@manfred-kunze-dev/backbone-mcp-server"],
|
|
71
|
+
"env": {
|
|
72
|
+
"BACKBONE_API_KEY": "your-api-key",
|
|
73
|
+
"BACKBONE_BASE_URL": "http://localhost:8080/api"
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Connecting to Cursor
|
|
81
|
+
|
|
82
|
+
Add to your `.cursor/mcp.json`:
|
|
83
|
+
u
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"mcpServers": {
|
|
87
|
+
"backbone": {
|
|
88
|
+
"command": "npx",
|
|
89
|
+
"args": ["@manfred-kunze-dev/backbone-mcp-server"],
|
|
90
|
+
"env": {
|
|
91
|
+
"BACKBONE_API_KEY": "your-api-key",
|
|
92
|
+
"BACKBONE_BASE_URL": "http://localhost:8080/api"
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
> **Installing from the GitLab registry:** Configure npm to use the GitLab registry for the `@manfred-kunze-dev` scope by adding this to your `.npmrc`:
|
|
100
|
+
> ```
|
|
101
|
+
> @manfred-kunze-dev:registry=https://gitlab.com/api/v4/projects/<PROJECT_ID>/packages/npm/
|
|
102
|
+
> //gitlab.com/api/v4/projects/<PROJECT_ID>/packages/npm/:_authToken=<YOUR_TOKEN>
|
|
103
|
+
> ```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Available Tools
|
|
108
|
+
|
|
109
|
+
### Projects
|
|
110
|
+
|
|
111
|
+
Manage projects within your organization.
|
|
112
|
+
|
|
113
|
+
| Tool | Description | Parameters |
|
|
114
|
+
|---|---|---|
|
|
115
|
+
| `backbone_list_projects` | List projects with optional search and pagination | `search?`, `page?`, `size?`, `sort?` |
|
|
116
|
+
| `backbone_get_project` | Get a project by ID | `projectId` |
|
|
117
|
+
| `backbone_create_project` | Create a new project | `name`, `description?` |
|
|
118
|
+
| `backbone_update_project` | Update a project | `projectId`, `name?`, `description?` |
|
|
119
|
+
| `backbone_delete_project` | Delete a project and all its data (irreversible) | `projectId` |
|
|
120
|
+
|
|
121
|
+
### Schemas
|
|
122
|
+
|
|
123
|
+
Define extraction schemas within projects. Schemas describe the structure of data to extract.
|
|
124
|
+
|
|
125
|
+
| Tool | Description | Parameters |
|
|
126
|
+
|---|---|---|
|
|
127
|
+
| `backbone_list_schemas` | List schemas in a project | `projectId`, `search?`, `page?`, `size?`, `sort?` |
|
|
128
|
+
| `backbone_get_schema` | Get a schema by ID | `projectId`, `schemaId` |
|
|
129
|
+
| `backbone_create_schema` | Create a new schema | `projectId`, `name`, `description?`, `content?` |
|
|
130
|
+
| `backbone_update_schema` | Update a schema | `projectId`, `schemaId`, `name?`, `description?`, `content?` |
|
|
131
|
+
| `backbone_delete_schema` | Delete a schema and all its versions (irreversible) | `projectId`, `schemaId` |
|
|
132
|
+
|
|
133
|
+
### Schema Versions
|
|
134
|
+
|
|
135
|
+
Manage versioned snapshots of schema definitions.
|
|
136
|
+
|
|
137
|
+
| Tool | Description | Parameters |
|
|
138
|
+
|---|---|---|
|
|
139
|
+
| `backbone_create_schema_version` | Create a new version (becomes active) | `projectId`, `schemaId`, `jsonSchema`, `changeDescription?` |
|
|
140
|
+
| `backbone_list_schema_versions` | List all versions of a schema | `projectId`, `schemaId`, `page?`, `size?` |
|
|
141
|
+
| `backbone_get_schema_version` | Get a specific version | `projectId`, `schemaId`, `versionId` |
|
|
142
|
+
| `backbone_get_latest_schema_version` | Get the latest active version | `projectId`, `schemaId` |
|
|
143
|
+
| `backbone_activate_schema_version` | Re-activate a historical version | `projectId`, `schemaId`, `versionId` |
|
|
144
|
+
|
|
145
|
+
### Schema Testing
|
|
146
|
+
|
|
147
|
+
Validate schemas and test extractions without persisting data.
|
|
148
|
+
|
|
149
|
+
| Tool | Description | Parameters |
|
|
150
|
+
|---|---|---|
|
|
151
|
+
| `backbone_validate_schema` | Validate a JSON Schema definition | `projectId`, `schemaId`, `jsonSchema` |
|
|
152
|
+
| `backbone_test_schema` | Test a schema against sample text with AI extraction | `projectId`, `schemaId`, `jsonSchema`, `sampleText`, `model` |
|
|
153
|
+
|
|
154
|
+
### Extractions
|
|
155
|
+
|
|
156
|
+
Extract structured data from text using schemas and AI models.
|
|
157
|
+
|
|
158
|
+
| Tool | Description | Parameters |
|
|
159
|
+
|---|---|---|
|
|
160
|
+
| `backbone_create_extraction` | Extract data from text (sync or async) | `projectId`, `schemaId`, `inputText`, `model`, `schemaVersionId?`, `async?` |
|
|
161
|
+
| `backbone_get_extraction` | Get an extraction by ID (check status or retrieve results) | `projectId`, `extractionId` |
|
|
162
|
+
| `backbone_list_extractions` | List extractions with filtering | `projectId`, `status?`, `schemaVersionId?`, `search?`, `page?`, `size?`, `sort?` |
|
|
163
|
+
| `backbone_estimate_tokens` | Estimate token usage without executing | `projectId`, `schemaId`, `inputText`, `schemaVersionId?` |
|
|
164
|
+
| `backbone_rerun_extraction` | Re-run an existing extraction | `projectId`, `extractionId` |
|
|
165
|
+
|
|
166
|
+
### Document Conversion
|
|
167
|
+
|
|
168
|
+
Convert documents (PDF, DOCX, etc.) to Markdown, text, HTML, or JSON.
|
|
169
|
+
|
|
170
|
+
| Tool | Description | Parameters |
|
|
171
|
+
|---|---|---|
|
|
172
|
+
| `backbone_convert_document` | Convert documents from URLs, base64, or local files | `sources[]` (type, url/data/path, filename), `outputFormats?`, `pageRange?`, `async?` |
|
|
173
|
+
| `backbone_get_task_status` | Check status of an async conversion task | `taskId`, `wait?` |
|
|
174
|
+
| `backbone_get_task_result` | Get the result of a completed conversion | `taskId` |
|
|
175
|
+
|
|
176
|
+
Each source in `sources` can be:
|
|
177
|
+
- **`url`** — fetch from a URL
|
|
178
|
+
- **`base64`** — provide raw base64 data with a filename
|
|
179
|
+
- **`file`** — provide a local file path (automatically read and encoded)
|
|
180
|
+
|
|
181
|
+
### Audio Transcription
|
|
182
|
+
|
|
183
|
+
Transcribe audio files using AI models.
|
|
184
|
+
|
|
185
|
+
| Tool | Description | Parameters |
|
|
186
|
+
|---|---|---|
|
|
187
|
+
| `backbone_transcribe_audio` | Transcribe an audio file | `filePath`, `model`, `language?`, `prompt?`, `responseFormat?`, `temperature?` |
|
|
188
|
+
|
|
189
|
+
Supported formats: flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, webm.
|
|
190
|
+
|
|
191
|
+
### AI Gateway
|
|
192
|
+
|
|
193
|
+
Access multiple AI providers through a unified OpenAI-compatible interface.
|
|
194
|
+
|
|
195
|
+
| Tool | Description | Parameters |
|
|
196
|
+
|---|---|---|
|
|
197
|
+
| `backbone_chat` | Send a chat completion request | `model`, `messages[]`, `temperature?`, `max_tokens?`, `top_p?`, `frequency_penalty?`, `presence_penalty?`, `stop?`, `response_format?`, `tools?`, `tool_choice?` |
|
|
198
|
+
| `backbone_list_models` | List available AI models and providers | *(none)* |
|
|
199
|
+
|
|
200
|
+
Models use the format `provider/model` (e.g. `openai/gpt-4o`, `anthropic/claude-sonnet-4-5-20250929`).
|
|
201
|
+
|
|
202
|
+
### API Documentation
|
|
203
|
+
|
|
204
|
+
Browse the backend's OpenAPI documentation by section. Useful for understanding endpoint details, request/response shapes, and parameter constraints.
|
|
205
|
+
|
|
206
|
+
| Tool | Description | Parameters |
|
|
207
|
+
|---|---|---|
|
|
208
|
+
| `backbone_list_api_doc_sections` | List available doc sections (tags) with endpoint counts | *(none)* |
|
|
209
|
+
| `backbone_get_api_docs` | Fetch filtered docs for a specific section | `tag` |
|
|
210
|
+
|
|
211
|
+
> **Note:** Requires `SPRINGDOC_ENABLED=true` on the backend. If docs are disabled, these tools return an informative error message.
|
|
212
|
+
|
|
213
|
+
The `get_api_docs` tool returns only the endpoints and schemas relevant to the requested tag, keeping context usage minimal. The OpenAPI spec is cached in memory after the first fetch.
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Development
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
# Build
|
|
221
|
+
npm run build
|
|
222
|
+
|
|
223
|
+
# Dev mode (watch + auto-recompile)
|
|
224
|
+
npm run dev
|
|
225
|
+
|
|
226
|
+
# Start
|
|
227
|
+
npm start
|
|
228
|
+
|
|
229
|
+
# Type-check without emitting
|
|
230
|
+
npm run typecheck
|
|
231
|
+
|
|
232
|
+
# Debug with MCP Inspector
|
|
233
|
+
npm run inspect
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### OpenAPI Type Generation
|
|
237
|
+
|
|
238
|
+
Types are generated from the backend's OpenAPI spec using `openapi-typescript`. This ensures that all API calls are type-checked at compile time — if the backend renames a field, the MCP server won't compile until updated.
|
|
239
|
+
|
|
240
|
+
**Prerequisites:**
|
|
241
|
+
- A running Backbone backend at `http://localhost:8080` (or pass a custom URL as argument)
|
|
242
|
+
- `BACKBONE_API_KEY` set — either in a `.env` file or as an environment variable
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
# Set up your .env (one-time)
|
|
246
|
+
cp .env.example .env
|
|
247
|
+
# Then edit .env with your API key
|
|
248
|
+
|
|
249
|
+
# Full pipeline: fetch spec from backend + generate TypeScript types
|
|
250
|
+
npm run generate
|
|
251
|
+
|
|
252
|
+
# Individual steps:
|
|
253
|
+
npm run generate:spec # Fetch spec → openapi/openapi.json
|
|
254
|
+
npm run generate:types # Generate types → src/generated/openapi.d.ts
|
|
255
|
+
|
|
256
|
+
# CI drift check: compare committed spec against live backend
|
|
257
|
+
npm run check:spec
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
> **Note:** `generate:types` does not need the API key — it reads from the committed `openapi/openapi.json` file. The `.env` file is loaded automatically by the `generate:spec` and `check:spec` scripts.
|
|
261
|
+
|
|
262
|
+
**When to regenerate:**
|
|
263
|
+
- After any backend API change (new endpoints, renamed fields, changed DTOs)
|
|
264
|
+
- The `check:spec` script can be used in CI to detect stale types automatically
|
|
265
|
+
|
|
266
|
+
**How it works:**
|
|
267
|
+
|
|
268
|
+
1. `generate:spec` — Fetches the OpenAPI spec from the backend's `/v3/api-docs` endpoint and saves it to `openapi/openapi.json`
|
|
269
|
+
2. `generate:types` — Runs `openapi-typescript` to convert `openapi.json` into TypeScript type definitions at `src/generated/openapi.d.ts`
|
|
270
|
+
3. `check:spec` — CI guard that compares the committed `openapi.json` against the live backend. Exits non-zero if they differ.
|
|
271
|
+
|
|
272
|
+
Both `mcp/` and `cli/` share the same backend spec and generated types.
|
|
273
|
+
|
|
274
|
+
### Project Structure
|
|
275
|
+
|
|
276
|
+
```
|
|
277
|
+
mcp/
|
|
278
|
+
├── openapi/
|
|
279
|
+
│ ├── openapi.json # Committed OpenAPI spec (generated)
|
|
280
|
+
│ └── scripts/
|
|
281
|
+
│ ├── fetch-spec.ts # Downloads spec from running backend
|
|
282
|
+
│ └── check-drift.ts # CI guard for spec drift detection
|
|
283
|
+
├── src/
|
|
284
|
+
│ ├── index.ts # Entry point, transport setup, tool registration
|
|
285
|
+
│ ├── client.ts # openapi-fetch client factory with error middleware
|
|
286
|
+
│ ├── errors.ts # Error types and MCP error formatting
|
|
287
|
+
│ ├── mime.ts # MIME type detection for file uploads
|
|
288
|
+
│ ├── schema-compat.ts # OpenAI-compatible schema enforcement
|
|
289
|
+
│ ├── generated/
|
|
290
|
+
│ │ └── openapi.d.ts # Auto-generated TypeScript types (do not edit)
|
|
291
|
+
│ └── tools/
|
|
292
|
+
│ ├── ai-gateway.ts # Chat completions & model listing
|
|
293
|
+
│ ├── conversion.ts # Document conversion
|
|
294
|
+
│ ├── docs.ts # API documentation browsing
|
|
295
|
+
│ ├── extraction.ts # Data extraction
|
|
296
|
+
│ ├── projects.ts # Project CRUD
|
|
297
|
+
│ ├── schema-testing.ts # Schema validation & testing
|
|
298
|
+
│ ├── schema-versions.ts # Schema version management
|
|
299
|
+
│ ├── schemas.ts # Schema CRUD
|
|
300
|
+
│ └── transcription.ts # Audio transcription
|
|
301
|
+
├── dist/ # Compiled output (generated)
|
|
302
|
+
├── package.json
|
|
303
|
+
└── tsconfig.json
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### Adding New Tools
|
|
307
|
+
|
|
308
|
+
1. Create a new file in `src/tools/` following the existing pattern
|
|
309
|
+
2. Export a `register(server: McpServer, client: ApiClient): void` function
|
|
310
|
+
3. Import and call `register()` in `src/index.ts`
|
|
311
|
+
4. Rebuild with `npm run build`
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import createClient from "openapi-fetch";
|
|
2
|
+
import type { paths } from "./generated/openapi.js";
|
|
3
|
+
export type ApiClient = ReturnType<typeof createClient<paths>>;
|
|
4
|
+
/**
|
|
5
|
+
* Create a typed openapi-fetch client with Bearer auth and error middleware.
|
|
6
|
+
*/
|
|
7
|
+
export declare function createApiClient(baseUrl: string, apiKey: string): ApiClient;
|
|
8
|
+
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import createClient from "openapi-fetch";
|
|
2
|
+
import { BackboneApiError } from "./errors.js";
|
|
3
|
+
/**
|
|
4
|
+
* Error-handling middleware: intercepts non-ok responses and throws BackboneApiError.
|
|
5
|
+
*/
|
|
6
|
+
const errorMiddleware = {
|
|
7
|
+
async onResponse({ response }) {
|
|
8
|
+
if (response.ok)
|
|
9
|
+
return undefined;
|
|
10
|
+
let body;
|
|
11
|
+
try {
|
|
12
|
+
body = await response.clone().json();
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
body = {
|
|
16
|
+
error: response.statusText,
|
|
17
|
+
message: `HTTP ${response.status}: ${response.statusText}`,
|
|
18
|
+
status: response.status,
|
|
19
|
+
timestamp: new Date().toISOString(),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
throw new BackboneApiError(body);
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Create a typed openapi-fetch client with Bearer auth and error middleware.
|
|
27
|
+
*/
|
|
28
|
+
export function createApiClient(baseUrl, apiKey) {
|
|
29
|
+
const client = createClient({
|
|
30
|
+
baseUrl: baseUrl.replace(/\/+$/, ""),
|
|
31
|
+
headers: {
|
|
32
|
+
Authorization: `Bearer ${apiKey}`,
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
client.use(errorMiddleware);
|
|
36
|
+
return client;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=client.js.map
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
interface ApiErrorBody {
|
|
2
|
+
error: string;
|
|
3
|
+
message: string;
|
|
4
|
+
status: number;
|
|
5
|
+
timestamp: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class BackboneApiError extends Error {
|
|
8
|
+
readonly status: number;
|
|
9
|
+
readonly errorType: string;
|
|
10
|
+
readonly timestamp: string;
|
|
11
|
+
constructor(apiError: ApiErrorBody);
|
|
12
|
+
}
|
|
13
|
+
export declare function formatErrorForMcp(error: unknown): string;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=errors.d.ts.map
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export class BackboneApiError extends Error {
|
|
2
|
+
status;
|
|
3
|
+
errorType;
|
|
4
|
+
timestamp;
|
|
5
|
+
constructor(apiError) {
|
|
6
|
+
super(apiError.message);
|
|
7
|
+
this.name = "BackboneApiError";
|
|
8
|
+
this.status = apiError.status;
|
|
9
|
+
this.errorType = apiError.error;
|
|
10
|
+
this.timestamp = apiError.timestamp;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export function formatErrorForMcp(error) {
|
|
14
|
+
if (error instanceof BackboneApiError) {
|
|
15
|
+
return `API Error (${error.status}): ${error.message}`;
|
|
16
|
+
}
|
|
17
|
+
if (error instanceof Error) {
|
|
18
|
+
return `Error: ${error.message}`;
|
|
19
|
+
}
|
|
20
|
+
return `Unknown error: ${String(error)}`;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=errors.js.map
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
5
|
+
import { createServer } from "node:http";
|
|
6
|
+
import { createApiClient } from "./client.js";
|
|
7
|
+
import * as conversion from "./tools/conversion.js";
|
|
8
|
+
import * as extraction from "./tools/extraction.js";
|
|
9
|
+
import * as aiGateway from "./tools/ai-gateway.js";
|
|
10
|
+
import * as transcription from "./tools/transcription.js";
|
|
11
|
+
import * as projects from "./tools/projects.js";
|
|
12
|
+
import * as schemas from "./tools/schemas.js";
|
|
13
|
+
import * as schemaVersions from "./tools/schema-versions.js";
|
|
14
|
+
import * as schemaTesting from "./tools/schema-testing.js";
|
|
15
|
+
import * as docs from "./tools/docs.js";
|
|
16
|
+
function requiredEnv(name) {
|
|
17
|
+
const value = process.env[name];
|
|
18
|
+
if (!value) {
|
|
19
|
+
console.error(`Missing required environment variable: ${name}`);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
async function main() {
|
|
25
|
+
const apiKey = requiredEnv("BACKBONE_API_KEY");
|
|
26
|
+
const baseUrl = process.env.BACKBONE_BASE_URL ?? "https://backbone.manfred-kunze.dev/api";
|
|
27
|
+
const transport = process.env.MCP_TRANSPORT ?? "stdio";
|
|
28
|
+
const httpPort = parseInt(process.env.MCP_HTTP_PORT ?? "3100", 10);
|
|
29
|
+
const client = createApiClient(baseUrl, apiKey);
|
|
30
|
+
const server = new McpServer({
|
|
31
|
+
name: "backbone",
|
|
32
|
+
version: "1.0.0",
|
|
33
|
+
});
|
|
34
|
+
// Register all tool groups
|
|
35
|
+
conversion.register(server, client);
|
|
36
|
+
extraction.register(server, client);
|
|
37
|
+
aiGateway.register(server, client);
|
|
38
|
+
transcription.register(server, client);
|
|
39
|
+
projects.register(server, client);
|
|
40
|
+
schemas.register(server, client);
|
|
41
|
+
schemaVersions.register(server, client);
|
|
42
|
+
schemaTesting.register(server, client);
|
|
43
|
+
docs.register(server, client, baseUrl, apiKey);
|
|
44
|
+
if (transport === "http") {
|
|
45
|
+
const httpTransport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
|
|
46
|
+
const httpServer = createServer(async (req, res) => {
|
|
47
|
+
const url = new URL(req.url ?? "/", `http://localhost:${httpPort}`);
|
|
48
|
+
if (url.pathname === "/mcp") {
|
|
49
|
+
await httpTransport.handleRequest(req, res);
|
|
50
|
+
}
|
|
51
|
+
else if (url.pathname === "/health") {
|
|
52
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
53
|
+
res.end(JSON.stringify({ status: "ok" }));
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
res.writeHead(404);
|
|
57
|
+
res.end("Not found");
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
await server.connect(httpTransport);
|
|
61
|
+
httpServer.listen(httpPort, () => {
|
|
62
|
+
console.error(`Backbone MCP server listening on http://localhost:${httpPort}/mcp`);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
const stdioTransport = new StdioServerTransport();
|
|
67
|
+
await server.connect(stdioTransport);
|
|
68
|
+
console.error("Backbone MCP server running on stdio");
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
main().catch((error) => {
|
|
72
|
+
console.error("Fatal error:", error);
|
|
73
|
+
process.exit(1);
|
|
74
|
+
});
|
|
75
|
+
//# sourceMappingURL=index.js.map
|
package/dist/mime.d.ts
ADDED
package/dist/mime.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const MIME_TYPES = {
|
|
2
|
+
// Documents
|
|
3
|
+
".pdf": "application/pdf",
|
|
4
|
+
".doc": "application/msword",
|
|
5
|
+
".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
6
|
+
".xls": "application/vnd.ms-excel",
|
|
7
|
+
".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
8
|
+
".ppt": "application/vnd.ms-powerpoint",
|
|
9
|
+
".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
10
|
+
".odt": "application/vnd.oasis.opendocument.text",
|
|
11
|
+
".ods": "application/vnd.oasis.opendocument.spreadsheet",
|
|
12
|
+
".odp": "application/vnd.oasis.opendocument.presentation",
|
|
13
|
+
".rtf": "application/rtf",
|
|
14
|
+
".csv": "text/csv",
|
|
15
|
+
".tsv": "text/tab-separated-values",
|
|
16
|
+
// Text
|
|
17
|
+
".txt": "text/plain",
|
|
18
|
+
".md": "text/markdown",
|
|
19
|
+
".html": "text/html",
|
|
20
|
+
".htm": "text/html",
|
|
21
|
+
".xml": "application/xml",
|
|
22
|
+
".json": "application/json",
|
|
23
|
+
".yaml": "application/x-yaml",
|
|
24
|
+
".yml": "application/x-yaml",
|
|
25
|
+
// Images
|
|
26
|
+
".png": "image/png",
|
|
27
|
+
".jpg": "image/jpeg",
|
|
28
|
+
".jpeg": "image/jpeg",
|
|
29
|
+
".gif": "image/gif",
|
|
30
|
+
".bmp": "image/bmp",
|
|
31
|
+
".tiff": "image/tiff",
|
|
32
|
+
".tif": "image/tiff",
|
|
33
|
+
".webp": "image/webp",
|
|
34
|
+
".svg": "image/svg+xml",
|
|
35
|
+
// Email
|
|
36
|
+
".eml": "message/rfc822",
|
|
37
|
+
".msg": "application/vnd.ms-outlook",
|
|
38
|
+
// Audio
|
|
39
|
+
".flac": "audio/flac",
|
|
40
|
+
".mp3": "audio/mpeg",
|
|
41
|
+
".mp4": "audio/mp4",
|
|
42
|
+
".mpeg": "audio/mpeg",
|
|
43
|
+
".mpga": "audio/mpeg",
|
|
44
|
+
".m4a": "audio/mp4",
|
|
45
|
+
".ogg": "audio/ogg",
|
|
46
|
+
".wav": "audio/wav",
|
|
47
|
+
".webm": "audio/webm",
|
|
48
|
+
};
|
|
49
|
+
export function getMimeType(filename) {
|
|
50
|
+
const ext = filename.slice(filename.lastIndexOf(".")).toLowerCase();
|
|
51
|
+
return MIME_TYPES[ext] ?? "application/octet-stream";
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=mime.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sanitize a JSON Schema to be compatible with OpenAI's structured output requirements.
|
|
3
|
+
*
|
|
4
|
+
* OpenAI requires:
|
|
5
|
+
* - Every object type must have `additionalProperties: false`
|
|
6
|
+
* - Every object must list all properties in `required`
|
|
7
|
+
*
|
|
8
|
+
* This function recursively walks the schema and applies these constraints.
|
|
9
|
+
*/
|
|
10
|
+
export declare function ensureOpenAiCompatible(schema: unknown): unknown;
|
|
11
|
+
//# sourceMappingURL=schema-compat.d.ts.map
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sanitize a JSON Schema to be compatible with OpenAI's structured output requirements.
|
|
3
|
+
*
|
|
4
|
+
* OpenAI requires:
|
|
5
|
+
* - Every object type must have `additionalProperties: false`
|
|
6
|
+
* - Every object must list all properties in `required`
|
|
7
|
+
*
|
|
8
|
+
* This function recursively walks the schema and applies these constraints.
|
|
9
|
+
*/
|
|
10
|
+
export function ensureOpenAiCompatible(schema) {
|
|
11
|
+
if (schema === null || schema === undefined || typeof schema !== "object") {
|
|
12
|
+
return schema;
|
|
13
|
+
}
|
|
14
|
+
if (Array.isArray(schema)) {
|
|
15
|
+
return schema.map(ensureOpenAiCompatible);
|
|
16
|
+
}
|
|
17
|
+
const obj = schema;
|
|
18
|
+
const result = {};
|
|
19
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
20
|
+
if (key === "properties" && typeof value === "object" && value !== null) {
|
|
21
|
+
// Recurse into each property definition
|
|
22
|
+
const props = {};
|
|
23
|
+
for (const [propName, propValue] of Object.entries(value)) {
|
|
24
|
+
props[propName] = ensureOpenAiCompatible(propValue);
|
|
25
|
+
}
|
|
26
|
+
result[key] = props;
|
|
27
|
+
}
|
|
28
|
+
else if (key === "items") {
|
|
29
|
+
// Recurse into array items
|
|
30
|
+
result[key] = ensureOpenAiCompatible(value);
|
|
31
|
+
}
|
|
32
|
+
else if (key === "anyOf" || key === "oneOf" || key === "allOf") {
|
|
33
|
+
// Recurse into combinators
|
|
34
|
+
result[key] = Array.isArray(value) ? value.map(ensureOpenAiCompatible) : value;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
result[key] = value;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// If this node is an object type with properties, enforce OpenAI constraints
|
|
41
|
+
if (obj.type === "object" && obj.properties && typeof obj.properties === "object") {
|
|
42
|
+
result.additionalProperties = false;
|
|
43
|
+
// Ensure all properties are in required
|
|
44
|
+
const propNames = Object.keys(obj.properties);
|
|
45
|
+
const existing = Array.isArray(obj.required) ? obj.required : [];
|
|
46
|
+
const merged = [...new Set([...existing, ...propNames])];
|
|
47
|
+
result.required = merged;
|
|
48
|
+
}
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=schema-compat.js.map
|