MetaMCP

Configuration

Config file format

MetaMCP reads .mcp.json by default. The format is the same as Claude Desktop and Claude Code config files.

{
  "mcpServers": {
    "<server-name>": {
      "command": "<executable>",
      "args": ["<arg1>", "<arg2>"],
      "env": {
        "<VAR>": "<value>"
      }
    }
  }
}

Each key under mcpServers is a server name. MetaMCP uses this name to identify the server in mcp_discover, mcp_call, and mcp_execute.

To use a different config file path, pass it with the --config flag:

metamcp --config path/to/my-config.json

Server entry fields

Each server entry supports the following fields:

Field Type Required Description
command string * Executable to spawn the child server (stdio transport).
args string[] No Arguments passed to the command.
env Record<string, string> No Environment variables passed to the child server process only.
url string * Remote server URL (HTTP or SSE transport).
transportType "http" or "sse" No Transport for remote servers. Defaults to "http" when url is set.
headers Record<string, string> No HTTP headers sent with remote transport requests.
oauth boolean No Enable OAuth authorization flow for this server.
timeoutMs number No Tool call timeout in milliseconds (default: 60000).
lifecycle string or object No Server lifecycle: "keep-alive", "ephemeral", or { "mode": "keep-alive", "idleTimeoutMs": 600000 }.

* Each entry must have either command (for local stdio servers) or url (for remote HTTP/SSE servers).

ℹ️

The config parser sets criticality to 'vital' by default for all servers. Vital servers are prioritized in the connection pool and trigger warnings on failure.

npx packages

Most MCP servers are distributed as npm packages. Use npx as the command to run them without a global install:

{
  "mcpServers": {
    "playwright": {
      "command": "npx",
      "args": ["-y", "@playwright/mcp@latest"]
    }
  }
}

The -y flag auto-confirms the npx install prompt. Without it, npx may hang waiting for user confirmation.

You can pin a specific version by replacing @latest with a version number (e.g., @playwright/mcp@0.0.10).

Local binaries

For servers installed locally or built from source, use an absolute path:

{
  "mcpServers": {
    "my-server": {
      "command": "/usr/local/bin/my-mcp-server",
      "args": ["--port", "3000"]
    }
  }
}
⚠️

Relative paths are resolved from the working directory where MetaMCP starts. Use absolute paths to avoid issues when MetaMCP is launched by Claude Desktop or other clients.

Environment variables

Pass server-specific environment variables using the env field:

{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_TOKEN": "ghp_xxxxxxxxxxxxxxxxxxxx"
      }
    }
  }
}

Environment variables in the env field are passed only to that child server's process. They do not leak to other servers or to MetaMCP itself.

💡

For secrets, consider referencing environment variables from your shell instead of hardcoding them in the config file. Set them in your shell profile and they will be inherited by MetaMCP's child processes.

Remote servers

MetaMCP can connect to remote MCP servers over HTTP or SSE. Use the url field instead of command:

Streamable HTTP (default for remote):

{
  "mcpServers": {
    "cloud-tools": {
      "url": "https://mcp.example.com/api",
      "headers": {
        "Authorization": "Bearer your-token"
      }
    }
  }
}

SSE transport:

{
  "mcpServers": {
    "sse-server": {
      "url": "https://mcp.example.com/sse",
      "transportType": "sse"
    }
  }
}

OAuth authorization:

{
  "mcpServers": {
    "oauth-server": {
      "url": "https://mcp.example.com/api",
      "oauth": true
    }
  }
}

When oauth is true, MetaMCP opens your browser for authorization on first connect. Tokens are persisted at ~/.metamcp/oauth/<server-name>/ and refreshed automatically on subsequent runs.

Server lifecycle

Each server can declare how MetaMCP manages its connection lifetime. Without a lifecycle declaration, servers follow the global idle timeout (default: 5 minutes).

Keep-alive (persistent connection):

{
  "mcpServers": {
    "database": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-sqlite", "/path/to/db"],
      "lifecycle": "keep-alive"
    }
  }
}

Keep-alive servers are exempt from the global idle timeout sweep. They remain connected until MetaMCP shuts down. This is ideal for servers with expensive initialization or persistent state.

Keep-alive with per-server idle timeout:

{
  "mcpServers": {
    "database": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-sqlite", "/path/to/db"],
      "lifecycle": { "mode": "keep-alive", "idleTimeoutMs": 600000 }
    }
  }
}

The server uses its own idle timeout (10 minutes in this example) instead of the global default. It is still exempt from the global sweep and only evicted after its own timeout expires.

Ephemeral (connect on demand):

{
  "mcpServers": {
    "converter": {
      "command": "/usr/local/bin/converter",
      "lifecycle": "ephemeral"
    }
  }
}

Ephemeral servers are torn down as soon as they go idle. They are spawned fresh on each use. This suits stateless, fast-starting utilities where keeping a process alive wastes resources.

Importing from editors

MetaMCP can auto-discover MCP server configurations from your installed editors and development tools. Pass the --import flag to merge external configs at startup:

metamcp --config .mcp.json --import

MetaMCP scans the following clients for configured MCP servers:

Client Config location
Cursor ~/.cursor/mcp.json
Claude Desktop ~/Library/Application Support/Claude/claude_desktop_config.json
Claude Code ~/.claude.json
VS Code ~/Library/Application Support/Code/User/mcp.json
Windsurf ~/.codeium/windsurf/mcp_config.json
Codex ~/.codex/config.toml or ~/.config/codex/config.toml
OpenCode ~/.config/opencode/config.json

Discovered servers are merged with your local .mcp.json configuration. Local config takes precedence: if a server name appears in both your config file and an editor, the local definition wins. Among editors, first-seen wins.

💡

Use --import during development to consolidate servers from all your tools without duplicating config entries. In production, prefer explicit .mcp.json configuration for reproducibility.

Config discovery

The metamcp init command auto-detects installed MCP clients and configures them to use MetaMCP:

metamcp init

This detects Claude Desktop, Claude Code, and other supported clients. It writes the appropriate config entries so you do not need to edit config files manually.

For the full list of init options, see CLI Reference.

CLI overrides

CLI flags override the built-in defaults for connection pool and circuit breaker behavior. Pass them when starting MetaMCP:

metamcp --config .mcp.json --max-connections 10 --idle-timeout 60000
Flag Default Description
--config <path> .mcp.json Path to the config file.
--max-connections <n> 20 Maximum concurrent child server connections.
--idle-timeout <ms> 300000 Idle connection timeout in milliseconds (5 minutes).
--failure-threshold <n> 5 Number of failures before the circuit breaker trips.
--cooldown <ms> 30000 Circuit breaker cooldown period in milliseconds (30s).

For the complete CLI reference, see CLI Reference.

Next steps

© 2026 MetaMCP. Open source under Apache-2.0.