Thanks to visit codestin.com
Credit goes to github.com

Skip to content

feat(connectors): per-MCP enable/disable toggle in Settings UI (#1004)#1018

Merged
itomek merged 5 commits into
mainfrom
feat/1004-mcp-enable-disable-toggle
May 11, 2026
Merged

feat(connectors): per-MCP enable/disable toggle in Settings UI (#1004)#1018
itomek merged 5 commits into
mainfrom
feat/1004-mcp-enable-disable-toggle

Conversation

@itomek

@itomek itomek commented May 8, 2026

Copy link
Copy Markdown
Collaborator

Closes #1004. Part of #927. Builds on PR #998 — please merge that first.

Users can now temporarily disable a configured MCP connector without losing its credentials or per-agent grants. Concrete user flow: toggle off GitHub MCP during a sensitive code review → toggle back on without re-pasting the PAT or re-granting agents.

The disabled flag was already persisted in mcp_servers.json and MCPClientManager.load_from_config() already skipped disabled entries. This PR adds the API/UI/live-reload wiring to drive it.

What lands

  • Toggle row in the connector detail view (above credentials), only when configured. Shows helper text when off.
  • Tile-level overflow menu (⋯) for one-click enable/disable/disconnect without drilling in.
  • Tile status pill flips to a warm-muted "Disabled" state (distinct from cool-muted "Not configured" so users see at a glance these are different states).
  • POST /api/connectors/{id}/enable and /disable (CSRF-guarded, 400 on non-MCP types, 404 on unconfigured ids).
  • Live reload — the lifespan wires a broadcast helper that calls manager.reload() on every cached ChatAgent's per-instance MCPClientManager. Toggling takes effect without restarting GAIA.

Test plan

  • python -m pytest tests/unit/connectors/test_enable_disable.py -v — 12 handler tests pass
  • python -m pytest tests/unit/connectors/test_router_connectors.py::TestEnableDisable -v — 8 router tests pass
  • python -m pytest tests/unit/connectors/test_handler_reload_wired.py -v — 4 wiring tests pass
  • Manual: configure mcp-github with a PAT → ChatAgent uses tools → click ⋯ on the GitHub tile → Disable → ChatAgent no longer sees GitHub tools (no restart) → Enable → tools return → restart GAIA → state persists.
  • cd src/gaia/apps/webui && npx tsc --noEmit && npm run build
  • python util/lint.py --all

@github-actions github-actions Bot added tests Test changes electron Electron app changes labels May 8, 2026
@itomek itomek force-pushed the feat/1004-mcp-enable-disable-toggle branch from d7d8c67 to 719851e Compare May 8, 2026 18:19
@github-actions github-actions Bot added documentation Documentation changes installer Installer changes dependencies Dependency updates devops DevOps/infrastructure changes jira mcp MCP integration changes cli CLI changes eval Evaluation framework changes security Security-sensitive changes performance Performance-critical changes website GAIA website (amd-gaia.ai) agents labels May 8, 2026
@itomek itomek self-assigned this May 8, 2026
@itomek itomek marked this pull request as ready for review May 8, 2026 20:44
@itomek itomek requested a review from kovtcharov-amd as a code owner May 8, 2026 20:44
Base automatically changed from feat/976-mcp-single-writer-security to main May 8, 2026 21:18
kovtcharov
kovtcharov previously approved these changes May 8, 2026
@itomek itomek enabled auto-merge May 8, 2026 21:40
@itomek itomek disabled auto-merge May 8, 2026 21:40
itomek added 5 commits May 8, 2026 17:40
Closes #1004. Part of #927. Builds on #976 (PR #998).

Users can now temporarily disable a configured MCP connector without
losing its credentials or per-agent grants. Toggle off the GitHub MCP
during a sensitive code review, toggle back on without re-pasting the
PAT — credentials and agent consent persist across the round-trip.

Persistence already worked: ``mcp_servers.json`` carries a per-entry
``disabled`` flag and ``MCPClientManager.load_from_config()`` already
skips disabled entries. This PR adds the API/UI/wiring to drive it.

Backend:
- ``McpServerHandler.set_enabled(connector_id, enabled)`` flips the
  ``disabled`` flag without touching keyring or grants. Reuses #976's
  atomic-write + chmod 0600 helpers; raises ``ConnectorsError`` on
  unknown / unconfigured ids
- ``McpServerHandler.set_reload_callback`` setter so the FastAPI
  lifespan can attach a callback after the singleton handler imports
- New endpoints ``POST /api/connectors/{id}/enable`` and ``/disable``
  (CSRF-guarded, 400 on non-MCP types, 404 on unconfigured)
- New SSE events ``connector.enabled`` / ``connector.disabled``
- ``_connector_summary`` exposes ``enabled: bool`` (defaults true for
  OAuth / not-yet-configured MCP so no spurious "Disabled" pills)
- ``reload_all_session_agents_mcp`` broadcasts to every cached
  ChatAgent's per-instance MCPClientManager — wired as the handler's
  reload_callback at lifespan startup. Toggling takes effect live; no
  GAIA restart needed

Frontend:
- ``ConnectorRow.enabled: boolean`` on the wire
- ``enableConnector`` / ``disableConnector`` API helpers
- SSE consumer recognises ``'enabled' | 'disabled'`` reasons
- Toggle row in MCPServerConfigureBody (only when configured), with
  helper text when disabled. Reuses existing ``.toggle-switch`` CSS
- New ConnectorTileMenu (⋯) on each tile header for one-click
  enable/disable/disconnect without drilling in. Self-positioning
  popup, click-outside + Escape to close
- New ``.connector-status.disabled`` pill in the tile header

Tests: 30 new (12 handler + 14 router + 4 reload-wiring). Full
connectors suite: 335 pass, 5 skipped, 1 pre-existing failure
(test_oauth_pkce, unrelated).
The popup was using position:absolute inside .connector-tile which has
overflow:hidden, clipping the dropdown entirely. Switch to position:fixed
with coordinates from getBoundingClientRect() on the trigger button.

Adds scroll+resize listeners (capture:true to catch the settings-page-body
scroller) that reposition the popup while open so it stays anchored to the
trigger as the user scrolls the Settings panel.
)

Custom Python agents that bundle their own mcp_servers.json were invisible
in Settings → Connectors — users had no way to see which servers were
active without reading the file directly.

A new read-only "Custom agent servers" section now appears below the
managed connectors list. Each tile shows the server name, originating
agent, Active/Disabled status, and expands to reveal the command + args
and the config file path with an edit hint. No toggle or disconnect action
— the agent's local JSON is the source of truth.

Backend: GET /api/connectors/agent-mcps scans registered custom agents
for mcp_servers.json, returns a flat list sorted enabled-first then
alphabetical. Malformed files and non-dict entries are skipped gracefully.

Frontend: AgentMcpServer type, listAgentMcps() API helper,
AgentMcpsSection + AgentMcpTile components, and matching CSS.

Tests: 10 new unit tests cover sorting, disabled flag, malformed JSON
resilience, per-entry type guards, legacy 'servers' key, and the
no-registry case.
)

Neither entry had a built-in consumer: the File Agent and Web Agent use
Python-native tool mixins (FileIOToolsMixin, FileSearchToolsMixin) and do
not go through the connectors framework. Showing them as "Not configured"
tiles confused users into thinking their File/Web agents needed setup.

Custom agents that want file or web MCP access supply their own
mcp_servers.json — visible in the new Custom Agent Servers section added
in #1020. The catalog contract is now explicit in the module docstring:
only entries with at least one built-in REQUIRED_CONNECTORS declaration belong here.

Ledger test updated: KEPT_IDS shrinks from 5 → 3; the two removed ids
move to DELETED_IDS with rationale comments.
@itomek itomek enabled auto-merge May 8, 2026 21:40
@itomek itomek force-pushed the feat/1004-mcp-enable-disable-toggle branch from 50d3e34 to 3d90581 Compare May 8, 2026 21:40
@itomek itomek added this pull request to the merge queue May 11, 2026
Merged via the queue into main with commit 6ad10fc May 11, 2026
25 checks passed
@itomek itomek deleted the feat/1004-mcp-enable-disable-toggle branch May 11, 2026 12:53
@itomek itomek mentioned this pull request May 14, 2026
6 tasks
pull Bot pushed a commit to bhardwajRahul/gaia that referenced this pull request May 15, 2026
## Why this matters

v0.18.0 ships agent memory v2 (hybrid-search second brain with LLM
extraction and observability dashboard), ChatAgent split into three
composable agents (Chat/FileIO/DocumentQA), parallel tool calls, and a
Telegram adapter scaffold — plus fixes the RAG-on-PDF timeout with Gemma
4 that broke document Q&A since v0.17.6 and adds CI gates that enforce
RAG quality baselines on every future PR.

Full notes: `docs/releases/v0.18.0.mdx`.

## What's New

- **Agent memory v2** ([amd#606](amd#606)) —
Hybrid semantic + keyword search, LLM extraction, observability
dashboard via SSE streaming
([amd#1032](amd#1032)). Per-user isolation
enforced; extraction runs async so it doesn't add latency.
- **ChatAgent split** ([amd#979](amd#979)) —
`ChatAgent`, `FileIOAgent`, and `DocumentQAAgent` replace the monolithic
class; each composable via `tools=`. Backward-compatible shim preserved.
- **Parallel tool calls** ([amd#946](amd#946))
— Multiple `tool_calls` from a single LLM turn are executed
concurrently, cutting round-trips for multi-tool workflows.
- **Telegram adapter scaffold, Phase 0**
([amd#951](amd#951)) — `gaia telegram
start|stop|status`, per-user session isolation, `[telegram]` extras.
Phase 1 (message handling + allowed-users gate) tracked in
[amd#889](amd#889).
- **Connectors: per-MCP toggle + single-writer enforcement**
([amd#1018](amd#1018),
[amd#998](amd#998)) — Disable individual MCP
servers without removing them; concurrent writes serialised with
actionable errors on contention.
- **File navigation, web browsing, and write security**
([amd#495](amd#495)) — `FileSearchToolsMixin`,
web browsing tool, and scratchpad mixin in `KNOWN_TOOLS`; write tools
check `allowed_paths` before dispatch.
- **Email UI and policy alerts**
([amd#995](amd#995),
[amd#1039](amd#1039),
[amd#952](amd#952)) — Pre-scan triage card,
in-chat Connect, policy alert cards, and durable receipts for
confirmation-gated actions.

## Bug Fixes

- **RAG-on-PDF timeouts on Gemma 4**
([amd#1034](amd#1034), closes
[amd#1030](amd#1030)) — Prompt-size budget
check added at composition time; CI gates enforce it on every PR
([amd#1040](amd#1040)).
- **Envelope-level parse failure crashed SD recovery**
([amd#1047](amd#1047), closes
[amd#1023](amd#1023)) — Falls through to a
clean recovery path with step-1 context preserved.
- **Windows-path tool args corrupted**
([amd#1027](amd#1027)) — Backslash
normalisation now happens after argument parsing.
- **Blender `send_command` hung**
([amd#1026](amd#1026), closes
[amd#1022](amd#1022)) — Read timeout applied
to persistent-connection servers.
- **`gaia chat init` in post-install banner**
([amd#1029](amd#1029), closes
[amd#1024](amd#1024)) — Replaced with the
correct `gaia init`.
- **Keyring treated as required**
([amd#1028](amd#1028)) — Import guarded;
optional on systems without `keyring`.
- **electron-builder URLs stale**
([amd#953](amd#953)) — Three doc/installer
files updated to current download paths.

## Tooling & Docs

- **RAG eval CI gates** ([amd#1040](amd#1040),
closes [amd#1033](amd#1033)) — RAG quality
baselines + prompt-size budget enforced on every PR.
- **Fork-PR authors now receive Claude review**
([amd#932](amd#932)) —
`allowed_non_write_users: "*"` with prompt-injection mitigations
documented.
- **Eval runs mandated before merging**
([amd#1036](amd#1036)) — `CLAUDE.md` requires
`gaia eval agent` for LLM-affecting changes.
- **GAIA website** ([amd#369](amd#369)) —
[amd-gaia.ai](https://amd-gaia.ai) live.
- **Custom agent guide reorganised**
([amd#997](amd#997)), Lemonade PPA docs
([amd#801](amd#801)), broken Lemonade CLI URL
fixed ([amd#996](amd#996)), WhatsApp adapter
evaluation spec ([amd#950](amd#950)).

## Release checklist

- [x] `util/validate_release_notes.py docs/releases/v0.18.0.mdx --tag
v0.18.0` passes
- [x] `src/gaia/version.py` → `0.18.0`
- [x] `src/gaia/apps/webui/package.json` → `0.18.0`
- [x] Navbar label in `docs/docs.json` → `v0.18.0 · Lemonade 10.2.0`
- [x] All 28 commits in range (v0.17.6..HEAD) are represented in the
notes
- [ ] Review from @kovtcharov-amd addressed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents cli CLI changes dependencies Dependency updates devops DevOps/infrastructure changes documentation Documentation changes electron Electron app changes eval Evaluation framework changes installer Installer changes mcp MCP integration changes performance Performance-critical changes security Security-sensitive changes tests Test changes website GAIA website (amd-gaia.ai)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(connectors): per-MCP enable/disable toggle in Settings UI

3 participants