@thehammer/danx-dashboard-mcp 0.1.203 → 0.1.204

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
@@ -87,6 +87,7 @@ import { z } from "zod";
87
87
  import { DashboardHttpClient } from "./http-client.js";
88
88
  import { planConnect, danxbotApi, danxbotApiList, danxbotApiSpec, attachFile, DANXBOT_API_METHODS, } from "./handlers.js";
89
89
  import { bodyValueSchema, queryValueSchema } from "./types.js";
90
+ import { termsAcceptanceCallHalt, termsHaltFor } from "./terms-halt.js";
90
91
  import { danxbotApiExamplesText } from "./danxbot-api-examples.js";
91
92
  import { registerLifecycleTools, applyLifecycleVisibility, readLifecycleUrlsFromEnv, } from "./lifecycle.js";
92
93
  function readEnvOrDie(name) {
@@ -279,6 +280,9 @@ export const server = new McpServer({
279
280
  name: "danx-dashboard-mcp",
280
281
  version: "0.1.0",
281
282
  }, { instructions: SERVER_INSTRUCTIONS });
283
+ function haltResult(text) {
284
+ return { content: [{ type: "text", text }], isError: true };
285
+ }
282
286
  function jsonResult(value) {
283
287
  return {
284
288
  content: [{ type: "text", text: JSON.stringify(value, null, 2) }],
@@ -386,7 +390,17 @@ strictTool("danxbot_api", "Call any dashboard API route your credential may reac
386
390
  },
387
391
  // DX-3997 — the result rides back verbatim, plus the dashboard's own `reminders[]` entries
388
392
  // for this plan-connected session (the server decides; `listener-reminder.ts` only relays).
389
- async (args) => jsonResult(await listenerReminder.apply(await danxbotApi(client, args))));
393
+ async (args) => {
394
+ // DX-4148 — an agent never accepts the Terms, and a terms refusal halts it (see terms-halt.ts).
395
+ const refused = termsAcceptanceCallHalt(args, config.baseUrl);
396
+ if (refused)
397
+ return haltResult(refused);
398
+ const result = await danxbotApi(client, args);
399
+ const halt = termsHaltFor(result);
400
+ if (halt)
401
+ return haltResult(halt);
402
+ return jsonResult(await listenerReminder.apply(result));
403
+ });
390
404
  // ---------------- danxbot_api_list (DX-3465 A5, PLN-11 R-25) ----------------
391
405
  strictTool("danxbot_api_list", "Lists the dashboard API routes your credential may call right now — `[{method, path, summary, permission}]`, " +
392
406
  "one line each, in the route TEMPLATE form `danxbot_api_spec` also expects (e.g. " +
@@ -0,0 +1,33 @@
1
+ const TERMS_ACCEPTANCE_PATH = "/api/account/terms-acceptance";
2
+ // Mirrors `termsAcceptUrl("/")` in src/lib/terms-accept-path.ts (a published package cannot import it);
3
+ // terms-gate.integration.test.ts pins the server's link to the same literal. Only meaningful for an
4
+ // operator session: a dispatch's DANXBOT_DASHBOARD_URL is internal, and agent credentials are never terms-gated.
5
+ const ACCEPT_SCREEN_PATH = "/terms/accept?return=%2F";
6
+ /** Keep in step with `termsRefusalInstruction` in src/dashboard/route-policy.ts. */
7
+ export function haltText(acceptUrl) {
8
+ return ("STOP ALL WORK NOW. The dashboard refuses your access until the person you act for accepts the " +
9
+ "current Terms of Use.\n\n" +
10
+ `Give the person this link to accept them: ${acceptUrl}\n\n` +
11
+ "Do not retry, do not look for another route, and never accept the Terms yourself. " +
12
+ "A dispatched agent ends with danxbot_complete({status: \"failed\", summary}) naming this link, " +
13
+ "and never blocks the card.");
14
+ }
15
+ /** The halt text for a `403 terms_not_accepted` result, or null for any other result. */
16
+ export function termsHaltFor(result) {
17
+ if (result.ok || result.status !== 403)
18
+ return null;
19
+ const body = result.body;
20
+ if (body?.error !== "terms_not_accepted")
21
+ return null;
22
+ if (typeof body.acceptUrl !== "string") {
23
+ throw new Error("[danx-dashboard-mcp] a terms_not_accepted refusal carried no acceptUrl");
24
+ }
25
+ return haltText(body.acceptUrl);
26
+ }
27
+ /** The refusal for a call that would accept the Terms (never an agent's act), or null for any other call. */
28
+ export function termsAcceptanceCallHalt(args, dashboardUrl) {
29
+ const path = args.path.split("?")[0].replace(/\/+$/, "");
30
+ if (args.method !== "POST" || path !== TERMS_ACCEPTANCE_PATH)
31
+ return null;
32
+ return haltText(`${dashboardUrl.replace(/\/+$/, "")}${ACCEPT_SCREEN_PATH}`);
33
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thehammer/danx-dashboard-mcp",
3
- "version": "0.1.203",
3
+ "version": "0.1.204",
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",