SkillAgentSearch skills...

inspector

Visual testing tool for MCP servers

Install / Use

claude mcp add modelcontextprotocol -- npx -y github:modelcontextprotocol/inspector

If the server publishes to npm under a different name, use that package instead — check the repo README.

About this skill
🔌

MCP Server

Model Context Protocol server

Quality Score

90/100

Supported Platforms

Claude Code
Claude Desktop

MCP Inspector

A developer tool for inspecting Model Context Protocol (MCP) servers. It ships as a single package, @modelcontextprotocol/inspector, that provides three ways to inspect a server:

  • Web — a Vite + React + Mantine single-page app with a Node backend.
  • CLI — a scriptable command-line client for automation, CI, and fast agent feedback loops.
  • TUI — an interactive terminal UI built with Ink.

All three run through one global mcp-inspector binary:

npx @modelcontextprotocol/inspector          # web UI (default)
npx @modelcontextprotocol/inspector --cli    # CLI
npx @modelcontextprotocol/inspector --tui    # TUI

Repo status. This is the v2 line of the Inspector. Active development happens on v2/main (the develop branch — all v2 PRs target it), which is merged into main at milestone releases; main is the default branch and holds the latest released v2, published to the npm latest tag. The legacy v1 line lives on v1/main — security fixes only, published straight from that branch to the npm v1-latest tag (npx @modelcontextprotocol/inspector@v1-latest). See AGENTS.md for branch/board conventions.

Project layout

v2 is not an npm workspace. Each client under clients/* keeps its own package.json and node_modules; shared code lives in core/ and is consumed via a @inspector/core build-time alias (no package.json of its own). A single npm install at the root cascades installs into every client (see Setup).

inspector/
├── clients/
│   ├── web/          # Web client (Vite + React + Mantine). src/ = browser app; server/ = Node dev/prod backend
│   ├── cli/          # CLI client (tsup bundle, @inspector/core alias)
│   ├── tui/          # TUI client (Ink + React, tsup bundle)
│   └── launcher/     # Shared launcher — provides the `mcp-inspector` bin, dispatches to web/cli/tui
├── core/             # Shared code consumed via the `@inspector/core` alias (no package.json)
│   ├── auth/         # OAuth: providers, discovery, storage, mid-session recovery (browser/node/remote backends)
│   ├── client/       # Install-level client config (`client.json`): browser-safe parse/validate + Node load/save, remote backend, secrets
│   ├── json/         # JSON + parameter/argument conversion utilities
│   ├── logging/      # Silent pino logger singleton
│   ├── mcp/          # InspectorClient runtime, state stores, transports, config import
│   ├── node/         # Node-only shared helpers: version reader, hostUrl (host normalize/canonicalize + all-interfaces/loopback detection)
│   ├── react/        # React hooks over the state stores
│   └── storage/      # File I/O helpers for the OAuth persist backends
├── test-servers/     # Composable MCP test servers + fixtures used by integration tests
├── scripts/          # Root build/verify tooling (install cascade, smokes, verify-build-gate, verify-format-coverage, pack:verify)
├── docs/             # Task-oriented guides (server configuration, MCP App review, launcher/config plan)
├── specification/    # Design/build specifications
├── AGENTS.md         # Contribution rules for agents AND humans (see below)
└── README.md         # You are here

Each client has its own README with client-specific detail: web · cli · tui · launcher.

Task-oriented guides live under docs/:

  • MCP server configuration — which server(s) the Inspector connects to: --catalog vs. --config, ad-hoc targets, the -- separator, the file format and its Inspector-specific per-server fields. Shared by all three clients; the cli and tui READMEs delegate their server-options sections to it.
  • Reviewing an MCP App — the CLI-first → one-shot-web recipe for automated App-tool review: --app-info probe → deep-link navigate → rendered widget, plus OAuth handoff and proxy support.
  • Launcher and config consolidation — why the launcher runs a client in-process rather than spawning it, and how the shared config processor fits in.

Setup

Requires Node >=22.19.0.

npm install     # root install; postinstall cascades into every client
  • Fresh clone: run npm install at the repo root.
  • After a pull that changes a client's dependencies: re-run npm install at the root to re-sync every client.

The cascade (scripts/install-clients.mjs) is dev-only — it exits early when the package is installed as a dependency, and the published tarball ships only each client's build/, so end users are unaffected. Set INSPECTOR_SKIP_CLIENT_INSTALL=1 to skip it.

Running during development

For day-to-day web iteration, run Vite directly from the web client (fast HMR, no launcher build needed):

cd clients/web && npm run dev

The launcher-driven scripts below run the built launcher, so build first (npm run build):

npm run web        # prod web launcher against clients/web/dist
npm run web:dev    # web launcher in --dev mode (Vite)

The @inspector/core shared package

Shared code architecture: the four clients over the @inspector/core shared package

core/ holds the logic shared by all three clients so that web, CLI, and TUI behave identically. Its entry point is the InspectorClient class (core/mcp/), which owns the connection to an MCP server, the request/response lifecycle, and a set of state stores; core/react/ exposes React hooks over those stores that both the web and TUI (Ink) React trees consume. OAuth (core/auth/) is factored into isomorphic logic plus browser/node/remote backends so the same flows work in the browser, in Node, and against a remote backend.

core/ intentionally has no package.json — it is not published on its own. Each client bundles it in via a @inspector/core alias:

  • CLI / TUI: esbuildOptions.alias in their tsup.config.ts maps @inspector/core → the repo core/ directory, and noExternal: [/^@inspector\/core/] inlines it into the bundle.
  • Web: the same alias in clients/web/vite.config.ts for the browser app and the Node backend runner.

Publishing core/ as its own package (e.g. for third parties to build on) is deliberately deferred — see issue #1636.

Web client: "dumb components" + Storybook

The v2 web client is built from presentational ("dumb") components — they accept data and callbacks as props and contain only display logic, with no direct data fetching or client state. State comes from the @inspector/core hooks, wired in near the top of the tree. This keeps components isolated, testable, and documentable.

That approach is what makes Storybook first-class here: every screen and element component has a *.stories.tsx file (96+ stories) that renders it against fixture props. Storybook play functions double as interaction tests, run headless in CI (npm run ci:storybook, Chromium via Playwright).

Styling follows a strict Mantine-first convention (theme variants and component props over CSS classes, --inspector-* CSS custom properties over raw color literals). The full rules live in AGENTS.md under React instructions — read them before touching web UI. Element components live in clients/web/src/components/elements/; theme variants in clients/web/src/theme/.

Test servers

test-servers/ provides composable MCP servers used by the integration and smoke suites, so tests exercise a real server over a real transport instead of mocks. A server is assembled from presets (fixture factories in test-servers/src/preset-registry.ts — tools, resources, prompts, tasks, elicitation, sampling, OAuth, …) and can be driven two ways:

  • In-process — import the factories (createTestServerHttp, createEchoTool, …) and run the server inside the test's event loop (used by the HTTP integration paths).
  • As a subprocesstest-servers/build/test-server-stdio.js is spawned as a real stdio child (used by the CLI smoke and stdio integration tests).

Configure a server declaratively with a JSON config (see test-servers/configs/*.json) selecting presets, then load it via --config. Because the servers are spawned as real subprocesses, the build output must exist first:

npm run test-servers:build   # (from clients/web) → tsc -p test-servers, emits test-servers/build/

The Vite alias @modelcontextprotocol/inspector-test-server (in clients/web/vite.config.ts) points at test-servers/build/index.js so getTestMcpServerPath() resolves to a real .js path.

Serving the modern protocol era

A streamable-HTTP server can also serve the modern (2026-07-28) protocol era via the SDK's createMcpHandler:

  • Set transport.modern in the JSON config — true for dual-era stateless serving, or { "legacy": "reject" } for modern-only strict.
  • Or pass modern on the ServerConfig for an in-process createTestServerHttp.

This is what lets an Inspector connection negotiating protocolEra: "auto" | "modern" reach the modern leg (populated server/discover, sessionless). See test-servers/configs/modern-http.json.

Showcase configs

Each config below is a ready-made server for exercising one feature by hand. Load one with --config, and unless noted, connect with Protocol Era = Modern.

| Config | Demonstrates | Issue | | ----------------------------------------- | -------------------------------------------------- | ---------------------------------------------------------------------- | | modern-mrtr-http.json | A single MRTR round-trip | — | | mrtr-showcase-http.json | Every MRTR preset in one server | — | | modern-network-http.json | Network tab: Mcp-* headers + error taxonomy | #1628 | | xmcpheader-modern-http.json | Tools tab: x-mcp-header mirroring and exclusions | #1632 | | pagination-http.json | Page-by-page list fetching | #1721 | | advertised-extensions-http.json | Tool registration gated on advertised extensions | #1739 | | logging-{legacy,modern}-http.json | Logging, both eras | #1629 | | subscriptions-{legacy,modern}-http.json | Resource subscriptions, both eras | #1630 | | tasks-{legacy,modern}-http.json | Tasks, both eras | #1631 |

MRTR

modern-mrtr-http.json serves the mrtr_confirm tool (preset mrtr_confirm, createMrtrTool) over the modern leg. Its handler returns inputRequired(...) embedding a form elicitation, so invoking it produces a real round-trip: input_required → the client fulfils the embedded elicitation and retries with a new id → complete.

The Inspector drives M

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars10.9k
CategoryDevelopment
Updated2d ago
Forks1.5k

Languages

TypeScript

Security Score

83/100

Audited on Sep 19, 2026

1 medium1 low