mcp
This commit is contained in:
@@ -22,15 +22,8 @@ export class McpServerService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async startHttp(port = 3001): Promise<void> {
|
async startHttp(port = 3001): Promise<void> {
|
||||||
const mcpServer = this.createServer();
|
|
||||||
const transport = new StreamableHTTPServerTransport({
|
|
||||||
sessionIdGenerator: undefined,
|
|
||||||
});
|
|
||||||
|
|
||||||
await mcpServer.connect(transport);
|
|
||||||
|
|
||||||
const httpServer = createServer((request, response) => {
|
const httpServer = createServer((request, response) => {
|
||||||
void this.handleHttpRequest(request, response, transport);
|
void this.handleHttpRequest(request, response);
|
||||||
});
|
});
|
||||||
|
|
||||||
await new Promise<void>((resolve) => {
|
await new Promise<void>((resolve) => {
|
||||||
@@ -55,7 +48,6 @@ export class McpServerService {
|
|||||||
private async handleHttpRequest(
|
private async handleHttpRequest(
|
||||||
request: IncomingMessage,
|
request: IncomingMessage,
|
||||||
response: ServerResponse,
|
response: ServerResponse,
|
||||||
transport: StreamableHTTPServerTransport,
|
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
this.setCorsHeaders(response);
|
this.setCorsHeaders(response);
|
||||||
|
|
||||||
@@ -80,20 +72,72 @@ export class McpServerService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.isBrowserHealthRequest(request)) {
|
||||||
|
response.writeHead(200, { 'content-type': 'application/json' });
|
||||||
|
response.end(
|
||||||
|
JSON.stringify({
|
||||||
|
name: 'strava-mcp',
|
||||||
|
status: 'ok',
|
||||||
|
transport: 'streamable-http',
|
||||||
|
endpoint: '/mcp',
|
||||||
|
note: 'Use an MCP client or POST a JSON-RPC initialize request with Accept: application/json, text/event-stream.',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mcpServer = this.createServer();
|
||||||
|
const transport = new StreamableHTTPServerTransport({
|
||||||
|
sessionIdGenerator: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
await mcpServer.connect(transport);
|
||||||
await transport.handleRequest(request, response);
|
await transport.handleRequest(request, response);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
process.stderr.write(
|
||||||
|
`MCP HTTP request failed: ${
|
||||||
|
error instanceof Error ? (error.stack ?? error.message) : String(error)
|
||||||
|
}\n`,
|
||||||
|
);
|
||||||
if (!response.headersSent) {
|
if (!response.headersSent) {
|
||||||
response.writeHead(500, { 'content-type': 'application/json' });
|
response.writeHead(this.errorStatus(error), {
|
||||||
|
'content-type': 'application/json',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
response.end(
|
response.end(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
error: error instanceof Error ? error.message : 'MCP request failed',
|
error: error instanceof Error ? error.message : 'MCP request failed',
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
} finally {
|
||||||
|
await mcpServer.close().catch(() => undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private isBrowserHealthRequest(request: IncomingMessage): boolean {
|
||||||
|
if (request.method !== 'GET') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const accept = request.headers.accept ?? '';
|
||||||
|
return !accept.includes('text/event-stream');
|
||||||
|
}
|
||||||
|
|
||||||
|
private errorStatus(error: unknown): number {
|
||||||
|
const message = error instanceof Error ? error.message : '';
|
||||||
|
if (message.includes('Not Acceptable')) {
|
||||||
|
return 406;
|
||||||
|
}
|
||||||
|
if (message.includes('Method not allowed')) {
|
||||||
|
return 405;
|
||||||
|
}
|
||||||
|
if (message.includes('Bad Request')) {
|
||||||
|
return 400;
|
||||||
|
}
|
||||||
|
return 500;
|
||||||
|
}
|
||||||
|
|
||||||
private isAuthorized(request: IncomingMessage): boolean {
|
private isAuthorized(request: IncomingMessage): boolean {
|
||||||
const token = process.env.MCP_AUTH_TOKEN;
|
const token = process.env.MCP_AUTH_TOKEN;
|
||||||
if (!token) {
|
if (!token) {
|
||||||
|
|||||||
Reference in New Issue
Block a user