I noticed that the latest update (0.45.7) brought support for MCP; however, there is no documentation on how to actually install the servers or anything. It’s not as straightforward as in other clients like Cline, where you can simply ask it to install or create a server for you. Will there be a tutorial, or will the documentation be updated anytime soon?
Hey, yes, we’re planning to do that.
Please do be more detailed with video, to understand the other users too, thank you!!
If helpful in the meantime, I made a quick thread of screenshots that explains the happy path (including how to get stdio MCP server environment variables to work): x.com
After you get the syntax down and know how it’s supposed to work, should mostly work analogously to Claude Desktop’s JSON config approach.
would love to get your feedback on these docs: Advanced / Model Context Protocol (MCP)– Cursor
thanks for the docs, i’m still having issues connecting to the a MCP typescript server running locally. Tried setting up according to the docs but i’m not sure if my mcp server is setup correctly.
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse";
import cors from "cors";
import express, { Request, Response } from "express";
import { SimpleGit, simpleGit } from "simple-git";
import { z } from "zod";
// Initialize git client
const git: SimpleGit = simpleGit();
// Create Express app
const app = express();
app.use(cors());
app.use(express.json());
// Create MCP server
const server = new McpServer({
name: "mcp-git-server",
version: "1.0.0",
});
// Store active SSE connections
const connections = new Map<string, SSEServerTransport>();
// Helper function to create branch name
function createBranchName(featureName: string): string {
return `feature/${featureName
.toLowerCase()
.replace(/[^a-z0-9]+/g, "-")
.replace(/^-+|-+$/g, "")}`;
}
interface StartFeatureParams {
featureName: string;
description?: string;
}
server.resource("config", "config://app", async (uri: URL) => ({
contents: [
{
uri: uri.href,
text: "MCP Git Server Configuration",
},
],
}));
// Add the startFeature tool
server.tool(
"startFeature",
{
featureName: z.string().describe("Name of the feature to create"),
description: z
.string()
.optional()
.describe("Optional description for commit message"),
},
async ({ featureName, description }: StartFeatureParams) => {
try {
const branchName = createBranchName(featureName);
// Make sure we're on master first
await git.checkout("master");
await git.pull("origin", "master");
// Create and checkout new branch
await git.checkoutLocalBranch(branchName);
// Add all changes
await git.add(".");
// Get the diff summary
const diffSummary = await git.diff(["--cached", "--stat"]);
// Commit with description or diff summary
const commitMessage =
description || `feat: ${featureName}\n\n${diffSummary}`;
await git.commit(commitMessage);
// Push to remote
await git.push("origin", branchName);
return {
content: [
{
type: "text",
text: `Successfully created and pushed branch: ${branchName}`,
},
],
};
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : "Unknown error occurred";
return {
content: [
{
type: "text",
text: `Failed to create feature branch: ${errorMessage}`,
},
],
isError: true,
};
}
}
);
// Start the server with SSE transport
if (require.main === module) {
const port = process.env.PORT || 3030;
// Handle SSE connection
app.get("/sse", async (req: Request, res: Response) => {
// Set SSE headers
res.setHeader("Content-Type", "text/event-stream");
res.setHeader("Cache-Control", "no-cache");
res.setHeader("Connection", "keep-alive");
res.setHeader("Access-Control-Allow-Origin", "*");
// Generate a unique connection ID
const connectionId = Math.random().toString(36).substring(2);
// Create and store the transport
const transport = new SSEServerTransport("/messages", res);
connections.set(connectionId, transport);
// Clean up on connection close
res.on("close", () => {
connections.delete(connectionId);
});
await server.connect(transport);
});
// Handle POST messages
app.post("/messages", async (req: Request, res: Response) => {
// Find the active connection
const transport = Array.from(connections.values())[0];
if (!transport) {
console.error("No active SSE connection");
res.status(400).json({ error: "No active SSE connection" });
return;
}
try {
await transport.handlePostMessage(req, res);
} catch (error) {
res.status(500).json({ error: "Failed to handle message" });
}
});
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
console.log(`MCP endpoint available at http://localhost:${port}/sse`);
});
}```
Wow, it looks amazing, thanks. in your example, did you connect brave, is it built-in for selection, or do you need to download it?
If you have npx
working on your local machine, you can use it without explicitly downloading anything new.
It’s one of the official reference MCP servers from Anthropic: servers/src/brave-search at main · modelcontextprotocol/servers · GitHub
until now, I am not getting to understand this, I tried all of the types of servers like method and I am not getting success even one, so frustrated
we’re deploying a fix for this in the next patch that comes out. sorry about this!
It’s okay, I am getting confuse for am I wrong or is the mcp is not fully stable yet
Sorry to say, but this is worse than useless - does not show you how to get brave into the system at all
You mean it doesn’t show you how to get the MCP server into Cursor? That’s correct, the last link I gave doesn’t have docs for Cursor (MCP servers exist without needing Cursor).
Here is how to use the brave-search MCP server with Cursor specifically: x.com
I just tried using it now; works great.
One thing when I’m running cursor on windows it’s trying to execute all my MCP on the windows environment as well, even when I’m using WSL. Would be good to be able to specify that it should run on my WSL so I don’t have to go through the pains of getting everything working on windows.
https://docs.cursor.com/advanced/model-context-protocol#model-context-protocol
It took some fussing around yesterday, but I was able to get it working following the basic STDIO example they provide for the weather reference. Then I extrapolated and got a custom studio MCP implementation on my older ES Modules, non typescript project as well.
It has been tested on both MacOS and Windows and works amazing with 3.5 sonnet composer agent so far.
I’m not sure if it was just a quirk of of my environments or not, but I did have to use the full path in the “Command” field eg:
node C:\Users\Username\Projects\YOURPROJECT\scripts\mcp-test.js
I did struggle with getting the sse based approach but it was probably my fault and I gave up halfway and just went the stdio approach because its all I needed for my use case anyway.
Overall MCP support has some pretty huge implications for the composer agent and I’m really excited about this.
EDIT: oh there is a quirk on Windows where you get an empty CMD popup window every time the Composer Agent calls an MCP tool. Could also be an environment issue on my end idk.
I genuinely appreciate this type of post. So I’ve been working a lot recently with Cline and creating a custom LibreChat. I guess to me anyway, Cursor without MCP is no Cursor at all. LibreChat also kinda only works by pointing to the index.js as well I was just having a really hard time understanding where to put the environment variables. Appreciate it
I am using Sequential Thinking with MCP and it is nice. is there a way to give cursor permission to auto advance? so that I don’t have to hit run tool 20 times?
I am having the same issue where a cmd prompt is opening. If I close it, the MCP server dies. Using Python with uv if that matters.
You just have to exit the cursor, right click, exit the app and re-enter, for it to work, I was frustrated that the icon did not turn green and the tool did not work, but I did that and that was it.
Any updates on documentation, keen to get this rolling with the docker
Fiddled a bit but not clear how to integrate with Cursor.