mcp-proxy 5.8.1 → 5.10.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 +33 -3
- package/dist/index.js +2 -2
- package/dist/{stdio-9KZaSDCW.js → stdio-DF5lH8jj.js} +92 -42
- package/dist/stdio-DF5lH8jj.js.map +1 -0
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/src/authentication.test.ts +77 -2
- package/src/authentication.ts +16 -4
- package/src/index.ts +3 -0
- package/src/startHTTPServer.test.ts +248 -0
- package/src/startHTTPServer.ts +147 -15
- package/dist/stdio-9KZaSDCW.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-DF5lH8jj.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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import http from "http";
|
|
1
|
+
import http, { IncomingMessage } from "http";
|
|
2
2
|
import { EventStore } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
3
3
|
import { JSONRPCMessage, ServerCapabilities } from "@modelcontextprotocol/sdk/types.js";
|
|
4
4
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
@@ -7,8 +7,26 @@ import { SSEClientTransportOptions } from "@modelcontextprotocol/sdk/client/sse.
|
|
|
7
7
|
import { StreamableHTTPClientTransportOptions } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
8
8
|
import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
|
|
9
9
|
|
|
10
|
+
//#region src/authentication.d.ts
|
|
11
|
+
interface AuthConfig {
|
|
12
|
+
apiKey?: string;
|
|
13
|
+
oauth?: {
|
|
14
|
+
protectedResource?: {
|
|
15
|
+
resource?: string;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
declare class AuthenticationMiddleware {
|
|
20
|
+
private config;
|
|
21
|
+
constructor(config?: AuthConfig);
|
|
22
|
+
getUnauthorizedResponse(): {
|
|
23
|
+
body: string;
|
|
24
|
+
headers: Record<string, string>;
|
|
25
|
+
};
|
|
26
|
+
validateRequest(req: IncomingMessage): boolean;
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
10
29
|
//#region src/InMemoryEventStore.d.ts
|
|
11
|
-
|
|
12
30
|
/**
|
|
13
31
|
* Simple in-memory implementation of the EventStore interface for resumability
|
|
14
32
|
* This is primarily intended for examples and testing, not for production use
|
|
@@ -54,6 +72,14 @@ declare const proxyServer: ({
|
|
|
54
72
|
}) => Promise<void>;
|
|
55
73
|
//#endregion
|
|
56
74
|
//#region src/startHTTPServer.d.ts
|
|
75
|
+
interface CorsOptions {
|
|
76
|
+
allowedHeaders?: string | string[];
|
|
77
|
+
credentials?: boolean;
|
|
78
|
+
exposedHeaders?: string[];
|
|
79
|
+
maxAge?: number;
|
|
80
|
+
methods?: string[];
|
|
81
|
+
origin?: ((origin: string) => boolean) | string | string[];
|
|
82
|
+
}
|
|
57
83
|
type SSEServer = {
|
|
58
84
|
close: () => Promise<void>;
|
|
59
85
|
};
|
|
@@ -64,10 +90,12 @@ type ServerLike = {
|
|
|
64
90
|
declare const startHTTPServer: <T extends ServerLike>({
|
|
65
91
|
apiKey,
|
|
66
92
|
authenticate,
|
|
93
|
+
cors,
|
|
67
94
|
createServer,
|
|
68
95
|
enableJsonResponse,
|
|
69
96
|
eventStore,
|
|
70
97
|
host,
|
|
98
|
+
oauth,
|
|
71
99
|
onClose,
|
|
72
100
|
onConnect,
|
|
73
101
|
onUnhandledRequest,
|
|
@@ -78,10 +106,12 @@ declare const startHTTPServer: <T extends ServerLike>({
|
|
|
78
106
|
}: {
|
|
79
107
|
apiKey?: string;
|
|
80
108
|
authenticate?: (request: http.IncomingMessage) => Promise<unknown>;
|
|
109
|
+
cors?: boolean | CorsOptions;
|
|
81
110
|
createServer: (request: http.IncomingMessage) => Promise<T>;
|
|
82
111
|
enableJsonResponse?: boolean;
|
|
83
112
|
eventStore?: EventStore;
|
|
84
113
|
host?: string;
|
|
114
|
+
oauth?: AuthConfig["oauth"];
|
|
85
115
|
onClose?: (server: T) => Promise<void>;
|
|
86
116
|
onConnect?: (server: T) => Promise<void>;
|
|
87
117
|
onUnhandledRequest?: (req: http.IncomingMessage, res: http.ServerResponse) => Promise<void>;
|
|
@@ -129,5 +159,5 @@ type TransportEvent = {
|
|
|
129
159
|
};
|
|
130
160
|
declare const tapTransport: (transport: Transport, eventHandler: (event: TransportEvent) => void) => Transport;
|
|
131
161
|
//#endregion
|
|
132
|
-
export { InMemoryEventStore, ServerType, proxyServer, startHTTPServer, startStdioServer, tapTransport };
|
|
162
|
+
export { type AuthConfig, AuthenticationMiddleware, type CorsOptions, InMemoryEventStore, ServerType, proxyServer, startHTTPServer, startStdioServer, tapTransport };
|
|
133
163
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { 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-DF5lH8jj.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
|
|
@@ -1850,5 +1850,5 @@ const tapTransport = (transport, eventHandler) => {
|
|
|
1850
1850
|
};
|
|
1851
1851
|
|
|
1852
1852
|
//#endregion
|
|
1853
|
-
export { InMemoryEventStore, ServerType, proxyServer, startHTTPServer, startStdioServer, tapTransport };
|
|
1853
|
+
export { AuthenticationMiddleware, InMemoryEventStore, ServerType, proxyServer, startHTTPServer, startStdioServer, tapTransport };
|
|
1854
1854
|
//# sourceMappingURL=index.js.map
|
|
@@ -29,6 +29,35 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
29
29
|
}) : target, mod));
|
|
30
30
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
31
31
|
|
|
32
|
+
//#endregion
|
|
33
|
+
//#region src/authentication.ts
|
|
34
|
+
var AuthenticationMiddleware = class {
|
|
35
|
+
constructor(config = {}) {
|
|
36
|
+
this.config = config;
|
|
37
|
+
}
|
|
38
|
+
getUnauthorizedResponse() {
|
|
39
|
+
const headers = { "Content-Type": "application/json" };
|
|
40
|
+
if (this.config.oauth?.protectedResource?.resource) headers["WWW-Authenticate"] = `Bearer resource_metadata="${this.config.oauth.protectedResource.resource}/.well-known/oauth-protected-resource"`;
|
|
41
|
+
return {
|
|
42
|
+
body: JSON.stringify({
|
|
43
|
+
error: {
|
|
44
|
+
code: 401,
|
|
45
|
+
message: "Unauthorized: Invalid or missing API key"
|
|
46
|
+
},
|
|
47
|
+
id: null,
|
|
48
|
+
jsonrpc: "2.0"
|
|
49
|
+
}),
|
|
50
|
+
headers
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
validateRequest(req) {
|
|
54
|
+
if (!this.config.apiKey) return true;
|
|
55
|
+
const apiKey = req.headers["x-api-key"];
|
|
56
|
+
if (!apiKey || typeof apiKey !== "string") return false;
|
|
57
|
+
return apiKey === this.config.apiKey;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
32
61
|
//#endregion
|
|
33
62
|
//#region src/InMemoryEventStore.ts
|
|
34
63
|
/**
|
|
@@ -14968,33 +14997,6 @@ var StreamableHTTPServerTransport = class {
|
|
|
14968
14997
|
}
|
|
14969
14998
|
};
|
|
14970
14999
|
|
|
14971
|
-
//#endregion
|
|
14972
|
-
//#region src/authentication.ts
|
|
14973
|
-
var AuthenticationMiddleware = class {
|
|
14974
|
-
constructor(config = {}) {
|
|
14975
|
-
this.config = config;
|
|
14976
|
-
}
|
|
14977
|
-
getUnauthorizedResponse() {
|
|
14978
|
-
return {
|
|
14979
|
-
body: JSON.stringify({
|
|
14980
|
-
error: {
|
|
14981
|
-
code: 401,
|
|
14982
|
-
message: "Unauthorized: Invalid or missing API key"
|
|
14983
|
-
},
|
|
14984
|
-
id: null,
|
|
14985
|
-
jsonrpc: "2.0"
|
|
14986
|
-
}),
|
|
14987
|
-
headers: { "Content-Type": "application/json" }
|
|
14988
|
-
};
|
|
14989
|
-
}
|
|
14990
|
-
validateRequest(req) {
|
|
14991
|
-
if (!this.config.apiKey) return true;
|
|
14992
|
-
const apiKey = req.headers["x-api-key"];
|
|
14993
|
-
if (!apiKey || typeof apiKey !== "string") return false;
|
|
14994
|
-
return apiKey === this.config.apiKey;
|
|
14995
|
-
}
|
|
14996
|
-
};
|
|
14997
|
-
|
|
14998
15000
|
//#endregion
|
|
14999
15001
|
//#region src/startHTTPServer.ts
|
|
15000
15002
|
const getBody = (request) => {
|
|
@@ -15024,6 +15026,10 @@ const createJsonRpcErrorResponse = (code, message) => {
|
|
|
15024
15026
|
jsonrpc: "2.0"
|
|
15025
15027
|
});
|
|
15026
15028
|
};
|
|
15029
|
+
const getWWWAuthenticateHeader = (oauth) => {
|
|
15030
|
+
if (!oauth?.protectedResource?.resource) return;
|
|
15031
|
+
return `Bearer resource_metadata="${oauth.protectedResource.resource}/.well-known/oauth-protected-resource"`;
|
|
15032
|
+
};
|
|
15027
15033
|
const handleResponseError = (error, res) => {
|
|
15028
15034
|
if (error instanceof Response) {
|
|
15029
15035
|
const fixedHeaders = {};
|
|
@@ -15045,7 +15051,48 @@ const cleanupServer = async (server, onClose) => {
|
|
|
15045
15051
|
console.error("[mcp-proxy] error closing server", error);
|
|
15046
15052
|
}
|
|
15047
15053
|
};
|
|
15048
|
-
const
|
|
15054
|
+
const applyCorsHeaders = (req, res, corsOptions) => {
|
|
15055
|
+
if (!req.headers.origin) return;
|
|
15056
|
+
const defaultCorsOptions = {
|
|
15057
|
+
allowedHeaders: "Content-Type, Authorization, Accept, Mcp-Session-Id, Last-Event-Id",
|
|
15058
|
+
credentials: true,
|
|
15059
|
+
exposedHeaders: ["Mcp-Session-Id"],
|
|
15060
|
+
methods: [
|
|
15061
|
+
"GET",
|
|
15062
|
+
"POST",
|
|
15063
|
+
"OPTIONS"
|
|
15064
|
+
],
|
|
15065
|
+
origin: "*"
|
|
15066
|
+
};
|
|
15067
|
+
let finalCorsOptions;
|
|
15068
|
+
if (corsOptions === false) return;
|
|
15069
|
+
else if (corsOptions === true || corsOptions === void 0) finalCorsOptions = defaultCorsOptions;
|
|
15070
|
+
else finalCorsOptions = {
|
|
15071
|
+
...defaultCorsOptions,
|
|
15072
|
+
...corsOptions
|
|
15073
|
+
};
|
|
15074
|
+
try {
|
|
15075
|
+
const origin = new URL(req.headers.origin);
|
|
15076
|
+
let allowedOrigin = "*";
|
|
15077
|
+
if (finalCorsOptions.origin) {
|
|
15078
|
+
if (typeof finalCorsOptions.origin === "string") allowedOrigin = finalCorsOptions.origin;
|
|
15079
|
+
else if (Array.isArray(finalCorsOptions.origin)) allowedOrigin = finalCorsOptions.origin.includes(origin.origin) ? origin.origin : "false";
|
|
15080
|
+
else if (typeof finalCorsOptions.origin === "function") allowedOrigin = finalCorsOptions.origin(origin.origin) ? origin.origin : "false";
|
|
15081
|
+
}
|
|
15082
|
+
if (allowedOrigin !== "false") res.setHeader("Access-Control-Allow-Origin", allowedOrigin);
|
|
15083
|
+
if (finalCorsOptions.credentials !== void 0) res.setHeader("Access-Control-Allow-Credentials", finalCorsOptions.credentials.toString());
|
|
15084
|
+
if (finalCorsOptions.methods) res.setHeader("Access-Control-Allow-Methods", finalCorsOptions.methods.join(", "));
|
|
15085
|
+
if (finalCorsOptions.allowedHeaders) {
|
|
15086
|
+
const allowedHeaders = typeof finalCorsOptions.allowedHeaders === "string" ? finalCorsOptions.allowedHeaders : finalCorsOptions.allowedHeaders.join(", ");
|
|
15087
|
+
res.setHeader("Access-Control-Allow-Headers", allowedHeaders);
|
|
15088
|
+
}
|
|
15089
|
+
if (finalCorsOptions.exposedHeaders) res.setHeader("Access-Control-Expose-Headers", finalCorsOptions.exposedHeaders.join(", "));
|
|
15090
|
+
if (finalCorsOptions.maxAge !== void 0) res.setHeader("Access-Control-Max-Age", finalCorsOptions.maxAge.toString());
|
|
15091
|
+
} catch (error) {
|
|
15092
|
+
console.error("[mcp-proxy] error parsing origin", error);
|
|
15093
|
+
}
|
|
15094
|
+
};
|
|
15095
|
+
const handleStreamRequest = async ({ activeTransports, authenticate, createServer, enableJsonResponse, endpoint, eventStore, oauth, onClose, onConnect, req, res, stateless }) => {
|
|
15049
15096
|
if (req.method === "POST" && new URL(req.url, "http://localhost").pathname === endpoint) {
|
|
15050
15097
|
try {
|
|
15051
15098
|
const sessionId = Array.isArray(req.headers["mcp-session-id"]) ? req.headers["mcp-session-id"][0] : req.headers["mcp-session-id"];
|
|
@@ -15057,6 +15104,8 @@ const handleStreamRequest = async ({ activeTransports, authenticate, createServe
|
|
|
15057
15104
|
if (!authResult || typeof authResult === "object" && "authenticated" in authResult && !authResult.authenticated) {
|
|
15058
15105
|
const errorMessage = authResult && typeof authResult === "object" && "error" in authResult && typeof authResult.error === "string" ? authResult.error : "Unauthorized: Authentication failed";
|
|
15059
15106
|
res.setHeader("Content-Type", "application/json");
|
|
15107
|
+
const wwwAuthHeader = getWWWAuthenticateHeader(oauth);
|
|
15108
|
+
if (wwwAuthHeader) res.setHeader("WWW-Authenticate", wwwAuthHeader);
|
|
15060
15109
|
res.writeHead(401).end(JSON.stringify({
|
|
15061
15110
|
error: {
|
|
15062
15111
|
code: -32e3,
|
|
@@ -15071,6 +15120,8 @@ const handleStreamRequest = async ({ activeTransports, authenticate, createServe
|
|
|
15071
15120
|
const errorMessage = error instanceof Error ? error.message : "Unauthorized: Authentication error";
|
|
15072
15121
|
console.error("Authentication error:", error);
|
|
15073
15122
|
res.setHeader("Content-Type", "application/json");
|
|
15123
|
+
const wwwAuthHeader = getWWWAuthenticateHeader(oauth);
|
|
15124
|
+
if (wwwAuthHeader) res.setHeader("WWW-Authenticate", wwwAuthHeader);
|
|
15074
15125
|
res.writeHead(401).end(JSON.stringify({
|
|
15075
15126
|
error: {
|
|
15076
15127
|
code: -32e3,
|
|
@@ -15118,6 +15169,8 @@ const handleStreamRequest = async ({ activeTransports, authenticate, createServe
|
|
|
15118
15169
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
15119
15170
|
if (errorMessage.includes("Authentication") || errorMessage.includes("Invalid JWT") || errorMessage.includes("Token") || errorMessage.includes("Unauthorized")) {
|
|
15120
15171
|
res.setHeader("Content-Type", "application/json");
|
|
15172
|
+
const wwwAuthHeader = getWWWAuthenticateHeader(oauth);
|
|
15173
|
+
if (wwwAuthHeader) res.setHeader("WWW-Authenticate", wwwAuthHeader);
|
|
15121
15174
|
res.writeHead(401).end(JSON.stringify({
|
|
15122
15175
|
error: {
|
|
15123
15176
|
code: -32e3,
|
|
@@ -15149,6 +15202,8 @@ const handleStreamRequest = async ({ activeTransports, authenticate, createServe
|
|
|
15149
15202
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
15150
15203
|
if (errorMessage.includes("Authentication") || errorMessage.includes("Invalid JWT") || errorMessage.includes("Token") || errorMessage.includes("Unauthorized")) {
|
|
15151
15204
|
res.setHeader("Content-Type", "application/json");
|
|
15205
|
+
const wwwAuthHeader = getWWWAuthenticateHeader(oauth);
|
|
15206
|
+
if (wwwAuthHeader) res.setHeader("WWW-Authenticate", wwwAuthHeader);
|
|
15152
15207
|
res.writeHead(401).end(JSON.stringify({
|
|
15153
15208
|
error: {
|
|
15154
15209
|
code: -32e3,
|
|
@@ -15275,24 +15330,18 @@ const handleSSERequest = async ({ activeTransports, createServer, endpoint, onCl
|
|
|
15275
15330
|
}
|
|
15276
15331
|
return false;
|
|
15277
15332
|
};
|
|
15278
|
-
const startHTTPServer = async ({ apiKey, authenticate, createServer, enableJsonResponse, eventStore, host = "::", onClose, onConnect, onUnhandledRequest, port, sseEndpoint = "/sse", stateless, streamEndpoint = "/mcp" }) => {
|
|
15333
|
+
const startHTTPServer = async ({ apiKey, authenticate, cors, createServer, enableJsonResponse, eventStore, host = "::", oauth, onClose, onConnect, onUnhandledRequest, port, sseEndpoint = "/sse", stateless, streamEndpoint = "/mcp" }) => {
|
|
15279
15334
|
const activeSSETransports = {};
|
|
15280
15335
|
const activeStreamTransports = {};
|
|
15281
|
-
const authMiddleware = new AuthenticationMiddleware({
|
|
15336
|
+
const authMiddleware = new AuthenticationMiddleware({
|
|
15337
|
+
apiKey,
|
|
15338
|
+
oauth
|
|
15339
|
+
});
|
|
15282
15340
|
/**
|
|
15283
15341
|
* @author https://dev.classmethod.jp/articles/mcp-sse/
|
|
15284
15342
|
*/
|
|
15285
15343
|
const httpServer = http.createServer(async (req, res) => {
|
|
15286
|
-
|
|
15287
|
-
const origin = new URL(req.headers.origin);
|
|
15288
|
-
res.setHeader("Access-Control-Allow-Origin", origin.origin);
|
|
15289
|
-
res.setHeader("Access-Control-Allow-Credentials", "true");
|
|
15290
|
-
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
15291
|
-
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Accept, Mcp-Session-Id, Last-Event-Id");
|
|
15292
|
-
res.setHeader("Access-Control-Expose-Headers", "Mcp-Session-Id");
|
|
15293
|
-
} catch (error) {
|
|
15294
|
-
console.error("[mcp-proxy] error parsing origin", error);
|
|
15295
|
-
}
|
|
15344
|
+
applyCorsHeaders(req, res, cors);
|
|
15296
15345
|
if (req.method === "OPTIONS") {
|
|
15297
15346
|
res.writeHead(204);
|
|
15298
15347
|
res.end();
|
|
@@ -15324,6 +15373,7 @@ const startHTTPServer = async ({ apiKey, authenticate, createServer, enableJsonR
|
|
|
15324
15373
|
enableJsonResponse,
|
|
15325
15374
|
endpoint: streamEndpoint,
|
|
15326
15375
|
eventStore,
|
|
15376
|
+
oauth,
|
|
15327
15377
|
onClose,
|
|
15328
15378
|
onConnect,
|
|
15329
15379
|
req,
|
|
@@ -21538,5 +21588,5 @@ function serializeMessage(message) {
|
|
|
21538
21588
|
}
|
|
21539
21589
|
|
|
21540
21590
|
//#endregion
|
|
21541
|
-
export { Client, InMemoryEventStore, JSONRPCMessageSchema, LATEST_PROTOCOL_VERSION, NEVER, ReadBuffer, Server, ZodIssueCode, __commonJS, __toESM, anyType, arrayType, booleanType, isInitializedNotification, isJSONRPCRequest, isJSONRPCResponse, numberType, objectType, proxyServer, serializeMessage, startHTTPServer, stringType };
|
|
21542
|
-
//# sourceMappingURL=stdio-
|
|
21591
|
+
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 };
|
|
21592
|
+
//# sourceMappingURL=stdio-DF5lH8jj.js.map
|