MCP Servers API

Register external MCP servers to extend voice agents with custom tools

MCP Servers API

Register external Model Context Protocol (MCP) servers to make their tools available to voice agents. When users speak naturally, the agent can call your tools automatically.

Base URL: https://api.ferni.ai/api/v2/developers/mcp-servers


Create MCP Server

Register a new MCP server.

POST /mcp-servers

Request Body

{
  "name": "my-crm-tools",
  "description": "CRM integration for customer lookups",
  "transport": "http",
  "endpoint": "https://mcp.yourcompany.com",
  "headers": {
    "X-API-Key": "{{secrets.CRM_API_KEY}}"
  },
  "secrets": {
    "CRM_API_KEY": "your-secret-key-here"
  },
  "autoConnect": true,
  "timeout": 30000
}

Parameters

Field Type Required Description
name string Yes Unique identifier (kebab-case, e.g., my-crm-tools)
description string Yes Human-readable description shown in logs
transport string Yes Connection type: http, websocket, or stdio
endpoint string For http/ws URL of your MCP server
command string For stdio Command to execute
args string[] For stdio Command arguments
headers object No HTTP headers (supports {{secrets.X}} interpolation)
secrets object No Secret values (encrypted at rest with AES-256-GCM)
autoConnect boolean No Connect on agent startup (default: true)
timeout number No Connection timeout in ms (default: 30000)
personaId string No Limit to specific persona (omit for all)

Response

{
  "success": true,
  "data": {
    "id": "mcp_lqx7abc_k3m9",
    "name": "my-crm-tools",
    "description": "CRM integration for customer lookups",
    "status": "active",
    "transport": "http",
    "endpoint": "https://mcp.yourcompany.com",
    "autoConnect": true,
    "enabled": true,
    "toolCount": 0,
    "createdAt": "2026-01-11T10:00:00Z",
    "updatedAt": "2026-01-11T10:00:00Z"
  }
}

cURL Example

curl -X POST https://api.ferni.ai/api/v2/developers/mcp-servers \
  -H "Authorization: Bearer pk_live_xxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-crm-tools",
    "description": "CRM integration",
    "transport": "http",
    "endpoint": "https://mcp.yourcompany.com"
  }'

List MCP Servers

Retrieve all registered MCP servers.

GET /mcp-servers

Query Parameters

Field Type Description
status string Filter by status: active, error, disabled
limit number Max results (default: 50, max: 100)
offset number Pagination offset

Response

{
  "success": true,
  "data": [
    {
      "id": "mcp_lqx7abc_k3m9",
      "name": "my-crm-tools",
      "description": "CRM integration",
      "status": "active",
      "transport": "http",
      "endpoint": "https://mcp.yourcompany.com",
      "autoConnect": true,
      "enabled": true,
      "toolCount": 3,
      "lastConnected": "2026-01-11T10:05:00Z",
      "createdAt": "2026-01-11T10:00:00Z",
      "updatedAt": "2026-01-11T10:00:00Z"
    }
  ],
  "pagination": {
    "total": 1,
    "limit": 50,
    "offset": 0
  }
}

Get MCP Server

Retrieve a specific MCP server by ID.

GET /mcp-servers/:id

Response

{
  "success": true,
  "data": {
    "id": "mcp_lqx7abc_k3m9",
    "name": "my-crm-tools",
    "description": "CRM integration",
    "status": "active",
    "transport": "http",
    "endpoint": "https://mcp.yourcompany.com",
    "headers": {
      "X-API-Key": "{{secrets.CRM_API_KEY}}"
    },
    "autoConnect": true,
    "enabled": true,
    "timeout": 30000,
    "toolCount": 3,
    "lastConnected": "2026-01-11T10:05:00Z",
    "lastError": null,
    "createdAt": "2026-01-11T10:00:00Z",
    "updatedAt": "2026-01-11T10:00:00Z"
  }
}

Note: Secret values are never returned in responses.


Update MCP Server

Update an existing MCP server. Only include fields you want to change.

PUT /mcp-servers/:id

Request Body

{
  "description": "Updated description",
  "timeout": 60000,
  "secrets": {
    "CRM_API_KEY": "new-secret-value"
  }
}

Secrets are merged, not replaced. To remove a secret, set it to null.

Response

{
  "success": true,
  "data": {
    "id": "mcp_lqx7abc_k3m9",
    "name": "my-crm-tools",
    "description": "Updated description",
    "timeout": 60000,
    "updatedAt": "2026-01-11T11:00:00Z"
  }
}

Delete MCP Server

Permanently remove an MCP server.

DELETE /mcp-servers/:id

Response

{
  "success": true,
  "data": {
    "deleted": true,
    "id": "mcp_lqx7abc_k3m9"
  }
}

Test Connection

Test connectivity to your MCP server and discover available tools.

POST /mcp-servers/:id/test

Successful Response

{
  "success": true,
  "data": {
    "connected": true,
    "latencyMs": 145,
    "serverInfo": {
      "name": "my-crm-tools",
      "version": "1.0.0"
    },
    "toolCount": 3,
    "tools": [
      {
        "name": "lookup_customer",
        "description": "Look up a customer by name or ID"
      },
      {
        "name": "create_ticket",
        "description": "Create a support ticket"
      },
      {
        "name": "list_orders",
        "description": "List recent orders for a customer"
      }
    ],
    "testedAt": "2026-01-11T10:05:00Z"
  }
}

Failed Response

{
  "success": true,
  "data": {
    "connected": false,
    "error": "Connection timeout after 30000ms",
    "testedAt": "2026-01-11T10:05:00Z"
  }
}

List Discovered Tools

Get the cached list of tools from an MCP server. Tools are discovered during the test operation.

GET /mcp-servers/:id/tools

Response

{
  "success": true,
  "data": [
    {
      "name": "lookup_customer",
      "description": "Look up a customer by name or ID",
      "inputSchema": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string",
            "description": "Customer name or ID"
          }
        },
        "required": ["query"]
      }
    },
    {
      "name": "create_ticket",
      "description": "Create a support ticket",
      "inputSchema": {
        "type": "object",
        "properties": {
          "subject": { "type": "string" },
          "description": { "type": "string" },
          "priority": { "type": "string", "enum": ["low", "medium", "high"] }
        },
        "required": ["subject", "description"]
      }
    }
  ]
}

Transport Types

HTTP Transport

Most common for production. Your server must expose MCP protocol over HTTP.

{
  "transport": "http",
  "endpoint": "https://mcp.yourcompany.com",
  "headers": {
    "Authorization": "Bearer {{secrets.API_TOKEN}}"
  }
}

WebSocket Transport

For real-time bidirectional communication.

{
  "transport": "websocket",
  "endpoint": "wss://mcp.yourcompany.com/ws"
}

Stdio Transport

For local development or sidecar containers.

{
  "transport": "stdio",
  "command": "node",
  "args": ["./mcp-server.js"]
}

Secret Management

Secrets are stored encrypted and referenced using {{secrets.KEY}} syntax.

Storing Secrets

{
  "headers": {
    "X-API-Key": "{{secrets.MY_API_KEY}}"
  },
  "secrets": {
    "MY_API_KEY": "actual-secret-value"
  }
}

Security

  • Encrypted at rest using AES-256-GCM
  • Never returned in API responses
  • Decrypted only when connecting to your server
  • Rotatable without server restart

Status Values

Status Description
active Server connected and healthy
error Last connection attempt failed
disabled Manually disabled by developer

Error Codes

Code Description
MCP_NAME_EXISTS Server name already registered
MCP_INVALID_ENDPOINT Endpoint URL is malformed
MCP_CONNECTION_FAILED Could not connect to server
MCP_TIMEOUT Connection timed out
MCP_INVALID_RESPONSE Server didn't return valid MCP protocol

Best Practices

  1. Use meaningful namesacme-crm-tools not mcp-1
  2. Store secrets properly — Never hardcode in headers
  3. Test before enabling — Run /test to verify connectivity
  4. Set appropriate timeouts — Increase for slow servers
  5. Monitor tool count — If 0, tools weren't discovered

Related