Fix MCP handler for JSON-RPC notifications
The handler now properly handles notifications (no 'id' field) by
returning 202 No Content instead of rejecting with method-not-found.
Fixes "sending notifications/initialized: Bad Request" error.
- Added notifications/initialized and notifications/cancelled handlers
- Unknown notifications silently ignored per JSON-RPC spec
- API route returns 202 for notifications
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-free
This commit is contained in:
parent
5a56e9f519
commit
8683267919
2 changed files with 31 additions and 14 deletions
|
|
@ -209,7 +209,12 @@ export async function startServer(port = 9876) {
|
||||||
// MCP JSON-RPC endpoint
|
// MCP JSON-RPC endpoint
|
||||||
if (path === "/mcp" && req.method === "POST") {
|
if (path === "/mcp" && req.method === "POST") {
|
||||||
const body = await parseBody(req);
|
const body = await parseBody(req);
|
||||||
const mcpResp = await handleMCP(body);
|
const { response: mcpResp, isNotification } = await handleMCP(body);
|
||||||
|
if (isNotification || !mcpResp) {
|
||||||
|
res.writeHead(202, { "Content-Type": "application/json" });
|
||||||
|
res.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
const status = mcpResp.error ? 400 : 200;
|
const status = mcpResp.error ? 400 : 200;
|
||||||
res.writeHead(status, { "Content-Type": "application/json" });
|
res.writeHead(status, { "Content-Type": "application/json" });
|
||||||
res.end(JSON.stringify(mcpResp));
|
res.end(JSON.stringify(mcpResp));
|
||||||
|
|
|
||||||
24
src/mcp.js
24
src/mcp.js
|
|
@ -32,24 +32,25 @@ const TOOLS = [
|
||||||
export function createMCPHandler(runner) {
|
export function createMCPHandler(runner) {
|
||||||
return async function handleMCP(body) {
|
return async function handleMCP(body) {
|
||||||
if (!body || body.jsonrpc !== "2.0") {
|
if (!body || body.jsonrpc !== "2.0") {
|
||||||
return mcpError(null, -32600, "Invalid Request: must be JSON-RPC 2.0");
|
return { response: mcpError(null, -32600, "Invalid Request: must be JSON-RPC 2.0"), isNotification: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
const { id, method, params } = body;
|
const { id, method, params } = body;
|
||||||
|
const isNotification = id === undefined || id === null;
|
||||||
|
|
||||||
switch (method) {
|
switch (method) {
|
||||||
case "tools/list":
|
case "tools/list":
|
||||||
return {
|
return {
|
||||||
jsonrpc: "2.0",
|
response: { jsonrpc: "2.0", id, result: { tools: TOOLS } },
|
||||||
id,
|
isNotification: false
|
||||||
result: { tools: TOOLS }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
case "tools/call":
|
case "tools/call":
|
||||||
return handleToolCall(id, params, runner);
|
return { response: await handleToolCall(id, params, runner), isNotification: false };
|
||||||
|
|
||||||
case "initialize":
|
case "initialize":
|
||||||
return {
|
return {
|
||||||
|
response: {
|
||||||
jsonrpc: "2.0",
|
jsonrpc: "2.0",
|
||||||
id,
|
id,
|
||||||
result: {
|
result: {
|
||||||
|
|
@ -57,10 +58,21 @@ export function createMCPHandler(runner) {
|
||||||
capabilities: { tools: {} },
|
capabilities: { tools: {} },
|
||||||
serverInfo: { name: "polysearch", version: "2.0.0" }
|
serverInfo: { name: "polysearch", version: "2.0.0" }
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
isNotification: false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
case "notifications/initialized":
|
||||||
|
case "notifications/cancelled":
|
||||||
|
log.debug({ method }, "notification received, no response");
|
||||||
|
return { response: null, isNotification: true };
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return mcpError(id, -32601, `Method not found: ${method}`);
|
if (isNotification) {
|
||||||
|
log.debug({ method }, "unknown notification, silently ignored");
|
||||||
|
return { response: null, isNotification: true };
|
||||||
|
}
|
||||||
|
return { response: mcpError(id, -32601, `Method not found: ${method}`), isNotification: false };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue