@thehammer/danx-dashboard-mcp 0.1.171 → 0.1.172

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/index.js CHANGED
@@ -84,7 +84,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
84
84
  import { z } from "zod";
85
85
  import { DashboardHttpClient } from "./http-client.js";
86
86
  import { planConnect, danxbotApi, danxbotApiList, danxbotApiSpec, attachFile, DANXBOT_API_METHODS, } from "./handlers.js";
87
- import { queryValueSchema } from "./types.js";
87
+ import { bodyValueSchema, queryValueSchema } from "./types.js";
88
88
  import { registerLifecycleTools, applyLifecycleVisibility, readLifecycleUrlsFromEnv, } from "./lifecycle.js";
89
89
  function readEnvOrDie(name) {
90
90
  const v = process.env[name];
@@ -348,7 +348,16 @@ strictTool("danxbot_api", "Call any dashboard API route your credential may reac
348
348
  // elements are restricted to scalars, the only thing a comma-join can
349
349
  // represent losslessly.
350
350
  query: queryValueSchema.optional(),
351
- body: z.unknown().optional(),
351
+ // DX-3685 — was `z.unknown()` (JSON Schema `{}`), which gave the model
352
+ // no structural hint that a body must be an OBJECT, so it sometimes
353
+ // sent `body` as a JSON-encoded string; `http-client.ts` then
354
+ // `JSON.stringify`'d that string again, and every dashboard route
355
+ // refused the resulting JSON-string-literal body with `body: must be an
356
+ // object` (every route's body schema is object-only — see
357
+ // `bodyValueSchema`'s own doc in `types.ts`). A string/array/etc body
358
+ // now fails zod validation at this boundary with a clear message
359
+ // instead of reaching the dashboard malformed.
360
+ body: bodyValueSchema.optional(),
352
361
  ...boardField,
353
362
  }, async (args) => jsonResult(await danxbotApi(client, args)));
354
363
  // ---------------- danxbot_api_list (DX-3465 A5, PLN-11 R-25) ----------------
package/dist/listen.js CHANGED
@@ -284,11 +284,6 @@ function cardList(cards) {
284
284
  * this signal cannot support. See `evaluateIdleNudge`'s own doc comment
285
285
  * (`src/issues/db/session-idle-nudge.ts`) for why a sub-agent-awareness
286
286
  * special case was rejected instead of this wording fix.
287
- *
288
- * DX-3676 — every named card clears every dispatch gate, so if the session
289
- * still cannot work one, the card's recorded state is wrong (DX-3400 sat in
290
- * ToDo with its real blocker only in a comment). The line therefore ends by
291
- * naming each state-correcting move, which is also what stops the nudge.
292
287
  */
293
288
  export function formatNudgeLine(event) {
294
289
  const invalid = invalidNudgeReason(event);
@@ -299,9 +294,7 @@ export function formatNudgeLine(event) {
299
294
  parts.push(`startable: ${cardList(event.startable)}`);
300
295
  if (event.held.length > 0)
301
296
  parts.push(`held: ${cardList(event.held)}`);
302
- return oneLine(`${LINE_PREFIX} this session has not made an MCP call in ${event.idleMinutes}m — ${parts.join("; ")}. ` +
303
- "Work these cards; any you cannot work, update to its true state: open a problem, add depends_on or " +
304
- "conflict_on, block it with the real reason, or rollback_pickup.");
297
+ return oneLine(`${LINE_PREFIX} this session has not made an MCP call in ${event.idleMinutes}m — ${parts.join("; ")}`);
305
298
  }
306
299
  /**
307
300
  * Incremental SSE parser. Comment lines (keep-alives, the connect marker) and
package/dist/types.js CHANGED
@@ -14,3 +14,33 @@ export const queryValueSchema = z.record(z.union([
14
14
  z.record(z.unknown()),
15
15
  z.array(z.union([z.string(), z.number(), z.boolean()])),
16
16
  ]));
17
+ /**
18
+ * DX-3685 — the zod schema for `danxbot_api`'s `body` argument. Every
19
+ * dashboard route that takes a body validates it against a
20
+ * `BodyObjectSchema` (`src/http/body-schema.ts`, this repo) whose top-level
21
+ * `type` is ALWAYS `"object"` — no route ever accepts a body that is a
22
+ * string, an array, or any other JSON type at the top level (a plain-object
23
+ * request is the ONLY shape `validateBody`'s `"object"` case accepts; every
24
+ * other top-level shape hits its `body: must be an object` refusal).
25
+ *
26
+ * The previous schema, `z.unknown()`, compiles to `{}` in the tool's
27
+ * published JSON Schema — "any value, no structural hint at all" — which
28
+ * gave the calling model zero signal that an OBJECT was expected. In
29
+ * production this meant the model sometimes serialized `body` as a
30
+ * JSON-encoded STRING (e.g. `'{"text":"test"}'` instead of
31
+ * `{text:"test"}`); `http-client.ts#request` then ran `JSON.stringify` on
32
+ * that already-stringified value, producing a JSON STRING LITERAL as the
33
+ * wire body instead of a JSON object, which the dashboard's shared body
34
+ * validator correctly rejected with `body: must be an object` on every
35
+ * write (DX-3685).
36
+ *
37
+ * `z.record(z.unknown())` (the same idiom `queryValueSchema` above uses for
38
+ * its own field-tree branch) both (a) advertises `type: "object"` in the
39
+ * published JSON Schema, giving the model the structural hint it was
40
+ * missing, and (b) makes zod itself refuse a string/array/number/etc body
41
+ * at the MCP validation boundary with a clear, actionable
42
+ * `Expected object, received string`-class error — never silently
43
+ * forwarded, and never auto-`JSON.parse`d back into shape (Core Principle 1
44
+ * forbids tolerating a second input shape).
45
+ */
46
+ export const bodyValueSchema = z.record(z.unknown());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thehammer/danx-dashboard-mcp",
3
- "version": "0.1.171",
3
+ "version": "0.1.172",
4
4
  "description": "Stdio MCP server fronting danxbot's dashboard API for agents (operator sessions and dispatched workers alike): the generic danxbot_api/danxbot_api_list/danxbot_api_spec tools reach any route the caller's credential may call, plus dedicated agent-specific tools (plan_connect, danxbot_complete, and other per-dispatch lifecycle callbacks) (DX-3465, PLN-11 R-25).",
5
5
  "license": "MIT",
6
6
  "type": "module",