Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To build a remote MCP server over HTTP, create an McpServer, register the tools, resources, and prompts it offers, create an HTTP transport, and connect the transport with server.connect(transport). For a new remote server, use Streamable HTTP rather than the legacy HTTP+SSE transport. Before you implement it, choose which protocol version and session model you support: the 2025-11-25 format and the 2026-07-28 draft differ in important ways.

What an HTTP MCP server does

An MCP server exposes capabilities—tools, resources, and prompts—that an MCP client can discover and use. With HTTP, the server is reachable at a remote endpoint instead of being started as a local subprocess. The endpoint carries MCP JSON-RPC messages; your application still defines what the server can do and must decide how callers are authenticated and what they are authorized to invoke.

The TypeScript SDK’s implementation sequence is intentionally short: create an McpServer and register its capabilities, create a transport, then call server.connect(transport). The difficult choices are around the wire protocol, state, and deployment boundaries—not the three-step connection itself.

Choose the HTTP transport and protocol version

Use Streamable HTTP for a new remote server

The MCP TypeScript SDK describes Streamable HTTP as its modern, fully featured transport. It carries client requests as HTTP POST messages and can return either JSON or server-sent events (SSE). SSE is optional for server-to-client notifications; clients can use JSON-only responses when they do not need that stream. Streamable HTTP also supports session management and resumability in the 2025-11-25 transport format.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

HTTP+SSE is retained for backward compatibility. Use it only when you have a specific legacy client requirement; for new work, prefer Streamable HTTP and test against the clients you intend to support.

Pin the wire behavior you intend to support

In the 2025-11-25 format, the server exposes one MCP endpoint path, such as /mcp, supporting both POST and GET. Each client JSON-RPC message is sent in a new POST, and clients advertise both application/json and text/event-stream in the Accept header. A server may return a session ID during initialization; subsequent requests then carry that ID.

The draft dated 2026-07-28 changes this model: it removes the GET stream endpoint and protocol-level sessions and describes a stateless core. Do not combine the older GET/session assumptions with a server implementing the draft wire behavior. Pin the protocol version in your deployment documentation and test the same version in your client matrix. Draft behavior can change before it becomes a stable compatibility target.

Decision 2025-11-25 format 2026-07-28 draft
Endpoint methods One endpoint supports POST and GET. GET stream endpoint removed.
Protocol sessions Session IDs may be issued and required on later requests. Describes a stateless core without protocol-level sessions.
Best fit Clients needing session state, resumability, or the existing session-capable behavior. Clients explicitly implementing the draft behavior.
Compatibility rule Pin and test one protocol version; do not assume a client or server using one model interoperates with the other unchanged.

Build a minimal TypeScript endpoint

The example below shows the stateless Express integration shape using the TypeScript SDK’s NodeStreamableHTTPServerTransport. It registers a small tool and delegates protocol responses to the transport. Install the SDK, Express, and Zod in your application using versions compatible with one another, and check the SDK server guide for the exact import and handler signatures of the version you pin. SDK APIs evolve; do not upgrade the SDK or change protocol behavior without rerunning your client tests.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import express from "express";
import { z } from "zod";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { NodeStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/nodeStreamableHttp.js";

const app = express();
app.use(express.json());

const server = new McpServer({ name: "example-http-server", version: "1.0.0" });
server.registerTool(
  "sum",
  {
    description: "Add two numbers.",
    inputSchema: { a: z.number(), b: z.number() }
  },
  async ({ a, b }) => ({
    content: [{ type: "text", text: String(a + b) }]
  })
);

// Stateless mode: no protocol session ID is generated.
const transport = new NodeStreamableHTTPServerTransport({
  sessionIdGenerator: undefined
});
await server.connect(transport);

app.post("/mcp", async (req, res) => {
  await transport.handleRequest(req, res, req.body);
});

// The transport handles the protocol's GET behavior for the version it implements.
app.get("/mcp", async (req, res) => {
  await transport.handleRequest(req, res);
});

app.listen(3000, "127.0.0.1", () => {
  console.log("MCP endpoint listening at http://127.0.0.1:3000/mcp");
});

Use the SDK transport’s own request handling for protocol responses; avoid writing a second JSON-RPC dispatcher in Express. The Express layer is still responsible for ordinary HTTP concerns such as body-size limits, authentication middleware, request logging, and error handling. The sample binds to loopback for local development. For a deliberately public deployment, bind through the hosting environment’s supported interface and put the endpoint behind deliberate network and identity controls.

Register a useful server contract

Choose a stable server name and version, then give each tool a clear name, description, and explicit input schema. Validate arguments at the boundary instead of trusting a client to send well-formed data. Register resources for data clients should read and prompts for reusable prompt templates; omit capabilities your server does not actually provide. Keep tool actions narrow enough that authorization can be checked for the specific operation.

Stateful or stateless?

Stateless mode suits API-style requests where each call can be handled without retained protocol state. Stateful mode is appropriate when you need session behavior, resumability, or richer server-to-client interactions supported by the selected protocol version. In the 2025-11-25 format, if initialization returns an Mcp-Session-Id, the client must include it on later requests. A server that requires a session should reject a request missing its ID with HTTP 400 rather than silently treating it as a new session.

Do not share one stateful transport indiscriminately across unrelated clients. Follow the SDK’s lifecycle pattern for creating, locating, and closing per-session transports, and ensure session identifiers cannot be guessed or used as a substitute for authentication. The stateless sample above avoids that session registry; it is not a template for session persistence.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Secure the endpoint before exposing it

An MCP endpoint is an application API, not merely a convenient socket for AI clients. Apply checks before requests reach tools, and treat both tool arguments and retrieved content as untrusted.

  • Validate Origin on every incoming connection. Reject an invalid Origin with HTTP 403. This is particularly important for local or private services, where a browser-based DNS-rebinding attack could otherwise reach a service the user did not intend to expose.
  • Bind locally to 127.0.0.1 during development. Do not bind to 0.0.0.0 unless network exposure is intentional and protected.
  • Authenticate every connection and authorize actions. Verify caller identity and scope, then check whether that identity may invoke each tool. Authentication alone does not mean every authenticated caller should be allowed to perform every action.
  • Limit resource use. Set request-body limits, per-request timeouts, and rate limits in the surrounding HTTP service. Bound expensive operations and avoid letting a caller supply unbounded input.
  • Log safely. Use structured logs for diagnosis, but redact credentials, sensitive tool arguments, and returned data that should not be retained.

Keep these controls at the HTTP and application layers even when the MCP transport validates protocol messages. Protocol validation does not decide whether a user is authorized to read a file, call an external service, or trigger a consequential operation.

Test the behavior clients depend on

Test against the exact SDK and protocol version you deploy. Include at least initialization, capability discovery, a valid tool call, invalid tool arguments, unsupported methods, and error responses. For a session-capable server, also test a request with a valid session ID, a missing ID when one is required, and cleanup when a session ends. Verify JSON and SSE behavior only if your implementation advertises and supports both modes.

  • Confirm requests to the single endpoint use the expected HTTP methods for the chosen protocol version.
  • Check that the server returns an HTTP 403 for an untrusted Origin and does not invoke a tool.
  • Check that unauthenticated callers and authenticated callers with insufficient scope cannot perform protected actions.
  • Send malformed or oversized input and confirm it is rejected without exhausting memory or leaving a hung request.
  • Disconnect during a long response and verify the behavior your client expects, including resumability only if supported by your selected format and transport.

Troubleshooting common HTTP MCP failures

Symptom Likely cause What to check
Initialization fails or the client reports an unsupported transport Client and server expect different protocol or transport behavior. Pin the protocol version; confirm both sides agree on Streamable HTTP rather than relying on legacy HTTP+SSE behavior.
A follow-up request is rejected after initialization The client omitted a session ID that the server requires, or sent an ID from another session. In session mode, confirm the initialization response’s Mcp-Session-Id is carried on subsequent requests and maps to the right transport.
GET behavior fails despite successful POST calls The client expects an SSE GET stream, but the server is stateless, does not offer that behavior, or implements the 2026-07-28 draft model. Check the pinned protocol version and whether the client actually needs the optional stream. Do not add an obsolete GET assumption to a draft implementation.
Valid tool calls never reach the handler The body parser, route, or transport integration is not passing the request through as expected. Verify the MCP path, HTTP method, parsed body, and SDK transport handler wiring. Let the transport generate protocol responses.
A browser or local client receives HTTP 403 Origin validation rejected the request. Inspect the actual Origin and your explicit allowlist. Do not disable Origin checks globally to make a request pass.
Calls work locally but fail through a proxy The proxy may not preserve the methods, headers, or streaming behavior required by the selected transport. Check POST and GET routing as applicable, session headers for the 2025 format, and SSE forwarding only where enabled. Test through the same proxy path as the client.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Performance, reliability, and operating cost

There is no universal throughput or latency figure for an MCP HTTP server: the tool’s work, hosting environment, proxy, and client behavior determine it. Keep handlers bounded, apply timeouts to downstream calls, and avoid blocking the event loop with long synchronous work. If a tool performs slow work, define what happens when a client disconnects and whether retrying that action is safe; a retry can repeat side effects unless the operation is designed to be idempotent.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Operationally, monitor request outcomes, tool errors, timeouts, and resource consumption without logging secrets. For stateful deployments, include session creation, expiration, cleanup, and resumability in reliability planning. For stateless deployments, verify that each request can be served without hidden per-process state if requests may reach different instances. There is no protocol-defined hosting price: estimate cost from your own compute, network, and downstream service usage.

Or skip the browser setup

If the MCP tool you want is website screenshots, you do not have to build and operate browser capture yourself. ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. Its MCP tools include take_screenshot, get_page_info, and capture_pdf; an AI agent can use them through Claude, Cursor, or another MCP client. For a direct API call, keep your key private and follow the ScreenshotNeo API documentation:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
  • Cookie banners are accepted before capture, and known consent platforms, newsletter popups, and chat widgets are removed; each of these steps can be turned off.
  • Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing. Responses identify the page verdict and billing status in X-Page-Verdict and X-Billed.
  • The free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan.

Sign up for ScreenshotNeo’s free plan to try 1,000 screenshots a month without a card.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.