Documentation
¶
Overview ¶
Package channel implements the Claude Code "channels" MCP capability (`claude/channel`) for the peerbus cc adapter (--adapter=cc).
SCHEMA: DOCUMENTED. Every wire shape here mirrors the authoritative schema in CHANNELS_SCHEMA.md (Claude Code v2.1.80+, channels-reference); the typed mirror is in handshake_notes.go and is round-trip tested. No live capture was required.
── What this is ──
A stdio MCP server that is, additionally, a claude/channel: it advertises capabilities.experimental["claude/channel"]={} (registers Claude Code's notification listener so push-wake works) AND the standard tools={} capability (the bus.* reply tools). It is built ON TOP of internal/mcp — the SAME JSON-RPC core the generic adapter uses; internal/mcp was extended additively (ServerOption + Server.Notify) rather than forked. The JSON-RPC framing, dispatch, and tool plumbing are not reimplemented here.
Inbound (push-wake): a broker `deliver` (already HMAC-verified and deduped by the SHARED internal/adapter machinery — see internal/adapter/cc.go) is mapped to a JSON-RPC notification `notifications/claude/channel` with
params = { content: <message body as text>,
meta: { from, source, msg_id } } (all meta values strings)
emitted via mcp.Server.Notify (the additive server->client path). meta keys are identifier-safe (letters/digits/underscore only) per CHANNELS_SCHEMA.md §3 — keys with hyphens are silently dropped by Claude Code, so we use from / source / msg_id.
Outbound (reply path): standard MCP tools/list + tools/call exposing bus.send / bus.broadcast / bus.peers — the SAME tool surface and semantics as the generic adapter, served by the same internal/mcp tool plumbing over the SAME broker client + shared dedupe + HMAC (wired in internal/adapter/cc.go). The reply path is ordinary MCP tool calls; there is no special channel reply notification and no turn/correlation id (CHANNELS_SCHEMA.md §4).
Permission relay (notifications/claude/channel/permission) is DELIBERATELY NOT implemented: peerbus keeps escalation policy in the consuming agent's prompt, never in the bus. We therefore do not declare experimental["claude/channel/permission"].
Package channel implements the Claude Code "channels" MCP capability (`claude/channel`) for the peerbus cc adapter.
DOCUMENTED SCHEMA.
Every type in this file mirrors the authoritative `claude/channel` wire schema sourced from official Claude Code documentation (`channels-reference.md`, Claude Code v2.1.80+), recorded verbatim at the repo root in CHANNELS_SCHEMA.md and summarized in docs/spikes/claude-channel-handshake.md. No live capture was required; the earlier PROVISIONAL/BLOCKED status is rescinded.
These structs document the schema in Go and are round-trip tested. The live cc adapter (channel.go) builds the same frames directly; this file is the schema-of-record the tests pin to.
Index ¶
Constants ¶
const ChannelCapabilityKey = "claude/channel"
ChannelCapabilityKey is the experimental capability key the server advertises: capabilities.experimental["claude/channel"] = {} (DOCUMENTED, CHANNELS_SCHEMA.md §1). Its presence registers Claude Code's notification listener for the push method below.
const MCPProtocolVersion = "2025-06-18"
MCPProtocolVersion is the MCP protocol version string the cc adapter advertises (echoed from the client when present; this is the fallback).
const PushMethod = "notifications/claude/channel"
PushMethod is the JSON-RPC notification method the server emits to push-wake an idle session (DOCUMENTED, CHANNELS_SCHEMA.md §3).
Variables ¶
This section is empty.
Functions ¶
func UniqueName ¶
func UniqueName() string
UniqueName generates a stable-ish unique peer name for auto-registration (cc2cc-parity ergonomics) when no name is configured. Scheme:
cc-<hostname>-<pid>-<6 hex random>
hostname+pid make it readable and naturally distinct per session/host; the random suffix breaks ties if two sessions on the same host race the same pid reuse across a restart. Documented here so the scheme is part of the contract, not an implementation accident.
Types ¶
type Capabilities ¶
type Capabilities struct {
Experimental map[string]json.RawMessage `json:"experimental,omitempty"`
Tools json.RawMessage `json:"tools,omitempty"`
}
Capabilities is the MCP capabilities object. The channel capability lives under experimental["claude/channel"] as an empty object; tools is the standard MCP capability, present because the cc adapter exposes the bus.* reply tools (two-way channel). DOCUMENTED — CHANNELS_SCHEMA.md §1.
type ClientInfo ¶
ClientInfo is the MCP client identity block.
type Inbound ¶
type Inbound struct {
ID string
From string
Source string
Body json.RawMessage
}
Inbound is one already-HMAC-verified, already-deduped delivery the cc adapter pushes into the session. Source is the envelope `source` (e.g. "peer-bus" — the tag the consuming agent's prompt keys escalation off; peerbus itself has no such logic). Body is the opaque application JSON verbatim.
type InitializeParams ¶
type InitializeParams struct {
ProtocolVersion string `json:"protocolVersion"`
Capabilities Capabilities `json:"capabilities"`
ClientInfo ClientInfo `json:"clientInfo"`
}
InitializeParams is the `initialize` request params (client -> server).
type InitializeResult ¶
type InitializeResult struct {
ProtocolVersion string `json:"protocolVersion"`
Capabilities Capabilities `json:"capabilities"`
ServerInfo ServerInfo `json:"serverInfo"`
}
InitializeResult is the `initialize` result (server -> client). The server advertises experimental["claude/channel"]={} (so Claude treats it as a push-capable channel) and tools={} (so Claude discovers the bus.* reply tools). DOCUMENTED — CHANNELS_SCHEMA.md §1.
type OutboundBus ¶
type OutboundBus interface {
Send(ctx context.Context, to string, body json.RawMessage) error
Broadcast(ctx context.Context, body json.RawMessage) error
Peers(ctx context.Context) ([]string, error)
}
OutboundBus is the broker-facing reply surface the bus.* tools delegate to. internal/adapter/cc.go implements it over the shared resuming broker client (HMAC sign + reconnect/resume) — the channel layer never touches the broker, HMAC, or dedupe itself.
type PushNotification ¶
type PushNotification struct {
JSONRPC string `json:"jsonrpc"`
Method string `json:"method"`
Params PushParams `json:"params"`
}
PushNotification is a full JSON-RPC notification frame that push-wakes an idle session. A notification has no `id`.
Method MUST equal PushMethod for the frame to be a valid push; the round-trip test treats a missing/empty Method as the malformed case.
type PushParams ¶
type PushParams struct {
Content string `json:"content"`
Meta map[string]string `json:"meta,omitempty"`
}
PushParams is the `params` of a `notifications/claude/channel` push (DOCUMENTED — CHANNELS_SCHEMA.md §3):
- Content (required): the event body, delivered as the text content of the injected <channel> XML tag.
- Meta (optional): each key/value becomes an XML attribute on the <channel> tag. ALL VALUES MUST BE STRINGS. Keys must be valid identifiers (letters, digits, underscores only); keys with hyphens or special characters are silently dropped by Claude Code.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is the cc-adapter MCP server: the internal/mcp JSON-RPC core configured as a claude/channel (experimental capability + Notify push path), with the bus.* tools delegating to an OutboundBus.
func NewServer ¶
NewServer builds the cc-adapter MCP server reading framed JSON-RPC from in and writing newline-delimited JSON-RPC to out. It advertises the claude/channel experimental capability and the standard tools capability, and serves bus.send/bus.broadcast/bus.peers over the supplied OutboundBus.
func (*Server) Deliver ¶
Deliver maps one inbound broker delivery to a claude/channel push-wake notification and emits it (DOCUMENTED — CHANNELS_SCHEMA.md §3). content is the message body as text; meta carries identifier-safe string attributes (from / source / msg_id) that Claude Code surfaces as <channel> XML attributes. The body is opaque JSON: if it is a JSON string we unwrap it to its text so the session sees plain text, otherwise the compact JSON is passed through verbatim.
type ServerInfo ¶
ServerInfo is the MCP server identity block.