@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.
Files changed (58) hide show
  1. package/README.md +256 -80
  2. package/dist/cli.js +52 -2
  3. package/dist/cli.js.map +1 -1
  4. package/dist/express.d.ts.map +1 -1
  5. package/dist/express.js +25 -12
  6. package/dist/express.js.map +1 -1
  7. package/dist/http-helpers.d.ts +90 -0
  8. package/dist/http-helpers.d.ts.map +1 -1
  9. package/dist/http-helpers.js +193 -3
  10. package/dist/http-helpers.js.map +1 -1
  11. package/dist/http-request-handler.d.ts +1 -0
  12. package/dist/http-request-handler.d.ts.map +1 -1
  13. package/dist/http-request-handler.js +9 -19
  14. package/dist/http-request-handler.js.map +1 -1
  15. package/dist/http.d.ts +2 -0
  16. package/dist/http.d.ts.map +1 -1
  17. package/dist/http.js +25 -49
  18. package/dist/http.js.map +1 -1
  19. package/dist/json.d.ts +5 -0
  20. package/dist/json.d.ts.map +1 -0
  21. package/dist/json.js +14 -0
  22. package/dist/json.js.map +1 -0
  23. package/dist/logger.d.ts.map +1 -1
  24. package/dist/logger.js +4 -1
  25. package/dist/logger.js.map +1 -1
  26. package/dist/options.d.ts +12 -0
  27. package/dist/options.d.ts.map +1 -0
  28. package/dist/options.js +34 -0
  29. package/dist/options.js.map +1 -0
  30. package/dist/request-transport.d.ts +21 -0
  31. package/dist/request-transport.d.ts.map +1 -0
  32. package/dist/request-transport.js +129 -0
  33. package/dist/request-transport.js.map +1 -0
  34. package/dist/server-card.d.ts +20 -7
  35. package/dist/server-card.d.ts.map +1 -1
  36. package/dist/server-card.js +41 -16
  37. package/dist/server-card.js.map +1 -1
  38. package/dist/server.d.ts +45 -0
  39. package/dist/server.d.ts.map +1 -1
  40. package/dist/server.js +423 -81
  41. package/dist/server.js.map +1 -1
  42. package/dist/tool-list.d.ts +9 -0
  43. package/dist/tool-list.d.ts.map +1 -0
  44. package/dist/tool-list.js +44 -0
  45. package/dist/tool-list.js.map +1 -0
  46. package/dist/tool-metadata.d.ts +53 -0
  47. package/dist/tool-metadata.d.ts.map +1 -0
  48. package/dist/tool-metadata.js +147 -0
  49. package/dist/tool-metadata.js.map +1 -0
  50. package/dist/ui/assembly-result-widget.d.ts +47 -0
  51. package/dist/ui/assembly-result-widget.d.ts.map +1 -0
  52. package/dist/ui/assembly-result-widget.js +449 -0
  53. package/dist/ui/assembly-result-widget.js.map +1 -0
  54. package/dist/upload-instructions.d.ts +29 -0
  55. package/dist/upload-instructions.d.ts.map +1 -0
  56. package/dist/upload-instructions.js +60 -0
  57. package/dist/upload-instructions.js.map +1 -0
  58. package/package.json +3 -2
package/dist/express.js CHANGED
@@ -1,19 +1,26 @@
1
- import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
2
1
  import express from 'express';
3
- import { isBasicAuthorized } from "./http-helpers.js";
2
+ import { applyCorsHeaders, assertHttpOptions, corsAllowHeaders, isBasicAuthorized, rejectMissingBearerToken, resolveAllowedOrigins, } from "./http-helpers.js";
4
3
  import { getMetrics, getMetricsContentType } from "./metrics.js";
4
+ import { createRequestTransport } from "./request-transport.js";
5
5
  import { createTransloaditMcpServer } from "./server.js";
6
6
  import { buildServerCard, serverCardPath } from "./server-card.js";
7
7
  export function createTransloaditMcpExpressRouter(options = {}) {
8
+ assertHttpOptions(options);
8
9
  const router = express.Router();
9
10
  const routePath = options.path ?? '/mcp';
10
11
  const metricsPath = options.metricsPath === false ? undefined : (options.metricsPath ?? '/metrics');
11
12
  const metricsAuth = options.metricsAuth;
12
- const serverCardJson = JSON.stringify(buildServerCard(routePath, { authKey: options.authKey, authSecret: options.authSecret }));
13
+ // Explicit `allowedOrigins` or hosted mode add an Origin policy here; embedders own CORS otherwise.
14
+ const allowedOrigins = resolveAllowedOrigins(options);
15
+ const serverCardJson = JSON.stringify(buildServerCard(routePath, {
16
+ authKey: options.authKey,
17
+ authSecret: options.authSecret,
18
+ resourceMetadataUrl: options.resourceMetadataUrl,
19
+ }));
13
20
  const sendServerCard = (res, includeBody) => {
14
21
  res.setHeader('Access-Control-Allow-Origin', '*');
15
22
  res.setHeader('Access-Control-Allow-Methods', 'GET,HEAD,OPTIONS');
16
- res.setHeader('Access-Control-Allow-Headers', 'Authorization,Content-Type,Mcp-Session-Id,Last-Event-ID');
23
+ res.setHeader('Access-Control-Allow-Headers', corsAllowHeaders);
17
24
  res.setHeader('Content-Type', 'application/json; charset=utf-8');
18
25
  res.setHeader('Cache-Control', 'public, max-age=3600');
19
26
  res.setHeader('X-Content-Type-Options', 'nosniff');
@@ -26,7 +33,7 @@ export function createTransloaditMcpExpressRouter(options = {}) {
26
33
  router.options(serverCardPath, (_req, res) => {
27
34
  res.setHeader('Access-Control-Allow-Origin', '*');
28
35
  res.setHeader('Access-Control-Allow-Methods', 'GET,HEAD,OPTIONS');
29
- res.setHeader('Access-Control-Allow-Headers', 'Authorization,Content-Type,Mcp-Session-Id,Last-Event-ID');
36
+ res.setHeader('Access-Control-Allow-Headers', corsAllowHeaders);
30
37
  res.status(204).end();
31
38
  });
32
39
  router.get(serverCardPath, (_req, res) => {
@@ -36,6 +43,17 @@ export function createTransloaditMcpExpressRouter(options = {}) {
36
43
  sendServerCard(res, false);
37
44
  });
38
45
  router.all(routePath, async (req, res) => {
46
+ if (allowedOrigins) {
47
+ if (!applyCorsHeaders(req, res, allowedOrigins))
48
+ return;
49
+ if (req.method === 'OPTIONS') {
50
+ res.status(204).end();
51
+ return;
52
+ }
53
+ }
54
+ // Any unauthenticated hosted method gets the OAuth challenge, so GET-probing clients find API2.
55
+ if (rejectMissingBearerToken(req, res, options.resourceMetadataUrl))
56
+ return;
39
57
  if (req.method !== 'POST') {
40
58
  res.status(405).json({
41
59
  jsonrpc: '2.0',
@@ -44,19 +62,14 @@ export function createTransloaditMcpExpressRouter(options = {}) {
44
62
  });
45
63
  return;
46
64
  }
47
- const transport = new StreamableHTTPServerTransport({
48
- sessionIdGenerator: undefined,
49
- allowedOrigins: options.allowedOrigins,
50
- allowedHosts: options.allowedHosts,
51
- enableDnsRebindingProtection: options.enableDnsRebindingProtection,
52
- });
65
+ const { transport, handle } = createRequestTransport(options);
53
66
  const server = createTransloaditMcpServer(options);
54
67
  res.on('close', () => {
55
68
  void transport.close();
56
69
  void server.close();
57
70
  });
58
71
  await server.connect(transport);
59
- await transport.handleRequest(req, res, req.body);
72
+ await handle(req, res, req.body);
60
73
  });
61
74
  if (metricsPath) {
62
75
  router.get(metricsPath, async (req, res) => {
@@ -1 +1 @@
1
- {"version":3,"file":"express.js","sourceRoot":"","sources":["../src/express.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"express.js","sourceRoot":"","sources":["../src/express.ts"],"names":[],"mappings":"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"}
@@ -11,5 +11,95 @@ export declare const isBasicAuthorized: (req: IncomingMessage, expected: {
11
11
  username: string;
12
12
  password: string;
13
13
  }) => boolean;
14
+ /**
15
+ * Browser origins the hosted endpoint accepts when no explicit `allowedOrigins` are configured:
16
+ * the ChatGPT and Claude web apps, Transloadit sites, devdock and loopback. Requests without an
17
+ * `Origin` header (CLIs, servers) are never subject to this list.
18
+ */
19
+ export declare const hostedAllowedOrigins: string[];
20
+ /**
21
+ * Matches an `Origin` header against an allowlist entry. Entries are exact origins or patterns
22
+ * with a `*.` subdomain wildcard and/or a `:*` any-port suffix.
23
+ */
24
+ export declare const matchesOriginPattern: (origin: string, pattern: string) => boolean;
25
+ export declare const isOriginAllowed: (origin: string, allowedOrigins: string[]) => boolean;
26
+ /** Explicit `allowedOrigins` win; hosted mode falls back to the ChatGPT/Claude/Transloadit list. */
27
+ export declare const resolveAllowedOrigins: (options: {
28
+ allowedOrigins?: string[];
29
+ resourceMetadataUrl?: string;
30
+ }) => string[] | undefined;
14
31
  export declare const applyCorsHeaders: (req: IncomingMessage, res: ServerResponse, allowedOrigins?: string[]) => boolean;
32
+ /**
33
+ * Request headers browser MCP clients send (Streamable HTTP adds `Mcp-Protocol-Version` after
34
+ * initialization); preflights that omit one block the client entirely.
35
+ */
36
+ export declare const corsAllowHeaders = "Authorization,Content-Type,Mcp-Protocol-Version,Mcp-Session-Id,Last-Event-ID";
37
+ /** Response headers browser clients must read: the session id and the OAuth challenge. */
38
+ export declare const corsExposeHeaders = "Mcp-Session-Id,WWW-Authenticate";
39
+ /** Human-readable status served on bare GETs and kept in the hosted 401 body. */
40
+ export declare const serverInfo: {
41
+ name: string;
42
+ status: string;
43
+ docs: string;
44
+ };
45
+ /**
46
+ * Bare GETs without the SSE Accept header are not valid MCP requests (Streamable HTTP requires
47
+ * `Accept: text/event-stream` for GET). Answer with a friendly status so directory health probes
48
+ * (Glama, uptime monitors) see a 200 instead of the SDK's opaque 406. Returns `true` when sent.
49
+ */
50
+ export declare const sendServerInfoForBareGet: (req: IncomingMessage, res: ServerResponse) => boolean;
51
+ /**
52
+ * `WWW-Authenticate` value (RFC 6750) that points OAuth clients at the protected-resource
53
+ * metadata and, for rejected requests, names the error so hosts show their linking UI.
54
+ */
55
+ export declare const buildBearerChallenge: (options: {
56
+ resourceMetadataUrl?: string;
57
+ error?: {
58
+ code: string;
59
+ description: string;
60
+ };
61
+ /** Scopes the client should request again (RFC 6750 `scope`, used to re-scope on 403). */
62
+ scopes?: string[];
63
+ }) => string;
64
+ /**
65
+ * Request body limits the README documents. Hosted requests only carry JSON-RPC and small base64
66
+ * payloads, and pass the bearer gate before API2 has checked the token, so they get the smaller one.
67
+ */
68
+ export declare const resolveMaxRequestBodyBytes: (options: {
69
+ maxRequestBodyBytes?: number;
70
+ resourceMetadataUrl?: string;
71
+ }) => number;
72
+ /**
73
+ * Reads a request body up to `maxBytes`. Returns `undefined` once it is larger; the rest is drained
74
+ * without being kept, so an oversized body cannot exhaust memory.
75
+ */
76
+ export declare const readBodyWithinLimit: (req: IncomingMessage, maxBytes: number) => Promise<string | undefined>;
77
+ export declare const sendBodyTooLarge: (res: ServerResponse, maxBytes: number) => void;
78
+ /**
79
+ * Refuses HTTP options that would fail silently later. The static-token check runs first and
80
+ * would reject every OAuth token with a bare `Bearer` challenge, so hosted OAuth could never start.
81
+ */
82
+ export declare const assertHttpOptions: (options: {
83
+ mcpToken?: string;
84
+ resourceMetadataUrl?: string;
85
+ upstreamSecret?: string;
86
+ maxRequestBodyBytes?: unknown;
87
+ maxUrlDownloadBytes?: unknown;
88
+ urlDownloadTimeoutMs?: unknown;
89
+ resultDomains?: string[];
90
+ widgetDomain?: string;
91
+ }) => void;
92
+ /**
93
+ * Self-hosted policy: the request must carry the static `TRANSLOADIT_MCP_TOKEN`. Returns `true`
94
+ * when the 401 was already sent.
95
+ */
96
+ export declare const rejectMissingMcpToken: (req: IncomingMessage, res: ServerResponse, mcpToken: string | undefined) => boolean;
97
+ /**
98
+ * Hosted policy: a bearer token only has to be present, because API2 verifies it on every
99
+ * forwarded call. Without one, any request (bare GET probes included, since clients such as Codex
100
+ * discover the authorization server from an unauthenticated GET) gets a 401 that points OAuth
101
+ * clients at the protected-resource metadata. The body keeps the friendly server status for
102
+ * humans. Returns `true` when the 401 was already sent.
103
+ */
104
+ export declare const rejectMissingBearerToken: (req: IncomingMessage, res: ServerResponse, resourceMetadataUrl: string | undefined) => boolean;
15
105
  //# sourceMappingURL=http-helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"http-helpers.d.ts","sourceRoot":"","sources":["../src/http-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAIhE,eAAO,MAAM,aAAa,GAAI,KAAK,MAAM,GAAG,SAAS,EAAE,UAAU,MAAM,KAAG,MAMzE,CAAA;AAED,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,KAAG,MACqB,CAAA;AAElE,eAAO,MAAM,kBAAkB,GAAI,QAAQ,MAAM,GAAG,SAAS,KAAG,MAAM,GAAG,SAKxE,CAAA;AAED,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,MAAM,GAAG,SAAS,KACzB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,SAgB3C,CAAA;AASD,eAAO,MAAM,YAAY,GAAI,KAAK,eAAe,EAAE,OAAO,MAAM,KAAG,OAIlE,CAAA;AAED,eAAO,MAAM,iBAAiB,GAC5B,KAAK,eAAe,EACpB,UAAU;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,KAC/C,OAOF,CAAA;AAED,eAAO,MAAM,gBAAgB,GAC3B,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,iBAAiB,MAAM,EAAE,KACxB,OA0BF,CAAA"}
1
+ {"version":3,"file":"http-helpers.d.ts","sourceRoot":"","sources":["../src/http-helpers.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { timingSafeEqual } from 'node:crypto';
2
+ import { assertRequestBodyLimit, assertServerOptions } from "./options.js";
2
3
  export const parsePathname = (url, fallback) => {
3
4
  try {
4
5
  return new URL(url ?? fallback, 'http://localhost').pathname;
@@ -57,13 +58,73 @@ export const isBasicAuthorized = (req, expected) => {
57
58
  return (timingSafeEqualString(provided.username, expected.username) &&
58
59
  timingSafeEqualString(provided.password, expected.password));
59
60
  };
61
+ /**
62
+ * Browser origins the hosted endpoint accepts when no explicit `allowedOrigins` are configured:
63
+ * the ChatGPT and Claude web apps, Transloadit sites, devdock and loopback. Requests without an
64
+ * `Origin` header (CLIs, servers) are never subject to this list.
65
+ */
66
+ export const hostedAllowedOrigins = [
67
+ 'https://chatgpt.com',
68
+ 'https://chat.openai.com',
69
+ 'https://claude.ai',
70
+ 'https://claude.com',
71
+ 'https://transloadit.com',
72
+ 'https://*.transloadit.com',
73
+ 'https://transloadit.dev:*',
74
+ 'https://*.transloadit.dev:*',
75
+ 'http://localhost:*',
76
+ 'https://localhost:*',
77
+ 'http://127.0.0.1:*',
78
+ 'https://127.0.0.1:*',
79
+ 'http://[::1]:*',
80
+ 'https://[::1]:*',
81
+ ];
82
+ const originPatternRegex = /^(?<protocol>https?):\/\/(?<host>\*\.)?(?<hostname>\[[^\]]+\]|[^:/]+)(?::(?<port>\*|\d+))?$/;
83
+ /**
84
+ * Matches an `Origin` header against an allowlist entry. Entries are exact origins or patterns
85
+ * with a `*.` subdomain wildcard and/or a `:*` any-port suffix.
86
+ */
87
+ export const matchesOriginPattern = (origin, pattern) => {
88
+ if (origin === pattern)
89
+ return true;
90
+ const match = originPatternRegex.exec(pattern);
91
+ if (!match?.groups)
92
+ return false;
93
+ let url;
94
+ try {
95
+ url = new URL(origin);
96
+ }
97
+ catch {
98
+ return false;
99
+ }
100
+ const { protocol, host, hostname, port } = match.groups;
101
+ if (url.protocol !== `${protocol}:`)
102
+ return false;
103
+ const originHost = url.hostname.replaceAll(/^\[|\]$/g, '');
104
+ const patternHost = (hostname ?? '').replaceAll(/^\[|\]$/g, '');
105
+ const hostMatches = host
106
+ ? originHost.endsWith(`.${patternHost}`) && originHost.length > patternHost.length + 1
107
+ : originHost === patternHost;
108
+ if (!hostMatches)
109
+ return false;
110
+ if (port === '*')
111
+ return true;
112
+ return url.port === (port ?? '');
113
+ };
114
+ export const isOriginAllowed = (origin, allowedOrigins) => allowedOrigins.some((pattern) => matchesOriginPattern(origin, pattern));
115
+ /** Explicit `allowedOrigins` win; hosted mode falls back to the ChatGPT/Claude/Transloadit list. */
116
+ export const resolveAllowedOrigins = (options) => {
117
+ if (options.allowedOrigins && options.allowedOrigins.length > 0)
118
+ return options.allowedOrigins;
119
+ return options.resourceMetadataUrl ? hostedAllowedOrigins : undefined;
120
+ };
60
121
  export const applyCorsHeaders = (req, res, allowedOrigins) => {
61
122
  const origin = req.headers.origin;
62
123
  if (!origin) {
63
124
  return true;
64
125
  }
65
126
  if (allowedOrigins && allowedOrigins.length > 0) {
66
- if (!allowedOrigins.includes(origin)) {
127
+ if (!isOriginAllowed(origin, allowedOrigins)) {
67
128
  res.statusCode = 403;
68
129
  res.end('Forbidden');
69
130
  return false;
@@ -75,8 +136,137 @@ export const applyCorsHeaders = (req, res, allowedOrigins) => {
75
136
  res.setHeader('Access-Control-Allow-Origin', '*');
76
137
  }
77
138
  res.setHeader('Access-Control-Allow-Methods', 'GET,POST,DELETE,OPTIONS');
78
- res.setHeader('Access-Control-Allow-Headers', 'Authorization,Content-Type,Mcp-Session-Id,Last-Event-ID');
79
- res.setHeader('Access-Control-Expose-Headers', 'Mcp-Session-Id');
139
+ res.setHeader('Access-Control-Allow-Headers', corsAllowHeaders);
140
+ res.setHeader('Access-Control-Expose-Headers', corsExposeHeaders);
141
+ return true;
142
+ };
143
+ /**
144
+ * Request headers browser MCP clients send (Streamable HTTP adds `Mcp-Protocol-Version` after
145
+ * initialization); preflights that omit one block the client entirely.
146
+ */
147
+ export const corsAllowHeaders = 'Authorization,Content-Type,Mcp-Protocol-Version,Mcp-Session-Id,Last-Event-ID';
148
+ /** Response headers browser clients must read: the session id and the OAuth challenge. */
149
+ export const corsExposeHeaders = 'Mcp-Session-Id,WWW-Authenticate';
150
+ /** Human-readable status served on bare GETs and kept in the hosted 401 body. */
151
+ export const serverInfo = {
152
+ name: 'Transloadit MCP Server',
153
+ status: 'ok',
154
+ docs: 'https://transloadit.com/docs/sdks/mcp-server/',
155
+ };
156
+ /**
157
+ * Bare GETs without the SSE Accept header are not valid MCP requests (Streamable HTTP requires
158
+ * `Accept: text/event-stream` for GET). Answer with a friendly status so directory health probes
159
+ * (Glama, uptime monitors) see a 200 instead of the SDK's opaque 406. Returns `true` when sent.
160
+ */
161
+ export const sendServerInfoForBareGet = (req, res) => {
162
+ const accept = req.headers.accept ?? '';
163
+ if (req.method !== 'GET' || accept.includes('text/event-stream'))
164
+ return false;
165
+ res.statusCode = 200;
166
+ res.setHeader('Content-Type', 'application/json');
167
+ res.end(JSON.stringify(serverInfo));
168
+ return true;
169
+ };
170
+ /**
171
+ * `WWW-Authenticate` value (RFC 6750) that points OAuth clients at the protected-resource
172
+ * metadata and, for rejected requests, names the error so hosts show their linking UI.
173
+ */
174
+ export const buildBearerChallenge = (options) => {
175
+ const parts = [];
176
+ if (options.resourceMetadataUrl) {
177
+ parts.push(`resource_metadata="${options.resourceMetadataUrl}"`);
178
+ }
179
+ if (options.error) {
180
+ parts.push(`error="${options.error.code}"`, `error_description="${options.error.description.replaceAll('"', "'")}"`);
181
+ }
182
+ if (options.scopes && options.scopes.length > 0) {
183
+ parts.push(`scope="${options.scopes.join(' ')}"`);
184
+ }
185
+ return parts.length > 0 ? `Bearer ${parts.join(', ')}` : 'Bearer';
186
+ };
187
+ /**
188
+ * Request body limits the README documents. Hosted requests only carry JSON-RPC and small base64
189
+ * payloads, and pass the bearer gate before API2 has checked the token, so they get the smaller one.
190
+ */
191
+ export const resolveMaxRequestBodyBytes = (options) => options.maxRequestBodyBytes ?? (options.resourceMetadataUrl ? 1 : 10) * 1024 * 1024;
192
+ /**
193
+ * Reads a request body up to `maxBytes`. Returns `undefined` once it is larger; the rest is drained
194
+ * without being kept, so an oversized body cannot exhaust memory.
195
+ */
196
+ export const readBodyWithinLimit = (req, maxBytes) => new Promise((resolve, reject) => {
197
+ const chunks = [];
198
+ let size = 0;
199
+ let tooLarge = false;
200
+ req.on('data', (chunk) => {
201
+ if (tooLarge)
202
+ return;
203
+ size += chunk.length;
204
+ if (size > maxBytes) {
205
+ tooLarge = true;
206
+ chunks.length = 0;
207
+ resolve(undefined);
208
+ return;
209
+ }
210
+ chunks.push(chunk);
211
+ });
212
+ req.on('end', () => {
213
+ if (!tooLarge)
214
+ resolve(Buffer.concat(chunks).toString('utf8'));
215
+ });
216
+ req.on('error', reject);
217
+ });
218
+ export const sendBodyTooLarge = (res, maxBytes) => {
219
+ res.statusCode = 413;
220
+ res.setHeader('Connection', 'close');
221
+ res.setHeader('Content-Type', 'application/json');
222
+ res.end(JSON.stringify({
223
+ jsonrpc: '2.0',
224
+ error: { code: -32000, message: `Request body exceeds ${maxBytes} bytes.` },
225
+ id: null,
226
+ }));
227
+ };
228
+ /**
229
+ * Refuses HTTP options that would fail silently later. The static-token check runs first and
230
+ * would reject every OAuth token with a bare `Bearer` challenge, so hosted OAuth could never start.
231
+ */
232
+ export const assertHttpOptions = (options) => {
233
+ if (options.mcpToken && options.resourceMetadataUrl) {
234
+ throw new Error('Configure either TRANSLOADIT_MCP_TOKEN (self-hosted) or TRANSLOADIT_MCP_RESOURCE_METADATA_URL (hosted OAuth), not both.');
235
+ }
236
+ assertRequestBodyLimit(options.maxRequestBodyBytes);
237
+ // Also checked per server instance; repeated here so a bad config fails at startup.
238
+ assertServerOptions(options);
239
+ };
240
+ /**
241
+ * Self-hosted policy: the request must carry the static `TRANSLOADIT_MCP_TOKEN`. Returns `true`
242
+ * when the 401 was already sent.
243
+ */
244
+ export const rejectMissingMcpToken = (req, res, mcpToken) => {
245
+ if (!mcpToken || isAuthorized(req, mcpToken))
246
+ return false;
247
+ res.statusCode = 401;
248
+ res.setHeader('WWW-Authenticate', 'Bearer');
249
+ res.end('Unauthorized');
250
+ return true;
251
+ };
252
+ /**
253
+ * Hosted policy: a bearer token only has to be present, because API2 verifies it on every
254
+ * forwarded call. Without one, any request (bare GET probes included, since clients such as Codex
255
+ * discover the authorization server from an unauthenticated GET) gets a 401 that points OAuth
256
+ * clients at the protected-resource metadata. The body keeps the friendly server status for
257
+ * humans. Returns `true` when the 401 was already sent.
258
+ */
259
+ export const rejectMissingBearerToken = (req, res, resourceMetadataUrl) => {
260
+ if (!resourceMetadataUrl || extractBearerToken(req.headers.authorization))
261
+ return false;
262
+ res.statusCode = 401;
263
+ res.setHeader('WWW-Authenticate', buildBearerChallenge({ resourceMetadataUrl }));
264
+ res.setHeader('Content-Type', 'application/json');
265
+ res.end(JSON.stringify({
266
+ ...serverInfo,
267
+ error: 'unauthorized',
268
+ error_description: 'This endpoint requires an OAuth bearer token. Discover the authorization server through the resource_metadata URL in the WWW-Authenticate header.',
269
+ }));
80
270
  return true;
81
271
  };
82
272
  //# sourceMappingURL=http-helpers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"http-helpers.js","sourceRoot":"","sources":["../src/http-helpers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"http-helpers.js","sourceRoot":"","sources":["../src/http-helpers.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,7 @@ type PathPolicy = {
8
8
  type RequestHandlerOptions = {
9
9
  allowedOrigins?: string[];
10
10
  mcpToken?: string;
11
+ resourceMetadataUrl?: string;
11
12
  path: PathPolicy;
12
13
  logger?: SevLogger;
13
14
  redactSecrets?: Array<string | undefined>;
@@ -1 +1 @@
1
- {"version":3,"file":"http-request-handler.d.ts","sourceRoot":"","sources":["../src/http-request-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAEhE,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAA;AACvG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAKxD,KAAK,UAAU,GAAG;IAChB,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AAED,KAAK,qBAAqB,GAAG;IAC3B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,UAAU,CAAA;IAChB,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB,aAAa,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;CAC1C,CAAA;AAED,eAAO,MAAM,uBAAuB,GAClC,WAAW,6BAA6B,EACxC,SAAS,qBAAqB,MAOhB,KAAK,eAAe,EAAE,KAAK,cAAc,kBAoDxD,CAAA"}
1
+ {"version":3,"file":"http-request-handler.d.ts","sourceRoot":"","sources":["../src/http-request-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAEhE,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAA;AACvG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAcxD,KAAK,UAAU,GAAG;IAChB,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AAED,KAAK,qBAAqB,GAAG;IAC3B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,IAAI,EAAE,UAAU,CAAA;IAChB,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB,aAAa,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;CAC1C,CAAA;AAED,eAAO,MAAM,uBAAuB,GAClC,WAAW,6BAA6B,EACxC,SAAS,qBAAqB,MAShB,KAAK,eAAe,EAAE,KAAK,cAAc,kBAuCxD,CAAA"}
@@ -1,10 +1,12 @@
1
- import { applyCorsHeaders, isAuthorized, normalizePath, parsePathname } from "./http-helpers.js";
1
+ import { applyCorsHeaders, assertHttpOptions, normalizePath, parsePathname, rejectMissingBearerToken, rejectMissingMcpToken, resolveAllowedOrigins, sendServerInfoForBareGet, } from "./http-helpers.js";
2
2
  import { buildRedactor, getLogger } from "./logger.js";
3
3
  export const createMcpRequestHandler = (transport, options) => {
4
+ assertHttpOptions(options);
4
5
  const expectedPath = normalizePath(options.path.expectedPath);
5
6
  const allowRoot = options.path.allowRoot ?? false;
6
7
  const logger = options.logger ?? getLogger().nest('http');
7
8
  const redact = buildRedactor(options.redactSecrets ?? []);
9
+ const allowedOrigins = resolveAllowedOrigins(options);
8
10
  return async (req, res) => {
9
11
  const pathname = normalizePath(parsePathname(req.url, expectedPath));
10
12
  if (pathname !== expectedPath && (!allowRoot || pathname !== '/')) {
@@ -12,7 +14,7 @@ export const createMcpRequestHandler = (transport, options) => {
12
14
  res.end('Not Found');
13
15
  return;
14
16
  }
15
- if (!applyCorsHeaders(req, res, options.allowedOrigins)) {
17
+ if (!applyCorsHeaders(req, res, allowedOrigins)) {
16
18
  return;
17
19
  }
18
20
  if (req.method === 'OPTIONS') {
@@ -20,25 +22,13 @@ export const createMcpRequestHandler = (transport, options) => {
20
22
  res.end();
21
23
  return;
22
24
  }
23
- if (options.mcpToken && !isAuthorized(req, options.mcpToken)) {
24
- res.statusCode = 401;
25
- res.setHeader('WWW-Authenticate', 'Bearer');
26
- res.end('Unauthorized');
25
+ if (rejectMissingMcpToken(req, res, options.mcpToken)) {
27
26
  return;
28
27
  }
29
- // Bare GETs without the SSE Accept header are not valid MCP requests (the
30
- // Streamable HTTP spec requires Accept: text/event-stream for GET). Return
31
- // a friendly JSON status so directory health-probes (Glama, uptime monitors)
32
- // see a 200 instead of the SDK's opaque 406.
33
- const accept = req.headers.accept ?? '';
34
- if (req.method === 'GET' && !accept.includes('text/event-stream')) {
35
- res.statusCode = 200;
36
- res.setHeader('Content-Type', 'application/json');
37
- res.end(JSON.stringify({
38
- name: 'Transloadit MCP Server',
39
- status: 'ok',
40
- docs: 'https://transloadit.com/docs/sdks/mcp-server/',
41
- }));
28
+ if (rejectMissingBearerToken(req, res, options.resourceMetadataUrl)) {
29
+ return;
30
+ }
31
+ if (sendServerInfoForBareGet(req, res)) {
42
32
  return;
43
33
  }
44
34
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"http-request-handler.js","sourceRoot":"","sources":["../src/http-request-handler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"http-request-handler.js","sourceRoot":"","sources":["../src/http-request-handler.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,wBAAwB,EACxB,qBAAqB,EACrB,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAgBtD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,SAAwC,EACxC,OAA8B,EAC9B,EAAE;IACF,iBAAiB,CAAC,OAAO,CAAC,CAAA;IAC1B,MAAM,YAAY,GAAG,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;IAC7D,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,SAAS,IAAI,KAAK,CAAA;IACjD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IACzD,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,aAAa,IAAI,EAAE,CAAC,CAAA;IACzD,MAAM,cAAc,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAA;IAErD,OAAO,KAAK,EAAE,GAAoB,EAAE,GAAmB,EAAE,EAAE;QACzD,MAAM,QAAQ,GAAG,aAAa,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAA;QACpE,IAAI,QAAQ,KAAK,YAAY,IAAI,CAAC,CAAC,SAAS,IAAI,QAAQ,KAAK,GAAG,CAAC,EAAE,CAAC;YAClE,GAAG,CAAC,UAAU,GAAG,GAAG,CAAA;YACpB,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;YACpB,OAAM;QACR,CAAC;QAED,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,GAAG,EAAE,cAAc,CAAC,EAAE,CAAC;YAChD,OAAM;QACR,CAAC;QAED,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC7B,GAAG,CAAC,UAAU,GAAG,GAAG,CAAA;YACpB,GAAG,CAAC,GAAG,EAAE,CAAA;YACT,OAAM;QACR,CAAC;QAED,IAAI,qBAAqB,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YACtD,OAAM;QACR,CAAC;QAED,IAAI,wBAAwB,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,mBAAmB,CAAC,EAAE,CAAC;YACpE,OAAM;QACR,CAAC;QAED,IAAI,wBAAwB,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;YACvC,OAAM;QACR,CAAC;QAED,IAAI,CAAC;YACH,MAAM,UAAU,GAAI,GAA0B,CAAC,IAAI,CAAA;YACnD,MAAM,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,CAAC,CAAA;QACrD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,GAAG,CAAC,oBAAoB,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;YACrF,GAAG,CAAC,UAAU,GAAG,GAAG,CAAA;YACpB,GAAG,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAA;QAClC,CAAC;IACH,CAAC,CAAA;AACH,CAAC,CAAA"}
package/dist/http.d.ts CHANGED
@@ -12,6 +12,8 @@ export type TransloaditMcpHttpOptions = TransloaditMcpServerOptions & {
12
12
  username: string;
13
13
  password: string;
14
14
  };
15
+ /** Largest accepted request body; defaults to 1 MiB hosted and 10 MiB self-hosted. */
16
+ maxRequestBodyBytes?: number;
15
17
  sessionIdGenerator?: (() => string) | undefined;
16
18
  logger?: SevLogger;
17
19
  };
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAEhE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAExD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAA;AAe9D,MAAM,MAAM,yBAAyB,GAAG,2BAA2B,GAAG;IACpE,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;IACzB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB,4BAA4B,CAAC,EAAE,OAAO,CAAA;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;IAC5B,WAAW,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;IAEpD,kBAAkB,CAAC,EAAE,CAAC,MAAM,MAAM,CAAC,GAAG,SAAS,CAAA;IAC/C,MAAM,CAAC,EAAE,SAAS,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG,CAAC,CACvC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,KAChB,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG;IACpB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3B,CAAA;AAyBD,wBAAgB,+BAA+B,CAC7C,OAAO,GAAE,yBAA8B,GACtC,yBAAyB,CA6J3B"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAEhE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAGxD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAA;AAsB9D,MAAM,MAAM,yBAAyB,GAAG,2BAA2B,GAAG;IACpE,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;IACzB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB,4BAA4B,CAAC,EAAE,OAAO,CAAA;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;IAC5B,WAAW,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;IACpD,sFAAsF;IACtF,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAE5B,kBAAkB,CAAC,EAAE,CAAC,MAAM,MAAM,CAAC,GAAG,SAAS,CAAA;IAC/C,MAAM,CAAC,EAAE,SAAS,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG,CAAC,CACvC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,KAChB,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG;IACpB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3B,CAAA;AAID,wBAAgB,+BAA+B,CAC7C,OAAO,GAAE,yBAA8B,GACtC,yBAAyB,CAwJ3B"}