How to Add a Remote MCP Server to Cursor, Claude Code, VS Code and Claude Desktop
Tested setup for adding a remote MCP server to Cursor, Claude Code, VS Code and Claude Desktop, using a real public endpoint. Copy-paste configs, curl and Inspector checks, mcp-remote, and what tools/list costs in latency and tokens.

On this page
A remote MCP server is a Model Context Protocol server you reach over HTTPS instead of starting it on your own machine. You add it with a URL, not a command. Every major AI coding client supports this now, but each one wants the URL in a slightly different shape. Cursor takes a bare url, Claude Code wants "type": "http", VS Code has two file formats, and Claude Desktop doesn't read a URL from its config file at all.
This guide gives you the working setup for each client, using a real public server: Benchline, my open-source developer tools site, which serves its tools over MCP at https://benchline.fabwaseem.com/mcp with no API key and no session. I checked every config block against the official docs on October 23, 2026, ran the Claude Code commands for real, called a tool through the official TypeScript SDK and through mcp-remote, and measured what the server costs in latency and in tokens. All numbers below come from those runs.
TL;DR: add a remote MCP server#
Before you blame the client, test the server with curl or the MCP Inspector. A remote server that answers tools/list will work in all four.
What "remote" means in MCP#
MCP has two standard transports. With stdio, the client starts the server as a child process (npx some-server) and talks to it through stdin and stdout. The server runs on your machine, with your files and your environment variables. With Streamable HTTP, the server is a web endpoint. The client POSTs JSON-RPC messages to one URL and reads the answer as JSON or as a Server-Sent Events stream. The transport spec defines both. The older HTTP+SSE transport is deprecated, and Claude Code's docs say to use HTTP where you can.
A remote server is just the second kind, hosted somewhere public. That has real advantages. You install nothing, the publisher ships fixes without asking you to update, and the same URL works in every client. It also means the server never sees your disk, which is a security win for tools that don't need it.
Benchline's endpoint is stateless: each POST stands alone, it returns no Mcp-Session-Id, and it answers with plain JSON. I explain how that server is built in Building Benchline: a stateless MCP server, and what the newer stateless spec changes in Stateless MCP servers and the 2026-07-28 spec. For this guide, all you need is the URL.
Check the server with curl first#
A Streamable HTTP server must get both application/json and text/event-stream in the Accept header. This call lists the tools:
curl -sS -X POST https://benchline.fabwaseem.com/mcp \
-H 'content-type: application/json' \
-H 'accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'And this one calls a tool:
curl -sS -X POST https://benchline.fabwaseem.com/mcp \
-H 'content-type: application/json' \
-H 'accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"format_json","arguments":{"json":"{\"a\":1}"}}}'Benchline accepts tools/list and tools/call without an initialize first, because it builds a fresh server for every request. A sessionful server would want initialize first and an Mcp-Session-Id header after that. When I sent initialize with protocol version 2025-06-18, the server answered with serverInfo benchline, the tools capability and no session header.
If you prefer a real client to raw JSON-RPC, the MCP Inspector has a CLI mode. Version 2.12.0 needs Node.js 22.19 or newer:
npx @modelcontextprotocol/inspector --cli \
--transport http --server-url https://benchline.fabwaseem.com/mcp \
--method tools/call --tool-name format_json --tool-arg 'json="{\"a\":1}"'One gotcha I hit: --tool-arg parses the value as JSON. My first try, json={"a":1}, sent an object, and the tool rejected it with -32602 Input validation error: expected string, received object. Wrapping the value in quotes makes it a JSON string.
Cursor#
Cursor reads ~/.cursor/mcp.json for servers you want in every project, and .cursor/mcp.json in a project for that project only. A remote server needs only a url:
{
"mcpServers": {
"benchline": {
"url": "https://benchline.fabwaseem.com/mcp"
}
}
}For a server that needs a token, add headers and read the value from your environment with Cursor's ${env:NAME} interpolation, so the secret never lands in the file:
{
"mcpServers": {
"my-api": {
"url": "https://api.example.com/mcp",
"headers": { "Authorization": "Bearer ${env:MY_SERVICE_TOKEN}" }
}
}
}Servers that use OAuth need no header. Cursor runs the sign-in itself, using PKCE and the server's protected resource metadata. If a server doesn't show up, open the Output panel and pick MCP Logs. Source: Cursor MCP docs.
Claude Code#
Claude Code has a one-line command for remote servers:
claude mcp add --transport http benchline https://benchline.fabwaseem.com/mcp
claude mcp listOn Claude Code 2.1.309 this printed Added HTTP MCP server benchline with URL: https://benchline.fabwaseem.com/mcp to local config, and claude mcp list showed benchline: https://benchline.fabwaseem.com/mcp (HTTP) - ✔ Connected. The default scope is local: the entry is saved in ~/.claude.json under the current project. Add --scope user to use it in every project, or --scope project to write it to .mcp.json and commit it for your team. For a token, pass --header "Authorization: Bearer …". For OAuth servers, run /mcp inside a session or claude mcp login <name>.
The project file looks like this:
{
"mcpServers": {
"benchline": {
"type": "http",
"url": "https://benchline.fabwaseem.com/mcp"
}
}
}Don't paste a Cursor block into .mcp.json. Claude Code reads an entry without type as a stdio server. When I tried the Cursor-style block above, claude mcp list printed Skipped — invalid MCP server config for "benchline": command: expected string, received undefined, and the server was not loaded. Adding "type": "http" fixes it, and "streamable-http" works as an alias. Source: Claude Code MCP docs.
VS Code#
VS Code now reads two formats, and it matters which file you edit.
The VS Code format lives in .vscode/mcp.json in your workspace, or in your user profile. It uses a top-level servers object, and type is required:
{
"servers": {
"benchline": {
"type": "http",
"url": "https://benchline.fabwaseem.com/mcp"
}
}
}The portable format lives in .mcp.json at the workspace root, or in ~/.copilot/mcp-config.json for your user. It uses mcpServers, the same shape as Claude Code's file, so one committed .mcp.json can serve both tools:
{
"mcpServers": {
"benchline": {
"type": "http",
"url": "https://benchline.fabwaseem.com/mcp"
}
}
}The guided MCP: Add Server command now suggests the Copilot Global file first and labels .vscode/mcp.json as deprecated, though VS Code still reads it. The two formats handle secrets differently. .vscode/mcp.json supports ${input:…} prompts and ${env:NAME}, while portable files use ${NAME} and no input prompts. VS Code first tries Streamable HTTP and falls back to SSE. Source: VS Code MCP configuration reference.
Claude Desktop#
This is where most copy-paste setups break. claude_desktop_config.json is for local stdio servers. The supported way to add a remote server is a custom connector:
- Open Customize > Connectors (on the web,
claude.ai/customize/connectors). - Click + Add, then Add custom connector.
- Enter a name and the server URL,
https://benchline.fabwaseem.com/mcp. - Under Authentication, pick No sign in for a public server like Benchline, or sign in for an OAuth server. There is also a Request headers section for API keys.
- In a chat, enable it from + > Connectors.
Custom connectors work on Free (one connector), Pro, Max, Team and Enterprise plans. On Team and Enterprise, an Owner adds the connector first. One detail matters a lot: Claude connects to a custom connector from Anthropic's cloud, not from your computer. The server has to be reachable from the public internet. A server on localhost, behind a VPN or on a company network won't connect, even if curl works on your laptop. Source: Claude Help Center.
For those servers, bridge the URL to stdio with mcp-remote in claude_desktop_config.json (on macOS in ~/Library/Application Support/Claude/, on Windows in %APPDATA%\Claude\):
{
"mcpServers": {
"benchline": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://benchline.fabwaseem.com/mcp"]
}
}
}Claude Desktop starts mcp-remote as a local process, and mcp-remote speaks Streamable HTTP to the server from your own network. I tested this by starting mcp-remote 0.15.2 from the official TypeScript SDK's stdio client, the way Claude Desktop would. The format_json call came back valid. The first start took 11.2 s, including npx fetching the package, and the call itself took 970 ms. For a token, use --header and keep the value in env, or --header-file so the secret stays out of the process list.
Call a tool with the official TypeScript SDK#
To check a server from code, or to use one in your own agent, the official SDK client takes about ten lines:
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
const client = new Client({ name: "remote-mcp-check", version: "1.0.0" });
await client.connect(
new StreamableHTTPClientTransport(new URL("https://benchline.fabwaseem.com/mcp")),
);
const { tools } = await client.listTools();
const result = await client.callTool({
name: "format_json",
arguments: { json: '{"b":2,"a":[1,2]}' },
});
console.log(result.structuredContent); // { output: '{\n "b": 2, …', valid: true, errors: [] }
await client.close();With @modelcontextprotocol/sdk 1.32.1, the client negotiated protocol 2025-11-25, got no session id, and the call returned structuredContent with valid: true. Twenty calls on that connected client took a median of 375 ms and a p95 of 419 ms.
The v2 client, @modelcontextprotocol/client 2.3.1, with versionNegotiation: { mode: "auto" } also connected and fell back to 2025-11-25, because Benchline's server doesn't speak 2026-07-28 yet. A direct 2026-07-28 request got Unsupported protocol version, and the list of versions the server does accept. Clients that negotiate handle this for you. Claude Code's v2 runtime, for example, asks each server which revision it supports and uses the newer one only where the server has it.
What a remote MCP server costs your context window#
Speed is rarely the problem with MCP. Tokens are. Each tool's name, description and JSON Schema can end up in the model's context, and that's paid on every turn. So I measured Benchline's tools/list:
- The full JSON-RPC response is 138,658 bytes. With
curl --compressedthe server sent 24,174 bytes of gzip. - Counted with the
o200k_basetokenizer (viajs-tiktoken), the whole response is 34,307 tokens. - Keep only what a model needs to choose and call a tool, meaning
name,descriptionandinputSchema, and it comes to 17,517 tokens (72,398 bytes of JSON). A rough characters-divided-by-4 estimate gives 18,100. Benchline's output schemas make up 52,458 bytes of the full response. - The largest single tool definition,
build_open_graph, is 584 tokens. The smallest is 75.
These are approximations. o200k_base is OpenAI's tokenizer, Claude and other models count differently, and each client decides which fields it forwards. Still, the order of magnitude holds. For comparison, the MCP server behind this site came to 5,949 tokens in my MCP vs API benchmark. Some clients soften the cost. Claude Code uses tool search by default, so Claude can look up tools when it needs them. VS Code lets you choose which tools a session can use, and Cursor lets you toggle whole servers off. Turn off what you aren't using.
Latency: why the first request is slow#
I measured with curl from my build box, which reaches the internet through an egress proxy, so the absolute numbers include that path. Yours will differ. The pattern is the useful part:
On a fresh connection, the TCP and TLS setup alone took a median of 928 ms before the first byte of the request went out. On a reused connection, tools/list sent its first byte after a median of 395 ms, and most of the remaining time went into downloading the uncompressed 138 KB body. Real clients keep connections open and fetch the tool list once per session, so you pay the slow path roughly once. Two practical points follow. A server with a large tool list should support compression. And MCP_TIMEOUT in Claude Code, or your client's equivalent, should allow a few seconds for the first connect.
Troubleshooting remote MCP servers#
Every error below is one I triggered against the live server or found in the client docs:
406 Not Acceptable: Client must accept both application/json and text/event-stream. YourAcceptheader is missing one of the two types. Real clients send both; hand-writtencurlandfetchcalls often don't.405 Method not allowedon GET. Normal for a stateless server that offers no server-to-client stream. The spec allows it, and clients carry on.Skipped — invalid MCP server config … command: expected stringin Claude Code. You have aurlwithout"type": "http".- A connector works in
curlbut not in Claude Desktop. Anthropic's cloud makes the connection, so it can't reach private networks. Usemcp-remote, or put the server somewhere public. 401 Unauthorized. The server wants OAuth or a token. Claude Code flags the server under/mcp, where you can sign in, and Cursor and VS Code both support OAuth for HTTP servers. If you configured a staticAuthorizationheader and it's rejected, fix the token: Claude Code won't fall back to OAuth.429 Too many requests. Public servers rate-limit. Benchline allows 60 requests a minute per address and sendsretry-after.Unsupported protocol version. The client asked for a revision the server doesn't have. Use a client that negotiates, or pin a version both support.- Spaces in
mcp-remoteheader args on Windows. The mcp-remote README warns that Cursor, Codex CLI and Claude Desktop on Windows don't escape spaces insideargs. WriteAuthorization:${AUTH_HEADER}with no space and putBearer …inenv.
Security checklist for remote MCP servers#
A remote server can't read your files, but it can still influence your agent. Before adding one:
- Trust the publisher. Tool descriptions and tool output reach your model, and both can carry prompt injection. Servers that fetch web content are the main risk.
- Keep secrets out of config files. Use
${env:NAME}in Cursor,${NAME}in Claude Code and portable VS Code files, or${input:…}in.vscode/mcp.json. Never commit a populatedAuthorizationheader. - Prefer OAuth over shared keys for anything multi-user, and read what scopes you grant.
- Keep tool approval on for tools that write or delete, and approve one call at a time until you trust a server.
- Pin
mcp-remote(mcp-remote@0.15.2) in shared configs, sonpxdoesn't pull a new version silently.
For the server side, including the OAuth SDK flaws I reproduced this month, read MCP security in 2026. If you want to build a remote server of your own, How to build an MCP server in Next.js covers the route handler, bearer auth and Origin checks.
How I tested#
All tests ran on October 23, 2026, from my Linux build box against the live https://benchline.fabwaseem.com/mcp:
- Latency:
curl8.14.1, 20 sequentialinitializeand 20tools/listPOSTs with a new connection each and a 1.5 s pause to stay under the rate limit. Then 20 of each on one connection withcurl --next. Median and p95 come fromtime_total, using linear interpolation. - Size and tokens: the saved
tools/listbody, counted withjs-tiktokenand theo200k_baseranks. - SDK:
@modelcontextprotocol/sdk1.32.1 and@modelcontextprotocol/client2.3.1 on Node.js 20.19. Twentyformat_jsoncalls on one connected client, 1.2 s apart. - Clients: Claude Code 2.1.309 in a throwaway
HOME.mcp-remote0.15.2 started over stdio by the SDK. MCP Inspector 2.12.0 CLI. I checked the Cursor, VS Code and Claude Desktop syntax against their official docs on the same day, but didn't run those apps on the box.
Key takeaways#
- A remote MCP server is a Streamable HTTP endpoint. You add it with a URL, and nothing runs on your machine.
- Cursor takes a bare
url. Claude Code and VS Code need"type": "http", and Claude Code skips aurlentry without it. - Claude Desktop adds remote servers as custom connectors, and the connection comes from Anthropic's cloud. Use
mcp-remoteinclaude_desktop_config.jsonfor servers that cloud can't reach. - Test with
curlor the MCP Inspector first. TheAcceptheader must list bothapplication/jsonandtext/event-stream. - Benchline's tool definitions came to 17,517 tokens (o200k_base). Context cost is the real price of adding a server, so turn off tools you don't use.
- On one connection, a
tools/callthrough the TypeScript SDK took a median of 375 ms. The first connect is the slow part. - Keep tokens in environment variables, prefer OAuth, and leave tool approval on for anything that writes.
Questions
Share


