You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit bbedff7
Browse filesBrowse the repository at this point in the historyBrowse files
description: "Drive a locally built server with a real client: the Inspector CLI (scripted), the Inspector web UI (by hand) and an LLM client. Use when smoke-testing a server change; when calling a tool, reading a resource or getting a prompt from the command line; when choosing a protocol era; or when the Inspector CLI will not connect to, or misreads, a server command."
3
+
description: "Drive a locally built server with a real client: the Inspector CLI (scripted), the Inspector web UI (through Playwright) and an LLM client. Use when smoke-testing a server change; when calling a tool, reading a resource or getting a prompt from the command line; when choosing a protocol era; or when the Inspector CLI will not connect to, or misreads, a server command."
4
4
disable-model-invocation: false
5
5
---
6
6
@@ -14,11 +14,11 @@ record is in `/pr-flow` (client evidence); building and starting the server is
14
14
15
15
Three clients, in the order to reach for them:
16
16
17
-
| Client | Driven by | Use it for |
18
-
| --- | --- | --- |
19
-
| Inspector **CLI**| A command. This is the **scripted path**, and the one an agent runs | One request, one JSON result: the evidence that goes in a PR |
20
-
| Inspector **web** UI | A person, by hand. Nothing in this repo automates a browser | What only a UI shows: notifications arriving, elicitation and sampling prompts, a long-running tool's progress |
21
-
| An **LLM client**| A prompt | Whether a model picks the tool and uses its result, which the PR checklist asks for |
| Inspector **CLI**| A command. This is the **scripted path**, and the one an agent runs | One request, one JSON result: the evidence that goes in a PR|
20
+
| Inspector **web** UI | A Playwright script in headless Chromium, which an agent writes and runs | What the CLI cannot do: elicitation and sampling round-trips, URL elicitation, tasks, notifications arriving, a long-running tool's progress |
21
+
| An **LLM client**| A prompt | Whether a model picks the tool and uses its result, which the PR checklist asks for|
22
22
23
23
Build first (`npm run build -w src/<server>`). Every command below runs the
24
24
last build of a TypeScript server, not your edit.
@@ -85,7 +85,7 @@ That rule produces the three failures people actually hit:
85
85
`--cli -e KEY=VALUE node …` leaves no server command at all, and the CLI
86
86
falls back to your personal catalog (`~/.mcp-inspector/mcp.json`). With
87
87
several servers in it that fails with `Multiple servers found in config
88
-
file. Please specify one with --server`. Either way it is no longer talking
88
+
file. Please specify one with --server`. Either way it is no longer talking
89
89
to your build, so move the option after the command.
90
90
-**`Method is required`** means the options ended up on the wrong side of a
`npx playwright install chromium`), and run the script from there. The
223
+
launcher inherits the script's working directory, so spawn it with `cwd` set
224
+
to the worktree root: the server commands above use paths relative to it, and
225
+
from the scratch directory no server would start.
226
+
227
+
### The recipe
228
+
229
+
-**Launch.** Spawn the launcher above with `MCP_AUTO_OPEN_ENABLED=false` in
230
+
its environment, or it opens a tab in your own browser as well. It prints a
231
+
tokenized URL (`http://127.0.0.1:6274?MCP_INSPECTOR_API_TOKEN=…`) on stdout;
232
+
read it from there and navigate to it. Start the launcher in its own process
233
+
group (`detached: true`) and kill the group when the script ends, so the
234
+
server it spawned goes with it.
235
+
-**Connect.** The connect control is a Mantine switch whose input is hidden:
236
+
`getByRole("switch", { name: /Connect or disconnect/ }).check({ force: true })`.
237
+
-**Pick a screen.** The Servers, Tools, Prompts and Resources tabs are radios
238
+
that cannot be clicked; click their label, `locator('label[for$="-Tools"]')`.
239
+
A tool is then a button named for its title and name:
240
+
`getByRole("button", { name: / echo$/ })`.
241
+
-**Fill and run.** A field is a textbox named for its property
242
+
(`getByRole("textbox", { name: /message/ })`). Run with the **Execute Tool**
243
+
button; it stays disabled until every required field is filled.
244
+
-**Selects.** A Mantine Select (an `enum` field, in a tool form or in an
245
+
elicitation) is a **read-only** textbox: `fill` does nothing. Click it, then
246
+
press `ArrowDown` and `Enter`, which picks the first option.
247
+
-**Read the result.** The panel's heading is **Results**, or **Tool Call
248
+
Failed**. A result with `isError: true` keeps the **Results** heading and
249
+
adds an alert named **Tool Error** holding the message, so check for that
250
+
alert rather than the heading. Which heading a failure gets varies by era:
251
+
rejecting a sampling request shows **Tool Call Failed** on 2026-07-28 and
252
+
**Results** plus **Tool Error** on 2025-11-25.
253
+
-**Elicitation.** A dialog named **Elicitation Request**, with **Cancel**,
254
+
**Decline** and **Submit**. Its question is the paragraph that opens with
255
+
`“`; the dialog's first `<p>` is its title.
256
+
-**Multi-step elicitation.** After **Submit**, wait for the question to change
257
+
or for the result heading, **never for the dialog to close**. Both eras
258
+
reuse the open dialog for the next step, so it never closes between steps,
259
+
and on the 2025 era it can read as hidden for a moment while the next
260
+
question renders, so a wait for it to close either hangs or returns early.
261
+
The URL error path's retry reuses the dialog the same way: tell its two
262
+
prompts apart by their **Request ID** line.
263
+
-**URL elicitation.** The dialog shows **Open in Browser**, and **I've
264
+
completed it** only after that has been clicked. The click opens a popup
265
+
page: catch it with `page.waitForEvent("popup")` around the click, close it,
266
+
then click **I've completed it**.
267
+
-**Sampling.** A dialog named **Sampling Request**: fill the **Response**
268
+
textbox and click **Send Response**, or click **Reject**.
269
+
-**Tasks.** On 2026-07-28 the Inspector follows the task handle itself: run
270
+
`simulate-research-query` and wait for **Results** like any other call.
271
+
-**Isolation.** Open a fresh page, and connect again, for each scenario. One
272
+
scenario's open dialog or dropped connection then cannot fail the next.
273
+
274
+
Era differences that change what to expect, beyond the tool list (see
Copy file name to clipboardExpand all lines: AGENTS.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -31,7 +31,7 @@ not in advance.
31
31
|[`local-dev`](.claude/skills/local-dev/SKILL.md)| Install, build and run each server from the checkout over the transports it implements; local `npx`/`uvx` and client-config runs; stale builds and fresh worktrees; the `overrides`, lockstep and `uv.lock` procedures | Model-invoked, or `/local-dev`|
32
32
|[`testing`](.claude/skills/testing/SKILL.md)| The in-process protocol-level harness, test placement, the commands per suite, `test` versus `coverage`, and clearing the per-file coverage gate | Model-invoked, or `/testing`|
33
33
|[`release`](.claude/skills/release/SKILL.md)| A milestone release end to end: the release issue, the preparation PRs on `v2/main` (audit, Version Packages, Python CalVer), the pure `v2/main` → `main` merge PR, the release ledger, and what a maintainer publishes |**Name-only**: `/release`|
34
-
|[`client-smoke`](.claude/skills/client-smoke/SKILL.md)| Driving a built server with the Inspector CLI (the scripted path), the Inspector web UI (by hand) and an LLM client; the CLI's argument split and exit codes; protocol eras and what can be exercised today | Model-invoked, or `/client-smoke`|
34
+
|[`client-smoke`](.claude/skills/client-smoke/SKILL.md)| Driving a built server with the Inspector CLI (the scripted path), the Inspector web UI (through Playwright) and an LLM client; the CLI's argument split and exit codes; protocol eras and what can be exercised today | Model-invoked, or `/client-smoke`|
35
35
36
36
A PR that adds a skill under `.claude/skills/<name>/SKILL.md` adds its row to
37
37
this table in the same change, and the table never lists a skill that does not
0 commit comments