Skip to content

Host one MCP server for all sessions: self-control, fleet overview, and orchestration #132

Description

@AThraen

This was generated by AI during triage.

Summary

Have CSM host one MCP server that every session can connect to, exposing three things to the agent running inside a session:

  1. Self — control how this session looks and behaves inside CSM (name, accent, notes, run commands, layout slot).
  2. Fleet — an overview of the other sessions (what they are, where they are, whether they're busy) and, gated, the ability to act on them (spawn, sleep, wake, close, group, focus).
  3. Chat — talk to peers, which is Chat-groups: let the agents in a group talk to each other over an MCP server hosted by CSM #125.

The motivating use case is an orchestrator session: one agent whose job is managing or coordinating the others, rather than doing the work itself. That agent needs all three — it has to see the fleet, act on it, and talk to it.

Relationship to the existing issues

This is the umbrella that joins two issues that are each one facet of it:

Issue Facet Status
#22 "let an agent drive CSM" — add/clone/sleep/reorder terminals one-line stub; this issue is its specified form
#125 "let agents reach each other through CSM" — chat-groups fully specified; becomes the chat namespace

#125 already argues these should be one server, one transport, one auth, separate tool namespaces rather than two servers growing in parallel. This issue agrees and adds the self and fleet namespaces on the same footing.

Triage question for the maintainer: #22 is a stub whose entire content is subsumed here. Close it as absorbed and keep this as the umbrella, or keep #22 as the umbrella and treat this as its spec? Not actioned either way pending a call.

Why self is not a new concept

CSM already lets a program inside a session mutate its own presentation — that is exactly what OSC 9001 shell integration does today, for color, title, git-branch and git-dirty. An agent that emits an escape sequence can already rename its own tab and repaint its own accent.

So the self namespace is not a new capability class; it is the same capability with a real protocol instead of an escape sequence, and a wider verb set. Two consequences worth carrying over deliberately:

  • The trust posture is already decided. OSC 9001 treats every pushed value as untrusted and validates it in the WPF-free ShellIntegrationPayload (strict hex colours, control chars stripped, length caps) precisely because the value comes from whatever is printing to the terminal. MCP arguments arrive from an agent, which is the same threat model, and some of them land in state.json the same way. The MCP handlers should validate through the same layer rather than growing a second, looser one.
  • The write-collision question is already live. OSC 9001 is currently the only writer of ColorOverride, and there is a documented poller stand-down (_gitOverriddenByOsc) so the git poll doesn't clobber a pushed branch. Adding a second writer for the same fields needs the same treatment, or the two channels will fight.

Shape

Transport and identity

Namespaces, roughly

self — scoped to the calling session, no capability gate needed beyond being connected:

Tool Notes
whoami identity, working folder, kind (Local/SSH/WSL), group
set_appearance name, accent colour — overlaps OSC 9001; same validation
set_notes / get_notes the per-session notepad is folder-keyed, so two sessions in one folder share it — the agent must be told that, not surprised by it
list_run_commands / run / stop run commands already have a headless-PTY runtime and a 1MB captured buffer
read_output the agent's own scrollback is already ANSI-stripped and indexed in SQLite

fleet — read is cheap, write is not:

Tool Tier
list_sessions read — name, folder, branch/dirty, kind, group, dormant, idle vs waiting-for-input vs waiting-for-approval
read_session_output read — but this is one agent reading another's transcript; see risks
focus_session, set_layout write, low blast radius, visible to the user immediately
create_session, sleep_session, wake_session, close_session write, high blast radius — closing a session is destructive and can discard in-flight work
assign_group, move_session write — note #131: sidebar and grid order currently diverge, so "move to position n" has no single meaning until that is fixed

chat — as specified in #125 (list_peers, send_message, read_messages).

Capability tiers, not one on/off switch

"Rename myself" and "close every other session" cannot sit behind the same permission. At minimum three tiers, off by default and opt-in per session:

  1. self only — the safe default for an ordinary agent.
  2. self + fleet read — situational awareness without side effects.
  3. self + fleet write — the orchestrator tier, granted explicitly to one session.

The orchestrator tier is the one a user grants knowingly to a specific session; it should be visible in the UI that a session holds it, because an agent that can close other sessions is a materially different thing from one that cannot.

Visibility for the human

Same non-negotiable as #125: if agents are driving CSM, the user must be able to see what they did. An audit log of MCP calls (which session, which tool, what arguments, what result) and a kill switch that revokes a session's tokens mid-flight. An orchestrator that silently sleeps a session the user was watching is a bug report with no evidence trail otherwise.

Risks

  • Cross-session prompt injection, amplified. Chat-groups: let the agents in a group talk to each other over an MCP server hosted by CSM #125 names this for messages; fleet.read_session_output is worse, because it hands agent A the raw scrollback of agent B, including whatever B's repo contents printed. It must be delimited and attributed as untrusted, never presented as instruction.
  • Destructive verbs with no human in the loop. close_session discards a session from state.json. The recently-closed ring (cap 10) is the only undo, and it is not sized for an agent in a loop. Consider making close route to sleep for MCP callers, or requiring confirmation.
  • Loops and cost. An orchestrator polling list_sessions or re-reading transcripts burns tokens invisibly. Needs rate limiting, as Chat-groups: let the agents in a group talk to each other over an MCP server hosted by CSM #125 concluded for chat.
  • A local HTTP listener is a new attack surface on the user's machine, reachable by anything running as that user. Bind loopback only, require the per-session token, and treat the token as a secret that never lands in state.json in cleartext.

Acceptance criteria

Deliberately coarse — this is an umbrella and should be sliced into tracer-bullet issues before implementation.

  • A single MCP server, started by CSM, that multiple sessions connect to concurrently over loopback with per-session tokens.
  • Server-assigned identity: a session's calls are attributed to it, and no tool accepts a caller-supplied session identity for its own scoping.
  • self.whoami and one self mutation (name or accent) round-trip, validated through the same layer as OSC 9001, and persist.
  • fleet.list_sessions reflects live state including busy/waiting, and excludes nothing the sidebar shows.
  • Capability tiers enforced server-side, defaulting to self only; a session without the orchestrator tier is refused fleet writes.
  • Every MCP call is recorded in a user-visible audit trail, and a kill switch revokes access without restarting CSM.
  • Any added dependency is licence-verified against the repo's OSS-only constraint.
  • MCP config is injected at session launch, not hand-configured by the user.

Out of scope

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions