Support multiple concurrent sessions with isolated feedback queues. Sessions can originate from MCP clients or external plugins.
| Type | Origin | Transport | Session ID |
|---|---|---|---|
| MCP | MCP initialize |
StreamableHTTPServerTransport |
{client-slug}-{generation} (e.g., opencode-1) |
| Plugin | POST /api/sessions or auto on GET /api/stream/:id |
SSE (text/event-stream) |
Plugin-provided (e.g., OpenCode session ID) |
Both types share the same feedback queue, waiter, and UI infrastructure.
- Client sends
initializetoPOST /mcpwithoutmcp-session-id. - Server creates a Streamable HTTP transport with a human-readable session ID (e.g.,
opencode-1,copilot-3). - Client reuses
mcp-session-idin subsequent MCP requests. - Server routes
get_feedbackand UI submissions by session id. - If a stream drops temporarily, the client can reconnect while the server process remains alive.
- If the server restarts, the client must initialize again; preserved state is reassociated to the new live session.
- Auto-prune is configurable via the UI settings ("Auto prune after" dropdown). Default is "Never" (disabled). When enabled, sessions inactive beyond the configured threshold (and not currently waiting) are pruned every minute. Manual prune via the "Prune Stale" button uses a 30-minute threshold.
- Plugin ensures the session exists via
POST /api/sessionswhen needed. - Plugin optionally sends the latest assistant text to
POST /api/context/:sessionIdfor UI display and remote notifications. - Plugin opens
GET /api/stream/:sessionIdand waits on the SSE stream. - Server auto-registers the session if needed, sends keepalive comments every 30 seconds, and emits
feedback/closed/errorevents. - On
session.deleted, the plugin callsDELETE /sessions/:sessionIdand clears local session caches. - Same auto-prune rules apply (configurable, default disabled).
get_feedbackblocks per session until feedback is submitted for that same session.- UI can target sessions explicitly via:
- URL:
/session/<sessionId> - API body:
POST /feedbackwithsessionId
- URL:
- Feedback/session metadata is persisted locally.
- Live waiter closures, replay-event history, and transport/server objects remain in-memory only.
- No legacy file-watching feedback path.
GET /sessionslists active sessions.POST /sessions/activesets default UI target session.DELETE /sessions/:sessionIddisconnects a session.
- Old pre-restart session IDs are not transparently resurrected.
- Recovery happens by creating a fresh MCP session and reassociating preserved feedback/session state.