MCP Integration Bug: Tool Function Names Not Properly Exposed

The Issue


Vapi's MCP integration creates a non-existent wrapper function instead of exposing actual MCP server tools, causing "Unknown tool" errors in production calls.

Expected vs Actual Behavior


MCP Server defines:
@mcp.tool
def get_appointment_timeslots(zip_code: str, address: str, city: str): pass

@mcp.tool  
def create_appointment(correlation_id: str, first_name: str, ...): pass


Should expose: get_appointment_timeslots and create_appointment
Vapi exposes: book_appointments (doesn't exist in MCP server)

Production Failure


AI attempted book_appointments 3 times, all failed:
// Request
{"function": {"name": "book_appointments", "arguments": "{\"action\": \"get_appointment_timeslots\", ...}"}}

// Response  
{"result": "[{\"type\": \"text\", \"text\": \"Unknown tool: book_appointments\"}]"}


Customer couldn't book appointment due to this bug.

Root Cause


Vapi incorrectly parses MCP tools/list JSON-RPC responses. Instead of exposing individual tools per the MCP specification, it creates a wrapper that doesn't exist.

Vapi's tool config shows the mismatch:
{
  "function": {"name": "book_appointments"},  // ❌ Fake wrapper
  "metadata": {
    "tools": [
      {"function": {"name": "ngrokfree-get_appointment_timeslots"}},  // ✅ Real tools
      {"function": {"name": "ngrokfree-create_appointment"}}
    ]
  }
}


Comparison


Claude Desktop (works correctly):
  • front-desk-appointment:get_appointment_timeslots ✅
  • front-desk-appointment:create_appointment ✅
## Impact on MCP's Purpose

This bug defeats the entire point of MCP. The protocol exists to expose groups of related tools through a single server, but Vapi's implementation forces developers to create individual tools one-by-one instead of leveraging MCP's server-based tool discovery. This makes MCP integration pointless on Vapi.
Was this page helpful?