channel

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 20, 2026 License: MIT Imports: 8 Imported by: 0

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

View Source
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.

View Source
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).

View Source
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

type ClientInfo struct {
	Name    string `json:"name"`
	Version string `json:"version"`
}

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

func NewServer(ob OutboundBus, in io.Reader, w io.Writer) *Server

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

func (s *Server) Deliver(in Inbound)

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.

func (*Server) Serve

func (s *Server) Serve(ctx context.Context) error

Serve runs the JSON-RPC read/dispatch loop until ctx is cancelled or stdin closes (the cc adapter's lifecycle is bound to its stdio session).

type ServerInfo

type ServerInfo struct {
	Name    string `json:"name"`
	Version string `json:"version"`
}

ServerInfo is the MCP server identity block.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL