Skip to content

feat(mcpi): experimental session CLI client (#1432) - #1783

Open
BobDickinson wants to merge 11 commits into
v2/mainfrom
v2/mcpi-client
Open

feat(mcpi): experimental session CLI client (#1432)#1783
BobDickinson wants to merge 11 commits into
v2/mainfrom
v2/mcpi-client

Conversation

@BobDickinson

@BobDickinson BobDickinson commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Closes #1432

Depends on #1782 (CLI improvements — handlers and shared helpers live there).

Summary

  • Add experimental clients/mcpi session CLI (connect once, many commands) with an implicit local Unix-socket daemon
  • Reuse clients/cli handlers / OAuth helpers via a temporary build-time @inspector/cli alias
  • Wire mcpi into monorepo validate / build / coverage / install-clients and document in AGENTS + specification/v2_cli_v2.md

Packaging

  • Not in the published @modelcontextprotocol/inspector tarball (files allowlist unchanged)
  • No root bin.mcpi — install via npm link from clients/mcpi for local use (see clients/mcpi/README.md)

Test plan

Made with Cursor

BobDickinson and others added 2 commits July 25, 2026 16:38
Add servers/list and servers/show, --relogin / --stored-auth-only, browser
OAuth navigation with OSC 8 links, and extract method handlers under
clients/cli/src/handlers. Tracks #1781.

Co-authored-by: Cursor <cursoragent@cursor.com>
Introduce clients/mcpi (session front-end + local daemon), wire it into
monorepo validate/build/coverage/install, and document the design. Not
shipped in the published inspector tarball. Closes #1432.

Co-authored-by: Cursor <cursoragent@cursor.com>
@BobDickinson BobDickinson added the v2 Issues and PRs for v2 label Jul 25, 2026
Base automatically changed from v2/cli-improvements to v2/main July 26, 2026 20:55
BobDickinson and others added 2 commits July 26, 2026 14:10
Take the merged #1782 CLI sources from v2/main; keep mcpi client wiring
in root validate/format/coverage; register mcpi in format-coverage verify.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@cliffhall cliffhall linked an issue Aug 17, 2026 that may be closed by this pull request
BobDickinson and others added 7 commits September 13, 2026 21:49
# Conflicts:
#	AGENTS.md
#	README.md
#	clients/launcher/package-lock.json
#	package.json
Two interface-drift breaks surfaced only at build/runtime (the git
merge itself was clean):

- clients/cli/handlers/method-types.ts dropped metaValueToString when
  _meta was widened to RequestMetadata (JsonValue, not string) in
  #1910. mcpi's stringifyMeta was flattening to strings for a type
  that no longer exists; pass the already-JSON metadata through
  directly instead.
- core/ gained proper-lockfile (auth/node/file-lock.ts) and yaml
  (mcp/skillFile.ts) as new dependencies. Both are bundled into mcpi's
  daemon via the noExternal @inspector/core reach-in, and both do a
  dynamic require() of a Node builtin in their CJS internals, which
  esbuild's ESM bundle output can't satisfy — the daemon threw on
  startup with 'Dynamic require of "process"/"path" is not
  supported' and every session-CLI test that needed a live daemon
  timed out waiting for it. Externalize both packages (already root
  dependencies, resolvable from node_modules at runtime).

Verified: npm run build:mcpi succeeds, npm run validate:mcpi (lint +
typecheck + 117 tests, coverage gate) passes clean.
Ad-hoc connect targets (bare URL/stdio, no catalog entry) had no way to
request auto/modern era negotiation - loadServerEntries/
headersToServerSettings never populate protocolEra, so an ad-hoc
connect always defaulted to legacy with no override, unlike a catalog
entry with a protocolEra field.

Add --era <legacy|auto|modern> to mcpi connect, applied via a new
withEraOverride() helper (mirrors the existing withConnectTimeout()
pattern) that overrides protocolEra on the resolved settings, or
synthesizes a bare-defaults settings object carrying just the override
when the target had none.
mcpi initialize never sent a live initialize request - it replayed
InspectorClient's cached connect-time state, which is populated the
same way regardless of era (legacy initialize response vs. modern
server/discover). The name was misleading, and it omitted the two
fields that do differ by era: protocolEra and (when probed)
supportedVersions.

Remove "initialize" from SESSION_RPC_METHODS (kept in
ONE_SHOT_METHODS - the one-shot CLI's --method initialize still
matches the literal wire method name on purpose). Add
mcpi sessions/show [session], combining daemon session bookkeeping
(name, serverIdentity, timestamps, isMru) with live connection state
(serverInfo, protocolVersion, protocolEra, capabilities, instructions,
supportedVersions). New daemon op sessions/show plus
SessionRegistry.sessionFor() backing both it and the existing
clientFor().

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CI (npm run validate) failed on verify:typecheck-coverage: mcpi had no
typecheck script wired into validate, unlike cli/tui/launcher. Fixing
that surfaced further gaps once mcpi's own toolchain was actually
exercised end-to-end:

- clients/mcpi: add typecheck/check scripts (validate -> check ->
  typecheck), tsconfig.test.json (mirrors cli's pattern), and the same
  compilerOptions overrides cli/tui use so core/'s
  noUncheckedIndexedAccess strictness doesn't spuriously fail here.
- clients/mcpi/package.json: bump @modelcontextprotocol/client, core,
  server, and server-legacy from a stale 2.0.0-beta.5 to 2.0.0 (real
  SDK version skew vs. the rest of the monorepo, caught by
  verify:dep-lockstep). Per AGENTS.md, the shared toolchain (eslint,
  vitest, typescript, etc.) is declared once at the repo root and in no
  client manifest, so drop mcpi's own copies of all of it instead of
  keeping them in sync by hand - matching cli/tui/launcher exactly, it
  now resolves the root copies via npm/Node's directory walk-up. Keep
  only what's genuinely client-specific: tsup (its bundler) and
  @types/express (needed transitively by the test-server barrel
  import, same reason cli has it). That transitive import also drags
  in a hoisted @types/node that drifts from root's, so pin it via
  overrides the same way clients/cli does.
- Fix real bugs typecheck caught: an unsound cast in format-session.ts,
  wrong-arity expectCliFailure() calls and an invalid
  AuthChallengeReason literal in two test files, and two throws missing
  an Error cause (preserve-caught-error) once the root's current eslint
  actually ran against this client for the first time.
- Register mcpi with the repo's cross-cutting guards that assumed a
  fixed client list: verify-test-timeouts.mjs (CONFIG_ROOTS /
  EXPECTED_PROJECTS plus its own test fixtures), verify-bundle-
  externals.mjs (BUNDLED_CLIENTS, since mcpi ships a tsup bundle),
  workflow-gate.test.mjs (local:validate must reach mcpi the same way
  it reaches its siblings), and root package.json's local:validate
  script.

Verified: npm run validate passes clean end-to-end (guards, core, and
all six clients).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…d them

The previous commit fixed verify:typecheck-coverage, which unblocked two
CI jobs that had never run to completion on this branch before: the
per-file branch-coverage gate and the externalized-dependency check.

Coverage (clients/mcpi, >=90% branches per file):
- server.ts, format-human.ts, and mcp.ts had branch coverage below the
  90% gate. The gaps traced to two features added this session that had
  thin or subprocess-only test coverage: sessions/show's enrichment
  fields (era, serverInfo, capabilities, supportedVersions, instructions)
  and the --era flag (previously untested at all).
- Added in-process tests (server.handle()/callDaemon() against a daemon
  constructed directly in the test file) instead of runMcp() subprocess
  calls, since subprocess code isn't visible to coverage instrumentation.
  Covers sessions/show's absent-field fallback paths and full success
  path, the --era auto/invalid-value paths, and the mcp.ts positional
  sessionArg fallback for sessions/show.

Build gate (verify:bundle-externals):
- mcpi's tsup entry is named mcp-bin.js (multi-entry config), not
  index.js like web/cli/tui, so the script's hardcoded index.js
  existence check reported "build/index.js is missing" for mcpi even
  after a real build. Added a per-client `entry` override (defaults to
  index.js) so mcpi's real entry file is checked.
- Once buildable, the scan found @modelcontextprotocol/ext-apps (a root
  runtime dependency reachable through cli's noExternal reach-in) had
  been inlined into mcpi's bundle instead of staying external. cli and
  tui already list it as external; added the same entry to mcpi's tsup
  config.

npm run validate and npm run coverage both pass cleanly at the repo
root after these changes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v2 Issues and PRs for v2

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Inspector mcpi client

2 participants