You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
With several browser tabs of the same app open (same port), the MCP surface acts as if there were one client:
devframe_connect_list-instances lists node instances keyed per (port, basePath) (packages/devframe/src/node/instance-registry.ts), so tabs are invisible by construction — N tabs share one dev-server process.
The client-tool bridge from feat: eagerly expose in-page tools to browser agents #376 (devframe:agent:sync-client-tools → node/client-agent.ts) tracks one session entry per tab, but tool ids collide across tabs and the provider loop lets the last-synced session silently own every tool. medula currently ships this as an uncommitted vendored patch and documents it as "the tab you focused last" — there is no actual focus tracking.
A coding agent cannot see which tabs are connected, nor act on a specific one.
Proposal
Make connected RPC clients (browser tabs) first-class on the MCP surface: list them per instance, and let a tool call target one.
Each tab mints a sessionStorage-backed tab id (same pattern as the hub's frame-nav tabId, packages/hub/src/client/frame-nav.ts), so it survives reloads and reconnects. Caveat to handle: browser tab duplication copies sessionStorage — follow the frame-nav dedupe approach.
The RPC client reports tab metadata to the node: tab id, URL, title, visibility/focus state, plus the client tool manifest it already syncs.
Freshness: metadata is (re)sent on connect, on focus/visibilitychange, and with every client-tool re-sync. No history-API patching; URL may lag briefly after an SPA navigation until the next event.
Cleaned up on session disconnect (existing _emitSessionDisconnected hook).
3. Listing (agentic)
New built-in agent tool devframe:agent:list-clients on each instance's own MCP endpoint: returns the connected tabs with id, URL, title, visibility, connectedAt, and available client tool names.
devframe_connect_list-instances (packages/agentic/src/connect/index.ts) calls it per live instance and nests a clients array in each instance entry — no new gateway tool.
4. Per-tab tool routing (agentic + core)
tools/list stays deduped: one entry per tool id regardless of tab count (no per-tab suffixing, no list churn).
Client-forwarded tools accept an optional reserved client_id argument, injected into their published inputSchema and stripped before forwarding. Works with any MCP client; devframe_connect_call-tool passes it through unchanged.
client_id given → route to that tab's session. Unknown/gone id → fail fast with an error that includes the current live client ids so the agent can re-target in one step.
client_id omitted → focus-aware default: the most-recently-focused visible tab wins, falling back to last-synced. This upstreams medula's vendored patch and makes its "tab you focused last" behavior actually true; stray headless tabs stop competing (a known medula pain point).
Problem
With several browser tabs of the same app open (same port), the MCP surface acts as if there were one client:
devframe_connect_list-instanceslists node instances keyed per(port, basePath)(packages/devframe/src/node/instance-registry.ts), so tabs are invisible by construction — N tabs share one dev-server process.devframe:agent:sync-client-tools→node/client-agent.ts) tracks one session entry per tab, but tool ids collide across tabs and the provider loop lets the last-synced session silently own every tool. medula currently ships this as an uncommitted vendored patch and documents it as "the tab you focused last" — there is no actual focus tracking.A coding agent cannot see which tabs are connected, nor act on a specific one.
Proposal
Make connected RPC clients (browser tabs) first-class on the MCP surface: list them per instance, and let a tool call target one.
1. Stable tab identity (devframe core, browser side)
tabId,packages/hub/src/client/frame-nav.ts), so it survives reloads and reconnects. Caveat to handle: browser tab duplication copies sessionStorage — follow the frame-nav dedupe approach.focus/visibilitychange, and with every client-tool re-sync. No history-API patching; URL may lag briefly after an SPA navigation until the next event.2. Per-tab session registry (devframe core, node side)
node/client-agent.ts) to keep, per RPC session: tab id, metadata, tool manifests,connectedAt, last-focused timestamp._emitSessionDisconnectedhook).3. Listing (agentic)
devframe:agent:list-clientson each instance's own MCP endpoint: returns the connected tabs with id, URL, title, visibility, connectedAt, and available client tool names.devframe_connect_list-instances(packages/agentic/src/connect/index.ts) calls it per live instance and nests aclientsarray in each instance entry — no new gateway tool.4. Per-tab tool routing (agentic + core)
tools/liststays deduped: one entry per tool id regardless of tab count (no per-tab suffixing, no list churn).client_idargument, injected into their published inputSchema and stripped before forwarding. Works with any MCP client;devframe_connect_call-toolpasses it through unchanged.client_idgiven → route to that tab's session. Unknown/gone id → fail fast with an error that includes the current live client ids so the agent can re-target in one step.client_idomitted → focus-aware default: the most-recently-focused visible tab wins, falling back to last-synced. This upstreams medula's vendored patch and makes its "tab you focused last" behavior actually true; stray headless tabs stop competing (a known medula pain point).Dependencies / sequencing
eager-client-script), which is still draft and based on v0.9.18 — it predates the 0.10 move of MCP into@devframes/agenticand needs a rebase. Landing strategy (rebase feat: eagerly expose in-page tools to browser agents #376 first vs. fold into one effort) intentionally left open here.client-agent.tspatch once this lands.Out of scope
document.modelContext) surfaces — untouched; this is about the feat: eagerly expose in-page tools to browser agents #376 RPC bridge.This issue was created with the help of an agent.