# Diaphora MCP Server

The Diaphora MCP server is the remote [Model Context Protocol](https://modelcontextprotocol.io/) endpoint for the Diaphora platform. Point any MCP-compatible client — Claude Code, the Claude apps, Cursor, your own agent — at it, authenticate once over OAuth, and you MCP tool access to the Diaphora Platform.

## Authentication

Diaphora Core uses **OAuth 2.1** (authorization code + PKCE). There are two ways a client obtains an OAuth client identity:

1. **Dynamic Client Registration (DCR)** — the client registers itself with the authorization server on first connect. This is what the Claude apps do, and what Claude Code does when you _don't_ pass `--client-id`. Nothing to pre-configure.
2. **Pre-registered client** — Diaphora issues you a `client_id` (and optional secret) up front, which you supply to the client. Use this when DCR is disabled or you need a stable client identity.

### Redirect URIs

The authorization server matches the redirect URI **exactly**. Register the URI(s) your client uses:

| Client | Redirect URI to register |
| --- | --- |
| Claude Code (CLI) with `--callback-port 8080` | `http://localhost:8080/callback` |
| Claude apps / web / desktop / Cowork | `https://claude.ai/api/mcp/auth_callback` |

Notes for whoever administers the OAuth server:

- The CLI callback is `localhost` (not `127.0.0.1`), plain `http`, path `/callback`, with the port included. If you want to accept any CLI port, register the port-less `http://localhost/callback` as well and allow port-agnostic matching.
- The token endpoint must accept the client-authentication method the client uses. Claude Code authenticates with `client_secret_basic`; if your OAuth client is registered for `client_secret_post`, the token exchange fails with _"unsupported authentication method._" Set the client's `token_endpoint_auth_method` to match.

See [Troubleshooting](/content/docs/mcp#troubleshooting/index.html) for the exact error strings and fixes.

## Tool reference

### Frags engine

These four tools are the generic interface to every plan in your org.

#### `frags_search_plans`

Search or list available plans.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `search` | string | no | Partial plan name to match. Omit entirely to list all plans. |

Returns an array of plans, each with its `id`, `name`, `description`, `parameters`, `visibility`, `namespace`, `labels` (required tools/collections), and `signature` (if promoted to a named tool).

#### `frags_load_plan`

Load a plan's full definition — parameters, required tools, sessions, and output schema.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `plan_id` | string | yes | The plan's UUID. |

#### `frags_run_plan`

Execute a plan by ID and return its results (or a results handle).

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `plan_id` | string | yes | The plan's UUID. |
| `parameters` | object (string→string) | no | Runtime parameter values the plan declares. |

#### `frags_fetch_results`

Retrieve the results of a previous plan run.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `results_id` | string | yes | The results ID returned by a run. |

**Typical flow:**`frags_search_plans` to find a plan → `frags_load_plan` to inspect its parameters → `frags_run_plan` with those parameters → `frags_fetch_results` if the run is asynchronous.

## Visibility and namespaces

Plans are scoped, so you only see and run what's relevant to you:

| Visibility | Who can see / run it |
| --- | --- |
| `user` | Only the creator |
| `namespace` | Members of the plan's namespace (e.g. a team like `barndoor`) |
| `organization` | Everyone in the organization |

`frags_search_plans` returns plans across the scopes available to your authenticated identity. A plan's `namespace` groups related work; its `labels` (e.g. `mcp:Barndoor-Slack`, `collection:proof_of_funds_postgres`) declare the tools and data collections it depends on — useful for knowing what a plan will touch before you run it.

## Building your own plans

The tools on this server run plans that already exist in your org. To author new plans — sessions, output schemas, tool calls, and promoting a plan to a named tool with a signature — head to the [Guides](/content/docs/guides/index.html), which walk through the Frags plan format end to end.

### Claude apps (web / desktop / mobile) and Cowork

Add Diaphora as a **custom connector** in Settings → Connectors, using the URL `https://mcp.diaphora.io/mcp`. The hosted Claude surfaces perform Dynamic Client Registration automatically, so there are no flags to set — you just approve the OAuth consent screen. (The redirect URI these surfaces use is `https://claude.ai/api/mcp/auth_callback`; it's already handled on Diaphora's side.)

## Connecting

The server speaks Streamable HTTP and authenticates with OAuth 2.1 (authorization code flow with PKCE). Below are the common clients.

### Claude Code (CLI)

Add the server with the HTTP transport. If Diaphora issued you a pre-registered OAuth client, pass its client ID; otherwise omit it and Claude Code will register itself dynamically (see [Authentication](/content/docs/mcp#authentication/index.html)).

ShellCopy

```
claude mcp add --transport http \
  --client-id <your-client-id> \
  --client-secret \
  --callback-port 8080 \
  diaphora-core https://mcp.diaphora.io/mcp
```

A few things that trip people up:

- `--client-secret` is a **bare flag** — it does not take the secret inline. Claude Code prompts for it (masked) or reads it from the `MCP_CLIENT_SECRET` environment variable. Passing `--client-secret 'value'` makes the CLI treat your secret as the server _name_ and fail with `Invalid name ...`.
- `--callback-port` fixes the local OAuth redirect port so it can be pre-registered on the server side (see below). Without it, Claude Code uses an ephemeral port that won't match a fixed allowlist.

Then complete the OAuth handshake from inside a session:

`/mcp
`

Select `diaphora` → **Authenticate**. A browser opens for consent; on success you'll be redirected to `http://localhost:8080/callback` and the status flips to authenticated. On recent CLI versions you can also run `claude mcp login diaphora-core` from the shell.

### Other MCP clients

Any client that supports remote MCP over Streamable HTTP with OAuth 2.1 can connect. Point it at `https://mcp.diaphora.io/mcp` and complete the browser-based authorization flow. If your client supports Dynamic Client Registration it needs no pre-configuration; otherwise register a client with Diaphora and configure its ID/secret.

## Troubleshooting

**`Invalid name <secret>. Names can only contain letters, numbers, hyphens, and underscores.`** You passed the secret inline to `--client-secret`. It's a bare flag — drop the value and let it prompt, or set `MCP_CLIENT_SECRET`.

**`redirect_uri does not match any of the OAuth 2.0 Client's pre-registered redirect urls`** The client's callback isn't on the allowlist. Register the exact URI — `http://localhost:8080/callback` for the CLI with `--callback-port 8080`, `https://claude.ai/api/mcp/auth_callback` for the Claude apps. Match `localhost` vs `127.0.0.1`, scheme, path, and port exactly.

**`The OAuth 2.0 Client supports 'client_secret_post', but method 'client_secret_basic' was requested`** The token-endpoint auth method doesn't match. Claude Code uses `client_secret_basic`; set the OAuth client's `token_endpoint_auth_method` to `client_secret_basic`. This is a server-side client-registration setting, not something the `claude mcp add` flags control.

**"Works in the Claude app but not in Claude Code."** The apps use Dynamic Client Registration (they register their own client with a matching auth method), while a CLI configured with a hand-registered `--client-id` uses that fixed client. Either align that client's `token_endpoint_auth_method` to `client_secret_basic`, or drop `--client-id` so the CLI does DCR too (if the server allows it).

## Reference

- Endpoint: `https://mcp.diaphora.io/mcp`
- Frags engine tools: `frags_search_plans`, `frags_load_plan`, `frags_run_plan`, `frags_fetch_results`
- Named agents (current): `sales_audit`, `prep_call_analysis`, `voice_of_customer`, `altai`
- Model Context Protocol: [https://modelcontextprotocol.io](https://modelcontextprotocol.io/)
