CLI Client
Purpose and Scope
The CLI client example is the repository’s reference MCP host: an interactive chat program that connects an LLM provider to one or more MCP servers without shipping any built-in tools of its own. That design is intentional. The host’s useful abilities come from connected servers, so the example demonstrates how a real client application discovers tools, resources, prompts, roots, sampling, elicitation, and protocol-era behavior through MCP instead of hardcoding application actions. Use this page when you want to run the example, inspect the host wiring, or copy a minimal but complete host architecture into another TypeScript application.
Sources: examples/cli-client/README.md, examples/cli-client/cli.ts
The standard demonstration pairs this host with the sibling todos server, but the CLI is not limited to that server. It can connect to a single URL, to a command line target over stdio, or to an MCP server configuration file shaped like common host configuration. The example therefore serves two audiences at once: humans can use the REPL to explore MCP behavior interactively, while implementers can read the code as a reference for provider selection, transport setup, user prompts, roots, OAuth callback configuration, and clean shutdown.
Sources: examples/cli-client/README.md, examples/cli-client/cli.ts, examples/cli-client/server.ts
Relevant Source Files
- examples/cli-client/README.md — User-facing guide for the reference host, including quick start commands, provider selection, the todos-server pairing, protocol-era status output, and the guided feature tour.
- examples/cli-client/cli.ts — Interactive command entry point; parses CLI flags, chooses the LLM provider, creates the readline UI, and wires the host loop for human use.
- examples/cli-client/client.ts — CI and scripted entry point; runs the canned conversation against todos-server, verifies behavior, and closes the host after exercising supported transports and eras.
- examples/cli-client/server.ts — Runner shim used by the example framework; delegates the server side of the story to the sibling todos-server package.
- examples/README.md — Repository-level examples guide; explains the story convention, generic client and server commands, supported transports, legacy handshake flag, and the special entry points for cli-client and todos-server.
Core Primitives
The example is organized around a few reusable host primitives rather than one large script. The command entry creates a user interface with readline and tab completion, then fills a host reference lazily so completion can use the host’s cached server lists after connection. A provider object hides vendor-specific LLM details behind a small interface, allowing the same MCP host loop to work with Anthropic, OpenAI, Gemini, or the keyless scripted provider. The host object receives the provider, UI, roots, and legacy option, then owns the MCP connections described by command-line targets or configuration.
Sources: examples/cli-client/cli.ts, examples/cli-client/client.ts
Those primitives mirror the split a production host usually needs. The provider turns chat turns and tool metadata into model calls. The host maintains MCP server connections and cached capabilities. The UI mediates confirmations, forms, and human input. The session loop reads user messages and delegates each turn to host-aware logic. The scripted entry point uses the same shape with a deterministic UI and provider, proving that the interactive behavior is not special-cased for terminals. That makes the example useful both as a demo and as a testable reference implementation.
Sources: examples/cli-client/client.ts, examples/cli-client/README.md
Running the Reference Host
For the fastest local run, start the CLI client from the repository root after installing and building the workspace. With no provider key, it uses the scripted provider and spawns the sibling todos server over stdio. This mode is enough to watch the host connect, negotiate capabilities, and execute a known conversation without depending on an external model service. It is also the safest first run when validating a local checkout, because the README describes the scripted provider as the keyless default and the same provider is used by CI.
pnpm install && pnpm build:all
pnpm --filter @mcp-examples/cli-client startSources: examples/cli-client/README.md, examples/cli-client/client.ts
For a real model-backed conversation, provide an API key and choose a provider explicitly, or let the CLI auto-pick from the environment. Provider resolution checks Anthropic credentials first, then OpenAI, then Gemini, and falls back to scripted when no key is present. A model can be pinned with a command-line option or provider-specific environment variable, but the README emphasizes that model identifiers are deliberately not hardcoded by default. Each provider can resolve a current mid-tier model from its own models API, keeping the example resilient as vendors update model catalogs.
ANTHROPIC_API_KEY=sk-… pnpm --filter @mcp-examples/cli-client start -- --provider anthropic
OPENAI_API_KEY=sk-… pnpm --filter @mcp-examples/cli-client start -- --provider openai
GEMINI_API_KEY=… pnpm --filter @mcp-examples/cli-client start -- --provider gemini
ANTHROPIC_API_KEY=sk-… pnpm --filter @mcp-examples/cli-client start -- --provider anthropic --model claude-sonnet-4-5Sources: examples/cli-client/README.md, examples/cli-client/cli.ts
Command and Configuration Reference
The interactive command accepts targets, provider options, workspace roots, OAuth callback configuration, and a protocol-era switch. Use a repeated server option for ad hoc connections, or point the command at a configuration file when modeling a host that manages multiple named servers. If neither a server target nor a config file is supplied, the CLI falls back to a local todos-server setup. The root option exposes workspace roots through the client roots behavior, while the callback port option is useful when a remote MCP server needs browser-based OAuth and the developer is port-forwarding over SSH.
| Option | Behavior |
|---|---|
--server <target> | Connect to one ad hoc server, either an HTTP(S) URL or a stdio command line; repeatable. |
--config <path> | Read an mcpServers config file; defaults to ./config.json before falling back to todos-server. |
--provider <name> | Select scripted, anthropic, openai, or gemini. |
--model <id> | Pin a provider model instead of resolving the provider default. |
--root <path> | Expose a workspace root to servers; repeatable and defaults to the current working directory. |
--callback-port <n> | Use a fixed loopback OAuth callback port. |
--legacy | Use the 2025 initialize handshake rather than probing for the 2026-07-28 behavior. |
--help | Print command usage. |
Sources: examples/cli-client/cli.ts
REPL Execution Flow
The interactive flow begins with argument parsing, provider selection, and UI construction. After that, the CLI builds a host configuration from server targets, a config file, or the default todos server. Once connected, the chat session handles each line of user input through the shared session loop. The README’s guided tour prompts are designed to touch the interesting MCP surfaces in one sitting: elicitation forms, approval-gated sampling, prompts, resources as context, progress, logging, cancellation, subscriptions, tool calls, and undo-style state changes in the paired server.
Sources: examples/cli-client/README.md, examples/cli-client/cli.ts
When paired over Streamable HTTP, the README highlights the connection status line as a quick diagnostic. It reports the server name, negotiated protocol era, and discovered counts for tools, resources, and prompts. Running with the default modern path can show a 2026-era connection, while adding the legacy flag forces a 2025-era handshake against the same server so the legacy feature paths can be observed. This makes the CLI especially useful when comparing behavior during migration, because the same host code can exercise both eras with only a command-line switch.
# Terminal A
pnpm --filter @mcp-examples/todos-server start:http
# Terminal B
ANTHROPIC_API_KEY=sk-… pnpm --filter @mcp-examples/cli-client start -- --server http://127.0.0.1:3000/mcp --provider anthropic
# Force the 2025-era path
ANTHROPIC_API_KEY=sk-… pnpm --filter @mcp-examples/cli-client start -- --server http://127.0.0.1:3000/mcp --provider anthropic --legacySources: examples/cli-client/README.md, examples/README.md
Scripted Client, Server Pairing, and Testing Signals
The noninteractive client entry point is the same story adapted for automated verification. It parses the example runner’s transport, URL, and era arguments, builds a scripted session, creates a deterministic UI with canned confirmation and form answers, and connects a host to todos-server over either stdio or HTTP. For a stdio run it builds a command that invokes the sibling todos-server TypeScript file; for HTTP it uses the supplied URL. After replaying all scripted inputs, it waits briefly for debounced list-change refreshes, verifies the session, closes the host, and prints a success message.
Sources: examples/cli-client/client.ts, examples/cli-client/server.ts
The repository examples guide explains why this matters: each example directory is treated as a runnable, self-verifying story, and CI runs supported client/server pairs over their transports. The CLI client is the notable exception to the generic story commands because it has its own human-facing start command and pairs with todos-server’s own HTTP entry point. When you need a reference host, start by reading the interactive command and then compare it with the scripted client. The differences show what is terminal convenience, what is deterministic test harness, and what is reusable MCP host wiring.
Sources: examples/README.md, examples/cli-client/cli.ts, examples/cli-client/client.ts
Next Steps
Use the CLI client as a living reference when building a host application that needs to connect to arbitrary MCP servers. First run the scripted default to validate your workspace, then pair it with todos-server over HTTP, and finally replace the target with your own server URL or stdio command. If your application needs more than one server, move from repeated ad hoc targets to an mcpServers configuration file. For deeper implementation work, read the client connection, client calling, OAuth, roots, server requests, subscriptions, and protocol versions pages alongside this example.