@llmindset/hf-mcp-server 0.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/components.json +21 -0
- package/dist/server/application.d.ts +30 -0
- package/dist/server/application.d.ts.map +1 -0
- package/dist/server/application.js +131 -0
- package/dist/server/application.js.map +1 -0
- package/dist/server/gradio-endpoint-connector.d.ts +46 -0
- package/dist/server/gradio-endpoint-connector.d.ts.map +1 -0
- package/dist/server/gradio-endpoint-connector.js +348 -0
- package/dist/server/gradio-endpoint-connector.js.map +1 -0
- package/dist/server/gradio-endpoint-connector.test.d.ts +2 -0
- package/dist/server/gradio-endpoint-connector.test.d.ts.map +1 -0
- package/dist/server/gradio-endpoint-connector.test.js +313 -0
- package/dist/server/gradio-endpoint-connector.test.js.map +1 -0
- package/dist/server/lib/logger.d.ts +5 -0
- package/dist/server/lib/logger.d.ts.map +1 -0
- package/dist/server/lib/logger.js +45 -0
- package/dist/server/lib/logger.js.map +1 -0
- package/dist/server/lib/mcp-api-client.d.ts +42 -0
- package/dist/server/lib/mcp-api-client.d.ts.map +1 -0
- package/dist/server/lib/mcp-api-client.js +188 -0
- package/dist/server/lib/mcp-api-client.js.map +1 -0
- package/dist/server/lib/tool-selection-strategy.d.ts +29 -0
- package/dist/server/lib/tool-selection-strategy.d.ts.map +1 -0
- package/dist/server/lib/tool-selection-strategy.js +113 -0
- package/dist/server/lib/tool-selection-strategy.js.map +1 -0
- package/dist/server/lib/tool-selection-strategy.test.d.ts +2 -0
- package/dist/server/lib/tool-selection-strategy.test.d.ts.map +1 -0
- package/dist/server/lib/tool-selection-strategy.test.js +407 -0
- package/dist/server/lib/tool-selection-strategy.test.js.map +1 -0
- package/dist/server/mcp-proxy.d.ts +5 -0
- package/dist/server/mcp-proxy.d.ts.map +1 -0
- package/dist/server/mcp-proxy.js +66 -0
- package/dist/server/mcp-proxy.js.map +1 -0
- package/dist/server/mcp-server.d.ts +8 -0
- package/dist/server/mcp-server.d.ts.map +1 -0
- package/dist/server/mcp-server.js +219 -0
- package/dist/server/mcp-server.js.map +1 -0
- package/dist/server/sse.d.ts +3 -0
- package/dist/server/sse.d.ts.map +1 -0
- package/dist/server/sse.js +47 -0
- package/dist/server/sse.js.map +1 -0
- package/dist/server/stdio.d.ts +3 -0
- package/dist/server/stdio.d.ts.map +1 -0
- package/dist/server/stdio.js +49 -0
- package/dist/server/stdio.js.map +1 -0
- package/dist/server/streamableHttp.d.ts +3 -0
- package/dist/server/streamableHttp.d.ts.map +1 -0
- package/dist/server/streamableHttp.js +53 -0
- package/dist/server/streamableHttp.js.map +1 -0
- package/dist/server/transport/base-transport.d.ts +132 -0
- package/dist/server/transport/base-transport.d.ts.map +1 -0
- package/dist/server/transport/base-transport.js +390 -0
- package/dist/server/transport/base-transport.js.map +1 -0
- package/dist/server/transport/json-rpc-errors.d.ts +36 -0
- package/dist/server/transport/json-rpc-errors.d.ts.map +1 -0
- package/dist/server/transport/json-rpc-errors.js +53 -0
- package/dist/server/transport/json-rpc-errors.js.map +1 -0
- package/dist/server/transport/sse-transport.d.ts +17 -0
- package/dist/server/transport/sse-transport.d.ts.map +1 -0
- package/dist/server/transport/sse-transport.js +170 -0
- package/dist/server/transport/sse-transport.js.map +1 -0
- package/dist/server/transport/stateless-http-transport.d.ts +11 -0
- package/dist/server/transport/stateless-http-transport.d.ts.map +1 -0
- package/dist/server/transport/stateless-http-transport.js +172 -0
- package/dist/server/transport/stateless-http-transport.js.map +1 -0
- package/dist/server/transport/stateless-http-transport.test.d.ts +2 -0
- package/dist/server/transport/stateless-http-transport.test.d.ts.map +1 -0
- package/dist/server/transport/stateless-http-transport.test.js +58 -0
- package/dist/server/transport/stateless-http-transport.test.js.map +1 -0
- package/dist/server/transport/stdio-transport.d.ts +12 -0
- package/dist/server/transport/stdio-transport.d.ts.map +1 -0
- package/dist/server/transport/stdio-transport.js +78 -0
- package/dist/server/transport/stdio-transport.js.map +1 -0
- package/dist/server/transport/streamable-http-transport.d.ts +21 -0
- package/dist/server/transport/streamable-http-transport.d.ts.map +1 -0
- package/dist/server/transport/streamable-http-transport.js +220 -0
- package/dist/server/transport/streamable-http-transport.js.map +1 -0
- package/dist/server/transport/transport-factory.d.ts +5 -0
- package/dist/server/transport/transport-factory.d.ts.map +1 -0
- package/dist/server/transport/transport-factory.js +21 -0
- package/dist/server/transport/transport-factory.js.map +1 -0
- package/dist/server/utils/api-metrics.d.ts +15 -0
- package/dist/server/utils/api-metrics.d.ts.map +1 -0
- package/dist/server/utils/api-metrics.js +39 -0
- package/dist/server/utils/api-metrics.js.map +1 -0
- package/dist/server/utils/auth-utils.d.ts +6 -0
- package/dist/server/utils/auth-utils.d.ts.map +1 -0
- package/dist/server/utils/auth-utils.js +25 -0
- package/dist/server/utils/auth-utils.js.map +1 -0
- package/dist/server/utils/browser-detection.d.ts +2 -0
- package/dist/server/utils/browser-detection.d.ts.map +1 -0
- package/dist/server/utils/browser-detection.js +15 -0
- package/dist/server/utils/browser-detection.js.map +1 -0
- package/dist/server/utils/browser-detection.test.d.ts +2 -0
- package/dist/server/utils/browser-detection.test.d.ts.map +1 -0
- package/dist/server/utils/browser-detection.test.js +50 -0
- package/dist/server/utils/browser-detection.test.js.map +1 -0
- package/dist/server/utils/gradio-metrics.d.ts +22 -0
- package/dist/server/utils/gradio-metrics.d.ts.map +1 -0
- package/dist/server/utils/gradio-metrics.js +60 -0
- package/dist/server/utils/gradio-metrics.js.map +1 -0
- package/dist/server/utils/query-params.d.ts +3 -0
- package/dist/server/utils/query-params.d.ts.map +1 -0
- package/dist/server/utils/query-params.js +17 -0
- package/dist/server/utils/query-params.js.map +1 -0
- package/dist/server/utils/query-params.test.d.ts +2 -0
- package/dist/server/utils/query-params.test.d.ts.map +1 -0
- package/dist/server/utils/query-params.test.js +75 -0
- package/dist/server/utils/query-params.test.js.map +1 -0
- package/dist/server/web-server.d.ts +29 -0
- package/dist/server/web-server.d.ts.map +1 -0
- package/dist/server/web-server.js +273 -0
- package/dist/server/web-server.js.map +1 -0
- package/dist/shared/constants.d.ts +5 -0
- package/dist/shared/constants.d.ts.map +1 -0
- package/dist/shared/constants.js +4 -0
- package/dist/shared/constants.js.map +1 -0
- package/dist/shared/settings.d.ts +19 -0
- package/dist/shared/settings.d.ts.map +1 -0
- package/dist/shared/settings.js +47 -0
- package/dist/shared/settings.js.map +1 -0
- package/dist/shared/transport-info.d.ts +18 -0
- package/dist/shared/transport-info.d.ts.map +1 -0
- package/dist/shared/transport-info.js +22 -0
- package/dist/shared/transport-info.js.map +1 -0
- package/dist/shared/transport-info.test.d.ts +2 -0
- package/dist/shared/transport-info.test.d.ts.map +1 -0
- package/dist/shared/transport-info.test.js +90 -0
- package/dist/shared/transport-info.test.js.map +1 -0
- package/dist/shared/transport-metrics.d.ts +180 -0
- package/dist/shared/transport-metrics.d.ts.map +1 -0
- package/dist/shared/transport-metrics.js +247 -0
- package/dist/shared/transport-metrics.js.map +1 -0
- package/dist/shared/transport-metrics.test.d.ts +2 -0
- package/dist/shared/transport-metrics.test.d.ts.map +1 -0
- package/dist/shared/transport-metrics.test.js +10 -0
- package/dist/shared/transport-metrics.test.js.map +1 -0
- package/dist/web/assets/button-C4Q2P8Ns.css +1 -0
- package/dist/web/assets/button-DOWMQOme.js +79 -0
- package/dist/web/assets/hf-logo-DbjPOSLw.svg +21 -0
- package/dist/web/assets/main-CB77vUha.js +115 -0
- package/dist/web/assets/mcpWelcome-Cpw1-KJi.js +1 -0
- package/dist/web/hf-logo-DbjPOSLw.svg +21 -0
- package/dist/web/index.html +15 -0
- package/dist/web/mcp-welcome.html +92 -0
- package/package.json +100 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { StatefulTransport, type TransportOptions, type BaseSession } from './base-transport.js';
|
|
2
|
+
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
|
|
3
|
+
interface SSEConnection extends BaseSession<SSEServerTransport> {
|
|
4
|
+
cleanup: () => Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
export declare class SseTransport extends StatefulTransport<SSEConnection> {
|
|
7
|
+
initialize(_options: TransportOptions): Promise<void>;
|
|
8
|
+
private handleSseConnection;
|
|
9
|
+
private handleSseMessage;
|
|
10
|
+
private createCleanupFunction;
|
|
11
|
+
private connectWithCleanup;
|
|
12
|
+
protected removeStaleSession(sessionId: string): Promise<void>;
|
|
13
|
+
cleanup(): Promise<void>;
|
|
14
|
+
closeConnection(sessionId: string): Promise<boolean>;
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=sse-transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse-transport.d.ts","sourceRoot":"","sources":["../../../src/server/transport/sse-transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACjG,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAO7E,UAAU,aAAc,SAAQ,WAAW,CAAC,kBAAkB,CAAC;IAC9D,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAED,qBAAa,YAAa,SAAQ,iBAAiB,CAAC,aAAa,CAAC;IAC3D,UAAU,CAAC,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;YA0B7C,mBAAmB;YAyFnB,gBAAgB;IAwD9B,OAAO,CAAC,qBAAqB;YAIf,kBAAkB;cAsBhB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK9D,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAoBxB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAe1D"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { StatefulTransport } from './base-transport.js';
|
|
2
|
+
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
|
|
3
|
+
import { logger } from '../lib/logger.js';
|
|
4
|
+
import { JsonRpcErrors, extractJsonRpcId } from './json-rpc-errors.js';
|
|
5
|
+
import { extractQueryParamsToHeaders } from '../utils/query-params.js';
|
|
6
|
+
export class SseTransport extends StatefulTransport {
|
|
7
|
+
async initialize(_options) {
|
|
8
|
+
this.app.get('/sse', (req, res) => {
|
|
9
|
+
this.trackRequest();
|
|
10
|
+
void this.handleSseConnection(req, res);
|
|
11
|
+
});
|
|
12
|
+
this.app.post('/message', (req, res) => {
|
|
13
|
+
this.trackRequest();
|
|
14
|
+
void this.handleSseMessage(req, res);
|
|
15
|
+
});
|
|
16
|
+
this.startStaleConnectionCheck();
|
|
17
|
+
this.startPingKeepAlive();
|
|
18
|
+
logger.info('SSE transport routes initialized', {
|
|
19
|
+
heartbeatInterval: this.HEARTBEAT_INTERVAL,
|
|
20
|
+
staleCheckInterval: this.STALE_CHECK_INTERVAL,
|
|
21
|
+
staleTimeout: this.STALE_TIMEOUT,
|
|
22
|
+
pingEnabled: this.PING_ENABLED,
|
|
23
|
+
pingInterval: this.PING_INTERVAL,
|
|
24
|
+
});
|
|
25
|
+
return Promise.resolve();
|
|
26
|
+
}
|
|
27
|
+
async handleSseConnection(req, res) {
|
|
28
|
+
try {
|
|
29
|
+
if (this.isShuttingDown) {
|
|
30
|
+
logger.warn('Rejecting SSE connection during shutdown');
|
|
31
|
+
this.trackError(503);
|
|
32
|
+
res.status(503).json(JsonRpcErrors.serverShuttingDown());
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const existingSessionId = req.query.sessionId;
|
|
36
|
+
if (existingSessionId) {
|
|
37
|
+
const existing = this.sessions.get(existingSessionId);
|
|
38
|
+
if (existing) {
|
|
39
|
+
logger.warn({
|
|
40
|
+
sessionId: existingSessionId,
|
|
41
|
+
age: Date.now() - existing.metadata.connectedAt.getTime(),
|
|
42
|
+
}, 'Client attempting to reconnect with existing sessionId');
|
|
43
|
+
await this.closeConnection(existingSessionId);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const headers = req.headers;
|
|
47
|
+
extractQueryParamsToHeaders(req, headers);
|
|
48
|
+
const authResult = await this.validateAuthAndTrackMetrics(headers);
|
|
49
|
+
if (!authResult.shouldContinue) {
|
|
50
|
+
this.trackError(authResult.statusCode);
|
|
51
|
+
res.status(authResult.statusCode || 401).send('Unauthorized');
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const server = await this.serverFactory(headers);
|
|
55
|
+
const transport = new SSEServerTransport('/message', res);
|
|
56
|
+
const sessionId = transport.sessionId;
|
|
57
|
+
logger.info({ sessionId }, 'New SSE connection established');
|
|
58
|
+
const cleanup = this.createCleanupFunction(sessionId);
|
|
59
|
+
const connection = {
|
|
60
|
+
transport,
|
|
61
|
+
server,
|
|
62
|
+
cleanup,
|
|
63
|
+
metadata: {
|
|
64
|
+
id: sessionId,
|
|
65
|
+
connectedAt: new Date(),
|
|
66
|
+
lastActivity: new Date(),
|
|
67
|
+
requestCount: 0,
|
|
68
|
+
capabilities: {},
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
this.sessions.set(sessionId, connection);
|
|
72
|
+
this.trackSessionCreated(sessionId);
|
|
73
|
+
this.startHeartbeat(sessionId, res);
|
|
74
|
+
this.setupSseEventHandlers(sessionId, res);
|
|
75
|
+
await this.connectWithCleanup(transport, server, sessionId, cleanup);
|
|
76
|
+
logger.debug({ sessionId }, 'SSE transport fully initialized');
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
logger.error({ error }, 'Error establishing SSE connection');
|
|
80
|
+
this.trackError(500, error instanceof Error ? error : new Error(String(error)));
|
|
81
|
+
if (!res.headersSent) {
|
|
82
|
+
res.status(500).json(JsonRpcErrors.internalError(null, 'Internal server error establishing SSE connection'));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async handleSseMessage(req, res) {
|
|
87
|
+
const trackingName = this.extractMethodForTracking(req.body);
|
|
88
|
+
try {
|
|
89
|
+
const sessionId = req.query.sessionId;
|
|
90
|
+
if (!sessionId) {
|
|
91
|
+
logger.warn('SSE message received without sessionId');
|
|
92
|
+
this.trackError(400);
|
|
93
|
+
this.metrics.trackMethod(trackingName, undefined, true);
|
|
94
|
+
res.status(400).json(JsonRpcErrors.invalidParams('sessionId is required', extractJsonRpcId(req.body)));
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
const connection = this.sessions.get(sessionId);
|
|
98
|
+
if (!connection) {
|
|
99
|
+
logger.warn({ sessionId }, 'SSE message for unknown session');
|
|
100
|
+
this.trackError(404);
|
|
101
|
+
this.metrics.trackMethod(trackingName, undefined, true);
|
|
102
|
+
res.status(404).json(JsonRpcErrors.sessionNotFound(sessionId, extractJsonRpcId(req.body)));
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
this.updateSessionActivity(sessionId);
|
|
106
|
+
if (trackingName) {
|
|
107
|
+
const session = this.sessions.get(sessionId);
|
|
108
|
+
if (session) {
|
|
109
|
+
session.metadata.requestCount++;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
await connection.transport.handlePostMessage(req, res, req.body);
|
|
113
|
+
this.metrics.trackMethod(trackingName, undefined, false);
|
|
114
|
+
logger.debug({ sessionId }, 'SSE message handled successfully');
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
logger.error({ error }, 'Error handling SSE message');
|
|
118
|
+
this.trackError(500, error instanceof Error ? error : new Error(String(error)));
|
|
119
|
+
this.metrics.trackMethod(trackingName, undefined, true);
|
|
120
|
+
if (!res.headersSent) {
|
|
121
|
+
res
|
|
122
|
+
.status(500)
|
|
123
|
+
.json(JsonRpcErrors.internalError(extractJsonRpcId(req.body), 'Internal server error handling SSE message'));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
createCleanupFunction(sessionId) {
|
|
128
|
+
return () => this.cleanupSession(sessionId);
|
|
129
|
+
}
|
|
130
|
+
async connectWithCleanup(transport, server, sessionId, cleanup) {
|
|
131
|
+
try {
|
|
132
|
+
this.setupServerForSession(server, sessionId);
|
|
133
|
+
await server.connect(transport);
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
logger.error({ error, sessionId }, 'Failed to connect transport to server');
|
|
137
|
+
this.trackError(500, error instanceof Error ? error : new Error(String(error)));
|
|
138
|
+
await cleanup();
|
|
139
|
+
throw error;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
async removeStaleSession(sessionId) {
|
|
143
|
+
logger.info({ sessionId }, 'Removing stale SSE connection');
|
|
144
|
+
await this.cleanupSession(sessionId);
|
|
145
|
+
}
|
|
146
|
+
async cleanup() {
|
|
147
|
+
logger.info({
|
|
148
|
+
activeConnections: this.sessions.size,
|
|
149
|
+
}, 'Starting SSE transport cleanup');
|
|
150
|
+
this.stopStaleConnectionCheck();
|
|
151
|
+
await this.cleanupAllSessions();
|
|
152
|
+
logger.info('SSE transport cleanup completed');
|
|
153
|
+
}
|
|
154
|
+
async closeConnection(sessionId) {
|
|
155
|
+
const session = this.sessions.get(sessionId);
|
|
156
|
+
if (!session) {
|
|
157
|
+
logger.debug({ sessionId }, 'Attempted to close non-existent connection');
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
try {
|
|
161
|
+
await this.cleanupSession(sessionId);
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
logger.error({ error, sessionId }, 'Error closing connection');
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=sse-transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse-transport.js","sourceRoot":"","sources":["../../../src/server/transport/sse-transport.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { BaseTransport, type TransportOptions, type SessionMetadata } from './base-transport.js';
|
|
2
|
+
export declare class StatelessHttpTransport extends BaseTransport {
|
|
3
|
+
private shouldHandle;
|
|
4
|
+
initialize(_options: TransportOptions): Promise<void>;
|
|
5
|
+
private handleJsonRpcRequest;
|
|
6
|
+
shutdown(): void;
|
|
7
|
+
cleanup(): Promise<void>;
|
|
8
|
+
getActiveConnectionCount(): number;
|
|
9
|
+
getSessions(): SessionMetadata[];
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=stateless-http-transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stateless-http-transport.d.ts","sourceRoot":"","sources":["../../../src/server/transport/stateless-http-transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,gBAAgB,EAAkB,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAmBjH,qBAAa,sBAAuB,SAAQ,aAAa;IAKxD,OAAO,CAAC,YAAY;IAuBpB,UAAU,CAAC,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;YAqDvC,oBAAoB;IAiJzB,QAAQ,IAAI,IAAI;IAKzB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IASxB,wBAAwB,IAAI,MAAM;IAQzB,WAAW,IAAI,eAAe,EAAE;CAIzC"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { BaseTransport, STATELESS_MODE } from './base-transport.js';
|
|
2
|
+
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
3
|
+
import { logger } from '../lib/logger.js';
|
|
4
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
5
|
+
import { JsonRpcErrors, extractJsonRpcId } from './json-rpc-errors.js';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
import { isJSONRPCNotification } from '@modelcontextprotocol/sdk/types.js';
|
|
9
|
+
import { extractQueryParamsToHeaders } from '../utils/query-params.js';
|
|
10
|
+
import { isBrowser } from '../utils/browser-detection.js';
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
+
const __dirname = path.dirname(__filename);
|
|
13
|
+
export class StatelessHttpTransport extends BaseTransport {
|
|
14
|
+
shouldHandle(requestBody) {
|
|
15
|
+
const body = requestBody;
|
|
16
|
+
const method = body?.method;
|
|
17
|
+
if (method === 'tools/list' || method === 'tools/call') {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
if (method === 'prompts/list' || method === 'prompts/get') {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
if (method === 'initialize') {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
initialize(_options) {
|
|
29
|
+
this.app.post('/mcp', (req, res) => {
|
|
30
|
+
this.trackRequest();
|
|
31
|
+
void this.handleJsonRpcRequest(req, res);
|
|
32
|
+
});
|
|
33
|
+
this.app.get('/mcp', (req, res) => {
|
|
34
|
+
if (process.env.MCP_STRICT_COMPLIANCE === 'true' || !isBrowser(req.headers)) {
|
|
35
|
+
this.metrics.trackStaticPageHit(405);
|
|
36
|
+
logger.debug('Rejected GET request to /mcp in strict compliance mode or from non-browser client');
|
|
37
|
+
res
|
|
38
|
+
.status(405)
|
|
39
|
+
.json(JsonRpcErrors.methodNotAllowed(null, 'Method not allowed. Use POST for stateless JSON-RPC requests.'));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const isSecure = req.secure || req.headers['x-forwarded-proto'] === 'https';
|
|
43
|
+
const host = req.get('host') || '';
|
|
44
|
+
const isLocalhost = host === 'localhost' || host.startsWith('localhost:') || host === '127.0.0.1' || host.startsWith('127.0.0.1:');
|
|
45
|
+
if (!isSecure && !isLocalhost) {
|
|
46
|
+
const httpsUrl = `https://${host}${req.originalUrl}`;
|
|
47
|
+
logger.debug(`Redirecting insecure request to HTTPS: ${httpsUrl}`);
|
|
48
|
+
res.redirect(301, httpsUrl);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
this.metrics.trackStaticPageHit(200);
|
|
52
|
+
const mcpWelcomePath = path.join(__dirname, '..', '..', 'web', 'mcp-welcome.html');
|
|
53
|
+
res.sendFile(mcpWelcomePath);
|
|
54
|
+
});
|
|
55
|
+
this.app.delete('/mcp', (_req, res) => {
|
|
56
|
+
this.trackRequest();
|
|
57
|
+
this.trackError(405);
|
|
58
|
+
logger.warn('Rejected DELETE request to /mcp in stateless mode');
|
|
59
|
+
res
|
|
60
|
+
.status(405)
|
|
61
|
+
.json(JsonRpcErrors.methodNotAllowed(null, 'Method not allowed. Use POST for stateless JSON-RPC requests.'));
|
|
62
|
+
});
|
|
63
|
+
logger.info('HTTP JSON transport initialized (stateless mode)');
|
|
64
|
+
return Promise.resolve();
|
|
65
|
+
}
|
|
66
|
+
async handleJsonRpcRequest(req, res) {
|
|
67
|
+
const startTime = Date.now();
|
|
68
|
+
let server = null;
|
|
69
|
+
let transport = null;
|
|
70
|
+
const headers = req.headers;
|
|
71
|
+
extractQueryParamsToHeaders(req, headers);
|
|
72
|
+
const requestBody = req.body;
|
|
73
|
+
const trackingName = this.extractMethodForTracking(requestBody);
|
|
74
|
+
const authResult = await this.validateAuthAndTrackMetrics(headers);
|
|
75
|
+
if (!authResult.shouldContinue || trackingName === 'tools/call:Authenticate') {
|
|
76
|
+
res.set('WWW-Authenticate', 'Bearer resource_metadata="https://huggingface.co/.well-known/oauth-protected-resources/mcp"');
|
|
77
|
+
res.status(authResult.statusCode || 401).send('Unauthorized');
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
this.trackNewConnection();
|
|
81
|
+
if (isJSONRPCNotification(req.body)) {
|
|
82
|
+
this.trackMethodCall(trackingName, startTime, false);
|
|
83
|
+
res.status(202).json({ jsonrpc: '2.0', result: null });
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
if (requestBody?.method === 'initialize' && requestBody?.params) {
|
|
88
|
+
const clientInfo = requestBody.params.clientInfo;
|
|
89
|
+
if (clientInfo?.name && clientInfo?.version) {
|
|
90
|
+
this.associateSessionWithClient({ name: clientInfo.name, version: clientInfo.version });
|
|
91
|
+
this.updateClientActivity({ name: clientInfo.name, version: clientInfo.version });
|
|
92
|
+
}
|
|
93
|
+
logger.debug({
|
|
94
|
+
clientInfo: requestBody.params.clientInfo,
|
|
95
|
+
capabilities: requestBody.params.capabilities,
|
|
96
|
+
}, 'Initialize request received');
|
|
97
|
+
}
|
|
98
|
+
const useFullServer = this.shouldHandle(requestBody);
|
|
99
|
+
if (useFullServer) {
|
|
100
|
+
extractQueryParamsToHeaders(req, headers);
|
|
101
|
+
const skipGradio = this.shouldSkipGradio(requestBody);
|
|
102
|
+
server = await this.serverFactory(headers, undefined, skipGradio);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
server = new McpServer({ name: '@huggingface/internal-responder', version: '0.0.1' });
|
|
106
|
+
}
|
|
107
|
+
transport = new StreamableHTTPServerTransport({
|
|
108
|
+
sessionIdGenerator: undefined,
|
|
109
|
+
enableJsonResponse: true,
|
|
110
|
+
});
|
|
111
|
+
const cleanup = async () => {
|
|
112
|
+
if (transport) {
|
|
113
|
+
await transport.close().catch((err) => {
|
|
114
|
+
logger.warn({ error: err }, 'Error closing transport');
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
if (server) {
|
|
118
|
+
await server.close().catch((err) => {
|
|
119
|
+
logger.warn({ error: err }, 'Error closing server');
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
res.on('close', () => {
|
|
124
|
+
logger.debug('Client disconnected');
|
|
125
|
+
void cleanup();
|
|
126
|
+
});
|
|
127
|
+
server.server.onerror = (error) => {
|
|
128
|
+
this.trackError(undefined, error);
|
|
129
|
+
logger.error({ error }, 'Stateless HTTP server error');
|
|
130
|
+
};
|
|
131
|
+
await server.connect(transport);
|
|
132
|
+
await transport.handleRequest(req, res, req.body);
|
|
133
|
+
this.trackMethodCall(trackingName, startTime, false);
|
|
134
|
+
logger.debug({
|
|
135
|
+
duration: Date.now() - startTime,
|
|
136
|
+
method: trackingName,
|
|
137
|
+
handledBy: useFullServer ? 'full' : 'stub',
|
|
138
|
+
}, 'Request completed');
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
logger.error({ error, method: trackingName }, 'Error handling request');
|
|
142
|
+
this.trackMethodCall(trackingName, startTime, true);
|
|
143
|
+
this.trackError(500, error instanceof Error ? error : new Error(String(error)));
|
|
144
|
+
if (transport) {
|
|
145
|
+
await transport.close().catch(() => {
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
if (server) {
|
|
149
|
+
await server.close().catch(() => {
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
if (!res.headersSent) {
|
|
153
|
+
const id = extractJsonRpcId(req.body);
|
|
154
|
+
res.status(500).json(JsonRpcErrors.internalError(id));
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
shutdown() {
|
|
159
|
+
logger.debug('Stateless HTTP transport shutdown signaled');
|
|
160
|
+
}
|
|
161
|
+
cleanup() {
|
|
162
|
+
logger.info('HTTP JSON transport cleanup complete');
|
|
163
|
+
return Promise.resolve();
|
|
164
|
+
}
|
|
165
|
+
getActiveConnectionCount() {
|
|
166
|
+
return STATELESS_MODE;
|
|
167
|
+
}
|
|
168
|
+
getSessions() {
|
|
169
|
+
return [];
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=stateless-http-transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stateless-http-transport.js","sourceRoot":"","sources":["../../../src/server/transport/stateless-http-transport.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stateless-http-transport.test.d.ts","sourceRoot":"","sources":["../../../src/server/transport/stateless-http-transport.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
2
|
+
import { StatelessHttpTransport } from './stateless-http-transport.js';
|
|
3
|
+
import express from 'express';
|
|
4
|
+
describe('StatelessHttpTransport', () => {
|
|
5
|
+
let transport;
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
const mockServerFactory = vi.fn();
|
|
8
|
+
const mockApp = express();
|
|
9
|
+
transport = new StatelessHttpTransport(mockServerFactory, mockApp);
|
|
10
|
+
});
|
|
11
|
+
describe('shouldHandle', () => {
|
|
12
|
+
it('should handle tools/list requests', () => {
|
|
13
|
+
const result = transport.shouldHandle({ method: 'tools/list' });
|
|
14
|
+
expect(result).toBe(true);
|
|
15
|
+
});
|
|
16
|
+
it('should handle tools/call requests', () => {
|
|
17
|
+
const result = transport.shouldHandle({ method: 'tools/call' });
|
|
18
|
+
expect(result).toBe(true);
|
|
19
|
+
});
|
|
20
|
+
it('should handle initialize requests', () => {
|
|
21
|
+
const result = transport.shouldHandle({ method: 'initialize' });
|
|
22
|
+
expect(result).toBe(true);
|
|
23
|
+
});
|
|
24
|
+
it('should not handle ping requests', () => {
|
|
25
|
+
const result = transport.shouldHandle({ method: 'ping' });
|
|
26
|
+
expect(result).toBe(false);
|
|
27
|
+
});
|
|
28
|
+
it('should handle prompts/list requests', () => {
|
|
29
|
+
const result = transport.shouldHandle({ method: 'prompts/list' });
|
|
30
|
+
expect(result).toBe(true);
|
|
31
|
+
});
|
|
32
|
+
it('should handle prompts/get requests', () => {
|
|
33
|
+
const result = transport.shouldHandle({ method: 'prompts/get' });
|
|
34
|
+
expect(result).toBe(true);
|
|
35
|
+
});
|
|
36
|
+
it('should not handle resources/list requests', () => {
|
|
37
|
+
const result = transport.shouldHandle({ method: 'resources/list' });
|
|
38
|
+
expect(result).toBe(false);
|
|
39
|
+
});
|
|
40
|
+
it('should not handle resources/read requests', () => {
|
|
41
|
+
const result = transport.shouldHandle({ method: 'resources/read' });
|
|
42
|
+
expect(result).toBe(false);
|
|
43
|
+
});
|
|
44
|
+
it('should handle undefined method gracefully', () => {
|
|
45
|
+
const result = transport.shouldHandle({});
|
|
46
|
+
expect(result).toBe(false);
|
|
47
|
+
});
|
|
48
|
+
it('should handle undefined body gracefully', () => {
|
|
49
|
+
const result = transport.shouldHandle(undefined);
|
|
50
|
+
expect(result).toBe(false);
|
|
51
|
+
});
|
|
52
|
+
it('should handle null body gracefully', () => {
|
|
53
|
+
const result = transport.shouldHandle(null);
|
|
54
|
+
expect(result).toBe(false);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
//# sourceMappingURL=stateless-http-transport.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stateless-http-transport.test.js","sourceRoot":"","sources":["../../../src/server/transport/stateless-http-transport.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { StatefulTransport, type TransportOptions, type BaseSession } from './base-transport.js';
|
|
2
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
+
type StdioSession = BaseSession<StdioServerTransport>;
|
|
4
|
+
export declare class StdioTransport extends StatefulTransport<StdioSession> {
|
|
5
|
+
private readonly SESSION_ID;
|
|
6
|
+
initialize(_options: TransportOptions): Promise<void>;
|
|
7
|
+
protected removeStaleSession(sessionId: string): Promise<void>;
|
|
8
|
+
cleanup(): Promise<void>;
|
|
9
|
+
getSession(): StdioSession | undefined;
|
|
10
|
+
}
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=stdio-transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdio-transport.d.ts","sourceRoot":"","sources":["../../../src/server/transport/stdio-transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACjG,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAGjF,KAAK,YAAY,GAAG,WAAW,CAAC,oBAAoB,CAAC,CAAC;AAKtD,qBAAa,cAAe,SAAQ,iBAAiB,CAAC,YAAY,CAAC;IAClE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAW;IAEhC,UAAU,CAAC,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAiE3D,SAAS,CAAC,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMxD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAwB9B,UAAU,IAAI,YAAY,GAAG,SAAS;CAGtC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { StatefulTransport } from './base-transport.js';
|
|
2
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
+
import { logger } from '../lib/logger.js';
|
|
4
|
+
export class StdioTransport extends StatefulTransport {
|
|
5
|
+
SESSION_ID = 'STDIO';
|
|
6
|
+
async initialize(_options) {
|
|
7
|
+
const transport = new StdioServerTransport();
|
|
8
|
+
const server = await this.serverFactory(null);
|
|
9
|
+
const session = {
|
|
10
|
+
transport,
|
|
11
|
+
server,
|
|
12
|
+
metadata: {
|
|
13
|
+
id: this.SESSION_ID,
|
|
14
|
+
connectedAt: new Date(),
|
|
15
|
+
lastActivity: new Date(),
|
|
16
|
+
requestCount: 0,
|
|
17
|
+
capabilities: {},
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
this.sessions.set(this.SESSION_ID, session);
|
|
21
|
+
this.trackSessionCreated(this.SESSION_ID);
|
|
22
|
+
try {
|
|
23
|
+
const originalSendMessage = transport.send.bind(transport);
|
|
24
|
+
transport.send = (message) => {
|
|
25
|
+
this.trackRequest();
|
|
26
|
+
this.updateSessionActivity(this.SESSION_ID);
|
|
27
|
+
const session = this.sessions.get(this.SESSION_ID);
|
|
28
|
+
if (session) {
|
|
29
|
+
session.metadata.requestCount++;
|
|
30
|
+
}
|
|
31
|
+
return originalSendMessage(message);
|
|
32
|
+
};
|
|
33
|
+
server.server.oninitialized = this.createClientInfoCapture(this.SESSION_ID);
|
|
34
|
+
server.server.onerror = (error) => {
|
|
35
|
+
this.trackError(undefined, error);
|
|
36
|
+
logger.error({ error }, 'STDIO server error');
|
|
37
|
+
};
|
|
38
|
+
await server.connect(transport);
|
|
39
|
+
logger.info('STDIO transport initialized');
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
logger.error({ error }, 'Error connecting STDIO transport');
|
|
43
|
+
const session = this.sessions.get(this.SESSION_ID);
|
|
44
|
+
this.sessions.delete(this.SESSION_ID);
|
|
45
|
+
this.trackSessionCleaned(session);
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
removeStaleSession(sessionId) {
|
|
50
|
+
logger.debug({ sessionId }, 'STDIO session staleness check (no-op)');
|
|
51
|
+
return Promise.resolve();
|
|
52
|
+
}
|
|
53
|
+
async cleanup() {
|
|
54
|
+
const session = this.sessions.get(this.SESSION_ID);
|
|
55
|
+
if (session) {
|
|
56
|
+
try {
|
|
57
|
+
await session.transport.close();
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
logger.error({ error }, 'Error closing STDIO transport');
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
await session.server.close();
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
logger.error({ error }, 'Error closing STDIO server');
|
|
67
|
+
}
|
|
68
|
+
this.trackSessionCleaned(session);
|
|
69
|
+
}
|
|
70
|
+
this.sessions.clear();
|
|
71
|
+
logger.info('STDIO transport cleaned up');
|
|
72
|
+
return Promise.resolve();
|
|
73
|
+
}
|
|
74
|
+
getSession() {
|
|
75
|
+
return this.sessions.get(this.SESSION_ID);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=stdio-transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdio-transport.js","sourceRoot":"","sources":["../../../src/server/transport/stdio-transport.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { StatefulTransport, type TransportOptions, type BaseSession } from './base-transport.js';
|
|
2
|
+
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
3
|
+
import type { Response } from 'express';
|
|
4
|
+
interface StreamableHttpConnection extends BaseSession<StreamableHTTPServerTransport> {
|
|
5
|
+
activeResponse?: Response;
|
|
6
|
+
}
|
|
7
|
+
type Session = StreamableHttpConnection;
|
|
8
|
+
export declare class StreamableHttpTransport extends StatefulTransport<Session> {
|
|
9
|
+
initialize(_options: TransportOptions): Promise<void>;
|
|
10
|
+
private setupRoutes;
|
|
11
|
+
private handleRequest;
|
|
12
|
+
private handlePostRequest;
|
|
13
|
+
private handleGetRequest;
|
|
14
|
+
private handleDeleteRequest;
|
|
15
|
+
private createSession;
|
|
16
|
+
private removeSession;
|
|
17
|
+
protected removeStaleSession(sessionId: string): Promise<void>;
|
|
18
|
+
cleanup(): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=streamable-http-transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streamable-http-transport.d.ts","sourceRoot":"","sources":["../../../src/server/transport/streamable-http-transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACjG,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AAEnG,OAAO,KAAK,EAAW,QAAQ,EAAE,MAAM,SAAS,CAAC;AAMjD,UAAU,wBAAyB,SAAQ,WAAW,CAAC,6BAA6B,CAAC;IACpF,cAAc,CAAC,EAAE,QAAQ,CAAC;CAC1B;AAED,KAAK,OAAO,GAAG,wBAAwB,CAAC;AAExC,qBAAa,uBAAwB,SAAQ,iBAAiB,CAAC,OAAO,CAAC;IACtE,UAAU,CAAC,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAerD,OAAO,CAAC,WAAW;YA0BL,aAAa;YA6Bb,iBAAiB;YAmFjB,gBAAgB;YA+BhB,mBAAmB;YAoBnB,aAAa;YA0Db,aAAa;cAOX,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK9D,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAS9B"}
|