jep-mcp-wrapper adds verifiable accountability semantics to MCP tool execution without changing the MCP protocol. Existing tool callables are wrapped in a side-channel JEP runtime that emits deterministic, append-only events for each execution lifecycle step.
JEPMCPWrapperwraps sync and async MCP tool callables.MCPExecutionTracerwrites lifecycle events (requested,running,succeeded,failed).ToolDelegationRuntimetracks the active actor, delegation lineage, parent context, and authority scope across nested tool calls.ReplayVerifierreplays archived execution chains, verifies lineage, validates deterministic hashes, and detects archive tampering.AppendOnlyEventArchivestores JSONL events as an append-only hash chain.
The wrapper records:
tool_nameactor- delegation lineage
- authority scope
- execution state
- parent event linkage
- deterministic event hash and previous hash
from pathlib import Path
from jep_mcp_wrapper import JEPMCPWrapper, ReplayVerifier
archive = "jep-events.jsonl"
wrapper = JEPMCPWrapper(
archive,
default_actor="agent:file-reader",
default_authority_scope={"filesystem": "read-only"},
)
def read_file(path: str) -> str:
return Path(path).read_text(encoding="utf-8")
read_file = wrapper.wrap_tool("filesystem.read_file", read_file)
print(read_file("README.md"))
replay = ReplayVerifier(archive).replay()
assert replay.verifiedNested wrapped calls automatically extend lineage. A search.query tool that calls a wrapped browser.fetch tool produces two execution chains: one with ("search.query",) and one with ("search.query", "browser.fetch").
from jep_mcp_wrapper import JEPMCPWrapper
wrapper = JEPMCPWrapper("events.jsonl", default_actor="agent:researcher")
def browser_fetch(url: str) -> str:
return f"page:{url}"
def search(query: str, fetch) -> str:
return fetch(f"https://example.test?q={query}")
fetch = wrapper.wrap_tool("browser.fetch", browser_fetch, authority_scope={"network": "example.test"})
search = wrapper.wrap_tool("search.query", search, authority_scope={"purpose": "research"})
search("accountability", fetch=fetch)from jep_mcp_wrapper import ReplayVerifier
verifier = ReplayVerifier("events.jsonl")
result = verifier.replay()
print(result.verified)
print(result.lineage_by_call)
print(verifier.detect_tampering())Replay verification checks:
- deterministic hash equality for every event,
- previous-hash continuity across the append-only archive,
- monotonic event sequence numbers,
- valid tool lifecycle transitions,
- stable lineage for every tool call,
- parent/child lineage consistency when parent links are present.
examples/filesystem_tool.pywraps a filesystem read tool.examples/browser_search_chain.pywraps browser and search tools with chained delegation.
- It does not modify MCP protocol schemas or wire semantics.
- It does not implement an orchestration framework.
- It does not decide whether a tool is authorized; it records the declared authority scope so execution can be audited and replayed.