| Filename | Latest commit message | Latest commit date |
|---|---|---|
* Extensions: first-class advertised-extensions map (Phase 1 of #1633) Collapse the two ad-hoc `capabilities.extensions` spreads in the InspectorClient constructor (EMA, gated on enterpriseManaged; the modern Tasks extension, always-on) into a single builder that is the source of truth for what the client advertises. - core/mcp/extensions.ts: `ADVERTISABLE_EXTENSIONS` registry (id + label + default-on flag), the `EMA_EXTENSION_KEY` constant, and `buildClientExtensions()`. The registry is the shared list the Server Settings toggle UI (Phase 2, #1739) will drive; EMA stays a conditional built-in (auth-mode driven, not a free toggle). - InspectorClientOptions.advertisedExtensions: per-extension overrides (present key wins over the registry default) so a future UI can toggle advertised extensions as a debugging knob. - Behavior preserved: tasks defaults to advertised, so the map is non-empty and rides every modern request envelope; EMA advertised iff enterpriseManaged. The raw modern-task envelope re-stamp is left untouched (it fires only on the raw tasks channel, which requires the extension anyway). Tests: extensions.test.ts covers the registry and every builder branch (defaults, EMA on/off, override enable/disable, unknown key) at 100%. The tasks-era and EMA integration suites still assert the same wire advertisement. `advertisedExtensions` is plumbed but not yet wired to the form (that lands in Phase 2). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5 * Extensions: address Phase 1 review (EMA-override test + envelope comment) - extensions.test.ts: add an EMA-specific assertion that an override for EMA_EXTENSION_KEY cannot advertise it (auth-mode only) — documents intent and guards against EMA being added to ADVERTISABLE_EXTENSIONS by mistake. - inspectorClient.ts: rewrite the withModernTaskEnvelope tasks-stamp comment so it stays accurate once Phase 2 lets a user disable general tasks advertisement — the force-stamp is load-bearing (the raw tasks/* channel requires the extension), not a redundant re-add. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5 * TUI: de-flake step-up OAuth frame assertions (raise poll ceiling) The step-up authorize tests intermittently timed out on the final "Step-up authorization succeeded" frame. Root cause is a test-infra timing budget, not product code: waitForFrame/waitUntil polled only 25× (25ms tick ≈ 625ms), and the step-up flow adds an extra async OAuth-runner hop plus React commits that can exceed that under CI load with v8 coverage. Hoist the poll count into a named POLL_TRIES = 100 (~2.5s ceiling). A poll exits the instant its predicate is true, so a higher ceiling never slows a passing assertion — it only widens the margin for the slow path. Verified 5× green (3 plain + 2 under --coverage), including the previously-flaky step-up cases. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5 * TUI: prettier-format the wrapped waitForFrame signature The POLL_TRIES change pushed waitForFrame's signature past the print width; Prettier wraps it. (Root has no aggregate format script — format is per-client, so this was missed locally.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5 --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
| .. | ||
| __tests__ | ||
| src | ||
| dev.ts | ||
| eslint.config.js | ||
| index.ts | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| test-config.json | ||
| tsconfig.json | ||
| tsup.config.ts | ||
| tui.tsx | ||
| vitest.config.ts | ||
MCP Inspector TUI Client
The Terminal User Interface (TUI) client brings the interactive exploration capabilities of the Web Client directly to your terminal. It is built using Ink to provide a rich, React-like component experience in a command-line environment.
Running the TUI
You can run the TUI client via npx:
npx @modelcontextprotocol/inspector --tui node build/index.js
With Configuration Files
The TUI can load all servers from an MCP catalog/config file. With no source
flag it uses the default writable catalog ~/.mcp-inspector/mcp.json (seeded
empty if missing):
npx @modelcontextprotocol/inspector --tui --catalog mcp.json # writable catalog (seeded if missing)
npx @modelcontextprotocol/inspector --tui --config mcp.json # read-only session (errors if absent)
(It does not use --server; all servers in the file are available in the TUI.)
Options
MCP server (which server(s) to connect to)
Options that specify the MCP server(s) (catalog/config file, ad-hoc command/URL, env vars, headers) are shared by the Web, CLI, and TUI and are documented in MCP server configuration: --catalog (writable catalog, seeded if missing; default ~/.mcp-inspector/mcp.json or MCP_CATALOG_PATH), --config (read-only session, errors if absent), -e, --cwd, --header, --transport, --server-url, and the positional [target...]. --catalog and --config are mutually exclusive, and neither combines with an ad-hoc target.
TUI-specific (OAuth for HTTP servers)
The TUI supports OAuth for SSE and Streamable HTTP servers. Per-server OAuth fields in mcp.json (static client id/secret, scopes, enterprise-managed flag) are applied automatically when loaded from --catalog or --config. Install-wide settings (CIMD, enterprise IdP) come from ~/.mcp-inspector/storage/client.json — the same file the web Client Settings dialog writes. You can point at a different file with --client-config or MCP_CLIENT_CONFIG_PATH.
OAuth callback URL
The TUI starts a small loopback HTTP server to receive the authorization redirect after you sign in in the browser. Defaults:
| Surface | Default callback |
|---|---|
| Web | http://localhost:6274/oauth/callback (main app server) |
| TUI | http://127.0.0.1:6276/oauth/callback (dedicated runner port; avoids colliding with web on 6274) |
Why a fixed default port? Enterprise-managed auth (EMA), CIMD, and many static OAuth apps require pre-registered redirect URIs. A predictable default (http://127.0.0.1:6276/oauth/callback) lets you register once on the IdP and reuse it across TUI sessions. Dynamic registration (DCR) can use ephemeral ports instead — see below.
Trade-off: only one TUI OAuth flow at a time can listen on the default port. A second instance starting OAuth while another is in progress may fail with EADDRINUSE. Override the listener with --callback-url or MCP_OAUTH_CALLBACK_URL (e.g. a different fixed port per instance, or http://127.0.0.1:0/oauth/callback when the authorization server accepts dynamically registered redirect URIs).
OAuth redirect URIs must match exactly what you register on the authorization server — localhost and 127.0.0.1 are different URIs. Register the TUI default on your OAuth app / IdP when using pre-registered (static), CIMD, or enterprise-managed clients. Override the listener with --callback-url or MCP_OAUTH_CALLBACK_URL; use http://127.0.0.1:0/oauth/callback for an OS-assigned ephemeral port when the authorization server registers redirect URIs dynamically (DCR).
Flags
| Option | Env | Description |
|---|---|---|
--client-config <path> |
MCP_CLIENT_CONFIG_PATH |
Install-level client config (default: ~/.mcp-inspector/storage/client.json). |
--client-id <id> |
— | OAuth client ID (static client); overrides client.json. |
--client-secret <secret> |
— | OAuth client secret (confidential clients); overrides client.json. |
--client-metadata-url <url> |
— | Client ID Metadata Document URL (CIMD); overrides client.json. |
--callback-url <url> |
MCP_OAUTH_CALLBACK_URL |
OAuth redirect/callback listener (default: http://127.0.0.1:6276/oauth/callback). |
Authenticating in the TUI
- Select an HTTP/SSE server and press C to connect.
- If authorization is required, the TUI starts OAuth automatically (browser opens for sign-in).
- After the callback completes, connect finishes without a second C.
- Use the Auth tab to inspect OAuth state (same fields as web Connection Info) or Clear OAuth state (disconnects when connected).
See also EMA / enterprise-managed auth and OAuth smoke testing for staging servers and verification steps.
Features
The TUI provides terminal-native tabs and panes for interacting with your MCP server:
- Resources: Browse and read resources exposed by the server.
- Prompts: List and test prompts.
- Tools: View available tools and execute them with form-like inputs.
- History: View the request and response history of your interactions.
- Console: View the direct stdout/stderr and diagnostic logging of the connected server.
Navigation
- Use the Arrow Keys (Left/Right) or Tab to switch between the main tabs (Resources, Tools, Prompts, etc.).
- Use the Arrow Keys (Up/Down) to scroll through lists of items.
- Press Enter to select an item, execute a tool, or fetch a resource.
- Press Escape or
Ctrl+Cto exit the application.
Development
Like the other clients, the TUI self-validates from its own folder:
npm run validate # format:check && lint && build && test:coverage
npm test # run all tests
npm run test:coverage # run tests under the per-file coverage gate
The repo-root validate:tui just delegates here. eslint.config.js registers
react-hooks for the classic rules only (rules-of-hooks + exhaustive-deps); the
stricter react-hooks@7 rules are not enforced on the interim component surface
(#1501).
Tests live in __tests__/. The coverage gate currently covers the TUI's
non-React logic (server resolution, logger, tab metadata, and the utils/
form/URL helpers); the Ink components and App.tsx are an interim exclusion in
vitest.config.ts pending a renderer-based follow-up.
