feat(examples): add a reference host/server pair — cli-client + todos-server (#2380)
This commit is contained in:
parent
1823aae891
commit
ba27d201e1
1 changed files with 4698 additions and 25 deletions
48
examples/cli-client/client.ts
Normal file
48
examples/cli-client/client.ts
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* The CI entry point: replays the scripted conversation in script/session.ts against the
|
||||
* sibling todos-server with the keyless ScriptedProvider, asserting at every step. This is
|
||||
* what `pnpm run:examples` executes over the stdio and Streamable HTTP legs; run it yourself
|
||||
* with `pnpm --filter @mcp-examples/cli-client client`. The interactive entry for humans is
|
||||
* cli.ts (`pnpm --filter @mcp-examples/cli-client start`).
|
||||
*/
|
||||
import { parseExampleArgs, siblingPath } from '@mcp-examples/shared';
|
||||
|
||||
import type { CliClientConfig } from './host/config';
|
||||
import { McpHost } from './host/host';
|
||||
import { createSession, handleUserInput } from './host/loop';
|
||||
import { ScriptedProvider } from './providers/scripted';
|
||||
import { ScriptedUI } from './script/scriptedUi';
|
||||
import { buildScriptedSession } from './script/session';
|
||||
|
||||
const { transport, url, era } = parseExampleArgs();
|
||||
|
||||
// Push-style server→client requests (2025-era sampling/elicitation) have no return path on a
|
||||
// stateless legacy HTTP deployment, so that leg skips the prioritize/clear_done steps and
|
||||
// still exercises tools, resources-as-context, and prompts.
|
||||
const interactive = !(era === 'legacy' && transport === 'http');
|
||||
|
||||
const session = buildScriptedSession({ interactive });
|
||||
const ui = new ScriptedUI({ confirmAnswers: session.confirmAnswers, askAnswers: session.askAnswers });
|
||||
const provider = new ScriptedProvider(session.turns);
|
||||
const host = new McpHost({ ui, provider, roots: [process.cwd()], legacy: era === 'legacy' });
|
||||
|
||||
const config: CliClientConfig =
|
||||
transport === 'stdio'
|
||||
? { mcpServers: { todos: { command: 'npx', args: ['-y', 'tsx', siblingPath(import.meta.url, '../todos-server/server.ts')] } } }
|
||||
: { mcpServers: { todos: { url } } };
|
||||
|
||||
await host.connect(config);
|
||||
|
||||
const chat = createSession(host, provider, ui);
|
||||
for (const [index, input] of session.inputs.entries()) {
|
||||
session.beforeInput?.[index]?.(ui);
|
||||
await handleUserInput(chat, input);
|
||||
}
|
||||
|
||||
// Give debounced list-change refreshes (the SDK coalesces them for ~300 ms) a moment to land.
|
||||
await new Promise(resolve => setTimeout(resolve, 750));
|
||||
|
||||
await session.verify({ ui, provider, host, era, transport });
|
||||
await host.close();
|
||||
|
||||
console.log('cli-client e2e: all checks passed');
|
||||
Loading…
Reference in a new issue