Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

MCP Servers

Moltis supports the Model Context Protocol (MCP) for connecting to external tool servers. MCP servers extend your agent’s capabilities without modifying Moltis itself.

What is MCP?

MCP is an open protocol that lets AI assistants connect to external tools and data sources. Think of MCP servers as plugins that provide:

  • Tools — Functions the agent can call (e.g., search, file operations, API calls)
  • Resources — Data the agent can read (e.g., files, database records)
  • Prompts — Pre-defined prompt templates

Supported Transports

TransportDescriptionUse Case
stdioLocal process via stdin/stdoutnpm packages, local scripts
Streamable HTTPRemote server via HTTPCloud services, shared servers

Adding an MCP Server

Via Web UI

  1. Go to SettingsMCP Servers
  2. Click Add Server
  3. For remote Streamable HTTP servers, enter the server URL and any optional request headers
  4. Click Save

After saving a remote server, Moltis only shows a sanitized URL plus header names/count in the UI and status views. Stored header values stay hidden.

Via Configuration

Add servers to moltis.toml:

[mcp]
request_timeout_secs = 30

[mcp.servers.filesystem]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/projects"]

[mcp.servers.github]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-github"]
env = { GITHUB_TOKEN = "ghp_..." }
request_timeout_secs = 90

[mcp.servers.remote_api]
transport = "sse"
url = "https://mcp.example.com/mcp?api_key=$REMOTE_MCP_KEY"
headers = { Authorization = "Bearer ${REMOTE_MCP_TOKEN}" }

Remote URLs and headers support $NAME and ${NAME} placeholders. For live remote servers, placeholder values resolve from Moltis-managed env overrides, either [env] in config or SettingsEnvironment Variables.

Official Servers

ServerDescriptionInstall
filesystemRead/write local filesnpx @modelcontextprotocol/server-filesystem
githubGitHub API accessnpx @modelcontextprotocol/server-github
postgresPostgreSQL queriesnpx @modelcontextprotocol/server-postgres
sqliteSQLite databasenpx @modelcontextprotocol/server-sqlite
puppeteerBrowser automationnpx @modelcontextprotocol/server-puppeteer
brave-searchWeb searchnpx @modelcontextprotocol/server-brave-search

Community Servers

Explore more at mcp.so and GitHub MCP Servers.

Configuration Options

[mcp]
request_timeout_secs = 30       # Global default timeout for MCP requests

[mcp.servers.my_server]
command = "node"                # Required for stdio transport
args = ["server.js"]            # Optional arguments

# Optional environment variables
env = { API_KEY = "secret", DEBUG = "true" }

# Optional: per-server timeout override
request_timeout_secs = 90

# Optional: remote transport
transport = "sse"               # "stdio" (default) or "sse"
url = "https://mcp.example.com/mcp"  # Required when transport = "sse"
headers = { "x-api-key" = "$REMOTE_MCP_KEY" }  # Optional request headers

Request Timeouts

Moltis applies MCP request timeouts in two layers:

  • mcp.request_timeout_secs sets the global default for every MCP server
  • mcp.servers.<name>.request_timeout_secs optionally overrides that default for a specific server

This is useful when most local MCP servers respond quickly, but one remote SSE server or one expensive tool server needs a longer timeout.

[mcp]
request_timeout_secs = 30

[mcp.servers.remote_api]
transport = "sse"
url = "https://mcp.example.com/mcp"
request_timeout_secs = 120

In the web UI, the MCP settings page lets you edit both the global default timeout and the optional timeout override for each configured server.

Remote SSE Secrets and Placeholders

Remote MCP servers often expect API keys or bearer tokens in the URL query string or request headers. Moltis supports both patterns.

[mcp.servers.linear_remote]
transport = "sse"
url = "https://mcp.example.com/mcp?api_key=$REMOTE_MCP_KEY"
headers = {
  Authorization = "Bearer ${REMOTE_MCP_TOKEN}",
  "x-workspace" = "team-a",
}
  • Use $NAME or ${NAME} placeholders in remote url and headers
  • Placeholder values resolve from Moltis-managed env overrides, either [env] in config or SettingsEnvironment Variables
  • UI and API status payloads only expose sanitized URLs plus header names/count, not raw header values
  • Query-string secrets are redacted when Moltis displays a remote URL after save

Server Lifecycle

┌─────────────────────────────────────────────────────┐
│                   MCP Server                         │
│                                                      │
│  Start → Initialize → Ready → [Tool Calls] → Stop   │
│            │                       │                 │
│            ▼                       ▼                 │
│     Health Check ◄─────────── Heartbeat             │
│            │                       │                 │
│            ▼                       ▼                 │
│    Crash Detected ───────────► Restart              │
│                                    │                 │
│                              Backoff Wait            │
└─────────────────────────────────────────────────────┘

Health Monitoring

Moltis monitors MCP servers and automatically:

  • Detects crashes via process exit
  • Restarts with exponential backoff
  • Disables after max restart attempts
  • Re-enables after cooldown period

Using MCP Tools

Once connected, MCP tools appear alongside built-in tools. The agent can use them naturally:

User: Search GitHub for Rust async runtime projects

Agent: I'll search GitHub for you.
[Calling github.search_repositories with query="rust async runtime"]

Found 15 repositories:
1. tokio-rs/tokio - A runtime for writing reliable async applications
2. async-std/async-std - Async version of the Rust standard library
...

Creating an MCP Server

Simple Node.js Server

// server.js
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

const server = new Server(
  { name: "my-server", version: "1.0.0" },
  { capabilities: { tools: {} } }
);

server.setRequestHandler("tools/list", async () => ({
  tools: [{
    name: "hello",
    description: "Says hello",
    inputSchema: {
      type: "object",
      properties: {
        name: { type: "string", description: "Name to greet" }
      },
      required: ["name"]
    }
  }]
}));

server.setRequestHandler("tools/call", async (request) => {
  if (request.params.name === "hello") {
    const name = request.params.arguments.name;
    return { content: [{ type: "text", text: `Hello, ${name}!` }] };
  }
});

const transport = new StdioServerTransport();
await server.connect(transport);

Configure in Moltis

[mcp.servers.my_server]
command = "node"
args = ["server.js"]

Debugging

Check Server Status

In the web UI, go to SettingsMCP Servers to see:

  • Connection status (connected/disconnected/error)
  • Available tools
  • Sanitized remote URL and configured header names
  • Recent errors

View Logs

MCP server stderr is captured in Moltis logs:

# View gateway logs
tail -f ~/.moltis/logs.jsonl | grep -i mcp

Test Locally

Run the server directly to debug:

echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | node server.js

OAuth Authentication

Remote MCP servers can require OAuth 2.1 authentication. Moltis handles this automatically — when a server returns 401 Unauthorized, the OAuth flow starts without any manual configuration.

How It Works

  1. Moltis connects to the remote MCP server
  2. The server returns 401 Unauthorized with a WWW-Authenticate header
  3. Moltis discovers the authorization server via RFC 9728 (Protected Resource Metadata)
  4. Moltis performs dynamic client registration (RFC 7591)
  5. A PKCE authorization code flow opens your browser for login
  6. After login, tokens are stored and used for all subsequent requests

Client registrations and tokens are cached locally, so you only need to log in once per server.

Manual OAuth Configuration

If a server doesn’t support standard OAuth discovery, you can configure credentials manually:

[mcp.servers.private_api]
url = "https://mcp.example.com/mcp"
transport = "sse"

[mcp.servers.private_api.oauth]
client_id = "your-client-id"
auth_url = "https://auth.example.com/authorize"
token_url = "https://auth.example.com/token"
scopes = ["mcp:read", "mcp:write"]

Re-authentication

If your session expires or tokens are revoked, Moltis automatically re-authenticates on the next 401 response. You can also trigger re-authentication manually via the mcp.reauth RPC method.

Security Considerations

Warning

MCP servers run with the same permissions as Moltis. Only use servers from trusted sources.

  • Review server code before running
  • Limit file access — use specific paths, not /
  • Use environment variables for secrets
  • Prefer placeholders in remote URLs and headers ($NAME / ${NAME}) instead of hardcoding secrets repeatedly
  • Network isolation — run untrusted servers in containers

Troubleshooting

Server won’t start

  • Check the command exists: which npx
  • Verify the package: npx @modelcontextprotocol/server-filesystem --help
  • Check for port conflicts

Tools not appearing

  • Server may still be initializing (wait a few seconds)
  • Check server logs for errors
  • Verify the server implements tools/list

Server keeps restarting

  • Check stderr for crash messages
  • Increase max_restart_attempts for debugging
  • Verify environment variables are set correctly