Direct answer

Write MCP tool descriptions as routing instructions for the model at the moment it decides what to call. A good description states the action, the right use cases, the wrong use cases, safety boundary, and the arguments that matter. Names, schemas, annotations and approval policy must agree with the description, because the agent uses all of them as one tool-selection surface.

Start With The Model's Choice

An MCP tool description is read inside a live decision, not inside your API docs. The client discovers tools with tools/list, receives each tool's name, optional title, description, inputSchema and optional annotations, then the model chooses whether to send a tools/call request. If the description only says Search records, the model has to infer the system, resource, freshness, permissions and failure mode from the user's prompt.

Write the first sentence as the positive route: what this tool does and when it is the correct first call. Write the second sentence as the boundary: what nearby tasks belong somewhere else. For example, Search Linear issues in the product workspace by text, label, assignee or status. Use for issue triage and sprint planning; do not use for code search or customer email lookup. That gives the model a service, resource, query shape and exclusions.

The description should not repeat implementation trivia. A model rarely needs to know that the tool wraps GET /v1/search or that the upstream SDK class is IssueClient. It needs the human task boundary. If the operation is expensive, stale, partial or scoped to one workspace, say that plainly before the model spends a call.

Make The Name Carry The First Hint

MCP names are unique within a server, case-sensitive in practice, and should use a limited ASCII character set with no spaces. That makes the name compact context. Do not waste it on generic verbs like search, get or run when the agent is choosing among many systems. Prefer linear_search_issues, github_search_code, stripe_get_invoice or postgres_query_readonly. The prefix says where the call goes; the suffix says what kind of work it performs.

Namespacing matters more when multiple MCP servers are aggregated. The MCP spec notes that uniqueness is scoped to a single server, so clients or proxies that combine tools may need a disambiguation strategy. A model looking at two tools named search has to read more text before it can act. A model looking at notion_search_pages and github_search_code gets the first branch for free.

Keep the name and description in the same abstraction level. A tool named delete_user with a description that says Deactivate an account creates hesitation and sometimes unsafe optimism. If the upstream performs a soft delete, name it deactivate_user. If it permanently removes a row, say delete_user_permanently and mention irreversibility.

Put Argument Meaning In The Schema

The input schema is part of the tool description surface. MCP uses JSON Schema for inputSchema, and each property can carry its own description. Use that space for accepted identifiers, date formats, whether a query searches titles only or full text, and whether omitted fields broaden or narrow the result.

{
  "name": "linear_search_issues",
  "description": "Search Linear issues in the product workspace. Use for issue triage, roadmap questions and sprint planning; do not use for code search or customer email.",
  "inputSchema": {
    "type": "object",
    "additionalProperties": false,
    "properties": {
      "query": {
        "type": "string",
        "description": "Natural-language or Linear filter query, such as 'label:bug status:triage auth redirect'."
      },
      "limit": {
        "type": "integer",
        "description": "Maximum issues to return. Use 10 unless the user asks for a broader scan.",
        "minimum": 1,
        "maximum": 50
      }
    },
    "required": ["query"]
  }
}

This schema tells the model how to call the tool without discovering the contract by trial and error. additionalProperties: false also says the model should not invent fields such as teamId or createdAfter. If a parameter accepts an enum, put the enum in the schema. If a no-argument tool exists, use an explicit empty-object schema so the model does not infer hidden options.

Do not overload one argument with several meanings. A field named id_or_email_or_slug invites guesses. Split it into separate tools or separate optional fields with clear descriptions.

Describe Risk Without Pretending It Enforces Risk

Descriptions should say what can change, but they are not authorization. MCP tool annotations add a risk vocabulary such as readOnlyHint, destructiveHint, idempotentHint and openWorldHint. Those hints help clients shape confirmation prompts and retry behavior, but the protocol treats annotations from untrusted servers as untrusted. If deleting a ticket must require approval, put that requirement in client policy, server authorization or both. Do not hope the model will infer it from a cautious adjective.

Still, the description should agree with the hint. A read-only tool can say Returns matching invoices and never creates, updates or sends invoices. A write tool can say Creates a draft invoice but does not send it. A dangerous tool can say Permanently cancels the subscription immediately; use only when the user explicitly asks to cancel now. These sentences help the model choose among read, draft and commit tools before any confirmation dialog appears.

Separate tools by risk level whenever possible. preview_invoice_change and apply_invoice_change are easier for an agent to use safely than one update_invoice tool with a dryRun boolean. The preview tool can be marked read-only and return a proposed diff. The apply tool can require a specific change id from the preview result. That design makes the safe path obvious and gives the approval UI concrete arguments to show the user.

Test Descriptions With Failure Prompts

You cannot inspect a tool description once and know it works. Build a small routing suite with prompts that are deliberately close together: Find the PR that changed login redirect, Find the issue about login redirect, Find the customer email about login redirect. The expected calls should be different. If the agent uses one search tool for all three, the tool names or descriptions are not drawing real boundaries.

Also test negative prompts. Ask for a destructive action while only the read tool is available. Ask for code search when only issue search is available. Ask for a broad export when the tool returns at most 50 rows. Good descriptions help the model stop, ask for a different source, or explain the limit instead of forcing a bad call. Anthropic's tool-writing guidance points out that agents can call the wrong tool, call the right tool with wrong parameters, call too few tools, or mishandle responses; your tests should catch each mode.

Use transcripts as source material. When an agent searches invoices for a support conversation or passes an internal id where the schema asked for an email, patch the tool surface that caused the mistake. The best changes are usually small: one exclusion, one example query, one clearer parameter name, or one split between read and write tools.

Keep big workspaces navigable

When a workspace has dozens of connected systems, even excellent descriptions can become too much context. That is where source-level discovery helps. The agent should first see a compact catalog such as github, linear, stripe, postgres_reporting and google_drive_board_docs, then open the source that matches the task. The sibling articles on lazy tool loading and namespacing tools across servers cover that architecture in detail; for description writing, the important rule is that source descriptions and tool descriptions must use the same boundaries.

In SPYN3, upstream descriptions reach the agent unchanged, and the reply to enable_toolset repeats each opened tool with its arguments and the start of its description. The agent reads the descriptions at the moment it has chosen a source, which is when they matter. Read and write access is a separate grant on the key, so a description that undersells a tool's effects cannot widen what the key may call.

A Short Review Checklist

  • Name: Does it identify the source and resource, not just the verb?
  • First sentence: Would the model know the right user request for this tool?
  • Exclusions: Does it name adjacent tasks that belong to another tool?
  • Schema: Are important formats, limits and enums visible in argument descriptions?
  • Risk: Do wording, annotations and approval policy agree?
  • Evaluation: Do close-neighbor prompts route to different tools for the right reasons?

If one of those answers is no, fix the tool surface before adding more prompt text around it. The model chooses from what the client gives it. Clear names, specific descriptions, tight schemas and honest risk boundaries make the correct call the path of least resistance.

Built for the next step

Write for selection

Make each tool description explain when to use it and when to avoid it.

Use the worksheet
About SPYN3

SPYN3 is a consolidated MCP layer: one hosted endpoint in front of every system you connect — MCP servers, Postgres, REST APIs, Google Drive — with tools foldered by source and read/write permissions per key. Switching agents means moving one URL. Free plan available; current capabilities are documented on the product facts page.

Sources

  1. MCP specification: tools — tool discovery, invocation and security considerations. Verified 14 Oct 2026
  2. MCP project: tool annotations — risk hints and their enforcement limits. Verified 14 Oct 2026
  3. Anthropic: writing effective tools for agents — namespacing, response design and tool evaluations. Verified 14 Oct 2026
  4. OpenAI API: MCP servers and connectors — remote MCP servers, deferred loading, approvals and risks. Verified 14 Oct 2026