Skip to content

feat(connectors): surface MCP-consuming agents in the "Active for" panel (#1227)#1310

Open
alexey-tyurin wants to merge 2 commits into
amd:mainfrom
alexey-tyurin:feat/surface-mcp-consuming-agents
Open

feat(connectors): surface MCP-consuming agents in the "Active for" panel (#1227)#1310
alexey-tyurin wants to merge 2 commits into
amd:mainfrom
alexey-tyurin:feat/surface-mcp-consuming-agents

Conversation

@alexey-tyurin
Copy link
Copy Markdown
Contributor

Summary

Widens the Settings → Connectors "Active for" panel so it lists agents that consume MCP servers dynamically (like the chat agent), not only agents that statically declare REQUIRED_CONNECTORS. The chat agent now appears as an activatable target for MCP-only connectors loaded from ~/.gaia/mcp_servers.json.

Why

Before this change, the "Active for" panel only listed agents whose class declared the connector in REQUIRED_CONNECTORS. The chat agent (builtin:chat) declares none for MCP servers — it loads them at runtime and already gates their tools through the activation ledger (_active_mcp_serversMCPClientManager.servers_for_agentis_agent_active). So a user could activate builtin:chat for an MCP connector via the CLI/SDK and it worked, but the Settings UI never showed the chat agent as eligible — a UI-only user had no way to toggle it. The runtime was correct; the panel just couldn't see these agents.

This PR closes that surfacing gap by adding a CONSUMES_MCP_SERVERS capability flag that flows from the agent class through the registry and API to the frontend, exactly the way REQUIRED_CONNECTORS already does. No activation, ledger, or SSE logic changes — those already work end-to-end (#1005, #1226).

Follow-up to #1219, which introduced per-agent MCP tool-visibility activations.

Linked issue

Closes #1227

Changes

  • New capability flag, surfaced like REQUIRED_CONNECTORS: Agent.CONSUMES_MCP_SERVERS ClassVar (False by default), set True on ChatAgent. The registry carries it as AgentRegistration.consumes_mcp_servers — hardcoded for the built-in chat (its lazy factory must not import the chat module at discovery time; a guard test keeps the two in sync) and read via class introspection on the custom-agent discovery path, so builder-scaffolded MCP agents surface automatically too.
  • API exposure: AgentInfo.consumes_mcp_servers (Pydantic) + the /api/agents serializer (_reg_to_info), and the matching TypeScript AgentInfo field.
  • Frontend: ConnectorsSection.tsx computes a separate, wider activatableAgents set for the "Active for" block (an agent is eligible if it declares the connector or sets consumes_mcp_servers); the "Per-agent grants" credential section is unchanged. AgentActivationCard no longer bails when an agent has no static requirement, and its one-click auto-grant falls back to the canonical MCP use scope for dynamic consumers (named constant, not a magic string).
  • Docs: docs/sdk/infrastructure/connectors.mdx documents the new CONSUMES_MCP_SERVERS flag in the agent-author guide and adds a "Which agents appear in the Active for panel" section covering both inclusion patterns.
  • Tests: base default, chat flag, class↔registration consistency guard, "no other built-in consumes MCP", custom-agent round-trip (True and default False), AgentInfo round-trip, and _reg_to_info exposure for a consumer vs a non-consumer.

Test plan

  • python util/lint.py --all — Black/isort clean, no new critical errors.
  • pytest tests/unit/test_agent_required_connectors.py tests/unit/test_agent_hub_api.py -q — 30 passed.
  • pytest tests/unit/connectors/ -q — 429 passed, 3 skipped (no regressions).
  • cd src/gaia/apps/webui && npm run buildtsc && vite build clean.
  • Manual golden path: add an MCP server to ~/.gaia/mcp_servers.json and configure it as an MCP connector → gaia chat --ui → Settings → Connectors → open the MCP tile. Confirm Chat now appears under "Active for"; toggle it ON. Verify gaia connectors activations list <connector_id> shows builtin:chat: active and the toggle survives a page reload (SSE refresh). Toggle OFF and confirm deactivation. Confirm an OAuth connector still shows no "Active for" section.

Checklist

  • I have linked a GitHub issue above (Closes #N / Fixes #N / Refs #N).
  • I have described why this change is being made, not just what changed.
  • I have run linting and tests locally (python util/lint.py --all, pytest tests/unit/).
  • I have updated documentation if user-visible behavior changed (see CONTRIBUTING.md).

@github-actions github-actions Bot added documentation Documentation changes tests Test changes agents labels May 31, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Clean, focused implementation that closes a genuine UX gap — the chat agent's "Active for" panel invisibility — without touching any activation, ledger, or SSE logic. The flag-follows-data pattern (ClassVar → AgentRegistration → Pydantic → TS type → frontend filter) is the right shape for this kind of capability surface, and the test suite is unusually thorough.


Issues

🟢 Minor — Multi-line comments on the new ClassVar exceed the one-line-max CLAUDE.md standard (agent.py:52–57, chat/agent.py:79–82)

The adjacent REQUIRED_CONNECTORS ClassVar in agent.py:49 is described in one line (# Empty list = no external connections required (the default for built-ins).). The new flag gets five. CLAUDE.md says "one short line max" for WHY comments.

src/gaia/agents/base/agent.py:52–57 — suggestion:

    # Registry reads this to include dynamic MCP consumers in the Settings "Active for" panel.
    CONSUMES_MCP_SERVERS: ClassVar[bool] = False

src/gaia/agents/chat/agent.py:79–82 — suggestion:

    # Dynamic MCP loader — registry exposes this for the Settings "Active for" panel.
    CONSUMES_MCP_SERVERS: ClassVar[bool] = True

Strengths

  • Guard test is the right call. test_builtin_chat_registration_matches_class explicitly checks that the hardcoded registry value matches ChatAgent.CONSUMES_MCP_SERVERS — exactly the kind of sync risk a lazy factory creates, and exactly the right place to catch drift.
  • MCP_DEFAULT_GRANT_SCOPES constant. Naming the canonical scope rather than inlining ['use'] is the correct move; the comment on it explains the "why" for dynamic consumers in one sentence.
  • activatableAgents separation from relevantAgents. The frontend neatly keeps credential-grant eligibility (static required_connections) separate from activation eligibility (wider), and the connectorType === 'mcp_server' guard is baked into activatableAgents's ternary rather than duplicated at the render site.
  • Test breadth. Base default, chat value, class↔registration sync, no-other-builtins regression guard, custom-agent round-trips (True and False), API serialization — these cover every layer the flag touches.

Verdict

Approve with suggestions. The two multi-line comment nits are the only findings; no bugs, no architectural concerns. Safe to merge after applying the one-liner suggestions (or skipping them — they're style-only).

@github-actions
Copy link
Copy Markdown
Contributor

Clean, well-scoped implementation. The design correctly separates the two inclusion paths (static REQUIRED_CONNECTORS vs. dynamic CONSUMES_MCP_SERVERS) without touching any activation, ledger, or SSE logic — exactly the right blast radius for a UI surfacing gap. One nit worth a one-line fix; everything else is solid.


Issues

🟢 Minor — Unnecessary defensive getattr in _reg_to_info (src/gaia/ui/routers/agents.py:115)

Every other field serialised by _reg_to_info uses direct attribute access (reg.min_memory_gb, reg.required_connections, reg.namespaced_agent_id). Since consumes_mcp_servers is now a proper dataclass field with a default, the getattr fallback is redundant and slightly misleading.

        consumes_mcp_servers=reg.consumes_mcp_servers,

🟢 Minor — Verbose comment block on AgentRegistration.consumes_mcp_servers (src/gaia/agents/registry.py:278–282)

GAIA convention (CLAUDE.md "Code Comments") is one short WHY line per field. The 5-line block mirrors what the field name and type already say; the neighbouring required_connections comment runs two lines. Trimming keeps the dataclass scannable.

    # Surfaced from the agent's CONSUMES_MCP_SERVERS ClassVar; True for dynamic MCP loaders.
    consumes_mcp_servers: bool = False

Same trimming applies to the parallel comment in src/gaia/ui/models.py:255–258 (4 lines; one line is enough for the same reason).


Strengths

  • test_builtin_chat_registration_matches_class is the right kind of guard test: it catches exactly the failure mode (hardcoded flag drifts from the class definition) that the lazy-factory workaround creates, without coupling the test to internal module paths.
  • Two-list design in ConnectorsSection.tsx (relevantAgents for per-credential grants, activatableAgents for the "Active for" panel) keeps the two sections independent and makes the intent immediately readable in the diff.
  • MCP_DEFAULT_GRANT_SCOPES named constant eliminates a magic ['use'] string from the activation callback; the JSDoc on AgentActivationCard is updated in the same commit to explain the fallback path.
  • TypeScript type is consumes_mcp_servers?: boolean (optional), so the frontend degrades gracefully against an older backend that doesn't send the field — the filter treats undefined as falsy and the agent simply won't appear.

Verdict

Approve. Both nits are stylistic and non-blocking. The implementation is correct, the guard test is smart, and the test matrix covers all four cases (base default, chat builtin, custom consumer, custom non-consumer) plus the serialisation round-trip.

@alexey-tyurin
Copy link
Copy Markdown
Contributor Author

@kovtcharov-amd -- My original commit
50fb140
for this PR got reported "All checks have passed" and Verdict "Approve with suggestions. The two multi-line comment nits are the only findings...".
So, I made suggested fixes in comments only, and this new commit somehow got Failed check:
Test GAIA CLI on Windows (Full Integration).
But it also got Verdict "Approve."
This failed test looks like a glitch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents documentation Documentation changes tests Test changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(connectors): widen "Active for" panel to surface MCP-consuming agents, not just REQUIRED_CONNECTORS declarants

1 participant