mcp-server-design.md
5,5 KB • MD • jun. 18, 2026 06:54
---
name: mcp-server-design
description: Guide for designing effective MCP servers with agent-friendly tools. Use when creating a new MCP server, designing MCP tools, or improving existing MCP server architecture.
---
# MCP Server Design
## Overview
This skill provides best practices for designing MCP (Model Context Protocol) servers that work effectively with LLM agents. The key insight: design for agents, not automation. LLMs are human-like thinkers, not API consumers.
## Core Philosophy
### Design for Agents, Not Automation
Traditional API design optimizes for programmatic access with granular endpoints. MCP tool design should optimize for how LLMs think and reason:
- **LLMs are human-like thinkers**: They understand intent, context, and purpose
- **Tools should be tasks, not endpoints**: Shape tools around what users want to accomplish
- **Reduce cognitive load**: Fewer, more purposeful tools beat many granular ones
### The Three Pillars
1. **Give everything ready**: Provide complete, actionable information
2. **Reduce effort**: Minimize steps needed to accomplish tasks
3. **Reduce paths**: Limit decision branches the LLM must navigate
## Tool Design Principles
### 1. Purpose-Built Tools Over Generic Wrappers
**Anti-pattern**: Wrapping every API endpoint as a tool
```typescript
// Bad: Generic database tools
// src/tools/run-sql.ts
// src/tools/list-tables.ts
// src/tools/describe-table.ts
```
**Best practice**: Design tools around user tasks
```typescript
// Good: Task-oriented tools
// src/tools/prepare-database-migration.ts
import { z } from "zod";
import type { ToolMetadata } from "xmcp";
export const schema = {
description: z.string().describe("What database changes are needed"),
};
export const metadata: ToolMetadata = {
name: "prepare-database-migration",
description: "Design a database change with safety checks and reviewed migration plan",
};
// src/tools/analyze-slow-queries.ts
// src/tools/create-backup.ts
```
### 2. Minimize Tool Count
LLMs struggle with long tool lists. Each additional tool:
- Increases selection confusion
- Adds tokens to every request
- Dilutes the purpose of each tool
**Guidelines**:
- Start with 5-10 core tools
- Add tools only when evals show they're needed
- Combine related operations when sensible
### 3. Name Tools for Purpose, Not Implementation
Tool names guide LLM behavior. The name should describe the task, not the mechanism.
| Instead of... | Use... |
|---------------|--------|
| `post-slack-message` | `notify-team` |
| `run-sql-query` | `analyze-data` |
| `call-api-endpoint` | `check-service-status` |
### 4. Shape Tools Like Tasks
For complex flows, one tool per task beats one tool per step.
**Anti-pattern**: Breaking deployment into atomic operations
```typescript
// Bad: Too many granular tools
// src/tools/create-branch.ts
// src/tools/commit-changes.ts
// src/tools/push-branch.ts
// src/tools/create-pr.ts
// src/tools/run-tests.ts
// src/tools/merge-pr.ts
```
**Best practice**: Single tool for the complete task
```typescript
// src/tools/deploy-changes.ts
import { z } from "zod";
import type { ToolMetadata } from "xmcp";
export const schema = {
description: z.string().describe("What changes are being deployed"),
runTests: z.boolean().default(true).describe("Run test suite first"),
autoMerge: z.boolean().default(false).describe("Auto-merge after tests pass"),
};
export const metadata: ToolMetadata = {
name: "deploy-changes",
description: "Deploy current changes through the complete workflow",
};
export default function deployChanges({ description, runTests, autoMerge }) {
// Handles: branch creation, commit, push, PR, tests, merge
}
```
## Decision Framework
### When to Create a New Tool
Create a new tool when:
- Users frequently ask for this specific capability
- The task has clear boundaries and purpose
- Existing tools can't accomplish it cleanly
- Evals show the LLM selects incorrect tools for this task
Don't create a new tool when:
- An existing tool can handle it with minor parameter changes
- It duplicates functionality (combine instead)
- It's a rare edge case (handle with existing tools + guidance)
### When to Combine Operations
Combine multiple operations into one tool when:
- They're almost always used together
- The intermediate results aren't useful alone
- Splitting them creates unnecessary decision points
Keep operations separate when:
- Users need granular control
- Intermediate results have standalone value
- Combining would create an overly complex tool
### Balancing Granularity
| Granular Tools | Combined Tools |
|----------------|----------------|
| More flexibility | Simpler mental model |
| Higher selection burden | Clearer intent |
| Risk of misuse | Less customizable |
## Quick Reference
### Tool Design Checklist
- [ ] Named for purpose, not implementation
- [ ] Description explains when to use it
- [ ] Parameters have clear descriptions
- [ ] Response includes next steps or context
- [ ] Tested with actual LLM requests
### Red Flags
- More than 15 tools in a single server
- Tools named after HTTP methods or endpoints
- Generic tools that "can do anything"
- Tools that require multiple calls for a single task
## Resources
### references/
- `design-principles.md` - Extended examples, anti-patterns, and real-world case studies
For deeper exploration of these concepts, read the design principles reference document.