- 00-kanban.md rebuilt: ▶ NEXT PLAN pointer (iteration 4 — emitter, corpus, `woc build`) then six buckets — stories, in progress, done, pending, discarded, learnings. It tracked only the Rust runtime before, so the whole OOP track (wovm shipped, woc Tasks 1-8 shipped) was invisible. - Board now records iteration 3's known gaps instead of silently owing them: `?T` plumbed but unenforced; E205/E201/E203/E204 dead, so structural interface satisfaction is unchecked. - New discarded.md — settled rejections with reasons so they are not re-proposed: inheritance, `abstract` newtypes, Money/SKU/Float, Dynamic/cast/ macro/extern, AOT-to-C, Menhir, shared engine state, external deployer. - RECOVERED docs/plan/exploration/blue-green-vm/00-vision.md — gone from disk, never committed (gitignored path), cited by five docs incl. principle 12. - Root cause was broader: all seven forward-roadmap plans in docs/superpowers/plans/ were untracked and ignored, on one disk only. Rules were half-fiction — 33 of 34 exploration files were already tracked, so they swallowed only *new* files. - Dropped the docs ignore rules (exploration, oop-vm, superpowers/plans, examples/agent-loop, examples/mcp-think) with a do-not-re-add comment; added __pycache__/*.pyc. `tests/` stays ignored but warns that the next plan lands the corpus there.
85 lines
2.9 KiB
Python
85 lines
2.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Smoke-test mcp-think over stdio, exactly the way Claude drives it.
|
|
|
|
Launches server.py as a subprocess (via `uv run --with mcp`), performs the
|
|
MCP lifecycle (initialize → initialized), lists the tools, and calls
|
|
`think` once. Requires Ollama running with the configured model pulled.
|
|
|
|
Usage: python3 test_client.py # standard library only
|
|
THINK_MODEL=qwen3:0.6b python3 test_client.py
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
|
|
def main() -> int:
|
|
proc = subprocess.Popen(
|
|
["uv", "run", "--with", "mcp", "python3", os.path.join(HERE, "server.py")],
|
|
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL,
|
|
env=os.environ.copy(), text=True,
|
|
)
|
|
stdin, stdout = proc.stdin, proc.stdout
|
|
assert stdin is not None and stdout is not None
|
|
|
|
msg_id = 0
|
|
|
|
def send(method: str, params: dict | None = None, notify: bool = False) -> dict:
|
|
nonlocal msg_id
|
|
msg: dict = {"jsonrpc": "2.0", "method": method}
|
|
if params is not None:
|
|
msg["params"] = params
|
|
if not notify:
|
|
msg_id += 1
|
|
msg["id"] = msg_id
|
|
stdin.write(json.dumps(msg) + "\n")
|
|
stdin.flush()
|
|
if notify:
|
|
return {}
|
|
# stdio transport: one JSON-RPC message per line
|
|
line = stdout.readline()
|
|
if not line:
|
|
raise RuntimeError("server closed the pipe")
|
|
return json.loads(line)
|
|
|
|
try:
|
|
r = send("initialize", {
|
|
"protocolVersion": "2025-06-18",
|
|
"capabilities": {},
|
|
"clientInfo": {"name": "mcp-think-smoke", "version": "0"},
|
|
})
|
|
server = r["result"]["serverInfo"]
|
|
print(f"initialize ok — server: {server['name']}")
|
|
|
|
send("notifications/initialized", {}, notify=True)
|
|
|
|
r = send("tools/list", {})
|
|
tools = [t["name"] for t in r["result"]["tools"]]
|
|
print(f"tools/list ok — {tools}")
|
|
assert {"think", "critique", "brainstorm", "summarize"} <= set(tools)
|
|
|
|
print("tools/call think(...) — waiting on the local model…")
|
|
r = send("tools/call", {
|
|
"name": "think",
|
|
"arguments": {"task": "In one sentence: why do write-ahead logs "
|
|
"fsync before acknowledging a commit?"},
|
|
})
|
|
content = r["result"]["content"][0]["text"]
|
|
print(f"\n--- local model says ---\n{content}\n")
|
|
if content.startswith("[mcp-think]"):
|
|
print("NOT OK — the server answered, but the local model is unavailable.")
|
|
return 1
|
|
print("OK — MCP lifecycle, tool discovery, and local-model call all work.")
|
|
return 0
|
|
finally:
|
|
stdin.close()
|
|
proc.terminate()
|
|
proc.wait(timeout=5)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|