Skip to content

feat(tui): publish MCP tools to remote Runtime Hosts - #4200

Open
me2seeks wants to merge 10 commits into
mainfrom
feat/3838-remote-mcp-companion
Open

feat(tui): publish MCP tools to remote Runtime Hosts#4200
me2seeks wants to merge 10 commits into
mainfrom
feat/3838-remote-mcp-companion

Conversation

@me2seeks

@me2seeks me2seeks commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Publish the TUI's MCP tools to a selected remote Runtime Host without widening the terminal Client credential or moving MCP ownership into the Host.

  • Store the capability-provider credential outside profile metadata, arguments, and conversation data. Bind it to the exact remote profile target and the terminal Client identity, separately from the terminal access credential.
  • Run one profile-bound publication companion for remote TUI profiles. The TUI MCP controller remains the sole MCP manager, configuration owner, and publication queue.
  • Let /mcp set or remove the provider credential and distinguish missing, rejected, target-mismatched, reconnecting, and published states. Credential entry uses a dedicated same-length mask and clears the secret before rendering action results or diagnostics.
  • Treat profile filesystem notifications only as invalidation signals, then re-read the canonical profile catalog. A generation fence repeats a read when another invalidation arrives in flight. A removed or changed target retires the companion, and retirement or explicit close shares one cleanup promise through connection and direct-peer teardown.
  • Exercise the production composition with the real credential store, authenticated WebSocket owner association, a real Session, model tool discovery, and an actual stdio MCP invocation.

Refs #3838
Built on #4187 (merged)

Review focus

The terminal credential still cannot publish Client Capabilities. A Host owner explicitly issues a separate provider credential associated with the terminal Client, and the TUI stores that secret in the local credential store for the exact profile target.

This PR does not add another McpClientManager, configuration store, publication queue, retry timer, profile registry, or Host-side MCP manager. The companion owns only its credential-bound connection. Filesystem watch events never become state; the profile catalog remains authoritative.

Provider ambiguity remains fail-closed at the Host selection boundary introduced by #4187. The TUI does not invent a second provider-selection or status authority.

Visual evidence

Fixture-only terminal evidence for missing, rejected, target-mismatched, reconnecting, published, and masked credential-entry states:

Remote TUI MCP publication states

Verification

  • npm --workspace maka-agent test — 653 passed, 0 failed
  • npm --workspace @maka/runtime-host run test:dist — 1,435 passed, 12 skipped, 0 failed
  • Exact current head: affected Runtime Host profile, TUI control, remote publication, masked input, and production Session→MCP integration suites — 70 passed, 0 failed
  • The production integration calls mcp__fixture__echo through the owner Session and observes remote-session-sentinel in the model's next request
  • Profile removal is performed through a second real catalog instance; credentials use the production credential store
  • Runtime Host, CLI, and affected workspace builds pass.
  • git diff --check origin/main...HEAD

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex traced the credential, Runtime Host connection, TUI MCP publication, profile invalidation, peer cleanup, secret presentation, and Session provider-selection boundaries; implemented the remote publication companion and review repairs; added unit and real production-composition coverage; and performed architecture, first-principles, and simplification reviews. The commits carry a Generated-by: Codex trailer.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@Astro-Han Astro-Han 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.

Thanks for preserving one TUI MCP manager and publication queue while adding only a credential-bound remote companion. That is the right architecture direction and avoids moving MCP ownership into Runtime Host.

I reviewed exact head 3f1e02758a6a097fe998b09470e01007d36c4f3d. The PR body contains no screenshots or terminal recording for the new /mcp credential and publication states. Please attach the missing, rejected, target-mismatched, reconnecting, and published flows, including the credential-entry screen, without exposing a real secret.

This stacked PR cannot merge until the P1 in its #4187 base is fixed: an unbound remote-owner credential can claim another Client ID and obtain the associated provider. #4200 does not introduce that primitive, but it makes the affected provider a real TUI MCP publication, so the stack inherits the trust-boundary failure.

I found three additional P2 issues:

  1. Removing a profile from another process does not retire the running companion. The target retains the old profile and credential, remains registered, and can republish after reconnect. Profile removal needs an explicit lifecycle fence that closes publication.
  2. A permanent libp2p reconnect failure or credential revocation updates availability but does not close the peer client. The native endpoint and relay resources can remain until credential replacement or TUI exit.
  3. The provider credential is entered through a normal visible Editor, despite the PR statement that the secret is not displayed. Please use a masked secret-input treatment and verify that rendered history and diagnostics never expose it.

The remote integration test verifies publication, restart, revocation, root mismatch, and child cleanup, but never binds a real Session and invokes the published MCP tool. It also mocks away the production target-and-owner credential key. Please add at least one production-composition path from TUI context → Session provider selection → actual MCP invocation using the real credential store boundary.

There are currently no hosted checks for this exact head.

Review analysis was assisted by Codex and independent @reviewer agents. Astro-Han verified the exact head, stacked authority boundary, profile and libp2p lifecycles, credential presentation, integration coverage, and severity judgment, and owns this review.

中文对照

谢谢你保留唯一的 TUI MCP manager 和 publication queue,只增加 credential-bound remote companion。这个架构方向正确,也避免把 MCP ownership 移进 Runtime Host。

我审查了精确 head 3f1e02758a6a097fe998b09470e01007d36c4f3d。PR 正文没有新 /mcp credential 和 publication 状态的截图或终端录屏。请补充 missing、rejected、target-mismatched、reconnecting 和 published 流程,包括 credential 输入界面,但不要暴露真实 secret。

这个 stacked PR 必须等待 base #4187 的 P1 修复:未绑定的 remote-owner credential 可以冒用另一个 Client ID 并获得对应 provider。#4200 没有新增这条 trust primitive,但会让受影响 provider 成为真实 TUI MCP publication,因此整组继承该信任边界问题。

还有三个 P2:

  1. 另一个进程删除 profile 时,正在运行的 companion 不会退出。target 仍保留旧 profile 和 credential,继续注册,并能在 reconnect 后重新发布。profile removal 需要明确的 lifecycle fence 来关闭 publication。
  2. libp2p 永久重连失败或 credential 被撤销时,只更新 availability,没有关闭 peer client;native endpoint 和 relay 资源可能保留到 credential replacement 或 TUI 退出。
  3. provider credential 使用普通可见 Editor 输入,与 PR 所说的 secret 不显示不符。请使用 masked secret input,并确认渲染历史和 diagnostics 不会泄露。

remote integration test 验证了 publication、restart、revocation、root mismatch 和 child cleanup,但没有绑定真实 Session 并调用已发布的 MCP tool;它也通过 mock 绕开了生产 target-and-owner credential key。请至少补一条真实 production composition:TUI context → Session provider selection → 实际 MCP invocation,并经过真实 credential store boundary。

当前 exact head 没有 hosted checks。

本次审查分析由 Codex 和独立的 @reviewer 子代理协助;Astro-Han 核验了精确 head、stacked authority boundary、profile 与 libp2p lifecycle、credential presentation、integration coverage 和问题分级,并对本次 Review 负责。

@github-actions github-actions Bot added the effort/XL Over 1000 readable lines label Aug 30, 2026
@me2seeks
me2seeks force-pushed the feat/3838-remote-mcp-companion branch from 3f1e027 to e49fb64 Compare August 30, 2026 05:57
@me2seeks
me2seeks force-pushed the feat/3838-remote-mcp-companion branch from e49fb64 to 0b6e5dd Compare August 30, 2026 06:01
@me2seeks

Copy link
Copy Markdown
Contributor Author

Thanks — addressed on 0b6e5dd33, with the repaired #4187 head underneath it.

  • Profile changes are now an invalidation signal only: the companion re-reads the canonical catalog and retires when the exact profile disappears or changes target.
  • Permanent direct-peer failure closes the peer endpoint, and later replacement/shutdown waits for that cleanup.
  • Provider credentials use a dedicated masked input; rendering receives only a same-length mask, and action results or diagnostics never receive the display value.
  • The integration now uses the production credential store and composition, creates a real owner Session, discovers mcp__fixture__echo, and invokes the real stdio MCP fixture through the associated provider.

I also added fixture-only terminal evidence for all requested states and the masked credential screen to the PR body. CLI passes 641/641, Runtime Host passes 1,411 with 9 skips, and the exact final-stack focused suites pass 144/144.

@me2seeks
me2seeks requested a review from Astro-Han August 30, 2026 07:51
Base automatically changed from feat/3838-mcp-provider-association to main August 30, 2026 11:55
@me2seeks
me2seeks force-pushed the feat/3838-remote-mcp-companion branch 2 times, most recently from 476a855 to 1198568 Compare August 30, 2026 12:49
@me2seeks

Copy link
Copy Markdown
Contributor Author

Thanks — both races are valid and addressed on 119856863 after syncing the stack onto current main.

  • Profile invalidations now carry a generation. If another notification arrives while the canonical catalog read is in flight, validation reads the catalog again instead of treating the first snapshot as current. The regression holds the first read on the old profile, removes the profile, then proves the second notification retires the companion.
  • Retirement and explicit close now share one cleanup promise. closed only fences new work; closePublication() does not settle until the existing connection and direct-peer endpoint have both finished closing. The regression gates those two cleanup stages independently.

The exact-head affected build and suites pass 70/70. The full CLI suite passes 653/653, and the full Runtime Host suite passes 1,435 with 12 skips and no failures.

@Astro-Han Astro-Han 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.

Thanks for the substantial follow-through on the previous review. I reviewed exact head 119856863c35b7f07f78086b870fa684fe1521f2.

The earlier trust-boundary, profile-retirement, peer-cleanup, masked-input, and real Session-to-MCP composition concerns are now addressed at their natural owners. The exact-head test and windows_recovery checks are green.

I found one remaining P1 concurrency issue inline: profile removal can race an already-queued provider-credential write and leave a deleted bearer secret persisted for silent reuse if the same profile identity is recreated. Please serialize that mutation with the profile catalog authority and cover the interleaving deterministically.

Because this changes the TUI product surface, live terminal and secret-handling acceptance is still required before approval.

Review analysis was assisted by Codex and independent @reviewer agents. Astro-Han verified the exact-head diff, production credential/profile boundaries, concurrency reachability, existing feedback closure, and severity before publication and owns this review.

中文对照

谢谢你完整跟进上一轮审查。我复核了精确 head 119856863c35b7f07f78086b870fa684fe1521f2。之前的信任边界、profile retirement、peer cleanup、masked input 和真实 Session→MCP 组合问题,都已经在自然 owner 处解决;当前两个检查均为绿色。

行内还剩一个 P1 并发问题:删除 profile 可能与已经排队的 provider credential 写入竞态,导致已删除的 bearer secret 重新持久化;如果随后重建同一 profile identity,它会被静默复用。请把该写入纳入 profile catalog authority 的串行边界,并用确定性交错测试覆盖。

这是 TUI 产品界面的变化,因此 Approve 前仍需要真实终端和 secret-handling 人工验收。

本次审查分析由 Codex 和独立的 @reviewer 子代理协助;Astro-Han 核验了精确 head、生产 credential/profile 边界、并发可达性、旧反馈闭环和问题分级,并对本次 Review 负责。

Comment thread packages/cli/src/tui-mcp-remote-publication.ts Outdated
@me2seeks
me2seeks force-pushed the feat/3838-remote-mcp-companion branch from 1198568 to 2b800ca Compare August 30, 2026 13:34
Store TUI capability-provider credentials separately from terminal access credentials and key them by both the immutable remote target and the owning Client identity.

Expose the established CLI Client identity to the TUI assembly without placing either credential in profile metadata.

Generated-by: Codex <noreply@openai.com>
Run one profile-bound capability-provider companion for remote TUI profiles while retaining the existing TUI MCP manager and publication queue as the only configuration and publication authorities.

Surface missing, rejected, and target-mismatched provider credentials in /mcp, and close the companion deterministically on credential rotation or TUI shutdown.

Generated-by: Codex <noreply@openai.com>
Cover two concurrently associated providers over authenticated WebSockets, an exact-root rejection, Host restart and republish, credential revocation, and final MCP child cleanup.

Generated-by: Codex <noreply@openai.com>
Abort initial companion connection attempts during replacement or shutdown, and store the owner-bound provider credential in the profile target slot so profile removal retires every associated secret.

Generated-by: Codex <noreply@openai.com>
Re-read the canonical profile catalog after cross-process changes and retire the companion when its bound profile disappears or changes target. Close the direct peer endpoint when reconnect reaches a permanent failure.

Generated-by: Codex <noreply@openai.com>
Use a dedicated single-line masked input for provider credentials and clear it before action results or diagnostics are rendered.

Generated-by: Codex <noreply@openai.com>
Exercise the production Runtime Host composition with a real credential store, authenticated owner association, stdio MCP fixture, Session binding, model tool discovery, and an actual MCP echo call.

Generated-by: Codex <noreply@openai.com>
Track permanent-failure peer closure through the publication lifecycle, narrow the profile fence to its read authority, and render credentials from a same-length mask instead of post-processing plaintext output.

Generated-by: Codex <noreply@openai.com>
@me2seeks
me2seeks force-pushed the feat/3838-remote-mcp-companion branch from 2b800ca to 31cdf62 Compare August 30, 2026 13:35

@Astro-Han Astro-Han 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.

Thanks for serializing the provider-credential mutation with profile removal; that closes the original write-after-delete interleaving. One same-target lifecycle case still bypasses the new “current” check. This is a suggestion from an outside review, so please do push back if profile IDs have an incarnation guarantee outside this catalog.

AI-assisted review disclosure: Codex ran independent credential-security, Runtime Host, and TUI production/test analysis lanes; Astro-Han is the contributor of record for this review.

(candidate): candidate is RemoteRuntimeHostProfile =>
candidate.id === expectedProfile.id && candidate.kind === 'remote',
);
if (!profile || !sameRemoteRuntimeHostProfileTarget(profile, expectedProfile)) return false;

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.

[P1] (category ② — supported cross-process removal/recreation path)

Thanks for re-reading the canonical profile under the update lock. sameRemoteRuntimeHostProfileTarget() only compares access/endpoint binding, so a second supported process can remove profile office and recreate the same ID/target before this validation or the companion’s coalesced invalidation read. The old companion then treats the new incarnation as its original profile, keeps its stronger provider bearer credential/connection alive, and a queued mutation can write against the recreated profile—even though removal deleted every credential and should retire that grant. Could persisted profiles carry an immutable incarnation/revision that is included in companion validation, mutation tokens, and credential binding (or an equivalent tombstone/generation), with a remove → recreate same ID/target before validation regression? Please feel free to push back if profile recreation is guaranteed to use a fresh identity through another enforced seam.

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

Labels

effort/XL Over 1000 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants