My MCP design process has been evolving. Here’s where it is today.
The Core Problem
LLMs are stateless. After each response, they lose all context. Most MCP servers assume the model remembers prior calls - this breaks constantly.
Typical broken pattern:
| |
The model can’t maintain this workflow. Each tool call is a fresh start.
What Works
The MCP servers I’ve studied - GitHub, Figma, PostgreSQL - don’t chain operations. They provide complete, self-contained workflows.
Figma MCP approach:
create_design(requirements)- Handles auth + creation + returns complete resultanalyze_layout(url)- Extracts all design data in one callmodify_component(url, changes)- Finds, modifies, and confirms changes
Each tool accomplishes a complete user intent, not a technical operation.
PostgreSQL MCP approach:
analyze_performance(connection, query)- Connects, analyzes, returns actionable insights- No separate auth, connection, or query tools needed
Three Design Principles
1. Make Each Tool Self-Contained
Every tool must work independently. Don’t assume the model “remembers” anything.
Bad: get_user_by_id(id) (requires prior authentication)
Good: get_user_data(connection_string, user_id) (self-contained)
2. Responses Are Prompts
Your tool responses guide the model’s next action. Don’t just return data—provide context and suggestions.
Bad response:
| |
Good response:
| |
3. Design for Intent, Not Operations
Group related functionality around what users actually want to accomplish.
API thinking: separate tools for auth, list, create, update, delete MCP thinking: tools for “provision new user,” “audit permissions,” “migrate data”
My Checklist
For my MCP implementations, I check:
- Self-contained? - Each tool works independently without prior context
- Response teaches? - Errors include suggestions, not just codes
- Grouped by intent? - Tools match user goals, not technical operations
- Tested across models? - What works for Opus might confuse Haiku
This works for my MCP designs. Adjust for your model and use case.
