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 ~/projectsServers 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 filesystemWhat the agent sees
On boot, for each registered server, the daemon:
- Spawns the process with stdin/stdout wired to the MCP transport.
- Calls
tools/listonce. - 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
| Server | Command | Notes |
|---|---|---|
| Filesystem | npx -y @modelcontextprotocol/server-filesystem <dir> | Sandboxed read/write inside a directory. |
| GitHub | npx -y @modelcontextprotocol/server-github | Issues, PRs, repo metadata. Needs a token. |
| Slack | npx -y @modelcontextprotocol/server-slack | Post messages, read channels. |
| Custom | your own binary | Anything 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:
- Implement an MCP server in any language with an SDK (TypeScript, Python, Go).
- Test it with the upstream MCP inspector.
- Register with
cmdop mcp servers add. - Watch
cmdop agent logs -fduring the next start to confirm the handshake.
Troubleshooting
- Server never loads —
cmdopcannot 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
strictmode and there is no rule. Addcmdop 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.