MCP tool servers
Leviath connects to Model Context Protocol servers over stdio or HTTP (streamable, with a legacy HTTP+SSE fallback), giving agents extra tools beyond the built-ins.
flowchart LR
subgraph D["Daemon"]
A["agent"]
end
A -->|tool call| B["MCP broker"]
B -->|stdio| S1["filesystem<br/>(npx server)"]
B -->|HTTP| S2["remote<br/>(mcp.example.com)"]
Managing servers
lev mcp add filesystem --command npx \
--arg -y --arg @modelcontextprotocol/server-filesystem --arg /path
lev mcp add remote --url https://mcp.example.com --header "Authorization=Bearer $TOK"
lev mcp list
lev mcp login <name> # OAuth servers: opens your browser
lev mcp logout <name> # drop the stored OAuth tokens
lev mcp test <name>
lev mcp remove <name>lev mcp add <name> takes --command + repeatable --arg for a stdio server, or --url
(with optional --header/--env) for an HTTP one; --no-login skips the OAuth handshake.
--header and --env both want KEY=VALUE, split on the first =. Note that this is not the
Name: value form an HTTP header is usually written in, so Authorization: Bearer ... is rejected
with --header must be KEY=VALUE.
--arg passes its value through to the server's own command line, so an argument of its own that
starts with - is fine: --arg -y is the -y that npx wants, not a flag of ours.
There are two ways an HTTP server authenticates you, and Leviath picks between them by asking the
server rather than by guessing. If a --header you configured is enough, as it is for a server that
takes an API token of its own, add reports that no login is needed and stores nothing. If the
server answers with a 401 instead, the OAuth flow runs and the tokens land in the credential
store. lev mcp login on an already-satisfied server says so rather than failing.
That question is asked with the headers as they will actually be sent, ${VAR} references
expanded, so a credential that comes from the environment is recognised as the credential it is.
Note
GitHub's MCP server accepts either. A personal access token in an Authorization header needs no
login at all, and the same endpoint runs the browser flow if you configure no header.
Or configure in ~/.leviath/config.toml:
[[mcp_servers]]
name = "filesystem"
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/path"]
[[mcp_servers]]
name = "remote"
url = "https://mcp.example.com"
headers = { Authorization = "Bearer ${MY_TOKEN}" } # ${VAR} is expandedDiscovery and invocation
On connect, Leviath discovers the server's tools and exposes them to any stage whose
available_tools includes them:
sequenceDiagram participant Agent participant Broker as MCP broker participant Server as MCP server Broker->>Server: initialize + list tools Server-->>Broker: tool schemas Agent->>Broker: call tool(args) Broker->>Server: invoke Server-->>Broker: result Broker-->>Agent: routed to a context region
OAuth, safely
lev mcp add detects OAuth servers, binds tokens to the server origin (RFC 8414 issuer check,
HTTPS-only, capped redirects), and stores them in ~/.leviath/mcp-auth.json (0600), refreshing
non-interactively.