External MCP Server Integration¶
OpenJarvis can extend agent capabilities by connecting to external Model Context Protocol (MCP) servers. This allows agents to use tools provided by services like Home Assistant, databases, custom APIs, or any MCP-compatible server -- without writing custom tool code.
How It Works¶
When OpenJarvis starts, it reads the [tools.mcp] section in config.toml. For each configured server, it:
- Opens a connection using the appropriate transport (Streamable HTTP or stdio).
- Performs the MCP initialize handshake (protocol version negotiation and
initializednotification). - Discovers available tools via
tools/list. - Wraps each discovered tool as a standard
BaseToolso agents can call them like any built-in tool.
If a server is unreachable or returns an error, OpenJarvis logs a warning and continues loading the remaining servers. One broken server does not prevent other tools from being available.
Configuration¶
External MCP servers are configured in config.toml under [tools.mcp]:
[tools.mcp]
enabled = true
servers = '[{"name": "homeassistant", "url": "http://172.16.3.1:9583/private_abc123"}]'
The servers value is a JSON-encoded string containing an array of server objects. Each object defines one external MCP server.
Note
The value must be a JSON string (with single-quote TOML delimiters around it), not a native TOML array. This is because the configuration system passes it through as a single string field.
Server Config Schema¶
Each server object supports the following fields:
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | No | Human-readable name used in log messages. Defaults to <unnamed>. |
url |
string | No* | URL for Streamable HTTP transport. |
command |
string | No* | Command to launch a stdio-based MCP server. |
args |
list of strings | No | Arguments passed to the stdio command. |
include_tools |
list of strings | No | Whitelist of tool names to import. Only these tools are loaded. |
exclude_tools |
list of strings | No | Blacklist of tool names to skip. All other tools are loaded. |
*Either url or command must be provided. If neither is set, the server is skipped with a warning.
When both include_tools and exclude_tools are specified, the whitelist is applied first, then the blacklist filters the result.
Examples¶
Home Assistant via Streamable HTTP¶
Connect to the ha-mcp Home Assistant add-on:
[tools.mcp]
enabled = true
servers = '[{"name": "homeassistant", "url": "http://172.16.3.1:9583/private_abc123"}]'
This discovers all HA tools (entity control, automations, history, etc.) and makes them available to agents.
Stdio Server¶
Launch a local MCP server as a subprocess:
[tools.mcp]
enabled = true
servers = '[{"name": "myserver", "command": "python", "args": ["-m", "my_mcp_server"]}]'
OpenJarvis starts the process automatically, communicates via JSON-RPC over stdin/stdout, and terminates it on shutdown.
Multiple Servers¶
[tools.mcp]
enabled = true
servers = '[{"name": "homeassistant", "url": "http://172.16.3.1:9583/private_abc123"}, {"name": "database", "command": "db-mcp-server", "args": ["--db", "postgres://localhost/mydb"]}]'
Tool Filtering¶
When a server exposes many tools but you only need a few, use include_tools to whitelist:
[tools.mcp]
enabled = true
servers = '[{"name": "ha", "url": "http://172.16.3.1:9583/private_abc123", "include_tools": ["hassTurnOn", "hassTurnOff", "hassGetState"]}]'
To load everything except specific tools, use exclude_tools:
[tools.mcp]
enabled = true
servers = '[{"name": "ha", "url": "http://172.16.3.1:9583/private_abc123", "exclude_tools": ["hassCreateBackup", "hassDeleteBackup"]}]'
Transport Types¶
Streamable HTTP¶
Used when the url field is set. The transport sends JSON-RPC requests as HTTP POST to the given URL using httpx. It tracks the Mcp-Session-Id header across requests as required by the MCP Streamable HTTP specification.
When to use: Remote MCP servers, services running as HTTP endpoints (e.g., Home Assistant MCP add-on, cloud-hosted MCP servers).
Connection parameters:
- Connect timeout: 10 seconds
- Request timeout: 60 seconds
Stdio¶
Used when the command field is set. OpenJarvis spawns the command as a subprocess and communicates via JSON-RPC lines on stdin/stdout.
When to use: Local MCP servers distributed as CLI tools, development/testing, servers that require filesystem access on the same machine.
SSETransport alias
SSETransport is provided as a backward-compatible alias for StreamableHTTPTransport. Both refer to the same implementation.
Error Handling¶
OpenJarvis handles MCP server failures gracefully:
- Server unreachable: A warning is logged and the server is skipped. All other servers and built-in tools continue to load normally.
- Timeout: HTTP requests time out after 60 seconds. The server is skipped with a warning.
- Invalid config: If the
serversJSON is malformed or a server entry has neitherurlnorcommand, a warning is logged and that entry is skipped. - Tool discovery failure: If
tools/listfails on a server, the error is caught and the server is skipped. - Runtime tool call failure: If a tool call to an external MCP server fails at runtime, it returns a
ToolResultwithsuccess=Falseand the error message.
No single server failure causes OpenJarvis to crash or prevents other tools from working.
Troubleshooting¶
Server not discovered¶
- Check that
[tools.mcp]hasenabled = true. - Verify the
serversJSON is valid. A common mistake is using TOML arrays instead of a JSON string. - Check the OpenJarvis logs for warnings like
Failed to discover external MCP tools.
Connection refused / timeout¶
- Verify the server is running and reachable from the OpenJarvis host:
curl -v http://host:port/. - Check firewall rules between the OpenJarvis container and the MCP server.
- For Docker deployments, ensure both containers are on the same network or use host IPs.
Tools not appearing¶
- Run with debug logging to see which tools were discovered.
- Check if
include_toolsorexclude_toolsfilters are too restrictive. - Verify the MCP server actually exposes tools via
tools/list(some servers only expose resources or prompts).
Stdio server crashes immediately¶
- Test the command manually:
python -m my_mcp_servershould start and wait for input on stdin. - Check stderr output in the OpenJarvis logs for error messages from the subprocess.
- Ensure all dependencies for the MCP server are installed in the same environment.