MCP, plugins, and hooks
This page maps the MCP, plugin, and hook surfaces in the extracted cli.js.
Use Hooks and events reference for the canonical hook/frame/method list and Tool inventory and schemas for MCP/plugin tool schema ownership. This page owns MCP/plugin runtime wiring.
Source anchors
| Semantic alias | Source | Approximate location | String or symbol | Meaning |
|---|---|---|---|---|
| McpCommandRegistrar | cli.js | line ~9173, byte 0xbf3c40 | function rR4(H) | Registers the mcp command family. |
| McpServeCommand | cli.js | line ~9173, byte 0xbf3ccb | command("serve") | Starts the Claude Code MCP server. |
| McpListCommand | cli.js | line ~9173, byte 0xbf3fba | command("list") | Lists configured MCP servers. |
| McpDesktopImportCommand | cli.js | line ~9173, byte 0xbf44e2 | command("add-from-claude-desktop") | Imports MCP servers from Claude Desktop. |
| McpProjectChoiceReset | cli.js | line ~9173, byte 0xbf461e | reset-project-choices | Resets approved/rejected project-scoped MCP choices. |
| McpNonblockingGate | cli.js | line ~19294, byte 0xd91824 | MCP_CONNECTION_NONBLOCKING | Runtime MCP connection non-blocking gate. |
| McpToolTimeout | cli.js | line ~4980, byte 0x937240 | MCP_TIMEOUT | MCP tool timeout environment variable. |
| McpConfigFlag | cli.js | line ~19525, byte 0xdc0b90 | --mcp-config <configs...> | Loads MCP config from JSON files or strings. |
| StrictMcpConfigFlag | cli.js | line ~19525, byte 0xdc1e70 | --strict-mcp-config | Ignores non-flag MCP configurations. |
| PluginCommandRegistrar | cli.js | line ~9297, byte 0xbfca96 | function fC4(H) | Registers plugin / plugins command family. |
| PluginTuiManager | cli.js | line ~7184, byte 0xb06c21 | description:"Manage Claude Code plugins" | In-session slash/TUI plugin management surface. |
| PluginMarketplaceCommand | cli.js | line ~9297, byte 0xbfd24d | Manage Claude Code marketplaces | CLI marketplace subcommand root. |
| PluginMarketplaceAddCommand | cli.js | line ~9297, byte 0xbfd2ab | Add a marketplace from a URL, path, or GitHub repo | Marketplace add command and source ingestion surface. |
| EnabledPluginsSetting | cli.js | line ~185, byte 0x11b66d | enabledPlugins | Settings key storing enabled plugin IDs and version constraints. |
| ExtraMarketplacesSetting | cli.js | line ~185, byte 0x11b871 | extraKnownMarketplaces | Settings key registering repository/team marketplaces. |
| StrictMarketplacePolicy | cli.js | line ~185, byte 0x113422 | strictKnownMarketplaces | Managed allowlist for marketplace sources. |
| BlockedMarketplacePolicy | cli.js | line ~185, byte 0x113479 | blockedMarketplaces | Managed blocklist for marketplace sources. |
| DependencyMarketplacePolicyBlock | cli.js | line ~1291, byte 0x4dad4d | dependency-marketplace-blocked-by-policy | Plugin dependency install can be blocked by marketplace policy. |
| PluginInstallTelemetry | cli.js | line ~1291, byte 0x4dbe08 | plugin_installed | Plugin install telemetry after dependency resolution and settings write. |
| PluginUninstallTelemetry | cli.js | line ~9173, byte 0xbf4ad9 | tengu_plugin_uninstalled_cli | CLI uninstall telemetry and orphan-scan follow-up. |
| PluginDisableTelemetry | cli.js | line ~9180, byte 0xbf52ce | tengu_plugin_disabled_cli | CLI disable telemetry. |
| PluginUpdateTelemetry | cli.js | line ~9182, byte 0xbf54de | tengu_plugin_updated_cli | CLI update telemetry after version check. |
| HookEventSchema | cli.js | line ~185, byte 0x10b6b4 | PreToolUse, PostToolUse, SessionStart, SessionEnd | Hook event schema. |
MCP runtime map
flowchart TD Flags[--mcp-config / --strict-mcp-config] --> Config[MCP config set] Settings[settings / project / managed policy] --> Config Plugins[plugin-provided MCP] --> Config Config --> Coordinator[MCP runtime coordinator] Coordinator --> Always[alwaysLoad servers] Coordinator --> Deferred[non-alwaysLoad servers] Coordinator --> ClaudeAi[claude.ai connectors] Coordinator --> Tools[MCP tools/resources/prompts]McpRuntimeCoordinator splits regular configs into always-load and non-always-load groups, honors MCP_CONNECTION_NONBLOCKING, connects regular and claude.ai connector configs, and deduplicates overlapping plugin/connector surfaces.
MCP command surface
| Subcommand | Runtime role |
|---|---|
serve | Starts Claude Code’s MCP server. |
list | Lists configured MCP servers; help text warns that stdio servers can be spawned for health checks. |
add, remove, get, add-json | Present in the command family by surrounding command registration, though individual anchors are less stable than McpCommandRegistrar. |
add-from-claude-desktop | Imports MCP servers from Claude Desktop on supported platforms. |
reset-project-choices | Clears project-scoped approve/reject choices for .mcp.json servers. |
Plugin surfaces
PluginCommandRegistrar registers plugin / plugins. High-signal plugin strings show:
- session-only plugins through
--plugin-dirand--plugin-url; - marketplace concepts and reserved marketplace names;
- plugin-provided
agents,skills,hooks,mcpServers, andoutputStylesschema surfaces; - plugin autoupdate guarded by updater state.
Plugin marketplace lifecycle
The plugin path has two user-facing entry surfaces: an in-session slash/TUI plugin menu and the CLI plugin / plugins command family. The CLI tree contains a marketplace root with add/list/update/remove-style wording, while settings and policy carry the durable state.
flowchart TD Source[Marketplace source: URL / path / GitHub repo / settings] --> Register[extraKnownMarketplaces] Policy[strictKnownMarketplaces / blockedMarketplaces] --> Register Register --> Catalog[Known marketplace catalog] Catalog --> Install[Install plugin + dependencies] Install --> Enabled[enabledPlugins setting] Enabled --> Runtime[hooks / MCP / skills / agents / output styles] Runtime --> Reload[plugin-affecting settings reload]| Stage | Source-visible evidence | Runtime implication |
|---|---|---|
| Register marketplace | marketplace add <source>, extraKnownMarketplaces, sparse checkout and scope options | Marketplaces can be declared from CLI or settings and scoped to user/project/local contexts. |
| Apply policy | strictKnownMarketplaces, blockedMarketplaces, dependency-marketplace-blocked-by-policy | Managed policy can allowlist or block sources before plugin/dependency installation completes. |
| Install plugin | plugin_installed, dependency closure handling, enabledPlugins writes | Install resolves dependency closure, writes enabled plugin state, and emits plugin/marketplace telemetry. |
| Update plugin | tengu_plugin_updated_cli, autoUpdate settings | Updates can be triggered from CLI and may be gated by marketplace auto-update configuration. |
| Disable or uninstall | tengu_plugin_disabled_cli, tengu_plugin_uninstalled_cli | Disable changes enabled state; uninstall can also run orphan scans/pruning. |
| Runtime contribution | plugin hooks, mcpServers, skills, agents, outputStyles | Enabled plugins become capability injectors, but still flow through settings, hooks, MCP, and permission boundaries. |
This narrows the previous marketplace gap from “command surfaces only” to a lifecycle model: source registration, policy filtering, dependency resolution, enabled-state writes, update/disable/uninstall operations, and runtime capability reloads. The remaining gap is exact per-command UI flow and every option branch inside the lazy-loaded marketplace handlers.
Hook events
The hook schema includes these high-signal lifecycle events:
| Hook family | Examples |
|---|---|
| Tool lifecycle | PreToolUse, PostToolUse, PostToolUseFailure, PostToolBatch |
| Prompt/session lifecycle | UserPromptSubmit, UserPromptExpansion, SessionStart, SessionEnd |
| Stop/compaction | Stop, StopFailure, PreCompact, PostCompact |
| Agent/task lifecycle | SubagentStart, SubagentStop, TaskCreated, TaskCompleted |
| Permission/config/worktree | PermissionRequest, PermissionDenied, ConfigChange, WorktreeCreate, WorktreeRemove |
Security interpretation
MCP and plugins extend model-visible capabilities, but they do not bypass the rest of the runtime. The same command surface also exposes strict config, project-choice reset, hook validation, timeouts, and permission-prompt routing, which indicates that external capabilities are integrated through guarded runtime boundaries.
MCP runtime internals
This section separates MCP command management from runtime MCP connection and event handling.
Additional anchors
| Semantic alias | Source | Approximate location | String or symbol | Meaning |
|---|---|---|---|---|
| McpRuntimeCoordinator | cli.js | line ~19294, byte 0xd917c8 | function fH9(H) | Runtime MCP connection coordinator. |
| RequiredMcpConfigSplit | cli.js | line ~19294, byte 0xd918a0 | alwaysLoad===!0 | Split between required and normal MCP configs. |
| RequiredMcpConnectLabel | cli.js | line ~19294, byte 0xd91940 | --mcp-config alwaysLoad servers | Required MCP config connect label. |
| ClaudeAiConnectorLabel | cli.js | line ~19294, byte 0xd919b0 | claude.ai connectors | Runtime connector connect label. |
| McpToolsListSchema | cli.js | line ~95, byte 0x907a4 | tools/list | MCP tools/list protocol schema. |
| McpResourceListSchemas | cli.js | line ~95, byte 0x8fe5c | resources/list, resources/templates/list | MCP resource listing schemas. |
| McpPromptSchemas | cli.js | line ~95, byte 0x9017a | prompts/list, prompts/get | MCP prompt listing/get schemas. |
| McpToolTimeoutEnv | cli.js | line ~4980, byte 0x937240 | MCP_TIMEOUT | MCP tool timeout env var, defaulting to 30000 ms. |
| McpConnectTimeoutEnv | cli.js | line ~4980, byte 0x9372a0 | MCP_CONNECT_TIMEOUT_MS | MCP connection timeout env var, defaulting to 5000 ms. |
| McpAuthErrorTelemetry | cli.js | line ~4983, byte 0x93fec6 | tengu_mcp_tool_call_auth_error | MCP tool-call auth-expiry telemetry/error path. |
| McpElicitationFrame | cli.js | line ~19349, byte 0xda6206 | elicitation_complete | MCP elicitation completion is bridged into headless frames. |
Runtime coordinator
The complete McpRuntimeCoordinator function is small enough to reconstruct:
- Receives
regularMcpConfigs,claudeaiConfigPromise, and state. - Computes a non-blocking flag from
MCP_CONNECTION_NONBLOCKINGor an explicitnonBlockingoption. - Stores the non-blocking state through
IV8(_). - Partitions regular MCP configs into
alwaysLoad === trueand all other configs. - Returned
connect()starts two parallel connection groups: regular configs viaBr6(...)and claude.ai connectors viakKA(...)afterclaudeaiConfigPromiseresolves. - Records startup markers
before_mcp_connect_user,before_mcp_connect_connector,after_mcp_connect_user,after_mcp_connect_connector.
flowchart TD Input[regularMcpConfigs + claudeaiConfigPromise] --> NonBlocking[MCP_CONNECTION_NONBLOCKING] Input --> Split[split alwaysLoad vs normal] Split --> Required[alwaysLoad servers] Split --> Normal[regular servers] Input --> Connectors[claude.ai connectors] Required --> Connect[connect() Promise.all] Normal --> Connect Connectors --> ConnectRequired versus non-required servers
The alwaysLoad split is important. Required servers are labeled --mcp-config alwaysLoad servers and normal servers as --mcp-config servers. Required servers are connected as a distinct group; normal servers can honor non-blocking/deferred behavior; claude.ai connectors are a separate promise-driven group. Because connect() awaits both groups, the final headless startup waits for the coordinator as a whole even when parts are internally non-blocking.
MCP protocol surfaces
| Protocol method | Role |
|---|---|
tools/list | Lists tools exposed by an MCP server. |
resources/list | Lists resources. |
resources/templates/list | Lists resource templates. |
prompts/list | Lists prompts. |
prompts/get | Retrieves a prompt by name/arguments. |
These schema anchors are paired with runtime anchors in McpRuntimeCoordinator, McpCommandRegistrar, HeadlessControlLoop, and MCP tool-call error handling, confirming MCP as both a command/config system and a runtime capability provider.
Timeout and auth-error mechanics
MCP_TIMEOUT→ tool-call timeout, falling back to30000ms.MCP_CONNECT_TIMEOUT_MS→ connection timeout, falling back to5000ms.
The MCP tool-call error path has a specific auth branch: on 401 or token-expiry-like errors, the runtime emits tengu_mcp_tool_call_auth_error and raises a user-facing error requiring re-authorization.
Elicitation and headless integration
MCP elicitation completion is visible in two places: the MCP client handles an elicitation completion notification and marks queued elicitation state as complete; HeadlessControlLoop emits system / elicitation_complete frames with mcp_server_name and elicitation_id. URL-mode elicitation is observable as a headless/SDK stream frame.
Command tree versus runtime connection
| Surface | Function | Role |
|---|---|---|
claude mcp ... | McpCommandRegistrar | Manage config and run the MCP server. |
| root action headless setup | McpRuntimeCoordinator | Connect runtime MCP servers/connectors for a session. |
| MCP protocol schemas | line ~95 schemas | Define method/result shapes. |
| Headless stream loop | HeadlessControlLoop | Emits MCP-related status, elicitation, auth, and tool-call state to headless consumers. |
Related docs
Created and maintained by Yingting Huang.