@peac/mcp-server 0.10.13 → 0.11.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.
@@ -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
  }
@@ -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 = {