---
name: handler
description: Use Handler when building, testing, and operating agentic systems
  that communicate via the A2A protocol. Reach for this skill when you need to
  inspect agent cards, send messages and files to A2A agents, manage tasks and
  sessions, configure production authentication, receive webhook notifications,
  or expose A2A operations through MCP for other agents.
metadata:
  mintlify-proj: handler
  version: "1.0"
---

# Handler

Handler is an open-source A2A protocol client for software engineers building, testing, and operating agentic systems. It provides a terminal-native control surface: an interactive TUI for exploration, a scriptable CLI with structured output for automation, and an MCP server so other agents can call A2A services through Handler.

## Product summary

Handler is a CLI tool and TUI for interacting with A2A (Agent-to-Agent) protocol servers. Use it to inspect agent cards, send messages and files, manage tasks, configure authentication, and receive push notifications. Handler supports six auth types (bearer, API key, HTTP Basic, mTLS, OAuth2, OpenID Connect) and can be bridged into MCP clients.

**Key files and commands:**
- Global config: `~/Library/Application Support/handler/servers.toml` (macOS), `$XDG_CONFIG_HOME/handler/servers.toml` (Linux), AppData (Windows)
- Repo config: `.handler/servers.toml` in repository root
- Primary commands: `handler tui`, `handler message send`, `handler task list`, `handler server add`, `handler mcp`
- Output modes: `--output text` (default), `--output json`, `--output ndjson` (for streaming)

**Primary docs:** https://handler.alduncanson.com

## When to use

Use Handler when you need to:

- **Inspect and validate agent cards** before debugging protocol issues
- **Send messages, files, and structured data** to A2A agents from shell scripts or CI/CD
- **Manage tasks** — list, get status, cancel, or resubscribe to streaming events
- **Configure production authentication** — save bearer tokens, API keys, mTLS certs, OAuth2, or OpenID Connect credentials globally or per-repo
- **Receive task notifications** via webhook with a local receiver
- **Bridge A2A operations into MCP** so other agents can call A2A services through Handler
- **Debug agent interactions interactively** with the TUI before automating them

Do not use Handler for: agent development (use the A2A protocol directly), managing agent infrastructure, or replacing enterprise platform controls.

## Quick reference

### Core commands

| Command | Purpose |
| --- | --- |
| `handler tui` | Launch interactive terminal UI |
| `handler card get --server NAME` | Fetch agent card |
| `handler card validate --server NAME` | Validate card structure |
| `handler message send --server NAME --text "..."` | Send message and wait for response |
| `handler message stream --server NAME --text "..."` | Send message and stream response in real time |
| `handler task list --server NAME` | List all tasks on agent |
| `handler task get TASK_ID --server NAME` | Get task status |
| `handler task cancel TASK_ID --server NAME` | Cancel running task |
| `handler server add NAME --url URL` | Add server to global config |
| `handler server add NAME --url URL --repository` | Add server to repo config |
| `handler server validate` | Validate all configured servers and auth |
| `handler mcp` | Start MCP server (stdio transport) |

### Message options

| Option | Purpose |
| --- | --- |
| `--text "..."` | Message text (optional if file/data attached) |
| `--file PATH` or `--file URL` | Attach file (local path sent inline, URL by reference) |
| `--data '{...}'` | Attach JSON data (repeatable) |
| `--stream` | Stream response instead of waiting |
| `--no-wait` | Return immediately with task ID, don't wait for completion |
| `--continue` | Resume saved conversation context |
| `--accept TYPE` | Tell agent which media types you can render (repeatable) |
| `--history-length N` | Request N recent messages from agent |
| `-e, --extension URI` | Request A2A extension (repeatable) |
| `--push-url URL` | Set webhook for task notifications |
| `--push-token TOKEN` | Token agent sends in notification header |

### Output modes

| Mode | Use case |
| --- | --- |
| `--output text` | Human-readable (default); warnings on stderr |
| `--output json` | Full protocol responses; useful for scripts |
| `--output ndjson` | Newline-delimited JSON; for streaming event consumers |

### Authentication types

| Type | CLI flag | TOML key | Notes |
| --- | --- | --- | --- |
| Bearer token | `--bearer-env VAR` | `type = "bearer"` | Sent as `Authorization: Bearer` |
| API key | `--api-key-env VAR` | `type = "api_key"` | Sent in `X-API-Key` by default; customize with `--api-key-header` |
| HTTP Basic | `--basic-username USER --basic-password-env VAR` | `type = "basic"` | Username shown; password never shown |
| mTLS | `--cert PATH --key PATH` | `type = "mtls"` | Paths expanded; key must not be group/world-readable |
| OAuth2 | `--oauth2-token-url URL --oauth2-client-id-env VAR --oauth2-client-secret-env VAR` | `type = "oauth2"` | Fetches and refreshes access token automatically |
| OpenID Connect | `--oidc-issuer-url URL --oidc-client-id-env VAR --oidc-client-secret-env VAR` | `type = "oidc"` | Discovers token endpoint from issuer |

### Server configuration (TOML)

```toml
version = 1

[servers.demo]
url = "https://agent.example.com"
extensions = ["https://example.com/extensions/traceability/v1"]

[servers.demo.auth]
type = "bearer"
env = "HANDLER_DEMO_TOKEN"
```

### Global options

| Option | Purpose |
| --- | --- |
| `-v, --verbose` | Enable verbose logging |
| `-d, --debug` | Enable debug logging |
| `--connect-timeout SECONDS` | HTTP connect timeout (env: `HANDLER_CONNECT_TIMEOUT`) |
| `--read-timeout SECONDS` | HTTP read timeout for non-streaming (env: `HANDLER_READ_TIMEOUT`) |
| `--stream-read-timeout SECONDS` | HTTP read timeout for streaming (defaults to `none`) |

## Decision guidance

### When to use CLI vs TUI

| Scenario | Use |
| --- | --- |
| Exploring an agent interactively, debugging auth, browsing cards | TUI (`handler tui`) |
| Scripting, CI/CD, shell history, structured output | CLI (`handler message send`, etc.) |
| Debugging a specific agent before saving config | TUI with `--url` |
| Repeated automation against configured servers | CLI with `--server` |

### When to use message send vs message stream

| Scenario | Use |
| --- | --- |
| Short, synchronous requests; you want the final answer | `message send` |
| Long-running tasks; you want to see progress | `message stream` |
| Automation that needs structured events | `message stream --output ndjson` |
| Fire-and-forget with polling later | `message send --no-wait` |

### When to use global vs repo-scoped config

| Scenario | Use |
| --- | --- |
| Personal dev setup, shared across projects | Global (`handler server add NAME --url URL`) |
| Agent URL/auth belongs with the repo, secrets from env | Repo-scoped (`handler server add NAME --url URL --repository`) |
| Shared team setup with different secrets per machine | Repo-scoped config + env vars on each machine |

### When to use MCP vs CLI

| Scenario | Use |
| --- | --- |
| Another agent needs to call A2A services | MCP (`handler mcp` in agent config) |
| You're scripting or automating from shell | CLI |
| Debugging a single call | CLI |
| Integrating Handler into an agent harness (Amp, Pi) | MCP |

## Workflow

### 1. Set up a server connection

**Option A: One-off exploration**
```bash
handler tui --url http://localhost:8000
```
Use the TUI to test auth, inspect the card, and send messages.

**Option B: Save for repeated use**
```bash
handler server add demo --url http://localhost:8000
handler server validate
```
For production, add auth:
```bash
handler server add prod --url https://agent.example.com --bearer-env HANDLER_PROD_TOKEN
```

### 2. Inspect the agent card

```bash
handler card get --server demo
handler card validate --server demo
```

If the agent offers an extended card to authenticated clients:
```bash
handler card get --server demo --extended
```

### 3. Send a message

**Simple text:**
```bash
handler message send --server demo --text "Hello"
```

**With file and structured data:**
```bash
handler message send --server demo \
  --text "Review this" \
  --file ./report.pdf \
  --data '{"priority": "high"}'
```

**Stream the response:**
```bash
handler message stream --server demo --text "Summarize your capabilities"
```

**For automation, use JSON output:**
```bash
handler --output json message send --server demo --text "Hello"
```

### 4. Manage tasks

List all tasks:
```bash
handler task list --server demo
```

Get status of a specific task:
```bash
handler task get TASK_ID --server demo
```

Cancel a running task:
```bash
handler task cancel TASK_ID --server demo
```

### 5. Set up push notifications

Configure a webhook for a task:
```bash
handler task notification set TASK_ID --server demo \
  --webhook-url http://127.0.0.1:9000/webhook \
  --token local-secret
```

Or attach the webhook when sending the message:
```bash
handler message send --server demo --text "Long job" --no-wait \
  --push-url http://127.0.0.1:9000/webhook \
  --push-token local-secret
```

Start a local webhook receiver:
```bash
handler server run push --port 9000 --token local-secret
```

### 6. Continue a conversation

Handler saves session context locally. Resume it:
```bash
handler message send --server demo --text "Follow up" --continue
```

Or inspect saved sessions:
```bash
handler session show --server demo
```

### 7. Bridge into MCP (for agent harnesses)

Add to your agent's MCP config (e.g., Amp, Pi):
```json
{
  "mcpServers": {
    "handler": {
      "command": "handler",
      "args": ["mcp"]
    }
  }
}
```

The agent can now call 13 MCP tools: `get_agent_card`, `send_message`, `get_task`, `list_tasks`, `cancel_task`, `set_task_notification`, `get_task_notification`, `list_task_notifications`, `delete_task_notification`, `list_sessions`, `get_session_info`, `clear_session_data`, `validate_agent_card`.

## Common gotchas

- **Credentials leak to wrong origins:** Handler only sends auth to the origin (scheme + host + port) you configured. If an agent card routes requests elsewhere, Handler warns and holds back credentials. Check `handler server show NAME` to verify the origin.

- **Secrets in TOML files:** Never put secret values in `servers.toml`. Always use environment variables with the `env` key. Handler will refuse to load a file with a literal secret value.

- **File size limit:** Inline files are capped at 10 MiB. Use `http(s)` URLs for larger files; the agent fetches them by reference.

- **Auth override doesn't persist:** `--bearer-env` or `--api-key-env` on a single command overrides saved auth for that call only. It does not update the server config.

- **Extended card requires auth:** If an agent advertises `extendedAgentCard` but you're not authenticated, `handler card get --extended` will fail. Add auth to the server config first.

- **Task notification token is required for security:** If you bind the webhook receiver beyond loopback (`--host` other than 127.0.0.1), always use `--token` to require the agent to send it in the `X-A2A-Notification-Token` header.

- **Streaming disables read timeout by default:** Long-running tasks won't be aborted during idle gaps between SSE events. Set `--stream-read-timeout` explicitly if you need a timeout.

- **`--no-wait` and `--stream` are mutually exclusive:** Use `--no-wait` to return immediately with a task ID, or `--stream` to watch events in real time. Not both.

- **Repo config requires `.handler/` directory:** When using `--repository`, Handler creates `.handler/servers.toml`. Make sure `.handler/` is not in `.gitignore` if you want the config to travel with the repo.

- **Validation catches config errors early:** Always run `handler server validate` after adding or editing servers. It catches invalid TOML, missing env vars, bad auth files, and agent card issues before you debug task execution.

## Verification checklist

Before submitting work with Handler:

- [ ] Run `handler server validate` to catch config errors, missing env vars, and auth issues
- [ ] Verify the agent card with `handler card get --server NAME` and `handler card validate --server NAME`
- [ ] Test a message with `handler message send --server NAME --text "test"` before automating
- [ ] Check that credentials are bound to the right origin: `handler server show NAME`
- [ ] If using push notifications, verify the webhook receiver is running and the token matches
- [ ] For MCP integration, confirm the agent harness can load Handler with `handler mcp` manually first
- [ ] Use `--output json` in scripts and verify the response structure matches expectations
- [ ] Clear saved sessions with `handler session clear --server NAME` if you need a fresh start
- [ ] Check logs with `-v` or `-d` if a command fails unexpectedly

## Resources

**Comprehensive page listing:** https://handler.alduncanson.com/llms.txt

**Critical documentation:**
- [Messages, tasks, and sessions](https://handler.alduncanson.com/guides/messages-tasks) — CLI automation, structured output, task management
- [Authentication](https://handler.alduncanson.com/guides/authentication) — all six auth types, credential binding, validation
- [MCP server](https://handler.alduncanson.com/guides/mcp) — exposing A2A tools to other agents, tool list, typical workflows

---

> For additional documentation and navigation, see: https://handler.alduncanson.com/llms.txt