Runtime Services
MCP and sidecars
Understand how Gooselake uses sidecar processes for Claude bridge behavior and the bundled MCP tool server.
Gooselake uses sidecars where protocol churn or provider integration details are better isolated from the core runtime server.
There are two bundled sidecars today:
sidecars/claude-bridge: Claude bridge process used by the Claude provider.sidecars/gg-mcp-server: MCP server that can exposegg_*tools to provider sessions and call back into the runtime gateway.
The analogy is an adapter plug. The runtime keeps the wall socket stable; sidecars absorb the odd shapes of provider/tool protocols.
Why sidecars exist
The runtime server owns durable state, provider orchestration, and HTTP/SSE APIs. Sidecars isolate integration surfaces that are better treated as process boundaries:
- provider SDK/CLI behavior
- JSON-lines bridge protocol details
- MCP server lifecycle
- environment injection
- provider-specific authentication plumbing
- tool-call callback wiring
This keeps runtime-core focused on records, invariants, events, and provider contracts.
Claude bridge
The Claude provider communicates with the Claude bridge sidecar. The bridge exposes JSON-lines methods such as:
bridge.pingbridge.capabilitiessession.createsession.resumesession.sendsession.interruptsession.approval.respondsession.waitsession.supported_commandssession.supported_modelssession.closebridge.shutdown
The runtime provider adapter converts runtime session/turn operations into bridge requests and maps bridge responses back into runtime records and events.
GG MCP server
The MCP sidecar lets provider sessions call runtime-backed tools. The high-level path is:
provider session
-> gg-mcp-server tool call
-> POST /v1/mcp/invoke
-> runtime tool gateway
-> runtime service
The runtime gateway requires a caller session identity. Tool calls should be attributable to an active runtime session.
Current gateway scope
The runtime MCP gateway is intentionally narrower than the full HTTP API. It exposes provider-safe control namespaces that are backed by the same runtime services used by HTTP:
gg_process: run a process, get status, read logs, and kill a processgg_team: inspect team status, send direct/broadcast team messages, and add/remove team members
Use /v1/mcp/capabilities to inspect what the running server supports:
curl "$BASE_URL/v1/mcp/capabilities" "${AUTH[@]}"
Capabilities include supportedNamespaces, tools, ggProcessEnabled, ggTeamEnabled, ggTeamManagePermissions, and ggTeamModelPresets. Team tools are listed only when team MCP is enabled. If disabled, gg_team_* calls return an ok:false envelope with feature_disabled.
The team MCP surface is:
gg_team_status: returns lead/member status for teams where the caller is an active member, including context-window remaining percentage when provider usage exposes enough data.gg_team_message: sends direct messages or broadcasts. Userecipient_agent_id: "broadcast"for broadcast fanout; the sender is excluded by default. Optionalimage_pathsare stored and delivered as image input items for supported providers.gg_team_manage: add one member whenremove_agent_idsis absent, or remove one or more members whenremove_agent_idsis present. Add mode accepts configuredmodel_presetnames and optionalimage_pathsfor the spawned member onboarding message when the selected provider supports image attachments.
gg_team calls share the same underlying team services as HTTP routes. Messages create normal team message, delivery, and event records. Member add/remove operations use the runtime spawn, join, remove, worktree assignment, and cleanup services.
Agent-initiated membership management is governed by runtime team policy:
[teams]
enabled = true
non_lead_can_add_members = false
non_lead_can_remove_members = false
[[teams.model_presets]]
name = "deep"
provider = "claude"
model = "claude-opus-4-8"
thinking_effort = "high"
The team lead can add and remove members by default. Non-lead members can use gg_team_manage add/remove only when the matching policy flag is enabled. This policy applies to MCP-initiated membership control; authenticated HTTP team administration remains the client/human control plane. Context-window percentage is derived from persisted turn usage; Codex and Claude can report it after completed turns, while ACP reports null unless its configured agent emits compatible context-window usage.
Codex and Claude sessions can receive team image attachments through the runtime input path. ACP image attachments are not modeled by this runtime yet, so gg_team_message and gg_team_manage calls that include image_paths for ACP recipients or spawned ACP sessions return unsupported_provider_images.
Codex, Claude, and ACP sessions all use the bundled gg-mcp-server path when MCP is enabled, so gg_process and gg_team behavior is provider-agnostic. Providers inject caller identity into the sidecar environment or per-call metadata; the model-authored tool arguments are not trusted for caller identity.
MCP environment
The MCP sidecar uses environment values such as:
GG_MCP_GATEWAY_URL="http://127.0.0.1:8080/v1/mcp"
GG_MCP_GATEWAY_TOKEN="..."
GG_MCP_CALLER_AGENT_ID="sess_codex_..."
GG_MCP_REQUIRE_TOOL_CALLER_AGENT_ID="1"
GG_MCP_ENABLE_PROCESS_TOOLS="1"
The exact environment is assembled by provider integration code when MCP tools are injected into a session.
When GG_MCP_REQUIRE_TOOL_CALLER_AGENT_ID=1, the sidecar requires caller identity per tool call. This lets a shared MCP server process safely serve different runtime sessions. GG_MCP_ENABLE_PROCESS_TOOLS=0 hides gg_process tools without disabling the unified server or the team tool path.
Failure modes
Common MCP failures:
- caller session ID missing
- caller session is closed or unknown
- bearer token is wrong
- tool namespace is unsupported
- process ownership does not match caller session
- process tools are disabled in config
- team MCP tools are disabled in config
- caller is not a team member
- non-lead caller is denied by
gg_team_managepolicy - sidecar binary is missing from the release/source layout
Start with:
curl "$BASE_URL/v1/mcp/capabilities" "${AUTH[@]}"
curl "$BASE_URL/v1/diagnostics/providers" "${AUTH[@]}"
Design boundary
Sidecars should not become alternate runtimes. They can translate, adapt, and bridge, but durable truth belongs in the core runtime and SQLite store.