Skip to content

First MCP server tool design

Building an MCP server is mostly an API design problem with one extra constraint: the caller is a model, not a person. Naming and arguments matter more than transport.

Published02 May 2026

Updated

Read time3 min · 528 words

Tool focusMCP, Anthropic, Claude Code

The first time you build a Model Context Protocol server, the tempting move is to start from the transport. Should it be stdio? HTTP? SSE? The answer matters, but not yet. Long before transport, the question is what your tool surface looks like to the caller — and the caller is a language model, not a developer.

Name tools the way you would name buttons

A model picks a tool by reading its name and description. That is the entire interface. So the naming has to be unambiguous in isolation. search_documents is a fine name. query is not — it could mean anything.

A good test: if you stripped your server down to a list of tool names with no descriptions, would a model reading them know which to call for a given task? If the answer is no, the names need work.

Arguments are not for the developer, they are for the model

Argument design follows the same rule. The model reads the argument schema and infers what to fill in. So argument names should describe the meaning of the value, not just the type. customer_id is better than id. published_after_iso8601 is better than date_filter.

Default values are a quiet superpower. Every argument that has a sensible default is one fewer thing the model has to guess. A tool with three arguments and three good defaults will be called correctly far more often than a tool with three required arguments.

Errors are part of the tool surface

When a tool fails, the model reads the error message. So error messages have to be useful as input to the model, not just as log lines for the developer. permission_denied: caller lacks scope read:invoices is something the model can react to. 500 internal server error is not.

A practical pattern is to return errors that name the specific scope, the specific input, or the specific precondition that failed. The model can then either retry with corrected input or escalate cleanly. Both outcomes are better than the silent loop where the model retries the same call with the same input and you wonder why your logs are noisy.

Scopes are the security boundary

Authentication and authorisation on an MCP server are the same problem as on any other API. The agent does not get a parallel identity universe. Per-user scopes apply, audit logs apply, secret rotation applies. The most common failure mode is treating the MCP server as an internal trusted thing that the agent calls on the user's behalf without thinking carefully about whose credentials the agent is actually holding.

A simple rule: if the call would require an OAuth token in a normal API context, it requires one in MCP context too. The transport is just plumbing.

Then choose the transport

Once the tool surface, arguments, errors, and scopes are in good shape, the transport choice is mostly a deployment question. stdio for local single-developer integration. HTTP for shared internal services. SSE where the tool produces a stream the agent should react to. None of these choices fix a poorly designed tool surface, and a well-designed tool surface survives a transport switch later.

Related notes

07 May 2026 · 3 min

Eval suites for codebase-specific agent use

Most AI rollouts skip evals because they feel like overhead. A small, codebase-specific eval suite, built in an afternoon, is the cheapest way to keep model and prompt changes from becoming a vibes call.

22 Apr 2026 · 3 min

Codex on a real repo

Codex is a repo-aware coding agent. Used carelessly it generates churn the team has to clean up. Used with scope and a real review gate, it ships work.

© 2026 Magrathean UK Ltd. All rights reserved.

Registered in England & Wales: Company No. 16955343. Registered Office: 16 Caledonian Court West Street, Watford, WD17 1RY.