Summary
MCP servers never appear in the UI's MCP Servers list. Creating one through the UI succeeds and the RemoteMCPServer resource is created correctly, but the list stays at 0 of 0 servers · 0 tools — and so does a fresh install, where the chart's own kagent-tool-server and kagent-grafana-mcp are also missing.
This is not a UI defect: the UI renders exactly what ListToolServers returns, and that RPC returns an empty list.
Reproduce
- Install the chart on a fresh cluster.
- Open MCP Servers. The list is empty, although the chart installed
kagent-tool-server and kagent-grafana-mcp.
- Add server → name
probe-server, URL mcp.example.com/sse → Create server.
CreateToolServer returns 200 and the page returns to the list.
kubectl get remotemcpservers.kagent.dev -n kagent shows probe-server with the correct URL.
- The list still shows
0 of 0 servers · 0 tools.
Where it is lost
ListToolServers reads the database, not the cluster:
ListToolServers (grpcserver/tool.go:53)
→ Service.ListToolServers (service/tool/service.go:113)
→ discoveryStore.ListToolServers → the `toolserver` table
On the cluster above, four RemoteMCPServer resources exist and the table has zero rows:
$ kubectl get remotemcpservers.kagent.dev -n kagent --no-headers | wc -l
4
$ psql -c 'select count(*) from toolserver;'
0
The RPC response body is 26 bytes — an empty list, faithfully rendered.
Root cause
StoreToolServer is the only writer of that table, and it has no production caller. Every reference in the module is either its own implementation or its own unit tests:
core/internal/database/client_postgres.go:1632 func (c *postgresClient) StoreToolServer(...)
core/internal/database/client_test.go (tests only)
api/database/client.go:43 (interface declaration)
The caller was removed in 26732e86 — chore: remove legacy ACP and controller runtime (#2565) — which deleted go/core/internal/controller/mcp_server_tool_controller.go and .../reconciler/reconciler.go, containing:
- if _, err := a.dbClient.StoreToolServer(ctx, toolServer); err != nil {
Nothing took over populating the table, but the read path still expects it to be populated. So the list can only ever be empty.
Impact
- Every MCP server is invisible in the UI, including the two the chart installs, on every install.
- A server created through the UI looks like it failed, because the only feedback is a list it never joins.
ListTools is affected the same way — the tool table is also empty (0 rows).
Version
Observed on 2a259337ff496344132064ec53f53c820984156d.
🤖 written by Claude
Summary
MCP servers never appear in the UI's MCP Servers list. Creating one through the UI succeeds and the
RemoteMCPServerresource is created correctly, but the list stays at0 of 0 servers · 0 tools— and so does a fresh install, where the chart's ownkagent-tool-serverandkagent-grafana-mcpare also missing.This is not a UI defect: the UI renders exactly what
ListToolServersreturns, and that RPC returns an empty list.Reproduce
kagent-tool-serverandkagent-grafana-mcp.probe-server, URLmcp.example.com/sse→ Create server.CreateToolServerreturns 200 and the page returns to the list.kubectl get remotemcpservers.kagent.dev -n kagentshowsprobe-serverwith the correct URL.0 of 0 servers · 0 tools.Where it is lost
ListToolServersreads the database, not the cluster:On the cluster above, four
RemoteMCPServerresources exist and the table has zero rows:The RPC response body is 26 bytes — an empty list, faithfully rendered.
Root cause
StoreToolServeris the only writer of that table, and it has no production caller. Every reference in the module is either its own implementation or its own unit tests:The caller was removed in
26732e86— chore: remove legacy ACP and controller runtime (#2565) — which deletedgo/core/internal/controller/mcp_server_tool_controller.goand.../reconciler/reconciler.go, containing:- if _, err := a.dbClient.StoreToolServer(ctx, toolServer); err != nil {Nothing took over populating the table, but the read path still expects it to be populated. So the list can only ever be empty.
Impact
ListToolsis affected the same way — thetooltable is also empty (0 rows).Version
Observed on
2a259337ff496344132064ec53f53c820984156d.🤖 written by Claude