# Coding Agents

> Scaffold FirstByte features with your coding agent. Resources include readable docs, an MCP server, a CLI, and ready-made skills.

Your coding agent can write FirstByte code that compiles. Point
Claude Code, Cursor, Codex CLI, or another agent at the resources below.
The agent can then scaffold, dial, and wire up features. You do not need
to spell out the wire format by hand.

Three things make that work:

1. A documentation surface that your agent can read directly (no HTML
   scraping).
2. An MCP server that it can call as a tool.
3. A CLI (`clutchcall`) that scaffolds projects with agent-ready
   `AGENTS.md` files included.

Point your agent at these resources before you ask it to write
FirstByte code.

## MCP server

The docs MCP server is available at:

```
https://docs.firstbyte.fast/api/mcp
```

It uses Streamable HTTP transport (POST JSON-RPC). It exposes three
tools:

| Tool          | Args                       | Returns                                                |
|---------------|----------------------------|--------------------------------------------------------|
| `list_pages`  | (none)                     | Navigation-grouped slug index of every docs page.      |
| `search_docs` | `query`, `limit?` (≤25)    | Ranked matches with title, description, and snippet.   |
| `get_page`    | `slug` (e.g. `rpc/method-ids`) | Full Markdown body of the page.                    |

### Wiring into Claude Code, Cursor, etc.

**Claude Code (.mcp.json):**
```json
{
  "mcpServers": {
    "firstbyte-docs": {
      "url": "https://docs.firstbyte.fast/api/mcp"
    }
  }
}
```

**Cursor (.cursor/mcp.json):**
```json
{
  "mcpServers": {
    "firstbyte-docs": {
      "url": "https://docs.firstbyte.fast/api/mcp"
    }
  }
}
```

**Codex CLI (codex.toml):**
```bash
[mcp_servers.firstbyte-docs]
url = "https://docs.firstbyte.fast/api/mcp"
```

After configuration, your agent sees `list_pages`, `search_docs`, and
`get_page` as callable tools next to its built-in toolbox.

### Smoke test

```bash
curl -X POST https://docs.firstbyte.fast/api/mcp \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

## Platform MCP server (control plane)

The docs server above is a read-only reference. A second MCP server runs
on the **control plane**. It lets an agent operate your workspace: list
calls, originate, manage agents, and pull analytics. The agent can do
anything that your role in the organization allows. See
[Platform MCP Server](/platform/mcp) for the full usage guide:

```
https://portal.firstbyte.fast/mcp
```

It uses the same transport (Streamable HTTP, POST JSON-RPC), but it is
authenticated. Mint an **MCP access key** in the portal under
**Settings → API Keys → MCP access keys** (owners/admins only). Send the
key as a Bearer token. The key acts as the user who minted it, confined
to that one organization. Every call runs under your own membership,
role, and per-modality grants. The key stops working the moment your
membership stops.

A key also holds narrow scopes. A scope has the form
`mcp:<domain>:<action>`, such as `mcp:cdr:read`. One scope permits one
action class in one operation group. There is no scope that permits
everything. Select the smallest set that does the job.

Instead of one tool per API operation (~540), the server exposes five
meta-tools in two sets. The tool listing labels each set, so a client can
separate them before it calls anything.

Public tools. Read-only, server metadata only, no scope needed:

| Tool                 | Args                            | Returns                                              |
|----------------------|---------------------------------|------------------------------------------------------|
| `whoami`             | (none)                          | Acting user, reachable org(s), roles, scopes.        |
| `list_operations`    | `group?`, `filter?`, `granted?` | Operation catalog, with the scope each op needs.     |
| `describe_operation` | `path`                          | Query/mutation, required scope, org scoping, input schema. |

Privileged tools. These reach tenant data, and each call needs the one
scope of the operation:

| Tool             | Args             | Needs                                        |
|------------------|------------------|----------------------------------------------|
| `read_operation` | `path`, `input?` | `mcp:<domain>:read`                          |
| `call_operation` | `path`, `input?` | `mcp:<domain>:write`, `:delete`, or `:admin` |

`read_operation` refuses a mutation, and `call_operation` refuses a
query. An agent follows this workflow: `whoami` → `list_operations` →
`describe_operation` → `read_operation` or `call_operation`. For
org-scoped operations, the server pins the organization id to the key's
org. An agent cannot be steered into another tenant.

**Claude Code (.mcp.json):**
```json
{
  "mcpServers": {
    "firstbyte-platform": {
      "url": "https://portal.firstbyte.fast/mcp",
      "headers": { "Authorization": "Bearer mpk_…" }
    }
  }
}
```

**Cursor (.cursor/mcp.json):**
```json
{
  "mcpServers": {
    "firstbyte-platform": {
      "url": "https://portal.firstbyte.fast/mcp",
      "headers": { "Authorization": "Bearer mpk_…" }
    }
  }
}
```

### Smoke test

```bash
curl -X POST https://portal.firstbyte.fast/mcp \
  -H 'content-type: application/json' \
  -H 'authorization: Bearer mpk_…' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"whoami","arguments":{}}}'
```

> **WARNING:**
> An MCP access key is a durable credential. Mint it with `read` scopes
>   only, unless the agent genuinely needs to change things. Do not select
>   a `delete` or `admin` scope for an agent that only creates and updates.
>   Set an expiry. Name the key after the agent that holds it, so that you
>   can identify the correct key to revoke later.

### Bill of materials

Before you point an agent at the control plane, you can audit what the
server itself is built from. It publishes a
[CycloneDX](https://cyclonedx.org/capabilities/mlbom/) 1.6 bill of
materials — every production dependency with its version, licence and
registry integrity hash, plus the AI models the server can invoke:

```bash
curl -s https://portal.firstbyte.fast/.well-known/sbom.cdx.json
```

The same document is served at `https://portal.firstbyte.fast/mcp/sbom.cdx.json`.
Neither path needs authentication: a bill of materials exists to inform
the decision to trust the server, so it cannot sit behind that trust.

The BOM is regenerated whenever the server binary is built, and
`metadata.component.version` carries the build sha the running server
reports at `/health`. That is how you tell whether the document
describes the deployment you are actually talking to.

## Plain-text documentation

Some agents do not speak MCP. For them, and for use as a static
prompt-context drop-in, every page is also published as plain Markdown:

| URL                                              | What it is                                                  |
|--------------------------------------------------|-------------------------------------------------------------|
| `https://docs.firstbyte.fast/llms.txt`            | A short, navigation-grouped index. Start triage here.       |
| `https://docs.firstbyte.fast/llms-full.txt`       | Every page concatenated, with page markers. Use it for whole-corpus context. |
| `https://docs.firstbyte.fast/<slug>.md`           | Per-page Markdown mirror (e.g. `/rpc/method-ids.md`).        |
| `https://docs.firstbyte.fast/search-index.json`   | Searchable JSON corpus (powers the MCP `search_docs` tool). |

The format follows the [llms.txt convention](https://llmstxt.org/). Put
the URL into an LLM's context window, and the LLM knows how to use it.

## CLI: `clutch`

The `clutch` CLI does what the MCP server does. After `clutch auth
login`, it also runs telephony operations against the live control-plane
API.

**Docs (no auth)**:

```bash
clutch docs overview                          # navigation index
clutch docs search "originate trunk"          # full-text search
clutch docs get-page rpc/method-ids           # one page as Markdown
```

**Auth**:

```bash
clutch auth login                             # browser OAuth → portal
clutch auth whoami                            # current identity + active org
```

**Trunks + calls** (after auth):

```bash
clutch trunks list                            # tabular view
clutch trunks show <id>                       # one trunk in detail
clutch dial +15551234567 --trunk <your-trunk-id> \
    --app AI_BIDIRECTIONAL_STREAM --app-args my-agent-id
clutch dial --list-apps                       # all 13 DialplanAction values
clutch hangup <call_sid>
```

> **WARNING:**
> `clutch dial` defaults `--app` to `AI_BIDIRECTIONAL_STREAM` (=6). If
>   you do not pass `--app-args <agent_id>`, the runtime has no agent to
>   bridge. The call then lands in silence. For raw audio piping without
>   an AI agent, use `--app ANSWER` (=5).

**Mid-call control verbs** (each calls `ExecuteDialplan` server-side):

```bash
clutch transfer <call_sid> +15551234567       # RFC 3515 SIP REFER
clutch mute     <call_sid>                    # gateway-side TX silence
clutch mute     <call_sid> --wire             # also send recvonly re-INVITE
clutch unmute   <call_sid>
clutch hold     <call_sid>
clutch unhold   <call_sid>
clutch send-dtmf <call_sid> 5 --mode rfc2833 --duration-ms 200
```

Override targets with env vars: `CLUTCH_BASE_URL` (portal), `CLUTCH_DOCS_BASE` (docs site).

## Scaffolding agent-ready projects

`clutchcall init <lang> <name>` creates a working starter in your
working directory:

```bash
clutchcall init go      my-voice-agent
clutchcall init python  my-py-agent
clutchcall init typescript browser-demo
```

Each starter includes:

- A working dial / event-handling sample (`main.clutchcall` /
  `main.py` / `src/index.ts`) that compiles against the FirstByte SDK.
- An **`AGENTS.md`** file tuned for that language. Agents read this file
  first when they enter the project. It captures the language-specific
  traps that an agent will otherwise re-discover the hard way
  (e.g. "Emscripten corrupts byte arrays passed as `std::string`; use
  `typed_memory_view` instead").
- A `.clutchcall.json` project manifest with a pinned schema version
  for `clutchcall migrate`.

## Best practices for AI-assisted development

These practices apply to any SDK that changes quickly. We list them
because the FirstByte wire format and method-ID table change between
minor releases.

1. **Browse before you search.** Tell your agent to fetch `/llms.txt`
   first, so that it knows what exists. Search excerpts are noisier than
   full pages.
2. **Fetch full pages, not excerpts.** Use `get_page` (MCP) or
   `get-page` (CLI) when you need authoritative answers. The grouped
   index is for navigation. The page itself is for code.
3. **Never hand-edit serde structs.** The Python, TypeScript, Go, Rust,
   Java, and .NET bindings are auto-generated from the schema. To add an
   RPC field, your agent should update the upstream schema and
   regenerate. It should not patch the binding by hand.
4. **Run `clutchcall migrate` after you bump the SDK.** This
   shows schema drift before runtime does.

## Agent Skills

The
[FirstByte Agent Skills](https://github.com/firstbytefast/skills)
repository ships end-to-end recipes. A recipe loads into your coding
agent's context when your intent matches. The agent then builds the
feature the correct way the first time. Put the repo into
`.claude/skills/` (Claude Code) or `.cursor/skills/` (Cursor). Your
agent then gains task-specific knowledge for these workflows:

**Generic recipes**
- `clutchcall-pstn-dial` — outbound PSTN dialing (auth, originate,
  audio frames, hangup).
- `clutchcall-ai-bridge` — wire a live call to OpenAI Realtime /
  Anthropic / Gemini Live with barge-in.
- `clutchcall-call-events` — `CallEvent` stream consumption,
  reconnection, Q.850 cause handling.
- `clutchcall-inbound-routing` — `SetInboundRouting` →
  `AnswerIncomingCall`, IVR menus, queueing.
- `clutchcall-sip-trunk` — register a carrier (Twilio, Telnyx,
  Bandwidth, Plivo), caller-ID rules, codecs.
- `clutchcall-bulk-campaign` — `OriginateBulk` with CSV input,
  pacing, abort + resume.
- `clutchcall-recording` — per-call recording, stereo, retrieval,
  transcription.
- `clutchcall-tool-calling` — LLM tool / function calling: the
  built-in implicit telephony toolset (transfer / hold / DTMF /
  disconnect / supervisor), custom server-side tools, and client-side
  tool calls via OpenAI Realtime.
- `clutchcall-rag-integration` — pgvector / Pinecone / Weaviate
  retrieval as a tool call with latency budgets and barge-in safety.
- `clutchcall-crm-enrichment` — pre-call enrichment (Salesforce
  / HubSpot lookup → system prompt overrides) vs. in-call tool lookup.

**Vendor bridges**
- `clutchcall-vendor-browser-webrtc` — capture mic in the browser,
  send PCMU over WebTransport.
- `clutchcall-vendor-livekit` — bridge PSTN into a LiveKit room.
- `clutchcall-vendor-daily` — bridge PSTN into a Daily room
  (Pipecat-friendly).
- `clutchcall-vendor-chime` — Amazon Chime SDK Meetings or Voice
  Connector.
- `clutchcall-vendor-twilio` — bridge from existing Twilio Media
  Streams (TwiML `<Stream>`) into FirstByte.
- `clutchcall-vendor-vapi` — bridge a Vapi.ai voice agent over
  Vapi's WebSocket transport.

Each skill is self-contained. It includes a prereqs checklist, working
Python/TypeScript code, a "verify it works" snippet, common gotchas, and
pointers back to the docs MCP for deeper reference.
