# MCP Client

Agenvoy's MCP client lets agents call tools exposed by any MCP server. Client and server share one package (`internal/runtime/mcp`) built on the official [`modelcontextprotocol/go-sdk`](https://github.com/modelcontextprotocol/go-sdk).

## Configuration layout

One file. The session-scoped layer was removed — every client reads the same config:

```
~/.config/agenvoy/mcp.json
```

### JSON format

```json
{
  "servers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}" }
    },
    "remote-api": {
      "url": "https://api.example.com/mcp",
      "headers": { "Authorization": "Bearer ${TOKEN}" }
    }
  }
}
```

`command` and `url` are mutually exclusive. `${VAR}` / `$VAR` placeholders inside `env`, `headers`, and `args` are expanded with `os.ExpandEnv` at startup.

## Transport types

| Type | Config keys | SDK transport | Use case |
|---|---|---|---|
| stdio | `command` + `args` + `env` | `CommandTransport` | Local CLIs (`npx`, native binaries) |
| Streamable HTTP | `url` + `headers` | `StreamableClientTransport` | Remote services, long-running MCP servers |

Both transports are handled by the SDK; Agenvoy only supplies the command or the endpoint plus a header-injecting HTTP client.

## Management

| Task | TUI | HTTP |
|---|---|---|
| List servers | `/mcp` | `GET /v1/mcp` |
| Add a server | `/mcp` | `POST /v1/mcp` |
| Remove a server | `/mcp` → `d` on the server | `POST /v1/mcp/remove` |
| Connection status | `/mcp` | `GET /v1/mcp/status` |
| Reconnect and re-register tools | `/mcp` → server → reconnect (that server only) | `POST /v1/mcp/reconnect` (all servers) |
| List registered MCP tools | `/mcp` → server → tools | `GET /v1/mcp/tools` |
| Per-tool auto-approve | `/mcp` → server → tools | `POST /v1/allowlist` with a `tool` block |
| Browser OAuth login | `/mcp` → server → login / relogin | `GET /v1/mcp/oauth?name=X` (SSE) |
| Pre-registered OAuth client | `/mcp` → server → client | `POST /v1/mcp/oauth/client` |
| Clear an OAuth login | — | `DELETE /v1/mcp/oauth` |

The add flow asks for the server name, transport (Local stdio / Remote HTTP), and the type-specific fields. There are no `agen mcp` CLI subcommands. Since v1.2.0 the TUI opens no MCP connections of its own: `/mcp` status, reconnect, tools and remove (disconnect) are sent to the daemon over its Unix socket (`~/.config/agenvoy/daemon.sock`), which owns every MCP client.

### OAuth for HTTP servers

A server marked `auth: oauth` logs in through `mcp.Login`: the daemon opens a loopback callback listener on `localhost:17988`, performs dynamic client registration when the provider allows it, and stores the resulting token and client id in the OS keychain. When the provider rejects dynamic registration, supply a pre-registered client with `POST /v1/mcp/oauth/client` (`redirect_uri` defaults to `http://localhost:17988/callback` and must match the provider console exactly). When the browser cannot reach the listener, paste the redirect URL back with `POST /v1/mcp/oauth/callback`.

## Recommended servers

Zero-auth, locally executed (no API key required):

| Server | Purpose |
|---|---|
| `mcp-server-sqlite` | Run SQL on local `.db` files |
| `@modelcontextprotocol/server-memory` | Persistent knowledge graph |
| `@playwright/mcp` | Browser automation (downloads chromium) |
| `@modelcontextprotocol/server-postgres` | Local Postgres connection |
| `mcp-server-time` | Timezone conversion / relative time |

Avoid registering MCP servers whose capabilities overlap with built-in tools (e.g., `filesystem`, `git`, `fetch`, `shell`) — duplicates only inflate the LLM tool list.
