@peac/mcp-server 0.11.3 → 0.12.0-preview.2

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/dist/cli.mjs CHANGED
@@ -8,7 +8,7 @@ import { z } from 'zod';
8
8
  import { sha256Hex, validateKeypair, base64urlDecode, derivePublicKey, base64urlEncode, decode, sign } from '@peac/crypto';
9
9
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
10
10
  import { ERRORS } from '@peac/kernel';
11
- import { verifyLocal, issue, IssueError } from '@peac/protocol';
11
+ import { verifyLocal, issueWire02, IssueError } from '@peac/protocol';
12
12
  import { parseReceiptClaims } from '@peac/schema';
13
13
  import * as nodePath from 'path';
14
14
  import { join } from 'path';
@@ -1150,16 +1150,15 @@ async function handleVerify(params) {
1150
1150
  const claims = result.claims;
1151
1151
  const claimsSummary = {
1152
1152
  iss: claims.iss,
1153
- aud: claims.aud,
1154
- rid: claims.rid,
1155
- variant: result.variant
1153
+ kind: claims.kind,
1154
+ type: claims.type,
1155
+ jti: claims.jti,
1156
+ ...claims.sub !== void 0 && { sub: claims.sub },
1157
+ variant: result.variant,
1158
+ wireVersion: result.wireVersion
1156
1159
  };
1157
- if (result.variant === "commerce") {
1158
- claimsSummary.amt = claims.amt;
1159
- claimsSummary.cur = claims.cur;
1160
- }
1161
1160
  const tr = truncateResponse(
1162
- `Verification PASSED (${result.variant} receipt, kid=${result.kid})`,
1161
+ `Verification PASSED (${result.variant} receipt, kind=${claims.kind ?? "unknown"}, kid=${result.kid})`,
1163
1162
  policy
1164
1163
  );
1165
1164
  return {
@@ -1392,49 +1391,44 @@ async function handleIssue(params) {
1392
1391
  isError: true
1393
1392
  };
1394
1393
  }
1395
- if (input.ttl_seconds !== void 0 && input.ttl_seconds > policy.limits.max_ttl_seconds) {
1396
- return {
1397
- text: `Input rejected: ttl_seconds ${input.ttl_seconds} exceeds max_ttl_seconds ${policy.limits.max_ttl_seconds}`,
1398
- structured: {
1399
- ok: false,
1400
- code: "E_MCP_INVALID_INPUT",
1401
- message: `ttl_seconds ${input.ttl_seconds} exceeds policy max of ${policy.limits.max_ttl_seconds}`
1402
- },
1403
- isError: true
1404
- };
1405
- }
1406
1394
  const keyPatterns = buildKeyPatterns(context.issuerKey.privateKey, context.issuerKey.publicKey);
1407
- const now = Math.floor(Date.now() / 1e3);
1408
- const exp = input.ttl_seconds !== void 0 ? now + input.ttl_seconds : void 0;
1409
1395
  try {
1410
- const result = await issue({
1396
+ if (input.policy && !input.policy.digest) {
1397
+ return {
1398
+ text: "Issue failed: policy.digest is required when policy block is provided",
1399
+ structured: {
1400
+ ok: false,
1401
+ code: "E_MCP_ISSUE_FAILED",
1402
+ message: "policy.digest is required when policy block is provided (uri/version alone is insufficient for binding)"
1403
+ },
1404
+ isError: true
1405
+ };
1406
+ }
1407
+ const policyBlock = input.policy?.digest ? { digest: input.policy.digest, uri: input.policy.uri, version: input.policy.version } : void 0;
1408
+ const result = await issueWire02({
1411
1409
  iss: context.issuerId,
1412
- aud: input.aud,
1413
- amt: input.amt,
1414
- cur: input.cur,
1415
- rail: input.rail,
1416
- reference: input.reference,
1417
- asset: input.asset,
1418
- env: input.env,
1419
- network: input.network,
1420
- evidence: input.evidence,
1421
- subject: input.subject,
1422
- exp,
1410
+ kind: input.kind,
1411
+ type: input.type,
1412
+ sub: input.sub,
1413
+ pillars: input.pillars,
1414
+ occurred_at: input.occurred_at,
1415
+ extensions: input.extensions,
1416
+ policy: policyBlock,
1423
1417
  privateKey: context.issuerKey.privateKey,
1424
1418
  kid: context.issuerKey.kid
1425
1419
  });
1426
1420
  const { payload } = decode(result.jws);
1427
1421
  const claimsSummary = {
1428
1422
  iss: payload.iss,
1429
- aud: payload.aud,
1423
+ kind: payload.kind,
1424
+ type: payload.type,
1430
1425
  iat: payload.iat,
1431
- ...payload.exp !== void 0 ? { exp: payload.exp } : {},
1432
- rid: payload.rid,
1433
- amt: payload.amt,
1434
- cur: payload.cur
1426
+ jti: payload.jti,
1427
+ ...payload.sub !== void 0 ? { sub: payload.sub } : {},
1428
+ ...payload.pillars !== void 0 ? { pillars: payload.pillars } : {}
1435
1429
  };
1436
1430
  const tr = truncateResponse(
1437
- `Receipt issued: rid=${claimsSummary.rid}, ${claimsSummary.amt} ${claimsSummary.cur}`,
1431
+ `Receipt issued: jti=${claimsSummary.jti}, kind=${claimsSummary.kind}, type=${claimsSummary.type}`,
1438
1432
  policy
1439
1433
  );
1440
1434
  const safeText = sanitizeOutput(tr.text, keyPatterns);
@@ -1858,18 +1852,41 @@ var DecodeOutputSchema = z.object({
1858
1852
  verified: z.literal(false)
1859
1853
  });
1860
1854
  var IssueInputSchema = z.object({
1861
- aud: z.string().url().describe("Audience / resource URI (https://)"),
1862
- amt: z.number().int().nonnegative().describe("Amount in smallest currency unit"),
1863
- cur: z.string().regex(/^[A-Z]{3}$/).describe("ISO 4217 currency code (uppercase, e.g. USD)"),
1864
- rail: z.string().describe("Payment rail identifier"),
1865
- reference: z.string().describe("Unique payment reference"),
1866
- asset: z.string().optional().describe("Asset transferred (e.g. USDC) -- defaults to currency"),
1867
- env: z.enum(["live", "test"]).default("test").describe("Environment"),
1868
- network: z.string().optional().describe("Network/chain identifier"),
1869
- evidence: z.unknown().optional().describe("Rail-specific evidence (JSON-safe)"),
1870
- subject: z.string().url().optional().describe("Subject URI (https://)"),
1871
- ttl_seconds: z.number().int().positive().optional().describe("Time-to-live in seconds (computes exp = iat + ttl)"),
1872
- kind: z.string().optional().describe("Receipt kind for policy filtering")
1855
+ kind: z.enum(["evidence", "challenge"]).describe("Structural kind: evidence (records interaction) or challenge (requests action)"),
1856
+ type: z.string().min(1).max(256).refine(
1857
+ (v) => /^https?:\/\//.test(v) || /^[a-zA-Z0-9][a-zA-Z0-9._-]*\.[a-zA-Z0-9._-]+\/[a-zA-Z0-9]/.test(v),
1858
+ {
1859
+ message: "type must be reverse-DNS (e.g. org.peacprotocol/payment) or absolute URI (https://...)"
1860
+ }
1861
+ ).describe("Semantic type in reverse-DNS or absolute URI form (e.g. org.peacprotocol/payment)"),
1862
+ sub: z.string().max(2048).optional().describe("Subject identifier (resource or interaction target)"),
1863
+ pillars: z.array(
1864
+ z.enum([
1865
+ "access",
1866
+ "attribution",
1867
+ "commerce",
1868
+ "compliance",
1869
+ "consent",
1870
+ "identity",
1871
+ "privacy",
1872
+ "provenance",
1873
+ "purpose",
1874
+ "safety"
1875
+ ])
1876
+ ).optional().refine(
1877
+ (arr) => !arr || new Set(arr).size === arr.length && [...arr].sort().every((v, i) => v === arr[i]),
1878
+ { message: "pillars must be unique and sorted ascending" }
1879
+ ).describe("Evidence pillars from closed 10-value taxonomy (sorted ascending)"),
1880
+ occurred_at: z.string().optional().refine((v) => !v || !isNaN(Date.parse(v)), {
1881
+ message: "occurred_at must be a valid ISO 8601 timestamp"
1882
+ }).describe("ISO 8601 timestamp when interaction occurred (evidence kind only)"),
1883
+ extensions: z.record(z.string(), z.unknown()).optional().describe("Extension groups keyed by reverse-DNS identifier"),
1884
+ policy: z.object({
1885
+ uri: z.string().url().max(2048).refine((v) => v.startsWith("https://"), { message: "policy.uri must use HTTPS" }).describe("Policy document URI (HTTPS only)"),
1886
+ version: z.string().max(256).optional().describe("Policy version"),
1887
+ digest: z.string().regex(/^sha256:[0-9a-f]{64}$/).optional().describe("Policy digest in sha256:<64 hex> format")
1888
+ }).optional().describe("Policy binding block"),
1889
+ ttl_seconds: z.number().int().positive().optional().describe("Reserved for future use (Wire 0.2 receipts do not expire)")
1873
1890
  });
1874
1891
  var MetaSchema4 = z.object({
1875
1892
  serverVersion: z.string(),
@@ -1878,12 +1895,12 @@ var MetaSchema4 = z.object({
1878
1895
  });
1879
1896
  var ClaimsSummarySchema = z.object({
1880
1897
  iss: z.string(),
1881
- aud: z.string(),
1898
+ kind: z.string(),
1899
+ type: z.string(),
1882
1900
  iat: z.number(),
1883
- exp: z.number().optional(),
1884
- rid: z.string(),
1885
- amt: z.number(),
1886
- cur: z.string()
1901
+ jti: z.string(),
1902
+ sub: z.string().optional(),
1903
+ pillars: z.array(z.string()).optional()
1887
1904
  });
1888
1905
  var IssueOutputSchema = z.object({
1889
1906
  _meta: MetaSchema4,
@@ -1919,7 +1936,8 @@ function makeMeta(ctx, serverName) {
1919
1936
  serverName,
1920
1937
  serverVersion: ctx.version,
1921
1938
  policyHash: ctx.policyHash,
1922
- protocolVersion: ctx.protocolVersion
1939
+ protocolVersion: ctx.protocolVersion,
1940
+ wireFormatVersion: "0.2"
1923
1941
  };
1924
1942
  }
1925
1943
  function handlerResultToCallToolResult(result, meta) {
@@ -2111,8 +2129,8 @@ function createPeacMcpServer(options) {
2111
2129
  register(
2112
2130
  "peac_issue",
2113
2131
  {
2114
- title: "Issue PEAC Receipt",
2115
- description: "Sign and return a new PEAC receipt JWS. Requires server configured with an Ed25519 issuer key (--issuer-key and --issuer-id).",
2132
+ title: "Issue Wire 0.2 PEAC Receipt",
2133
+ description: "Sign and return a Wire 0.2 PEAC receipt JWS. Accepts kind, type, pillars, extensions, and policy fields. Wire 0.2 only: Wire 0.1 fields are not accepted. Requires server configured with an Ed25519 issuer key (--issuer-key and --issuer-id).",
2116
2134
  inputSchema: IssueInputSchema,
2117
2135
  outputSchema: IssueOutputSchema,
2118
2136
  annotations: ISSUE_TOOL_ANNOTATIONS