agent-passport-system-mcp 2.19.0 → 2.20.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/README.md CHANGED
@@ -10,7 +10,7 @@ MCP server for the [Agent Passport System](https://github.com/aeoess/agent-passp
10
10
 
11
11
  > **🤖 For AI agents:** If you are an agent reading this, 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). This README is designed for humans.
12
12
 
13
- **124 tools** across 63 core modules + 32 v2 constitutional governance modules (separation of powers, circuit breakers, approval fatigue detection, and more). Independently cited by [PDR in Production (Nanook & Gerundium, UBC)](https://doi.org/10.5281/zenodo.19323172). Works with any MCP client: Claude Desktop, Cursor, Windsurf, and more.
13
+ **125 tools** across 96 modules (64 core + 32 v2 constitutional governance). Separation of powers, circuit breakers, approval fatigue detection, and more. Independently cited by [PDR in Production (Nanook & Gerundium, UBC)](https://doi.org/10.5281/zenodo.19323172). Works with any MCP client: Claude Desktop, Cursor, Windsurf, and more.
14
14
 
15
15
  ## Quick Start
16
16
 
@@ -29,7 +29,7 @@ npm install -g agent-passport-system-mcp
29
29
  npx agent-passport-system-mcp setup
30
30
  ```
31
31
 
32
- Auto-configures Claude Desktop and Cursor. Restart your AI client. 124 tools ready.
32
+ Auto-configures Claude Desktop and Cursor. Restart your AI client. 125 tools ready.
33
33
 
34
34
  <details>
35
35
  <summary>Manual config (if setup doesn't detect your client)</summary>
@@ -61,7 +61,7 @@ Or for remote SSE:
61
61
  ```
62
62
  </details>
63
63
 
64
- ## Tools (63)
64
+ ## Tools (125)
65
65
 
66
66
  ### Identity (Layer 1) — 5 tools
67
67
 
@@ -208,8 +208,8 @@ Layer 1 — Agent Passport Protocol (Ed25519 identity)
208
208
 
209
209
  ## Links
210
210
 
211
- - npm SDK: [agent-passport-system](https://www.npmjs.com/package/agent-passport-system) (v1.29.1, 1919 tests)
212
- - Python SDK: [agent-passport-system](https://pypi.org/project/agent-passport-system/) (v0.5.1)
211
+ - npm SDK: [agent-passport-system](https://www.npmjs.com/package/agent-passport-system) (v1.33.0, 2230 tests)
212
+ - Python SDK: [agent-passport-system](https://pypi.org/project/agent-passport-system/) (v0.8.0)
213
213
  - Paper (Protocol): [doi.org/10.5281/zenodo.18749779](https://doi.org/10.5281/zenodo.18749779)
214
214
  - Paper (Faceted Narrowing): [doi.org/10.5281/zenodo.19260073](https://doi.org/10.5281/zenodo.19260073)
215
215
  - Docs: [aeoess.com/llms-full.txt](https://aeoess.com/llms-full.txt)
package/build/index.js CHANGED
@@ -52,7 +52,9 @@ requestV2Migration,
52
52
  // v2: Attestation
53
53
  createV2Attestation, assessV2AttestationQuality, } from "agent-passport-system";
54
54
  // Agent Attestation Architecture (Phase 1 — Consilium Build)
55
- import { createIssuanceContext, bindAttestation, createEmptyEvidenceRecord, PASSPORT_GRADE_LABELS, } from "agent-passport-system";
55
+ import { createIssuanceContext, bindAttestation, createEmptyEvidenceRecord, PASSPORT_GRADE_LABELS,
56
+ // v1.33.0 — action_ref + freshness + evidence-based grade
57
+ computeActionRef, isEvidenceFresh, computeEvidenceAge, classifyEvidenceQuality, evidenceQualityToGrade, } from "agent-passport-system";
56
58
  // Data Governance (Modules 36A, 38, 39 + Enforcement Gate + Training Attribution)
57
59
  import { registerSelfAttestedSource, createContributionLedger, queryContributions, getSourceMetrics, getAgentDataFootprint, generateSettlement, verifySettlement, generateDataComplianceReport, DataEnforcementGate, createTrainingAttribution, verifyTrainingAttribution, createTrainingLedger, recordTrainingAttribution, getModelDataSources, } from "agent-passport-system";
58
60
  // Data Lifecycle Governance (Modules 43+)
@@ -155,8 +157,26 @@ const state = {
155
157
  issuanceContexts: new Map(),
156
158
  issuanceChallenges: new Map(),
157
159
  issuanceCount: 0,
160
+ postIssuanceBehavior: new Map(),
161
+ recentlyIssuedPassports: new Set(),
162
+ issuanceTimestamps: new Map(),
163
+ endorsementLatencies: new Map(),
158
164
  };
159
165
  // Load persisted task state
166
+ // ── Post-issuance behavioral sequence recording ──
167
+ // Consilium signal #2: first 10 tool calls after passport issuance.
168
+ // Real agents do work. Farming agents extract. Server-recorded, can't retroactively change.
169
+ const MAX_BEHAVIORAL_SEQUENCE = 10;
170
+ function recordBehavior(toolName) {
171
+ // Record for all recently-issued passport holders in this session
172
+ for (const agentId of state.recentlyIssuedPassports) {
173
+ const seq = state.postIssuanceBehavior.get(agentId) || [];
174
+ if (seq.length < MAX_BEHAVIORAL_SEQUENCE) {
175
+ seq.push({ tool: toolName, ts: new Date().toISOString() });
176
+ state.postIssuanceBehavior.set(agentId, seq);
177
+ }
178
+ }
179
+ }
160
180
  function loadTasks() {
161
181
  if (existsSync(STORE_PATH)) {
162
182
  try {
@@ -450,6 +470,7 @@ server.tool("identify", "Identify yourself to the coordination server. Sets your
450
470
  private_key: z.string().describe("Your Ed25519 private key (for signing)"),
451
471
  agent_id: z.string().optional().describe("Your agent ID"),
452
472
  }, async (args) => {
473
+ recordBehavior('identify');
453
474
  state.agentKey = args.public_key;
454
475
  state.privateKey = args.private_key;
455
476
  state.agentId = args.agent_id || null;
@@ -543,16 +564,49 @@ server.tool("issue_passport", "Issue a complete agent passport with keys, signed
543
564
  const passport = hasIssuer
544
565
  ? countersignPassport(agent.passport, AEOESS_ISSUER_PRIVATE_KEY, 'aeoess')
545
566
  : agent.passport;
546
- // Phase 4: Derive issuance context
567
+ // Phase 4: Derive issuance context with computed signals
547
568
  const evidence = createEmptyEvidenceRecord(observed);
569
+ const issuanceAgeMs = Date.now() - (globalThis.__mcpStartTime || Date.now());
570
+ const derivedSignals = [
571
+ { key: 'issuance_age_ms', value: String(issuanceAgeMs), derivedFrom: ['serverStartTime', 'requestedAt'], computedAt: new Date().toISOString() },
572
+ { key: 'session_passport_count', value: String(state.issuanceCount), derivedFrom: ['issuanceCount'], computedAt: new Date().toISOString() },
573
+ ];
548
574
  const context = createIssuanceContext(evidence, {
549
575
  hasIssuerSignature: hasIssuer,
576
+ derivedSignals,
550
577
  });
551
578
  // Phase 5: Bind attestation to passport
552
579
  const attestedPassport = bindAttestation(passport, context);
553
580
  // Store the issuance context (server-side memory)
554
581
  const passportId = passport.passport.agentId;
555
582
  state.issuanceContexts.set(passportId, context);
583
+ state.recentlyIssuedPassports.add(passportId);
584
+ state.issuanceTimestamps.set(passportId, Date.now());
585
+ // Initialize behavioral sequence tracking for this agent
586
+ state.postIssuanceBehavior.set(passportId, [{ tool: 'issue_passport', ts: new Date().toISOString() }]);
587
+ // Bridge: fire-and-forget POST to gateway (if configured)
588
+ // When Mini adds POST /issuance-dossier, this data starts flowing automatically.
589
+ const gwUrl = process.env.AEOESS_GATEWAY_URL; // e.g. https://gateway.aeoess.com
590
+ const gwKey = process.env.AEOESS_GATEWAY_KEY; // e.g. aps_live_...
591
+ if (gwUrl && gwKey) {
592
+ fetch(`${gwUrl}/api/v1/issuance-dossier`, {
593
+ method: 'POST',
594
+ headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${gwKey}` },
595
+ body: JSON.stringify({
596
+ passport_id: passportId,
597
+ public_key_hash: sha256(attestedPassport.passport.publicKey),
598
+ passport_grade: context.assessment.passportGrade,
599
+ flags: context.assessment.flags,
600
+ attestation_bundle_hash: context.assessment.attestationBundleHash,
601
+ observed_context: context.evidence.observed,
602
+ runtime_attestations: context.evidence.runtimeAttestations,
603
+ provider_attestations: context.evidence.providerAttestations,
604
+ self_declared_signals: context.evidence.selfDeclaredSignals,
605
+ derived_signals: context.assessment.derivedSignals || [],
606
+ prior_passport_ref: context.evidence.priorPassportRef || null,
607
+ }),
608
+ }).catch(() => { }); // fire-and-forget: never block passport issuance
609
+ }
556
610
  return {
557
611
  content: [{
558
612
  type: "text",
@@ -686,6 +740,50 @@ server.tool("list_issuance_records", "List all stored issuance records with thei
686
740
  };
687
741
  });
688
742
  // ═══════════════════════════════════════
743
+ // TOOL: get_behavioral_sequence
744
+ // ═══════════════════════════════════════
745
+ server.tool("get_behavioral_sequence", "Get the post-issuance behavioral sequence for an agent. Shows the first 10 tool calls after passport issuance. Real agents do work. Farming agents extract. This is consilium signal #2.", {
746
+ agent_id: z.string().describe("The agent ID to query"),
747
+ }, async (args) => {
748
+ const sequence = state.postIssuanceBehavior.get(args.agent_id);
749
+ if (!sequence || sequence.length === 0) {
750
+ return {
751
+ content: [{
752
+ type: "text",
753
+ text: JSON.stringify({
754
+ agent_id: args.agent_id,
755
+ found: false,
756
+ note: "No behavioral sequence recorded. Agent may have been issued before tracking was enabled.",
757
+ }, null, 2),
758
+ }],
759
+ };
760
+ }
761
+ // Classify the behavioral pattern
762
+ const toolNames = sequence.map(s => s.tool);
763
+ const hasWork = toolNames.some(t => ['submit_evidence', 'publish_intent_card', 'create_agora_message', 'submit_deliverable'].includes(t));
764
+ const hasExtraction = toolNames.some(t => ['commerce_preflight', 'create_checkout'].includes(t));
765
+ const pattern = hasWork ? 'productive' : hasExtraction ? 'extractive' : 'neutral';
766
+ return {
767
+ content: [{
768
+ type: "text",
769
+ text: JSON.stringify({
770
+ agent_id: args.agent_id,
771
+ found: true,
772
+ sequence_length: sequence.length,
773
+ max_tracked: MAX_BEHAVIORAL_SEQUENCE,
774
+ pattern,
775
+ tools_called: toolNames,
776
+ sequence,
777
+ note: pattern === 'extractive'
778
+ ? "Agent's first actions after passport were value extraction (commerce). Farming signal."
779
+ : pattern === 'productive'
780
+ ? "Agent's first actions after passport were productive work. Healthy pattern."
781
+ : "Neutral pattern — identity/delegation setup.",
782
+ }, null, 2),
783
+ }],
784
+ };
785
+ });
786
+ // ═══════════════════════════════════════
689
787
  // TOOL: get_my_role
690
788
  // ═══════════════════════════════════════
691
789
  server.tool("get_my_role", "Get your current role, assigned tasks, and role-specific instructions.", {}, async () => {
@@ -1104,6 +1202,7 @@ server.tool("submit_evidence", "[RESEARCHER] Submit research evidence as a signe
1104
1202
  })).describe("Evidence claims with citations"),
1105
1203
  methodology: z.string().describe("How you gathered this evidence"),
1106
1204
  }, async (args) => {
1205
+ recordBehavior('submit_evidence');
1107
1206
  const keyErr = requireKey();
1108
1207
  if (keyErr)
1109
1208
  return { content: [{ type: "text", text: keyErr }], isError: true };
@@ -1320,6 +1419,7 @@ server.tool("create_delegation", "[OPERATOR] Create a scoped delegation from one
1320
1419
  max_depth: z.number().default(1).describe("How many levels of sub-delegation"),
1321
1420
  expires_in_hours: z.number().default(24).describe("Delegation validity in hours"),
1322
1421
  }, async (args) => {
1422
+ recordBehavior('create_delegation');
1323
1423
  const keyErr = requireKey();
1324
1424
  if (keyErr)
1325
1425
  return { content: [{ type: "text", text: keyErr }], isError: true };
@@ -1388,6 +1488,7 @@ server.tool("revoke_delegation", "[OPERATOR] Revoke a delegation. Optionally cas
1388
1488
  reason: z.string().describe("Why the delegation is being revoked"),
1389
1489
  cascade: z.boolean().default(true).describe("Also revoke all sub-delegations"),
1390
1490
  }, async (args) => {
1491
+ recordBehavior('revoke_delegation');
1391
1492
  const keyErr = requireKey();
1392
1493
  if (keyErr)
1393
1494
  return { content: [{ type: "text", text: keyErr }], isError: true };
@@ -1946,6 +2047,7 @@ server.tool("commerce_preflight", "Run preflight checks before a purchase. Valid
1946
2047
  delegation_id: z.string().describe("Commerce delegation ID"),
1947
2048
  agent_id: z.string().describe("Agent making the purchase"),
1948
2049
  }, async (args) => {
2050
+ recordBehavior('commerce_preflight');
1949
2051
  const keyErr = requireKey();
1950
2052
  if (keyErr)
1951
2053
  return { content: [{ type: "text", text: keyErr }], isError: true };
@@ -2236,6 +2338,12 @@ server.tool("endorse_agent", "Endorse an agent as a principal. Creates a cryptog
2236
2338
  relationship: z.enum(["creator", "operator", "employer", "sponsor"]).describe("How principal relates to agent"),
2237
2339
  expires_in_days: z.number().default(365).describe("Days until endorsement expires"),
2238
2340
  }, async (args) => {
2341
+ recordBehavior('endorse_agent');
2342
+ // Consilium signal #5: endorsement latency. T+200ms = automation. T+3h = human.
2343
+ const issuedAt = state.issuanceTimestamps.get(args.agent_id);
2344
+ if (issuedAt && !state.endorsementLatencies.has(args.agent_id)) {
2345
+ state.endorsementLatencies.set(args.agent_id, Date.now() - issuedAt);
2346
+ }
2239
2347
  if (!state.principal || !state.principalPrivateKey) {
2240
2348
  return { content: [{ type: "text", text: 'No principal identity. Call create_principal first.' }], isError: true };
2241
2349
  }
@@ -2792,6 +2900,7 @@ server.tool("publish_intent_card", "Publish an IntentCard to the Intent Network
2792
2900
  visibility: z.enum(["public", "verified", "minimal"]).default("public"),
2793
2901
  ttl_hours: z.number().default(24).describe("Hours until card expires"),
2794
2902
  }, async (args) => {
2903
+ recordBehavior('publish_intent_card');
2795
2904
  const keyErr = requireKey();
2796
2905
  if (keyErr)
2797
2906
  return { content: [{ type: "text", text: keyErr }], isError: true };
@@ -4118,6 +4227,55 @@ server.tool("apply_reputation_downgrade", "Apply import policy downgrade to a fo
4118
4227
  const result = applyReputationDowngrade(rep, policy);
4119
4228
  return { content: [{ type: "text", text: `🌐 Reputation Downgrade\n\nAccepted: ${result.accepted}\nOriginal tier: ${args.attested_tier} → Effective: ${result.effectiveTier}\nOriginal diversity: ${args.attested_diversity_score} → Effective: ${result.effectiveDiversity.toFixed(2)}\nDowngrade ratio: ${args.downgrade_ratio}` }] };
4120
4229
  });
4230
+ // ═══════════════════════════════════════
4231
+ // v1.33.0 — action_ref + freshness + evidence-based grade
4232
+ // ═══════════════════════════════════════
4233
+ server.tool("compute_action_ref", "Compute content-addressed request identity (SHA-256 of agentId + actionType + scope + normalized timestamp). Two receipts with the same action_ref describe the same request.", {
4234
+ agent_id: z.string(),
4235
+ action_type: z.string(),
4236
+ scope_required: z.array(z.string()),
4237
+ timestamp: z.string().optional().describe("ISO 8601 timestamp; defaults to now"),
4238
+ }, async (args) => {
4239
+ const intent = {
4240
+ agentId: args.agent_id,
4241
+ action: { type: args.action_type, scopeRequired: args.scope_required },
4242
+ createdAt: args.timestamp ?? new Date().toISOString(),
4243
+ };
4244
+ const ref = computeActionRef(intent);
4245
+ return { content: [{ type: "text", text: `🔗 action_ref: ${ref}\n\nAgent: ${args.agent_id}\nType: ${args.action_type}\nScope: ${args.scope_required.join(', ')}\nTimestamp: ${intent.createdAt}` }] };
4246
+ });
4247
+ server.tool("is_evidence_fresh", "Check whether typed attestation evidence is still fresh. rotating: ttl required; snapshot: maxAge optional; static: always fresh.", {
4248
+ type: z.enum(['rotating', 'snapshot', 'static']),
4249
+ valid_at: z.string().describe("ISO 8601 timestamp evidence was produced"),
4250
+ ttl: z.number().optional().describe("Seconds (required for rotating)"),
4251
+ max_age: z.number().optional().describe("Seconds (optional for snapshot)"),
4252
+ now: z.string().optional().describe("ISO 8601 override for current time"),
4253
+ }, async (args) => {
4254
+ const freshness = { type: args.type, validAt: args.valid_at };
4255
+ if (args.ttl !== undefined)
4256
+ freshness.ttl = args.ttl;
4257
+ if (args.max_age !== undefined)
4258
+ freshness.maxAge = args.max_age;
4259
+ const nowDate = args.now ? new Date(args.now) : undefined;
4260
+ const fresh = isEvidenceFresh(freshness, nowDate);
4261
+ const ageSec = computeEvidenceAge(freshness, nowDate);
4262
+ return { content: [{ type: "text", text: `${fresh ? '✅' : '❌'} Evidence fresh: ${fresh}\n\nType: ${args.type}\nValid at: ${args.valid_at}\nAge: ${ageSec}s${args.ttl !== undefined ? `\nTTL: ${args.ttl}s` : ''}${args.max_age !== undefined ? `\nMax age: ${args.max_age}s` : ''}` }] };
4263
+ });
4264
+ server.tool("classify_evidence_quality", "Classify attestation evidence quality (none / issuer_vouched / infrastructure / principal_bound) and return the corresponding grade (0-3).", {
4265
+ method: z.string().optional().describe("Attestation method (e.g. 'spiffe')"),
4266
+ has_issuer_signature: z.boolean().optional(),
4267
+ has_principal_binding: z.boolean().optional(),
4268
+ evidence: z.record(z.any()).optional().describe("Evidence object (checked for known infrastructure keys)"),
4269
+ }, async (args) => {
4270
+ const quality = classifyEvidenceQuality({
4271
+ method: args.method,
4272
+ hasIssuerSignature: args.has_issuer_signature,
4273
+ hasPrincipalBinding: args.has_principal_binding,
4274
+ evidence: args.evidence,
4275
+ });
4276
+ const grade = evidenceQualityToGrade(quality);
4277
+ return { content: [{ type: "text", text: `🎖️ Evidence Quality: ${quality}\nGrade: ${grade}\n\nInputs:\n method: ${args.method ?? 'none'}\n issuerSignature: ${args.has_issuer_signature ?? false}\n principalBinding: ${args.has_principal_binding ?? false}\n evidence keys: ${args.evidence ? Object.keys(args.evidence).join(', ') || '(empty)' : '(none)'}` }] };
4278
+ });
4121
4279
  server.prompt("coordination_role", "Get instructions for your assigned coordination role", {}, async () => {
4122
4280
  const role = state.agentRole || 'default';
4123
4281
  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.19.0",
3
+ "version": "2.20.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. 124 tools across 95 modules. Policy eval <2ms. Identity, delegation, reputation, enforcement, attestation, feeless Nano wallet, commerce.",
5
+ "description": "MCP server for the Agent Passport System — enforcement infrastructure for the agent economy. 128 tools across 103 modules. Policy eval <2ms. Identity, delegation, reputation, enforcement, attestation, feeless Nano wallet, commerce.",
6
6
  "type": "module",
7
7
  "bin": {
8
8
  "agent-passport-system-mcp": "./build/bin.js",
@@ -49,7 +49,7 @@
49
49
  "homepage": "https://github.com/aeoess/agent-passport-mcp",
50
50
  "dependencies": {
51
51
  "@modelcontextprotocol/sdk": "^1.27.1",
52
- "agent-passport-system": "^1.29.1",
52
+ "agent-passport-system": "^1.33.0",
53
53
  "zod": "^3.25.76"
54
54
  },
55
55
  "devDependencies": {