# MCP

How nikcli connects local and remote Model Context Protocol servers, authenticates OAuth servers, and exposes MCP tools to agent sessions.

## Overview

MCP support is implemented in `packages/nikcli/src/mcp/index.ts`. The service reads `config.mcp`, creates local stdio or remote HTTP/SSE clients, records status, converts server tools into AI SDK dynamic tools, and exposes prompts/resources to sessions.

stdio

### Local

Runs a command in the current instance directory with environment from the config entry.

HTTP

### Remote

Tries Streamable HTTP first, then SSE, with optional headers and OAuth provider support.

Auth

### OAuth

Stores tokens in `mcp-auth.json`, supports dynamic or configured client registration, and can open a browser for auth.

Agent

### Tools

MCP tool schemas are wrapped as strict dynamic tools with per-call timeout support.

## Add a server

Use `nikcli mcp add` for interactive config patching, or edit `mcp` in `nikcli.json` directly. `nikcli mcp list` initializes configured servers and shows status.

Terminal

bash 

```
nikcli mcp add
nikcli mcp list
nikcli mcp auth remote-docs
nikcli mcp auth list
nikcli mcp logout remote-docs
nikcli mcp debug remote-docs
```

$ shell · paste into your terminal

| Command | Purpose |
| --- | --- |
| `mcp list` | Read config, connect servers, show connected/disabled/failed/auth status. |
| `mcp add` | Add a local or remote MCP entry to global or project config. |
| `mcp auth` | Start OAuth flow for a remote server with OAuth enabled. |
| `mcp auth list` | List OAuth-capable servers and token status. |
| `mcp logout` | Remove stored MCP auth for a server. |
| `mcp debug` | Inspect a configured server with a raw MCP client. |

## Local stdio servers

Local servers use `StdioClientTransport`. The command runs with cwd set to the current project directory. The environment is `process.env` plus configured `environment`; when the command is `nikcli`, `BUN_BE_BUN=1` is added.

nikcli.json

json 

1

2

3

4

5

6

7

8

9

10

11

12

```
{
  "mcp": {
    "filesystem": {
      "type": "local",
      "command": ["bunx", "@modelcontextprotocol/server-filesystem", "."],
      "environment": {
        "LOG_LEVEL": "info"
      },
      "timeout": 30000
    }
  }
}
```

| Field | Required | Meaning |
| --- | --- | --- |
| `type` | Yes | `local`. |
| `command` | Yes | Command array. First item is executable, rest are args. |
| `environment` | No | Extra environment variables passed to the child process. |
| `enabled` | No | `false` keeps the server disabled. |
| `timeout` | No | Connect and tool-list timeout in milliseconds. Default is 30000. |

## Remote servers

Remote servers use two transports in sequence. nikcli tries `StreamableHTTPClientTransport` first, then `SSEClientTransport`. Both receive configured headers and the OAuth auth provider when OAuth is enabled.

remote MCP

json 

1

2

3

4

5

6

7

8

9

10

11

12

```
{
  "mcp": {
    "remote-docs": {
      "type": "remote",
      "url": "https://example.com/mcp",
      "headers": {
        "X-Workspace": "docs"
      },
      "timeout": 45000
    }
  }
}
```

| Field | Required | Meaning |
| --- | --- | --- |
| `type` | Yes | `remote`. |
| `url` | Yes | Remote MCP endpoint URL. |
| `headers` | No | Static request headers for connect and capability calls. |
| `oauth` | No | OAuth config object, `false` to disable OAuth, or omitted to enable OAuth support. |
| `enabled` | No | Disable without deleting config. |
| `timeout` | No | Connection and capability-list timeout in milliseconds. |

## OAuth

Remote MCP OAuth is on by default unless `oauth` is `false`. The `McpOAuthProvider` supports configured client id, client secret, and scope. Tokens, client metadata, code verifier, OAuth state, and server URL are stored through `McpAuth.Service` in `Global.Path.data/mcp-auth.json`.

pre-registered client

json 

1

2

3

4

5

6

7

8

9

10

11

12

13

```
{
  "mcp": {
    "corp-docs": {
      "type": "remote",
      "url": "https://mcp.example.com",
      "oauth": {
        "clientId": "client-id",
        "clientSecret": "client-secret",
        "scope": "read write"
      }
    }
  }
}
```

Client registration errors

If a server returns an unauthorized error mentioning registration or client id, nikcli reports `needs_client_registration` and asks you to add `clientId` in config.

## Status model

| Status | Meaning |
| --- | --- |
| `connected` | Client connected and `listTools` succeeded. |
| `disabled` | Config entry has `enabled: false` or the server was disconnected. |
| `failed` | Connection or initial tool-list failed. Error string is stored. |
| `needs_auth` | Remote server returned unauthorized and OAuth can continue. |
| `needs_client_registration` | Remote server requires configured OAuth client id. |

The service keeps `status` and `clients` maps in instance state. When the instance shuts down, all MCP clients are closed and pending OAuth transports are cleared.

## Tools, prompts, resources

Connected MCP servers can contribute tools, prompts, and resources. Tool input schemas are wrapped as strict JSON schemas with `additionalProperties: false`. Tool calls use `resetTimeoutOnProgress` so long calls can continue when the server sends progress.

| Capability | Service method | Behavior |
| --- | --- | --- |
| Tools | `tools` | Fetches tool lists from connected clients and converts each MCP tool into an AI SDK dynamic tool. |
| Prompts | `prompts` | Lists prompts and names them as `client:prompt` after sanitizing names. |
| Resources | `resources` | Lists resources and attaches client name to each resource record. |
| Prompt read | `getPrompt` | Calls the selected client's prompt with optional string args. |
| Resource read | `readResource` | Reads a resource URI from the selected client. |
| Tool-list changed | `mcp.tools.changed` | Published when a server sends `ToolListChangedNotification`. |

## API routes

MCP has both classic Hono routes and typed HttpApi handlers.

| Route | Behavior |
| --- | --- |
| `GET /mcp` | Status map. |
| `POST /mcp` | Add a server config and attempt connection. |
| `POST /mcp/:name/auth` | Start OAuth and return authorization URL in typed API. |
| `POST /mcp/:name/auth/callback` | Finish OAuth with authorization code. |
| `POST /mcp/:name/auth/authenticate` | Run full CLI/TUI OAuth flow where supported. |
| `DELETE /mcp/:name/auth` | Remove stored auth. |
| `POST /mcp/:name/connect` | Connect or reconnect a server. |
| `POST /mcp/:name/disconnect` | Close client and mark disabled. |
| `POST /mcp/:name/toggle` | Patch config enabled state and disconnect when disabling. |

Terminal

bash 

```
curl http://127.0.0.1:4096/mcp

curl -X POST http://127.0.0.1:4096/mcp/remote-docs/connect

curl -X POST http://127.0.0.1:4096/mcp/remote-docs/toggle \
  -H "Content-Type: application/json" \
  -d '{"enabled":false}'
```

$ shell · paste into your terminal

## Timeouts and headers

The default MCP timeout is 30000 ms. A server-specific `timeout` overrides connect, initial `listTools`, and tool-call timeouts. Remote `headers` are passed to both Streamable HTTP and SSE transports.

Timeout failures remove tool availability

If a connected client later fails to list tools, the MCP service records the failure and that server's tools are not added to the agent tool set until it reconnects successfully.

## Failure modes

| Symptom | Likely cause | Fix |
| --- | --- | --- |
| `needs_auth` | Remote server requires OAuth and no valid token is stored. | Run `nikcli mcp auth <name>`. |
| `needs_client_registration` | Server does not support dynamic client registration. | Add `oauth.clientId`, and client secret if required. |
| Local server failed | Command missing, bad args, bad cwd, or server did not initialize before timeout. | Run the command manually from the project directory and increase timeout if needed. |
| Connected but no tools | `listTools` failed after connect. | Check server logs and tool-list response. |
| Browser did not open | Automatic browser open failed. | The CLI prints the auth URL through the `mcp.browser.open.failed` event path. |

## Source anchors

| Need | File |
| --- | --- |
| MCP service | `packages/nikcli/src/mcp/index.ts` |
| MCP auth storage | `packages/nikcli/src/mcp/auth.ts` |
| OAuth provider and callback | `packages/nikcli/src/mcp/oauth-provider.ts`, `packages/nikcli/src/mcp/oauth-callback.ts` |
| CLI command | `packages/nikcli/src/cli/cmd/mcp.ts` |
| Classic routes | `packages/nikcli/src/server/httpapi/mcp.ts` |
| Typed routes | `packages/nikcli/src/server/httpapi/mcp.ts` |
| TUI dialog | `packages/tui/src/component/dialog-mcp.tsx` |

---

Source: https://nikcli-ai.dev/docs/mcp
