Skip to content
nikcli
Docs
Documentation

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
CommandPurpose
mcp listRead config, connect servers, show connected/disabled/failed/auth status.
mcp addAdd a local or remote MCP entry to global or project config.
mcp authStart OAuth flow for a remote server with OAuth enabled.
mcp auth listList OAuth-capable servers and token status.
mcp logoutRemove stored MCP auth for a server.
mcp debugInspect 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
{
  "mcp": {
    "filesystem": {
      "type": "local",
      "command": ["bunx", "@modelcontextprotocol/server-filesystem", "."],
      "environment": {
        "LOG_LEVEL": "info"
      },
      "timeout": 30000
    }
  }
}
FieldRequiredMeaning
typeYeslocal.
commandYesCommand array. First item is executable, rest are args.
environmentNoExtra environment variables passed to the child process.
enabledNofalse keeps the server disabled.
timeoutNoConnect 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
{
  "mcp": {
    "remote-docs": {
      "type": "remote",
      "url": "https://example.com/mcp",
      "headers": {
        "X-Workspace": "docs"
      },
      "timeout": 45000
    }
  }
}
FieldRequiredMeaning
typeYesremote.
urlYesRemote MCP endpoint URL.
headersNoStatic request headers for connect and capability calls.
oauthNoOAuth config object, false to disable OAuth, or omitted to enable OAuth support.
enabledNoDisable without deleting config.
timeoutNoConnection 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
{
  "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

StatusMeaning
connectedClient connected and listTools succeeded.
disabledConfig entry has enabled: false or the server was disconnected.
failedConnection or initial tool-list failed. Error string is stored.
needs_authRemote server returned unauthorized and OAuth can continue.
needs_client_registrationRemote 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.

CapabilityService methodBehavior
ToolstoolsFetches tool lists from connected clients and converts each MCP tool into an AI SDK dynamic tool.
PromptspromptsLists prompts and names them as client:prompt after sanitizing names.
ResourcesresourcesLists resources and attaches client name to each resource record.
Prompt readgetPromptCalls the selected client's prompt with optional string args.
Resource readreadResourceReads a resource URI from the selected client.
Tool-list changedmcp.tools.changedPublished when a server sends ToolListChangedNotification.

API routes

MCP has both classic Hono routes and typed HttpApi handlers.

RouteBehavior
GET /mcpStatus map.
POST /mcpAdd a server config and attempt connection.
POST /mcp/:name/authStart OAuth and return authorization URL in typed API.
POST /mcp/:name/auth/callbackFinish OAuth with authorization code.
POST /mcp/:name/auth/authenticateRun full CLI/TUI OAuth flow where supported.
DELETE /mcp/:name/authRemove stored auth.
POST /mcp/:name/connectConnect or reconnect a server.
POST /mcp/:name/disconnectClose client and mark disabled.
POST /mcp/:name/togglePatch 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}'

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

SymptomLikely causeFix
needs_authRemote server requires OAuth and no valid token is stored.Run nikcli mcp auth <name>.
needs_client_registrationServer does not support dynamic client registration.Add oauth.clientId, and client secret if required.
Local server failedCommand 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 toolslistTools failed after connect.Check server logs and tool-list response.
Browser did not openAutomatic browser open failed.The CLI prints the auth URL through the mcp.browser.open.failed event path.

Source anchors

NeedFile
MCP servicepackages/nikcli/src/mcp/index.ts
MCP auth storagepackages/nikcli/src/mcp/auth.ts
OAuth provider and callbackpackages/nikcli/src/mcp/oauth-provider.ts, packages/nikcli/src/mcp/oauth-callback.ts
CLI commandpackages/nikcli/src/cli/cmd/mcp.ts
Classic routespackages/nikcli/src/server/httpapi/mcp.ts
Typed routespackages/nikcli/src/server/httpapi/mcp.ts
TUI dialogpackages/tui/src/component/dialog-mcp.tsx