# MCP Quickstart

This walkthrough registers a federated MCP server, publishes its tools, grants a principal, and
connects an MCP client to the tool gateway. Management lives under the project MCP prefix
`/v1/projects/:projectId/mcp/`; the tool gateway the client speaks is `/v1?mcp=<id>` on the hosted
edge (`/mcp/v1?mcp=<id>` on a self-hosted Node runtime). The required `?mcp=` selects which MCP a
connection exposes — a built-in id (`provon` or `duckduckgo`) or a registered server id.

Use the [`provon mcp` CLI](../cli/mcp.md), authenticated to your project. A key used to manage the
gateway must carry `mcp:manage`; a key used to invoke tools must carry `mcp:invoke`. Neither is in
the default key set, so grant them explicitly. The underlying HTTP contracts are in the
[MCP API reference](../api/mcp.md).

## 1. Register a server

For a remote MCP server over streamable HTTP:

```bash
provon mcp servers create "Acme internal tools" --source mcp \
  --url https://mcp.acme.example.com
```

`--source` is `mcp` or `openapi`. Native MCP federation uses streamable HTTP; OpenAPI servers may
be registered through the dedicated import command.

The server record returns with an `id` and a `connectionStatus` (initially `unknown` — it has not
been probed yet). Connection health (`unknown / reachable / unreachable / disabled`) and
authentication health are tracked as two separate states and are never collapsed into one status.

## 2. Attach a sealed upstream credential

The upstream auth method is a whitelisted credential type: `authorization_bearer` (injected
outbound as `Authorization: Bearer <secret>`) or `x_api_key` (injected as `X-Api-Key: <secret>`).
The secret is sealed at rest, never returned to you, and never forwarded from the caller's token.

```bash
SERVER_ID="<server id from step 1>"

provon mcp servers credentials add "$SERVER_ID" \
  --label acme-robot --secret "<upstream token>" --auth-method authorization_bearer
```

New credentials start as **Backups**; exactly one credential is the active **Primary**. There is no
selection priority. Isolation-test a backup (`servers credentials test`), then cut it over
(`servers credentials promote`); `pause`/`resume` hold and re-enable without revoking.

## 3. Test the connection and sync the catalog

Testing opens an outbound connection and records the server's connection status. Catalog sync
discovers the upstream tools and persists them. Imported OpenAPI operations land as **`draft`**
tools; publish the ones you want discoverable. Catalog sync works on both the self-hosted Node
runtime and the hosted edge for HTTP MCP and OpenAPI servers.

```bash
provon mcp servers test "$SERVER_ID"
provon mcp servers sync "$SERVER_ID"
```

`provon mcp tools list "$SERVER_ID"` shows the catalog. Publish a tool before discovery:
`provon mcp tools set-publish-state <server> <tool> --state published`. Other states are
`draft`, `deprecated`, or `archived`.

## 4. Grant a principal

Authorization is explicit and default-deny for **federation** tools. The five hosted tools
(`web_search`, Trace, and Finding readers) are already reachable by any `mcp:invoke`
caller without a policy; use a policy to admit federation tools or to carve out an explicit deny.

Allow the principal that will call the tool gateway:

```bash
provon mcp policies create \
  --effect allow \
  --principal-kind api_key --principal-ref "<invoking api key id>" \
  --action read --action invoke \
  --priority 100
```

`--principal-kind` is one of `user` or `api_key`. Omit
`--server` / `--tool` to scope to all, or repeat them to narrow. Any deny overrides every allow; a
request may only narrow what an allow grants. See [Security](./security.md) for the full model.

## 5. Connect an MCP client

Point any MCP-compatible client at the streamable-HTTP tool gateway for the MCP it needs and
authenticate with the **invoking** key (which carries `mcp:invoke`):

```text
URL:   https://mcp.provon.dev/v1?mcp=<serverId>
Auth:  Authorization: Bearer <key with mcp:invoke>
```

The `?mcp=` parameter selects the connection's scope. Use a registered server id to reach that
federation server's tools, or a built-in id (`provon` for trace/Finding readers, `duckduckgo` for web
search). Omitting `?mcp=` returns `400 MCP_ID_REQUIRED`.

The client performs `initialize`, then `tools/list` to discover the published tools within that MCP
that your policy allows, and `tools/call` to run one. On a local Node deployment the URL is
`http://127.0.0.1:3000/mcp/v1?mcp=<serverId>`.

## Verify the setup

1. `provon mcp servers test <serverId>` reports reachable, and the credential shows an active
   primary after `promote`.
2. `provon mcp tools list <serverId>` shows the synced tools; each intended tool has publish state
   `published`.
3. `provon mcp policies list` contains the allow policy for the invoking principal with `read` and
   `invoke`.
4. The client `initialize` handshake succeeds, `tools/list` returns only the allowed published
   tools, and one `tools/call` returns content without a permission or upstream error.
5. Removing the policy or setting a tool back to `draft` makes it disappear from `tools/list` on
   the next connection.

## Workbench

Open **MCP gateway** in the Workbench navigation. The section has two screens:

- **`/mcp`** — the server list, access policies, and the project-wide tool catalog. From here you
  create, edit, and delete servers, import an OpenAPI document as tools, and test a server
  connection. You also create and remove the allow/deny [policies](./security.md) that govern who
  can discover and invoke federation tools.
- **`/mcp/:serverId`** — one server's detail. Two independent badges show its **connection**
  health (`reachable` / `unknown` / `unreachable` / `disabled`) and its **auth** posture
  (`not_required` / `missing` / `active` / `invalid` / `revoked`) — they are never collapsed into one
  status. Toggle it **enabled**, run **test**, **discover** its upstream catalog, **sync** tools,
  flip each tool's **publish state** (`draft` / `published` / `deprecated` / `archived`), and
  manage sealed **credentials** (Primary/Backup, with test / pause / resume / promote / revoke).
  Only `not_required` (anonymous) and `active` are callable. When auth is `missing`, `invalid`, or
  `revoked`, the catalog stays editable but outbound calls are blocked until you test and promote an
  active primary. Built-in MCPs have no upstream and no credentials section at all — they
  authenticate as the project identity.

Every Workbench action maps 1:1 to a `provon mcp` command and a route in the
[MCP API reference](../api/mcp.md); use the browser for interactive setup and the CLI or API for
scripted workflows.
