feat(mcp): expose MCP server management as goclaw_mcp_servers_* tools - #1452
feat(mcp): expose MCP server management as goclaw_mcp_servers_* tools#1452bclermont wants to merge 1 commit into
Conversation
MCP server CRUD was reachable only over REST (/v1/mcp/servers). An agent could mint an admin API key with goclaw_api_keys_create but then had to leave MCP entirely to register, inspect or reconnect a server. Adds eight tools backed by the same store the REST handlers use: list, get, create, update, delete, tools, test, reconnect. Parity with the REST path where it matters for safety: - ValidateServerConfig on create, and on update against the merged config so a partial change can't slip past validation - the same column allowlist on update - pool eviction when url/credentials/settings change, and on delete - cache-invalidate broadcast so live agents see the change Credentials (api_key, header and env values) are masked on every read: a tool result lands in an LLM context and its transcript, which is not a place raw tokens belong. OAuth-protected servers are never discovered with their static headers — without a valid token the tools report authorization_required rather than listing tools the caller can't call. Surface parity: REST, web UI and CLI already cover this resource; this adds the missing MCP surface only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
clark-cant
left a comment
There was a problem hiding this comment.
Summary
Adds eight MCP CRUD tools for server management, with validation, credential masking, pool eviction, OAuth-aware discovery, and tests.
Risk level
Medium — security-sensitive admin surface and a large new handler family.
Mandatory gates
- Duplicate / prior implementation: clear; related MCP OAuth and tool-listing work exists, but no duplicate CRUD implementation found.
- Project standards: docs/codebase conventions reviewed; CI is green.
- Strategic necessity: clear value; keeps server lifecycle management inside MCP and preserves REST safety parity.
Findings
Important
internal/mcp/crud_mcp_servers.gois a 698-line new handler file. This exceeds the repository\u0027s apparent maintainability/file-size conventions and combines registration, argument decoding, validation/merge logic, masking, discovery, pool lifecycle, and eight handlers in one module. Split by domain (for example registration/args, CRUD handlers, discovery/masking) or otherwise reduce the module size before merge so future security review and testing do not become a single large hotspot.
Suggestion
- Keep the generated/Claude attribution out of the commit message if this repository does not use it consistently; it is process noise rather than implementation context.
Verdict
Request changes — split the new handler hotspot while preserving the current tests and CI coverage.
clark-cant
left a comment
There was a problem hiding this comment.
✅ Approved — Clean implementation that fills the MCP CRUD gap. Code quality is solid: credential masking, ValidateServerConfig on create/update, pool eviction on credential changes, cache-invalidate broadcast. Tests cover masking, grant counts, structured field storage, slug rejection, and full family registration. No anti-slop patterns. Strategic value is clear.
Gates:
- Duplicate/prior implementation: clear — no prior MCP server CRUD tools
- Project standards: follows existing CRUD patterns (matches goclaw_providers_, goclaw_api_keys_)
- Strategic necessity: clear value — agents can now manage MCP servers without leaving MCP
Posted by github-maintain at $(date -u +'%Y-%m-%dT%H:%M:%SZ')
Problem
MCP server CRUD is reachable only over REST (
/v1/mcp/servers). The CRUD MCP server at/api/mcp/exposes agents, skills, cron, api_keys, providers, secure_cli and more — but not MCP servers themselves. An agent can mint an admin API key withgoclaw_api_keys_createand then has to leave MCP entirely to register, inspect or reconnect a server.Change
Eight tools in
internal/mcp/crud_mcp_servers.go, backed by the samestore.MCPServerStorethe REST handlers use:goclaw_mcp_servers_listGET /v1/mcp/serversgoclaw_mcp_servers_getGET /v1/mcp/servers/{id}goclaw_mcp_servers_createPOST /v1/mcp/serversgoclaw_mcp_servers_updatePUT /v1/mcp/servers/{id}goclaw_mcp_servers_deleteDELETE /v1/mcp/servers/{id}goclaw_mcp_servers_toolsGET /v1/mcp/servers/{id}/toolsgoclaw_mcp_servers_testPOST /v1/mcp/servers/testgoclaw_mcp_servers_reconnectPOST /v1/mcp/servers/{id}/reconnectGated on
CRUDDeps.MCPServerslike every other family;MCPManager/MCPPool/MCPOAuthare optional refinements (live tool listing, pool eviction, OAuth-backed discovery).Safety parity with the REST path
ValidateServerConfigon create, and on update against the merged config (update fields over the stored row) so a partial change can't slip past validationEvictServer) when url/credentials/settings/transport change, and on deleteDeliberate differences
api_key, header and env values; keys preserved). A tool result lands in an LLM context and its transcript — not a place raw tokens belong. Matchesgoclaw_providers_*.authorization_required: truerather than listing tools the caller cannot invoke, mirroring the REST tool-list endpoint._testreturns{success:false, error}rather than a tool error for a rejected config — the caller asked whether a config works, and "no" is an answer._reconnectwithout a pool reportsstatus: "no_pool"instead of claiming a reconnect that didn't happen.Tests
internal/mcp/crud_mcp_servers_test.go— masking (and that masking doesn't mutate stored rows), grant counts, structured field storage, slug rejection, non-allowlisted command rejection, allowlist filtering on update, merged-config validation, no-op update, delete, test-as-result, no-pool reconnect, full family registration.go build ./...,go build -tags sqliteonly ./...,go vetandgo test ./internal/mcp/ ./internal/gateway/all pass.Surface parity
REST, web UI and CLI already cover this resource — this adds the missing MCP surface only.
🤖 Generated with Claude Code