Found the issue. My mcp server has capabilities like prompts and tools, does not have right request handler for prompts as my mcp server does not handle prompts yet. Cursor started throwing -32601 error as per mcp spec: Completion - Model Context Protocol.
Because of this error, cursor could not find tools from my mcp server. Once i remove the prompts from capabilities, it started working. phheww!! Sample code attached If we remove prompts from line no 31, it works fine.
import express from "express";
import { z } from "zod";
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import {
ListToolsRequestSchema,
CallToolRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
enum ToolName {
ECHO = "echo",
}
const EchoSchema = z.object({
message: z.string().describe("The message to echo back"),
});
class EchoMCPServer {
private server: Server;
private app: express.Application;
private transports: Map<string, SSEServerTransport> = new Map();
constructor() {
this.server = new Server(
{
name: "echo-mcp-server",
version: "1.0.0",
},
{
capabilities: {
prompts: {},
tools: {},
},
}
);
this.app = express();
this.app.use(express.json());
this.setupHandlers();
this.setupRoutes();
}
private setupHandlers() {
console.log("setupHandlers");
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
console.log("ListToolsRequestSchema");
return {
tools: [
{
name: ToolName.ECHO,
description: "Echo back the provided message",
inputSchema: {
type: "object",
properties: {
message: {
type: "string",
description: "The message to echo back",
},
},
required: ["message"],
},
},
],
};
});
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
console.log("CallToolRequestSchema");
const { name, arguments: args } = request.params;
if (name === ToolName.ECHO) {
const validatedArgs = EchoSchema.parse(args);
return {
content: [
{
type: "text",
text: `Echo: ${validatedArgs.message}`,
},
],
};
}
throw new Error(`Unknown tool: ${name}`);
});
}
private setupRoutes() {
this.app.get("/sse", async (req, res) => {
const sessionId = (req.query.sessionId as string) || "default";
console.log("sse", sessionId);
let transport = this.transports.get(sessionId);
if (!transport) {
transport = new SSEServerTransport("/message", res);
this.transports.set(sessionId, transport);
await this.server.connect(transport);
transport.onclose = () => {
console.log(`SSE connection closed for session: ${sessionId}`);
this.transports.delete(sessionId);
};
console.log(`SSE connection established for session: ${sessionId}`);
}
});
this.app.post("/message", async (req, res) => {
const sessionId = (req.headers["x-session-id"] as string) || "default";
console.log("message", sessionId);
const transport = this.transports.get(sessionId);
if (!transport) {
return res.status(404).json({ error: "Session not found" });
}
try {
await transport.handleMessage(req.body);
res.status(200).end();
} catch (error) {
console.error("Error handling message:", error);
res.status(500).json({ error: "Internal server error" });
}
});
}
public start(port: number = 3001) {
this.app.listen(port, () => {
console.log(`Echo MCP Server running on port ${port}`);
console.log(`SSE endpoint: http://localhost:${port}/sse`);
console.log(`Message endpoint: http://localhost:${port}/message`);
});
}
}
const server = new EchoMCPServer();
server.start();