feat: add --protocol-era launch flag for ad-hoc servers (#2208)

An ad-hoc --server-url / command launch always negotiated the legacy era,
because protocolEra was only settable per server in mcp.json. A wrapper
that mints a short-lived bearer token therefore had to write that token to
disk to exercise a server under auto or modern.

--protocol-era <legacy|auto|modern> now feeds settings.protocolEra in all
three clients through a shared parseProtocolEra coercer:

- CLI/TUI overlay it in loadServerEntries alongside --header, onto an
  ad-hoc target and onto a --catalog/--config entry for that run.
- Web stamps it on the in-memory ad-hoc entry, which the backend lifts
  into settings like headers; as with --header it is rejected alongside
  --catalog/--config, but unlike --header it applies to stdio too.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SZ4rrvH6xaCfrst75gJh7x
Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
cliffhall 2026-09-14 00:11:56 -04:00
commit 55db703196
2 changed files with 324 additions and 30 deletions

View file

@ -29,7 +29,7 @@ npx @modelcontextprotocol/inspector --tui --config mcp.json # read-only sessi
### 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](../../docs/mcp-server-configuration.md): `--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.
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](../../docs/mcp-server-configuration.md): `--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`, `--protocol-era` (`legacy`/`auto`/`modern`; sets the era an ad-hoc server negotiates, or overrides a file's `protocolEra`), `--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)

View file

@ -5,7 +5,9 @@ import { render } from "ink";
import {
parseKeyValuePair,
parseHeaderPair,
parseProtocolEra,
} from "@inspector/core/mcp/node/index.js";
import type { ServerProtocolEra } from "@inspector/core/mcp/types.js";
import { loadRunnerClientConfig } from "@inspector/core/client/runner.js";
import {
parseRunnerOAuthCallbackUrl,
@ -41,6 +43,11 @@ export async function runTui(args?: string[]): Promise<void> {
parseHeaderPair,
{},
)
.option(
"--protocol-era <era>",
"Protocol era to negotiate: legacy, auto, or modern (overrides the file's protocolEra; default legacy)",
parseProtocolEra,
)
.option(
"--client-id <id>",
"OAuth client ID (static client) for HTTP servers",
@ -78,6 +85,7 @@ export async function runTui(args?: string[]): Promise<void> {
e?: Record<string, string>;
cwd?: string;
header?: Record<string, string>;
protocolEra?: ServerProtocolEra;
clientId?: string;
clientSecret?: string;
clientMetadataUrl?: string;
@ -95,6 +103,7 @@ export async function runTui(args?: string[]): Promise<void> {
cwd: options.cwd?.trim() || undefined,
env: options.e,
headers: options.header,
protocolEra: options.protocolEra,
transport: options.transport,
serverUrl: options.serverUrl?.trim() || undefined,
};