Skip to content

docs: plan MCP source reconciliation - #1527

Open
JAORMX wants to merge 8 commits into
mainfrom
plan/mcp-source-reconciliation
Open

JAORMX wants to merge 8 commits into
mainfrom
plan/mcp-source-reconciliation

Conversation

@JAORMX

@JAORMX JAORMX commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Stage

Plan / Interface — scope amendment

Summary

  • retain automatic ToolHive polling and MCP list-change notification reconciliation
  • preserve existing exact-name authority: removals filter availability, previously granted names can reappear, and explicit /mcp-refresh admits additions
  • replace the earlier durable digest/revocation/migration design with immutable runtime replacement and bounded run/operation pinning
  • retain one client-visible /mcp-refresh while direct and broker backend lifecycles remain separate
  • define candidate failures, no-op polling, retirement backpressure, explicit union persistence confirmation, and cancellation outcomes
  • synchronize with main without rewriting reviewed history; renumber the proposed MCP ADR to 0345 to avoid main's ADR 0342 collision

The earlier endpoint-identity amendment is superseded: no new credential-free URL policy or routing digest is introduced by this scope.

Verification

  • acceptance-plan checker and fixture suite: passed
  • task docs: passed
  • advisory design and security review: completed; persistence, unchanged-poll, cancellation, and retirement clarifications folded into the contract
  • git diff --check: passed

The directing human authorizes implementation stacked on this Plan PR before merge. Implementation records the exact amended plan commit; neither this PR nor the implementation is automatically merged. The old wider implementation is preserved separately and is not the amended delivery.

Tracking: #1511

JAORMX and others added 2 commits September 14, 2026 22:19
Co-Authored-By: mecatl <noreply@stacklok.com>
Co-Authored-By: mecatl <noreply@stacklok.com>

@jhrozek jhrozek left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few plan-review questions from a panel review (Spec/Standards/Test-adequacy/Domain), focused on scope-vs-issue framing and test-name granularity. No blockers — the broker-isolation concerns I initially had turned out to be moot once I confirmed mcp.mode is a mutually-exclusive global/broker switch, so broker and direct-MCP authority never coexist in the same session. Raised separately, as a top-level comment: a UX idea to unify /mcp-refresh and /tools-connect into one client-visible command.

🤖 Generated with Claude Code

Comment thread docs/acceptance/mcp-source-reconciliation.md Outdated
Comment thread docs/acceptance/mcp-source-reconciliation.md Outdated
Comment thread docs/acceptance/mcp-source-reconciliation.md Outdated
Comment thread docs/adr/0342-mcp-source-reconciliation.md Outdated
@jhrozek

jhrozek commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

UX idea: unify /mcp-refresh and /tools-connect

Went through this plan against ADR 0335/#1530 (idle-session broker workspace refresh) with a focus on broker interaction, since both introduce an idle-session-only, owner-authorized "refresh my MCP tool set" control around the same time.

Once I confirmed mcp.mode makes broker and global/direct MCP mutually exclusive at the deployment level (internal/cliconfig/mcp_authority.go's ResolveMCPAuthority), the isolation concerns I initially had turned out to be moot — a session's Authority.CapabilitySet.Tools is never shared between the two, so there's no collision risk.

But that same fact raises a UX question: since which mode is running is (and should stay) an implementation detail, should the two refresh mechanisms present as the same command to the user?

Today, per this plan + ADR 0335:

  • Broker mode → /tools-connect
  • Global mode → /mcp-refresh

Two different verbs for the same underlying user intent ("re-check and re-admit my MCP tool set"), and which one exists on a given deployment is exactly the kind of thing mode-hiding is supposed to avoid surfacing. The same asymmetry shows up in the mecatui Ctrl+O//mcp panel too — renderMCPPanel hard-branches on st.brokerMode into two differently-shaped renderers (renderBrokerMCPPanel has an in-panel x keybinding to cancel a pending broker setup; the direct-mode inventory view has no equivalent affordance for the new generation/stale/degraded status this plan adds).

Proposal: make /mcp-refresh the one client-visible name in both modes (mecatui dispatches to whichever backend RPC the negotiated capability indicates), with /tools-connect becoming a deprecated alias — cheap to do now since #1530 hasn't merged yet. The underlying operations can and should stay separate (broker refresh is destructive and can launch external OAuth consent; direct refresh is a quick bounded set-algebra replace with no consent) — that's a real difference worth preserving in behavior and help text, just not in the command name. ServerCapabilities.mcp_refresh would also want to be derived the mirror-image way WorkspaceEnrollment already is (internal/app/build.go:2607, brokerProcess.WorkspaceEnrollmentRequired()) — true iff mcp.mode: global — so the two capability bits stay reliably mutually exclusive on the client side too.

Happy to take this on as a follow-up once this PR merges, if that's useful.

🤖 Generated with Claude Code

Co-Authored-By: OpenAI <noreply@openai.com>
@JAORMX

JAORMX commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

Adopted in f37c7d9ef. Mecatui now has one client-visible /mcp-refresh contract: direct mcp_refresh routes only to RefreshMcpSources; broker workspace_enrollment routes only to ConnectWorkspaceServices. /tools-connect remains a deprecated broker-only compatibility alias.

The operations remain separate. Broker routing preserves ADR 0335 consent/presentation, cancellation via /tools-cancel, and destructive replacement disclosure; direct refresh is consent-free. Both capability bits, missing collaborators, and other contradictory capability states fail closed, with no fallback or double operation.

The stacked implementation follows this updated plan; it has not merged.

JAORMX and others added 5 commits September 16, 2026 09:28
Co-Authored-By: mecatl <noreply@stacklok.com>
Renumber the proposed MCP ADR to 0345 and preserve both acceptance-plan index entries.

Co-Authored-By: mecatl <noreply@stacklok.com>
Co-Authored-By: mecatl <noreply@stacklok.com>
Co-Authored-By: mecatl <noreply@stacklok.com>
Renumber the proposed reconciliation ADR to 0346 after main allocated 0345; the technical contract is unchanged.

Co-Authored-By: OpenAI Codex <codex@openai.com>

@jhrozek jhrozek left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-approving after the latest push (316f99d) — reviewed the addressed-findings commit f37c7d9 previously; no new concerns since.

@jhrozek

jhrozek commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

ADR numbering collision: 0346 used twice

This PR adds docs/adr/0346-mcp-source-reconciliation.md, but main already has docs/adr/0346-unified-prompt-cache-dialect.md (landed via #1572, merged 2026-09-17, after this PR's ADR was numbered). Git reports no merge conflict (different filenames), but merging as-is leaves two ADRs both numbered 0346 on main.

This PR's ADR should be renumbered (e.g. to 0347) — plus any cross-references to "ADR 0346" in this PR's own docs (the acceptance plan review comments already reference it by number) — before merging.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants