From cc7ded8c5d5efb44562bde8f3206e980143aa154 Mon Sep 17 00:00:00 2001 From: 4studiolabs <4studiolabs.dev@gmail.com> Date: Sun, 6 Sep 2026 14:15:32 -0300 Subject: [PATCH] Fix -32600 for non-object JSON-RPC bodies --- src/index.ts | 3 +++ test/index.test.mjs | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/index.ts b/src/index.ts index 7b4cca9..48f21b4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -57,6 +57,9 @@ export default { } catch { return json(rpcError(null, -32700, "parse error")); } + if (typeof body !== "object" || body === null || Array.isArray(body)) { + return json(rpcError(null, -32600, "Invalid Request")); + } const result = await handle(body, env, caller); // Notifications (no id) get a 202 with no body per JSON-RPC. diff --git a/test/index.test.mjs b/test/index.test.mjs index ef49ed2..eea909f 100644 --- a/test/index.test.mjs +++ b/test/index.test.mjs @@ -104,6 +104,26 @@ test("tools/call rejects non-object arguments", async (t) => { assert.equal(upstreamCalls, 0); }); +test("non-object JSON-RPC bodies get -32600 Invalid Request", async (t) => { + const env = { + BRIDGEKIT_CLIENTS: JSON.stringify({ + "client-key": { name: "test client", tools: [], allowWrite: false }, + }), + }; + + for (const badBody of [null, [], "foo", 42, true]) { + await t.test(`body ${JSON.stringify(badBody)}`, async () => { + const response = await mcpRequest(env, badBody); + + assert.deepEqual(await response.json(), { + jsonrpc: "2.0", + id: null, + error: { code: -32600, message: "Invalid Request" }, + }); + }); + } +}); + test("/ai rejects requests without a client key before calling the model", async () => { let upstreamCalls = 0; globalThis.fetch = async () => {