@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.cjs +77 -59
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +78 -60
- package/dist/cli.mjs.map +1 -1
- package/dist/handlers/issue.d.ts +2 -2
- package/dist/handlers/issue.d.ts.map +1 -1
- package/dist/handlers/verify.d.ts.map +1 -1
- package/dist/index.cjs +77 -59
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +78 -60
- package/dist/index.mjs.map +1 -1
- package/dist/schemas/issue.d.ts +35 -20
- package/dist/schemas/issue.d.ts.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/manifest.json +1 -1
- package/package.json +5 -5
- package/server.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import { ERRORS } from '@peac/kernel';
|
|
3
|
-
import { verifyLocal,
|
|
3
|
+
import { verifyLocal, issueWire02, IssueError } from '@peac/protocol';
|
|
4
4
|
import { base64urlDecode, decode, sha256Hex, sign, validateKeypair, derivePublicKey, base64urlEncode } from '@peac/crypto';
|
|
5
5
|
import { readFile, mkdir, rename, rm, mkdtemp, writeFile, stat, lstat } from 'fs/promises';
|
|
6
6
|
import { parseReceiptClaims } from '@peac/schema';
|
|
@@ -395,16 +395,15 @@ async function handleVerify(params) {
|
|
|
395
395
|
const claims = result.claims;
|
|
396
396
|
const claimsSummary = {
|
|
397
397
|
iss: claims.iss,
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
398
|
+
kind: claims.kind,
|
|
399
|
+
type: claims.type,
|
|
400
|
+
jti: claims.jti,
|
|
401
|
+
...claims.sub !== void 0 && { sub: claims.sub },
|
|
402
|
+
variant: result.variant,
|
|
403
|
+
wireVersion: result.wireVersion
|
|
401
404
|
};
|
|
402
|
-
if (result.variant === "commerce") {
|
|
403
|
-
claimsSummary.amt = claims.amt;
|
|
404
|
-
claimsSummary.cur = claims.cur;
|
|
405
|
-
}
|
|
406
405
|
const tr = truncateResponse(
|
|
407
|
-
`Verification PASSED (${result.variant} receipt, kid=${result.kid})`,
|
|
406
|
+
`Verification PASSED (${result.variant} receipt, kind=${claims.kind ?? "unknown"}, kid=${result.kid})`,
|
|
408
407
|
policy
|
|
409
408
|
);
|
|
410
409
|
return {
|
|
@@ -637,49 +636,44 @@ async function handleIssue(params) {
|
|
|
637
636
|
isError: true
|
|
638
637
|
};
|
|
639
638
|
}
|
|
640
|
-
if (input.ttl_seconds !== void 0 && input.ttl_seconds > policy.limits.max_ttl_seconds) {
|
|
641
|
-
return {
|
|
642
|
-
text: `Input rejected: ttl_seconds ${input.ttl_seconds} exceeds max_ttl_seconds ${policy.limits.max_ttl_seconds}`,
|
|
643
|
-
structured: {
|
|
644
|
-
ok: false,
|
|
645
|
-
code: "E_MCP_INVALID_INPUT",
|
|
646
|
-
message: `ttl_seconds ${input.ttl_seconds} exceeds policy max of ${policy.limits.max_ttl_seconds}`
|
|
647
|
-
},
|
|
648
|
-
isError: true
|
|
649
|
-
};
|
|
650
|
-
}
|
|
651
639
|
const keyPatterns = buildKeyPatterns(context.issuerKey.privateKey, context.issuerKey.publicKey);
|
|
652
|
-
const now = Math.floor(Date.now() / 1e3);
|
|
653
|
-
const exp = input.ttl_seconds !== void 0 ? now + input.ttl_seconds : void 0;
|
|
654
640
|
try {
|
|
655
|
-
|
|
641
|
+
if (input.policy && !input.policy.digest) {
|
|
642
|
+
return {
|
|
643
|
+
text: "Issue failed: policy.digest is required when policy block is provided",
|
|
644
|
+
structured: {
|
|
645
|
+
ok: false,
|
|
646
|
+
code: "E_MCP_ISSUE_FAILED",
|
|
647
|
+
message: "policy.digest is required when policy block is provided (uri/version alone is insufficient for binding)"
|
|
648
|
+
},
|
|
649
|
+
isError: true
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
const policyBlock = input.policy?.digest ? { digest: input.policy.digest, uri: input.policy.uri, version: input.policy.version } : void 0;
|
|
653
|
+
const result = await issueWire02({
|
|
656
654
|
iss: context.issuerId,
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
network: input.network,
|
|
665
|
-
evidence: input.evidence,
|
|
666
|
-
subject: input.subject,
|
|
667
|
-
exp,
|
|
655
|
+
kind: input.kind,
|
|
656
|
+
type: input.type,
|
|
657
|
+
sub: input.sub,
|
|
658
|
+
pillars: input.pillars,
|
|
659
|
+
occurred_at: input.occurred_at,
|
|
660
|
+
extensions: input.extensions,
|
|
661
|
+
policy: policyBlock,
|
|
668
662
|
privateKey: context.issuerKey.privateKey,
|
|
669
663
|
kid: context.issuerKey.kid
|
|
670
664
|
});
|
|
671
665
|
const { payload } = decode(result.jws);
|
|
672
666
|
const claimsSummary = {
|
|
673
667
|
iss: payload.iss,
|
|
674
|
-
|
|
668
|
+
kind: payload.kind,
|
|
669
|
+
type: payload.type,
|
|
675
670
|
iat: payload.iat,
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
cur: payload.cur
|
|
671
|
+
jti: payload.jti,
|
|
672
|
+
...payload.sub !== void 0 ? { sub: payload.sub } : {},
|
|
673
|
+
...payload.pillars !== void 0 ? { pillars: payload.pillars } : {}
|
|
680
674
|
};
|
|
681
675
|
const tr = truncateResponse(
|
|
682
|
-
`Receipt issued:
|
|
676
|
+
`Receipt issued: jti=${claimsSummary.jti}, kind=${claimsSummary.kind}, type=${claimsSummary.type}`,
|
|
683
677
|
policy
|
|
684
678
|
);
|
|
685
679
|
const safeText = sanitizeOutput(tr.text, keyPatterns);
|
|
@@ -1119,18 +1113,41 @@ var DecodeOutputSchema = z.object({
|
|
|
1119
1113
|
verified: z.literal(false)
|
|
1120
1114
|
});
|
|
1121
1115
|
var IssueInputSchema = z.object({
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1116
|
+
kind: z.enum(["evidence", "challenge"]).describe("Structural kind: evidence (records interaction) or challenge (requests action)"),
|
|
1117
|
+
type: z.string().min(1).max(256).refine(
|
|
1118
|
+
(v) => /^https?:\/\//.test(v) || /^[a-zA-Z0-9][a-zA-Z0-9._-]*\.[a-zA-Z0-9._-]+\/[a-zA-Z0-9]/.test(v),
|
|
1119
|
+
{
|
|
1120
|
+
message: "type must be reverse-DNS (e.g. org.peacprotocol/payment) or absolute URI (https://...)"
|
|
1121
|
+
}
|
|
1122
|
+
).describe("Semantic type in reverse-DNS or absolute URI form (e.g. org.peacprotocol/payment)"),
|
|
1123
|
+
sub: z.string().max(2048).optional().describe("Subject identifier (resource or interaction target)"),
|
|
1124
|
+
pillars: z.array(
|
|
1125
|
+
z.enum([
|
|
1126
|
+
"access",
|
|
1127
|
+
"attribution",
|
|
1128
|
+
"commerce",
|
|
1129
|
+
"compliance",
|
|
1130
|
+
"consent",
|
|
1131
|
+
"identity",
|
|
1132
|
+
"privacy",
|
|
1133
|
+
"provenance",
|
|
1134
|
+
"purpose",
|
|
1135
|
+
"safety"
|
|
1136
|
+
])
|
|
1137
|
+
).optional().refine(
|
|
1138
|
+
(arr) => !arr || new Set(arr).size === arr.length && [...arr].sort().every((v, i) => v === arr[i]),
|
|
1139
|
+
{ message: "pillars must be unique and sorted ascending" }
|
|
1140
|
+
).describe("Evidence pillars from closed 10-value taxonomy (sorted ascending)"),
|
|
1141
|
+
occurred_at: z.string().optional().refine((v) => !v || !isNaN(Date.parse(v)), {
|
|
1142
|
+
message: "occurred_at must be a valid ISO 8601 timestamp"
|
|
1143
|
+
}).describe("ISO 8601 timestamp when interaction occurred (evidence kind only)"),
|
|
1144
|
+
extensions: z.record(z.string(), z.unknown()).optional().describe("Extension groups keyed by reverse-DNS identifier"),
|
|
1145
|
+
policy: z.object({
|
|
1146
|
+
uri: z.string().url().max(2048).refine((v) => v.startsWith("https://"), { message: "policy.uri must use HTTPS" }).describe("Policy document URI (HTTPS only)"),
|
|
1147
|
+
version: z.string().max(256).optional().describe("Policy version"),
|
|
1148
|
+
digest: z.string().regex(/^sha256:[0-9a-f]{64}$/).optional().describe("Policy digest in sha256:<64 hex> format")
|
|
1149
|
+
}).optional().describe("Policy binding block"),
|
|
1150
|
+
ttl_seconds: z.number().int().positive().optional().describe("Reserved for future use (Wire 0.2 receipts do not expire)")
|
|
1134
1151
|
});
|
|
1135
1152
|
var MetaSchema4 = z.object({
|
|
1136
1153
|
serverVersion: z.string(),
|
|
@@ -1139,12 +1156,12 @@ var MetaSchema4 = z.object({
|
|
|
1139
1156
|
});
|
|
1140
1157
|
var ClaimsSummarySchema = z.object({
|
|
1141
1158
|
iss: z.string(),
|
|
1142
|
-
|
|
1159
|
+
kind: z.string(),
|
|
1160
|
+
type: z.string(),
|
|
1143
1161
|
iat: z.number(),
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
cur: z.string()
|
|
1162
|
+
jti: z.string(),
|
|
1163
|
+
sub: z.string().optional(),
|
|
1164
|
+
pillars: z.array(z.string()).optional()
|
|
1148
1165
|
});
|
|
1149
1166
|
var IssueOutputSchema = z.object({
|
|
1150
1167
|
_meta: MetaSchema4,
|
|
@@ -1180,7 +1197,8 @@ function makeMeta(ctx, serverName) {
|
|
|
1180
1197
|
serverName,
|
|
1181
1198
|
serverVersion: ctx.version,
|
|
1182
1199
|
policyHash: ctx.policyHash,
|
|
1183
|
-
protocolVersion: ctx.protocolVersion
|
|
1200
|
+
protocolVersion: ctx.protocolVersion,
|
|
1201
|
+
wireFormatVersion: "0.2"
|
|
1184
1202
|
};
|
|
1185
1203
|
}
|
|
1186
1204
|
function handlerResultToCallToolResult(result, meta) {
|
|
@@ -1372,8 +1390,8 @@ function createPeacMcpServer(options) {
|
|
|
1372
1390
|
register(
|
|
1373
1391
|
"peac_issue",
|
|
1374
1392
|
{
|
|
1375
|
-
title: "Issue PEAC Receipt",
|
|
1376
|
-
description: "Sign and return a
|
|
1393
|
+
title: "Issue Wire 0.2 PEAC Receipt",
|
|
1394
|
+
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).",
|
|
1377
1395
|
inputSchema: IssueInputSchema,
|
|
1378
1396
|
outputSchema: IssueOutputSchema,
|
|
1379
1397
|
annotations: ISSUE_TOOL_ANNOTATIONS
|