MCP Server Integration
MCP (Model Context Protocol) is an open standard that allows Otto's agent to connect to external tool servers at runtime. Each MCP server exposes one or more tools that the agent can call, extendin...
MCP (Model Context Protocol) is an open standard that allows Otto's agent to connect to external tool servers at runtime. Each MCP server exposes one or more tools that the agent can call, extending Otto's capabilities without modifying its core code.
Why MCP Matters
MCP is Otto's primary extensibility mechanism. Instead of building every integration directly into Otto, you can connect MCP servers that provide specialized tools -- web search, documentation lookup, code analysis, presentation generation, and more. If an MCP server exists for a service, Otto can use it.
The agent treats MCP tools the same as its built-in tools. When working on a task, Otto decides which tools to call based on the task requirements, whether those tools are built-in or provided by an MCP server.
Default MCP Server: Tavily Web Search
Otto ships with one MCP server pre-configured: Tavily, which gives the agent web search capabilities.
Default configuration (mcp-config.json):
To enable web search, set the TAVILY_API_KEY environment variable. You can get a free API key at tavily.com.
Configuration
Config Loading Priority
Otto loads MCP configuration from the first available source, in this order:
MCP_CONFIG_JSONenvironment variable -- Inline JSON string. Recommended for production deployments.MCP_SERVERSenvironment variable -- File path pointing to a JSON config file.mcp-config.jsonfile -- Atdata/mcp/mcp-config.json(mounted into containers at/app/mcp-config.json). Used for local development.- Redis dynamic config -- Runtime overlay stored in Redis (key:
otto:config:mcp). Enables hot-reload without restarts.
Config File Format
The configuration follows a standard format with a top-level mcpServers object. Each key is the server name, and the value describes how to connect:
Server Configuration Fields
| Field | Required | Default | Description |
|---|---|---|---|
transport | No | stdio | Transport type: stdio or sse |
command | Yes (stdio) | -- | Command to launch the MCP server process |
args | No | [] | Arguments passed to the command |
env | No | null | Environment variables for the server process |
url | Yes (sse) | -- | URL for SSE (Server-Sent Events) transport |
timeout | No | 30 | Connection timeout in seconds |
Environment Variable Substitution
Config values support ${VAR} syntax for environment variable substitution. This lets you reference secrets without hardcoding them:
At load time, ${MY_SERVICE_API_KEY} is replaced with the value of that environment variable.
Transport Types
stdio
The most common transport. Otto spawns the MCP server as a child process and communicates over stdin/stdout. This is what npx-based MCP servers use.
sse (Server-Sent Events)
For MCP servers running as standalone HTTP services. Otto connects to the server's SSE endpoint.
Adding Custom MCP Servers
Option 1: Edit the Config File
For development, edit data/mcp/mcp-config.json:
Restart the backend after editing.
Option 2: Environment Variable
For production, set the entire config as a JSON string in MCP_CONFIG_JSON:
Option 3: Capabilities UI
From the Otto web interface:
- Navigate to the Capabilities page.
- Open the MCP tab.
- Click Configure MCP Servers.
- Paste your JSON configuration into the editor. Real-time validation highlights any JSON errors.
- Save. The configuration is stored in Redis and applied without restarting the backend.
Option 4: Redis Dynamic Config
For programmatic configuration changes, write directly to the Redis key otto:config:mcp. This is what the Capabilities UI uses under the hood.
Examples of Useful MCP Servers
| Server | Package | What It Provides |
|---|---|---|
| Tavily | tavily-mcp | Web search and content extraction |
| Context7 | context7-mcp | Programming documentation lookup |
| Sequential Thinking | @anthropic/sequential-thinking-mcp | Structured step-by-step reasoning |
| Gamma | (custom) | Presentation and slide deck generation |
| GitHub | @modelcontextprotocol/server-github | Repository access, PR management |
| Filesystem | @modelcontextprotocol/server-filesystem | Extended file system access |
| Brave Search | @anthropic/brave-search-mcp | Web search via Brave |
Check the MCP server registry for a growing list of available servers.
How MCP Tools Appear to the Agent
When the agent graph initializes, Otto's MCPManager connects to all configured MCP servers, discovers their available tools, and registers them alongside Otto's built-in tools. The agent sees a flat list of all tools and chooses whichever ones are appropriate for the task.
For example, if Tavily is configured, the agent can call tavily_search and tavily_extract tools. If a Gamma MCP server is configured, the agent gains access to gamma_create_generation and gamma_get_generation_status.
MCP tools are subject to the same skill-based tool restrictions as built-in tools. If a matched skill declares an allowed-tools list, only MCP tools matching those names or patterns are available for that task.
Environment Variables
| Variable | Required | Description |
|---|---|---|
MCP_CONFIG_JSON | No | Full MCP configuration as an inline JSON string |
MCP_SERVERS | No | File path to an MCP configuration JSON file |
TAVILY_API_KEY | No | API key for the default Tavily web search MCP server |
Troubleshooting
MCP server fails to connect
- Check backend logs for MCP-related errors. Otto logs detailed information during server startup.
- For stdio servers, verify that
npxis available in the container. The Otto Docker image includes Node.js for this purpose. - For SSE servers, verify the URL is reachable from the backend container.
Tools are not appearing
- Confirm the MCP config is being loaded by checking startup logs. Otto logs the number of servers found and their names.
- Verify environment variable substitution is working. If
${TAVILY_API_KEY}is not set, the literal string is passed through, which will cause authentication failures.
MCP server crashes or times out
- The
MCPManagerincludes retry logic with exponential backoff. Transient failures are retried automatically. - Increase the
timeoutvalue in the server config if the server is slow to start. - For stdio servers, ensure the npm package name and version are correct.
Dynamic config not taking effect
- Redis dynamic config is loaded as an overlay. Verify the config is stored correctly at the
otto:config:mcpRedis key. - The Capabilities UI provides real-time JSON validation. Use it to verify your config before saving.