From 8445e3b4af80b0fb9780f16787d1ffabbb1f88d3 Mon Sep 17 00:00:00 2001
From: Nikola Irinchev <irinchev@me.com>
Date: Thu, 24 Apr 2025 17:35:45 +0200
Subject: [PATCH 1/3] fix: workaround windsurf sometimes skipping the arguments

---
 src/server.ts                                   | 10 ++++++++++
 .../tools/mongodb/metadata/connect.test.ts      | 17 +++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/src/server.ts b/src/server.ts
index fd16c75d..7adab9ae 100644
--- a/src/server.ts
+++ b/src/server.ts
@@ -8,6 +8,7 @@ import { mongoLogId } from "mongodb-log-writer";
 import { ObjectId } from "mongodb";
 import { Telemetry } from "./telemetry/telemetry.js";
 import { UserConfig } from "./config.js";
+import { CallToolRequestSchema, CallToolResult } from "@modelcontextprotocol/sdk/types.js";
 
 export interface ServerOptions {
     session: Session;
@@ -33,6 +34,15 @@ export class Server {
         this.registerTools();
         this.registerResources();
 
+        const existingHandler = this.mcpServer.server["_requestHandlers"].get(CallToolRequestSchema.shape.method.value);
+        this.mcpServer.server.setRequestHandler(CallToolRequestSchema, (request, extra): Promise<CallToolResult> => {
+            if (!request.params.arguments) {
+                request.params.arguments = {};
+            }
+
+            return existingHandler(request, extra);
+        });
+
         await initializeLogger(this.mcpServer, this.userConfig.logPath);
 
         await this.mcpServer.connect(transport);
diff --git a/tests/integration/tools/mongodb/metadata/connect.test.ts b/tests/integration/tools/mongodb/metadata/connect.test.ts
index 017c6779..3b5eb6c5 100644
--- a/tests/integration/tools/mongodb/metadata/connect.test.ts
+++ b/tests/integration/tools/mongodb/metadata/connect.test.ts
@@ -15,6 +15,23 @@ describeWithMongoDB("Connect tool", (integration) => {
         },
     ]);
 
+    describe("without arguments", () => {
+        it("prompts for connection string if not set", async () => {
+            const response = await integration.mcpClient().callTool({ name: "connect" });
+            const content = getResponseContent(response.content);
+            expect(content).toContain("No connection details provided");
+        });
+
+        it("connects to the database if connection string is set", async () => {
+            config.connectionString = integration.connectionString();
+
+            const response = await integration.mcpClient().callTool({ name: "connect" });
+            const content = getResponseContent(response.content);
+            expect(content).toContain("Successfully connected");
+            expect(content).toContain(integration.connectionString());
+        });
+    });
+
     describe("with default config", () => {
         describe("without connection string", () => {
             it("prompts for connection string", async () => {

From ab4f604d0d38d116061f6f052eaafb587bf6a9fa Mon Sep 17 00:00:00 2001
From: Nikola Irinchev <irinchev@me.com>
Date: Thu, 24 Apr 2025 17:43:54 +0200
Subject: [PATCH 2/3] add a comment explaining the workaround

---
 src/server.ts | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/server.ts b/src/server.ts
index 7adab9ae..81c54124 100644
--- a/src/server.ts
+++ b/src/server.ts
@@ -34,6 +34,12 @@ export class Server {
         this.registerTools();
         this.registerResources();
 
+        // This is a workaround for an issue we've seen with some models, where they'll see that everything in the `arguments`
+        // object is optional, and then not pass it at all. However, the MCP server expects the `arguments` object to be if
+        // the tool accepts any arguments, even if they're all optional.
+        //
+        // see: https://github.com/modelcontextprotocol/typescript-sdk/blob/131776764536b5fdca642df51230a3746fb4ade0/src/server/mcp.ts#L705
+        // Since paramsSchema here is not undefined, the server will create a non-optional z.object from it.
         const existingHandler = this.mcpServer.server["_requestHandlers"].get(CallToolRequestSchema.shape.method.value);
         this.mcpServer.server.setRequestHandler(CallToolRequestSchema, (request, extra): Promise<CallToolResult> => {
             if (!request.params.arguments) {

From 5685bd2ddac00ee1cbb747332a8aff1e8bb073b8 Mon Sep 17 00:00:00 2001
From: Nikola Irinchev <irinchev@me.com>
Date: Thu, 24 Apr 2025 18:13:47 +0200
Subject: [PATCH 3/3] fix lint

---
 src/server.ts | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/src/server.ts b/src/server.ts
index 81c54124..14bea760 100644
--- a/src/server.ts
+++ b/src/server.ts
@@ -9,6 +9,7 @@ import { ObjectId } from "mongodb";
 import { Telemetry } from "./telemetry/telemetry.js";
 import { UserConfig } from "./config.js";
 import { CallToolRequestSchema, CallToolResult } from "@modelcontextprotocol/sdk/types.js";
+import assert from "assert";
 
 export interface ServerOptions {
     session: Session;
@@ -40,7 +41,15 @@ export class Server {
         //
         // see: https://github.com/modelcontextprotocol/typescript-sdk/blob/131776764536b5fdca642df51230a3746fb4ade0/src/server/mcp.ts#L705
         // Since paramsSchema here is not undefined, the server will create a non-optional z.object from it.
-        const existingHandler = this.mcpServer.server["_requestHandlers"].get(CallToolRequestSchema.shape.method.value);
+        const existingHandler = (
+            this.mcpServer.server["_requestHandlers"] as Map<
+                string,
+                (request: unknown, extra: unknown) => Promise<CallToolResult>
+            >
+        ).get(CallToolRequestSchema.shape.method.value);
+
+        assert(existingHandler, "No existing handler found for CallToolRequestSchema");
+
         this.mcpServer.server.setRequestHandler(CallToolRequestSchema, (request, extra): Promise<CallToolResult> => {
             if (!request.params.arguments) {
                 request.params.arguments = {};