返回 CodeWhale
stdio_server.sh.fixture
根目录 / crates / tui / tests / fixtures / conformance / mcp / stdio_server.sh.fixture
1 #!/bin/sh
2 # Deterministic stdio MCP server for the `mcp` conformance family.
3 #
4 # sh stdio_server.sh.fixture DIR (any copy of this file; the harness copies it
5 # to stdio_server.sh in a temp dir)
6 #
7 # It answers from files in DIR, which the harness writes from the case's
8 # `server` object (same shape the HTTP transcript server uses):
9 #
10 # initialize.reply, tools_list.reply the JSON-RPC reply minus its id,
11 # e.g. "result":{"tools":[...]}
12 # call.<tool>.reply the same, for tools/call of <tool>
13 # call.<tool>.exit present: exit without replying
14 # (a server that dies mid-call)
15 #
16 # Every tools/call request line is appended to DIR/calls.log before it is
17 # answered, so the harness can report what the server was actually asked to
18 # run. One JSON-RPC message per line on stdin and stdout; notifications get
19 # no reply. Plain POSIX sh: no Node, no JSON parser.
20 dir=$1
21 reply() {
22 printf '{"jsonrpc":"2.0","id":"%s",%s}\n' "$1" "$2"
23 }
24 while IFS= read -r line; do
25 id=$(printf '%s\n' "$line" | sed -n 's/.*"id":"\([^"]*\)".*/\1/p')
26 method=$(printf '%s\n' "$line" | sed -n 's/.*"method":"\([^"]*\)".*/\1/p')
27 case "$method" in
28 notifications/*) ;;
29 initialize) reply "$id" "$(cat "$dir/initialize.reply")" ;;
30 tools/list) reply "$id" "$(cat "$dir/tools_list.reply")" ;;
31 tools/call)
32 printf '%s\n' "$line" >> "$dir/calls.log"
33 tool=$(printf '%s\n' "$line" | sed -n 's/.*"name":"\([^"]*\)".*/\1/p')
34 [ -f "$dir/call.$tool.exit" ] && exit 0
35 if [ -f "$dir/call.$tool.reply" ]; then
36 reply "$id" "$(cat "$dir/call.$tool.reply")"
37 else
38 reply "$id" '"error":{"code":-32602,"message":"no scripted tools/call answer"}'
39 fi
40 ;;
41 *)
42 [ -n "$id" ] && reply "$id" '"error":{"code":-32601,"message":"method not found"}'
43 ;;
44 esac
45 done
46
46 lines Plain Text