---
name: buddy-protocol
description: |
  The Buddy Protocol — an open convention for MCP servers to expose a
  friendly, data-grounded status companion that can federate with peers.
  Defines the well-known tool name, request/response shape, federation
  semantics, and reference implementation. Adopted first by Ghost Protocol's
  Wyrm (`wyrm-mcp@5.8.0+`); intended for any MCP server that wants its
  agent / dashboard / status surface to feel like a *colleague* rather than
  a `kubectl get pods` printout.
argument-hint: "[overview | adopt | reference | federate]"
user-invocable: true
---

# The Buddy Protocol

**Open convention. No central registry. Anyone who follows the conventions
in this document is "buddy-compatible."**

The Model Context Protocol (MCP) gives AI agents a way to invoke tools on
remote servers. The Buddy Protocol is a *thin convention layer on top of
MCP* that turns any server into a friendly, queryable status companion.
Two buddies on different MCP servers can discover and chat with each
other without prior coordination — just by following the convention.

## Why a protocol

You can call any MCP tool you like. The reason this is a *protocol* and not
just "call a tool" is **discoverability + federation**. When Wyrm's
`wyrm_buddy` runs, it walks every registered outbound MCP server and asks
*"do you have a buddy?"* Without a convention, that question can't be
answered. With one, it's a tool-name match.

The result: your AI runs `wyrm_buddy` against the Wyrm project, and at the
bottom of the reply it gets a "From other buddies" section with messages
from your Linear-buddy, Slack-buddy, GitHub-buddy, deployment-buddy, etc.
All without you wiring anything together.

## The convention

### 1 · Tool name

A buddy-compatible MCP server **MUST** expose at least one tool whose name
matches one of these patterns (case-insensitive):

- **`buddy`** — the well-known name, **preferred for generic federation**
- **`<server>_buddy`** — for richer, server-specific output (e.g. `wyrm_buddy`)
- **`buddy_<context>`** — for multiple buddies on the same server (e.g.
  `buddy_oncall`, `buddy_release`)

A server **MAY** expose any combination. If both `buddy` and `*_buddy` are
present, callers SHOULD prefer `buddy` for peer queries (less context) and
`*_buddy` for first-party use (richer output).

### 2 · Input schema (request)

All fields optional. Servers MUST handle the case where every field is
omitted.

| Field | Type | Description |
|---|---|---|
| `from_buddy` | string | The calling buddy's identity, e.g. `"wyrm@5.8.0"`. Used for cycle prevention (don't reply to yourself). |
| `project_hint` | string | Path / name / identifier of the project the calling buddy is contextualised on. Receiver MAY use it to scope the reply, or MAY ignore it. |
| `mood_hint` | string | One of `"normal"`, `"celebratory"`, `"stuck"`, `"quiet"`. Lets a peer adapt tone to the calling buddy's mood. |
| `size` | string | One of `"full"`, `"compact"`, `"mini"`. Receivers SHOULD cap output accordingly. Default: `"compact"` for peer queries. |
| `format` | string | `"markdown"` (default) or `"json"`. `"json"` returns a structured payload (see §3). |

Servers MUST gracefully ignore unknown fields.

### 3 · Output (response)

**Markdown shape (default).** The tool returns a normal MCP tool result whose
content is a single `text` block. The text is markdown the calling buddy
can paste verbatim into its own response under a "From other buddies"
heading.

Constraints:

- **`compact`** size: ≤ 400 tokens output
- **`mini`** size: single line, ≤ 80 chars
- **`full`** size: ≤ 800 tokens
- No leading h1 — the calling buddy provides the section heading
- Cite real data (issue IDs, deploy SHAs, PR numbers). The buddy protocol
  inherits Wyrm's "no hallucinated encouragement" rule: every claim must
  trace to a real row.

**JSON shape (when `format: "json"`).**

```json
{
  "buddy": {
    "name": "linear-buddy",
    "version": "1.0.0",
    "mood": "normal",
    "summary": "3 issues in review, 0 P0 incidents, 12d streak",
    "highlights": [
      { "kind": "issue", "id": "LIN-1234", "title": "...", "url": "..." }
    ],
    "links": { "dashboard": "https://..." }
  }
}
```

### 4 · Federation rules

- A buddy **MAY** call other buddies it has registered.
- A buddy **MUST NOT** call back into a buddy that's already in the call
  chain (cycle prevention). Use `from_buddy` to detect.
- A buddy **MUST** have a per-call timeout (suggested: 5s) and treat
  timeouts as silent skip — never block the user-facing buddy.
- A buddy **MUST** cap fold-in count (suggested: ≤ 3 peer replies per
  call) to stay token-frugal.
- A buddy **SHOULD** skip federation in `mood_hint: "quiet"` calls.
- A buddy **MAY** add `federate: false` to its first-party tool to let
  the operator opt out of peer queries.

### 5 · Persona, mood, and tone

The protocol is voice-agnostic — buddies bring their own voice. But:

- A buddy SHOULD adapt its tone to the requesting `mood_hint`:
  - `celebratory` → emphasise wins
  - `stuck` → surface failures helpfully, not accusatorially
  - `normal` → standard state dump
  - `quiet` → silent (or single-line)
- A buddy MUST NOT invent encouragement or speculate about state it can't
  verify. Every claim cites a real row.

## Reference implementation (Wyrm)

Wyrm 5.8.0 implements the protocol with three entry points:

| Entry point | Purpose |
|---|---|
| `buddy` | The well-known name. Generic, project-agnostic status. What other buddies call. |
| `wyrm_buddy` | Rich, project-specific. Accepts `project_path`, mood/size/persona overrides, federates with peers. What your AI calls. |
| `gatherBuddyInputs()` | Internal data collector. Single SQL pass over sessions, quests, truths, scaffolds, failures, goals, hours. |

When `wyrm_buddy` federates, it calls each registered MCP server's `buddy`
tool first; falls back to `*_buddy` matches if `buddy` isn't present;
folds the replies into a "From other buddies" markdown section in the
local reply.

## Adopting the protocol

To make your MCP server buddy-compatible:

1. **Add a `buddy` tool** to your MCP server with the input schema in §2.
2. **Return markdown** in the shape from §3. Cite real rows.
3. **(Optional) Add `<name>_buddy`** for richer first-party callers.
4. **(Optional) Implement outbound federation** — call peer buddies
   yourself, fold their replies in. Cycle-protect via `from_buddy`.

That's the whole protocol. There is no compliance test, no registry, no
maintainer; the convention is the spec.

## Anti-patterns

- ❌ Returning structured JSON in the `markdown` slot — the calling buddy
  can't render arbitrary JSON inline; use `format: "json"` if you want
  structured.
- ❌ Calling peer buddies synchronously in a chain (A calls B which calls C
  which calls A) — implement the `from_buddy` cycle check.
- ❌ Buddy that takes 30s to respond — cap your data-gathering, return
  partial state if needed, suggest 5s as the budget.
- ❌ Buddy that hallucinates ("good morning! I think you're doing great!").
  Without data-grounding, it's just a chatbot.
- ❌ Forgetting to scope by `project_hint` when set — peer queries should
  return state relevant to the calling project, not your whole org.

## Why "buddy"?

The name was chosen because:

- It's short, casual, and not associated with a particular vendor (unlike
  `companion`, `assistant`, `agent` — all overloaded).
- It conveys *peer relationship*, not subordination — buddies federate,
  they don't dispatch to each other.
- The English word's connotation of "checking in" matches the protocol's
  use case better than "status" or "health" (both of which feel
  ops-rotation rather than conversational).

## Versioning

This document describes Buddy Protocol **v1.0**. Future versions will
maintain backward compatibility — additive fields only, no required
field removals. Servers SHOULD include their protocol version in the
JSON response shape under `buddy.protocol`.

## Future

- **`buddy_subscribe`** (planned): a tool that lets one buddy subscribe to
  another's state-change events via SSE / long-poll, for ambient
  awareness rather than poll-on-demand.
- **`buddy_broadcast`** (planned): a tool that fans a notification out to
  all registered peer buddies (e.g. "I just shipped v5.8.0 — let your
  operator know").

Both are out of scope for v1.0 but compatible with the call-and-response
shape defined here.
