Skip to content

feat(tui): manage client-owned MCP servers with /mcp #3838

Description

@me2seeks

Problem

Maka now supports legacy | auto | 2026-07-28 MCP protocol preferences for both remote and stdio servers, but the TUI has no MCP management surface. Desktop owns an McpConfigStore and McpClientManager; the CLI only exposes the low-level runtime-host capability-provider serve command, which reads an existing config and must be managed as a separate process.

As a result, a TUI user cannot discover, add, enable, disable, remove, or reconnect MCP servers, and cannot tell whether configured tools are connected and published to the selected Runtime Host.

There is also an authority constraint to preserve: MCP configuration, credentials, transports, and child processes belong to the client machine. Runtime Host remains the authority for Run composition, execution, provider binding, and recovery after a Client Capability is published. A terminal-client credential intentionally cannot publish Client Capabilities.

Desired outcome

Add /mcp to the TUI slash-command catalog. It should open an interactive management view over the current client workspace mcp.json:

MCP servers

  ● filesystem   stdio    connected      12 tools   legacy
  ○ docs         remote   disabled        0 tools   auto

  a Add   Enter Details   Space Enable/disable   r Reconnect   d Remove   Esc Close

The add flow should offer both:

  1. Guided setup
    • stable server ID
    • stdio or Streamable HTTP transport
    • command and arguments, or URL
    • legacy | auto | 2026-07-28 protocol preference
    • optional cwd/environment or request headers
  2. Paste JSON
    • accept either a wrapped mcp.json document or a direct server map through the existing import normalizer
    • preview which entries will be added or replaced before committing

Sensitive values must not enter the conversation transcript or diagnostics. Persistence should continue through the existing atomic, mode-0600 config store. After a committed mutation, the same TUI-side owner should synchronize McpClientManager and refresh the published Client Capability snapshot so the UI cannot report a config change as live before publication has caught up.

The view should distinguish at least: disabled, connecting, connected, reconnecting, error, and configured-but-not-published. Errors should stay attached to the affected server instead of failing the whole /mcp view.

Ownership and design constraints

  • Keep MCP config, credentials, transports, child processes, reconnects, and tool discovery client-owned. Do not move them into Runtime Host.
  • Keep Runtime Host as the execution authority for published Client Capability calls.
  • Reuse the existing deep modules: McpConfigStore for durable config, McpClientManager for MCP connection/discovery/call truth, and the existing Client Capability channel/publication lifecycle for Host registration.
  • Add one TUI-owned MCP control module that renders snapshots and serializes user intent across those existing modules. Do not make the /mcp handler reproduce lifecycle state.
  • Do not introduce a repository-wide provider abstraction up front. The standalone CLI provider, TUI, and Desktop have different lifecycle and composition requirements. Extract shared orchestration only after the vertical slice proves an identical invariant in at least two callers.
  • Do not migrate Desktop onto the TUI control module. Desktop combines MCP with Browser, Computer Use, Settings, and other native Client Capabilities in one registration lifecycle.
  • For a Local Host, publish on the same authenticated TUI connection that initiates the Session. This lets the Host select the initiating provider exactly and avoids inventing a detached companion identity.
  • Re-publish the TUI snapshot when that connection is replaced, without creating a parallel connection owner or replaying unrelated commands.
  • Do not assume that a detached remote capability_provider is automatically associated with a TUI Session. Runtime Host currently selects the initiating provider, or the only provider for a contract; two detached providers advertising the same contract are ambiguous. Remote publication therefore has an explicit design gate in PR 3.
  • Bind publication to the selected Host profile/root. Closing the TUI or switching targets must unregister/close the old publication before publishing to another target.
  • Reuse the existing MCP schema, normalizer, endpoint policy, OAuth credential storage, dual-era negotiation, and Client Capability projection. Do not introduce a TUI-only config format or a second publication authority.
  • /mcp is a local management command and should be refused while a turn is active, matching other state-changing TUI commands.

Proposed rollout

PR 1: local vertical slice — /mcp status and publication

  • Register /mcp in the shared slash-command catalog and add localized help/autocomplete copy.
  • Add a TUI-owned MCP control module that composes the existing config store, manager, and Client Capability channel.
  • Load the existing workspace mcp.json, connect enabled servers, and publish their tools on the same Local TUI connection that creates/controls Sessions.
  • Re-publish after a successful connection replacement and close/unregister deterministically with the TUI context.
  • Add a read-only list/details view with configured protocol, negotiated protocol, tool count, per-server diagnostics, and publication state.
  • Exercise one real local path from saved config through manager discovery, Host-visible publication, tool invocation, reconnect, and shutdown.
  • Keep Desktop and the standalone runtime-host capability-provider serve command unchanged. If this slice reveals genuinely identical orchestration, extract only that proven duplication within the same PR.

PR 2: TUI management actions

  • Add guided and JSON import flows.
  • Add enable/disable, edit, remove, test, and reconnect actions.
  • Serialize McpConfigStore mutation, manager synchronization, and capability refresh through the TUI control module.
  • Cover write failure, connection failure, stale completion, cancellation, and shutdown without duplicating tests already owned by the store, manager, or publication modules.

PR 3: remote Host provider association and publication

  • First settle one exact association from the selected TUI connection/Session to its least-privilege MCP provider. A detached provider that is merely connected to the same Host is not sufficient when another provider offers the same contract.
  • Preserve the rule that terminal-client cannot publish Client Capabilities; do not solve association by silently widening that preset.
  • If the selected design uses a separate capability_provider credential, keep it out of profile JSON, arguments, transcripts, and logs, and bind it to the exact profile/root and TUI-owned provider identity.
  • Surface missing/revoked credentials, provider ambiguity, and reconnects as explicit publication states.
  • Verify two concurrent providers, exact Session binding, invocation routing, reconnect, root mismatch, revocation, and cleanup against a real remote Runtime Host before enabling remote /mcp publication.

These can remain separate reviewable PRs, but every PR must leave one TUI lifecycle owner and one exact Host provider binding, with no parallel configuration or publication path for the same Session.

Confirmed adjacent MCP pain points

These are recorded here because /mcp must respect the same ownership boundaries, not because they should all be folded into the TUI rollout.

Pain point Current evidence Tracking / next unit of work Relationship to this issue
Desktop main-process OOM during prolonged Host flapping Real Windows crash after about 12 hours, about 3.6 GB V8 heap, and hundreds of candidate generations #3458; #3462 only reduced retry churn Separate P0 root-cause fix. Do not close #3458 based on slower retries.
One invalid optional MCP tool can poison a Desktop capability candidate Current capability projection validates the aggregate offer at the Host boundary #3366 Do not duplicate the active fix. /mcp should expose omitted/error tools per server.
JSON Schema 2020-12 compatibility is narrower than MCP's contract Host projection still uses an explicit keyword allowlist; #3559 and #3560 fixed concrete annotation cases Gather real server schemas before opening a broader compatibility change Do not widen the allowlist speculatively inside a TUI PR.
Modern MRTR input_required results are rejected McpClientManager.callTool() rejects task, inputRequests, and requestState markers Separate RFC and Host interaction design Not part of /mcp; continuation must enter the Host-owned interaction path rather than create UI-side execution authority.
Standalone provider recovery and config freshness are coarse Config is read once; disconnected/error servers are retried by one fixed 5-second scan Two narrow follow-ups: config reload and bounded per-server retry/backoff Do not add a second retry timer or lifecycle policy in the TUI view.
OAuth consent does not disclose issuer/scopes before opening the browser The main-process controller has an explicit disclosure TODO #2921 Reuse the eventual consent contract; do not copy the current omission into TUI guided setup.
Large MCP tool catalogs consume prompt/tool budget Existing design work is active #1382 Contribute there rather than adding a second tool-search design here.

#3458 closure requires a retained-root fix

#3462 deliberately mitigated the regeneration storm by escalating the retry delay. It did not prove that memory is bounded. If an object graph survives every failed Runtime Host candidate, slower retries only postpone the same OOM.

The root-cause work should therefore:

  1. Reproduce the flapping lifecycle under an instrumented Electron main process and capture comparable heap snapshots across multiple failed candidate generations.
  2. Identify the retaining path and its production owner. Candidate maps, capability publication queues, IPC handlers, subscriptions, observers, process handles, and diagnostic buffers are starting hypotheses, not conclusions.
  3. Repair that owner's disposal/generation boundary so a closed candidate is unreachable. Add circuit-breaking only if a genuinely external resource cannot be released; it must not replace deletion of an avoidable retained graph.
  4. Verify both object-count convergence and a bounded heap plateau during prolonged flapping, then verify that a later healthy candidate can still connect and publish capabilities.
  5. Keep Desktop main process OOM after prolonged Runtime Host connection flapping (repeated MCP capability alignment failures) #3458 open until those memory measurements exist. Reduced retry frequency, passing unit tests, or fewer log lines alone are not closure evidence.

PR 1 may proceed independently, but it must not add another cross-generation retention path. Its controller should have deterministic disposal, one registration per active connection generation, and a focused churn test showing that listeners, subscriptions, publication queues, and stdio children return to the active-generation baseline after replacement.

Follow-up boundaries

  • Treat MCP alignment errors during Host flapping as a symptom/amplifier until a heap retaining path proves otherwise.
  • Validate schema compatibility against observed server inventories before relaxing the Host admission boundary.
  • Model MRTR user input as a typed continuation into the existing Host interaction authority; the MCP manager should decode/normalize it, not own the conversation.
  • Give reconnect/config reload one production owner. Desktop, TUI, and the standalone provider must not each grow different uncoordinated policies.
  • Keep resources/templates UI, MCP Apps, Tasks extensions, catalogs, and cache policy as discovery items until a concrete user scenario and authority boundary justify separate work.

Acceptance criteria

  • /mcp is discoverable from TUI help/autocomplete and has localized copy.
  • Existing valid mcp.json entries appear without migration or duplication.
  • A user can add and use both stdio and remote MCP servers from the TUI after the corresponding rollout slice lands.
  • All three protocol preferences round-trip for both transports.
  • Config changes refresh the Host-visible tool set without restarting the TUI.
  • One broken server does not hide healthy servers or their tools.
  • TUI exit, Host switch, reconnect, and config refresh leave no orphan stdio child and no stale Client Capability registration.
  • Repeated connection replacement leaves only the active generation's listeners, subscriptions, queues, and publication state.
  • The TUI does not introduce another periodic reconnect authority.
  • Local Sessions select the MCP provider on their initiating TUI connection.
  • Remote Sessions retain one exact provider binding even when another Client publishes the same MCP contract.
  • Remote publication never reuses or broadens a terminal-client credential.
  • Desktop behavior and the standalone capability-provider command remain compatible.
  • Any new shared module passes the deletion test: removing it would reintroduce the same non-trivial invariant into at least two production callers.

Non-goals

  • Closing Desktop main process OOM after prolonged Runtime Host connection flapping (repeated MCP capability alignment failures) #3458 through retry throttling without retained-heap evidence.
  • Fixing MRTR continuation, schema compatibility, OAuth consent, or large-catalog search inside the /mcp PR series.
  • Moving MCP ownership into Runtime Host.
  • Adding a second MCP schema or copying the Desktop renderer form into the TUI.
  • Migrating Desktop to a new provider lifecycle as part of this work.
  • Treating an arbitrary detached provider as the TUI provider without an exact Host binding contract.
  • Generalizing this work into a plugin/extension framework.
  • Hiding remote capability-provider credential provisioning behind privilege escalation.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions