@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 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`
@@ -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
@@ -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
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
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
@@ -0,0 +1,2 @@
1
+ export declare function getMimeType(filename: string): string;
2
+ //# sourceMappingURL=mime.d.ts.map
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
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { ApiClient } from "../client.js";
3
+ export declare function register(server: McpServer, client: ApiClient): void;
4
+ //# sourceMappingURL=ai-gateway.d.ts.map