Files
Skald-Circle/crates/skald-core
dguiducci 6f35c53d93 activate_tools: diagnose a group instead of pretending it activated
A group name that resolved to no running MCP server was granted anyway,
persisted in `activated_tools`, and reported as a success with "registered
but not yet running — tools will appear after reconnect". Every part of
that was false: nothing registers connectors anymore (the agent-facing
`register_mcp` went away with §14), no reconnect will ever produce the
tools, and the model — believing it had succeeded — called `mcp__x__…` a
round later and failed there instead of here. The junk grant row stayed in
the session forever, resolving to zero tool defs on every projection.

`SkaldToolActivator` now resolves first and acts only on what resolved,
walking the connector states in order: the built-in `config` group, then
the servers running in this user's view, then `mcp_user_servers` (owner
pool), then `mcp_global_servers` + `mcp_global_access`, then `mcp_catalog`
+ `mcp_catalog_access` (registry pool), then unknown. Only `activated`
touches the in-memory grant set and the DB; everything else leaves no
trace at all.

The result is a JSON object keyed by group name — `status` (activated /
needs_login / not_activated / not_authorized / unavailable / unknown),
`tool_prefix`, `tool_count`, `description`, `message` — with the same
shape whether the call succeeded or not, so the model parses one thing
rather than prose. `message` is written to be relayed to a non-technical
user and says who can fix it: the user in Connectors, or the admin. When
no group at all activates, the tool fails with that same JSON, so the
model reports the diagnosis instead of proceeding. A diagnosis query that
errors is logged and falls through to the next candidate — a broken lookup
must never become a false claim about a connector.

The activator needs the registry pool, the user id and the config defs;
both construction sites are updated, so a sub-agent gets the same
diagnosis as the root agent.

Removes `tools/activate_tools.rs` and its interface-tool registration: it
was unreachable (`SkaldToolSet::find` prefers natives, and `NATIVE_NAMES`
explicitly drops the legacy interface tool of that name) but carried the
same wrong string, waiting to be fixed twice.
2026-07-26 21:41:53 +01:00
..