What is an MCP server?
An MCP server is a program that offers tools, data and prompt templates to an AI application over the Model Context Protocol, an open standard for connecting models to outside systems. The AI application runs an MCP client, asks the server which tools it has, and calls them on the model's behalf. One server works with any client that speaks the protocol, so a tool written once can be used from many different AI applications.
Checked against current documentation on 30 September 2026.
The Model Context Protocol
Anthropic introduced the Model Context Protocol in 2024. On 9 December 2025 it announced that it was donating the protocol to the Linux Foundation's new Agentic AI Foundation. The project's own governance page describes a group of maintainers, led by two lead maintainers, who make the technical decisions and take changes through written proposals.
The current specification revision is dated 28 July 2026, and it is the one the specification's "latest" address serves as of 30 September 2026. Earlier revisions still exist, and many servers in the wild speak them. The transports section below covers what that means for you.
The protocol names three roles. A host is the AI application a person uses. A client is the connector inside the host that talks to one server. A server is the program that offers capabilities. Messages between client and server are JSON-RPC 2.0, a plain request and response format built on JSON.
A server can offer three kinds of thing. Tools are functions the model can call, such as creating a database or reading a log. Resources are context and data, for the person or the model to use. Prompts are templated messages for a person to pick from. Most servers people build are mostly tools.
How a tool call works
A client finds out what a server can do by sending tools/list. The server replies with each tool's name, a description written for the model, and a JSON Schema for its arguments. The model reads those descriptions and decides which tool suits the task.
When the model picks one, the client sends tools/call with the tool's name and its arguments. The server runs it and returns content the model can read. A tool can also declare an output schema, and then it returns structured JSON that matches it alongside the text.
POST /mcp HTTP/1.1
Content-Type: application/json
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: whoami
{ "jsonrpc": "2.0", "id": 2, "method": "tools/call",
"params": { "name": "whoami", "arguments": {},
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": { "name": "ExampleClient", "version": "1.0.0" },
"io.modelcontextprotocol/clientCapabilities": {} } } }Note the headers. In this revision every request carries its own protocol version and client capabilities, and Streamable HTTP mirrors the method and tool name into headers so a load balancer can route without reading the body. A server must reject a request whose headers and body disagree.
Errors come back two ways. A malformed request or an unknown tool is a protocol error, a standard JSON-RPC error. A tool that ran and failed, say because a date was in the past, returns a normal result marked isError, with text the model can read and correct from. The specification says clients should pass those tool errors to the model so it can retry. Good servers put the fix in that text.
{ "jsonrpc": "2.0", "id": 4,
"result": { "resultType": "complete", "isError": true,
"content": [{ "type": "text",
"text": "Invalid departure date: must be in the future. Current date is 08/08/2025." }] } }Transports: stdio and Streamable HTTP
| Transport | How it works | Use it for | Status |
|---|---|---|---|
| stdio | The client launches the server as a subprocess. Newline-delimited messages over standard input and output. | Local tools on the same machine | Standard |
| Streamable HTTP | Each message is an HTTP POST to one endpoint. The reply is a JSON object or a stream scoped to that request. | Hosted servers, reached by URL | Standard |
| HTTP with SSE | The 2024-11-05 design with separate stream and POST endpoints. | Only to talk to old servers | Deprecated |
The 2026-07-28 revision removed protocol-level sessions and the standalone GET stream from Streamable HTTP. Because each request stands alone, a hosted server can sit behind an ordinary load balancer with no sticky routing. If your server needs state across calls, such as a shopping basket, the specification suggests returning an explicit handle from one tool and taking it as an argument in the next.
Two edge cases catch people out. If a reverse proxy buffers a streamed reply, the client sees nothing until the end, so servers should send X-Accel-Buffering: no. And a local HTTP server that binds to every network interface can be reached from a web page by DNS rebinding. The specification says servers must check the Origin header and should bind to 127.0.0.1 when running locally.
A client that meets an older server falls back. If a request in the new shape gets a 400 that is not a recognised modern error, the client retries with the older initialize handshake. You do not need to do anything, but it explains why one client can talk to servers of different ages.
Building your own: what to decide
You write a server when a model needs to use a system that does not offer one. The official SDKs handle the protocol, so most of the work is design. These are the decisions that matter, in order.
- 1Pick a few tools, not all of themEvery tool description goes into the model's context. Twenty well-named tools beat two hundred that overlap. Names should be 1 to 128 characters of letters, digits, underscores, hyphens and dots, and unique within your server.
- 2Write descriptions for the modelSay what the tool does, what it costs, and when not to use it. The model chooses from the description alone.
- 3Describe the arguments with JSON SchemaMark required fields and give each a short description. A tool with no arguments should say so with an object schema that allows no properties.
- 4Return errors that teachUse isError for a tool that ran and failed, and say what to change. Save protocol errors for broken requests.
- 5Check who is callingValidate every input, check access on every call and rate limit. The specification lists all three as things servers must do.
- 6Test with a real clientConnect it, read the tool list as the model would, and try to make it choose wrongly. Fix the descriptions, not the model.
For the wider picture of who is building servers and why, see why MCP adoption is growing so fast.
Keeping an MCP server safe
A tool is code the model can run, so the question is what the credential behind it can reach. The specification says tools represent arbitrary code execution and that clients should treat tool annotations as untrusted unless they come from a trusted server. It also treats the tool list as something that can depend on who is asking.
“For trust & safety and security, there SHOULD always be a human in the loop with the ability to deny tool invocations.”
A server may return a different tool list depending on the authorisation on the request, for example only the tools the caller's scopes permit. That is the most useful safety feature the protocol has: a tool the key cannot use is never shown, so the model never tries it. The tool list must not vary from one connection to the next or as a side effect of other requests, only with the credentials sent.
- Give each agent its own key rather than sharing a person's. Revoking it then affects one agent.
- Scope keys to what the task needs. Reading logs and deleting a database should not share a credential.
- Put a spend limit on anything that costs money, checked before the action rather than reported after it.
- Give keys an expiry, so a leaked one stops working on its own.
- Offer a dry run for anything that changes state, so the model can see the consequences before committing. How a dry-run plan works.
- Never return secrets from a tool. A model will repeat what it reads.
- Never mark a password, key or personal detail as a mirrored header parameter. The specification warns that header values are visible to network intermediaries.
Scoped keys are the part most teams get wrong first. Scoped API keys for AI agents goes through how to size them.
Helm7's MCP server
Helm7 is a hosting platform, and its MCP server can do everything its REST API can, because both are generated from one list of operations. Every agent key carries scopes, an optional monthly spend cap and an optional expiry, and tools the key cannot use are left out of tools/list. Every operation that changes infrastructure accepts dry_run and returns a plan with its monthly cost before anything happens. The agents page shows a full session.
{
"mcpServers": {
"helm7": {
"url": "https://www.helm7.com/mcp",
"headers": { "Authorization": "Bearer hlm_sk_..." }
}
}
}An agent can also get a key with no account at all. cloud_init creates a temporary workspace with a small quota and an expiry, so an agent can try the platform end to end and only involve a person when there is something worth keeping. Try it from the quickstart, and see the API reference for the same operations over REST.
Common questions
Is an MCP server the same as an API?
It usually sits in front of one. An API is written for programs whose authors read the documentation. An MCP server describes its tools to a model at run time, in a format every MCP client understands, so the model can find and use them without custom code.
Who maintains the Model Context Protocol?
A group of maintainers, with lead maintainers who make the final calls. Anthropic introduced the protocol in 2024 and announced on 9 December 2025 that it was donating it to the Linux Foundation's Agentic AI Foundation.
Which version of the specification is current?
Revision 2026-07-28 is the one the specification's latest address serves as of 30 September 2026. It made requests stateless and removed protocol-level sessions from Streamable HTTP. Clients fall back to the older initialize handshake when they meet an older server.
Do I need to run an MCP server myself?
Not to use one. Hosted servers like Helm7's are a URL and a key. You write your own when you want a model to use a system that does not offer one.
What is the difference between stdio and Streamable HTTP?
With stdio the client starts the server as a local process and they swap messages over standard input and output. With Streamable HTTP the server runs elsewhere and each message is an HTTP POST to one URL. Use stdio for local tools and Streamable HTTP for anything hosted.
Can an MCP server decide which tools a caller sees?
Yes. The tool list may vary with the authorisation on the request, for example returning only the tools the caller's scopes allow. It may not vary by connection or as a side effect of other requests.