The Art of Building Great MCPs

Building good MCPs is an art. You want to minimize wrong tool calls and maximize AI success.

Core Principles

1. Less is More

Don’t expose every API endpoint as an MCP tool. Pick the most important ones. ❌ Bad: 50 similar tools confuse AI
["create_user", "add_user", "new_user", "register_user", "signup_user"]
✅ Good: One clear tool per action
["create_user"]

2. Crystal Clear Descriptions

AI depends on your descriptions to understand when to use tools. ❌ Bad: Vague description
{
  "name": "process_data",
  "description": "Processes data"
}
✅ Good: Specific description
{
  "name": "calculate_tax",
  "description": "Calculate tax amount for a purchase based on item price and location"
}

3. Simple Schemas

Complex input schemas lead to AI errors. ❌ Bad: Nested complexity
{
  "properties": {
    "user": {
      "type": "object",
      "properties": {
        "profile": {
          "type": "object", 
          "properties": {
            "settings": { /* more nesting... */ }
          }
        }
      }
    }
  }
}
✅ Good: Flat and simple
{
  "properties": {
    "user_id": {"type": "string"},
    "email": {"type": "string"},
    "name": {"type": "string"}
  }
}

Tool Design Patterns

Action-Oriented Naming

Use verbs that clearly indicate what happens:
{
  "send_email": "✅ Clear action",
  "email": "❌ Unclear if reading or sending",
  "get_email": "✅ Clear action", 
  "email_data": "❌ What happens to the data?"
}

Consistent Naming Conventions

Pick a pattern and stick to it:
{
  "get_user": "✅ Consistent pattern",
  "create_user": "✅ Consistent pattern",
  "fetchUserData": "❌ Different pattern",
  "user_delete": "❌ Different pattern"
}

Error-Resistant Parameters

Design parameters that are hard to mess up: ❌ Error-prone: Free text that needs parsing
{
  "date": {"type": "string", "description": "Date in any format"}
}
✅ Error-resistant: Structured input
{
  "year": {"type": "integer", "minimum": 2020, "maximum": 2030},
  "month": {"type": "integer", "minimum": 1, "maximum": 12},
  "day": {"type": "integer", "minimum": 1, "maximum": 31}
}

Resource Best Practices

Meaningful URIs

Use URIs that make sense to AI: ✅ Good URIs:
user://profile          # User's profile data
contacts://list         # List of contacts  
calendar://events       # Calendar events
tasks://pending         # Pending tasks
❌ Bad URIs:
resource://1            # What is resource 1?
data://x                # What is x?
api://endpoint          # Too generic

Clear Resource Descriptions

Explain what data the resource contains: ❌ Vague:
{
  "uri": "user://data",
  "description": "User data"
}
✅ Specific:
{
  "uri": "user://profile", 
  "description": "User profile including name, email, preferences, and account settings"
}

Prompt Templates

Use Variables Wisely

Make templates flexible but not complex: ✅ Good template:
Hi {name}, 

Your meeting with {attendee} is scheduled for {date} at {time}.

Best regards,
{sender}
❌ Complex template:
{greeting_type} {name_with_title}, 

{conditional_text_based_on_time_of_day} {meeting_type} with {attendee_list_formatted} is {scheduling_verb} for {date_formatted_long} at {time_with_timezone}.

{closing_based_on_relationship},
{sender_with_signature}

Testing Your Designs

Test with Realistic Prompts

Don’t just test if tools work - test if AI chooses the right tools:
Test prompts:
❌ "Call the send_email function"
✅ "Email John about tomorrow's meeting"
✅ "Let Sarah know I'll be late"  
✅ "Send a thank you note to the client"

Watch for Confusion Patterns

Common signs AI is confused:
  • Wrong tool selection: AI picks similar but wrong tool
  • Missing parameters: AI doesn’t provide required fields
  • Repeated failures: AI keeps trying the same broken approach
  • No tool usage: AI gives up and doesn’t use any tools

Common Mistakes

Mistake #1: Too Many Similar Tools

// ❌ Confusing for AI
["email_send", "send_email", "mail_send", "dispatch_email"]

// ✅ Pick one clear name
["send_email"]

Mistake #2: Boolean Parameters for Actions

// ❌ AI gets confused by booleans
{
  "name": "manage_user",
  "parameters": {
    "create": {"type": "boolean"},
    "delete": {"type": "boolean"}
  }
}

// ✅ Separate tools for separate actions
{
  "create_user": { /* parameters */ },
  "delete_user": { /* parameters */ }
}

Mistake #3: Generic Error Messages

// ❌ Unhelpful for AI
"An error occurred"

// ✅ Specific guidance
"Email address must be valid format (example@domain.com)"

Performance Tips

Optimize for Common Use Cases

Design tools around what users actually ask for: Common request: “Schedule a meeting with John tomorrow at 2pm” ❌ Poor design: Separate tools for each step
1. find_user → get_calendar → check_availability → create_event → send_invite
✅ Good design: One tool for the complete workflow
schedule_meeting(attendee, date, time) → handles all steps internally

Minimize Tool Chains

Long chains of tool calls often fail: ❌ Fragile: 5-step process where any step can fail ✅ Robust: 2-step process with error handling

Quality Checklist

Before deploying your MCP:
  • Tool names clearly indicate actions
  • Descriptions are specific and helpful
  • Parameters use simple types when possible
  • Similar tools have distinct purposes
  • Error messages guide AI toward correct usage
  • Resources have meaningful URIs
  • Prompts use clear variable names
  • Test results show AI picks correct tools
  • Success rate is above 80% in testing

Next Steps