Codex vs Claude

What a Tool Protocol Standardises, and What It Leaves to You

David Guzenburg/ / 11 min read

Nine servers attached, two hundred tool definitions in play, and an agent worse at its job than it was with none.

MCPintegrationtoolingcontext

A protocol standardises plumbing, not judgement

The value of a tool-connection standard is easy to state and easy to overstate. It means a server written once works with any client that speaks the protocol, that discovery is uniform, and that you are not writing a bespoke integration per tool per agent. That is a genuine and substantial saving, and it is the whole of what the standard provides.

What it does not standardise is the part that determines whether the integration is any good: what the tools should be, what they should be called, what they return, and how much of your context window they consume. Those decisions are yours, they are design work, and a protocol that makes connection trivial can make it feel as though they have been made for you.

The failure this produces is a session with nine servers attached, two hundred tool definitions in play, and an agent that is worse at its job than it was with none.

Every attached server is a context cost

Start with the mechanical problem, because it is the one people meet first and misdiagnose. Tool definitions occupy context. A server exposing forty tools, each with a description and a parameter schema, is a meaningful fraction of a window before anyone has asked a question.

Modern clients mitigate this by deferring definitions — only names and server instructions load until a tool is actually used — which helps a great deal and does not make the cost zero. The practical consequence stands: attach the servers a task needs, not the ones you might want someday, and check what is actually consuming your window rather than guessing.

Prefer the command-line tool where one exists

A conclusion that surprises people who have just set up their first server. For a great many integrations — version control hosts, cloud providers, issue trackers, error monitoring — a well-designed command-line tool is already installed, already authenticated, and already documented, and it costs nothing in context because the agent invokes it through the shell it already has.

A protocol server earns its complexity when the integration is stateful, when discovery genuinely matters, when the data is not naturally text-shaped, or when several different surfaces need the same connection. "Wrap a command-line tool the agent could have run directly" is not on that list, and it is a substantial share of what exists.

The test

If a competent engineer would have used a CLI to do this by hand, the agent probably should too. Protocols are for the things a shell command cannot express.

Tool descriptions are prompt engineering, and they are somebody else's

Every attached server contributes text that goes into your agent's context and shapes its behaviour. That text was written by whoever wrote the server, with their idea of when their tools should be used, and it competes with your own instructions.

Mostly this is benign and occasionally it is not: a description that oversells its tool's applicability will pull the agent toward it in situations where something else was appropriate. And in the adversarial case it is an injection surface, which is the subject of prompt injection through tool descriptions.

Read the descriptions of anything you attach. They are short, they are the actual interface, and the README is not a substitute for them.

What a good tool looks like

Since the protocol will not tell you, it is worth stating. A good tool does one thing, has a name that says what that thing is in your domain's vocabulary, takes few parameters, and returns a compact result rather than a dump.

The return value is where most tools fail. A query tool that returns four thousand rows has not helped the agent; it has moved a problem into the context window. A tool that returns the first fifty rows, the total count, and a note about how to narrow the query is dramatically more useful, and the difference is design rather than protocol.

Granularity is the hard design decision

Too fine and the agent needs six calls to accomplish anything, each round trip adding latency and context. Too coarse and you have one tool with fourteen parameters that the agent gets wrong in a different way each time.

The heuristic that works: a tool should correspond to a thing a person would ask for. "Find the issues assigned to me that are blocked" is a task; "list issues", "filter by assignee", "filter by status" are steps in an implementation. Model the tasks.

Errors are context, so write them for a reader

An underrated design surface. When a tool fails, its error message goes into the agent's context and becomes the basis for what it tries next. A message saying 400 Bad Request produces a retry loop. A message saying the "status" parameter must be one of: open, closed, merged — you sent "in progress" produces a correct second call.

This is the cheapest quality improvement available in a tool server and it is almost universally neglected, because errors are written for logs rather than for the thing that will read them.

Read-only by default

A design principle worth adopting across every server you write or attach. Reading is recoverable, writing is not, and the two do not need to live in the same server.

Splitting them means the read server can be attached freely while the write server is attached only for tasks that need it, which is a far better default than one server with a mix of capabilities and a permission rule trying to sort them out afterwards. It also makes the audit question trivial: a session with only the read server attached could not have changed anything.

Authentication is where the abstraction leaks

The protocol standardises how tools are described and called. It does considerably less to standardise how a server gets the credential it needs, which in practice means an environment variable, a token file, or an interactive flow, all with different lifetimes and different blast radii.

So each server you attach is a separate credential decision, and the uniform interface makes them feel like one. Ask, per server: what can this credential do, where does it live, and how would I revoke it. The answers vary more than the tool list suggests, and they are covered more fully in credential boundaries for agents.

Versions move underneath you

A server is a dependency in the hot path of your agent's behaviour, and an unpinned one can change what your tools do between Tuesday and Wednesday. A renamed parameter, a changed default, a broadened description — none of which appear in your repository's diff.

Pin versions. Review upgrades, at least to the extent of reading the changed tool descriptions. And be aware that this is a supply-chain surface with a shorter feedback loop than most, because a bad server version affects behaviour immediately rather than at build time — the review process for one is in reviewing third-party MCP servers.

Where the standard genuinely earns its keep

Connecting an agent to something that has no command-line interface and no text representation: a design tool's document model, a proprietary internal system, a database's live schema, an observability platform's query API. Those are cases where a bespoke integration was the alternative, and a standard interface is unambiguously better.

It also earns its keep across surfaces. One server serving a terminal agent, an editor extension and a hosted runner is the case the standard was designed for, and it is a real saving over three integrations.

Build your own before you attach three more

The most valuable server most teams could have is one nobody else can write: a small one exposing four tools over your own systems. Look up a customer by identifier in the internal admin API. Fetch the deploy history for a service. Query the feature flag state. Read the runbook for an alert.

Those are the things an agent cannot get from a shell command or a generic integration, they are the things that make it useful in your environment specifically, and they take an afternoon. Attaching four third-party servers takes ten minutes and mostly gives you capabilities the shell already had.

Instructions from a server are still instructions

A subtlety worth being explicit about. Servers can supply not only tool descriptions but general instructions that load into context, and those sit alongside your repository's own guidance with no visual distinction in the agent's view of the world.

So an attached server is, in a small way, co-authoring your agent's system prompt. That is fine when you have read what it says and chose it. It is not fine as a thing that happens by default across nine servers, and the reason it goes unnoticed is that everything works — the agent behaves slightly differently from how your instructions specify, and nobody attributes it to a dependency.

Measure before and after attaching

The practical habit that catches all of the above. Run a representative task before attaching a server and after, and compare: context consumed, tool calls made, and whether the agent used the new tools when it should have and left them alone when it should not.

Half the time the answer is that the server helped. The other half it did nothing except consume window, or it pulled the agent toward its tools for tasks that did not need them. Both outcomes are worth knowing, and neither is visible without the comparison — which is why most people's server list only ever grows.

Servers are easier to add than to remove

The last structural point. Adding one is a config line and an immediate capability. Removing one requires knowing that nothing depends on it, which nobody tracks, so the default is accumulation.

A quarterly pass over the list, asking of each server when it was last actually used, keeps the set honest. The answer for at least one of them will be "never since the week I set it up", and removing it is free performance and one less dependency in the hot path of everything the agent does.

The summary I would give a team adopting this: the protocol removed the integration tax, which was real, and it did not remove the design work, which is where the value was. Budget accordingly. An afternoon spent designing four good tools over your own systems beats a week spent attaching other people's.

The failure mode of a good abstraction

A closing observation about why this article had to be written at all. When integration becomes uniform, integrations stop feeling like decisions. Attaching a server is one line, so it gets the consideration a one-line change gets, which is none.

That is the cost of a good abstraction: it hides the thing it abstracts, including the parts you should have thought about. The corrective is not to avoid the abstraction but to keep a checklist for the moments it makes frictionless — what does this add to context, what credential does it need, what do its descriptions say, who publishes it. Four questions, thirty seconds, and they restore the deliberation the one-line change removed.

If you want one action from this: open your configuration, list the servers attached, and for each one write a sentence saying what it does that a shell command could not. The ones where you cannot write the sentence are the ones consuming context for nothing, and removing them is the cheapest improvement available to any agent setup that has been running for more than a few months.

Takeaway

A tool protocol standardises connection and discovery, and leaves every decision that determines quality — which tools, what they return, how errors read — with you. Attach only what a task needs, prefer an existing command-line tool where one exists, read the tool descriptions because they are prompt text you did not write, split read from write servers, pin versions, and write error messages for the agent that will read them. Then spend the afternoon building the small server over your own systems that nobody else can.

Keep reading
Codex vs Claude

Image Generation Through MCP: A Credential, an Egress Path and a Spend Line

Attaching an image server to an agent adds four things at once. Constraining the write path, capping the spend, caching on a prompt hash, and why a shell script often beats a protocol.

Tooling & Integration

Building a Local MCP Server: Exposing What the Filesystem Cannot Answer

A working TypeScript MCP server over stdio, why the tool description decides whether it is ever called, returning errors the model can read, and the read-only role to create before it runs.

Tooling & Integration

Giving Claude a Second Opinion: Connecting Gemini Through a Local MCP Server

A working walkthrough for wiring another model into Claude Code as a tool: the server code, the registration command, the flag ordering that breaks it, and why the context parameter is the part people get wrong.

Codex vs Claude

Reading the Design File: Precise Values Are Not the Same as Tokens

Connecting an agent to the design tool replaces measured pixels with read properties, and the benefit depends entirely on whether the file's variable names map to your code's tokens. The mapping manifest, generating from variables rather than frames, and pulling through a reviewed pull request.

← Default-Deny Egress: The Control You Turn Off in the First Hour  ·  Local Machine or Managed Container: The Difference That Actually Survives →

All codex vs claude articles  ·  Every article