1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
//! An MCP client in one runnable file.
//!
//! Spawns the
//! [`stdio_server`](protocol_droid::adapters::primary::stdio::serve_stdio)
//! example as a child process, connects to it with
//! [`Client::connect_stdio`](protocol_droid::application::client::Client::connect_stdio),
//! lists the tools it advertises, and calls one.
//!
//! # Why this exists
//!
//! The write-a-client.md guide shows a 9-line example
//! using the new [`Client::connect_stdio`] façade. This
//! file is the runnable counterpart — a consumer who
//! copies it and changes the `ChildSpec::new(...)`
//! program has a working MCP client pointed at any
//! stdio server they want to drive.
//!
//! # What it does
//!
//! 1. Spawns `cargo run -p protocol-droid --example
//! stdio_server` as a child. The child's stdout is
//! the protocol stream; its stderr is drained into
//! `Diagnostics::stderr()` by the library's
//! `StdioClient`.
//! 2. Connects with `Client::connect_stdio(&spec)`.
//! That single call covers the four steps a
//! consumer would otherwise write by hand:
//! `StdioClient::spawn`, `handshake`, and
//! `Client::from_session`.
//! 3. Lists the tools the server advertises. The
//! `stdio_server` example has one tool, `shout`,
//! so the result is a single entry.
//! 4. Calls `shout` with `text: "hello"`. The server
//! uppercases it and reports the character count.
//!
//! # Running
//!
//! ```text
//! cargo run -p protocol-droid --example mcp_client
//! ```
//!
//! The child cargo process is killed when the client
//! returns; the example does not install a SIGINT
//! handler of its own, so ctrl-c also kills the child
//! through the standard parent/child relationship.
use ChildSpec;
use Client;
use JsonObject;
use json;
async
/// The `ChildSpec` for the `stdio_server` example.
///
/// `cargo run --example stdio_server` is what the
/// example's own docs tell the reader to run, so the
/// child is the same one. The `--example` flag and
/// the example name are the only arguments; cargo
/// handles the rest. The CARGO env var is set when
/// running through cargo, so the child picks up the
/// same toolchain.