agent-passport-system-mcp 2.23.0 → 2.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CONTRIBUTING.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Contributing to Agent Passport System MCP Server
2
2
 
3
- Thanks for your interest in contributing! This is the MCP server for the [Agent Passport System](https://github.com/aeoess/agent-passport-system) — 49 tools across 8 protocol layers for AI agent identity, trust, governance, and commerce.
3
+ Thanks for your interest in contributing! This is the MCP server for the [Agent Passport System](https://github.com/aeoess/agent-passport-system) — 132 tools across the full protocol surface for AI agent identity, trust, governance, and commerce.
4
4
 
5
5
  ## Getting Started
6
6
 
@@ -53,6 +53,55 @@ If you're adding new MCP tools, follow the existing pattern in `src/index.ts`:
53
53
  3. Update the README tool table
54
54
  4. Update the tool count in the README header
55
55
 
56
+ ---
57
+
58
+ ## What makes a PR mergeable
59
+
60
+ 1. **Build passes.** `npm run build` succeeds with zero TypeScript errors.
61
+ 2. **SDK alignment.** If you're exposing a new SDK capability as an MCP tool, the SDK function must already exist and be tested. This repo wraps; it doesn't redefine.
62
+ 3. **Tool naming consistency.** Follow existing naming conventions (`snake_case`, verb-first for actions).
63
+ 4. **Zod schemas.** Every tool registers a zod input schema — no untyped parameters.
64
+ 5. **README table updated.** New tools show up in the README tool table with their category.
65
+ 6. **Scope discipline.** One concern per PR. Refactors ride alongside in separate PRs.
66
+
67
+ ## Stability expectations
68
+
69
+ Follows semantic versioning. New tools land in minor releases. Changes to tool signatures (renames, parameter changes) are breaking and require a major version bump with migration notes. SDK version alignment is tracked in `package.json` peer dependencies.
70
+
71
+ ## Out of scope
72
+
73
+ - **New protocol logic.** All protocol behavior lives in `agent-passport-system`. This repo exposes it via MCP.
74
+ - **Disabling zod validation** for convenience — validation is load-bearing for MCP client safety.
75
+ - **Named integrations woven into tool implementations** — integration examples belong in documentation or a sibling adapter repo.
76
+ - **Breaking changes to tool signatures** without major version bump and migration documentation.
77
+
78
+ ---
79
+
80
+ ## How review works
81
+
82
+ Every PR is evaluated against five questions, applied to every contributor equally:
83
+
84
+ 1. **Identity.** Is the contributor identifiable, with a real GitHub presence?
85
+ 2. **Format.** Does the change match existing patterns (tool registration, zod schema, README table)?
86
+ 3. **Substance.** Does the new tool actually wrap tested SDK functionality?
87
+ 4. **Scope.** Does the PR stay scoped to its stated purpose?
88
+ 5. **Reversibility.** Can the change be reverted cleanly if a downstream issue surfaces?
89
+
90
+ Substantive declines include the reason.
91
+
92
+ ---
93
+
94
+ ## Practical details
95
+
96
+ - **Maintainer:** [@aeoess](https://github.com/aeoess) (Tymofii Pidlisnyi)
97
+ - **Review timing:** maintainer-bandwidth dependent. If a PR has had no response after 5 business days, ping it.
98
+ - **CLA / DCO:** no CLA is required. Contributions accepted on the understanding that the submitter has the right to contribute under the Apache-2.0 license.
99
+ - **Publishing:** maintainers handle npm release publishing. Please do not bump version numbers in PRs. If your change requires a version bump, call that out in the PR description.
100
+ - **Security issues:** open a private security advisory via GitHub rather than a public issue.
101
+ - **Code of Conduct:** Contributor Covenant 2.1 — see [`CODE_OF_CONDUCT.md`](./CODE_OF_CONDUCT.md).
102
+
103
+ ---
104
+
56
105
  ## License
57
106
 
58
- By contributing, you agree that your contributions will be licensed under the project's Apache-2.0 license.
107
+ By contributing, you agree that your contributions will be licensed under the project's Apache-2.0 license. See [`LICENSE`](./LICENSE).
package/README.md CHANGED
@@ -12,13 +12,13 @@ Enforcement and accountability layer for AI agents. Bring your own identity. 20
12
12
  APS_PROFILE=essential npx agent-passport-system-mcp
13
13
  ```
14
14
 
15
- `essential` is the default profile — the 20 tools 90% of integrations need. Set `APS_PROFILE=full` for all 132 tools.
15
+ `essential` is the default profile — the 149 tools 90% of integrations need. Set `APS_PROFILE=full` for all 149 tools.
16
16
 
17
17
  Available profiles: essential (default), identity, governance, coordination, commerce, data, gateway, comms, minimal, full.
18
18
 
19
19
  > **For AI agents:** visit [aeoess.com/llms.txt](https://aeoess.com/llms.txt) for machine-readable documentation or [llms-full.txt](https://aeoess.com/llms-full.txt) for the complete technical reference. MCP discovery: [.well-known/mcp.json](https://aeoess.com/.well-known/mcp.json).
20
20
 
21
- Works with any MCP client: Claude Desktop, Claude Code, Cursor, Windsurf, and more. Full surface area under `APS_PROFILE=full`: 132 tools across 103 modules (71 core + 32 v2 constitutional governance). Independently cited by [PDR in Production (Nanook & Gerundium, UBC)](https://doi.org/10.5281/zenodo.19323172).
21
+ Works with any MCP client: Claude Desktop, Claude Code, Cursor, Windsurf, and more. Full surface area under `APS_PROFILE=full`: 149 tools across 103 modules (71 core + 32 v2 constitutional governance). Independently cited by [PDR in Production (Nanook & Gerundium, UBC)](https://doi.org/10.5281/zenodo.19323172).
22
22
 
23
23
  ## Quick Start
24
24
 
@@ -69,7 +69,7 @@ Or for remote SSE:
69
69
  ```
70
70
  </details>
71
71
 
72
- ## Tools (128)
72
+ ## Tools (132)
73
73
 
74
74
  ### Identity (Layer 1) — 5 tools
75
75
 
@@ -216,7 +216,7 @@ Layer 1 — Agent Passport Protocol (Ed25519 identity)
216
216
 
217
217
  ## Links
218
218
 
219
- - npm SDK: [agent-passport-system](https://www.npmjs.com/package/agent-passport-system) (v1.41.0, 2764 tests)
219
+ - npm SDK: [agent-passport-system](https://www.npmjs.com/package/agent-passport-system) (v1.44.0, 2910 tests)
220
220
  - Python SDK: [agent-passport-system](https://pypi.org/project/agent-passport-system/) (v0.8.0)
221
221
  - Paper (Protocol): [doi.org/10.5281/zenodo.18749779](https://doi.org/10.5281/zenodo.18749779)
222
222
  - Paper (Faceted Narrowing): [doi.org/10.5281/zenodo.19260073](https://doi.org/10.5281/zenodo.19260073)
package/build/index.js CHANGED
@@ -62,7 +62,11 @@ import { registerSelfAttestedSource, createContributionLedger, queryContribution
62
62
  // Data Lifecycle Governance (Modules 43+)
63
63
  import { createDerivationReceipt, resolveExtendedLineage, evaluateRevocationImpact, createDecisionLineageReceipt, isPurposePermitted, purposeCategory, isRetentionExpired, checkAggregateConstraints, isTransferPermitted, computeGovernanceTaint, fileDispute, checkCombinationPermitted, createAccessSnapshot, resolveRightsPropagation, DEFAULT_RIGHTS_PROPAGATION, detectPurposeDrift, declareReidentificationRisk, verifyGovernanceBlock, parseGovernanceBlockFromHTML, isUsagePermitted, embedGovernance, generateApsTxt, verifyApsTxt, resolveTermsForPath, createChainedGovernanceBlock, createAccessReceipt, governanceLoop360, } from "agent-passport-system";
64
64
  // Rome-Complete: Charter, Approval, Time, Reserve, Federation
65
- import { createCharter, signCharter, verifyCharter, evaluateThreshold, createApprovalRequest, addApprovalSignature, createHybridTimestamp, compareTimestamps, validateTemporalRights, createReserveAttestation, vouchReputation, applyReputationDowngrade, } from "agent-passport-system";
65
+ import { createCharter, signCharter, verifyCharter, evaluateThreshold, createApprovalRequest, addApprovalSignature, createHybridTimestamp, compareTimestamps, validateTemporalRights, createReserveAttestation, vouchReputation, applyReputationDowngrade,
66
+ // v2 boundary primitives (AttributionConsent, ProvisionalStatement, HumanEscalationFlag)
67
+ createAttributionReceipt, signAttributionConsent, verifyAttributionConsent, checkArtifactCitations, receiptCore, createProvisional, promoteStatement, verifyPromotion, withdrawProvisional, withdrawalPayload, isBinding, checkEscalationRequired, requestOwnerConfirmation, recordOwnerConfirmation,
68
+ // Attribution Primitive (unified four-axis signed Merkle receipt)
69
+ computeAttributionActionRef, constructAttributionPrimitive, projectAttribution, verifyAttributionProjection, verifyAttributionPrimitive, checkProjectionConsistency, } from "agent-passport-system";
66
70
  // ═══════════════════════════════════════
67
71
  // State Management
68
72
  // ═══════════════════════════════════════
@@ -454,6 +458,10 @@ const TOOL_PROFILES = {
454
458
  'create_agent_context', 'execute_with_context',
455
459
  'commerce_preflight', 'get_commerce_spend', 'request_human_approval',
456
460
  'resolve_authority', 'check_tier', 'rotate_key',
461
+ // v2 boundary primitives — most-used entry points
462
+ 'aps_create_attribution_receipt',
463
+ 'aps_create_provisional',
464
+ 'aps_check_escalation_required',
457
465
  ]),
458
466
  };
459
467
  const activeProfile = (process.env.APS_PROFILE || 'full').toLowerCase();
@@ -631,6 +639,25 @@ const TOOL_SCOPE_MAP = {
631
639
  'compare_timestamps': 'temporal',
632
640
  'validate_temporal_rights': 'temporal',
633
641
  'create_reserve_attestation': 'temporal',
642
+ // v2 boundary primitives
643
+ 'aps_create_attribution_receipt': 'governance',
644
+ 'aps_sign_attribution_consent': 'governance',
645
+ 'aps_verify_attribution_consent': 'governance',
646
+ 'aps_check_artifact_citations': 'governance',
647
+ 'aps_attribution_receipt_id': 'governance',
648
+ 'aps_create_provisional': 'coordination',
649
+ 'aps_promote_statement': 'coordination',
650
+ 'aps_verify_promotion': 'coordination',
651
+ 'aps_withdraw_provisional': 'coordination',
652
+ 'aps_check_escalation_required': 'delegation',
653
+ 'aps_record_owner_confirmation': 'delegation',
654
+ // Attribution Primitive (unified four-axis signed Merkle receipt)
655
+ 'aps_construct_attribution_primitive': 'governance',
656
+ 'aps_project_attribution': 'governance',
657
+ 'aps_verify_attribution_projection': 'governance',
658
+ 'aps_verify_attribution_primitive': 'governance',
659
+ 'aps_check_projection_consistency': 'governance',
660
+ 'aps_compute_attribution_action_ref': 'identity',
634
661
  };
635
662
  // ═══════════════════════════════════════
636
663
  // TOOL: list_profiles
@@ -4532,6 +4559,297 @@ server.tool("is_key_active", "Check if a public key is currently authorized for
4532
4559
  const active = isKeyActive(doc, args.public_key);
4533
4560
  return { content: [{ type: "text", text: `${active ? '✅ Active' : '🔒 Inactive/Retired'}\n\nKey: ${args.public_key.slice(0, 16)}...\nDID: ${doc.id || 'unknown'}\nVerification methods: ${doc.verificationMethod.length}\nRotation log entries: ${(doc.rotationLog || []).length}` }] };
4534
4561
  });
4562
+ // ═══════════════════════════════════════════════════════════════
4563
+ // v2 Boundary Primitives — AttributionConsent, ProvisionalStatement,
4564
+ // HumanEscalationFlag. Representation, commitment, escalation boundaries.
4565
+ // ═══════════════════════════════════════════════════════════════
4566
+ // ── AttributionConsent (representation boundary) ────────────────
4567
+ server.tool("aps_create_attribution_receipt", "Representation boundary: build a citer-signed AttributionReceipt attributing a claim to a third-party principal. The receipt is not yet valid — the cited principal must sign consent via aps_sign_attribution_consent before checkArtifactCitations accepts it.", {
4568
+ citer: z.string().describe("DID/public key of the citing agent"),
4569
+ citer_public_key: z.string().describe("Hex public key of citer"),
4570
+ citer_private_key: z.string().describe("Hex private key of citer"),
4571
+ cited_principal: z.string().describe("DID/public key of the cited principal"),
4572
+ cited_principal_public_key: z.string().describe("Hex public key of cited principal"),
4573
+ citation_content: z.string().describe("The quoted or paraphrased claim"),
4574
+ binding_context: z.string().describe("ID of the binding artifact this citation is scoped to"),
4575
+ gateway_id: z.string().optional().describe("Gateway id for timestamping (default: 'mcp')"),
4576
+ ttl_ms: z.number().optional().describe("Receipt TTL in ms (default: 24h)"),
4577
+ }, async (args) => {
4578
+ try {
4579
+ const gw = args.gateway_id ?? 'mcp';
4580
+ const ttl = args.ttl_ms ?? 24 * 3600_000;
4581
+ const created_at = createHybridTimestamp(gw);
4582
+ const expires_at = createHybridTimestamp(gw);
4583
+ expires_at.wallClockEarliest = created_at.wallClockEarliest + ttl;
4584
+ expires_at.wallClockLatest = created_at.wallClockLatest + ttl;
4585
+ const receipt = createAttributionReceipt({
4586
+ citer: args.citer,
4587
+ citer_public_key: args.citer_public_key,
4588
+ citer_private_key: args.citer_private_key,
4589
+ cited_principal: args.cited_principal,
4590
+ cited_principal_public_key: args.cited_principal_public_key,
4591
+ citation_content: args.citation_content,
4592
+ binding_context: args.binding_context,
4593
+ created_at, expires_at,
4594
+ });
4595
+ return { content: [{ type: "text", text: JSON.stringify(receipt, null, 2) }] };
4596
+ }
4597
+ catch (e) {
4598
+ return { content: [{ type: "text", text: safeError("createAttributionReceipt failed", e) }], isError: true };
4599
+ }
4600
+ });
4601
+ server.tool("aps_sign_attribution_consent", "Representation boundary: the cited principal adds their consent signature to an AttributionReceipt. Without this signature, verifyAttributionConsent and checkArtifactCitations reject the receipt.", {
4602
+ receipt: z.any().describe("AttributionReceipt JSON from aps_create_attribution_receipt"),
4603
+ cited_principal_private_key: z.string().describe("Hex private key of cited principal"),
4604
+ }, async (args) => {
4605
+ try {
4606
+ const signed = signAttributionConsent(args.receipt, args.cited_principal_private_key);
4607
+ return { content: [{ type: "text", text: JSON.stringify(signed, null, 2) }] };
4608
+ }
4609
+ catch (e) {
4610
+ return { content: [{ type: "text", text: safeError("signAttributionConsent failed", e) }], isError: true };
4611
+ }
4612
+ });
4613
+ server.tool("aps_verify_attribution_consent", "Representation boundary: verify an AttributionReceipt end-to-end (id, citer signature, consent signature, expiry). Returns {valid, reason?}.", {
4614
+ receipt: z.any().describe("AttributionReceipt JSON"),
4615
+ now: z.any().optional().describe("Optional HybridTimestamp to pin the evaluation moment"),
4616
+ }, async (args) => {
4617
+ const result = verifyAttributionConsent(args.receipt, args.now);
4618
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
4619
+ });
4620
+ server.tool("aps_check_artifact_citations", "Representation boundary: gate a binding artifact's citations. Each citation must resolve to a provided, signed, unexpired receipt whose content + principal match, with per-artifact replay protection.", {
4621
+ artifact: z.any().describe("CitingArtifact with optional citations[] array"),
4622
+ receipts: z.array(z.any()).describe("AttributionReceipts backing each citation"),
4623
+ binding_context: z.string().optional().describe("Require receipts to be scoped to this binding context"),
4624
+ }, async (args) => {
4625
+ const opts = {};
4626
+ if (args.binding_context)
4627
+ opts.binding_context = args.binding_context;
4628
+ const result = checkArtifactCitations(args.artifact, args.receipts, opts);
4629
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
4630
+ });
4631
+ server.tool("aps_attribution_receipt_id", "Representation boundary helper: compute the canonical sha256 id of an AttributionReceipt's unsigned core. Verifiers use this to detect id tampering.", {
4632
+ receipt: z.any().describe("AttributionReceipt JSON (signatures ignored)"),
4633
+ }, async (args) => {
4634
+ const { createHash } = await import('crypto');
4635
+ const core = receiptCore(args.receipt);
4636
+ const id = createHash('sha256').update(core).digest('hex');
4637
+ return { content: [{ type: "text", text: JSON.stringify({ id, core_bytes: core.length }, null, 2) }] };
4638
+ });
4639
+ // ── ProvisionalStatement (commitment boundary) ──────────────────
4640
+ server.tool("aps_create_provisional", "Commitment boundary: emit a provisional statement for agent-to-agent negotiation. Default is non-binding until a PromotionEvent satisfies a PromotionPolicy. Dead-man expiry auto-withdraws.", {
4641
+ author: z.string().describe("AgentDID/public key of the emitting agent"),
4642
+ author_principal: z.string().describe("PrincipalDID behind the author"),
4643
+ content: z.string().describe("Statement content (offer, position, claim)"),
4644
+ author_private_key: z.string().describe("Hex private key of author for signing"),
4645
+ gateway_id: z.string().optional().describe("Gateway id for timestamping (default: 'mcp')"),
4646
+ dead_man_ms: z.number().optional().describe("Dead-man expiry relative to now (ms). If elapsed without promotion/withdrawal, statement auto-withdraws."),
4647
+ }, async (args) => {
4648
+ try {
4649
+ const gw = args.gateway_id ?? 'mcp';
4650
+ let dead_man_expires_at;
4651
+ if (typeof args.dead_man_ms === 'number') {
4652
+ const dm = createHybridTimestamp(gw);
4653
+ dm.wallClockEarliest += args.dead_man_ms;
4654
+ dm.wallClockLatest += args.dead_man_ms;
4655
+ dead_man_expires_at = dm;
4656
+ }
4657
+ const statement = createProvisional({
4658
+ author: args.author,
4659
+ author_principal: args.author_principal,
4660
+ content: args.content,
4661
+ authorPrivateKey: args.author_private_key,
4662
+ gatewayId: gw,
4663
+ ...(dead_man_expires_at ? { dead_man_expires_at } : {}),
4664
+ });
4665
+ return { content: [{ type: "text", text: JSON.stringify(statement, null, 2) }] };
4666
+ }
4667
+ catch (e) {
4668
+ return { content: [{ type: "text", text: safeError("createProvisional failed", e) }], isError: true };
4669
+ }
4670
+ });
4671
+ server.tool("aps_promote_statement", "Commitment boundary: promote a provisional statement to binding by attaching a PromotionEvent that satisfies the PromotionPolicy (m-of-n principal signatures). dead_man_elapsed cannot promote — it auto-withdraws via the dead-man path.", {
4672
+ statement: z.any().describe("ProvisionalStatement from aps_create_provisional"),
4673
+ promotion_event: z.any().describe("PromotionEvent with kind, promoted_at, promoter, promoter_signature, policy_reference"),
4674
+ policy: z.any().describe("PromotionPolicy {id, required_signers, threshold, max_time_to_promote}"),
4675
+ }, async (args) => {
4676
+ try {
4677
+ const promoted = promoteStatement(args.statement, args.promotion_event, args.policy);
4678
+ return { content: [{ type: "text", text: JSON.stringify({ promoted, is_binding: isBinding(promoted) }, null, 2) }] };
4679
+ }
4680
+ catch (e) {
4681
+ return { content: [{ type: "text", text: safeError("promoteStatement failed", e) }], isError: true };
4682
+ }
4683
+ });
4684
+ server.tool("aps_verify_promotion", "Commitment boundary: verify that a promoted statement's PromotionEvent cryptographically satisfies the PromotionPolicy (policy_reference match, promoter in required_signers, threshold, signature, max_time_to_promote, author-signature tamper check).", {
4685
+ statement: z.any().describe("Promoted ProvisionalStatement"),
4686
+ policy: z.any().describe("PromotionPolicy to check against"),
4687
+ }, async (args) => {
4688
+ const result = verifyPromotion(args.statement, args.policy);
4689
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
4690
+ });
4691
+ server.tool("aps_withdraw_provisional", "Commitment boundary: author withdraws their own provisional statement. Already-promoted statements cannot be withdrawn. Caller must supply the author's signature over the withdrawal payload (canonicalize({action:'withdraw', statement_id})).", {
4692
+ statement: z.any().describe("ProvisionalStatement to withdraw"),
4693
+ author_signature: z.string().optional().describe("Hex Ed25519 signature. If omitted, provide author_private_key and the tool will sign for you."),
4694
+ author_private_key: z.string().optional().describe("If provided, tool signs the withdrawal payload with this key."),
4695
+ }, async (args) => {
4696
+ try {
4697
+ let sig = args.author_signature;
4698
+ if (!sig) {
4699
+ if (!args.author_private_key) {
4700
+ throw new Error('Supply author_signature or author_private_key');
4701
+ }
4702
+ const { sign } = await import('agent-passport-system');
4703
+ sig = sign(withdrawalPayload(args.statement.id), args.author_private_key);
4704
+ }
4705
+ const withdrawn = withdrawProvisional(args.statement, sig);
4706
+ return { content: [{ type: "text", text: JSON.stringify(withdrawn, null, 2) }] };
4707
+ }
4708
+ catch (e) {
4709
+ return { content: [{ type: "text", text: safeError("withdrawProvisional failed", e) }], isError: true };
4710
+ }
4711
+ });
4712
+ // ── HumanEscalationFlag (escalation boundary) ───────────────────
4713
+ server.tool("aps_check_escalation_required", "Escalation boundary: check whether an action on a v2 delegation requires owner confirmation before execution. Returns {required, requirement?, reason?}. Use aps_record_owner_confirmation to clear the flag when required.", {
4714
+ delegation: z.any().describe("V2Delegation with optional scope.escalation_requirements"),
4715
+ action_class: z.string().describe("Action class (e.g. 'org_creation', 'spend_above_threshold')"),
4716
+ action_details: z.any().optional().describe("Structured details; hashed for audit"),
4717
+ session_id: z.string().optional().describe("Session id (required for per_session scope)"),
4718
+ }, async (args) => {
4719
+ const check = checkEscalationRequired(args.delegation, {
4720
+ action_class: args.action_class,
4721
+ action_details: args.action_details ?? {},
4722
+ session_id: args.session_id ?? null,
4723
+ });
4724
+ return { content: [{ type: "text", text: JSON.stringify(check, null, 2) }] };
4725
+ });
4726
+ server.tool("aps_record_owner_confirmation", "Escalation boundary: owner signs an OwnerConfirmation authorizing a flagged action. Builds the ConfirmationRequest and signs it in a single call. The confirmation is bound to action_details via hash and scoped (per_action / per_session / time_window).", {
4727
+ delegation: z.any().describe("V2Delegation with escalation_requirements for this action class"),
4728
+ action_class: z.string().describe("Action class being confirmed"),
4729
+ action_details: z.any().describe("Structured action details — hashed and bound to the confirmation"),
4730
+ session_id: z.string().optional().describe("Session id (required for per_session scope)"),
4731
+ owner_private_key: z.string().describe("Hex private key of the delegation's owner (delegator)"),
4732
+ }, async (args) => {
4733
+ try {
4734
+ const request = requestOwnerConfirmation(args.delegation, {
4735
+ action_class: args.action_class,
4736
+ action_details: args.action_details ?? {},
4737
+ session_id: args.session_id ?? null,
4738
+ });
4739
+ const confirmation = recordOwnerConfirmation({
4740
+ request,
4741
+ delegation: args.delegation,
4742
+ owner_private_key: args.owner_private_key,
4743
+ });
4744
+ return { content: [{ type: "text", text: JSON.stringify({ request, confirmation }, null, 2) }] };
4745
+ }
4746
+ catch (e) {
4747
+ return { content: [{ type: "text", text: safeError("recordOwnerConfirmation failed", e) }], isError: true };
4748
+ }
4749
+ });
4750
+ // ═══════════════════════════════════════
4751
+ // Attribution Primitive — unified four-axis signed Merkle receipt
4752
+ // Spec: ATTRIBUTION-PRIMITIVE-v1.1.md. One signed object per action with
4753
+ // four axis projections (D, P, G, C) that verify independently.
4754
+ // ═══════════════════════════════════════
4755
+ server.tool("aps_construct_attribution_primitive", "Build and sign a four-axis AttributionPrimitive for an action. Axes: D (data sources), P (protocol modules), G (delegation chain), C (compute providers). Returns the complete signed object.", {
4756
+ action: z.object({
4757
+ agentId: z.string(),
4758
+ actionType: z.string(),
4759
+ params: z.record(z.any()),
4760
+ nonce: z.string(),
4761
+ }).describe("Action identity tuple; the action_ref is derived as sha256(canonical(this))"),
4762
+ axes: z.object({
4763
+ D: z.array(z.any()),
4764
+ P: z.array(z.any()),
4765
+ G: z.array(z.any()),
4766
+ C: z.array(z.any()),
4767
+ }).describe("Four-axis content. See spec §1.2 for entry shapes per axis."),
4768
+ issuer: z.string().describe("Issuer DID (gateway or agent producing the receipt)"),
4769
+ issuer_private_key: z.string().describe("Ed25519 private key hex that signs the envelope"),
4770
+ timestamp: z.string().optional().describe("ISO-8601 UTC with ms precision + Z (§2.5). Defaults to now()."),
4771
+ }, async (args) => {
4772
+ try {
4773
+ const primitive = constructAttributionPrimitive({
4774
+ action: args.action,
4775
+ axes: args.axes,
4776
+ issuer: args.issuer,
4777
+ issuerPrivateKey: args.issuer_private_key,
4778
+ timestamp: args.timestamp,
4779
+ });
4780
+ return { content: [{ type: "text", text: JSON.stringify(primitive, null, 2) }] };
4781
+ }
4782
+ catch (e) {
4783
+ return { content: [{ type: "text", text: safeError("constructAttributionPrimitive failed", e) }], isError: true };
4784
+ }
4785
+ });
4786
+ server.tool("aps_project_attribution", "Extract a single-axis projection from an AttributionPrimitive. The projection carries the axis content plus a two-hop Merkle path that lets a downstream verifier reconstruct the signed root without seeing the other three axes. axis: 'D' | 'P' | 'G' | 'C'.", {
4787
+ primitive: z.any().describe("An AttributionPrimitive (from aps_construct_attribution_primitive)"),
4788
+ axis: z.enum(["D", "P", "G", "C"]).describe("Axis to project"),
4789
+ }, async (args) => {
4790
+ try {
4791
+ const projection = projectAttribution(args.primitive, args.axis);
4792
+ return { content: [{ type: "text", text: JSON.stringify(projection, null, 2) }] };
4793
+ }
4794
+ catch (e) {
4795
+ return { content: [{ type: "text", text: safeError("projectAttribution failed", e) }], isError: true };
4796
+ }
4797
+ });
4798
+ server.tool("aps_verify_attribution_projection", "Verify a single-axis AttributionProjection under the issuer's Ed25519 public key. Returns {valid: true} or {valid: false, reason: 'INVALID_AXIS_TAG'|'MERKLE_MISMATCH'|'SIGNATURE_INVALID'|'MALFORMED'}. Verification is purely local — no other axes required.", {
4799
+ projection: z.any().describe("An AttributionProjection (from aps_project_attribution)"),
4800
+ issuer_public_key: z.string().describe("Issuer Ed25519 public key hex"),
4801
+ }, async (args) => {
4802
+ try {
4803
+ const result = verifyAttributionProjection(args.projection, args.issuer_public_key);
4804
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
4805
+ }
4806
+ catch (e) {
4807
+ return { content: [{ type: "text", text: safeError("verifyAttributionProjection failed", e) }], isError: true };
4808
+ }
4809
+ });
4810
+ server.tool("aps_verify_attribution_primitive", "End-to-end verify of a full AttributionPrimitive: constructs projections for all four axes and verifies each one. Useful as a post-construction sanity check or for verifying a primitive received from a peer.", {
4811
+ primitive: z.any().describe("An AttributionPrimitive"),
4812
+ issuer_public_key: z.string().describe("Issuer Ed25519 public key hex"),
4813
+ }, async (args) => {
4814
+ try {
4815
+ const result = verifyAttributionPrimitive(args.primitive, args.issuer_public_key);
4816
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
4817
+ }
4818
+ catch (e) {
4819
+ return { content: [{ type: "text", text: safeError("verifyAttributionPrimitive failed", e) }], isError: true };
4820
+ }
4821
+ });
4822
+ server.tool("aps_check_projection_consistency", "Cross-projection consistency check (§2.4): given two projections, confirm they originate from the same signed receipt. Returns {same_receipt: true} or {same_receipt: false, reason: 'DIFFERENT_ACTIONS'|'DIFFERENT_RECEIPTS'|'DIFFERENT_SIGNATURES'|'METADATA_MISMATCH'}.", {
4823
+ projection_a: z.any().describe("First AttributionProjection"),
4824
+ projection_b: z.any().describe("Second AttributionProjection"),
4825
+ }, async (args) => {
4826
+ try {
4827
+ const result = checkProjectionConsistency(args.projection_a, args.projection_b);
4828
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
4829
+ }
4830
+ catch (e) {
4831
+ return { content: [{ type: "text", text: safeError("checkProjectionConsistency failed", e) }], isError: true };
4832
+ }
4833
+ });
4834
+ server.tool("aps_compute_attribution_action_ref", "Derive the action_ref (hex sha256) for an action tuple. action_ref is the content-addressed anchor that all four axis projections bind to. Useful for indexing primitives by action without constructing the full primitive.", {
4835
+ agentId: z.string(),
4836
+ actionType: z.string(),
4837
+ params: z.record(z.any()),
4838
+ nonce: z.string(),
4839
+ }, async (args) => {
4840
+ try {
4841
+ const action_ref = computeAttributionActionRef({
4842
+ agentId: args.agentId,
4843
+ actionType: args.actionType,
4844
+ params: args.params,
4845
+ nonce: args.nonce,
4846
+ });
4847
+ return { content: [{ type: "text", text: JSON.stringify({ action_ref }, null, 2) }] };
4848
+ }
4849
+ catch (e) {
4850
+ return { content: [{ type: "text", text: safeError("computeAttributionActionRef failed", e) }], isError: true };
4851
+ }
4852
+ });
4535
4853
  server.prompt("coordination_role", "Get instructions for your assigned coordination role", {}, async () => {
4536
4854
  const role = state.agentRole || 'default';
4537
4855
  const instructions = ROLE_PROMPTS[role] || ROLE_PROMPTS['default'];
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "agent-passport-system-mcp",
3
- "version": "2.23.0",
3
+ "version": "2.25.0",
4
4
  "mcpName": "io.github.aeoess/agent-passport-mcp",
5
- "description": "MCP server for the Agent Passport System — enforcement infrastructure for the agent economy. 132 tools across 103 modules. Policy eval <2ms. Identity, delegation, reputation, enforcement, attestation, feeless Nano wallet, commerce. Tracks SDK v1.41.0 (2,764 tests).",
5
+ "description": "MCP server for the Agent Passport System — enforcement infrastructure for the agent economy. 149 tools across 122 modules. Policy eval <2ms. Identity, delegation, reputation, enforcement, attestation, feeless Nano wallet, commerce, attribution primitive. Tracks SDK v1.44.0 (2,910 tests).",
6
6
  "type": "module",
7
7
  "bin": {
8
8
  "agent-passport-system-mcp": "./build/bin.js",
@@ -15,6 +15,7 @@
15
15
  ],
16
16
  "scripts": {
17
17
  "build": "npx tsc && chmod 755 build/bin.js build/index.js build/setup.js",
18
+ "test": "node --test tests/",
18
19
  "watch": "tsc --watch",
19
20
  "inspector": "npx @modelcontextprotocol/inspector build/index.js",
20
21
  "prepublishOnly": "npm run build",
@@ -49,7 +50,7 @@
49
50
  "homepage": "https://github.com/aeoess/agent-passport-mcp",
50
51
  "dependencies": {
51
52
  "@modelcontextprotocol/sdk": "^1.27.1",
52
- "agent-passport-system": "^1.41.0",
53
+ "agent-passport-system": "^1.44.0",
53
54
  "zod": "^3.25.76"
54
55
  },
55
56
  "devDependencies": {