mc8yp 2.6.1 → 2.6.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/README.md CHANGED
@@ -276,11 +276,13 @@ There is deliberately no raw-request escape hatch — the typed namespaces are t
276
276
 
277
277
  Operations can be hidden from derivation and discovery by annotating them in the OpenAPI spec with the vendor extension `x-mc8yp-exclude: true` — with no escape hatch, exclusion is absolute for the sandbox.
278
278
 
279
- ### Sandbox surface (`sandbox`) — microservice mode only
279
+ ### Sandbox surface (`sandbox`) — microservice mode only, opt-in
280
280
 
281
- > **Experimental.** Available in deployed microservice mode; not exposed in the local CLI (agent harnesses there bring their own file I/O).
281
+ > **Experimental.** Available in deployed microservice mode only, and **disabled by default**; not exposed in the local CLI (agent harnesses there bring their own file I/O).
282
282
 
283
- In microservice mode, codemode has one more global — `sandbox` — an in-memory shell with a virtual filesystem for wrangling data you fetched from the API (`jq`, `awk`, `sed`, `grep`, `sort`, `uniq`, `cut`, `sqlite3`, …). It has **no network access and no host filesystem access** — it never reaches Cumulocity. Fetch with `c8y`/service namespaces, process in the sandbox, read the result back.
283
+ In microservice mode, codemode has one more optional global — `sandbox` — an in-memory shell with a virtual filesystem for wrangling data you fetched from the API (`jq`, `awk`, `sed`, `grep`, `sort`, `uniq`, `cut`, `sqlite3`, …). It has **no network access and no host filesystem access** — it never reaches Cumulocity. Fetch with `c8y`/service namespaces, process in the sandbox, read the result back.
284
+
285
+ **It is off unless you turn it on.** Enable it per connection with the `mc8yp-enable-sandbox` header or the `enableSandbox` query param (any of empty, `*`, or `true`). Without it, `sandbox` is absent — same as CLI mode.
284
286
 
285
287
  ```js
286
288
  async () => {
package/dist/cli.mjs CHANGED
@@ -1546,7 +1546,7 @@ const consola = createConsola();
1546
1546
  //#endregion
1547
1547
  //#region package.json
1548
1548
  var name = "mc8yp";
1549
- var version = "2.6.1";
1549
+ var version = "2.6.2";
1550
1550
  var description$1 = "Cumulocity IoT MCP Server - Model Context Protocol integration for IoT device management";
1551
1551
  //#endregion
1552
1552
  //#region \0virtual:core-openapi
@@ -58667,7 +58667,7 @@ function createCodeModeGuidePrompt() {
58667
58667
  const namespaceNames = resolvedSpecs ? buildNamespaces(resolvedSpecs, restrictions, allowRules).map((ns) => ns.name) : ["c8y"];
58668
58668
  const policyLines = [...restrictions.map((rule) => `- deny: \`${rule.source}\``), ...allowRules.map((rule) => `- allow: \`${rule.source}\``)];
58669
58669
  const restrictionSection = policyLines.length > 0 ? `\n## Current Connection Access Policy\n${policyLines.join("\n")}\n\nOperations blocked by these rules are omitted from discovery (search/describe) entirely, and any live request that matches a deny rule (or misses the allow list) fails before reaching the tenant.\n` : "";
58670
- const sandboxSection = c8yMcpServer.ctx.custom?.env === "server" ? `\n## Sandbox (scratch compute)
58670
+ const sandboxSection = c8yMcpServer.ctx.custom?.env === "server" && c8yMcpServer.ctx.custom?.enableSandbox ? `\n## Sandbox (scratch compute)
58671
58671
 
58672
58672
  \`sandbox\` is your workspace: a persistent in-memory filesystem + Unix shell, separate from the API. It is where you keep files and process data. When the user asks to save or write a file, write it here (\`sandbox.writeFile\`) — never dump a file into the chat instead. Use the shell for text/data processing that is awkward in plain JS — \`jq\`, \`awk\`, \`sed\`, \`grep\`, \`sort\`, \`uniq\`, \`cut\`, \`sqlite3\`, etc. via \`sandbox.exec\`. It has NO network access and NO host filesystem access; it never reaches Cumulocity. Fetch data with \`c8y\`/namespaces, write it into the sandbox, process it, read the result back.
58673
58673
 
@@ -135162,7 +135162,7 @@ async function execute(functionCode) {
135162
135162
  live = createUnauthenticatedCalls(error instanceof Error ? error.message : String(error));
135163
135163
  }
135164
135164
  const sessionId = c8yMcpServer.ctx.sessionId;
135165
- const sandboxApi = c8yMcpServer.ctx.custom?.env === "server" && sessionId ? buildSandboxApi(sessionId) : void 0;
135165
+ const sandboxApi = c8yMcpServer.ctx.custom?.env === "server" && sessionId && c8yMcpServer.ctx.custom?.enableSandbox ? buildSandboxApi(sessionId) : void 0;
135166
135166
  const result = await (await getSandbox()).run({
135167
135167
  code: ENTRY_SOURCE,
135168
135168
  filename: EXECUTE_ENTRY_PATH,
@@ -135187,16 +135187,19 @@ function getSafetyPreface(env) {
135187
135187
  ].join("\n");
135188
135188
  }
135189
135189
  /**
135190
- * Purpose framing for the `sandbox` workspace. Server-only: deployed sessions
135191
- * always have it, so the always-read tool description can state it plainly. CLI
135192
- * has no sandbox. This is deliberately about PURPOSE (files/data processing
135193
- * live here), not procedure — the observed failure was the agent not realizing
135194
- * the sandbox is where files go and dumping output to chat.
135190
+ * Purpose framing for the `sandbox` workspace. Server-only, and disabled by
135191
+ * default — a connection must opt in (`mc8yp-enable-sandbox` header /
135192
+ * `enableSandbox` query param) before the `sandbox` global exists, so this
135193
+ * always-read tool description cannot assert it is present the way it can
135194
+ * for `codemode`/`docs`. CLI never has a sandbox regardless. This is
135195
+ * deliberately about PURPOSE (files/data processing live here), not
135196
+ * procedure — the observed failure was the agent not realizing the sandbox
135197
+ * is where files go and dumping output to chat.
135195
135198
  * @param env - execution environment.
135196
135199
  */
135197
135200
  function getSandboxNote(env) {
135198
135201
  if (env !== "server") return "";
135199
- return "\nYour workspace — `sandbox`: this session has a persistent in-memory filesystem + Unix shell, separate from the API. It is where you keep files and process data. When the user asks to save or write a file, or when you need to filter/transform/aggregate fetched data (jq, awk, grep, sort, sqlite), do it here — `sandbox.writeFile(path, text)`, `sandbox.readFile(path)`, `sandbox.exec(command)` — never dump a file into the chat instead. Files persist across codemode calls in this session. Full method list: `codemode.describe(\"sandbox\")`.\n";
135202
+ return "\nYour workspace — `sandbox`: if this connection has it enabled (check `typeof sandbox !== 'undefined'`), it is a persistent in-memory filesystem + Unix shell, separate from the API, for keeping files and processing data. When the user asks to save or write a file, or when you need to filter/transform/aggregate fetched data (jq, awk, grep, sort, sqlite), do it here — `sandbox.writeFile(path, text)`, `sandbox.readFile(path)`, `sandbox.exec(command)` — never dump a file into the chat instead. Files persist across codemode calls in this session. Full method list: `codemode.describe(\"sandbox\")`.\n";
135200
135203
  }
135201
135204
  function createCodemodeTool(env) {
135202
135205
  return defineTool({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mc8yp",
3
- "version": "2.6.1",
3
+ "version": "2.6.2",
4
4
  "type": "module",
5
5
  "description": "Cumulocity IoT MCP Server - Model Context Protocol integration for IoT device management",
6
6
  "keywords": [