# MCP CLI

The `provon mcp` group manages project-scoped MCP servers, tools, upstream credentials, and
access policies. Every command is project-scoped: the project resolves from the active profile,
and there is no global MCP API.

Output is JSON by default; pass `--output human` for tables and one-line summaries:

```bash
provon mcp --output human servers list
```

## Prerequisites

- Selected project and authenticated credential.
- Management commands (servers, credentials, tools, policies) require `mcp:manage`; neither
  capability is in the default key set, so grant it explicitly.
- Tool invocation through the gateway requires `mcp:invoke`; see [MCP Security](../mcp/security.md).

## Command Tree

```text
provon mcp
  servers list
  servers create <display-name> [flags]
  servers update <server-id> [flags]
  servers delete <server-id>
  servers test <server-id>
  servers discover <server-id>
  servers sync <server-id>
  servers credentials list <server-id>
  servers credentials add <server-id> [flags]
  servers credentials test <server-id> <credential-id>
  servers credentials promote <server-id> <credential-id>
  servers credentials pause <server-id> <credential-id>
  servers credentials resume <server-id> <credential-id>
  servers credentials delete <server-id> <credential-id>
  openapi import [display-name] --spec-file <path> | --url <url>
  tools list <server-id>
  tools set-publish-state <server-id> <tool-id> --state <state>
  policies list
  policies create [flags]
  policies delete <policy-id>
```

## Servers

```bash
# Register a remote MCP server over streamable HTTP
provon mcp servers create "Acme internal tools" --source mcp \
  --url https://mcp.acme.example.com

# List, update, disable, delete
provon mcp servers list
provon mcp servers update mcp_srv_xxx --url https://new-host.example.com
provon mcp servers update mcp_srv_xxx --disabled
provon mcp servers delete mcp_srv_xxx
```

Create flags: `--source mcp|openapi` (default `mcp`), `--url`, `--spec-file <path>`,
`--enabled` (default) / `--disabled`. MCP servers require an HTTP `--url`; OpenAPI servers
derive it from the spec document.

Update flags: `--name`, `--url` (pass an empty value to clear), `--spec-file`, `--enabled` /
`--disabled`.

## Test, Discover, And Sync

```bash
provon mcp servers test mcp_srv_xxx      # upstream reachability
provon mcp servers discover mcp_srv_xxx # provisional tools without writing the catalog
provon mcp servers sync mcp_srv_xxx      # persist the upstream tool catalog
```

`discover` previews what `sync` would register; `sync` rebuilds the persisted tool catalog.

## Credentials

Credentials are sealed at rest and sent on the whitelisted outbound header for the server. New
credentials start as backups; exactly one credential is the active primary used on the
outbound path, and the rest are held for cutover after their own isolation test.

```bash
provon mcp servers credentials list mcp_srv_xxx
provon mcp servers credentials add mcp_srv_xxx \
  --label acme-robot --secret "<upstream token>" --auth-method authorization_bearer
provon mcp servers credentials test mcp_srv_xxx mcp_cred_yyy
provon mcp servers credentials promote mcp_srv_xxx mcp_cred_yyy
provon mcp servers credentials pause mcp_srv_xxx mcp_cred_yyy
provon mcp servers credentials resume mcp_srv_xxx mcp_cred_yyy
provon mcp servers credentials delete mcp_srv_xxx mcp_cred_yyy
```

`add` flags: `--label` (required), `--secret` (required), `--auth-method`
(`authorization_bearer`, default; or `x_api_key`), `--enabled` / `--disabled`.

Behavior:

- `test` isolation-checks a credential without promoting it: 401 classifies as an invalid
  credential, 403 as permission denied (a policy problem rather than a bad secret), other
  responses as unreachable.
- `promote` atomically cuts the selected credential over to primary.
- `pause` / `resume` hold and re-enable a credential without revoking it.
- `delete` removes the credential permanently.

## OpenAPI Import

```bash
provon mcp openapi import "Acme CRM" --spec-file ./acme-openapi.json
provon mcp openapi import "Acme CRM" --url https://acme.example.com/openapi.json
```

Provide exactly one of `--spec-file` or `--url` (`mcp.openapi_source_required` otherwise).
Import creates an `openapi`-source server and one draft tool per operation. Imported tools are
not discoverable until published with `tools set-publish-state`; see
[OpenAPI import](../mcp/openapi.md).

## Tools

```bash
provon mcp tools list mcp_srv_xxx
provon mcp tools set-publish-state mcp_srv_xxx mcp_tool_zzz --state draft
```

Publish states: `draft`, `published`, `deprecated`, `archived`.

## Policies

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

- `--effect`: `allow` or `deny` (required).
- `--principal-kind`: `user` or `api_key` (required); `--principal-ref` is required.
- `--action`: repeatable; at least one of `read`, `invoke` (`mcp.policy_no_actions` otherwise).
- Scope with repeatable `--server <id>` and `--tool <name>`; omit both for all targets.
- `--priority` defaults to `100`; higher values order matches, and any deny overrides allow.

There is no `manage` action: mutating the catalog and policies requires the management-surface
capability `mcp:manage`, not a principal-grantable tool action.

Two built-in servers, `provon` and `duckduckgo`, expose five tools
(`search_traces`, `get_trace`, `list_findings`, `get_finding`, `web_search`) and are always
addressable without a federation policy. Policies govern federated servers: admit tool calls
with an allow policy, or carve out explicit denies.

## Invoking Through The Gateway

The tool gateway endpoint is not a `provon mcp` subcommand. Connect an MCP client to it with
an `mcp:invoke`-bearing key:

- Node runtime: `POST /mcp/v1`
- Worker runtime: `POST /v1`
- Target a server with the `mcp` query parameter, e.g. `POST /mcp/v1?mcp=<serverId>`;
  omitting the parameter returns a 400 asking for the `mcp` id. Use the id shown by
  `provon mcp servers list`.

## Success Check

```bash
provon mcp servers list
provon mcp tools list <server-id>
```

A healthy result lists the server and its cataloged tools; after `sync`, newly registered tools
appear in `tools list`, and OpenAPI tools move to callable state only after
`provon mcp tools set-publish-state <server-id> <tool-id> --state published`.

## Troubleshooting

| Symptom                           | Likely cause                                | Fix                                                                     |
| --------------------------------- | ------------------------------------------- | ----------------------------------------------------------------------- |
| `HTTP_403` on management commands | Missing `mcp:manage`                        | Grant the capability on the key or use a session with management access |
| `mcp.openapi_source_required`     | Neither or both spec sources supplied       | Pass exactly one of `--spec-file`, `--url`                              |
| Credential test 401               | Stale or malformed upstream secret          | Rotate with `credentials add`, then `promote`                           |
| Credential test 403               | Secret valid but upstream scope missing     | Fix upstream permissions; this is not a key-format error                |
| Tools hidden after import         | Still `draft`                               | Run `tools set-publish-state <server-id> <tool-id> --state published`   |
| Policy deny on invoke             | Deny rule matches the principal/server/tool | Review `policies list` and adjust priority or scope                     |
| Client call missing `mcp` id      | Query parameter omitted                     | Append `?mcp=<serverId>` to the gateway endpoint                        |
