MCP Server Engineering
Every tool you give an agent costs tokens before it asks a single question — so how do you build a server that gives the right capability at the right cost?
This is the builder's view of MCP. If you want to decide which MCP servers to adopt, that is a value-selection job — see the MCP tool radar. This page is how to engineer a server that any client can reuse.
Model Context Protocol standardises how AI models reach external capabilities — databases, APIs, file systems, other tools. Before MCP, every application invented its own integration layer. MCP is the USB-C standard for agent-tool connections: build the server once, use it with any MCP-compatible client.
Architecture
Three roles, one protocol, nested:
Host (Claude Code, Cursor, Claude Desktop)
└── Client (one per server connection)
└── Server (exposes tools/resources/prompts)
└── External system (DB, API, filesystem)
- Host — contains the LLM and manages all client connections (Claude Code, Cursor, Claude Desktop).
- Client — the protocol adapter, one per server, handling transport. Built into the host.
- Server — what you build: it exposes capabilities to the client (Supabase MCP, GitHub MCP, your own).
Connection flow: the host creates a client per configured server → the client connects over its transport → client and server negotiate capabilities in a handshake → the model receives all tool schemas and calls them as it reasons → results flow back through the client into model context.
The Three Primitives
Every server exposes some combination of three capability types. Choosing the right one is the core design decision:
- Tools — functions the model calls (search, query, write, execute). The schema sits in context always; the result arrives only when called. This is the main capability.
- Resources — file-like data the model can read (documents, DB records, configs). Loaded on request; can be large.
- Prompts — reusable prompt templates with typed arguments. Minimal schema cost; injected on demand.
Tools are the workhorse. Reach for resources when the workflow is read-heavy, and prompts when it is templated.
Token Economics — the design constraint
Loading tools is not free. Research shows MCP tool definitions inflate input tokens by 3× to 236× depending on the toolset [source: arXiv 2508.12566]. Every schema loaded before the first message is tokens unavailable for reasoning. This is the constraint that shapes every server you build:
Session budget = context_window × 0.6 (reserve 40% for reasoning)
MCP overhead = Σ(tool_schema_tokens) + Σ(tool_result_tokens)
Target = schema overhead < 15% of session budget
Design for loading strategy from the start:
- Static (always load) — all schemas in context from turn one. Fine for toolsets of ≤5 tools used every session.
- Dynamic (load on demand) — only the schemas currently needed. Cuts overhead by ~96% on large toolsets [source: Speakeasy].
- Curated profiles — the right tools per role, nothing extra. The recommended approach.
The practical rule you design toward: if a tool isn't in the caller's always-load set, don't make them pay for its schema. Keep tools few, schemas tight, and results field-maskable.
Transports
- stdio — the server runs as a subprocess; the client talks over stdin/stdout. Zero-latency, no networking. Best for local servers (filesystem, CLI tools).
- HTTP + SSE — the server runs as a remote HTTP service; the client connects via SSE. Best for cloud-hosted, shared instances — one server for the whole team.
Why MCP Beats Bespoke Function Calling
Traditional function calling made every application define its own tools — no reuse, no standard security, no dynamic discovery. MCP changes each axis:
- Integration — build once against the protocol instead of per-application custom code.
- Discovery — dynamic capability negotiation instead of a static startup list.
- Security — server-enforced access controls instead of per-integration ad-hoc rules.
- Composability — a shared server ecosystem (2,000+ servers) instead of each agent rebuilding the stack.
- Surface — tools plus resources plus prompts, not tools alone.
The compounding effect: a well-designed server built once works in Claude Code, Cursor, Claude Desktop, and any future client without modification.
How to Apply
- List the capability you're exposing and decide its primitive — tool, resource, or prompt.
- Write the tightest schema that still lets the model call it correctly; every token in the schema is paid on every session.
- Choose a transport: stdio for local, HTTP+SSE for shared/remote.
- Decide loading strategy — static only if ≤5 always-used tools; otherwise dynamic or a curated profile.
- Field-mask results so a call returns only what was asked for.
- Publish so any client can negotiate it.
Proof of done: the server's schema overhead is under ~15% of the session budget, an unfamiliar client can discover and call it from the handshake alone, and no result floods the context window.
Failure Modes
- Schema bloat. Too many tools or verbose schemas eat the reasoning budget before the agent starts.
- Static-loading a large toolset. Every session pays for tools it never calls.
- Unmaskable results. A single query returns a wall of data that blows the window.
- Stateful assumptions over stdio. Treating a subprocess transport like a persistent session.
- Tool ambiguity. Two tools the model can't distinguish → wrong-tool calls at scale.
Changes my mind: if context windows grew cheap and effectively unbounded, token economics would stop governing server design and the discipline here would relax toward "expose everything."
Context
- instance-of Intelligent Hyperlinks — MCP is the third pipe: a standard that lets an agent discover and call a capability
- pairs-with Agent-First CLI Design — a hardened CLI exposes itself through exactly this protocol
- pairs-with AI Harness — the harness carries only the tools it needs; this page keeps each tool cheap enough to carry
- depends-on Agent Protocols — where MCP sits in the broader protocol stack
- applies-to MCP Tool Radar — the selection view that decides which servers earn their token cost
- up Agent Tooling — the engineering hub
Links
- MCP Specification — official protocol documentation
- MCP token research — academic benchmarks on token inflation
- Dynamic toolsets — the 96% reduction approach
Questions
Which server design decision — schema clarity, stateless versus stateful context, or the authentication model — has the most impact on agent reliability at scale?
- At what tool count does a server become too complex for an agent to select the right tool without extra routing logic?
- If dynamic loading cuts token overhead by 96% but adds 2–3× more tool calls, when is static loading still worth it?
- Which of the three primitives is most underused — and what workflow does that gap represent?