MCP Support
A perfectly good VCI app has zero MCP servers. Only add MCP when you need to reach outside the app's own state (e.g. sync to an external service). Skip to When to add MCP if you want the short version.
What is MCP?
Model Context Protocol (MCP) is an open standard for connecting AI models to external tools and data sources. An MCP server exposes a set of tools the model can call — think of it as a plugin system for the AI.
A VCI app's native tool surface is intentionally small (≤ 8 domain tools). MCP lets you extend that surface without polluting the core: plug in Notion for note sync, Google Calendar for events, a web search server, GitHub, Linear, and so on.
Enabling MCP
OpenAI's Realtime API supports remote MCP servers natively as a tool
type. You add them to the same tools array in the session.update
event, alongside your function tools:
{
"type": "session.update",
"session": {
"type": "realtime",
"tools": [
// Your native function tools (unchanged)
{ "type": "function", "name": "add_note" },
{ "type": "function", "name": "delete_note" },
// MCP servers added inline
{
"type": "mcp",
"server_label": "notion",
"server_url": "https://mcp.notion.com/sse",
"authorization": "Bearer <notion-oauth-token>",
"require_approval": "always"
},
{
"type": "mcp",
"server_label": "search",
"server_url": "https://mcp.search.example.com/sse",
"require_approval": "never",
"allowed_tools": ["web_search"]
}
]
}
}
The model can now call MCP tools as naturally as native ones. Voice command: "add this to my Notion inbox" → the model calls the Notion MCP server → confirmation spoken back.
Remote MCP servers
Remote MCP servers speak MCP over HTTP + SSE (or streamable HTTP). They are the only flavor usable directly from a browser VCI app — the model connects to them from OpenAI's side, not yours.
Finding servers
- Public directories: mcpservers.org, modelcontextprotocol/servers.
- First-party: many SaaS vendors now ship their own MCP endpoint (Notion, Linear, GitHub, Slack, Sanity, Vercel, etc.).
- Roll your own: MCP is spec-based; a minimal server is ~150 lines of code.
Local (stdio) MCP servers
Local MCP servers (spawned as subprocesses over stdio) cannot be used directly from a browser. To integrate them, you need a small backend proxy that connects to the local server and exposes an SSE endpoint — at which point they are functionally remote MCP servers again.
Wiring MCP tools
Recommended flow for optional MCP support in your VCI app:
- In
storage, add agetMcpServers()function returning an array of configured MCP server entries (URL, label, token, approval mode). - In the
ui, add a small settings panel (still not for domain actions — this is a config surface) where the user can enable/disable MCP servers and paste tokens. - In
realtime.js, when building thetoolsarray forsession.update, concatenate native function tools with configured MCP entries. - Re-send
session.updatewhenever MCP config changes so the live session picks up the new tools.
function buildTools() {
const native = NATIVE_FUNCTION_TOOLS;
const mcp = Storage.getMcpServers().map(s => ({
type: "mcp",
server_label: s.label,
server_url: s.url,
authorization: s.token ? "Bearer " + s.token : undefined,
require_approval: s.approvalMode || "always",
allowed_tools: s.allowedTools, // optional whitelist
}));
return [...native, ...mcp];
}
MCP security & approvals
Every MCP server you add can, in principle, call arbitrary tools with arbitrary arguments generated by the model. A malicious or compromised server can exfiltrate data via its tool arguments. Treat MCP servers like npm packages: audit before use.
Approval modes
| Mode | Behavior | Use when |
|---|---|---|
"always" | Every MCP tool call surfaces to the user for approval before executing. | Third-party servers, anything that mutates external state. |
"never" | MCP tools auto-execute without user confirmation. | Trusted first-party read-only servers (e.g. an internal search endpoint you control). |
Token handling
- Personal-use apps: store MCP auth tokens in
localStorage, same trade-off as the OpenAI key. - Public apps: mint short-lived MCP tokens on your backend, hand them to the browser alongside the ephemeral OpenAI token.
- Whitelist tools per server via
allowed_toolswhenever possible — reduces blast radius if the server misbehaves.
When to add MCP
| Add MCP when… | Skip MCP when… |
|---|---|
| You need to reach an external service you don't control (Notion, GitHub, Slack, etc.). | The app is entirely local — state stays in localStorage. |
| The domain vocabulary is stable and you want to extend it without rewriting the app. | You could just add a native function tool with a small fetch. |
| A first-party MCP server already exists for the service you need. | You're prototyping and don't want the ceremony. |