AI infrastructure
What Is an MCP Server? Model Context Protocol Guide
An MCP server is a program that exposes tools, data and prompt templates to an AI application through the Model Context Protocol, an open standard for connecting models to external systems. The AI application decides when to call the server. The server does the work and returns the result.
By Jasdeep Bains, SeaGit
·
Key takeaways
- The Model Context Protocol (MCP) is an open protocol that Anthropic introduced on 25 November 2024. It defines how a host application connects to servers that provide context and actions.
- A server exposes three kinds of primitives: tools the model can call, resources the application can read, and prompts users can pick.
- Local servers run as a subprocess and talk over stdio. Remote servers use Streamable HTTP and should use OAuth to authorize callers.
- Treat every tool as an action with real side effects. Scope credentials to the minimum, require confirmation for writes, and never hardcode secrets.
What the Model Context Protocol is
Before MCP, every AI application that wanted to read a database, a ticket queue or a file share had to write its own connector. A connector built for one assistant did not work in another. MCP standardizes that connection. Anthropic published the protocol and its first reference servers on 25 November 2024, and the specification is now maintained in the open at modelcontextprotocol.io.
The protocol does not define what your server does. It defines how a client finds out what a server offers, how it calls those offerings, and how the server reports results and errors. That shared contract is why one server can be used from more than one application.
Host, client and server
MCP names three roles. The host is the AI application the user works in, such as a desktop assistant or an IDE with an agent. The host creates a client for each server it connects to. The client is the connector inside the host that speaks the protocol. The server is the program that provides the capabilities.
One host can hold connections to several servers at once, for example a file server, a calendar server and an internal API server. Each connection has its own client, so one server cannot see the traffic meant for another.
What a server exposes: tools, resources and prompts
An MCP server offers three kinds of primitive. The difference between them is who decides to use them.
- Tools are functions the model can call with arguments, such as create_ticket or run_query. The model chooses when to call a tool, and the host usually asks the user to approve it.
- Resources are read-only data identified by a URI, such as a file or a record. The host or the user chooses which resources to load into context.
- Prompts are reusable message templates that the user selects, often shown as a command in the host interface.
A tool is defined by a name, a description and a JSON Schema for its input. Results come back as a list of content items, and a failed call can set isError so the model sees that it failed. The description matters: the model reads it to decide whether to call the tool, so write it as plain instructions.
Transports: stdio and Streamable HTTP
The current specification defines two standard transports. Clients should support stdio whenever they can.
- stdio: the client starts the server as a child process and exchanges newline-delimited JSON-RPC messages over stdin and stdout. The server may write logs to stderr. Anything else written to stdout breaks the connection, so never print debug output there.
- Streamable HTTP: the server is reachable at one HTTP endpoint. The client POSTs each message, and the server replies with a JSON body or an event stream. A server can assign a session ID in the Mcp-Session-Id header.
The earlier HTTP+SSE transport, from protocol version 2024-11-05, has been replaced by Streamable HTTP. Older tutorials still show two endpoints, one for the event stream and one for POST. New servers should implement Streamable HTTP, and only keep the old endpoints if a legacy client must still connect.
JSON-RPC messages underneath
MCP messages use JSON-RPC 2.0 and must be UTF-8. There are three shapes: requests with an id, responses that echo the id, and notifications that carry no id and expect no reply. A host that wants the tools of a server sends a tools/list request, then a tools/call request for each use.
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get_note","arguments":{"title":"ship"}}}A minimal server in Python
The official Python SDK package is named mcp. Install it with uv, as the build guide shows, then write one file. The type hints and the docstring become the tool schema and description.
uv init notes-mcp && cd notes-mcp
uv add "mcp[cli]"from mcp.server import MCPServer
mcp = MCPServer("notes")
NOTES = {"ship": "Release freeze starts Friday."}
@mcp.tool()
def get_note(title: str) -> str:
"""Return the text of a saved note by its title."""
return NOTES.get(title, "No note with that title.")
if __name__ == "__main__":
mcp.run(transport="stdio")Read-only tools like this one are the safest starting point. Some older articles show a class called FastMCP from a different import path. The SDK API has changed across releases, so check the version you install against the SDK README before you copy an example.
Local servers and remote servers
A local server runs on the same machine as the host, usually over stdio. It can read local files and use credentials stored on that machine. It is simple to start and needs no network setup, but it is only available on the machine it runs on.
A remote server runs somewhere else and is reached over Streamable HTTP. It serves many users from one deployment and keeps credentials on the server side. It also needs TLS, authentication, rate limits and logging, which a local server does not.
A host usually starts a local server from a configuration entry that gives the command, the arguments and any environment variables the server needs. Put the secret values in that environment entry or in a secret manager, not in the server source. The host then owns the process lifecycle: it starts the server when needed and stops it when the session ends.
Security considerations
An MCP server gives a language model the power to act. Most incidents come from three places, and each has a practical control.
- Tool permissions: a tool that writes, deletes or spends money should need explicit user approval in the host. Split read and write tools so a read-only task never gets write access.
- Prompt injection: text in a document, web page or ticket can tell the model to call a tool. Treat tool results as untrusted input, and do not let retrieved content alone authorize an action.
- Credentials: give each server the narrowest scope it needs, use short-lived tokens where you can, and never hardcode secrets in source or in the example config. Read them from the environment or a secret manager.
Validate every argument against its schema and enforce the same authorization checks you would on any API endpoint. The MCP security best practices page lists the threats for remote servers in more detail, including token passthrough and session hijacking.
When to build an MCP server, and when to call an API
Build an MCP server when several AI applications should reach the same capability, or when a person will use a model to drive the tool and needs it discoverable with a description. A server is a good fit for a set of related actions over one system.
- Call the API directly when your own application is the only consumer and the calls are fixed in code. A plain HTTP call is simpler to test and to reason about.
- Build a server when the model should decide which action to take, and you want that action list to travel between hosts without rewriting it.
- Do not wrap an API in MCP only because the trend is there. A thin wrapper adds a process, a schema and an auth layer with no gain if one app calls it.