From 3ecc73c9b0dbb3b8ec08c2eb5d1b7ff4601d11cc Mon Sep 17 00:00:00 2001 From: Steven Diaz Date: Tue, 10 Nov 2026 21:39:06 -0800 Subject: [PATCH] Document OAuth sign-in for the hosted Vapi MCP server The hosted server at https://mcp.vapi.ai/mcp now signs users in with their Vapi account over OAuth and no longer accepts API keys. Replace the API-key setup for every client with the OAuth flow, and add an FAQ for API keys, organizations, headless use and the removed SSE endpoint. Co-Authored-By: Claude Opus 5.5 --- fern/sdk/mcp-server.mdx | 441 ++++++++++------------------------------ 1 file changed, 103 insertions(+), 338 deletions(-) diff --git a/fern/sdk/mcp-server.mdx b/fern/sdk/mcp-server.mdx index 94d2b74ee..eb3f04879 100644 --- a/fern/sdk/mcp-server.mdx +++ b/fern/sdk/mcp-server.mdx @@ -2,12 +2,12 @@ title: Vapi MCP Server subtitle: Connect Vapi to AI assistants with Model Context Protocol (MCP) slug: sdk/mcp-server -description: Use the Vapi MCP Server to expose Vapi APIs as tools over the Model Context Protocol, managing assistants, phone numbers, and calls from any MCP client. +description: Connect Claude, Codex, Cursor, VS Code and other MCP clients to the hosted Vapi MCP Server, sign in with your Vapi account, and manage assistants, phone numbers, and calls. --- ## Overview -The **Vapi MCP Server** exposes Vapi APIs as tools via the Model Context Protocol (MCP), so you can manage assistants, phone numbers, and calls from any MCP-compatible AI assistant (like Claude Desktop) or agent framework. +The **Vapi MCP Server** exposes Vapi APIs as tools via the Model Context Protocol (MCP), so you can manage assistants, phone numbers, and calls from any MCP-compatible AI assistant (like Claude) or agent framework. Use this server to connect your AI workflows to real-world telephony, automate voice tasks, and build richer conversational agents. @@ -23,76 +23,85 @@ Use this server to connect your AI workflows to real-world telephony, automate v If an earlier CLI release configured `@vapi-ai/mcp-docs-server` in your agent, replace that legacy entry with the hosted connection below. Existing agent configurations are not removed automatically. -Use **Streamable HTTP** at `https://mcp.vapi.ai/mcp` for remote connections. The legacy HTTP+SSE transport is deprecated; migrate existing remote configurations to this endpoint. +## Server URL and sign-in -## Connect your agent +The hosted server uses **Streamable HTTP** at: -Get a [Vapi API key](/security-and-privacy/api-keys), then choose your client. These connections use the hosted server; you do not need to install the Vapi CLI or run a Vapi MCP server locally. +``` +https://mcp.vapi.ai/mcp +``` - - - For the Codex CLI, set your API key and register the remote server: +You sign in with your Vapi account over **OAuth**. There is no API key to copy: - ```bash - export VAPI_API_KEY="YOUR_VAPI_API_KEY" - codex mcp add vapi --url https://mcp.vapi.ai/mcp \ - --bearer-token-env-var VAPI_API_KEY - codex mcp list - ``` + + + Add `https://mcp.vapi.ai/mcp` to your MCP client using the instructions for your client below. + + + Your client opens a browser window. Sign in to Vapi the same way you sign in to the [dashboard](https://dashboard.vapi.ai): Google, GitHub, SSO, or email and password with MFA. If you're already signed in to the dashboard, this step is skipped. + + + Pick the Vapi organization this connection can access and approve. Tools then act as you, in that organization, with your role's permissions. + + - Codex saves the connection in `~/.codex/config.toml` and reads the key from `VAPI_API_KEY` when it connects. Keep that variable available whenever you launch Codex. If you use the desktop app or IDE extension, its launch environment must also contain the variable. +Your client stores the session and refreshes it automatically, so you only sign in again if the session is revoked or you disconnect. - Start a new Codex session and use `/mcp` to inspect the connection. See [Codex MCP setup](https://developers.openai.com/codex/mcp). - + + The hosted server no longer accepts Vapi API keys. If your client configuration sends an `Authorization: Bearer` header with an API key, remove the header and sign in with OAuth instead. + + +## Connect your agent + + - Set your API key and add the server to your private user configuration: + Add the server to your user configuration: ```bash - export VAPI_API_KEY="YOUR_VAPI_API_KEY" - claude mcp add --transport http --scope user vapi \ - https://mcp.vapi.ai/mcp \ - --header 'Authorization: Bearer ${VAPI_API_KEY}' - claude mcp get vapi + claude mcp add --transport http --scope user vapi https://mcp.vapi.ai/mcp ``` - The single quotes preserve the environment-variable reference in `~/.claude.json`. Keep `VAPI_API_KEY` set whenever you launch Claude Code. Start a new session and use `/mcp` to check the connection. + Start a Claude Code session, run `/mcp`, select **vapi**, and choose **Authenticate**. Sign in and pick an organization in the browser. See [Claude Code MCP setup](https://code.claude.com/docs/en/mcp). - - Register the hosted server with header authentication: + + For Claude Desktop and claude.ai, add Vapi as a custom connector: - ```bash - hermes mcp add vapi --url https://mcp.vapi.ai/mcp --auth header - ``` + 1. Open **Settings → Connectors** and choose **Add custom connector**. + 2. Enter `Vapi` as the name and `https://mcp.vapi.ai/mcp` as the URL. Leave the advanced OAuth settings empty. + 3. Select **Connect**, then sign in and pick an organization in the browser. - Confirm that the server requires authentication, then paste your Vapi API key at the masked **API key / Bearer token** prompt. Enter the key without the `Bearer` prefix. Select the tools you want to enable and finish saving the connection. + On Team and Enterprise plans, an owner adds the connector for the organization, and each member connects with their own Vapi account. - Hermes saves the connection in your active profile's `config.yaml` and the key in its `.env` file. Start a new session, or run `/reload-mcp` in an existing session. To test the connection: + See [Claude custom connectors](https://claude.com/docs/connectors/custom). + + + Register the server, then sign in: ```bash - hermes mcp test vapi + codex mcp add vapi --url https://mcp.vapi.ai/mcp + codex mcp login vapi ``` - See [Hermes MCP setup](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp). + `codex mcp login` opens the browser to sign in and pick an organization. On a machine without a local browser, run `codex mcp login vapi --no-browser`, open the printed URL elsewhere, and paste the redirect URL back. + + See [Codex MCP setup](https://learn.chatgpt.com/docs/extend/mcp?surface=cli). - Add this entry to your private user configuration at `~/.cursor/mcp.json`, preserving any other servers: + Add this entry to `~/.cursor/mcp.json`, preserving any other servers: ```json { "mcpServers": { "vapi": { - "url": "https://mcp.vapi.ai/mcp", - "headers": { - "Authorization": "Bearer YOUR_VAPI_API_KEY" - } + "url": "https://mcp.vapi.ai/mcp" } } } ``` - Replace `YOUR_VAPI_API_KEY` with your Vapi API key. Open Cursor's MCP settings and enable `vapi`, then start a new chat. Keep this user configuration private and update the header after rotating your key. + Open Cursor's MCP settings, enable `vapi`, and complete the sign-in when Cursor prompts you. See [Cursor MCP setup](https://cursor.com/docs/mcp). @@ -101,58 +110,52 @@ Get a [Vapi API key](/security-and-privacy/api-keys), then choose your client. T ```json { - "inputs": [ - { - "type": "promptString", - "id": "vapi-api-key", - "description": "Vapi API key", - "password": true - } - ], "servers": { "vapi": { "type": "http", - "url": "https://mcp.vapi.ai/mcp", - "headers": { - "Authorization": "Bearer ${input:vapi-api-key}" - } + "url": "https://mcp.vapi.ai/mcp" } } } ``` - Start `vapi` from **MCP: List Servers** and enter your API key when prompted. Use a **Local** chat session and enable its tools. VS Code does not forward servers that use input prompts to Copilot harness sessions. + Start `vapi` from **MCP: List Servers** and sign in when VS Code asks you to authenticate. See [VS Code MCP setup](https://code.visualstudio.com/docs/agents/reference/mcp-configuration). - - To connect through Claude Desktop's local stdio configuration, use `mcp-remote` as a bridge to the hosted server. This option requires Node.js and `npx` to be available to Claude Desktop. + + Add the server to `~/.hermes/config.yaml`: + + ```yaml + mcp_servers: + vapi: + url: "https://mcp.vapi.ai/mcp" + auth: oauth + ``` - Open **Settings → Developer → Edit Config**. Add this entry to `claude_desktop_config.json`, preserving any other servers: + Then sign in: + + ```bash + hermes mcp login vapi + ``` + + Start a new session, or run `/reload-mcp` in an existing one. See [Hermes MCP setup](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp). + + + Use Streamable HTTP at `https://mcp.vapi.ai/mcp` in any client that supports remote MCP servers with OAuth. + + If your client only supports local (stdio) servers, bridge to the hosted server with [`mcp-remote`](https://www.npmjs.com/package/mcp-remote), which handles the sign-in. This requires Node.js: ```json { "mcpServers": { "vapi": { "command": "npx", - "args": [ - "-y", - "mcp-remote", - "https://mcp.vapi.ai/mcp", - "--transport", - "http-only", - "--header", - "Authorization: Bearer ${VAPI_API_KEY}" - ], - "env": { - "VAPI_API_KEY": "YOUR_VAPI_API_KEY" - } + "args": ["-y", "mcp-remote", "https://mcp.vapi.ai/mcp"] } } } ``` - - Replace `YOUR_VAPI_API_KEY` with your Vapi API key and restart Claude Desktop. Keep this configuration private and update the key after rotating it. This starts a local adapter; Vapi's MCP server stays hosted. @@ -183,292 +186,54 @@ The Vapi MCP Server exposes these actions as MCP tools: --- -## Integration Options +## Custom MCP clients - - - Connect to the Vapi-hosted MCP server using the Streamable HTTP protocol. - - Recommended for most production use cases. - - - Use this for clients or SDKs that support Streamable HTTP transport. - - - - **Endpoint:** `https://mcp.vapi.ai/mcp` - - **Authentication:** Pass your Vapi API key as a bearer token: -
Authorization: Bearer YOUR_VAPI_API_KEY - - Configure the URL and authentication header directly in clients with remote MCP support. For a client that needs a local stdio adapter, use the [Claude Desktop tab](#connect-your-agent) above. -
- - - The OpenAI responses API now supports MCP. Read more here. - - - ```typescript title="typescript" - import OpenAI from 'openai'; - // Replace with your actual OpenAI API key - const openai = new OpenAI({ apiKey: 'YOUR_OPENAI_API_KEY' }); - async function main() { - const response = await openai.responses.create({ - model: 'gpt-4.1', - tools: [ - { - type: 'mcp', - server_label: 'vapi-mcp', - server_url: 'https://mcp.vapi.ai/mcp', - headers: { "Authorization": "Bearer YOUR_VAPI_API_KEY" } - }, - ], - input: 'What vapi tools do you have available?', - }); - console.dir(response, { depth: null }); - } - main(); - ``` - ```python title="python" - import openai - # Replace with your actual OpenAI API key - openai.api_key = 'YOUR_OPENAI_API_KEY' - response = openai.responses.create( - model="gpt-4.1", - tools=[ - { - "type": "mcp", - "server_label": "vapi-mcp", - "server_url": "https://mcp.vapi.ai/mcp", - "headers": {"Authorization": "Bearer YOUR_VAPI_API_KEY"} - }, - ], - input="What vapi tools do you have available?", - ) - print(response) - ``` - - - - Run the MCP server on your own machine for development or testing. - - - **Start locally:** - ```bash - npx -y @vapi-ai/mcp-server - ``` - - **Authentication:** Set the `VAPI_TOKEN` environment variable to your API key. - - Example config for Claude: - ```json - { - "mcpServers": { - "vapi-mcp-server": { - "command": "npx", - "args": [ - "-y", - "@vapi-ai/mcp-server" - ], - "env": { - "VAPI_TOKEN": "YOUR_VAPI_API_KEY" - } - } - } - } - ``` - - Use this for clients or SDKs that support local command-based MCP servers. - - - The client launches this server as a subprocess and communicates over **stdio**. This configuration does not start an HTTP endpoint. - -
- ---- +If you're building your own MCP client, use an [MCP SDK](https://modelcontextprotocol.io/docs/sdk) that implements [MCP authorization](https://modelcontextprotocol.io/specification/latest/basic/authorization). The server follows the standard flow: -## Custom MCP Client Integration - -You can use any MCP-compatible client (SDKs available for multiple languages). - - - - Choose a language: - - [TypeScript](https://github.com/modelcontextprotocol/typescript-sdk) - - [Python](https://github.com/modelcontextprotocol/python-sdk) - - [Java](https://github.com/modelcontextprotocol/java-sdk) - - [Kotlin](https://github.com/modelcontextprotocol/kotlin-sdk) - - [C#](https://github.com/modelcontextprotocol/csharp-sdk) - - - Set up your SDK to connect to https://mcp.vapi.ai/mcp using **Streamable HTTP** and authenticate with your Vapi API key in the Authorization: Bearer YOUR_VAPI_API_KEY header. - - - Query available tools, list assistants, create calls, etc, via your SDK. - - +- An unauthenticated request gets `401` with a `WWW-Authenticate` header that points to the protected resource metadata at `https://mcp.vapi.ai/.well-known/oauth-protected-resource/mcp`. +- That metadata names the authorization server. Clients register with Dynamic Client Registration or a Client ID Metadata Document, then use the authorization code flow with PKCE. +- Request the scopes `openid offline_access` and the resource `https://mcp.vapi.ai/mcp`, then send the access token as `Authorization: Bearer `. --- -### Example: Build a client with Node.js +## FAQ -```javascript -import { Client } from '@modelcontextprotocol/sdk/client/index.js'; -import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'; -import dotenv from 'dotenv'; + + + No. The hosted server only accepts OAuth sign-in. Remove any `Authorization` header or API key from your MCP configuration and follow the setup for your client above. API keys still work everywhere else in Vapi, including the [API](/api-reference) and [server SDKs](/sdks). + -dotenv.config(); + + Each connection is bound to the organization you picked when you signed in. To switch, disconnect or clear the authentication in your client and sign in again. To use several organizations at once, add the server once per organization under different names, such as `vapi-prod` and `vapi-staging`. + -const mcpClient = new Client({ name: 'vapi-client', version: '1.0.0' }); -const transport = new StreamableHTTPClientTransport( - new URL('https://mcp.vapi.ai/mcp'), - { requestInit: { headers: { Authorization: `Bearer ${process.env.VAPI_TOKEN}` } } } -); + + The same things you can in the chosen organization, with your role's permissions. If you lose access to the organization, the connection stops working on the next request. The connection can't create or read API keys, credentials, or billing details. + -async function main() { - await mcpClient.connect(transport); - const assistants = await mcpClient.callTool({ name: 'list_assistants', arguments: {} }); - console.log(assistants); - await mcpClient.close(); -} + + Remove the server from your client, or use its clear-authentication option (for example `/mcp` in Claude Code, or **Disconnect** for Claude connectors). + -main(); -``` + + OAuth sign-in needs a person to approve it in a browser. For unattended jobs, call the [Vapi API](/api-reference) directly with an [API key](/security-and-privacy/api-keys), or use a [server SDK](/sdks). + -### Detailed example: Build a client with Node.js - -```javascript -#!/usr/bin/env node -import { Client } from '@modelcontextprotocol/sdk/client/index.js'; -import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'; -import dotenv from 'dotenv'; - -// Load environment variables from .env file -dotenv.config(); - -// Ensure API key is available -if (!process.env.VAPI_TOKEN) { - console.error('Error: VAPI_TOKEN environment variable is required'); - process.exit(1); -} - -async function main() { - try { - // Initialize MCP client - const mcpClient = new Client({ - name: 'vapi-client-example', - version: '1.0.0', - }); - // Create Streamable HTTP transport for connection to remote Vapi MCP server - const serverUrl = 'https://mcp.vapi.ai/mcp'; - const headers = { - Authorization: `Bearer ${process.env.VAPI_TOKEN}`, - }; - const options = { - requestInit: { headers: headers }, - }; - const transport = new StreamableHTTPClientTransport(new URL(serverUrl), options); - console.log('Connecting to Vapi MCP server via Streamable HTTP...'); - await mcpClient.connect(transport); - console.log('Connected successfully'); - - // Helper function to parse tool responses - function parseToolResponse(response) { - if (!response?.content) return response; - const textItem = response.content.find(item => item.type === 'text'); - if (textItem?.text) { - try { - return JSON.parse(textItem.text); - } catch { - return textItem.text; - } - } - return response; - } - - try { - // List available tools - const toolsResult = await mcpClient.listTools(); - console.log('Available tools:'); - toolsResult.tools.forEach((tool) => { - console.log(`- ${tool.name}: ${tool.description}`); - }); - - // List assistants - console.log('\nListing assistants...'); - const assistantsResponse = await mcpClient.callTool({ - name: 'list_assistants', - arguments: {}, - }); - const assistants = parseToolResponse(assistantsResponse); - if (!(Array.isArray(assistants) && assistants.length > 0)) { - console.log('No assistants found. Please create an assistant in the Vapi dashboard first.'); - return; - } - console.log('Your assistants:'); - assistants.forEach((assistant) => { - console.log(`- ${assistant.name} (${assistant.id})`); - }); - - // List phone numbers - console.log('\nListing phone numbers...'); - const phoneNumbersResponse = await mcpClient.callTool({ - name: 'list_phone_numbers', - arguments: {}, - }); - const phoneNumbers = parseToolResponse(phoneNumbersResponse); - if (!(Array.isArray(phoneNumbers) && phoneNumbers.length > 0)) { - console.log('No phone numbers found. Please add a phone number in the Vapi dashboard first.'); - return; - } - console.log('Your phone numbers:'); - phoneNumbers.forEach((phoneNumber) => { - console.log(`- ${phoneNumber.phoneNumber} (${phoneNumber.id})`); - }); - - // Create a call using the first assistant and first phone number. - // Outbound calls need an imported number. With free Vapi numbers, only inbound calls are supported. - const phoneNumberId = phoneNumbers[0].id; - const assistantId = assistants[0].id; - console.log(`\nCreating a call using assistant (${assistantId}) and phone number (${phoneNumberId})...`); - const createCallResponse = await mcpClient.callTool({ - name: 'create_call', - arguments: { - assistantId: assistantId, - phoneNumberId: phoneNumberId, - customer: { - number: "+1234567890" // Replace with actual customer phone number - } - // Optional: schedule a call for the future - // scheduledAt: "2025-04-15T15:30:00Z" - // assistantOverrides: { - // variableValues: { - // name: 'John Doe', - // age: '25', - // }, - // }, - }, - }); - const createdCall = parseToolResponse(createCallResponse); - console.log('Call created:', JSON.stringify(createdCall, null, 2)); - } finally { - console.log('\nDisconnecting from server...'); - await mcpClient.close(); - console.log('Disconnected'); - } - } catch (error) { - console.error('Error:', error); - process.exit(1); - } -} - -main(); -``` + + The legacy HTTP+SSE endpoint (`https://mcp.vapi.ai/sse`) has been removed. Use Streamable HTTP at `https://mcp.vapi.ai/mcp`. + - For more detailed examples and complete client implementations, see the [MCP Client Quickstart](https://modelcontextprotocol.io/quickstart/client). + + Clear the saved authentication for `vapi` in your client and connect again. Make sure you can sign in to the [dashboard](https://dashboard.vapi.ai) with the same account, and that you're a member of the organization you pick. If your company manages MCP connections centrally, ask your admin to allow `https://mcp.vapi.ai/mcp`. + + ## References -- [Github repo](https://github.com/VapiAI/mcp-server) +- [GitHub repo](https://github.com/VapiAI/mcp-server) - [Model Context Protocol docs](https://modelcontextprotocol.io) +- [MCP authorization specification](https://modelcontextprotocol.io/specification/latest/basic/authorization) - [Vapi dashboard](https://dashboard.vapi.ai) -- [MCP client quickstart](https://modelcontextprotocol.io/quickstart/client)