Part 5 · Scaling the Set

Tool Engineering · ~8 min

MCP Tool Exposure

Everything so far applies to a single tool. MCP is where a server exposes a whole set across hosts — and the first decisions, made before naming or schemas, are whether something should even be a tool.

Why this, for you: the server-side surface. MCP lets you write a tool server once and use it from any compliant host — but that reach means a bad exposure decision is repeated across every agent that connects. This lesson covers the choices unique to the protocol: primitive type, naming for discovery, and structured output.

The Model Context Protocol standardises how agents connect to external tools: the host speaks MCP on one side, your server on the other, and the same server works in Claude Code, Copilot, or Cursor without rewriting. That portability is the point — and the reason a sloppy exposure decision compounds, because every connected agent inherits it.

An MCP server exposes three primitives, and picking the wrong one creates friction before naming or schema design even matters: tools are model-controlled actions, resources are application-attached read-only context, and prompts are user-triggered workflows. Read-only context exposed as a tool wastes a selection decision the agent shouldn't have to make.

1 First decision: tool, resource, or prompt?

PrimitiveControlled byUse when
ToolModel (agent invokes)The agent takes an action or fetches dynamic data — create_issue, search_logs
ResourceApplication (client attaches)Read-only context the agent sees but can't invoke — project config, schema, env info
PromptUser (slash command)A reusable multi-step workflow — /summarize-pr, /deploy-staging

Exposing static project config as a tool forces the agent to decide when to call it; exposing it as a resource lets the client attach it as context with no selection step at all. The primitive choice is the first place an MCP server can make the agent's job easier or harder.

2 Naming for discovery

Tool search matches on names and descriptions — so opaque names cause routing failures, the same search-miss you met in the previous lesson, now at the naming layer. The conventions that hold up:

# Hard to route to query_db_orders · prod_lookup_v2 · doIt # verb_noun, snake_case, no version or abbreviation, ≤32 chars search_customer_orders · list_services · create_issue

snake_case is used by the large majority of public MCP servers; the verb_noun pattern names the action and its object; and descriptions should carry 1–5 realistic examples plus negative guidance — "do NOT use for metrics, use query_metrics instead" — to prevent the misrouting that distinct names alone can't fix.

3 Structured output and the two error channels

An outputSchema lets a server return validated structuredContent the agent can rely on, rather than parsing free text — return both the structured form and serialized JSON for backwards compatibility. And MCP separates errors into two channels with different audiences, a distinction that decides whether the agent can recover:

ChannelAudience & purpose
Protocol error (JSON-RPC code)The client — structural faults: missing params, invalid method. Not the agent's to fix.
Tool execution error (isError: true)The agent — business-logic failures. Should carry actionable feedback the model can self-correct on.

The annotations live here too

This is where you set the readOnlyHint and idempotentHint from Lesson 8, and the destructiveHint the harness may gate on. They're metadata, not trustable from an untrusted server — so set them honestly on your own server and audit them on others. Exposure isn't only the shape of the call; it's the promises the call advertises about its effects.

The server-side checklist that falls out: verb_noun names, every parameter described with constraints and an example, enums and defaults wherever possible, descriptions that say when not to call, errors that carry the constraint and recovery context, read-only context as resources, and a tool list kept small enough to stay discoverable.

↪ Your win: expose the server so any host reads it right

Retrieval practice — recall, don't peek

Question 1Read-only context the agent should see but never invoke belongs as an MCP…

Question 2The recommended MCP tool-naming pattern is…

Question 3An isError: true tool execution error is meant for the…

Question 4Distinct tool names alone won't stop misrouting; the description also needs…

Question 5 · spaced recall from Lesson 09To keep selection sharp on a large catalog, you eager-load…

Ask me anything. Want to run the server-design checklist against an MCP server you're building, or work through whether a capability should be a tool, a resource, or a prompt? Next, the final content lesson: Tool-Call Cost & Latency Budgeting — pricing the whole toolset as a line item, not just shaping one call.
✎ Feedback