inspector/clients/tui
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Cliff Hall 73fe059072
Some checks failed
Run install, format, lint, build, and test on every push / build (push) Has been cancelled
Run install, format, lint, build, and test on every push / publish (push) Has been cancelled
Run install, format, lint, build, and test on every push / publish-github-container-registry (push) Has been cancelled
fix(deps): raise vite to 8.1.5 to close three dev-server file-read advisories; 2.0.0-rc.3 (#1841)
The #1837 sweep moved vite to 8.0.16 in the root and tui manifests but left
`clients/web` pinned at **8.0.0** — `npm update` reported "up to date" and only
an explicit install would move it. That left five open advisories, three high:

  GHSA-fx2h-pf6j-xcff  high    `server.fs.deny` bypass via Windows ADS
  GHSA-v2wj-q39q-566r  high    `server.fs.deny` bypassed with queries
  GHSA-p9ff-h696-f583  high    arbitrary file read via the dev server
  GHSA-v6wh-96g9-6wx3  medium  launch-editor NTLMv2 hash disclosure
  GHSA-4w7w-66w2-5vf9  medium  path traversal in optimized deps

These are worth fixing rather than dismissing as "dev-only". Unlike the other
remaining dev-scope alerts, `server.fs.deny` bypass is *remotely triggerable*: a
malicious page can read arbitrary files from anyone running `npm run dev`.
Published-package users are unaffected — they get the built `dist` and never
run vite — but contributors are.

Also raises the declared floor to `^8.1.5` in all three manifests that declare
vite. The root previously declared `^8.0.0`, which still *permitted* the
vulnerable 8.0.0 on a fresh resolve, so pinning the lockfile alone would have
left a regression path open.

Bumped to rc.3 rather than folding this into 2.0.0: vite builds the shipped
bundle, so changing it changes the artifact, and the tree that ships should be
the tree that was validated against the live registry. rc.2 validated a
different tree.

`npm run ci` passes — full chain including the coverage gate, build gate,
smokes, and 462 Storybook tests.


Claude-Session: https://claude.ai/code/session_01Txmv2qqv3yeKgRzoqXytzD

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 02:43:48 -04:00
..
__tests__ test(cli,tui): typecheck the __tests__ dirs (#1791) (#1799) 2026-07-27 12:05:35 -04:00
src fix(core): register peer-request handlers before connect (#1797) (#1798) 2026-07-27 11:32:23 -04:00
dev.ts feat: port CLI, TUI, and launcher from v1.5 into v2 (#1452) 2026-06-14 20:27:49 -04:00
eslint.config.js chore: close a batch of quality-gate & tidy gaps (#1785 #1787 #1789 #1790 #1767) (#1792) 2026-07-26 10:43:11 -04:00
index.ts feat(web): enforce localhost-only binding; expand loopback origin allow-list (#1796) 2026-07-26 22:15:10 -04:00
package-lock.json fix(deps): raise vite to 8.1.5 to close three dev-server file-read advisories; 2.0.0-rc.3 (#1841) 2026-07-28 02:43:48 -04:00
package.json fix(deps): raise vite to 8.1.5 to close three dev-server file-read advisories; 2.0.0-rc.3 (#1841) 2026-07-28 02:43:48 -04:00
README.md docs: restore the missing docs/ targets and split the catalog-seeding wording (#1811) (#1812) 2026-07-27 20:37:14 -04:00
test-config.json feat: port CLI, TUI, and launcher from v1.5 into v2 (#1452) 2026-06-14 20:27:49 -04:00
tsconfig.json test(cli,tui): typecheck the __tests__ dirs (#1791) (#1799) 2026-07-27 12:05:35 -04:00
tsconfig.test.json test(cli,tui): typecheck the __tests__ dirs (#1791) (#1799) 2026-07-27 12:05:35 -04:00
tsup.config.ts chore: close a batch of quality-gate & tidy gaps (#1785 #1787 #1789 #1790 #1767) (#1792) 2026-07-26 10:43:11 -04:00
tui.tsx feat(web): enforce localhost-only binding; expand loopback origin allow-list (#1796) 2026-07-26 22:15:10 -04:00
vitest.config.ts test(tui): extend coverage gate to Ink components + App.tsx (closes #1501) (#1538) 2026-06-29 08:19:12 -04:00

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.

MCP Inspector TUI Screenshot

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 empty 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 empty 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). Must bind a loopback host (localhost / 127.0.0.0/8 / [::1]); a non-loopback host hard-errors, since the listener receives the authorization code over plaintext http.

Authenticating in the TUI

  1. Select an HTTP/SSE server and press C to connect.
  2. If authorization is required, the TUI starts OAuth automatically (browser opens for sign-in).
  3. After the callback completes, connect finishes without a second C.
  4. 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.
  • Protocol: View JSON-RPC request/response/notification history (matches the web Protocol monitor).
  • Network: View HTTP fetch traffic for SSE / Streamable HTTP servers (matches the web Network monitor).
  • Console: View stdio stderr from the connected server process (matches the web Console monitor).

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+C to 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.