In short: A headless MCP is a Model Context Protocol setup with no chat UI: a stateless server exposes tools as a background API, and an autonomous client orchestrates the LLM and that server through scripts, webhooks, or cron. Since the 2026-07-28 stateless spec, both run remotely and serverless over Streamable HTTP — SSE is now legacy.
Most MCP tutorials still hand you a local server, a stdio pipe, and a desktop chat client. That shape is a demo, not a deployment. The production pattern in 2026 is headless — no GUI, no sticky session, just background services trading JSON over HTTP — and this guide builds both halves of it from the ground up.
What is a headless MCP — and why did it become the default in 2026?
Think of the Model Context Protocol as USB-C for AI. Before USB-C, every device carried its own connector; before MCP, every LLM integration was a bespoke adapter glued to one vendor's API. MCP standardizes how a model reaches data, tools, and remote services, so a single client can speak to many backends through one wire format. The Model Context Protocol defines that wire.
"Headless" borrows its meaning from headless CMS and headless browsers: the engine runs without the front end. A headless MCP has no chat window and no human in the loop at request time. Tools get invoked by a schedule, a webhook, or another program, and the agent decides when to call them.
Two shifts in mid-2026 turned this from a niche into the norm. The 2026-07-28 MCP specification rewrote the protocol core to be stateless, added header-based routing so proxies can steer traffic without reading request bodies, and hardened authorization. Servers can now scale horizontally; clients can run anywhere. For where this sits in the wider stack, see the reference framework in our guide to the 2026 agentic architecture.
The two components: headless MCP server vs headless MCP client/host
A headless setup decouples into two independently deployable pieces, and conflating them is the most common early mistake. Pin down the inputs and outputs of each before you write a line of code.
The server is a standalone tool-provider API. It exposes a catalog of tools and the data behind them, runs as a background workload on Cloudflare Workers, AWS Lambda, or a plain Docker container, and answers over stateless HTTP. It holds no conversation. A tool call goes in; a result comes out. Nothing lingers between requests.
The client, sometimes called the host, is the autonomous agent. It boots from a cron job, a webhook, or a script, connects to one or more servers, hands the available tools to an LLM, and runs the tool-use loop until the task is done — with no chat UI in front of it. If you are mapping where this component lives in a larger system, our breakdown of the layers of a robust AI agent architecture places orchestration in context.
How to build a headless MCP server (Node.js / TypeScript)
A server does two jobs: it advertises its tools, and it runs them. In protocol terms that is a tools/list handler returning each tool's name, description, and JSON Schema, and a tools/call handler that executes a named tool with validated arguments.
Define and serve the tools
Transport is where 2026 breaks from older tutorials. The modern default is stateless Streamable HTTP at a single /mcp endpoint. The helper createMcpHandler graduated into the official MCP TypeScript SDK, so you wire tools to an HTTP handler and keep no session bookkeeping of your own.
import { createMcpHandler } from "@modelcontextprotocol/sdk/server/http";
import { z } from "zod";
const handler = createMcpHandler((server) => {
server.tool(
"get_order_status",
"Look up the status of an order by its ID",
{ orderId: z.string() },
async ({ orderId }) => {
const status = await db.orders.status(orderId);
return { content: [{ type: "text", text: status }] };
}
);
});
// Stateless Streamable HTTP: every POST to /mcp is self-contained.
export default { fetch: handler };
Each request stands alone. There is no initialize handshake to clear first and no Mcp-Session-Id pinning the caller to one instance, so any worker can answer any request. That property is exactly what makes serverless hosting viable.
Why the old SSE pattern is gone
If a tutorial tells you to open /mcp/sse and post replies to /mcp/messages, it predates the current spec. The SSE transport deprecation (April 1, 2026) retired that two-endpoint dance. SSE still answers for backward compatibility, but the next minor version removes it and the public MCP registry rejects new SSE-only listings. The table below is the migration in one view.
| Dimension | Legacy SSE (pre-2026) | Streamable HTTP (2026-07-28) |
|---|---|---|
| Handshake | initialize round-trip before any call | None — each request is self-contained |
| Session header | Mcp-Session-Id pins the client to one instance | Stateless; no session header |
| Endpoints | /mcp/sse to read, /mcp/messages to write | Single /mcp endpoint |
| Routing | Sticky single-instance; an open stream held per client | Mcp-Method / Mcp-Name headers let proxies route by header |
| Long operations | Elicitations depend on the open stream | Multi Round-Trip Requests return a resumable requestState |
| Hosting model | Needs sticky sessions or Durable Objects | Ordinary HTTP workload; any worker answers |
| Status | Deprecated April 1, 2026; rejected for new registry listings | Current standard |
The routing headers matter more than they look. Because Mcp-Protocol-Version, Mcp-Method, and Mcp-Name ride in the HTTP headers, a load balancer can rate-limit or shard MCP traffic without parsing a single JSON body. And Multi Round-Trip Requests replace stream-dependent elicitations with a serialized requestState that any instance can resume, so a long-running operation no longer needs one server holding a socket open.
How to build a headless MCP client / agent (Python + uv)
The client is the autonomous half, and its loop is short to describe: connect, list the server's tools, translate those schemas into the LLM's tool format, send the model a task, and route every tool call the model emits back to the server — then feed results in until the model stops asking.
Scaffold it with uv, which resolves and pins dependencies fast, then add the mcp SDK and your model provider's SDK.
uv init headless-agent
cd headless-agent
uv add mcp anthropic
The agent below connects to the server, maps MCP tool schemas onto the model's tool format, and drives the tool-use loop with no human prompt in sight.
import asyncio
from mcp.client.streamable_http import streamablehttp_client
from mcp import ClientSession
async def run(task: str):
async with streamablehttp_client("https://tools.example.com/mcp") as (read, write, _):
async with ClientSession(read, write) as session:
await session.initialize()
listed = await session.list_tools()
tools = [
{
"name": t.name,
"description": t.description,
"input_schema": t.inputSchema,
}
for t in listed.tools
]
messages = [{"role": "user", "content": task}]
while True:
reply = llm.create(messages=messages, tools=tools)
calls = [b for b in reply.content if b.type == "tool_use"]
if not calls:
return reply
messages.append({"role": "assistant", "content": reply.content})
for call in calls:
result = await session.call_tool(call.name, call.input)
messages.append({
"role": "user",
"content": [{
"type": "tool_result",
"tool_use_id": call.id,
"content": result.content,
}],
})
asyncio.run(run("Refund order 4021 and post a summary to Slack"))
Trigger run() from cron, a webhook, or a queue worker and you have a background agent. The same loop scales from one server to many — which is where the enterprise pattern goes next.
2026 enterprise best practices: serverless, auth hardening, and vendor MCP ecosystems
Go serverless
Statelessness is what unlocks serverless. With no session to pin and no stream to hold, an MCP server is an ordinary request-in, response-out function. MCP on Cloudflare Workers now runs without Durable Objects, and teams including Sentry and Linear already run stateless MCP in production.
Scale-to-zero and horizontal fan-out come almost for free, though cold starts and tail latency still deserve attention under real traffic. Our field notes on real-time AI agents in 2026 cover where those seams show and why they still break.
Harden authorization
A headless agent with tool access is a target, and the spec's authorization overhaul reflects it. Authorization was tightened across six enhancement proposals, including OAuth built on Client ID Metadata Documents (CIMD). Wrap every endpoint in OAuth or JWT middleware, and sandbox each agent context so a confused-deputy or prompt-injection attack cannot escalate through the tools. The Five Eyes security playbook for agentic AI is a practical checklist here.
Adopt vendor MCP ecosystems
The build-your-own-wrapper era is closing. Vendors now ship their own headless servers. The Salesforce Headless 360 MCP Server beta, announced at TDX 2026 and built on hosted MCP servers that reached GA in April 2026, exposes roughly 100 skills — mostly admin Setup tasks — behind just four tools, with the agent discovering available operations at runtime through a Discover call.
The 2026 pattern follows from that: chain one headless client across several vendor servers — Salesforce, GitHub, PostgreSQL, Slack — instead of hand-rolling an integration per system. One agent, many endpoints. Our take on MCP-first connectors running a business through AI agents pushes the idea to its conclusion.
Key takeaways
- Headless MCP means no chat UI: a stateless server exposes tools, and an autonomous client orchestrates the LLM through cron, webhooks, or scripts.
- The 2026-07-28 spec made the protocol core stateless, added Mcp-Method and Mcp-Name routing headers, and hardened OAuth with Client ID Metadata Documents.
- Streamable HTTP at /mcp is the standard transport; SSE was deprecated April 1, 2026 and is rejected for new registry listings.
- Statelessness enables serverless hosting — Cloudflare Workers without Durable Objects, with Sentry and Linear in production.
- Chain a single client across vendor servers such as Salesforce Headless 360 rather than building custom wrappers.
FAQ
What is the difference between a headless MCP server and a headless MCP client?
The server is a standalone background API that exposes tools and data to an LLM over stateless HTTP; it executes tool calls and returns results, holding no conversation. The client, or host, is the autonomous agent that orchestrates the LLM and the server — it connects, lists tools, and runs the tool-use loop from a script, webhook, or cron job, with no user-facing chat app anywhere in the path.
Should I still use SSE transport for a new MCP server in 2026?
No. SSE was deprecated on April 1, 2026 in favor of stateless Streamable HTTP at the /mcp endpoint. Existing SSE servers still work for backward compatibility, but the next minor version removes the transport and the public MCP registry rejects new SSE-only listings. Build anything new on Streamable HTTP.
What changed in the July 28, 2026 MCP specification?
The core became stateless: the initialize handshake, the Mcp-Session-Id header, and sticky single-instance routing are gone. In their place are Multi Round-Trip Requests that replace stream-dependent elicitations with a resumable requestState, Mcp-Method and Mcp-Name routing headers for proxies and load balancers, OAuth authorization hardened with Client ID Metadata Documents, and a formal, versioned extensions framework with 12-month deprecation windows.
Can a headless MCP server run serverless on Cloudflare Workers or AWS Lambda?
Yes. Statelessness removes sticky sessions and open streams, so a server behaves like any ordinary HTTP workload — it runs on Cloudflare Workers without Durable Objects, and equally on Lambda or a container. Sentry and Linear already run stateless MCP in production, and createMcpHandler now ships in the official MCP TypeScript SDK to make that wiring straightforward.
How do I secure a headless MCP endpoint?
Put every endpoint behind OAuth or JWT middleware using the hardened authorization spec built on Client ID Metadata Documents, and sandbox each agent context so tool access cannot be abused. The main threats to design against are confused-deputy attacks and prompt injection, so scope tokens tightly, isolate credentials per agent, and never let a tool inherit broader permissions than the task requires.
Ready to ship one? Stand up a stateless headless MCP server on Streamable HTTP, then chain a single background client to the vendor endpoints your workflows already depend on — and let the agent do the wiring.