Protocols · LLM Agents
MCP, OpenAPI, and the Missing Runtime Layer
Model Context Protocol is not useful because API calls are hard. It becomes useful when many LLM hosts need to discover, invoke, constrain, and audit many external tool servers through one runtime contract.
Key takeaways
- A direct HTTP call is still the right answer for one script talking to one service.
- OpenAPI describes an HTTP API; MCP defines how an LLM host discovers and invokes capabilities at runtime.
- The MCP Client is an adapter inside the host. The MCP Server is the external executor that owns the downstream credentials and business logic.
- A good MCP Server curates tools. It should not mirror every endpoint of the underlying API.
- MCP standardizes the call contract, not trust. Security, filtering, audit, retries, and rollback remain architecture work.
I Start from a plain requests call
You have a language model and a service: weather, a task tracker, a database. You want the model to use that service, not merely talk about it. The first honest answer is that a direct HTTP request is often enough.
If the model says “I need the weather in London”, your code can call the weather API with requests, return the result to the model, and stop there. No MCP Server is required. Wrapping that one call in MCP adds a layer without an architectural reason.
The need appears when the caller is not your script, the host is not under your control, and the same external capability must be discovered and invoked by many independent runtimes.
II Protocol is the rulebook; server is the executor
A protocol is a set of rules: method names such as tools/list and tools/call, fields of a tool descriptor, response shape, error shape, lifecycle. Rules do not execute anything.
An MCP Server is a concrete program. It receives a protocol message, maps it to downstream work, calls the real API, handles credentials and errors, and returns a result. The protocol is one; servers are many.
This resolves the common question “why many servers if there is one protocol?” HTTP is one protocol too, but the world contains many web servers. The protocol defines how to speak; the server does the work.
III What MCP adds above OpenAPI
MCP does not replace OpenAPI. They live at different layers. OpenAPI describes endpoints, parameters, schemas, and responses. MCP defines a runtime contract by which an LLM host discovers available capabilities and invokes them in a standard form.
Static descriptions are useful, but someone still has to execute the call, handle auth, normalize errors, and keep the model from seeing unnecessary surface area. MCP adds runtime discovery, execution, bidirectional primitives, and one invocation shape across servers.
In practice the layers compose: an MCP Server can be generated from an OpenAPI spec and then curated into a smaller, safer tool catalog.
IV Who is who in one call
The Host is the application that contains the model and orchestrates the conversation: a desktop assistant, an IDE, an internal agent platform. The model lives inside the host.
The MCP Client is not the end-user app. It is the adapter inside the host. A host normally creates one MCP Client connection per server.
The MCP Server is the external executor: the wrapped service boundary. The model does not call it directly and does not need the service token. The host asks; the server executes.
V What actually moves on the wire
MCP uses JSON-RPC 2.0. For the core loop you only need to understand three messages: initialize, tools/list, and tools/call. The full specification also covers lifecycle, capability negotiation, transports, resources, prompts, authorization, sessions, and errors.
Tools are actions. Resources are read-only data addressed by URIs. Prompts are reusable templates. Keeping those concepts separate matters: reading a document is not the same boundary as asking a server to mutate something.
Integration approaches compared
Pros
Cons
VI The server is a curator, not a mirror
A weak MCP Server exposes the underlying API one endpoint at a time. A useful server designs a smaller tool catalog for the model: names are task-oriented, input schemas are tight, unsafe actions are absent unless deliberately allowed.
This is where the integration becomes architecture. A read-only server for analysis, a CI-focused server, and a write-capable automation server can all sit over the same GitHub API, with different scopes and different tool names.
Namespacing is practical hygiene. If two servers expose a generic search tool, the host can confuse intent. Names such as github_read_search and github_ci_rerun are less pretty, but safer.
Service API
28 endpoints · 14 shown
VII Transport: local process or network service
stdio is the natural transport for local servers. The host starts the server as a child process and communicates through standard input and output. It is fast, local, and easy to isolate with a process, container, or sandbox.
Streamable HTTP is the current transport for remote servers. A single HTTP endpoint accepts client messages; the server can respond with JSON or text/event-stream when progress, multiple messages, or server-to-client notifications are needed.
MCP does not provide a global server registry. The host learns which servers to connect to out of band: mcp.json, environment variables, IDE settings, desktop configuration, or a managed gateway.
VIII When the server asks for a word
The basic shape is client asks, server answers. MCP also defines reverse-direction primitives that matter for agentic workflows.
sampling lets a server ask the host to run something through a model. The server still does not own the model key. It asks the host, and the host decides which model to use, whether to show the prompt, and whether to allow the request.
elicitation lets a server request missing information from the user. That keeps the human in the loop instead of forcing the server to guess.
IX A minimal FastMCP skeleton
A small server can be only a thin layer around an ordinary API client. The point is not that fifteen lines are production-ready; the point is that the center remains a normal API call.
# pip install fastmcp
from fastmcp import FastMCP
mcp = FastMCP("github-reader") # read-only server
@mcp.tool()
def find_issues(repo: str, query: str) -> list:
"""Find issues in a repository by text query."""
try:
return github_api.search_issues(repo, query) # inside: ordinary requests
except github_api.RateLimitError as e:
raise RuntimeError(f"GitHub API rate limit exceeded: {e}") from e
@mcp.tool()
def read_pull_request(repo: str, number: int) -> dict:
"""Read pull request details by number."""
return github_api.get_pr(repo, number)
if __name__ == "__main__":
mcp.run() # stdio by default X Errors and state belong at different levels
A protocol error means the message itself is wrong: unknown method, invalid shape, incompatible version. A tool execution error means the request was valid, but the downstream work failed: rate limit, timeout, upstream 500, invalid repository.
In MCP, protocol failures return JSON-RPC error. Tool execution failures normally return a tools/call result with isError: true and actionable text the model can use.
State needs the same split. Protocol sessions can have lifecycle and negotiation, while long-running workflow state belongs to the Host or Orchestrator: branch names, partial results, retry policy, compensation logic, and user approvals.
XI MCP does not make the system safe for you
MCP is not DLP, IAM, or compliance. If a server can read CRM records, tickets, repositories, or user data, the standard alone does not prevent those records from reaching the model or leaking elsewhere.
The Host controls what context is sent to the model: masking PII, applying workspace policy, and pruning irrelevant output. The MCP Server controls what it returns from downstream systems: smaller payloads, no secrets, no internal fields unless necessary.
Production safety comes from allowlisted tools, least-privilege OAuth scopes, audit logs, confirmation prompts for destructive actions, output sanitization, and rollback design.
XII Short answers to common misunderstandings
Who writes the server? The service vendor, a community maintainer, or your own team for an internal service. Several servers can coexist for one service.
Why a server, not a library? A library is language-bound and runs in the host process. A server communicates through messages, owns its credentials, can live locally or remotely, and can be updated independently.
Is this just an API call? Mechanically, yes. The new part is standardized self-description and invocation, so an unrelated host can ask what exists and call it without a custom integration for that pair.
XIII Where the ecosystem is going
The direction is toward more remote servers, managed gateways, clearer authorization patterns, and better session behavior behind load balancers and proxies.
The interesting work is less about the metaphor and more about operational details: horizontal scaling, stateless operation where appropriate, middleware patterns, auditability, and safe tool curation.
XIV What MCP does not solve
MCP reduces integration complexity, but it does not remove system design. It does not decide which tools are safe, what data can be sent to a model, how retries work, how to resume a long workflow, or how to roll back a partially completed business operation.
In one line: MCP standardizes the call contract, not trust.
FAQ
Does MCP replace OpenAPI?
No. OpenAPI describes HTTP APIs. MCP defines a runtime contract for LLM hosts to discover and invoke capabilities.
When is MCP unnecessary?
When one script talks to one service and you control both sides. A direct HTTP call is simpler.
What is an MCP Client?
An adapter inside the host. It is not the end-user application.
What is an MCP Server?
An external executor that exposes curated tools and calls downstream systems.
Does MCP solve security?
No. It standardizes calls; security still requires least privilege, audit, filtering, and approval paths.