Tool Naming & Descriptions
Agents discover tools by reading names and descriptions. This is the single highest-leverage thing you can get right.
Why This Matters
When an LLM receives a list of tools, it reads every name and description to decide which one to call. Poor names create ambiguity. Vague descriptions cause the model to guess — or pick the wrong tool entirely. The tool metadata you write is literally the UI for an AI agent.
description field tells agents when to use it. Your inputSchema descriptions tell agents how to call it. Keep these concerns separate.
Tool Naming Rules
The MCP specification defines formal naming constraints. Follow these to ensure compatibility across all clients.
Spec Requirements
- Names SHOULD be 1–128 characters
- Allowed characters:
A-Z,a-z,0-9, underscore_, hyphen-, dot. - No spaces, commas, slashes, or other special characters
- Names are case-sensitive and must be unique within your server
Community Conventions
Analysis of 500+ MCP servers shows strong community consensus:
- snake_case is used by over 90% of servers — treat it as the standard
- ~95% of tool names are multi-word (e.g.,
fetch_forecast, notforecast) - Less than 1% use camelCase, despite JavaScript/TypeScript dominance
- Target 32 characters or fewer for UI readability
Naming Patterns That Work
Start With an Action Verb
Every tool name should begin with a verb that makes the action obvious:
| Prefix | Use For | Examples |
|---|---|---|
get_ | Fetching a single resource | get_user, get_order_status |
list_ | Retrieving multiple items | list_repositories, list_open_issues |
create_ | Creating a new resource | create_ticket, create_branch |
update_ | Modifying an existing resource | update_profile, update_settings |
delete_ | Removing a resource | delete_comment, delete_webhook |
search_ | Querying with filters | search_documents, search_logs |
run_ | Executing a process | run_query, run_migration |
The Service-Action-Resource Pattern
For multi-service environments, prefix with the service name to prevent collisions:
github_create_issueinstead ofcreate_issueslack_send_messageinstead ofsend_messagedb_run_queryinstead ofquery
Dot Notation for Namespacing
The spec supports dots for hierarchical namespacing: admin.tools.list, user.profile.update. Use this when your server has clear domain boundaries.
Names to Avoid
| Bad Name | Problem | Better Name |
|---|---|---|
do_stuff | Too vague | process_payment |
handle | No noun, no specificity | handle_webhook_event |
data | Not a verb, not specific | get_sales_data |
executeActionOnResource | camelCase, too generic | update_resource |
tool1 | Meaningless | validate_email |
Writing Great Descriptions
The description field is the most important piece of metadata on your tool. It is what the LLM reads to decide whether to call your tool or a different one.
The Golden Rules
- 1–2 sentences max. Front-load the critical information.
- Lead with verb + resource. "Create a new Salesforce contact" not "This tool is used for creating contacts in Salesforce."
- Say when to use it, not just what it does. "Search customer orders by email. Use when a user asks about their order history." is better than "Searches orders."
- Don't duplicate schema info. Auth details, pagination, and rate limits belong in the
inputSchema, not the description. - Differentiate from sibling tools. If you have
get_userandsearch_users, the descriptions must make the distinction obvious.
Good vs. Bad Descriptions
| Quality | Example |
|---|---|
| Good | "Read the contents of multiple files simultaneously. More efficient than reading files individually when analyzing or comparing multiple files." |
| Bad | "Reads files." |
| Good | "Update shared drive settings including name, color, and restrictions. Requires drive admin permissions." |
| Bad | "Updates a drive." |
Parameter Descriptions
Every property in your inputSchema should have its own description. This is where you put the detail that helps the agent fill in arguments correctly.
- State the type and constraints: "Customer email address (must be a valid email)"
- Explain expected format: "ISO 8601 date string, e.g. 2026-03-01"
- Clarify optional vs. required behavior: "If omitted, defaults to the last 30 days"
- Use
.describe()in Zod orField(description=...)in Pydantic — don't skip it
Tool Annotations
Since spec version 2025-03-26, tools support behavioral annotations that help clients make safety decisions:
| Annotation | Default | What It Signals |
|---|---|---|
readOnlyHint | false | Tool does not modify the environment |
destructiveHint | true | Tool may perform destructive updates (delete, overwrite) |
idempotentHint | false | Repeated calls with same args have no additional effect |
openWorldHint | true | Tool interacts with external entities (web, APIs) |
These annotations affect real client behavior — ChatGPT, for example, renders tools without readOnlyHint: true as "write" tools that require user confirmation.
Avoiding Name Collisions
When users connect multiple MCP servers, duplicate tool names cause undefined behavior. Protect against this:
- Prefix tools with your service/domain name:
github_search_repos - Never use generic names like
search,query, orrunwithout a qualifier - Some frameworks auto-prefix with the server name (e.g.,
web1___search_web) but don't rely on it
Quick Checklist
- Every tool has a snake_case name starting with a verb
- Names are under 32 characters
- Names use only allowed characters (letters, digits,
_,-,.) - Description is 1–2 sentences, front-loaded with purpose
- Description says when to use the tool, not just what it does
- Every input parameter has its own description
- Tool annotations are set accurately (
readOnlyHint,destructiveHint) - No generic names that could collide with other servers
- Sibling tools have clearly differentiated descriptions
Essential Resources
Official Specification
- Tools — MCP Spec (Stable 2025-06-18)
- Tools — MCP Spec (Draft)
- Tools Concepts Overview
- Build an MCP Server — Official Getting Started
- MCP Inspector — Debugging Tool Metadata
Spec Discussions & Proposals
- SEP-986: Specify Format for Tool Names
- SEP-1382: Documentation Best Practices for MCP Tools
- SEP-1395: Standardization of MCP Name
SDKs & Frameworks
- MCP Python SDK (GitHub)
- MCP TypeScript SDK (GitHub)
- FastMCP — Tools Documentation
- TypeScript SDK API Reference
Guides & Best Practices
- MCP Server Naming Conventions — Data-Driven Analysis (ZazenCodes)
- MCP Tool Descriptions: Overview, Examples & Best Practices (Merge.dev)
- MCP Best Practices — Philipp Schmid
- MCP Best Practices — Peter Steinberger
- Implementing MCP: Tips, Tricks & Pitfalls (Nearform)
- 5 Best Practices for Building MCP Servers (Snyk)
- MCP Best Practices: Architecture & Implementation Guide
- 3 Insider Tips for Using MCP Effectively (Merge.dev)
Deep Dives
- MCP Tool Annotations: Adding Metadata & Context (Marc Nuri)
- Code Execution with MCP: Building Efficient AI Agents (Anthropic)
- Tools for Your LLM: A Deep Dive into MCP (Towards Data Science)
- Fixing MCP Tool Name Collisions (LetsDo DevOps)
- RAG-MCP: Mitigating Prompt Bloat via Retrieval-Augmented Generation (arXiv)
- How LLMs Choose the Right MCP Tools (Medium)
- How We Built the Microsoft Learn MCP Server (Microsoft)