What Is a Remote MCP Server?
A remote MCP server exposes tools, resources, and prompts over Streamable HTTP so AI clients can discover and use them across a network.
A remote MCP server is an independently running implementation of the Model Context Protocol that an AI client reaches over a network. The current official remote transport is Streamable HTTP. The server exposes capabilities such as tools, resources and prompts through JSON-RPC 2.0 messages.
“Remote” describes where the server runs and how the client connects. It is still MCP; it is not a separate protocol and it is not automatically the same thing as a regular REST API.
Remote MCP server in one minute
- You configure an MCP client with the server’s HTTPS endpoint.
- The client sends an initialization request.
- Client and server negotiate a protocol version and capabilities.
- The client sends JSON-RPC requests with HTTP POST.
- The server returns JSON or streams messages with server-sent events.
- The client invokes discovered tools or reads declared resources.
After initialization, subsequent requests include the MCP-Protocol-Version header. A server may support multiple simultaneous client connections because it runs as an independent network service.
How the protocol works
1. Endpoint configuration
An MCP client needs the remote endpoint URL. Use HTTPS for production deployments. The URL identifies an MCP endpoint, not merely an arbitrary JSON endpoint.
2. Initialization and capability negotiation
The first JSON-RPC request is an initialize call. It includes the client’s protocol version and implementation information. The server responds with its selected protocol version and capabilities, such as whether it provides tools, resources or prompts. The client then sends an initialized notification.
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-06-18",
"capabilities": {},
"clientInfo": {
"name": "example-client",
"version": "1.0.0"
}
}
}
Protocol versions and message schemas are maintained by the MCP project. See the official MCP specification for the current requirements.
3. Requests, responses and streams
Tool discovery uses methods such as tools/list; invocation uses tools/call. Resource-capable servers expose resource listing and reading methods. Every request and response follows JSON-RPC 2.0. Streamable HTTP allows a response to contain server-sent events, which is useful when a tool produces progress or several messages.
The transport can also use follow-up HTTP GET requests for server-to-client streams and notifications. Your client must preserve the session details and headers required by the server.
Minimal Streamable HTTP client with cURL
The exact endpoint path and authentication method are server-specific. The following sequence shows the wire pattern. Replace the URL, token and protocol version with the values documented by your server.
# Initialize a session
curl -i https://mcp.example.com/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{
"jsonrpc":"2.0",
"id":1,
"method":"initialize",
"params":{
"protocolVersion":"2025-06-18",
"capabilities":{},
"clientInfo":{"name":"curl-client","version":"1.0.0"}
}
}'
# After the server selects a version, send the negotiated version
curl -i https://mcp.example.com/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H 'MCP-Protocol-Version: 2025-06-18' \
-d '{"jsonrpc":"2.0","method":"notifications/initialized","params":{}}'
# Discover tools
curl -i https://mcp.example.com/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H 'MCP-Protocol-Version: 2025-06-18' \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'
In a real client, read the initialization response, retain any session identifier returned by the server, and include it exactly as the server’s transport documentation requires.
Python example
This example performs initialization and tool discovery with the standard requests library. It handles JSON responses; an implementation that receives an event stream must parse the SSE body and process each event.
import os
import requests
ENDPOINT = "https://mcp.example.com/mcp"
TOKEN = os.environ.get("MCP_TOKEN")
headers = {
"Content-Type": "application/json",
"Accept": "application/json, text/event-stream",
}
if TOKEN:
headers["Authorization"] = f"Bearer {TOKEN}"
initialize = {
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-06-18",
"capabilities": {},
"clientInfo": {"name": "python-client", "version": "1.0.0"},
},
}
response = requests.post(ENDPOINT, json=initialize, headers=headers, timeout=30)
response.raise_for_status()
init_result = response.json()
negotiated = init_result["result"]["protocolVersion"]
headers["MCP-Protocol-Version"] = negotiated
initialized = {
"jsonrpc": "2.0",
"method": "notifications/initialized",
"params": {},
}
requests.post(ENDPOINT, json=initialized, headers=headers, timeout=30).raise_for_status()
tools_list = {"jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {}}
result = requests.post(ENDPOINT, json=tools_list, headers=headers, timeout=30)
result.raise_for_status()
print(result.json())
Node.js example
const endpoint = 'https://mcp.example.com/mcp';
const token = process.env.MCP_TOKEN;
const headers = {
'content-type': 'application/json',
'accept': 'application/json, text/event-stream',
...(token ? { authorization: `Bearer ${token}` } : {})
};
async function post(message, extraHeaders = {}) {
const response = await fetch(endpoint, {
method: 'POST',
headers: { ...headers, ...extraHeaders },
body: JSON.stringify(message)
});
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);
return response.json();
}
const init = await post({
jsonrpc: '2.0',
id: 1,
method: 'initialize',
params: {
protocolVersion: '2025-06-18',
capabilities: {},
clientInfo: { name: 'node-client', version: '1.0.0' }
}
});
const version = init.result.protocolVersion;
await post({ jsonrpc: '2.0', method: 'notifications/initialized', params: {} }, {
'MCP-Protocol-Version': version
});
const tools = await post({
jsonrpc: '2.0',
id: 2,
method: 'tools/list',
params: {}
}, { 'MCP-Protocol-Version': version });
console.log(tools);
Remote versus local MCP servers
| Property | Local MCP | Remote MCP |
|---|---|---|
| Typical transport | stdio | Streamable HTTP |
| Process ownership | The client launches a subprocess | The server runs independently |
| Message path | stdin/stdout | HTTP requests and optional SSE streams |
| Sharing | Usually one local client process | Can serve multiple network clients |
| Operations | Managed with the desktop or agent installation | Requires TLS, authentication, logging and service operations |
Local stdio is convenient for private tools on one machine. Remote Streamable HTTP is appropriate when several clients need the same service, when the server needs its own deployment lifecycle, or when an AI application must reach tools over a network.
Is a remote MCP server just an API?
It is an HTTP service, but MCP adds a defined interaction model. A compliant server performs initialization and capability negotiation, uses JSON-RPC 2.0 messages, and exposes MCP primitives such as tools, resources and prompts. A REST endpoint that returns JSON is not automatically an MCP server.
You can place an MCP server behind an API gateway, but the gateway must preserve the HTTP methods, headers, streaming behavior and request bodies required by the MCP transport.
Authentication and authorization
Authentication is optional for MCP itself. A protected HTTP deployment should follow the MCP authorization specification. In that model, the server is an OAuth 2.1 resource server and the client is an OAuth client. The server publishes protected-resource metadata so a client can discover the authorization server.
- Send
Authorization: Bearer <access-token>on every HTTP request. - Do not put access tokens in query strings.
- Validate that the token was issued for your server’s resource and audience.
- Return HTTP 401 for invalid or expired tokens.
- Use HTTPS for the endpoint and authorization flows.
See the MCP authorization specification for discovery and token requirements. Do not pass a client’s token through to an unrelated downstream service.
Security checklist
- Validate the HTTP
Originheader to reduce DNS-rebinding risk. - Bind local-only services to
localhost, not all network interfaces. - Give each tool the minimum permissions it needs.
- Document which tools can change external state, delete data or spend money.
- Apply rate limits and retain request and error logs without storing secrets.
- Rotate credentials and keep them in a secret manager.
- Validate token audience, issuer, expiry and scopes before dispatching a tool.
- Use a secure tunnel for private or on-premises servers instead of exposing them directly when your client supports that pattern.
Reliability, scaling and cost considerations
Reliability
Handle connection failures, HTTP 401 and 403 responses, timeouts, malformed JSON-RPC messages and server-side tool errors separately. Retry only operations that are safe to repeat. A state-changing tool should support idempotency or require an explicit request identifier so a network retry cannot perform the action twice.
Streaming
Clients must support both a normal JSON response and an event stream. Set a practical connect timeout and a longer read timeout for tools that legitimately take time. If a proxy buffers or closes SSE connections, configure it to pass through streaming responses and keep-alive traffic.
Scaling
Prefer stateless request handling where possible. If a server maintains sessions, store session state in shared storage or route a client consistently to the same instance. Monitor initialization failures, tool latency, stream disconnects, authentication failures and rate-limit responses.
Cost
MCP does not define a hosting price. Your costs come from compute, network transfer, identity services, downstream APIs and any work performed by tools. Cache read-only data when it is safe, set limits on expensive tools and expose clear errors when a quota is exhausted.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| HTTP 401 | Missing, expired or invalid bearer token | Refresh the token and send it in the Authorization header on every request. |
| HTTP 403 | Token lacks the required scope or audience | Request the server’s scope and validate the token resource and audience. |
| HTTP 400 after initialization | Missing or incorrect protocol header | Use the negotiated version in MCP-Protocol-Version on subsequent requests. |
| Tools are empty | The server did not advertise the tools capability or the account is not authorized | Inspect the initialization result and server permissions, then call tools/list again. |
| JSON parse error | The response is an SSE stream rather than one JSON document | Check Content-Type and parse SSE events incrementally. |
| Connection closes during a long call | Proxy idle timeout or client read timeout | Enable keep-alives, configure proxy timeouts and increase the read timeout. |
| Duplicate side effect | A client retried a non-idempotent tool | Add idempotency keys or disable automatic retries for that operation. |
| Works locally but not remotely | Origin, TLS, firewall or reverse-proxy configuration | Check certificate validity, allowed origins, ingress rules and streaming pass-through. |
Connect an AI application
Clients such as agent environments and the OpenAI Responses API can be configured with a remote MCP server_url. Depending on the server, the client can supply an OAuth access token. OpenAI also documents Secure MCP Tunnel for private or on-premises servers that should not be exposed publicly; see the OpenAI remote MCP documentation.
Before adding a server, review its declared tools, required scopes, data handling and state-changing operations. A remote server can be reached by multiple clients, so treat its endpoint as production infrastructure.
Or skip the browser setup
If your MCP workflow needs screenshots, ScreenshotNeo provides a remote MCP server with take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients. It also has a direct HTTP API when an MCP client is not needed.
One request returns a PNG, JPEG, WebP or PDF. Before capture, cookie and consent banners are accepted and more than 60 known consent platforms, newsletter popups and chat widgets are removed. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed; the response identifies the result with X-Page-Verdict and X-Billed headers. Every feature is included on every plan.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
See the ScreenshotNeo API and MCP documentation for authentication, capture options and MCP setup. The free plan includes 1,000 screenshots each month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.
FAQ
Does remote mean the server must be public?
It must be reachable by the client, but it can remain private behind authentication, a VPN or a secure tunnel.
Can one remote server serve several AI clients?
Yes. Its independent HTTP process can handle multiple connections, subject to its capacity, authorization rules and rate limits.
Is OAuth required?
No. Authorization is optional for MCP. Protected HTTP deployments should follow the MCP authorization specification and use bearer-token validation.
Which transport should a new remote deployment use?
Use Streamable HTTP, the official remote transport. Stdio remains the usual transport for local deployments.
What should I log?
Log request IDs, method names, latency, status and tool errors while redacting access tokens, cookies and other sensitive values.


