Otto Docs
Integrations

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.


Otto ships with one MCP server pre-configured: Tavily, which gives the agent web search capabilities.

Default configuration (mcp-config.json):

{
  "mcpServers": {
    "tavily-mcp": {
      "transport": "stdio",
      "command": "npx",
      "args": ["-y", "tavily-mcp@latest"],
      "env": {
        "TAVILY_API_KEY": "${TAVILY_API_KEY}"
      }
    }
  }
}

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:

  1. MCP_CONFIG_JSON environment variable -- Inline JSON string. Recommended for production deployments.
  2. MCP_SERVERS environment variable -- File path pointing to a JSON config file.
  3. mcp-config.json file -- At data/mcp/mcp-config.json (mounted into containers at /app/mcp-config.json). Used for local development.
  4. 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:

{
  "mcpServers": {
    "server-name": {
      "transport": "stdio",
      "command": "npx",
      "args": ["-y", "package-name@latest"],
      "env": {
        "API_KEY": "${MY_API_KEY}"
      }
    }
  }
}

Server Configuration Fields

FieldRequiredDefaultDescription
transportNostdioTransport type: stdio or sse
commandYes (stdio)--Command to launch the MCP server process
argsNo[]Arguments passed to the command
envNonullEnvironment variables for the server process
urlYes (sse)--URL for SSE (Server-Sent Events) transport
timeoutNo30Connection timeout in seconds

Environment Variable Substitution

Config values support ${VAR} syntax for environment variable substitution. This lets you reference secrets without hardcoding them:

{
  "env": {
    "API_KEY": "${MY_SERVICE_API_KEY}"
  }
}

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.

{
  "transport": "stdio",
  "command": "npx",
  "args": ["-y", "some-mcp-server@latest"],
  "env": { "API_KEY": "${API_KEY}" }
}

sse (Server-Sent Events)

For MCP servers running as standalone HTTP services. Otto connects to the server's SSE endpoint.

{
  "transport": "sse",
  "url": "http://localhost:3001/sse"
}

Adding Custom MCP Servers

Option 1: Edit the Config File

For development, edit data/mcp/mcp-config.json:

{
  "mcpServers": {
    "tavily-mcp": {
      "transport": "stdio",
      "command": "npx",
      "args": ["-y", "tavily-mcp@latest"],
      "env": { "TAVILY_API_KEY": "${TAVILY_API_KEY}" }
    },
    "your-new-server": {
      "transport": "stdio",
      "command": "npx",
      "args": ["-y", "your-mcp-package@latest"],
      "env": { "YOUR_API_KEY": "${YOUR_API_KEY}" }
    }
  }
}

Restart the backend after editing.

Option 2: Environment Variable

For production, set the entire config as a JSON string in MCP_CONFIG_JSON:

MCP_CONFIG_JSON='{"mcpServers":{"tavily-mcp":{"transport":"stdio","command":"npx","args":["-y","tavily-mcp@latest"],"env":{"TAVILY_API_KEY":"your-key"}}}}'

Option 3: Capabilities UI

From the Otto web interface:

  1. Navigate to the Capabilities page.
  2. Open the MCP tab.
  3. Click Configure MCP Servers.
  4. Paste your JSON configuration into the editor. Real-time validation highlights any JSON errors.
  5. 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

ServerPackageWhat It Provides
Tavilytavily-mcpWeb search and content extraction
Context7context7-mcpProgramming documentation lookup
Sequential Thinking@anthropic/sequential-thinking-mcpStructured step-by-step reasoning
Gamma(custom)Presentation and slide deck generation
GitHub@modelcontextprotocol/server-githubRepository access, PR management
Filesystem@modelcontextprotocol/server-filesystemExtended file system access
Brave Search@anthropic/brave-search-mcpWeb 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

VariableRequiredDescription
MCP_CONFIG_JSONNoFull MCP configuration as an inline JSON string
MCP_SERVERSNoFile path to an MCP configuration JSON file
TAVILY_API_KEYNoAPI 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 npx is 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 MCPManager includes retry logic with exponential backoff. Transient failures are retried automatically.
  • Increase the timeout value 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:mcp Redis key.
  • The Capabilities UI provides real-time JSON validation. Use it to verify your config before saving.