@transloadit/mcp-server 0.4.2 → 0.5.1
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/README.md +256 -80
- package/dist/cli.js +52 -2
- package/dist/cli.js.map +1 -1
- package/dist/express.d.ts.map +1 -1
- package/dist/express.js +25 -12
- package/dist/express.js.map +1 -1
- package/dist/http-helpers.d.ts +90 -0
- package/dist/http-helpers.d.ts.map +1 -1
- package/dist/http-helpers.js +193 -3
- package/dist/http-helpers.js.map +1 -1
- package/dist/http-request-handler.d.ts +1 -0
- package/dist/http-request-handler.d.ts.map +1 -1
- package/dist/http-request-handler.js +9 -19
- package/dist/http-request-handler.js.map +1 -1
- package/dist/http.d.ts +2 -0
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +25 -49
- package/dist/http.js.map +1 -1
- package/dist/json.d.ts +5 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +14 -0
- package/dist/json.js.map +1 -0
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +4 -1
- package/dist/logger.js.map +1 -1
- package/dist/options.d.ts +12 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +34 -0
- package/dist/options.js.map +1 -0
- package/dist/request-transport.d.ts +21 -0
- package/dist/request-transport.d.ts.map +1 -0
- package/dist/request-transport.js +129 -0
- package/dist/request-transport.js.map +1 -0
- package/dist/server-card.d.ts +20 -7
- package/dist/server-card.d.ts.map +1 -1
- package/dist/server-card.js +41 -16
- package/dist/server-card.js.map +1 -1
- package/dist/server.d.ts +45 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +423 -81
- package/dist/server.js.map +1 -1
- package/dist/tool-list.d.ts +9 -0
- package/dist/tool-list.d.ts.map +1 -0
- package/dist/tool-list.js +44 -0
- package/dist/tool-list.js.map +1 -0
- package/dist/tool-metadata.d.ts +53 -0
- package/dist/tool-metadata.d.ts.map +1 -0
- package/dist/tool-metadata.js +147 -0
- package/dist/tool-metadata.js.map +1 -0
- package/dist/ui/assembly-result-widget.d.ts +47 -0
- package/dist/ui/assembly-result-widget.d.ts.map +1 -0
- package/dist/ui/assembly-result-widget.js +449 -0
- package/dist/ui/assembly-result-widget.js.map +1 -0
- package/dist/upload-instructions.d.ts +29 -0
- package/dist/upload-instructions.d.ts.map +1 -0
- package/dist/upload-instructions.js +60 -0
- package/dist/upload-instructions.js.map +1 -0
- package/package.json +3 -2
package/dist/http.js
CHANGED
|
@@ -1,36 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { applyCorsHeaders, assertHttpOptions, isBasicAuthorized, normalizePath, parsePathname, readBodyWithinLimit, rejectMissingBearerToken, rejectMissingMcpToken, resolveAllowedOrigins, resolveMaxRequestBodyBytes, sendBodyTooLarge, sendServerInfoForBareGet, } from "./http-helpers.js";
|
|
2
|
+
import { parseJson } from "./json.js";
|
|
3
3
|
import { getMetrics, getMetricsContentType } from "./metrics.js";
|
|
4
|
+
import { createRequestTransport } from "./request-transport.js";
|
|
4
5
|
import { createTransloaditMcpServer } from "./server.js";
|
|
5
6
|
import { buildServerCard, serverCardPath } from "./server-card.js";
|
|
6
7
|
const defaultPath = '/mcp';
|
|
7
|
-
/** Read the full request body and JSON-parse it before handing it to the MCP transport. */
|
|
8
|
-
function readJsonBody(req) {
|
|
9
|
-
return new Promise((resolve, reject) => {
|
|
10
|
-
const chunks = [];
|
|
11
|
-
req.on('data', (chunk) => chunks.push(chunk));
|
|
12
|
-
req.on('end', () => {
|
|
13
|
-
const raw = Buffer.concat(chunks).toString('utf8');
|
|
14
|
-
if (!raw) {
|
|
15
|
-
resolve(undefined);
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
try {
|
|
19
|
-
resolve(JSON.parse(raw));
|
|
20
|
-
}
|
|
21
|
-
catch {
|
|
22
|
-
resolve(undefined);
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
req.on('error', reject);
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
8
|
export function createTransloaditMcpHttpHandler(options = {}) {
|
|
29
9
|
const activeRequests = new Set();
|
|
10
|
+
assertHttpOptions(options);
|
|
30
11
|
const expectedPath = options.path ?? defaultPath;
|
|
31
12
|
const metricsPath = options.metricsPath === false ? undefined : normalizePath(options.metricsPath ?? '/metrics');
|
|
32
13
|
const metricsAuth = options.metricsAuth;
|
|
33
|
-
const
|
|
14
|
+
const allowedOrigins = resolveAllowedOrigins(options);
|
|
15
|
+
const serverCardJson = JSON.stringify(buildServerCard(expectedPath, {
|
|
16
|
+
authKey: options.authKey,
|
|
17
|
+
authSecret: options.authSecret,
|
|
18
|
+
resourceMetadataUrl: options.resourceMetadataUrl,
|
|
19
|
+
}));
|
|
34
20
|
const handler = (async (req, res) => {
|
|
35
21
|
const pathname = normalizePath(parsePathname(req.url, expectedPath));
|
|
36
22
|
if (pathname === serverCardPath) {
|
|
@@ -81,7 +67,7 @@ export function createTransloaditMcpHttpHandler(options = {}) {
|
|
|
81
67
|
res.end('Not Found');
|
|
82
68
|
return;
|
|
83
69
|
}
|
|
84
|
-
if (!applyCorsHeaders(req, res,
|
|
70
|
+
if (!applyCorsHeaders(req, res, allowedOrigins)) {
|
|
85
71
|
return;
|
|
86
72
|
}
|
|
87
73
|
if (req.method === 'OPTIONS') {
|
|
@@ -89,24 +75,13 @@ export function createTransloaditMcpHttpHandler(options = {}) {
|
|
|
89
75
|
res.end();
|
|
90
76
|
return;
|
|
91
77
|
}
|
|
92
|
-
if (
|
|
93
|
-
res.statusCode = 401;
|
|
94
|
-
res.setHeader('WWW-Authenticate', 'Bearer');
|
|
95
|
-
res.end('Unauthorized');
|
|
78
|
+
if (rejectMissingMcpToken(req, res, options.mcpToken)) {
|
|
96
79
|
return;
|
|
97
80
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
if (req.method === 'GET' && !accept.includes('text/event-stream')) {
|
|
103
|
-
res.statusCode = 200;
|
|
104
|
-
res.setHeader('Content-Type', 'application/json');
|
|
105
|
-
res.end(JSON.stringify({
|
|
106
|
-
name: 'Transloadit MCP Server',
|
|
107
|
-
status: 'ok',
|
|
108
|
-
docs: 'https://transloadit.com/docs/sdks/mcp-server/',
|
|
109
|
-
}));
|
|
81
|
+
if (rejectMissingBearerToken(req, res, options.resourceMetadataUrl)) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (sendServerInfoForBareGet(req, res)) {
|
|
110
85
|
return;
|
|
111
86
|
}
|
|
112
87
|
if (req.method !== 'POST') {
|
|
@@ -119,13 +94,14 @@ export function createTransloaditMcpHttpHandler(options = {}) {
|
|
|
119
94
|
}));
|
|
120
95
|
return;
|
|
121
96
|
}
|
|
122
|
-
const
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
97
|
+
const maxBytes = resolveMaxRequestBodyBytes(options);
|
|
98
|
+
const rawBody = await readBodyWithinLimit(req, maxBytes);
|
|
99
|
+
if (rawBody === undefined) {
|
|
100
|
+
sendBodyTooLarge(res, maxBytes);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const parsedBody = parseJson(rawBody);
|
|
104
|
+
const { transport, handle } = createRequestTransport(options);
|
|
129
105
|
const server = createTransloaditMcpServer(options);
|
|
130
106
|
const activeRequest = { transport, server };
|
|
131
107
|
activeRequests.add(activeRequest);
|
|
@@ -137,7 +113,7 @@ export function createTransloaditMcpHttpHandler(options = {}) {
|
|
|
137
113
|
res.on('close', cleanupActiveRequest);
|
|
138
114
|
await server.connect(transport);
|
|
139
115
|
try {
|
|
140
|
-
await
|
|
116
|
+
await handle(req, res, parsedBody);
|
|
141
117
|
}
|
|
142
118
|
catch {
|
|
143
119
|
if (!res.headersSent) {
|
package/dist/http.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
|
package/dist/json.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** A plain object; arrays are rejected because callers read named fields. */
|
|
2
|
+
export declare const isRecord: (value: unknown) => value is Record<string, unknown>;
|
|
3
|
+
/** Parses JSON text, returning `undefined` for empty or invalid input instead of throwing. */
|
|
4
|
+
export declare const parseJson: (text: string) => unknown;
|
|
5
|
+
//# sourceMappingURL=json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../src/json.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,eAAO,MAAM,QAAQ,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CACH,CAAA;AAEtE,8FAA8F;AAC9F,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,KAAG,OAOxC,CAAA"}
|
package/dist/json.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** A plain object; arrays are rejected because callers read named fields. */
|
|
2
|
+
export const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
3
|
+
/** Parses JSON text, returning `undefined` for empty or invalid input instead of throwing. */
|
|
4
|
+
export const parseJson = (text) => {
|
|
5
|
+
if (!text)
|
|
6
|
+
return undefined;
|
|
7
|
+
try {
|
|
8
|
+
return JSON.parse(text);
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=json.js.map
|
package/dist/json.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","sourceRoot":"","sources":["../src/json.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAoC,EAAE,CAC3E,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;AAEtE,8FAA8F;AAC9F,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,IAAY,EAAW,EAAE;IACjD,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAA;IAC3B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC,CAAA"}
|
package/dist/logger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAmBnD,eAAO,MAAM,YAAY,GAAI,OAAO,OAAO,EAAE,SAAS,MAAM,EAAE,KAAG,MAchE,CAAA;AAED,eAAO,MAAM,aAAa,GAAI,SAAS,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,KAAG,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,CAG7F,CAAA;AAED,eAAO,MAAM,SAAS,QAAO,SAAuB,CAAA"}
|
package/dist/logger.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { SevLogger } from '@transloadit/sev-logger';
|
|
2
2
|
const baseLogger = new SevLogger({ breadcrumbs: ['mcp-server'] });
|
|
3
3
|
const redactString = (value, secrets) => {
|
|
4
|
-
let output = value
|
|
4
|
+
let output = value
|
|
5
|
+
.replace(/Bearer\s+[^\s]+/gi, 'Bearer [redacted]')
|
|
6
|
+
// The hosted upstream secret travels as a header; scrub it even when it was not listed.
|
|
7
|
+
.replace(/Transloadit-Mcp-Upstream(["']?\s*[:=]\s*["']?)[^\s"',}]+/gi, 'Transloadit-Mcp-Upstream$1[redacted]');
|
|
5
8
|
for (const secret of secrets) {
|
|
6
9
|
if (!secret)
|
|
7
10
|
continue;
|
package/dist/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAEnD,MAAM,UAAU,GAAG,IAAI,SAAS,CAAC,EAAE,WAAW,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,CAAA;AAEjE,MAAM,YAAY,GAAG,CAAC,KAAa,EAAE,OAAiB,EAAU,EAAE;IAChE,IAAI,MAAM,GAAG,KAAK,
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAEnD,MAAM,UAAU,GAAG,IAAI,SAAS,CAAC,EAAE,WAAW,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,CAAA;AAEjE,MAAM,YAAY,GAAG,CAAC,KAAa,EAAE,OAAiB,EAAU,EAAE;IAChE,IAAI,MAAM,GAAG,KAAK;SACf,OAAO,CAAC,mBAAmB,EAAE,mBAAmB,CAAC;QAClD,wFAAwF;SACvF,OAAO,CACN,4DAA4D,EAC5D,sCAAsC,CACvC,CAAA;IACH,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,MAAM;YAAE,SAAQ;QACrB,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;IAClD,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,KAAc,EAAE,OAAiB,EAAU,EAAE;IACxE,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;IAClE,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QACpD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;QAC1E,OAAO,KAAK,CAAC,CAAC,CAAC,GAAG,OAAO,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAA;IACjD,CAAC;IACD,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;QACxC,IAAI,UAAU;YAAE,OAAO,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;IAC1D,CAAC;IAAC,MAAM,CAAC;QACP,SAAS;IACX,CAAC;IACD,OAAO,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAA;AAC7C,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,OAAkC,EAAgC,EAAE;IAChG,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAoB,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAA;IAChF,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,UAAU,CAAC,CAAA;AACnD,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,GAAc,EAAE,CAAC,UAAU,CAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Validates what every server instance relies on, however it is constructed. */
|
|
2
|
+
export declare const assertServerOptions: (options: {
|
|
3
|
+
resourceMetadataUrl?: string;
|
|
4
|
+
upstreamSecret?: string;
|
|
5
|
+
maxUrlDownloadBytes?: unknown;
|
|
6
|
+
urlDownloadTimeoutMs?: unknown;
|
|
7
|
+
resultDomains?: string[];
|
|
8
|
+
widgetDomain?: string;
|
|
9
|
+
}) => void;
|
|
10
|
+
/** Validates the HTTP request body limit. */
|
|
11
|
+
export declare const assertRequestBodyLimit: (value: unknown) => void;
|
|
12
|
+
//# sourceMappingURL=options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAaA,iFAAiF;AACjF,eAAO,MAAM,mBAAmB,GAAI,SAAS;IAC3C,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,KAAG,IAiBH,CAAA;AAED,6CAA6C;AAC7C,eAAO,MAAM,sBAAsB,GAAI,OAAO,OAAO,KAAG,IAEvD,CAAA"}
|
package/dist/options.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { parseWidgetOrigin } from "./ui/assembly-result-widget.js";
|
|
2
|
+
/**
|
|
3
|
+
* Limits also arrive from JSON config files, where a value such as `"1MB"` would silently disable
|
|
4
|
+
* a numeric comparison, so each one must be a positive integer.
|
|
5
|
+
*/
|
|
6
|
+
const assertPositiveInteger = (value, name, unit) => {
|
|
7
|
+
if (value === undefined)
|
|
8
|
+
return;
|
|
9
|
+
if (typeof value !== 'number' || !Number.isInteger(value) || value <= 0) {
|
|
10
|
+
throw new Error(`${name} must be a positive integer number of ${unit}.`);
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
/** Validates what every server instance relies on, however it is constructed. */
|
|
14
|
+
export const assertServerOptions = (options) => {
|
|
15
|
+
// API2 only accepts relayed `aud=mcp` tokens from the hosted service, so without the secret
|
|
16
|
+
// every authenticated call fails; refusing to start surfaces that in the deploy's health check.
|
|
17
|
+
if (options.resourceMetadataUrl && !options.upstreamSecret) {
|
|
18
|
+
throw new Error('TRANSLOADIT_MCP_RESOURCE_METADATA_URL (hosted mode) requires TRANSLOADIT_MCP_UPSTREAM_SECRET: API2 only accepts relayed MCP tokens from the hosted service.');
|
|
19
|
+
}
|
|
20
|
+
assertPositiveInteger(options.maxUrlDownloadBytes, 'maxUrlDownloadBytes', 'bytes');
|
|
21
|
+
assertPositiveInteger(options.urlDownloadTimeoutMs, 'urlDownloadTimeoutMs', 'milliseconds');
|
|
22
|
+
// A malformed origin would only surface as blank previews in the host, so it fails startup.
|
|
23
|
+
for (const domain of options.resultDomains ?? []) {
|
|
24
|
+
parseWidgetOrigin(domain, 'resultDomains');
|
|
25
|
+
}
|
|
26
|
+
if (options.widgetDomain) {
|
|
27
|
+
parseWidgetOrigin(options.widgetDomain, 'widgetDomain');
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
/** Validates the HTTP request body limit. */
|
|
31
|
+
export const assertRequestBodyLimit = (value) => {
|
|
32
|
+
assertPositiveInteger(value, 'maxRequestBodyBytes', 'bytes');
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAElE;;;GAGG;AACH,MAAM,qBAAqB,GAAG,CAAC,KAAc,EAAE,IAAY,EAAE,IAAY,EAAQ,EAAE;IACjF,IAAI,KAAK,KAAK,SAAS;QAAE,OAAM;IAC/B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QACxE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,yCAAyC,IAAI,GAAG,CAAC,CAAA;IAC1E,CAAC;AACH,CAAC,CAAA;AAED,iFAAiF;AACjF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,OAOnC,EAAQ,EAAE;IACT,4FAA4F;IAC5F,gGAAgG;IAChG,IAAI,OAAO,CAAC,mBAAmB,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CACb,6JAA6J,CAC9J,CAAA;IACH,CAAC;IACD,qBAAqB,CAAC,OAAO,CAAC,mBAAmB,EAAE,qBAAqB,EAAE,OAAO,CAAC,CAAA;IAClF,qBAAqB,CAAC,OAAO,CAAC,oBAAoB,EAAE,sBAAsB,EAAE,cAAc,CAAC,CAAA;IAC3F,4FAA4F;IAC5F,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,aAAa,IAAI,EAAE,EAAE,CAAC;QACjD,iBAAiB,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;IAC5C,CAAC;IACD,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;QACzB,iBAAiB,CAAC,OAAO,CAAC,YAAY,EAAE,cAAc,CAAC,CAAA;IACzD,CAAC;AACH,CAAC,CAAA;AAED,6CAA6C;AAC7C,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,KAAc,EAAQ,EAAE;IAC7D,qBAAqB,CAAC,KAAK,EAAE,qBAAqB,EAAE,OAAO,CAAC,CAAA;AAC9D,CAAC,CAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
|
|
3
|
+
type RequestTransportOptions = {
|
|
4
|
+
resourceMetadataUrl?: string;
|
|
5
|
+
allowedHosts?: string[];
|
|
6
|
+
enableDnsRebindingProtection?: boolean;
|
|
7
|
+
maxRequestBodyBytes?: number;
|
|
8
|
+
};
|
|
9
|
+
/** A per-request MCP transport plus the function that serves the HTTP request through it. */
|
|
10
|
+
export type RequestTransport = {
|
|
11
|
+
transport: Transport;
|
|
12
|
+
handle: (req: IncomingMessage, res: ServerResponse, parsedBody: unknown) => Promise<void>;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Creates the stateless transport for one HTTP request. Origins are checked before this point by
|
|
16
|
+
* `applyCorsHeaders`, which understands `*.` and `:*` wildcards; the SDK compares origins
|
|
17
|
+
* literally, so it only receives the Host allowlist.
|
|
18
|
+
*/
|
|
19
|
+
export declare const createRequestTransport: (options: RequestTransportOptions) => RequestTransport;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=request-transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-transport.d.ts","sourceRoot":"","sources":["../src/request-transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAEhE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+CAA+C,CAAA;AAY9E,KAAK,uBAAuB,GAAG;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB,4BAA4B,CAAC,EAAE,OAAO,CAAA;IACtC,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC7B,CAAA;AAED,6FAA6F;AAC7F,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,SAAS,CAAA;IACpB,MAAM,EAAE,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,EAAE,UAAU,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1F,CAAA;AAqGD;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,GAAI,SAAS,uBAAuB,KAAG,gBA4BzE,CAAA"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
2
|
+
import { WebStandardStreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js';
|
|
3
|
+
import { readBodyWithinLimit, resolveMaxRequestBodyBytes, sendBodyTooLarge, } from "./http-helpers.js";
|
|
4
|
+
import { isRecord, parseJson } from "./json.js";
|
|
5
|
+
/**
|
|
6
|
+
* Finds the challenge a tool attached after API2 rejected the forwarded token. Tool results are
|
|
7
|
+
* the only place that knows, because API2 checks the token when a tool calls it.
|
|
8
|
+
*/
|
|
9
|
+
const findUpstreamChallenge = (body) => {
|
|
10
|
+
const parsed = parseJson(body);
|
|
11
|
+
const messages = Array.isArray(parsed) ? parsed : [parsed];
|
|
12
|
+
for (const message of messages) {
|
|
13
|
+
if (!isRecord(message) || !isRecord(message.result))
|
|
14
|
+
continue;
|
|
15
|
+
const { result } = message;
|
|
16
|
+
if (result.isError !== true || !isRecord(result._meta))
|
|
17
|
+
continue;
|
|
18
|
+
const challenges = result._meta['mcp/www_authenticate'];
|
|
19
|
+
const header = Array.isArray(challenges)
|
|
20
|
+
? challenges.find((challenge) => typeof challenge === 'string')
|
|
21
|
+
: undefined;
|
|
22
|
+
if (typeof header !== 'string')
|
|
23
|
+
continue;
|
|
24
|
+
if (header.includes('error="invalid_token"'))
|
|
25
|
+
return { status: 401, header };
|
|
26
|
+
if (header.includes('error="insufficient_scope"'))
|
|
27
|
+
return { status: 403, header };
|
|
28
|
+
}
|
|
29
|
+
return undefined;
|
|
30
|
+
};
|
|
31
|
+
const toWebRequest = (req) => {
|
|
32
|
+
const headers = new Headers();
|
|
33
|
+
for (const [name, value] of Object.entries(req.headers)) {
|
|
34
|
+
if (value === undefined)
|
|
35
|
+
continue;
|
|
36
|
+
for (const entry of Array.isArray(value) ? value : [value])
|
|
37
|
+
headers.append(name, entry);
|
|
38
|
+
}
|
|
39
|
+
// The body always arrives pre-parsed, so headers and a fixed base URL are all it needs.
|
|
40
|
+
return new Request(new URL(req.url ?? '/', 'http://localhost'), { method: req.method, headers });
|
|
41
|
+
};
|
|
42
|
+
const sendParseError = (res) => {
|
|
43
|
+
res.statusCode = 400;
|
|
44
|
+
res.setHeader('Content-Type', 'application/json');
|
|
45
|
+
res.end(JSON.stringify({
|
|
46
|
+
jsonrpc: '2.0',
|
|
47
|
+
error: { code: -32700, message: 'Parse error: Invalid JSON' },
|
|
48
|
+
id: null,
|
|
49
|
+
}));
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Returns the JSON-RPC message, reading it within the body limit when no parser consumed the
|
|
53
|
+
* stream yet (an Express app without `express.json()`). `undefined` means a response was sent.
|
|
54
|
+
*/
|
|
55
|
+
const readMessage = async (req, res, parsedBody, maxBytes) => {
|
|
56
|
+
if (parsedBody !== undefined || req.method !== 'POST' || req.readableEnded) {
|
|
57
|
+
return { message: parsedBody };
|
|
58
|
+
}
|
|
59
|
+
const rawBody = await readBodyWithinLimit(req, maxBytes);
|
|
60
|
+
if (rawBody === undefined) {
|
|
61
|
+
sendBodyTooLarge(res, maxBytes);
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
const message = parseJson(rawBody);
|
|
65
|
+
if (message === undefined) {
|
|
66
|
+
sendParseError(res);
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
return { message };
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Serves a hosted request through the SDK's web-standard transport in JSON mode, so the status is
|
|
73
|
+
* decided after the tool ran: MCP OAuth clients refresh only on HTTP 401 and re-scope only on
|
|
74
|
+
* HTTP 403 `insufficient_scope`, and a tool result over HTTP 200 would keep them retrying a
|
|
75
|
+
* rejected token.
|
|
76
|
+
*/
|
|
77
|
+
const relayHostedRequest = async (transport, req, res, message) => {
|
|
78
|
+
const response = await transport.handleRequest(toWebRequest(req), { parsedBody: message });
|
|
79
|
+
const body = await response.text();
|
|
80
|
+
// A client retries the whole HTTP request after re-authorizing, so a batch keeps its 200: the
|
|
81
|
+
// other calls may have succeeded (an Assembly created twice would be charged twice). Its failed
|
|
82
|
+
// items still carry the challenge in `_meta["mcp/www_authenticate"]`.
|
|
83
|
+
const challenge = !Array.isArray(message) && response.headers.get('content-type')?.includes('application/json')
|
|
84
|
+
? findUpstreamChallenge(body)
|
|
85
|
+
: undefined;
|
|
86
|
+
res.statusCode = challenge?.status ?? response.status;
|
|
87
|
+
for (const [name, value] of response.headers)
|
|
88
|
+
res.setHeader(name, value);
|
|
89
|
+
if (challenge)
|
|
90
|
+
res.setHeader('WWW-Authenticate', challenge.header);
|
|
91
|
+
res.end(body);
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* Creates the stateless transport for one HTTP request. Origins are checked before this point by
|
|
95
|
+
* `applyCorsHeaders`, which understands `*.` and `:*` wildcards; the SDK compares origins
|
|
96
|
+
* literally, so it only receives the Host allowlist.
|
|
97
|
+
*/
|
|
98
|
+
export const createRequestTransport = (options) => {
|
|
99
|
+
const shared = {
|
|
100
|
+
sessionIdGenerator: undefined,
|
|
101
|
+
allowedHosts: options.allowedHosts,
|
|
102
|
+
enableDnsRebindingProtection: options.enableDnsRebindingProtection,
|
|
103
|
+
};
|
|
104
|
+
const maxBytes = resolveMaxRequestBodyBytes(options);
|
|
105
|
+
if (!options.resourceMetadataUrl) {
|
|
106
|
+
const transport = new StreamableHTTPServerTransport(shared);
|
|
107
|
+
return {
|
|
108
|
+
transport,
|
|
109
|
+
handle: async (req, res, parsedBody) => {
|
|
110
|
+
const read = await readMessage(req, res, parsedBody, maxBytes);
|
|
111
|
+
if (read)
|
|
112
|
+
await transport.handleRequest(req, res, read.message);
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
const transport = new WebStandardStreamableHTTPServerTransport({
|
|
117
|
+
...shared,
|
|
118
|
+
enableJsonResponse: true,
|
|
119
|
+
});
|
|
120
|
+
return {
|
|
121
|
+
transport,
|
|
122
|
+
handle: async (req, res, parsedBody) => {
|
|
123
|
+
const read = await readMessage(req, res, parsedBody, maxBytes);
|
|
124
|
+
if (read)
|
|
125
|
+
await relayHostedRequest(transport, req, res, read.message);
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
};
|
|
129
|
+
//# sourceMappingURL=request-transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-transport.js","sourceRoot":"","sources":["../src/request-transport.ts"],"names":[],"mappings":"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"}
|
package/dist/server-card.d.ts
CHANGED
|
@@ -1,10 +1,22 @@
|
|
|
1
|
+
import type { ToolAnnotations } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
import type { ToolName, ToolSecurityScheme } from './tool-metadata.ts';
|
|
1
3
|
export declare const serverCardPath = "/.well-known/mcp/server-card.json";
|
|
2
4
|
type JsonSchemaObject = Record<string, unknown>;
|
|
3
|
-
type
|
|
4
|
-
name:
|
|
5
|
+
type ServerCardToolInput = {
|
|
6
|
+
name: ToolName;
|
|
7
|
+
inputSchema: JsonSchemaObject;
|
|
8
|
+
};
|
|
9
|
+
type ServerCardToolDefinition = ServerCardToolInput & {
|
|
5
10
|
title: string;
|
|
6
11
|
description: string;
|
|
7
|
-
|
|
12
|
+
annotations: ToolAnnotations;
|
|
13
|
+
securitySchemes: ToolSecurityScheme[];
|
|
14
|
+
};
|
|
15
|
+
type ServerCardAuthentication = {
|
|
16
|
+
required: boolean;
|
|
17
|
+
schemes: string[];
|
|
18
|
+
/** RFC 9728 protected-resource metadata that names the OAuth authorization server. */
|
|
19
|
+
resourceMetadataUrl?: string;
|
|
8
20
|
};
|
|
9
21
|
type ServerCard = {
|
|
10
22
|
$schema: string;
|
|
@@ -22,20 +34,21 @@ type ServerCard = {
|
|
|
22
34
|
type: string;
|
|
23
35
|
endpoint: string;
|
|
24
36
|
};
|
|
25
|
-
authentication?:
|
|
26
|
-
required: boolean;
|
|
27
|
-
schemes: string[];
|
|
28
|
-
};
|
|
37
|
+
authentication?: ServerCardAuthentication;
|
|
29
38
|
capabilities: {
|
|
30
39
|
tools: {
|
|
31
40
|
listChanged: boolean;
|
|
32
41
|
};
|
|
42
|
+
resources: {
|
|
43
|
+
listChanged: boolean;
|
|
44
|
+
};
|
|
33
45
|
};
|
|
34
46
|
tools: ['dynamic'] | ServerCardToolDefinition[];
|
|
35
47
|
};
|
|
36
48
|
export declare const buildServerCard: (endpoint: string, options?: {
|
|
37
49
|
authKey?: string;
|
|
38
50
|
authSecret?: string;
|
|
51
|
+
resourceMetadataUrl?: string;
|
|
39
52
|
}) => ServerCard;
|
|
40
53
|
export {};
|
|
41
54
|
//# sourceMappingURL=server-card.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-card.d.ts","sourceRoot":"","sources":["../src/server-card.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server-card.d.ts","sourceRoot":"","sources":["../src/server-card.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAA;AAEzE,OAAO,KAAK,EAAgB,QAAQ,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAOpF,eAAO,MAAM,cAAc,sCAAsC,CAAA;AAEjE,KAAK,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAE/C,KAAK,mBAAmB,GAAG;IACzB,IAAI,EAAE,QAAQ,CAAA;IACd,WAAW,EAAE,gBAAgB,CAAA;CAC9B,CAAA;AAED,KAAK,wBAAwB,GAAG,mBAAmB,GAAG;IACpD,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,eAAe,CAAA;IAC5B,eAAe,EAAE,kBAAkB,EAAE,CAAA;CACtC,CAAA;AAED,KAAK,wBAAwB,GAAG;IAC9B,QAAQ,EAAE,OAAO,CAAA;IACjB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,sFAAsF;IACtF,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC7B,CAAA;AAED,KAAK,UAAU,GAAG;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,eAAe,EAAE,MAAM,CAAA;IACvB,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;IAC5D,WAAW,EAAE,MAAM,CAAA;IACnB,gBAAgB,EAAE,MAAM,CAAA;IACxB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;IAC7C,cAAc,CAAC,EAAE,wBAAwB,CAAA;IACzC,YAAY,EAAE;QAAE,KAAK,EAAE;YAAE,WAAW,EAAE,OAAO,CAAA;SAAE,CAAC;QAAC,SAAS,EAAE;YAAE,WAAW,EAAE,OAAO,CAAA;SAAE,CAAA;KAAE,CAAA;IACtF,KAAK,EAAE,CAAC,SAAS,CAAC,GAAG,wBAAwB,EAAE,CAAA;CAChD,CAAA;AA8ID,eAAO,MAAM,eAAe,GAC1B,UAAU,MAAM,EAChB,UAAS;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAAO,KACpF,UAkCF,CAAA"}
|
package/dist/server-card.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { LATEST_PROTOCOL_VERSION } from '@modelcontextprotocol/sdk/types.js';
|
|
2
2
|
import packageJson from '../package.json' with { type: 'json' };
|
|
3
|
+
import { resolveSecuritySchemes, resolveToolAuthMode, toolMetadata } from "./tool-metadata.js";
|
|
3
4
|
export const serverCardPath = '/.well-known/mcp/server-card.json';
|
|
4
|
-
const
|
|
5
|
+
const toolInputs = [
|
|
5
6
|
{
|
|
6
7
|
name: 'transloadit_lint_assembly_instructions',
|
|
7
|
-
title: 'Lint Assembly Instructions',
|
|
8
|
-
description: 'Lint Assembly Instructions without creating an Assembly. Returns structured issues.',
|
|
9
8
|
inputSchema: {
|
|
10
9
|
type: 'object',
|
|
11
10
|
additionalProperties: false,
|
|
@@ -19,8 +18,6 @@ const tools = [
|
|
|
19
18
|
},
|
|
20
19
|
{
|
|
21
20
|
name: 'transloadit_create_assembly',
|
|
22
|
-
title: 'Create or resume an Assembly',
|
|
23
|
-
description: 'Create or resume an Assembly, optionally uploading files and waiting for completion.',
|
|
24
21
|
inputSchema: {
|
|
25
22
|
type: 'object',
|
|
26
23
|
additionalProperties: false,
|
|
@@ -30,6 +27,20 @@ const tools = [
|
|
|
30
27
|
type: 'array',
|
|
31
28
|
items: { type: 'object' },
|
|
32
29
|
},
|
|
30
|
+
attachments: {
|
|
31
|
+
type: 'array',
|
|
32
|
+
items: {
|
|
33
|
+
type: 'object',
|
|
34
|
+
additionalProperties: false,
|
|
35
|
+
required: ['download_url', 'file_id'],
|
|
36
|
+
properties: {
|
|
37
|
+
download_url: { type: 'string' },
|
|
38
|
+
file_id: { type: 'string' },
|
|
39
|
+
mime_type: { type: 'string' },
|
|
40
|
+
file_name: { type: 'string' },
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
},
|
|
33
44
|
fields: { type: 'object' },
|
|
34
45
|
wait_for_completion: { type: 'boolean' },
|
|
35
46
|
wait_timeout_ms: { type: 'number' },
|
|
@@ -43,8 +54,6 @@ const tools = [
|
|
|
43
54
|
},
|
|
44
55
|
{
|
|
45
56
|
name: 'transloadit_get_assembly_status',
|
|
46
|
-
title: 'Get Assembly Status',
|
|
47
|
-
description: 'Fetch the latest Assembly status by URL or ID.',
|
|
48
57
|
inputSchema: {
|
|
49
58
|
type: 'object',
|
|
50
59
|
additionalProperties: false,
|
|
@@ -56,8 +65,6 @@ const tools = [
|
|
|
56
65
|
},
|
|
57
66
|
{
|
|
58
67
|
name: 'transloadit_wait_for_assembly',
|
|
59
|
-
title: 'Wait For Assembly Completion',
|
|
60
|
-
description: 'Polls until the Assembly completes or timeout is reached.',
|
|
61
68
|
inputSchema: {
|
|
62
69
|
type: 'object',
|
|
63
70
|
additionalProperties: false,
|
|
@@ -71,8 +78,6 @@ const tools = [
|
|
|
71
78
|
},
|
|
72
79
|
{
|
|
73
80
|
name: 'transloadit_list_robots',
|
|
74
|
-
title: 'List Robots',
|
|
75
|
-
description: 'Returns a filtered list of robots with short summaries.',
|
|
76
81
|
inputSchema: {
|
|
77
82
|
type: 'object',
|
|
78
83
|
additionalProperties: false,
|
|
@@ -86,8 +91,6 @@ const tools = [
|
|
|
86
91
|
},
|
|
87
92
|
{
|
|
88
93
|
name: 'transloadit_get_robot_help',
|
|
89
|
-
title: 'Get Robot Help',
|
|
90
|
-
description: 'Returns a robot summary and parameter details.',
|
|
91
94
|
inputSchema: {
|
|
92
95
|
type: 'object',
|
|
93
96
|
additionalProperties: false,
|
|
@@ -99,8 +102,6 @@ const tools = [
|
|
|
99
102
|
},
|
|
100
103
|
{
|
|
101
104
|
name: 'transloadit_list_templates',
|
|
102
|
-
title: 'List Templates',
|
|
103
|
-
description: 'List Assembly Templates (owned and/or builtin). Tip: pass include_builtin: "exclusively-latest" to list builtins only.',
|
|
104
105
|
inputSchema: {
|
|
105
106
|
type: 'object',
|
|
106
107
|
additionalProperties: false,
|
|
@@ -118,9 +119,31 @@ const tools = [
|
|
|
118
119
|
},
|
|
119
120
|
},
|
|
120
121
|
},
|
|
122
|
+
{
|
|
123
|
+
name: 'transloadit_get_profile',
|
|
124
|
+
inputSchema: {
|
|
125
|
+
type: 'object',
|
|
126
|
+
additionalProperties: false,
|
|
127
|
+
properties: {},
|
|
128
|
+
},
|
|
129
|
+
},
|
|
121
130
|
];
|
|
131
|
+
/** Tool definitions with the security schemes this deployment mode can honor. */
|
|
132
|
+
const buildTools = (mode) => toolInputs.map((tool) => {
|
|
133
|
+
const metadata = toolMetadata[tool.name];
|
|
134
|
+
return {
|
|
135
|
+
...tool,
|
|
136
|
+
title: metadata.title,
|
|
137
|
+
description: metadata.description,
|
|
138
|
+
annotations: metadata.annotations,
|
|
139
|
+
securitySchemes: resolveSecuritySchemes(metadata, mode),
|
|
140
|
+
};
|
|
141
|
+
});
|
|
122
142
|
export const buildServerCard = (endpoint, options = {}) => {
|
|
123
143
|
const hasCredentials = Boolean(options.authKey && options.authSecret);
|
|
144
|
+
const tools = buildTools(resolveToolAuthMode(options));
|
|
145
|
+
// Hosted deployments hand out tokens through OAuth; self-hosted ones accept a static bearer.
|
|
146
|
+
const schemes = options.resourceMetadataUrl ? ['oauth2', 'bearer'] : ['bearer'];
|
|
124
147
|
return {
|
|
125
148
|
$schema: 'https://static.modelcontextprotocol.io/schemas/mcp-server-card/v1.json',
|
|
126
149
|
version: '1.0',
|
|
@@ -139,10 +162,12 @@ export const buildServerCard = (endpoint, options = {}) => {
|
|
|
139
162
|
},
|
|
140
163
|
authentication: {
|
|
141
164
|
required: !hasCredentials,
|
|
142
|
-
schemes
|
|
165
|
+
schemes,
|
|
166
|
+
...(options.resourceMetadataUrl ? { resourceMetadataUrl: options.resourceMetadataUrl } : {}),
|
|
143
167
|
},
|
|
144
168
|
capabilities: {
|
|
145
169
|
tools: { listChanged: false },
|
|
170
|
+
resources: { listChanged: false },
|
|
146
171
|
},
|
|
147
172
|
tools,
|
|
148
173
|
};
|