Corrects the ACT acronym expansion to "Agent Context Token" in the reference implementation. Adds proper pyproject.toml for the act package and the MCP+LangGraph PoC planning document.
4.3 KiB
PoC Plan — ACT + ECT over MCP with LangGraph
Target: end-to-end working demo for IETF 123 preparation and draft credibility.
Location: demo/act-ect-mcp/ (moved out of workspace/poc/ to be a first-class peer of paper/ and workspace/)
Date: 2026-04-12
Scenario
A user issues a mandate (ACT authorization token) to a LangGraph agent: "research topic X, produce summary." The agent, running in a LangGraph StateGraph, calls two tools exposed by an MCP server:
search(query)— returns fake hitssummarize(text)— returns fake summary
Every MCP tool call is authenticated by:
- ACT mandate in
Authorization: Bearer <act-jwt>header (capability check:cap=["mcp.search","mcp.summarize"]) - ECT execution context in a signed HTTP header per
draft-ietf-wimse-http-signature-03using thewimse-audsignature parameter - Tool-call body hashed into ECT
inp_hash
On tool success, the agent mints an ACT execution record with:
status="completed"pred=[mandate.jti]for the first call,pred=[mandate.jti, prev_exec.jti]for subsequent calls (DAG, not linear)inp_hash/out_hashbound to request/response bodies
A standalone verify CLI walks the resulting ACT ledger + ECT store and prints the DAG.
Components
poc/mcp-langgraph/
├── README.md # how to run, what it proves
├── pyproject.toml # depends on ietf-act, ietf-ect, mcp, langgraph, fastapi
├── keys/ # generated ES256 keys (gitignored)
├── src/
│ ├── keys.py # key gen + JWKS loader
│ ├── tokens.py # ACT mandate/exec minters, ECT header builder
│ ├── http_sig.py # minimal http-signature-03 signer/verifier
│ ├── server.py # MCP server (FastMCP streamable-http) + ECT/ACT middleware
│ ├── agent.py # LangGraph agent + MCP client, injects ACT+ECT
│ └── verify_cli.py # walks ledger, prints DAG
├── demo.sh # end-to-end: start server, run agent, run verifier
└── tests/
├── test_token_flow.py # one tool call → one exec record linked via pred
└── test_dag_shape.py # two tool calls → DAG with expected pred edges
Build sequence (verifiable increments)
- Skeleton + deps:
pyproject.toml, package layout, install works. - Keys + tokens:
keys.py,tokens.py. Unit test: mint mandate, mint exec, verify both. - HTTP signature:
http_sig.py. Unit test: sign request, verify (round-trip). - MCP server: FastMCP with two fake tools + ASGI middleware that verifies ACT+ECT on every call. Manual curl test.
- LangGraph agent: StateGraph,
langchain-mcp-adapterswith custom headers callback. No LLM — scripted node sequence that calls both tools. - Verifier CLI: prints the DAG (mandate → exec1 → exec2).
- End-to-end
demo.sh: spawns server, runs agent, runs verifier. Green = PoC done.
Explicit non-goals
- Real LLM via Ollama (local, zero API cost).
create_react_agentdecides which MCP tools to call. Token flow is deterministic regardless of LLM output. - No registration / discovery of agents — assume pre-shared JWKS.
- No distributed SCITT anchoring — in-memory ledger only.
- No Go interop in this PoC (Python + Python). Go path tracked separately.
Tradeoffs
Real MCP vs. MCP-shaped: use real MCP SDK (FastMCP server + streamablehttp_client). More credible for IETF reviewers; adds dep weight. If the MCP SDK blocks us from injecting ECT on the HTTP layer, fall back to FastAPI endpoints that mirror the MCP JSON-RPC shape.
LLM: real. Ollama qwen3:8b as default (local, free, reproducible per CLAUDE.md cost policy). Swap to Anthropic/OpenAI via env var. LangGraph create_react_agent wires LLM + MCP tools.
Success criteria
demo.shexits 0, verifier prints a DAG with 1 mandate + 2 execs + correctprededges.- All unit tests green.
- README shows a reviewer can reproduce in under 5 minutes (
uv sync && ./demo.sh).
Questions before coding
- OK to put PoC under
workspace/poc/mcp-langgraph/(new dir), not underpackages/? - OK to pin
mcp>=1.0,langgraph>=0.2,langchain-mcp-adaptersas deps? - LangGraph without an LLM is fine for v1 of the PoC, right?