MCP Tools
Portoser includes a built-in FastMCP server so AI assistants (Claude Desktop, Cursor, Continue, custom MCP clients) can interact with your cluster.
Status: The FastMCP server, the tool registry, and the audit log are wired and operational. First-party tools that act on the cluster (deploy, health, diagnose, etc.) are not yet shipped. The path below is for registering your own tools today; the first-party set lands in a near-term release.
Where the MCP server runs
web/backend/main.py instantiates the FastMCP server at startup:
mcp_instance = FastMCP(name="Portoser MCP Server")
The server is exposed over SSE and accessible to MCP clients on the same host as the web backend.
Connection details for clients
curl http://localhost:8000/api/mcp/config
returns a JSON document with the sse_url, transport, and any auth headers the client needs. Plug this into your MCP client's config.
For Claude Desktop, the relevant snippet is:
{
"mcpServers": {
"portoser": {
"command": "node",
"args": ["<path-to-mcp-bridge>"],
"env": {
"PORTOSER_SSE_URL": "http://localhost:8000/mcp/sse"
}
}
}
}
(Exact bridge command depends on your MCP client; the canonical bridge ships in the tools/mcp-bridge directory.)
The tool registry
Custom tools are managed via REST and persisted in PostgreSQL. The registry holds:
- Tool name and description
- Tool code (single-file or multi-file)
- Permissions (which RBAC groups can invoke)
- Audit log entries for every operation
Add a tool
curl -X POST http://localhost:8000/api/mcp/tools \
-H "Content-Type: application/json" \
-d '{
"name": "list_services",
"description": "List all services in the registry",
"code": "def list_services():\n return registry.services()\n",
"permissions": ["operator"]
}'
The tool is then visible to any connected MCP client.
Inspect tools
curl http://localhost:8000/api/mcp/tools | jq
Multi-file tools
For tools that span multiple Python modules, POST a files array instead of code. The runtime imports them in order. See web/backend/services/mcp_postgres_db.py:add_multi_file_tool for the schema.
What's coming as first-party tools
The roadmap, in priority order:
cluster.list_services/cluster.list_machines— read-only cluster inspectioncluster.health— aggregated health snapshotcluster.diagnose— run the diagnose phase on a servicecluster.deploy— guarded deploy with dry-run flag and confirmationregistry.read/registry.diff— view and propose registry changesvault.get_secret/vault.set_secret— secret operations with policy gating
These will be opt-in per cluster — operators decide which tool groups an MCP client can call.
Audit logging
Every tool invocation is logged to mcp_audit_logs with:
- Caller identity (Keycloak user or anonymous)
- Tool name and arguments (secrets redacted)
- Timestamp and result
- IP address of the caller
Read the log:
curl http://localhost:8000/api/mcp/audit/logs?limit=50 | jq
This is the right place to start when something unexpected changes in your cluster and an MCP client is connected.
Security
The MCP server inherits the web backend's auth model. When Keycloak is enabled, every tool call requires a valid bearer token; the registered tools' permissions list is checked against the caller's RBAC groups. When Keycloak is disabled (dev mode), the server is open.
Don't expose the MCP SSE endpoint to the internet directly. Either keep it behind your tunnel of choice (WireGuard, Tailscale, Cloudflare Tunnel) or front it with mTLS.