agent-passport-system-mcp 2.5.0 → 2.7.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.
@@ -0,0 +1,36 @@
1
+ # Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We are committed to making participation in this project a welcoming experience for everyone.
6
+
7
+ ## Standards
8
+
9
+ Examples of positive behavior:
10
+
11
+ - Using inclusive language
12
+ - Being respectful of differing viewpoints
13
+ - Accepting constructive feedback gracefully
14
+ - Focusing on what is best for the community
15
+
16
+ Examples of unacceptable behavior:
17
+
18
+ - Personal attacks or derogatory comments
19
+ - Publishing others' private information without permission
20
+ - Other conduct which could reasonably be considered inappropriate in a professional setting
21
+
22
+ ## Responsibilities
23
+
24
+ Project maintainers are responsible for clarifying standards of acceptable behavior and are expected to take fair corrective action in response to any instances of unacceptable behavior.
25
+
26
+ ## Scope
27
+
28
+ This Code of Conduct applies within all project spaces, including issues, pull requests, and community discussions.
29
+
30
+ ## Enforcement
31
+
32
+ Instances of unacceptable behavior may be reported by contacting the project maintainer. All reports will be reviewed and investigated promptly and fairly.
33
+
34
+ ## Attribution
35
+
36
+ This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 2.1.
@@ -0,0 +1,58 @@
1
+ # Contributing to Agent Passport System MCP Server
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.
4
+
5
+ ## Getting Started
6
+
7
+ 1. Fork the repository
8
+ 2. Clone your fork: `git clone https://github.com/<your-username>/agent-passport-mcp.git`
9
+ 3. Install dependencies: `npm install --include=dev`
10
+ 4. Build the project: `npm run build`
11
+
12
+ ## Development
13
+
14
+ The MCP server is a single-file TypeScript implementation (`src/index.ts`) that wraps the Agent Passport System SDK. All protocol logic lives in the SDK; this repo provides the MCP tool interface.
15
+
16
+ ### Building
17
+
18
+ ```bash
19
+ npm run build
20
+ ```
21
+
22
+ Build must succeed with zero TypeScript errors before submitting a PR.
23
+
24
+ ### Code Style
25
+
26
+ - TypeScript throughout
27
+ - Single-file architecture (`src/index.ts`)
28
+ - Each MCP tool follows the same pattern: validation, SDK call, JSON response
29
+ - Use `zod` for input validation
30
+
31
+ ## Submitting Changes
32
+
33
+ 1. Create a feature branch from `main`
34
+ 2. Make your changes with clear, descriptive commits
35
+ 3. Ensure `npm run build` succeeds with zero errors
36
+ 4. Open a pull request with a description of what you changed and why
37
+
38
+ ## Reporting Issues
39
+
40
+ Open an issue on GitHub with:
41
+
42
+ - A clear title and description
43
+ - Steps to reproduce (if applicable)
44
+ - Expected vs actual behavior
45
+ - Your environment (Node.js version, OS, MCP client)
46
+
47
+ ## Adding New Tools
48
+
49
+ If you're adding new MCP tools, follow the existing pattern in `src/index.ts`:
50
+
51
+ 1. Add the SDK import
52
+ 2. Register the tool with `server.tool()` including zod schema
53
+ 3. Update the README tool table
54
+ 4. Update the tool count in the README header
55
+
56
+ ## License
57
+
58
+ By contributing, you agree that your contributions will be licensed under the project's Apache-2.0 license.
package/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  MCP server for the [Agent Passport System](https://github.com/aeoess/agent-passport-system) — cryptographic identity, delegation, governance, and commerce for AI agents.
10
10
 
11
- **49 tools** across all 8 protocol layers. Works with any MCP client: Claude Desktop, Cursor, Windsurf, and more.
11
+ **61 tools** across all 16 protocol modules. Works with any MCP client: Claude Desktop, Cursor, Windsurf, and more.
12
12
 
13
13
  ## Quick Start
14
14
 
@@ -148,6 +148,38 @@ Add to your MCP config:
148
148
  | `create_disclosure` | Selective disclosure of principal identity (public/verified-only/minimal) |
149
149
  | `get_fleet_status` | Status of all agents endorsed by the current principal |
150
150
 
151
+ ### Reputation-Gated Authority — 5 tools
152
+
153
+ | Tool | Description |
154
+ |------|-------------|
155
+ | `resolve_authority` | Compute effective reputation score and authority tier for an agent |
156
+ | `check_tier` | Check if agent's earned tier permits action at given autonomy/spend |
157
+ | `review_promotion` | Create signed promotion review (earned-only reviewers, no self-promotion) |
158
+ | `update_reputation` | Bayesian (mu, sigma) updates from task results |
159
+ | `get_promotion_history` | List all promotion reviews this session |
160
+
161
+ ### Proxy Gateway — 6 tools
162
+
163
+ | Tool | Description |
164
+ |------|-------------|
165
+ | `gateway_create` | Create a ProxyGateway with enforcement config and tool executor |
166
+ | `gateway_register_agent` | Register agent (passport + attestation + delegations) with gateway |
167
+ | `gateway_process` | Execute tool call through full enforcement pipeline (identity → scope → policy → execute → receipt) |
168
+ | `gateway_approve` | Two-phase: approve request without executing (returns approval token) |
169
+ | `gateway_execute` | Two-phase: execute previously approved request (rechecks revocation) |
170
+ | `gateway_stats` | Get gateway counters (requests, permits, denials, replays, revocation rechecks) |
171
+
172
+ ### Intent Network (Agent-Mediated Matching) — 6 tools
173
+
174
+ | Tool | Description |
175
+ |------|-------------|
176
+ | `publish_intent_card` | Publish what your human needs, offers, and is open to. Signed, scoped, auto-expiring |
177
+ | `search_matches` | Find relevant IntentCards — ranked by need/offer overlap, tags, budget compatibility |
178
+ | `get_digest` | "What matters to me right now?" — matches, pending intros, incoming requests |
179
+ | `request_intro` | Propose connecting two humans based on a match. Both sides must approve |
180
+ | `respond_to_intro` | Approve or decline an introduction request |
181
+ | `remove_intent_card` | Remove your card when needs/offers change |
182
+
151
183
  ## Architecture
152
184
 
153
185
  ```
@@ -163,7 +195,7 @@ Layer 1 — Agent Passport Protocol (Ed25519 identity)
163
195
 
164
196
  ## Links
165
197
 
166
- - npm SDK: [agent-passport-system](https://www.npmjs.com/package/agent-passport-system) (v1.11.0, 470 tests)
198
+ - npm SDK: [agent-passport-system](https://www.npmjs.com/package/agent-passport-system) (v1.13.0, 534 tests)
167
199
  - Python SDK: [agent-passport-system](https://pypi.org/project/agent-passport-system/) (v0.4.0, 86 tests)
168
200
  - Paper: [doi.org/10.5281/zenodo.18749779](https://doi.org/10.5281/zenodo.18749779)
169
201
  - Docs: [aeoess.com/llms-full.txt](https://aeoess.com/llms-full.txt)
package/build/index.js CHANGED
@@ -33,7 +33,9 @@ commercePreflight, createCommerceDelegation, getSpendSummary, requestHumanApprov
33
33
  // Principal Identity
34
34
  createPrincipalIdentity, endorseAgent, verifyEndorsement, revokeEndorsement, createDisclosure, createFleet, addToFleet, getFleetStatus, revokeFromFleet,
35
35
  // Reputation-Gated Authority (Layer 9)
36
- computeEffectiveScore, createScopedReputation, resolveAuthorityTier, checkTierForIntent, advisoryTierPrecheck, createPromotionReview, updateReputationFromResult, DEFAULT_TIERS, } from "agent-passport-system";
36
+ computeEffectiveScore, createScopedReputation, resolveAuthorityTier, checkTierForIntent, advisoryTierPrecheck, createPromotionReview, updateReputationFromResult, DEFAULT_TIERS, createProxyGateway,
37
+ // Intent Network (Agent-Mediated Matching)
38
+ createIntentNetwork, createIntentCard, publishCard, removeCard, searchMatches, requestIntro, respondToIntro, getDigest, } from "agent-passport-system";
37
39
  // ═══════════════════════════════════════
38
40
  // State Management
39
41
  // ═══════════════════════════════════════
@@ -64,6 +66,9 @@ const state = {
64
66
  fleet: null,
65
67
  reputations: new Map(),
66
68
  promotionHistory: [],
69
+ gateway: null,
70
+ gatewayKeys: null,
71
+ intentNetwork: createIntentNetwork(),
67
72
  };
68
73
  // Load persisted task state
69
74
  function loadTasks() {
@@ -2112,6 +2117,451 @@ server.tool("get_promotion_history", "Get the promotion review history for this
2112
2117
  };
2113
2118
  });
2114
2119
  // ═══════════════════════════════════════
2120
+ // Proxy Gateway (Enforcement Boundary)
2121
+ // ═══════════════════════════════════════
2122
+ server.tool("create_gateway", "Create a ProxyGateway enforcement boundary. The gateway validates identity, delegation scope, policy compliance, and provides replay protection for every tool call. Returns gateway ID and public key.", {
2123
+ gatewayId: z.string().optional().describe("Custom gateway ID (auto-generated if omitted)"),
2124
+ approvalTTLSeconds: z.number().optional().describe("Two-phase approval timeout in seconds (default: 300)"),
2125
+ maxPendingPerAgent: z.number().optional().describe("Max pending approvals per agent (default: 10)"),
2126
+ }, async ({ gatewayId, approvalTTLSeconds, maxPendingPerAgent }) => {
2127
+ const keys = generateKeyPair();
2128
+ const id = gatewayId || `gateway-${Date.now().toString(36)}`;
2129
+ if (!state.floor) {
2130
+ return { content: [{ type: "text", text: "Error: Load a Values Floor first (load_values_floor)" }] };
2131
+ }
2132
+ const config = {
2133
+ gatewayId: id,
2134
+ gatewayPublicKey: keys.publicKey,
2135
+ gatewayPrivateKey: keys.privateKey,
2136
+ floor: state.floor,
2137
+ approvalTTLSeconds: approvalTTLSeconds ?? 300,
2138
+ maxPendingPerAgent: maxPendingPerAgent ?? 10,
2139
+ recheckRevocationOnExecute: true,
2140
+ };
2141
+ // Default executor echoes tool calls — real execution is done by MCP client
2142
+ const executor = async (tool, params) => {
2143
+ return { success: true, result: { tool, params, executedVia: 'mcp-gateway' } };
2144
+ };
2145
+ state.gateway = createProxyGateway(config, executor);
2146
+ state.gatewayKeys = keys;
2147
+ return {
2148
+ content: [{
2149
+ type: "text",
2150
+ text: JSON.stringify({
2151
+ created: true,
2152
+ gatewayId: id,
2153
+ publicKey: keys.publicKey,
2154
+ approvalTTLSeconds: config.approvalTTLSeconds,
2155
+ maxPendingPerAgent: config.maxPendingPerAgent,
2156
+ note: "Gateway ready. Register agents with register_gateway_agent, then process calls with gateway_process_tool_call.",
2157
+ }, null, 2),
2158
+ }],
2159
+ };
2160
+ });
2161
+ server.tool("register_gateway_agent", "Register an agent with the gateway. The agent must have a valid passport and floor attestation. Delegations define what scopes the agent can use through the gateway.", {
2162
+ agentId: z.string().describe("Agent ID to register"),
2163
+ }, async ({ agentId }) => {
2164
+ if (!state.gateway) {
2165
+ return { content: [{ type: "text", text: "Error: Create gateway first (create_gateway)" }] };
2166
+ }
2167
+ const agent = state.agents.get(agentId);
2168
+ if (!agent) {
2169
+ return { content: [{ type: "text", text: `Error: Agent "${agentId}" not found in session. Join social contract first.` }] };
2170
+ }
2171
+ const agentDelegations = Array.from(state.delegations.values()).filter(d => d.delegatedTo === agent.publicKey);
2172
+ if (agentDelegations.length === 0) {
2173
+ return { content: [{ type: "text", text: `Error: No delegations found for agent "${agentId}". Create a delegation first.` }] };
2174
+ }
2175
+ if (!agent.attestation) {
2176
+ return { content: [{ type: "text", text: `Error: Agent "${agentId}" has no floor attestation. Attest to floor first.` }] };
2177
+ }
2178
+ state.gateway.registerAgent(agent.passport, agent.attestation, agentDelegations);
2179
+ return {
2180
+ content: [{
2181
+ type: "text",
2182
+ text: JSON.stringify({
2183
+ registered: true,
2184
+ agentId,
2185
+ delegationCount: agentDelegations.length,
2186
+ scopes: agentDelegations.flatMap(d => d.scope),
2187
+ }, null, 2),
2188
+ }],
2189
+ };
2190
+ });
2191
+ server.tool("gateway_process_tool_call", "Process a tool call through the gateway enforcement boundary. Validates identity, delegation, policy, and replay protection in a single atomic operation. Returns execution result with full 3-signature proof chain.", {
2192
+ agentId: z.string().describe("ID of the requesting agent"),
2193
+ tool: z.string().describe("Tool name to execute"),
2194
+ params: z.record(z.unknown()).optional().describe("Tool parameters"),
2195
+ scopeRequired: z.string().describe("Delegation scope needed for this tool"),
2196
+ spendAmount: z.number().optional().describe("Spend amount if commerce action"),
2197
+ spendCurrency: z.string().optional().describe("Currency code (e.g. USD)"),
2198
+ context: z.string().optional().describe("Human-readable context for audit"),
2199
+ }, async ({ agentId, tool, params, scopeRequired, spendAmount, spendCurrency, context }) => {
2200
+ if (!state.gateway) {
2201
+ return { content: [{ type: "text", text: "Error: Create gateway first (create_gateway)" }] };
2202
+ }
2203
+ const agent = state.agents.get(agentId);
2204
+ if (!agent) {
2205
+ return { content: [{ type: "text", text: `Error: Agent "${agentId}" not found in session.` }] };
2206
+ }
2207
+ const { canonicalize } = await import("agent-passport-system");
2208
+ const requestId = `mcp-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
2209
+ const payload = canonicalize({ requestId, agentId, tool, params: params || {}, scopeRequired, spend: spendAmount ? { amount: spendAmount, currency: spendCurrency || 'USD' } : undefined });
2210
+ const request = {
2211
+ requestId,
2212
+ agentId,
2213
+ agentPublicKey: agent.publicKey,
2214
+ signature: sign(payload, agent.keyPair.privateKey),
2215
+ tool,
2216
+ params: params || {},
2217
+ scopeRequired,
2218
+ spend: spendAmount ? { amount: spendAmount, currency: spendCurrency || 'USD' } : undefined,
2219
+ context,
2220
+ };
2221
+ const result = await state.gateway.processToolCall(request);
2222
+ return {
2223
+ content: [{
2224
+ type: "text",
2225
+ text: JSON.stringify({
2226
+ executed: result.executed,
2227
+ requestId: result.requestId,
2228
+ result: result.result ?? undefined,
2229
+ denialReason: result.denialReason ?? undefined,
2230
+ toolError: result.toolError ?? undefined,
2231
+ ...(result.decision && { verdict: result.decision.verdict, reason: result.decision.reason }),
2232
+ ...(result.proof && {
2233
+ proof: {
2234
+ hasRequestSignature: !!result.proof.requestSignature,
2235
+ hasDecisionSignature: !!result.proof.decisionSignature,
2236
+ hasReceiptSignature: !!result.proof.receiptSignature,
2237
+ policyReceiptId: result.proof.policyReceipt?.policyReceiptId,
2238
+ },
2239
+ }),
2240
+ ...(result.receipt && {
2241
+ receipt: {
2242
+ receiptId: result.receipt.receiptId,
2243
+ agentId: result.receipt.agentId,
2244
+ action: result.receipt.action,
2245
+ },
2246
+ }),
2247
+ }, null, 2),
2248
+ }],
2249
+ };
2250
+ });
2251
+ server.tool("gateway_approve", "Two-phase execution: approve a tool call without executing it. Returns an approval ID that can be executed later with gateway_execute_approval. Useful for human-in-the-loop workflows.", {
2252
+ agentId: z.string().describe("ID of the requesting agent"),
2253
+ tool: z.string().describe("Tool name to approve"),
2254
+ params: z.record(z.unknown()).optional().describe("Tool parameters"),
2255
+ scopeRequired: z.string().describe("Delegation scope needed"),
2256
+ context: z.string().optional().describe("Human-readable context"),
2257
+ }, async ({ agentId, tool, params, scopeRequired, context }) => {
2258
+ if (!state.gateway) {
2259
+ return { content: [{ type: "text", text: "Error: Create gateway first (create_gateway)" }] };
2260
+ }
2261
+ const agent = state.agents.get(agentId);
2262
+ if (!agent) {
2263
+ return { content: [{ type: "text", text: `Error: Agent "${agentId}" not found in session.` }] };
2264
+ }
2265
+ const { canonicalize } = await import("agent-passport-system");
2266
+ const requestId = `mcp-approve-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
2267
+ const payload = canonicalize({ requestId, agentId, tool, params: params || {}, scopeRequired, spend: undefined });
2268
+ const request = {
2269
+ requestId,
2270
+ agentId,
2271
+ agentPublicKey: agent.publicKey,
2272
+ signature: sign(payload, agent.keyPair.privateKey),
2273
+ tool,
2274
+ params: params || {},
2275
+ scopeRequired,
2276
+ context,
2277
+ };
2278
+ const result = state.gateway.approve(request);
2279
+ return {
2280
+ content: [{
2281
+ type: "text",
2282
+ text: JSON.stringify({
2283
+ approved: result.approved,
2284
+ ...(result.approval && {
2285
+ approvalId: result.approval.approvalId,
2286
+ expiresAt: result.approval.expiresAt,
2287
+ nonce: result.approval.nonce,
2288
+ }),
2289
+ ...(result.denial && { denial: result.denial }),
2290
+ }, null, 2),
2291
+ }],
2292
+ };
2293
+ });
2294
+ server.tool("gateway_execute_approval", "Execute a previously approved tool call. Rechecks delegation validity before execution — if delegation was revoked since approval, execution is denied.", {
2295
+ approvalId: z.string().describe("Approval ID from gateway_approve"),
2296
+ }, async ({ approvalId }) => {
2297
+ if (!state.gateway) {
2298
+ return { content: [{ type: "text", text: "Error: Create gateway first (create_gateway)" }] };
2299
+ }
2300
+ const result = await state.gateway.executeApproval(approvalId);
2301
+ return {
2302
+ content: [{
2303
+ type: "text",
2304
+ text: JSON.stringify({
2305
+ executed: result.executed,
2306
+ requestId: result.requestId,
2307
+ result: result.result ?? undefined,
2308
+ denialReason: result.denialReason ?? undefined,
2309
+ ...(result.proof && {
2310
+ proof: {
2311
+ policyReceiptId: result.proof.policyReceipt?.policyReceiptId,
2312
+ },
2313
+ }),
2314
+ }, null, 2),
2315
+ }],
2316
+ };
2317
+ });
2318
+ server.tool("gateway_stats", "Get gateway statistics: total requests, permits, denials, replay attempts blocked, active agents, and pending approvals.", {}, async () => {
2319
+ if (!state.gateway) {
2320
+ return { content: [{ type: "text", text: "Error: Create gateway first (create_gateway)" }] };
2321
+ }
2322
+ return {
2323
+ content: [{
2324
+ type: "text",
2325
+ text: JSON.stringify(state.gateway.getStats(), null, 2),
2326
+ }],
2327
+ };
2328
+ });
2329
+ // ═══════════════════════════════════════
2330
+ // Intent Network (Agent-Mediated Matching)
2331
+ // ═══════════════════════════════════════
2332
+ server.tool("publish_intent_card", "Publish an IntentCard to the network. Represents what your human needs, offers, and is open to. Cards are signed, scoped, and expire automatically.", {
2333
+ principal_alias: z.string().describe("Human's display name or alias"),
2334
+ needs: z.array(z.object({
2335
+ category: z.string().describe("Category (e.g. 'engineering', 'design', 'funding')"),
2336
+ description: z.string().describe("What is needed"),
2337
+ priority: z.enum(["critical", "high", "medium", "low"]).default("medium"),
2338
+ tags: z.array(z.string()).optional(),
2339
+ budget_amount: z.number().optional(),
2340
+ budget_currency: z.string().optional(),
2341
+ })).optional().describe("What the human needs"),
2342
+ offers: z.array(z.object({
2343
+ category: z.string().describe("Category of what's offered"),
2344
+ description: z.string().describe("What is offered"),
2345
+ priority: z.enum(["critical", "high", "medium", "low"]).default("medium"),
2346
+ tags: z.array(z.string()).optional(),
2347
+ budget_amount: z.number().optional(),
2348
+ budget_currency: z.string().optional(),
2349
+ })).optional().describe("What the human offers"),
2350
+ open_to: z.array(z.string()).optional().describe("Categories open to (e.g. ['introductions', 'partnerships'])"),
2351
+ not_open_to: z.array(z.string()).optional().describe("Categories explicitly not open to"),
2352
+ approval_required: z.array(z.string()).optional().describe("What needs human approval before sharing"),
2353
+ visibility: z.enum(["public", "verified", "minimal"]).default("public"),
2354
+ ttl_hours: z.number().default(24).describe("Hours until card expires"),
2355
+ }, async (args) => {
2356
+ const keyErr = requireKey();
2357
+ if (keyErr)
2358
+ return { content: [{ type: "text", text: keyErr }], isError: true };
2359
+ const mapItem = (item) => ({
2360
+ category: item.category,
2361
+ description: item.description,
2362
+ priority: item.priority || 'medium',
2363
+ tags: item.tags || [],
2364
+ budget: item.budget_amount ? { amount: item.budget_amount, currency: item.budget_currency || 'USD' } : undefined,
2365
+ visibility: 'public',
2366
+ });
2367
+ const card = createIntentCard({
2368
+ agentId: state.agentId || 'anonymous',
2369
+ principalAlias: args.principal_alias,
2370
+ publicKey: state.agentKey,
2371
+ privateKey: state.privateKey,
2372
+ needs: (args.needs || []).map(mapItem),
2373
+ offers: (args.offers || []).map(mapItem),
2374
+ openTo: args.open_to || [],
2375
+ notOpenTo: args.not_open_to || [],
2376
+ approvalRequired: args.approval_required || [],
2377
+ ttlSeconds: (args.ttl_hours || 24) * 3600,
2378
+ });
2379
+ const result = publishCard(state.intentNetwork, card);
2380
+ if (!result.published) {
2381
+ return { content: [{ type: "text", text: `Failed to publish: ${result.error}` }], isError: true };
2382
+ }
2383
+ return {
2384
+ content: [{
2385
+ type: "text",
2386
+ text: JSON.stringify({
2387
+ published: true,
2388
+ cardId: card.cardId,
2389
+ agentId: card.agentId,
2390
+ principalAlias: card.principalAlias,
2391
+ needs: card.needs.length,
2392
+ offers: card.offers.length,
2393
+ expiresAt: card.expiresAt,
2394
+ networkSize: state.intentNetwork.cards.size,
2395
+ note: 'Card published. Other agents can now discover matches. Use search_matches to find relevant cards.',
2396
+ }, null, 2),
2397
+ }],
2398
+ };
2399
+ });
2400
+ server.tool("search_matches", "Search the network for IntentCards relevant to your human. Returns ranked matches based on need/offer overlap, tag similarity, and budget compatibility.", {
2401
+ min_score: z.number().optional().describe("Minimum relevance score 0-1 (default: 0.1)"),
2402
+ max_results: z.number().optional().describe("Maximum results to return (default: 10)"),
2403
+ category_filter: z.string().optional().describe("Only match within this category"),
2404
+ }, async (args) => {
2405
+ const keyErr = requireKey();
2406
+ if (keyErr)
2407
+ return { content: [{ type: "text", text: keyErr }], isError: true };
2408
+ const agentId = state.agentId || 'anonymous';
2409
+ const matches = searchMatches(state.intentNetwork, agentId, {
2410
+ minScore: args.min_score,
2411
+ maxResults: args.max_results,
2412
+ categories: args.category_filter ? [args.category_filter] : undefined,
2413
+ });
2414
+ return {
2415
+ content: [{
2416
+ type: "text",
2417
+ text: JSON.stringify({
2418
+ matchCount: matches.length,
2419
+ matches: matches.map(m => {
2420
+ const isA = m.agentA === agentId;
2421
+ return {
2422
+ matchId: m.matchId,
2423
+ otherAgent: isA ? m.agentB : m.agentA,
2424
+ otherCard: isA ? m.cardB : m.cardA,
2425
+ score: m.score,
2426
+ mutual: m.mutual,
2427
+ needOfferMatches: m.needOfferMatches.map(nom => ({
2428
+ needCategory: nom.need.category,
2429
+ offerCategory: nom.offer.category,
2430
+ matchType: nom.matchType,
2431
+ relevanceScore: nom.relevanceScore,
2432
+ })),
2433
+ explanation: m.explanation,
2434
+ };
2435
+ }),
2436
+ networkSize: state.intentNetwork.cards.size,
2437
+ }, null, 2),
2438
+ }],
2439
+ };
2440
+ });
2441
+ server.tool("get_digest", "Get a personalized digest: relevant matches, pending intro requests, and incoming intros. The killer feature — 'what matters to me right now?'", {}, async () => {
2442
+ const agentId = state.agentId || 'anonymous';
2443
+ const digest = getDigest(state.intentNetwork, agentId);
2444
+ return {
2445
+ content: [{
2446
+ type: "text",
2447
+ text: JSON.stringify({
2448
+ agentId: digest.agentId,
2449
+ generatedAt: digest.generatedAt,
2450
+ summary: digest.summary,
2451
+ matchCount: digest.matches.length,
2452
+ topMatches: digest.matches.slice(0, 5).map((m) => {
2453
+ const isA = m.agentA === agentId;
2454
+ return {
2455
+ otherAgent: isA ? m.agentB : m.agentA,
2456
+ score: m.score,
2457
+ explanation: m.explanation,
2458
+ };
2459
+ }),
2460
+ introsPending: digest.introsPending.length,
2461
+ introsReceived: digest.introsReceived.length,
2462
+ introsReceivedDetail: digest.introsReceived.map((intro) => ({
2463
+ introId: intro.introId,
2464
+ fromAgent: intro.requestedBy,
2465
+ message: intro.message,
2466
+ status: intro.status,
2467
+ })),
2468
+ }, null, 2),
2469
+ }],
2470
+ };
2471
+ });
2472
+ server.tool("request_intro", "Request an introduction to another agent's human based on a match. Both sides must approve before real information crosses.", {
2473
+ match_id: z.string().describe("Match ID from search_matches"),
2474
+ target_card_id: z.string().describe("Card ID of the agent you want an intro to"),
2475
+ message: z.string().describe("Brief message explaining why this intro would be valuable"),
2476
+ disclose_fields: z.array(z.string()).optional().describe("Fields you're willing to share (e.g. ['needs', 'offers', 'openTo'])"),
2477
+ }, async (args) => {
2478
+ const keyErr = requireKey();
2479
+ if (keyErr)
2480
+ return { content: [{ type: "text", text: keyErr }], isError: true };
2481
+ try {
2482
+ const result = requestIntro(state.intentNetwork, {
2483
+ requestedBy: state.agentId || 'anonymous',
2484
+ targetAgentId: args.target_card_id,
2485
+ matchId: args.match_id,
2486
+ message: args.message,
2487
+ fieldsToDisclose: args.disclose_fields || ['needs', 'offers'],
2488
+ privateKey: state.privateKey,
2489
+ });
2490
+ if ('error' in result) {
2491
+ return { content: [{ type: "text", text: `Intro request failed: ${result.error}` }], isError: true };
2492
+ }
2493
+ return {
2494
+ content: [{
2495
+ type: "text",
2496
+ text: JSON.stringify({
2497
+ introId: result.introId,
2498
+ status: result.status,
2499
+ targetAgent: result.targetAgentId,
2500
+ message: result.message,
2501
+ note: 'Intro request sent. The other agent\'s human will see this in their digest and can approve or decline.',
2502
+ }, null, 2),
2503
+ }],
2504
+ };
2505
+ }
2506
+ catch (e) {
2507
+ return { content: [{ type: "text", text: `Intro request failed: ${e.message}` }], isError: true };
2508
+ }
2509
+ });
2510
+ server.tool("respond_to_intro", "Respond to an introduction request. Approve to share your disclosed information, or decline.", {
2511
+ intro_id: z.string().describe("Intro request ID"),
2512
+ approved: z.boolean().describe("Whether to approve the introduction"),
2513
+ message: z.string().optional().describe("Optional response message"),
2514
+ disclose_fields: z.array(z.string()).optional().describe("Fields you're willing to share back"),
2515
+ }, async (args) => {
2516
+ const keyErr = requireKey();
2517
+ if (keyErr)
2518
+ return { content: [{ type: "text", text: keyErr }], isError: true };
2519
+ try {
2520
+ const result = respondToIntro(state.intentNetwork, {
2521
+ introId: args.intro_id,
2522
+ respondedBy: state.agentId || 'anonymous',
2523
+ verdict: args.approved ? 'approve' : 'decline',
2524
+ message: args.message,
2525
+ disclosedFields: args.disclose_fields ? Object.fromEntries(args.disclose_fields.map(f => [f, 'disclosed'])) : undefined,
2526
+ privateKey: state.privateKey,
2527
+ });
2528
+ if ('error' in result) {
2529
+ return { content: [{ type: "text", text: `Intro response failed: ${result.error}` }], isError: true };
2530
+ }
2531
+ return {
2532
+ content: [{
2533
+ type: "text",
2534
+ text: JSON.stringify({
2535
+ introId: result.introId,
2536
+ verdict: result.verdict,
2537
+ approved: args.approved,
2538
+ note: args.approved
2539
+ ? 'Introduction approved. Both parties can now see disclosed information.'
2540
+ : 'Introduction declined.',
2541
+ }, null, 2),
2542
+ }],
2543
+ };
2544
+ }
2545
+ catch (e) {
2546
+ return { content: [{ type: "text", text: `Intro response failed: ${e.message}` }], isError: true };
2547
+ }
2548
+ });
2549
+ server.tool("remove_intent_card", "Remove your IntentCard from the network. Use when your needs or offers have changed.", {
2550
+ card_id: z.string().describe("Card ID to remove"),
2551
+ }, async (args) => {
2552
+ const removed = removeCard(state.intentNetwork, args.card_id);
2553
+ return {
2554
+ content: [{
2555
+ type: "text",
2556
+ text: JSON.stringify({
2557
+ removed,
2558
+ cardId: args.card_id,
2559
+ networkSize: state.intentNetwork.cards.size,
2560
+ }, null, 2),
2561
+ }],
2562
+ };
2563
+ });
2564
+ // ═══════════════════════════════════════
2115
2565
  // MCP Prompts — Role-Specific
2116
2566
  // ═══════════════════════════════════════
2117
2567
  server.prompt("coordination_role", "Get instructions for your assigned coordination role", {}, async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-passport-system-mcp",
3
- "version": "2.5.0",
3
+ "version": "2.7.0",
4
4
  "mcpName": "io.github.aeoess/agent-passport-mcp",
5
5
  "description": "MCP server for Agent Passport System — cryptographic identity, delegation, governance, and deliberation for AI agents",
6
6
  "type": "module",
@@ -8,7 +8,9 @@
8
8
  "agent-passport-system-mcp": "build/index.js"
9
9
  },
10
10
  "files": [
11
- "build"
11
+ "build",
12
+ "CONTRIBUTING.md",
13
+ "CODE_OF_CONDUCT.md"
12
14
  ],
13
15
  "scripts": {
14
16
  "build": "tsc && chmod 755 build/index.js",
@@ -45,7 +47,7 @@
45
47
  "homepage": "https://github.com/aeoess/agent-passport-mcp",
46
48
  "dependencies": {
47
49
  "@modelcontextprotocol/sdk": "^1.12.0",
48
- "agent-passport-system": "file:../agent-passport-system/agent-passport-system-1.11.0.tgz",
50
+ "agent-passport-system": "file:../agent-passport-system/agent-passport-system-1.13.0.tgz",
49
51
  "zod": "^3.25.0"
50
52
  },
51
53
  "devDependencies": {