Skip to Content

External MCP Servers

CMDOP is happy to call any MCP-compliant server. Register a filesystem server, a GitHub server, an in-house tool — its tools merge into the agent’s catalog and the same permission gate applies.

Why register external servers

The CMDOP agent loop already speaks MCP as a client. That means you do not need to write a Go tool to extend the agent — point it at an existing MCP server (NPM, PyPI, your own binary) and its tools become callable from cmdop chat, the desktop chat tab, and any MCP integration that is already pointed at CMDOP.

Common cases:

  • Give the agent sandboxed filesystem access to a single directory.
  • Let the agent open GitHub issues or read a PR diff.
  • Bridge an internal service (Slack, Linear, a database query tool) that already speaks MCP.

Register a server

cmdop mcp servers add filesystem \ --command npx \ --args -y @modelcontextprotocol/server-filesystem ~/projects

Servers are persisted across daemon restarts. Each entry has a name, a command, and an args list — the daemon spawns the process over stdio at boot and again after cmdop agent restart.

List and remove

cmdop mcp servers list cmdop mcp servers remove filesystem

What the agent sees

On boot, for each registered server, the daemon:

  1. Spawns the process with stdin/stdout wired to the MCP transport.
  2. Calls tools/list once.
  3. Merges the tools into its catalog with a namespace prefix: <server>:<tool>.

So a filesystem server contributes filesystem:read_file, filesystem:list_directory, etc. From the LLM’s point of view they are just more tools.

Permissions on external tools

External tools flow through the same gate as built-ins. Rules use the namespaced name:

cmdop permissions allow 'github:create_issue' cmdop permissions deny 'github:delete_repo' cmdop permissions ask 'filesystem:write_file(*)'

Floor checks still apply on path-shaped arguments. The gate sees the tool name plus the matchable arg (path, hostname, command) and runs the same policy lookup it does for built-ins. See Agent Permissions.

External servers run as their own process and bring their own permission model. CMDOP gates the call into the server — it cannot gate what the server does internally. Treat each external server like a third-party dependency: pin versions, read its README, sandbox where you can.

Common servers worth registering

ServerCommandNotes
Filesystemnpx -y @modelcontextprotocol/server-filesystem <dir>Sandboxed read/write inside a directory.
GitHubnpx -y @modelcontextprotocol/server-githubIssues, PRs, repo metadata. Needs a token.
Slacknpx -y @modelcontextprotocol/server-slackPost messages, read channels.
Customyour own binaryAnything that speaks MCP stdio works.

Pick servers that map to actions you would otherwise script in execute_command. Native MCP tools have typed schemas, retry semantics, and audit entries that a shell pipeline does not.

Authoring your own

CMDOP imposes no extra contract beyond MCP itself. If your server speaks the standard stdio JSON-RPC dialect — initialize, tools/list, tools/call — it works. Pin a name in cmdop mcp servers add and it shows up.

A minimal pattern:

  1. Implement an MCP server in any language with an SDK (TypeScript, Python, Go).
  2. Test it with the upstream MCP inspector.
  3. Register with cmdop mcp servers add.
  4. Watch cmdop agent logs -f during the next start to confirm the handshake.

Troubleshooting

  • Server never loadscmdop cannot find the command. Use an absolute path in --command.
  • No tools advertised — the server returned an empty tools/list, or initialize failed. Run the command standalone to see its stderr.
  • Tool calls always denied — the gate is in strict mode and there is no rule. Add cmdop permissions allow '<server>:<tool>'.
  • Wrong handshake version — your server speaks an older MCP protocol. Upgrade or swap.

cmdop agent logs -f shows the registration handshake; grep for the server name.

Last updated on