blob: d6bde4c8709950c588e658aa0ce9cb743f68a291 [file]
"""One tool call through `amem serve` over stdio, as the author given: how the demo
speaks as an agent without a harness. A held task, if given, is in MEMORY_TASK, as the
launcher sets it for a harness working a task.
python3 mcp.py <amem> <root> <author> <tool> '<json arguments>' [task-id]
python3 mcp.py <amem> <root> <author> batch '[{"tool": t, "arguments": {...}}, ...]'
Prints the tool's JSON result, or `refused: <message>` and exits 1. A batch is several
calls in one session, as a harness makes them; it prints the last result. `steps` is a
batch that goes on past a refusal and prints one JSON line per call, `{"tool", "ok",
"result"}` or `{"tool", "ok": false, "refused"}`, for an act that shows each."""
import json
import os
import subprocess
import sys
amem, root, author, tool, args = sys.argv[1:6]
env = dict(os.environ)
if len(sys.argv) > 6 and sys.argv[6]:
env["MEMORY_TASK"] = sys.argv[6]
p = subprocess.Popen([amem, "--root", root, "serve", "--author", author],
stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True, env=env)
def send(m):
p.stdin.write(json.dumps(m) + "\n")
p.stdin.flush()
def recv():
return json.loads(p.stdout.readline())
send({"jsonrpc": "2.0", "id": 1, "method": "initialize",
"params": {"protocolVersion": "2025-06-18", "capabilities": {},
"clientInfo": {"name": "demo", "version": "0"}}})
recv()
send({"jsonrpc": "2.0", "method": "notifications/initialized"})
calls = json.loads(args) if tool in ("batch", "steps") else [{"tool": tool, "arguments": json.loads(args)}]
def outcome(r):
if "error" in r:
return False, r["error"]["message"]
res = r["result"]
text = " ".join(c.get("text", "") for c in res.get("content", []))
return not res.get("isError"), text
if tool == "steps":
for n, c in enumerate(calls, start=2):
send({"jsonrpc": "2.0", "id": n, "method": "tools/call",
"params": {"name": c["tool"], "arguments": c["arguments"]}})
ok, text = outcome(recv())
line = {"tool": c["tool"], "ok": ok}
if ok:
try:
line["result"] = json.loads(text)
except ValueError:
line["result"] = text
else:
line["refused"] = text
print(json.dumps(line), flush=True)
p.stdin.close()
p.wait()
sys.exit(0)
r = None
for n, c in enumerate(calls, start=2):
send({"jsonrpc": "2.0", "id": n, "method": "tools/call",
"params": {"name": c["tool"], "arguments": c["arguments"]}})
r = recv()
if "error" in r or r["result"].get("isError"):
break
p.stdin.close()
p.wait()
if "error" in r:
print("refused: " + r["error"]["message"])
sys.exit(1)
res = r["result"]
if res.get("isError"):
print("refused: " + " ".join(c.get("text", "") for c in res.get("content", [])))
sys.exit(1)
text = "".join(c.get("text", "") for c in res.get("content", []))
print(text)