@peac/mcp-server 0.10.13 → 0.11.3

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,65 @@
1
+ /**
2
+ * MCP Streamable HTTP transport (DD-119, DD-123)
3
+ *
4
+ * Adds HTTP transport alongside stdio. Unprotected mode only (v0.11.0).
5
+ * Each session gets its own McpServer + transport (CVE-2026-25536 defense).
6
+ *
7
+ * Endpoints:
8
+ * POST /mcp JSON-RPC tool calls (requires Mcp-Session-Id after init)
9
+ * DELETE /mcp Terminate session
10
+ * GET /health Health check (no auth)
11
+ * GET /.well-known/oauth-protected-resource[/<path>] PRM (conditional)
12
+ * GET /mcp 405 Method Not Allowed
13
+ */
14
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
15
+ /**
16
+ * Trust-proxy configuration for X-Forwarded-For interpretation.
17
+ *
18
+ * Presets:
19
+ * - 'off': never trust forwarded headers (default; safe for direct clients)
20
+ * - 'loopback': trust only from 127.0.0.0/8 and ::1
21
+ * - 'linklocal': trust loopback + link-local (169.254.0.0/16, fe80::/10)
22
+ * - 'private': trust loopback + link-local + RFC 1918 (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
23
+ * - 'all': trust any remote address (DISCOURAGED; use only when behind a fully trusted proxy chain)
24
+ *
25
+ * Explicit addresses:
26
+ * - comma-separated IPs: trust only from listed addresses (e.g., '10.0.0.1,10.0.0.2')
27
+ *
28
+ * WARNING: only enable behind a trusted reverse proxy. An attacker can forge
29
+ * X-Forwarded-For from an untrusted peer to bypass per-IP rate limiting.
30
+ */
31
+ export type TrustProxyValue = 'off' | 'loopback' | 'linklocal' | 'private' | 'all' | string;
32
+ export interface HttpTransportOptions {
33
+ /** Port to listen on. Default: 3000 */
34
+ port?: number;
35
+ /** Bind address. Default: '127.0.0.1' (localhost only) */
36
+ host?: string;
37
+ /** Allowed CORS origins (empty = deny all). */
38
+ corsOrigins?: string[];
39
+ /** OAuth authorization server URIs (enables PRM with publicUrl). */
40
+ authorizationServers?: string[];
41
+ /** Canonical public URL of this server (required for PRM). */
42
+ publicUrl?: string;
43
+ /** Trust X-Forwarded-For for rate limiting. Default: 'off' */
44
+ trustProxy?: TrustProxyValue;
45
+ /** Max request body bytes. Default: 1MB */
46
+ maxRequestBytes?: number;
47
+ /** Rate limit: requests per minute per session. Default: 100 */
48
+ rateLimitRpm?: number;
49
+ /** Session TTL in ms. Default: 30 min */
50
+ sessionTtlMs?: number;
51
+ /** Max concurrent sessions. Default: 100 */
52
+ maxSessions?: number;
53
+ /** Max sessions per client IP. Default: 10 */
54
+ maxSessionsPerIp?: number;
55
+ /** Factory to create new McpServer instances (one per session) */
56
+ serverFactory: () => McpServer;
57
+ }
58
+ /**
59
+ * Create and start an HTTP server for MCP Streamable HTTP transport.
60
+ * Returns a cleanup function to shut everything down.
61
+ */
62
+ export declare function createHttpTransport(options: HttpTransportOptions): Promise<{
63
+ cleanup: () => Promise<void>;
64
+ }>;
65
+ //# sourceMappingURL=http-transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-transport.d.ts","sourceRoot":"","sources":["../src/http-transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIzE;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,UAAU,GAAG,WAAW,GAAG,SAAS,GAAG,KAAK,GAAG,MAAM,CAAC;AAE5F,MAAM,WAAW,oBAAoB;IACnC,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,oEAAoE;IACpE,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,2CAA2C;IAC3C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yCAAyC;IACzC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8CAA8C;IAC9C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kEAAkE;IAClE,aAAa,EAAE,MAAM,SAAS,CAAC;CAChC;AA0FD;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,CA+X3C"}
package/dist/index.cjs CHANGED
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var mcp_js = require('@modelcontextprotocol/sdk/server/mcp.js');
4
+ var kernel = require('@peac/kernel');
4
5
  var protocol = require('@peac/protocol');
5
6
  var crypto = require('@peac/crypto');
6
7
  var promises = require('fs/promises');
@@ -33,7 +34,7 @@ var nodePath__namespace = /*#__PURE__*/_interopNamespace(nodePath);
33
34
 
34
35
  // src/infra/constants.ts
35
36
  var SERVER_NAME = "peac-mcp-server";
36
- var SERVER_VERSION = "0.10.12";
37
+ var SERVER_VERSION = "0.11.2";
37
38
  var MCP_PROTOCOL_VERSION = "2025-11-25";
38
39
  var DEFAULT_MAX_JWS_BYTES = 16384;
39
40
  var DEFAULT_MAX_RESPONSE_BYTES = 65536;
@@ -747,10 +748,40 @@ async function handleIssue(params) {
747
748
  };
748
749
  }
749
750
  }
751
+ var WINDOWS_RESERVED_NAMES = /* @__PURE__ */ new Set([
752
+ "con",
753
+ "prn",
754
+ "aux",
755
+ "nul",
756
+ "com1",
757
+ "com2",
758
+ "com3",
759
+ "com4",
760
+ "com5",
761
+ "com6",
762
+ "com7",
763
+ "com8",
764
+ "com9",
765
+ "lpt1",
766
+ "lpt2",
767
+ "lpt3",
768
+ "lpt4",
769
+ "lpt5",
770
+ "lpt6",
771
+ "lpt7",
772
+ "lpt8",
773
+ "lpt9"
774
+ ]);
750
775
  function assertRelativePath(p) {
751
776
  if (!p || p.trim().length === 0) {
752
777
  throw new PathTraversalError("Path must not be empty");
753
778
  }
779
+ if (p.includes("\0")) {
780
+ throw new PathTraversalError("Null bytes are not allowed in paths");
781
+ }
782
+ if (p.includes(":")) {
783
+ throw new PathTraversalError("Colons are not allowed in paths (drive letters, NTFS ADS)");
784
+ }
754
785
  if (nodePath__namespace.isAbsolute(p)) {
755
786
  throw new PathTraversalError("Absolute paths are not allowed");
756
787
  }
@@ -767,6 +798,14 @@ function assertRelativePath(p) {
767
798
  if (p.startsWith(".")) {
768
799
  throw new PathTraversalError("Hidden paths (starting with .) are not allowed");
769
800
  }
801
+ if (p.endsWith(".") || p.endsWith(" ")) {
802
+ throw new PathTraversalError("Trailing dots and spaces are not allowed");
803
+ }
804
+ const dotIndex = p.indexOf(".");
805
+ const baseName = (dotIndex >= 0 ? p.slice(0, dotIndex) : p).toLowerCase();
806
+ if (WINDOWS_RESERVED_NAMES.has(baseName)) {
807
+ throw new PathTraversalError(`Windows reserved device name: ${baseName.toUpperCase()}`);
808
+ }
770
809
  }
771
810
  function resolveOutputPath(basePath, relativePath) {
772
811
  assertRelativePath(relativePath);
@@ -1136,7 +1175,7 @@ var IssueOutputSchema = zod.z.object({
1136
1175
  });
1137
1176
  var BundleInputSchema = zod.z.object({
1138
1177
  receipts: zod.z.array(zod.z.string().max(16384)).min(1).max(256).describe("Receipt JWS strings to bundle (1-256)"),
1139
- metadata: zod.z.record(zod.z.unknown()).optional().describe("Optional metadata to include in the manifest"),
1178
+ metadata: zod.z.record(zod.z.string(), zod.z.unknown()).optional().describe("Optional metadata to include in the manifest"),
1140
1179
  output_path: zod.z.string().max(255).optional().describe("Output directory name (single segment within --bundle-dir)")
1141
1180
  });
1142
1181
  var MetaSchema5 = zod.z.object({
@@ -1192,9 +1231,17 @@ var BUNDLE_TOOL_ANNOTATIONS = {
1192
1231
  };
1193
1232
  var MAX_INPUT_DEPTH = 10;
1194
1233
  function errorCallToolResult(meta, code, message) {
1234
+ const errorDef = kernel.ERRORS[code];
1195
1235
  return {
1196
1236
  content: [{ type: "text", text: message }],
1197
- structuredContent: { _meta: meta, ok: false, code, message },
1237
+ structuredContent: {
1238
+ _meta: meta,
1239
+ ok: false,
1240
+ code,
1241
+ message,
1242
+ retryable: errorDef?.retryable ?? false,
1243
+ next_action: errorDef?.next_action ?? "none"
1244
+ },
1198
1245
  isError: true
1199
1246
  };
1200
1247
  }
@@ -1298,7 +1345,7 @@ function createPeacMcpServer(options) {
1298
1345
  "peac_verify",
1299
1346
  {
1300
1347
  title: "Verify PEAC Receipt",
1301
- description: "Verify a PEAC receipt JWS signature and validate claims. Returns structured check results.",
1348
+ description: "Verify a PEAC receipt: check Ed25519 signature, validate claims, and return structured check results. Read-only, no side effects.",
1302
1349
  inputSchema: VerifyInputSchema,
1303
1350
  outputSchema: VerifyOutputSchema,
1304
1351
  annotations: PURE_TOOL_ANNOTATIONS
@@ -1314,7 +1361,7 @@ function createPeacMcpServer(options) {
1314
1361
  "peac_inspect",
1315
1362
  {
1316
1363
  title: "Inspect PEAC Receipt",
1317
- description: "Decode and inspect a PEAC receipt without verifying the signature. Shows header, payload metadata, and optionally full claims.",
1364
+ description: "Inspect a PEAC receipt without verifying the signature. Returns decoded header, payload metadata, and timestamps. Read-only.",
1318
1365
  inputSchema: InspectInputSchema,
1319
1366
  outputSchema: InspectOutputSchema,
1320
1367
  annotations: PURE_TOOL_ANNOTATIONS
@@ -1330,7 +1377,7 @@ function createPeacMcpServer(options) {
1330
1377
  "peac_decode",
1331
1378
  {
1332
1379
  title: "Decode PEAC Receipt",
1333
- description: "Raw decode of a PEAC receipt JWS. Returns header and payload without signature verification.",
1380
+ description: "Raw-decode a PEAC receipt JWS into header and payload objects. No signature check. Use peac_verify for trusted results.",
1334
1381
  inputSchema: DecodeInputSchema,
1335
1382
  outputSchema: DecodeOutputSchema,
1336
1383
  annotations: PURE_TOOL_ANNOTATIONS
@@ -1347,7 +1394,7 @@ function createPeacMcpServer(options) {
1347
1394
  "peac_issue",
1348
1395
  {
1349
1396
  title: "Issue PEAC Receipt",
1350
- description: "Sign and return a PEAC receipt JWS. Requires server to be configured with --issuer-key and --issuer-id.",
1397
+ description: "Sign and return a new PEAC receipt JWS. Requires server configured with an Ed25519 issuer key (--issuer-key and --issuer-id).",
1351
1398
  inputSchema: IssueInputSchema,
1352
1399
  outputSchema: IssueOutputSchema,
1353
1400
  annotations: ISSUE_TOOL_ANNOTATIONS
@@ -1364,7 +1411,7 @@ function createPeacMcpServer(options) {
1364
1411
  "peac_create_bundle",
1365
1412
  {
1366
1413
  title: "Create Evidence Bundle",
1367
- description: "Create a signed evidence bundle directory from receipt JWS strings. Requires --issuer-key, --issuer-id, and --bundle-dir.",
1414
+ description: "Create a signed evidence bundle directory from one or more receipt JWS strings. Writes files to disk. Requires --issuer-key, --issuer-id, and --bundle-dir.",
1368
1415
  inputSchema: BundleInputSchema,
1369
1416
  outputSchema: BundleOutputSchema,
1370
1417
  annotations: BUNDLE_TOOL_ANNOTATIONS
@@ -1405,9 +1452,9 @@ var JwksConfigSchema = zod.z.object({
1405
1452
  var PolicySchema = zod.z.object({
1406
1453
  version: zod.z.literal("1"),
1407
1454
  allow_network: zod.z.boolean().default(false),
1408
- redaction: RedactionSchema.default({}),
1409
- tools: zod.z.record(zod.z.string(), ToolPolicySchema).default({}),
1410
- limits: LimitsSchema.default({}),
1455
+ redaction: RedactionSchema.prefault({}),
1456
+ tools: zod.z.record(zod.z.string(), ToolPolicySchema).prefault({}),
1457
+ limits: LimitsSchema.prefault({}),
1411
1458
  jwks: JwksConfigSchema.optional()
1412
1459
  });
1413
1460
  var DEFAULT_POLICY = {