ProtocolArc
Health Pass
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Community trust — 11 GitHub stars
Code Pass
- Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
Contract lab for agent protocol envelopes - versioned MCP/A2A message contracts, envelope validation, and compatibility diffs (compatible/forward/breaking). Python 3 stdlib + optional .NET 9 runtime.
ProtocolArc
A contract lab for agent protocol envelopes. Describe an MCP or A2A message shape as a versioned contract, validate real envelopes against it, and classify what changes between revisions as compatible, forward, or breaking.
Python 3 standard library · optional .NET 9 runtime · deterministic output
What it is for
Agent systems pass structured envelopes between tools and peers: MCP tool calls, A2A task sends, and similar JSON-RPC shaped messages. When the shape of those messages changes, older clients can break in ways that are hard to see until traffic fails. ProtocolArc turns the envelope shape into an explicit, versioned contract so that:
- an envelope can be checked against the contract it claims to satisfy,
- two revisions of the same contract can be compared to see whether the change is safe, and
- a whole set of envelopes and contracts can be cross-checked into one matrix report.
A contract failure and a contract change are treated as different things. A malformed document raises a structural error. A document that parses but does not satisfy a contract produces ordered findings with severities, never an exception.
The compatibility model
diff compares two revisions of the same contract and reports the worst outcome across all field-level changes. One breaking change makes the whole diff breaking.
| Verdict | Meaning |
|---|---|
compatible |
The new revision accepts everything the old one did. |
forward |
Old consumers keep working; new fields are optional, types widened, constraints relaxed. |
breaking |
A change can reject previously valid envelopes: a required field added or removed, a type narrowed, an enum restricted, or an optional field tightened to required. |
Data model
A contract names a protocol, carries a semantic revision, and lists ordered FieldSpec entries. Each field has a dotted path (params.name), one or more accepted JSON types, a required flag, and an optional enum. A strict contract also flags top-level keys it does not declare.
{
"name": "mcp.tool_call",
"revision": "1.0.0",
"kind": "mcp",
"title": "MCP Tool Call",
"strict": false,
"fields": [
{ "name": "jsonrpc", "type": "string", "enum": ["2.0"] },
{ "name": "id", "type": ["string", "integer"] },
{ "name": "method", "type": "string", "enum": ["tools/call"] },
{ "name": "params.name", "type": "string" },
{ "name": "params.arguments", "type": "object", "required": false }
]
}
An envelope declares the contract it targets, an optional revision, and its data body. The bundled fixtures cover both an MCP contract that evolves from 1.0.0 to 2.0.0 and a strict A2A task_send contract.
Commands
python -m protocolarc <validate|diff|matrix|report|describe> ...
Exit codes are meaningful: 0 success, 1 validation errors present, 2 breaking compatibility detected by diff, 3 a usage or input error.
validate checks envelopes against one contract:
python -m protocolarc validate \
examples/contracts/mcp_tool_call_1.0.0.json \
examples/fixtures/mcp_calls.jsonl
[PASS] [email protected] <- mcp_calls.jsonl:1
[FAIL] [email protected] <- mcp_calls.jsonl:3
ERROR field.enum method: value 'tools/list' not in {'tools/call'}
diff compares two revisions and classifies the change:
python -m protocolarc diff \
examples/contracts/mcp_tool_call_1.0.0.json \
examples/contracts/mcp_tool_call_2.0.0.json
mcp.tool_call: 1.0.0 -> 2.0.0
compatibility: BREAKING
breaking field.type.narrowed id: string|integer -> string
breaking field.required.tightened params.arguments: optional -> required
forward field.added.optional params.timeout_ms: added integer
matrix cross-validates a set of envelopes against a set of contracts (files or directories):
python -m protocolarc matrix \
--contracts examples/contracts \
--envelopes examples/fixtures/mcp_calls.jsonl examples/fixtures/a2a_tasks.json
report renders the same matrix as markdown (default), json, or text, optionally to a file:
python -m protocolarc report \
--contracts examples/contracts \
--envelopes examples/fixtures/mcp_calls.jsonl \
--format markdown --out report.md
describe prints a contract's field table:
python -m protocolarc describe examples/contracts/a2a_task_send_1.0.0.json
The .NET runtime
runtime/ holds ProtocolArc.Runtime, a native validator that mirrors the Python validate logic so a contract checked by either component yields the same findings. It is meant for hot paths where envelopes stream through a gateway.
cd runtime
dotnet run -- selfcheck
dotnet run -- validate ../examples/contracts/mcp_tool_call_1.0.0.json ../examples/fixtures/mcp_calls.jsonl --json
dotnet run -- describe ../examples/contracts/a2a_task_send_1.0.0.json
selfcheck builds a contract and two envelopes in memory and asserts the expected pass and fail split, so CI can confirm the runtime works without external fixtures.
How validation reads an envelope
For each contract field, the validator resolves the dotted path in the envelope body and applies rules in a fixed order:
contract.match: the envelope must target the contract being checked (error).revision.hint: a declared revision that differs from the contract is a warning, since it may be an older client talking to a newer contract.field.required: a missing required field is an error.field.type: a present field must match one of the accepted JSON types.field.enum: a scalar value must be within the declared enum.field.unknown: under a strict contract, an undeclared top-level key is a warning.
Findings are sorted by severity, then field, then rule, so the output is stable across runs.
Repository layout
protocolarc/
├── protocolarc/ Python package (stdlib only)
│ ├── __main__.py python -m protocolarc entry point
│ ├── cli.py validate / diff / matrix / report / describe
│ ├── model.py Contract, Envelope, FieldSpec
│ ├── loader.py parse contract and envelope documents
│ ├── validate.py envelope validation, ordered findings
│ ├── diff.py revision comparison and compatibility classes
│ ├── matrix.py cross-product matrix and revision chains
│ └── report.py markdown / json / text renderers
├── runtime/ ProtocolArc.Runtime (.NET 9), mirrors the validator
├── examples/
│ ├── contracts/ mcp.tool_call 1.0.0 / 1.1.0 / 2.0.0, a2a.task_send
│ └── fixtures/ mcp_calls.jsonl, a2a_tasks.json
└── docs/assets/ banner and pipeline diagrams
Determinism
Field ordering is preserved from the contract, and every derived collection is sorted before rendering, so repeated runs over the same inputs produce byte-identical output. Reports come in json, markdown, and text, and each is a pure function of the matrix it renders.
Extending it
Add a validation rule by appending a Finding inside validate_envelope with a rule name, field, severity, and message; the sort key keeps output stable. Add a compatibility rule by extending the CHANGE_IMPACT map in diff.py and emitting the matching Change. Keep the .NET runtime in step with any validation change so both components agree.
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found