From e987a486892b4792ac9795aece657d4fb789cd61 Mon Sep 17 00:00:00 2001 From: Aletheia Date: Tue, 7 Jul 2026 20:06:27 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20MCP=20protocol=20compliance=20=E2=80=94?= =?UTF-8?q?=20ACK=20notifications=20with=20202,=20negotiate=20protocolVers?= =?UTF-8?q?ion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ported from the Android edition's server: - JSON-RPC notifications (requests without an id, e.g. notifications/initialized) now get the bare HTTP 202 the MCP spec requires instead of a malformed JSON-RPC error response, which strict clients rejected. - initialize echoes the client's requested protocolVersion when it is a version we support (2024-11-05 / 2025-03-26 / 2025-06-18) instead of always claiming 2025-03-26. Co-Authored-By: Claude Fable 5 --- server/app.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/server/app.py b/server/app.py index f42cf91..4e935a9 100644 --- a/server/app.py +++ b/server/app.py @@ -17,7 +17,7 @@ import sys import uuid from contextlib import asynccontextmanager -from fastapi import FastAPI, Request, WebSocket, WebSocketDisconnect +from fastapi import FastAPI, Request, Response, WebSocket, WebSocketDisconnect from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse @@ -224,6 +224,9 @@ async def mcp_endpoint(request: Request): method = body.get("method", "") params = body.get("params", {}) req_id = body.get("id") + # Notifications (no id) — spec requires a bare 202 ACK, not a JSON-RPC error. + if req_id is None: + return Response(status_code=202) # Resolve user user = await _resolve_mcp_user(request) @@ -252,9 +255,11 @@ async def mcp_endpoint(request: Request): session_id = str(uuid.uuid4()) _mcp_sessions[session_id] = user["user_id"] log.info(f"MCP session created: {session_id[:8]}... for user {user['user_id']}") + client_ver = (params or {}).get("protocolVersion", "2025-03-26") + supported = {"2024-11-05", "2025-03-26", "2025-06-18"} result = { - "protocolVersion": "2025-03-26", + "protocolVersion": client_ver if client_ver in supported else "2025-03-26", "capabilities": {"tools": {}}, "serverInfo": {"name": "Signal Bridge Remote", "version": "1.0.0"}, } @@ -263,6 +268,7 @@ async def mcp_endpoint(request: Request): return response elif method == "tools/list": + log.info(f"tools/list hit — user={user['user_id']} ua={request.headers.get('user-agent','?')}") return _jsonrpc_result(req_id, {"tools": TOOLS}) elif method == "tools/call":