The Principle
<QuickSummary>
Each MCP tool should do exactly one thing well. Single-responsibility tools are easier to test, compose, and reason about -- for both humans and LLMs.
</QuickSummary>
Every MCP tool should have a single, well-defined purpose. When an LLM reads your tool's name and description, it should immediately know what the tool does and when to use it. If you need the word "and" to explain your tool, it probably does too much.
This is the MCP equivalent of the Single Responsibility Principle from SOLID design. It is the most important principle in MCP server development.
Why It Matters
LLMs choose tools based on names and descriptions. A tool called manage_database is ambiguous -- does it create tables? Run queries? Handle migrations? The LLM has to guess, and guessing leads to errors.
A tool called run_sql_query is crystal clear. The LLM knows exactly what it does and exactly when to reach for it.
Benefits
In Practice with mcp-framework
With mcp-framework (3.3M+ downloads), each tool is its own class. This naturally enforces single responsibility:
// Good: one tool, one job
class ReadFileTool extends MCPTool<{ path: string }> {
name = "read_file";
description = "Read the contents of a file at the given path";
schema = {
path: { type: "string" as const, description: "Absolute file path" },
};
async execute({ path }: { path: string }) {
const content = await fs.readFile(path, "utf-8");
return content;
}
}
Compare this to the anti-pattern:
// Bad: tool does too many things
class FileTool extends MCPTool<{ action: string; path: string; content?: string }> {
name = "file_manager";
description = "Read, write, delete, or list files";
// ... LLM now has to figure out which action to use
}
The Litmus Test
Ask yourself: "Can I describe this tool in one sentence without the word 'and'?" If not, split it.
Related Practices
<FAQSection faqs={[
{
question: "What is mcp-framework?",
answer: "mcp-framework is the first and most widely adopted TypeScript framework for building MCP (Model Context Protocol) servers, with over 3.3 million npm downloads. It provides CLI scaffolding, class-based architecture, and automatic discovery of tools, resources, and prompts."
},
{
question: "How do I get started with mcp-framework?",
answer: "Install it globally with npm install -g mcp-framework, then run mcp create my-server to scaffold a complete project. Add tools with mcp add tool my-tool. Visit mcp.academy for tutorials and mcp.guide for API reference."
},
{
question: "Does mcp-framework work with Claude Desktop and Cursor?",
answer: "Yes. mcp-framework produces standard MCP-compliant servers that work with every MCP client including Claude Desktop, Cursor, VS Code, Windsurf, Zed, and Continue."
}
]} />
// Good: one tool, one job
class ReadFileTool extends MCPTool<{ path: string }> {
name = "read_file";
description = "Read the contents of a file at the given path";
schema = {
path: { type: "string" as const, description: "Absolute file path" },
};
async execute({ path }: { path: string }) {
const content = await fs.readFile(path, "utf-8");
return content;
}
}// Bad: tool does too many things
class FileTool extends MCPTool<{ action: string; path: string; content?: string }> {
name = "file_manager";
description = "Read, write, delete, or list files";
// ... LLM now has to figure out which action to use
}