mcp-proxy 5.9.0 → 5.11.0
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 +148 -1
- package/dist/bin/mcp-proxy.js +1 -1
- package/dist/index.d.ts +22 -2
- package/dist/index.js +1 -1
- package/dist/{stdio-CsjPjeWC.js → stdio-BEX6di72.js} +105 -29
- package/dist/stdio-BEX6di72.js.map +1 -0
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/src/authentication.test.ts +145 -7
- package/src/authentication.ts +51 -5
- package/src/index.ts +1 -0
- package/src/startHTTPServer.test.ts +392 -0
- package/src/startHTTPServer.ts +207 -35
- package/dist/stdio-CsjPjeWC.js.map +0 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
A TypeScript streamable HTTP and SSE proxy for [MCP](https://modelcontextprotocol.io/) servers that use `stdio` transport.
|
|
4
4
|
|
|
5
5
|
> [!NOTE]
|
|
6
|
-
> CORS is enabled by default.
|
|
6
|
+
> CORS is enabled by default with configurable options. See [CORS Configuration](#cors-configuration) for details.
|
|
7
7
|
|
|
8
8
|
> [!NOTE]
|
|
9
9
|
> For a Python implementation, see [mcp-proxy](https://github.com/sparfenyuk/mcp-proxy).
|
|
@@ -143,6 +143,152 @@ The following endpoints do not require authentication:
|
|
|
143
143
|
- **Generate strong keys**: Use cryptographically secure random strings for API keys
|
|
144
144
|
- **Rotate keys regularly**: Change API keys periodically for better security
|
|
145
145
|
|
|
146
|
+
### CORS Configuration
|
|
147
|
+
|
|
148
|
+
MCP Proxy provides flexible CORS (Cross-Origin Resource Sharing) configuration to control how browsers can access your MCP server from different origins.
|
|
149
|
+
|
|
150
|
+
#### Default Behavior
|
|
151
|
+
|
|
152
|
+
By default, CORS is enabled with the following settings:
|
|
153
|
+
- **Origin**: `*` (allow all origins)
|
|
154
|
+
- **Methods**: `GET, POST, OPTIONS`
|
|
155
|
+
- **Headers**: `Content-Type, Authorization, Accept, Mcp-Session-Id, Last-Event-Id`
|
|
156
|
+
- **Credentials**: `true`
|
|
157
|
+
- **Exposed Headers**: `Mcp-Session-Id`
|
|
158
|
+
|
|
159
|
+
#### Basic Configuration
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
import { startHTTPServer } from 'mcp-proxy';
|
|
163
|
+
|
|
164
|
+
// Use default CORS settings (backward compatible)
|
|
165
|
+
await startHTTPServer({
|
|
166
|
+
createServer: async () => { /* ... */ },
|
|
167
|
+
port: 3000,
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
// Explicitly enable default CORS
|
|
171
|
+
await startHTTPServer({
|
|
172
|
+
createServer: async () => { /* ... */ },
|
|
173
|
+
port: 3000,
|
|
174
|
+
cors: true,
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// Disable CORS completely
|
|
178
|
+
await startHTTPServer({
|
|
179
|
+
createServer: async () => { /* ... */ },
|
|
180
|
+
port: 3000,
|
|
181
|
+
cors: false,
|
|
182
|
+
});
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
#### Advanced CORS Configuration
|
|
186
|
+
|
|
187
|
+
For more control over CORS behavior, you can provide a detailed configuration:
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
import { startHTTPServer, CorsOptions } from 'mcp-proxy';
|
|
191
|
+
|
|
192
|
+
const corsOptions: CorsOptions = {
|
|
193
|
+
// Allow specific origins
|
|
194
|
+
origin: ['https://app.example.com', 'https://admin.example.com'],
|
|
195
|
+
|
|
196
|
+
// Or use a function for dynamic origin validation
|
|
197
|
+
origin: (origin: string) => origin.endsWith('.example.com'),
|
|
198
|
+
|
|
199
|
+
// Specify allowed methods
|
|
200
|
+
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
|
|
201
|
+
|
|
202
|
+
// Allow any headers (useful for browser clients with custom headers)
|
|
203
|
+
allowedHeaders: '*',
|
|
204
|
+
|
|
205
|
+
// Or specify exact headers
|
|
206
|
+
allowedHeaders: [
|
|
207
|
+
'Content-Type',
|
|
208
|
+
'Authorization',
|
|
209
|
+
'Accept',
|
|
210
|
+
'Mcp-Session-Id',
|
|
211
|
+
'Last-Event-Id',
|
|
212
|
+
'X-Custom-Header',
|
|
213
|
+
'X-API-Key'
|
|
214
|
+
],
|
|
215
|
+
|
|
216
|
+
// Headers to expose to the client
|
|
217
|
+
exposedHeaders: ['Mcp-Session-Id', 'X-Total-Count'],
|
|
218
|
+
|
|
219
|
+
// Allow credentials
|
|
220
|
+
credentials: true,
|
|
221
|
+
|
|
222
|
+
// Cache preflight requests for 24 hours
|
|
223
|
+
maxAge: 86400,
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
await startHTTPServer({
|
|
227
|
+
createServer: async () => { /* ... */ },
|
|
228
|
+
port: 3000,
|
|
229
|
+
cors: corsOptions,
|
|
230
|
+
});
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
#### Common Use Cases
|
|
234
|
+
|
|
235
|
+
**Allow any custom headers (solves browser CORS issues):**
|
|
236
|
+
```typescript
|
|
237
|
+
await startHTTPServer({
|
|
238
|
+
createServer: async () => { /* ... */ },
|
|
239
|
+
port: 3000,
|
|
240
|
+
cors: {
|
|
241
|
+
allowedHeaders: '*', // Allows X-Custom-Header, X-API-Key, etc.
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**Restrict to specific domains:**
|
|
247
|
+
```typescript
|
|
248
|
+
await startHTTPServer({
|
|
249
|
+
createServer: async () => { /* ... */ },
|
|
250
|
+
port: 3000,
|
|
251
|
+
cors: {
|
|
252
|
+
origin: ['https://myapp.com', 'https://admin.myapp.com'],
|
|
253
|
+
allowedHeaders: '*',
|
|
254
|
+
},
|
|
255
|
+
});
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
**Development-friendly settings:**
|
|
259
|
+
```typescript
|
|
260
|
+
await startHTTPServer({
|
|
261
|
+
createServer: async () => { /* ... */ },
|
|
262
|
+
port: 3000,
|
|
263
|
+
cors: {
|
|
264
|
+
origin: ['http://localhost:3000', 'http://localhost:5173'], // Common dev ports
|
|
265
|
+
allowedHeaders: '*',
|
|
266
|
+
credentials: true,
|
|
267
|
+
},
|
|
268
|
+
});
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
#### Migration from Older Versions
|
|
272
|
+
|
|
273
|
+
If you were using mcp-proxy 5.5.6 and want the same permissive behavior in 5.9.0+:
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
// Old behavior (5.5.6) - automatic wildcard headers
|
|
277
|
+
await startHTTPServer({
|
|
278
|
+
createServer: async () => { /* ... */ },
|
|
279
|
+
port: 3000,
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
// New equivalent (5.9.0+) - explicit wildcard headers
|
|
283
|
+
await startHTTPServer({
|
|
284
|
+
createServer: async () => { /* ... */ },
|
|
285
|
+
port: 3000,
|
|
286
|
+
cors: {
|
|
287
|
+
allowedHeaders: '*',
|
|
288
|
+
},
|
|
289
|
+
});
|
|
290
|
+
```
|
|
291
|
+
|
|
146
292
|
### Node.js SDK
|
|
147
293
|
|
|
148
294
|
The Node.js SDK provides several utilities that are used to create a proxy.
|
|
@@ -198,6 +344,7 @@ Options:
|
|
|
198
344
|
- `streamEndpoint`: Streamable HTTP endpoint path (default: "/mcp", set to null to disable)
|
|
199
345
|
- `stateless`: Enable stateless mode for HTTP streamable transport (default: false)
|
|
200
346
|
- `apiKey`: API key for authenticating requests (optional)
|
|
347
|
+
- `cors`: CORS configuration (default: enabled with permissive settings, see CORS Configuration section)
|
|
201
348
|
- `onConnect`: Callback when a server connects (optional)
|
|
202
349
|
- `onClose`: Callback when a server disconnects (optional)
|
|
203
350
|
- `onUnhandledRequest`: Callback for unhandled HTTP requests (optional)
|
package/dist/bin/mcp-proxy.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { Client, InMemoryEventStore, ReadBuffer, Server, __commonJS, __toESM, proxyServer, serializeMessage, startHTTPServer } from "../stdio-
|
|
2
|
+
import { Client, InMemoryEventStore, ReadBuffer, Server, __commonJS, __toESM, proxyServer, serializeMessage, startHTTPServer } from "../stdio-BEX6di72.js";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { basename, dirname, extname, join, normalize, relative, resolve } from "path";
|
|
5
5
|
import { format, inspect } from "util";
|
package/dist/index.d.ts
CHANGED
|
@@ -11,15 +11,25 @@ import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
|
|
|
11
11
|
interface AuthConfig {
|
|
12
12
|
apiKey?: string;
|
|
13
13
|
oauth?: {
|
|
14
|
+
error?: string;
|
|
15
|
+
error_description?: string;
|
|
16
|
+
error_uri?: string;
|
|
14
17
|
protectedResource?: {
|
|
15
18
|
resource?: string;
|
|
16
19
|
};
|
|
20
|
+
realm?: string;
|
|
21
|
+
scope?: string;
|
|
17
22
|
};
|
|
18
23
|
}
|
|
19
24
|
declare class AuthenticationMiddleware {
|
|
20
25
|
private config;
|
|
21
26
|
constructor(config?: AuthConfig);
|
|
22
|
-
getUnauthorizedResponse(
|
|
27
|
+
getUnauthorizedResponse(options?: {
|
|
28
|
+
error?: string;
|
|
29
|
+
error_description?: string;
|
|
30
|
+
error_uri?: string;
|
|
31
|
+
scope?: string;
|
|
32
|
+
}): {
|
|
23
33
|
body: string;
|
|
24
34
|
headers: Record<string, string>;
|
|
25
35
|
};
|
|
@@ -72,6 +82,14 @@ declare const proxyServer: ({
|
|
|
72
82
|
}) => Promise<void>;
|
|
73
83
|
//#endregion
|
|
74
84
|
//#region src/startHTTPServer.d.ts
|
|
85
|
+
interface CorsOptions {
|
|
86
|
+
allowedHeaders?: string | string[];
|
|
87
|
+
credentials?: boolean;
|
|
88
|
+
exposedHeaders?: string[];
|
|
89
|
+
maxAge?: number;
|
|
90
|
+
methods?: string[];
|
|
91
|
+
origin?: ((origin: string) => boolean) | string | string[];
|
|
92
|
+
}
|
|
75
93
|
type SSEServer = {
|
|
76
94
|
close: () => Promise<void>;
|
|
77
95
|
};
|
|
@@ -82,6 +100,7 @@ type ServerLike = {
|
|
|
82
100
|
declare const startHTTPServer: <T extends ServerLike>({
|
|
83
101
|
apiKey,
|
|
84
102
|
authenticate,
|
|
103
|
+
cors,
|
|
85
104
|
createServer,
|
|
86
105
|
enableJsonResponse,
|
|
87
106
|
eventStore,
|
|
@@ -97,6 +116,7 @@ declare const startHTTPServer: <T extends ServerLike>({
|
|
|
97
116
|
}: {
|
|
98
117
|
apiKey?: string;
|
|
99
118
|
authenticate?: (request: http.IncomingMessage) => Promise<unknown>;
|
|
119
|
+
cors?: boolean | CorsOptions;
|
|
100
120
|
createServer: (request: http.IncomingMessage) => Promise<T>;
|
|
101
121
|
enableJsonResponse?: boolean;
|
|
102
122
|
eventStore?: EventStore;
|
|
@@ -149,5 +169,5 @@ type TransportEvent = {
|
|
|
149
169
|
};
|
|
150
170
|
declare const tapTransport: (transport: Transport, eventHandler: (event: TransportEvent) => void) => Transport;
|
|
151
171
|
//#endregion
|
|
152
|
-
export { type AuthConfig, AuthenticationMiddleware, InMemoryEventStore, ServerType, proxyServer, startHTTPServer, startStdioServer, tapTransport };
|
|
172
|
+
export { type AuthConfig, AuthenticationMiddleware, type CorsOptions, InMemoryEventStore, ServerType, proxyServer, startHTTPServer, startStdioServer, tapTransport };
|
|
153
173
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AuthenticationMiddleware, Client, InMemoryEventStore, JSONRPCMessageSchema, LATEST_PROTOCOL_VERSION, NEVER, ReadBuffer, Server, ZodIssueCode, anyType, arrayType, booleanType, isInitializedNotification, isJSONRPCRequest, isJSONRPCResponse, numberType, objectType, proxyServer, serializeMessage, startHTTPServer, stringType } from "./stdio-
|
|
1
|
+
import { AuthenticationMiddleware, Client, InMemoryEventStore, JSONRPCMessageSchema, LATEST_PROTOCOL_VERSION, NEVER, ReadBuffer, Server, ZodIssueCode, anyType, arrayType, booleanType, isInitializedNotification, isJSONRPCRequest, isJSONRPCResponse, numberType, objectType, proxyServer, serializeMessage, startHTTPServer, stringType } from "./stdio-BEX6di72.js";
|
|
2
2
|
import process from "node:process";
|
|
3
3
|
|
|
4
4
|
//#region node_modules/.pnpm/eventsource-parser@3.0.6/node_modules/eventsource-parser/dist/index.js
|
|
@@ -35,14 +35,27 @@ var AuthenticationMiddleware = class {
|
|
|
35
35
|
constructor(config = {}) {
|
|
36
36
|
this.config = config;
|
|
37
37
|
}
|
|
38
|
-
getUnauthorizedResponse() {
|
|
38
|
+
getUnauthorizedResponse(options) {
|
|
39
39
|
const headers = { "Content-Type": "application/json" };
|
|
40
|
-
if (this.config.oauth
|
|
40
|
+
if (this.config.oauth) {
|
|
41
|
+
const params = [];
|
|
42
|
+
if (this.config.oauth.realm) params.push(`realm="${this.config.oauth.realm}"`);
|
|
43
|
+
if (this.config.oauth.protectedResource?.resource) params.push(`resource_metadata="${this.config.oauth.protectedResource.resource}/.well-known/oauth-protected-resource"`);
|
|
44
|
+
const error = options?.error || this.config.oauth.error || "invalid_token";
|
|
45
|
+
params.push(`error="${error}"`);
|
|
46
|
+
const escaped = (options?.error_description || this.config.oauth.error_description || "Unauthorized: Invalid or missing API key").replace(/"/g, "\\\"");
|
|
47
|
+
params.push(`error_description="${escaped}"`);
|
|
48
|
+
const error_uri = options?.error_uri || this.config.oauth.error_uri;
|
|
49
|
+
if (error_uri) params.push(`error_uri="${error_uri}"`);
|
|
50
|
+
const scope = options?.scope || this.config.oauth.scope;
|
|
51
|
+
if (scope) params.push(`scope="${scope}"`);
|
|
52
|
+
if (params.length > 0) headers["WWW-Authenticate"] = `Bearer ${params.join(", ")}`;
|
|
53
|
+
}
|
|
41
54
|
return {
|
|
42
55
|
body: JSON.stringify({
|
|
43
56
|
error: {
|
|
44
57
|
code: 401,
|
|
45
|
-
message: "Unauthorized: Invalid or missing API key"
|
|
58
|
+
message: options?.error_description || "Unauthorized: Invalid or missing API key"
|
|
46
59
|
},
|
|
47
60
|
id: null,
|
|
48
61
|
jsonrpc: "2.0"
|
|
@@ -15026,19 +15039,37 @@ const createJsonRpcErrorResponse = (code, message) => {
|
|
|
15026
15039
|
jsonrpc: "2.0"
|
|
15027
15040
|
});
|
|
15028
15041
|
};
|
|
15029
|
-
const getWWWAuthenticateHeader = (oauth) => {
|
|
15030
|
-
if (!oauth
|
|
15031
|
-
|
|
15042
|
+
const getWWWAuthenticateHeader = (oauth, options) => {
|
|
15043
|
+
if (!oauth) return;
|
|
15044
|
+
const params = [];
|
|
15045
|
+
if (oauth.realm) params.push(`realm="${oauth.realm}"`);
|
|
15046
|
+
if (oauth.protectedResource?.resource) params.push(`resource_metadata="${oauth.protectedResource.resource}/.well-known/oauth-protected-resource"`);
|
|
15047
|
+
const error = options?.error || oauth.error;
|
|
15048
|
+
if (error) params.push(`error="${error}"`);
|
|
15049
|
+
const error_description = options?.error_description || oauth.error_description;
|
|
15050
|
+
if (error_description) {
|
|
15051
|
+
const escaped = error_description.replace(/"/g, "\\\"");
|
|
15052
|
+
params.push(`error_description="${escaped}"`);
|
|
15053
|
+
}
|
|
15054
|
+
const error_uri = options?.error_uri || oauth.error_uri;
|
|
15055
|
+
if (error_uri) params.push(`error_uri="${error_uri}"`);
|
|
15056
|
+
const scope = options?.scope || oauth.scope;
|
|
15057
|
+
if (scope) params.push(`scope="${scope}"`);
|
|
15058
|
+
if (params.length === 0) return;
|
|
15059
|
+
return `Bearer ${params.join(", ")}`;
|
|
15032
15060
|
};
|
|
15033
|
-
const handleResponseError = (error, res) => {
|
|
15034
|
-
if (error instanceof Response) {
|
|
15061
|
+
const handleResponseError = async (error, res) => {
|
|
15062
|
+
if (error && typeof error === "object" && "status" in error && "headers" in error && "statusText" in error || error instanceof Response) {
|
|
15063
|
+
const responseError = error;
|
|
15035
15064
|
const fixedHeaders = {};
|
|
15036
|
-
|
|
15065
|
+
responseError.headers.forEach((value, key$1) => {
|
|
15037
15066
|
if (fixedHeaders[key$1]) if (Array.isArray(fixedHeaders[key$1])) fixedHeaders[key$1].push(value);
|
|
15038
15067
|
else fixedHeaders[key$1] = [fixedHeaders[key$1], value];
|
|
15039
15068
|
else fixedHeaders[key$1] = value;
|
|
15040
15069
|
});
|
|
15041
|
-
|
|
15070
|
+
const body = await responseError.text();
|
|
15071
|
+
res.writeHead(responseError.status, responseError.statusText, fixedHeaders);
|
|
15072
|
+
res.end(body);
|
|
15042
15073
|
return true;
|
|
15043
15074
|
}
|
|
15044
15075
|
return false;
|
|
@@ -15051,6 +15082,47 @@ const cleanupServer = async (server, onClose) => {
|
|
|
15051
15082
|
console.error("[mcp-proxy] error closing server", error);
|
|
15052
15083
|
}
|
|
15053
15084
|
};
|
|
15085
|
+
const applyCorsHeaders = (req, res, corsOptions) => {
|
|
15086
|
+
if (!req.headers.origin) return;
|
|
15087
|
+
const defaultCorsOptions = {
|
|
15088
|
+
allowedHeaders: "Content-Type, Authorization, Accept, Mcp-Session-Id, Last-Event-Id",
|
|
15089
|
+
credentials: true,
|
|
15090
|
+
exposedHeaders: ["Mcp-Session-Id"],
|
|
15091
|
+
methods: [
|
|
15092
|
+
"GET",
|
|
15093
|
+
"POST",
|
|
15094
|
+
"OPTIONS"
|
|
15095
|
+
],
|
|
15096
|
+
origin: "*"
|
|
15097
|
+
};
|
|
15098
|
+
let finalCorsOptions;
|
|
15099
|
+
if (corsOptions === false) return;
|
|
15100
|
+
else if (corsOptions === true || corsOptions === void 0) finalCorsOptions = defaultCorsOptions;
|
|
15101
|
+
else finalCorsOptions = {
|
|
15102
|
+
...defaultCorsOptions,
|
|
15103
|
+
...corsOptions
|
|
15104
|
+
};
|
|
15105
|
+
try {
|
|
15106
|
+
const origin = new URL(req.headers.origin);
|
|
15107
|
+
let allowedOrigin = "*";
|
|
15108
|
+
if (finalCorsOptions.origin) {
|
|
15109
|
+
if (typeof finalCorsOptions.origin === "string") allowedOrigin = finalCorsOptions.origin;
|
|
15110
|
+
else if (Array.isArray(finalCorsOptions.origin)) allowedOrigin = finalCorsOptions.origin.includes(origin.origin) ? origin.origin : "false";
|
|
15111
|
+
else if (typeof finalCorsOptions.origin === "function") allowedOrigin = finalCorsOptions.origin(origin.origin) ? origin.origin : "false";
|
|
15112
|
+
}
|
|
15113
|
+
if (allowedOrigin !== "false") res.setHeader("Access-Control-Allow-Origin", allowedOrigin);
|
|
15114
|
+
if (finalCorsOptions.credentials !== void 0) res.setHeader("Access-Control-Allow-Credentials", finalCorsOptions.credentials.toString());
|
|
15115
|
+
if (finalCorsOptions.methods) res.setHeader("Access-Control-Allow-Methods", finalCorsOptions.methods.join(", "));
|
|
15116
|
+
if (finalCorsOptions.allowedHeaders) {
|
|
15117
|
+
const allowedHeaders = typeof finalCorsOptions.allowedHeaders === "string" ? finalCorsOptions.allowedHeaders : finalCorsOptions.allowedHeaders.join(", ");
|
|
15118
|
+
res.setHeader("Access-Control-Allow-Headers", allowedHeaders);
|
|
15119
|
+
}
|
|
15120
|
+
if (finalCorsOptions.exposedHeaders) res.setHeader("Access-Control-Expose-Headers", finalCorsOptions.exposedHeaders.join(", "));
|
|
15121
|
+
if (finalCorsOptions.maxAge !== void 0) res.setHeader("Access-Control-Max-Age", finalCorsOptions.maxAge.toString());
|
|
15122
|
+
} catch (error) {
|
|
15123
|
+
console.error("[mcp-proxy] error parsing origin", error);
|
|
15124
|
+
}
|
|
15125
|
+
};
|
|
15054
15126
|
const handleStreamRequest = async ({ activeTransports, authenticate, createServer, enableJsonResponse, endpoint, eventStore, oauth, onClose, onConnect, req, res, stateless }) => {
|
|
15055
15127
|
if (req.method === "POST" && new URL(req.url, "http://localhost").pathname === endpoint) {
|
|
15056
15128
|
try {
|
|
@@ -15063,7 +15135,10 @@ const handleStreamRequest = async ({ activeTransports, authenticate, createServe
|
|
|
15063
15135
|
if (!authResult || typeof authResult === "object" && "authenticated" in authResult && !authResult.authenticated) {
|
|
15064
15136
|
const errorMessage = authResult && typeof authResult === "object" && "error" in authResult && typeof authResult.error === "string" ? authResult.error : "Unauthorized: Authentication failed";
|
|
15065
15137
|
res.setHeader("Content-Type", "application/json");
|
|
15066
|
-
const wwwAuthHeader = getWWWAuthenticateHeader(oauth
|
|
15138
|
+
const wwwAuthHeader = getWWWAuthenticateHeader(oauth, {
|
|
15139
|
+
error: "invalid_token",
|
|
15140
|
+
error_description: errorMessage
|
|
15141
|
+
});
|
|
15067
15142
|
if (wwwAuthHeader) res.setHeader("WWW-Authenticate", wwwAuthHeader);
|
|
15068
15143
|
res.writeHead(401).end(JSON.stringify({
|
|
15069
15144
|
error: {
|
|
@@ -15076,10 +15151,14 @@ const handleStreamRequest = async ({ activeTransports, authenticate, createServe
|
|
|
15076
15151
|
return true;
|
|
15077
15152
|
}
|
|
15078
15153
|
} catch (error) {
|
|
15154
|
+
if (await handleResponseError(error, res)) return true;
|
|
15079
15155
|
const errorMessage = error instanceof Error ? error.message : "Unauthorized: Authentication error";
|
|
15080
15156
|
console.error("Authentication error:", error);
|
|
15081
15157
|
res.setHeader("Content-Type", "application/json");
|
|
15082
|
-
const wwwAuthHeader = getWWWAuthenticateHeader(oauth
|
|
15158
|
+
const wwwAuthHeader = getWWWAuthenticateHeader(oauth, {
|
|
15159
|
+
error: "invalid_token",
|
|
15160
|
+
error_description: errorMessage
|
|
15161
|
+
});
|
|
15083
15162
|
if (wwwAuthHeader) res.setHeader("WWW-Authenticate", wwwAuthHeader);
|
|
15084
15163
|
res.writeHead(401).end(JSON.stringify({
|
|
15085
15164
|
error: {
|
|
@@ -15125,10 +15204,14 @@ const handleStreamRequest = async ({ activeTransports, authenticate, createServe
|
|
|
15125
15204
|
try {
|
|
15126
15205
|
server = await createServer(req);
|
|
15127
15206
|
} catch (error) {
|
|
15207
|
+
if (await handleResponseError(error, res)) return true;
|
|
15128
15208
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
15129
15209
|
if (errorMessage.includes("Authentication") || errorMessage.includes("Invalid JWT") || errorMessage.includes("Token") || errorMessage.includes("Unauthorized")) {
|
|
15130
15210
|
res.setHeader("Content-Type", "application/json");
|
|
15131
|
-
const wwwAuthHeader = getWWWAuthenticateHeader(oauth
|
|
15211
|
+
const wwwAuthHeader = getWWWAuthenticateHeader(oauth, {
|
|
15212
|
+
error: "invalid_token",
|
|
15213
|
+
error_description: errorMessage
|
|
15214
|
+
});
|
|
15132
15215
|
if (wwwAuthHeader) res.setHeader("WWW-Authenticate", wwwAuthHeader);
|
|
15133
15216
|
res.writeHead(401).end(JSON.stringify({
|
|
15134
15217
|
error: {
|
|
@@ -15140,7 +15223,6 @@ const handleStreamRequest = async ({ activeTransports, authenticate, createServe
|
|
|
15140
15223
|
}));
|
|
15141
15224
|
return true;
|
|
15142
15225
|
}
|
|
15143
|
-
if (handleResponseError(error, res)) return true;
|
|
15144
15226
|
res.writeHead(500).end("Error creating server");
|
|
15145
15227
|
return true;
|
|
15146
15228
|
}
|
|
@@ -15158,10 +15240,14 @@ const handleStreamRequest = async ({ activeTransports, authenticate, createServe
|
|
|
15158
15240
|
try {
|
|
15159
15241
|
server = await createServer(req);
|
|
15160
15242
|
} catch (error) {
|
|
15243
|
+
if (await handleResponseError(error, res)) return true;
|
|
15161
15244
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
15162
15245
|
if (errorMessage.includes("Authentication") || errorMessage.includes("Invalid JWT") || errorMessage.includes("Token") || errorMessage.includes("Unauthorized")) {
|
|
15163
15246
|
res.setHeader("Content-Type", "application/json");
|
|
15164
|
-
const wwwAuthHeader = getWWWAuthenticateHeader(oauth
|
|
15247
|
+
const wwwAuthHeader = getWWWAuthenticateHeader(oauth, {
|
|
15248
|
+
error: "invalid_token",
|
|
15249
|
+
error_description: errorMessage
|
|
15250
|
+
});
|
|
15165
15251
|
if (wwwAuthHeader) res.setHeader("WWW-Authenticate", wwwAuthHeader);
|
|
15166
15252
|
res.writeHead(401).end(JSON.stringify({
|
|
15167
15253
|
error: {
|
|
@@ -15173,7 +15259,6 @@ const handleStreamRequest = async ({ activeTransports, authenticate, createServe
|
|
|
15173
15259
|
}));
|
|
15174
15260
|
return true;
|
|
15175
15261
|
}
|
|
15176
|
-
if (handleResponseError(error, res)) return true;
|
|
15177
15262
|
res.writeHead(500).end("Error creating server");
|
|
15178
15263
|
return true;
|
|
15179
15264
|
}
|
|
@@ -15243,7 +15328,7 @@ const handleSSERequest = async ({ activeTransports, createServer, endpoint, onCl
|
|
|
15243
15328
|
try {
|
|
15244
15329
|
server = await createServer(req);
|
|
15245
15330
|
} catch (error) {
|
|
15246
|
-
if (handleResponseError(error, res)) return true;
|
|
15331
|
+
if (await handleResponseError(error, res)) return true;
|
|
15247
15332
|
res.writeHead(500).end("Error creating server");
|
|
15248
15333
|
return true;
|
|
15249
15334
|
}
|
|
@@ -15289,7 +15374,7 @@ const handleSSERequest = async ({ activeTransports, createServer, endpoint, onCl
|
|
|
15289
15374
|
}
|
|
15290
15375
|
return false;
|
|
15291
15376
|
};
|
|
15292
|
-
const startHTTPServer = async ({ apiKey, authenticate, createServer, enableJsonResponse, eventStore, host = "::", oauth, onClose, onConnect, onUnhandledRequest, port, sseEndpoint = "/sse", stateless, streamEndpoint = "/mcp" }) => {
|
|
15377
|
+
const startHTTPServer = async ({ apiKey, authenticate, cors, createServer, enableJsonResponse, eventStore, host = "::", oauth, onClose, onConnect, onUnhandledRequest, port, sseEndpoint = "/sse", stateless, streamEndpoint = "/mcp" }) => {
|
|
15293
15378
|
const activeSSETransports = {};
|
|
15294
15379
|
const activeStreamTransports = {};
|
|
15295
15380
|
const authMiddleware = new AuthenticationMiddleware({
|
|
@@ -15300,16 +15385,7 @@ const startHTTPServer = async ({ apiKey, authenticate, createServer, enableJsonR
|
|
|
15300
15385
|
* @author https://dev.classmethod.jp/articles/mcp-sse/
|
|
15301
15386
|
*/
|
|
15302
15387
|
const httpServer = http.createServer(async (req, res) => {
|
|
15303
|
-
|
|
15304
|
-
const origin = new URL(req.headers.origin);
|
|
15305
|
-
res.setHeader("Access-Control-Allow-Origin", origin.origin);
|
|
15306
|
-
res.setHeader("Access-Control-Allow-Credentials", "true");
|
|
15307
|
-
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
15308
|
-
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Accept, Mcp-Session-Id, Last-Event-Id");
|
|
15309
|
-
res.setHeader("Access-Control-Expose-Headers", "Mcp-Session-Id");
|
|
15310
|
-
} catch (error) {
|
|
15311
|
-
console.error("[mcp-proxy] error parsing origin", error);
|
|
15312
|
-
}
|
|
15388
|
+
applyCorsHeaders(req, res, cors);
|
|
15313
15389
|
if (req.method === "OPTIONS") {
|
|
15314
15390
|
res.writeHead(204);
|
|
15315
15391
|
res.end();
|
|
@@ -21557,4 +21633,4 @@ function serializeMessage(message) {
|
|
|
21557
21633
|
|
|
21558
21634
|
//#endregion
|
|
21559
21635
|
export { AuthenticationMiddleware, Client, InMemoryEventStore, JSONRPCMessageSchema, LATEST_PROTOCOL_VERSION, NEVER, ReadBuffer, Server, ZodIssueCode, __commonJS, __toESM, anyType, arrayType, booleanType, isInitializedNotification, isJSONRPCRequest, isJSONRPCResponse, numberType, objectType, proxyServer, serializeMessage, startHTTPServer, stringType };
|
|
21560
|
-
//# sourceMappingURL=stdio-
|
|
21636
|
+
//# sourceMappingURL=stdio-BEX6di72.js.map
|