protect-mcp 0.4.2 → 0.4.4

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
@@ -3,13 +3,15 @@ import {
3
3
  formatSimulation,
4
4
  parseLogFile,
5
5
  simulate
6
- } from "./chunk-VWUN6AI6.mjs";
6
+ } from "./chunk-VIA2B65K.mjs";
7
7
  import {
8
8
  ProtectGateway,
9
9
  initSigning,
10
+ isCedarAvailable,
11
+ loadCedarPolicies,
10
12
  loadPolicy,
11
13
  validateCredentials
12
- } from "./chunk-7HBHIKLN.mjs";
14
+ } from "./chunk-VF3OCG4D.mjs";
13
15
 
14
16
  // src/cli.ts
15
17
  function printHelp() {
@@ -31,6 +33,7 @@ Usage:
31
33
 
32
34
  Options:
33
35
  --policy <path> Policy/config JSON file (default: allow-all)
36
+ --cedar <dir> Cedar policy directory (alternative to --policy, evaluates locally via WASM)
34
37
  --slug <slug> ScopeBlind tenant slug (optional)
35
38
  --enforce Enable enforcement mode (default: shadow mode)
36
39
  --http Start HTTP/SSE server instead of stdio proxy
@@ -42,6 +45,7 @@ Commands:
42
45
  quickstart Zero-config onboarding: init + demo + show receipts in one command
43
46
  init Generate config template, Ed25519 keypair, and sample policy
44
47
  demo Start a demo server wrapped with protect-mcp (see receipts instantly)
48
+ doctor Check your setup: keys, policies, verifier, API connectivity
45
49
  trace <id> Visualize the receipt DAG from a given receipt_id (ASCII tree)
46
50
  status Show tool call statistics from the local decision log
47
51
  digest Generate a human-readable summary of agent activity
@@ -64,6 +68,7 @@ Examples:
64
68
  }
65
69
  function parseArgs(argv) {
66
70
  let policyPath;
71
+ let cedarDir;
67
72
  let slug;
68
73
  let enforce = false;
69
74
  let verbose = false;
@@ -88,6 +93,8 @@ function parseArgs(argv) {
88
93
  process.exit(0);
89
94
  } else if (arg === "--policy" && i + 1 < options.length) {
90
95
  policyPath = options[++i];
96
+ } else if (arg === "--cedar" && i + 1 < options.length) {
97
+ cedarDir = options[++i];
91
98
  } else if (arg === "--slug" && i + 1 < options.length) {
92
99
  slug = options[++i];
93
100
  } else if (arg === "--enforce") {
@@ -99,7 +106,7 @@ function parseArgs(argv) {
99
106
  `);
100
107
  }
101
108
  }
102
- return { policyPath, slug, enforce, verbose, childCommand };
109
+ return { policyPath, cedarDir, slug, enforce, verbose, childCommand };
103
110
  }
104
111
  async function handleInit(argv) {
105
112
  const { writeFileSync, existsSync, mkdirSync } = await import("fs");
@@ -733,7 +740,7 @@ async function handleTrace(argv) {
733
740
  process.stderr.write("[PROTECT_MCP] Usage: protect-mcp trace <receipt_id> [--endpoint <url>] [--depth <n>]\n");
734
741
  process.exit(1);
735
742
  }
736
- let endpoint = "https://evidence-indexer.tomjwxf.workers.dev";
743
+ let endpoint = "https://api.scopeblind.com/evidence";
737
744
  let depth = 3;
738
745
  for (let i = 1; i < argv.length; i++) {
739
746
  if (argv[i] === "--endpoint" && argv[i + 1]) {
@@ -983,12 +990,57 @@ async function main() {
983
990
  await handleReport(args.slice(1));
984
991
  process.exit(0);
985
992
  }
986
- const { policyPath, slug, enforce, verbose, childCommand } = parseArgs(args);
993
+ if (args[0] === "doctor") {
994
+ await handleDoctor();
995
+ process.exit(0);
996
+ }
997
+ const { policyPath, cedarDir, slug, enforce, verbose, childCommand } = parseArgs(args);
987
998
  let policy = null;
988
999
  let policyDigest = "none";
989
1000
  let credentials;
990
1001
  let signing;
991
- if (policyPath) {
1002
+ let cedarPolicySet = null;
1003
+ let effectiveCedarDir = cedarDir;
1004
+ if (!effectiveCedarDir && !policyPath) {
1005
+ const { existsSync, readdirSync } = await import("fs");
1006
+ for (const candidate of ["cedar", "policies", "."]) {
1007
+ try {
1008
+ if (existsSync(candidate) && readdirSync(candidate).some((f) => f.endsWith(".cedar"))) {
1009
+ effectiveCedarDir = candidate;
1010
+ process.stderr.write(`[PROTECT_MCP] Auto-detected Cedar policies in ./${candidate}/
1011
+ `);
1012
+ break;
1013
+ }
1014
+ } catch {
1015
+ }
1016
+ }
1017
+ }
1018
+ if (effectiveCedarDir) {
1019
+ try {
1020
+ const cedarAvailable = await isCedarAvailable();
1021
+ if (!cedarAvailable) {
1022
+ process.stderr.write("[PROTECT_MCP] Warning: @cedar-policy/cedar-wasm not installed. Install with: npm install @cedar-policy/cedar-wasm\n");
1023
+ process.stderr.write("[PROTECT_MCP] Cedar policies will be loaded but evaluated with fallback (allow-all).\n");
1024
+ }
1025
+ cedarPolicySet = loadCedarPolicies(effectiveCedarDir);
1026
+ policyDigest = cedarPolicySet.digest;
1027
+ policy = {
1028
+ tools: { "*": { require: "any" } },
1029
+ policy_engine: "cedar",
1030
+ cedar_dir: effectiveCedarDir
1031
+ };
1032
+ process.stderr.write(`[PROTECT_MCP] Cedar policy engine: loaded ${cedarPolicySet.fileCount} policies from ${effectiveCedarDir} (digest: ${policyDigest})
1033
+ `);
1034
+ if (verbose) {
1035
+ process.stderr.write(`[PROTECT_MCP] Cedar files: ${cedarPolicySet.files.join(", ")}
1036
+ `);
1037
+ }
1038
+ } catch (err) {
1039
+ process.stderr.write(`[PROTECT_MCP] Error loading Cedar policies: ${err instanceof Error ? err.message : err}
1040
+ `);
1041
+ process.exit(1);
1042
+ }
1043
+ } else if (policyPath) {
992
1044
  try {
993
1045
  const loaded = loadPolicy(policyPath);
994
1046
  policy = loaded.policy;
@@ -1034,11 +1086,14 @@ async function main() {
1034
1086
  if (useHttp) {
1035
1087
  const portIdx = args.indexOf("--port");
1036
1088
  const httpPort = portIdx >= 0 && args[portIdx + 1] ? parseInt(args[portIdx + 1]) : 3e3;
1037
- const { startHttpTransport } = await import("./http-transport-RIVV2RVQ.mjs");
1089
+ const { startHttpTransport } = await import("./http-transport-VLIPOPIC.mjs");
1038
1090
  startHttpTransport({ port: httpPort, config, serverCommand: childCommand });
1039
1091
  return;
1040
1092
  }
1041
1093
  const gateway = new ProtectGateway(config);
1094
+ if (cedarPolicySet) {
1095
+ gateway.setCedarPolicies(cedarPolicySet);
1096
+ }
1042
1097
  await gateway.start();
1043
1098
  }
1044
1099
  async function handleSimulate(args) {
@@ -1083,6 +1138,127 @@ async function handleSimulate(args) {
1083
1138
  process.stdout.write(formatSimulation(summary) + "\n");
1084
1139
  }
1085
1140
  }
1141
+ async function handleDoctor() {
1142
+ const { existsSync, readFileSync, readdirSync } = await import("fs");
1143
+ const { join } = await import("path");
1144
+ const { execSync } = await import("child_process");
1145
+ const green2 = (s) => `\x1B[32m\u2713\x1B[0m ${s}`;
1146
+ const red2 = (s) => `\x1B[31m\u2717\x1B[0m ${s}`;
1147
+ const yellow2 = (s) => `\x1B[33m\u26A0\x1B[0m ${s}`;
1148
+ const dim2 = (s) => `\x1B[2m${s}\x1B[0m`;
1149
+ process.stdout.write("\n\x1B[1mprotect-mcp doctor\x1B[0m\n");
1150
+ process.stdout.write(dim2("Checking your ScopeBlind setup...\n\n"));
1151
+ let issues = 0;
1152
+ const nodeVersion = process.version;
1153
+ const major = parseInt(nodeVersion.slice(1));
1154
+ if (major >= 18) {
1155
+ process.stdout.write(green2(`Node.js ${nodeVersion}
1156
+ `));
1157
+ } else {
1158
+ process.stdout.write(red2(`Node.js ${nodeVersion} \u2014 requires >= 18
1159
+ `));
1160
+ issues++;
1161
+ }
1162
+ const configPath = join(process.cwd(), "scopeblind.config.json");
1163
+ if (existsSync(configPath)) {
1164
+ try {
1165
+ const config = JSON.parse(readFileSync(configPath, "utf-8"));
1166
+ if (config.signing?.private_key || config.signing?.key_file) {
1167
+ process.stdout.write(green2("Signing keys configured\n"));
1168
+ } else {
1169
+ process.stdout.write(yellow2("Config found but no signing keys \u2014 run: protect-mcp init\n"));
1170
+ issues++;
1171
+ }
1172
+ } catch {
1173
+ process.stdout.write(red2("Invalid scopeblind.config.json\n"));
1174
+ issues++;
1175
+ }
1176
+ } else {
1177
+ process.stdout.write(yellow2("No scopeblind.config.json \u2014 run: protect-mcp init\n"));
1178
+ }
1179
+ let policyFound = false;
1180
+ for (const dir of ["cedar", "policies", "."]) {
1181
+ try {
1182
+ if (existsSync(dir) && readdirSync(dir).some((f) => f.endsWith(".cedar"))) {
1183
+ process.stdout.write(green2(`Cedar policies found in ./${dir}/
1184
+ `));
1185
+ policyFound = true;
1186
+ break;
1187
+ }
1188
+ } catch {
1189
+ }
1190
+ }
1191
+ if (!policyFound) {
1192
+ for (const name of ["policy.json", "protect-mcp.policy.json", "scopeblind-policy.json"]) {
1193
+ if (existsSync(name)) {
1194
+ process.stdout.write(green2(`JSON policy found: ${name}
1195
+ `));
1196
+ policyFound = true;
1197
+ break;
1198
+ }
1199
+ }
1200
+ }
1201
+ if (!policyFound) {
1202
+ process.stdout.write(yellow2("No policy files found \u2014 running in shadow mode (allow all)\n"));
1203
+ }
1204
+ try {
1205
+ const cedarAvailable = await isCedarAvailable();
1206
+ if (cedarAvailable) {
1207
+ process.stdout.write(green2("Cedar WASM engine available\n"));
1208
+ } else {
1209
+ process.stdout.write(dim2(" Cedar WASM not installed \u2014 install: npm install @cedar-policy/cedar-wasm\n"));
1210
+ }
1211
+ } catch {
1212
+ process.stdout.write(dim2(" Cedar WASM not installed\n"));
1213
+ }
1214
+ const logFile = join(process.cwd(), "protect-mcp-decisions.jsonl");
1215
+ const receiptFile = join(process.cwd(), "protect-mcp-receipts.jsonl");
1216
+ if (existsSync(logFile)) {
1217
+ try {
1218
+ const lines = readFileSync(logFile, "utf-8").trim().split("\n").length;
1219
+ process.stdout.write(green2(`Decision log: ${lines} entries
1220
+ `));
1221
+ } catch {
1222
+ process.stdout.write(green2("Decision log exists\n"));
1223
+ }
1224
+ } else {
1225
+ process.stdout.write(dim2(" No decision log yet \u2014 will be created on first tool call\n"));
1226
+ }
1227
+ if (existsSync(receiptFile)) {
1228
+ try {
1229
+ const lines = readFileSync(receiptFile, "utf-8").trim().split("\n").length;
1230
+ process.stdout.write(green2(`Receipt file: ${lines} signed receipts
1231
+ `));
1232
+ } catch {
1233
+ process.stdout.write(green2("Receipt file exists\n"));
1234
+ }
1235
+ }
1236
+ try {
1237
+ execSync("npx @veritasacta/verify --version 2>/dev/null", { stdio: "pipe", timeout: 1e4 });
1238
+ process.stdout.write(green2("Verifier available: @veritasacta/verify\n"));
1239
+ } catch {
1240
+ process.stdout.write(dim2(" Verifier not cached \u2014 install: npm install -g @veritasacta/verify\n"));
1241
+ }
1242
+ try {
1243
+ const res = await fetch("https://api.scopeblind.com/health", { signal: AbortSignal.timeout(5e3) });
1244
+ if (res.ok) {
1245
+ process.stdout.write(green2("ScopeBlind API reachable\n"));
1246
+ } else {
1247
+ process.stdout.write(yellow2("ScopeBlind API returned non-200 \u2014 receipts will be stored locally\n"));
1248
+ }
1249
+ } catch {
1250
+ process.stdout.write(dim2(" ScopeBlind API not reachable \u2014 offline mode (receipts stored locally)\n"));
1251
+ }
1252
+ process.stdout.write("\n");
1253
+ if (issues === 0) {
1254
+ process.stdout.write("\x1B[32m\x1B[1mAll checks passed.\x1B[0m Ready to wrap MCP servers.\n");
1255
+ process.stdout.write(dim2("\n npx protect-mcp -- node your-server.js\n\n"));
1256
+ } else {
1257
+ process.stdout.write(`\x1B[33m\x1B[1m${issues} issue(s) found.\x1B[0m Fix them and run doctor again.
1258
+
1259
+ `);
1260
+ }
1261
+ }
1086
1262
  async function handleReport(args) {
1087
1263
  let period = 30;
1088
1264
  let format = "json";
@@ -1 +1,107 @@
1
1
  #!/usr/bin/env node
2
+ /**
3
+ * @scopeblind/protect-mcp — Built-in Demo MCP Server
4
+ *
5
+ * A minimal MCP server (JSON-RPC over stdio) that registers 5 demo tools.
6
+ * Used by `protect-mcp demo` to let users see receipts flowing
7
+ * without having their own MCP server.
8
+ *
9
+ * Tools:
10
+ * - read_file (safe, high-frequency)
11
+ * - write_file (medium risk)
12
+ * - delete_file (destructive, blocked by default policy)
13
+ * - web_search (rate-limited)
14
+ * - deploy (high-privilege)
15
+ */
16
+ interface JsonRpcRequest {
17
+ jsonrpc: '2.0';
18
+ id?: string | number;
19
+ method: string;
20
+ params?: Record<string, unknown>;
21
+ }
22
+ declare function handleRequest(request: JsonRpcRequest): string;
23
+ /**
24
+ * Smithery sandbox server — returns a minimal MCP server instance
25
+ * that Smithery can scan for tool/resource capabilities.
26
+ */
27
+ declare function createSandboxServer(): {
28
+ tools: ({
29
+ name: string;
30
+ description: string;
31
+ inputSchema: {
32
+ type: string;
33
+ properties: {
34
+ path: {
35
+ type: string;
36
+ description: string;
37
+ };
38
+ content?: undefined;
39
+ query?: undefined;
40
+ environment?: undefined;
41
+ reason?: undefined;
42
+ };
43
+ required: string[];
44
+ };
45
+ } | {
46
+ name: string;
47
+ description: string;
48
+ inputSchema: {
49
+ type: string;
50
+ properties: {
51
+ path: {
52
+ type: string;
53
+ description: string;
54
+ };
55
+ content: {
56
+ type: string;
57
+ description: string;
58
+ };
59
+ query?: undefined;
60
+ environment?: undefined;
61
+ reason?: undefined;
62
+ };
63
+ required: string[];
64
+ };
65
+ } | {
66
+ name: string;
67
+ description: string;
68
+ inputSchema: {
69
+ type: string;
70
+ properties: {
71
+ query: {
72
+ type: string;
73
+ description: string;
74
+ };
75
+ path?: undefined;
76
+ content?: undefined;
77
+ environment?: undefined;
78
+ reason?: undefined;
79
+ };
80
+ required: string[];
81
+ };
82
+ } | {
83
+ name: string;
84
+ description: string;
85
+ inputSchema: {
86
+ type: string;
87
+ properties: {
88
+ environment: {
89
+ type: string;
90
+ description: string;
91
+ enum: string[];
92
+ };
93
+ reason: {
94
+ type: string;
95
+ description: string;
96
+ };
97
+ path?: undefined;
98
+ content?: undefined;
99
+ query?: undefined;
100
+ };
101
+ required: string[];
102
+ };
103
+ })[];
104
+ handleRequest: typeof handleRequest;
105
+ };
106
+
107
+ export { createSandboxServer };
@@ -1 +1,107 @@
1
1
  #!/usr/bin/env node
2
+ /**
3
+ * @scopeblind/protect-mcp — Built-in Demo MCP Server
4
+ *
5
+ * A minimal MCP server (JSON-RPC over stdio) that registers 5 demo tools.
6
+ * Used by `protect-mcp demo` to let users see receipts flowing
7
+ * without having their own MCP server.
8
+ *
9
+ * Tools:
10
+ * - read_file (safe, high-frequency)
11
+ * - write_file (medium risk)
12
+ * - delete_file (destructive, blocked by default policy)
13
+ * - web_search (rate-limited)
14
+ * - deploy (high-privilege)
15
+ */
16
+ interface JsonRpcRequest {
17
+ jsonrpc: '2.0';
18
+ id?: string | number;
19
+ method: string;
20
+ params?: Record<string, unknown>;
21
+ }
22
+ declare function handleRequest(request: JsonRpcRequest): string;
23
+ /**
24
+ * Smithery sandbox server — returns a minimal MCP server instance
25
+ * that Smithery can scan for tool/resource capabilities.
26
+ */
27
+ declare function createSandboxServer(): {
28
+ tools: ({
29
+ name: string;
30
+ description: string;
31
+ inputSchema: {
32
+ type: string;
33
+ properties: {
34
+ path: {
35
+ type: string;
36
+ description: string;
37
+ };
38
+ content?: undefined;
39
+ query?: undefined;
40
+ environment?: undefined;
41
+ reason?: undefined;
42
+ };
43
+ required: string[];
44
+ };
45
+ } | {
46
+ name: string;
47
+ description: string;
48
+ inputSchema: {
49
+ type: string;
50
+ properties: {
51
+ path: {
52
+ type: string;
53
+ description: string;
54
+ };
55
+ content: {
56
+ type: string;
57
+ description: string;
58
+ };
59
+ query?: undefined;
60
+ environment?: undefined;
61
+ reason?: undefined;
62
+ };
63
+ required: string[];
64
+ };
65
+ } | {
66
+ name: string;
67
+ description: string;
68
+ inputSchema: {
69
+ type: string;
70
+ properties: {
71
+ query: {
72
+ type: string;
73
+ description: string;
74
+ };
75
+ path?: undefined;
76
+ content?: undefined;
77
+ environment?: undefined;
78
+ reason?: undefined;
79
+ };
80
+ required: string[];
81
+ };
82
+ } | {
83
+ name: string;
84
+ description: string;
85
+ inputSchema: {
86
+ type: string;
87
+ properties: {
88
+ environment: {
89
+ type: string;
90
+ description: string;
91
+ enum: string[];
92
+ };
93
+ reason: {
94
+ type: string;
95
+ description: string;
96
+ };
97
+ path?: undefined;
98
+ content?: undefined;
99
+ query?: undefined;
100
+ };
101
+ required: string[];
102
+ };
103
+ })[];
104
+ handleRequest: typeof handleRequest;
105
+ };
106
+
107
+ export { createSandboxServer };
@@ -1,7 +1,29 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
3
20
 
4
21
  // src/demo-server.ts
22
+ var demo_server_exports = {};
23
+ __export(demo_server_exports, {
24
+ createSandboxServer: () => createSandboxServer
25
+ });
26
+ module.exports = __toCommonJS(demo_server_exports);
5
27
  var import_node_readline = require("readline");
6
28
  var TOOLS = [
7
29
  {
@@ -135,3 +157,13 @@ rl.on("line", (line) => {
135
157
  }
136
158
  });
137
159
  process.stderr.write("[DEMO_SERVER] protect-mcp demo server started \u2014 5 tools registered\n");
160
+ function createSandboxServer() {
161
+ return {
162
+ tools: TOOLS,
163
+ handleRequest
164
+ };
165
+ }
166
+ // Annotate the CommonJS export names for ESM import in node:
167
+ 0 && (module.exports = {
168
+ createSandboxServer
169
+ });
@@ -1,136 +1,7 @@
1
1
  #!/usr/bin/env node
2
-
3
- // src/demo-server.ts
4
- import { createInterface } from "readline";
5
- var TOOLS = [
6
- {
7
- name: "read_file",
8
- description: "Read the contents of a file",
9
- inputSchema: {
10
- type: "object",
11
- properties: { path: { type: "string", description: "File path to read" } },
12
- required: ["path"]
13
- }
14
- },
15
- {
16
- name: "write_file",
17
- description: "Write content to a file",
18
- inputSchema: {
19
- type: "object",
20
- properties: {
21
- path: { type: "string", description: "File path to write" },
22
- content: { type: "string", description: "Content to write" }
23
- },
24
- required: ["path", "content"]
25
- }
26
- },
27
- {
28
- name: "delete_file",
29
- description: "Delete a file from the filesystem",
30
- inputSchema: {
31
- type: "object",
32
- properties: { path: { type: "string", description: "File path to delete" } },
33
- required: ["path"]
34
- }
35
- },
36
- {
37
- name: "web_search",
38
- description: "Search the web for information",
39
- inputSchema: {
40
- type: "object",
41
- properties: { query: { type: "string", description: "Search query" } },
42
- required: ["query"]
43
- }
44
- },
45
- {
46
- name: "deploy",
47
- description: "Deploy the application to production",
48
- inputSchema: {
49
- type: "object",
50
- properties: {
51
- environment: { type: "string", description: "Target environment", enum: ["staging", "production"] },
52
- reason: { type: "string", description: "Deployment reason" }
53
- },
54
- required: ["environment"]
55
- }
56
- }
57
- ];
58
- function handleRequest(request) {
59
- if (request.method === "initialize") {
60
- return JSON.stringify({
61
- jsonrpc: "2.0",
62
- id: request.id,
63
- result: {
64
- protocolVersion: "2024-11-05",
65
- serverInfo: { name: "protect-mcp-demo", version: "0.2.0" },
66
- capabilities: { tools: {} }
67
- }
68
- });
69
- }
70
- if (request.method === "notifications/initialized") {
71
- return "";
72
- }
73
- if (request.method === "tools/list") {
74
- return JSON.stringify({
75
- jsonrpc: "2.0",
76
- id: request.id,
77
- result: { tools: TOOLS }
78
- });
79
- }
80
- if (request.method === "tools/call") {
81
- const toolName = request.params?.name || "unknown";
82
- const args = request.params?.arguments || {};
83
- let resultText;
84
- switch (toolName) {
85
- case "read_file":
86
- resultText = `[demo] Read file: ${args.path || "/example.txt"}
87
- Contents: Hello from protect-mcp demo server!`;
88
- break;
89
- case "write_file":
90
- resultText = `[demo] Wrote ${String(args.content || "").length} bytes to ${args.path || "/example.txt"}`;
91
- break;
92
- case "delete_file":
93
- resultText = `[demo] Deleted file: ${args.path || "/example.txt"}`;
94
- break;
95
- case "web_search":
96
- resultText = `[demo] Search results for "${args.query || "test"}":
97
- 1. Example result \u2014 scopeblind.com
98
- 2. MCP security \u2014 modelcontextprotocol.io`;
99
- break;
100
- case "deploy":
101
- resultText = `[demo] Deployed to ${args.environment || "staging"}${args.reason ? ` (reason: ${args.reason})` : ""}`;
102
- break;
103
- default:
104
- resultText = `[demo] Unknown tool: ${toolName}`;
105
- }
106
- return JSON.stringify({
107
- jsonrpc: "2.0",
108
- id: request.id,
109
- result: {
110
- content: [{ type: "text", text: resultText }]
111
- }
112
- });
113
- }
114
- if (request.id !== void 0) {
115
- return JSON.stringify({
116
- jsonrpc: "2.0",
117
- id: request.id,
118
- error: { code: -32601, message: `Method not found: ${request.method}` }
119
- });
120
- }
121
- return "";
122
- }
123
- var rl = createInterface({ input: process.stdin, crlfDelay: Infinity });
124
- rl.on("line", (line) => {
125
- const trimmed = line.trim();
126
- if (!trimmed) return;
127
- try {
128
- const request = JSON.parse(trimmed);
129
- const response = handleRequest(request);
130
- if (response) {
131
- process.stdout.write(response + "\n");
132
- }
133
- } catch {
134
- }
135
- });
136
- process.stderr.write("[DEMO_SERVER] protect-mcp demo server started \u2014 5 tools registered\n");
2
+ import {
3
+ createSandboxServer
4
+ } from "./chunk-U76JZVH6.mjs";
5
+ export {
6
+ createSandboxServer
7
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ProtectGateway
3
- } from "./chunk-7HBHIKLN.mjs";
3
+ } from "./chunk-VF3OCG4D.mjs";
4
4
 
5
5
  // src/http-transport.ts
6
6
  import { createServer } from "http";