@signal4/s4 2.6.1 → 2.8.0

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.
Files changed (76) hide show
  1. package/README.md +60 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +407 -196
  4. package/dist/cli.js.map +1 -1
  5. package/dist/cli_args.d.ts +24 -0
  6. package/dist/cli_args.d.ts.map +1 -0
  7. package/dist/cli_args.js +130 -0
  8. package/dist/cli_args.js.map +1 -0
  9. package/dist/client.d.ts +103 -3
  10. package/dist/client.d.ts.map +1 -1
  11. package/dist/client.js +195 -23
  12. package/dist/client.js.map +1 -1
  13. package/dist/format.d.ts +103 -4
  14. package/dist/format.d.ts.map +1 -1
  15. package/dist/format.js +299 -64
  16. package/dist/format.js.map +1 -1
  17. package/dist/handler_types.d.ts +10 -0
  18. package/dist/handler_types.d.ts.map +1 -1
  19. package/dist/handler_types.js +25 -0
  20. package/dist/handler_types.js.map +1 -1
  21. package/dist/handlers/ads.js +4 -4
  22. package/dist/handlers/ads.js.map +1 -1
  23. package/dist/handlers/analyze.d.ts.map +1 -1
  24. package/dist/handlers/analyze.js +22 -6
  25. package/dist/handlers/analyze.js.map +1 -1
  26. package/dist/handlers/bookmarks.js +2 -2
  27. package/dist/handlers/bookmarks.js.map +1 -1
  28. package/dist/handlers/claim_detail.d.ts.map +1 -1
  29. package/dist/handlers/claim_detail.js +18 -10
  30. package/dist/handlers/claim_detail.js.map +1 -1
  31. package/dist/handlers/claims.d.ts.map +1 -1
  32. package/dist/handlers/claims.js +72 -27
  33. package/dist/handlers/claims.js.map +1 -1
  34. package/dist/handlers/count.d.ts +14 -0
  35. package/dist/handlers/count.d.ts.map +1 -0
  36. package/dist/handlers/count.js +158 -0
  37. package/dist/handlers/count.js.map +1 -0
  38. package/dist/handlers/explore.d.ts.map +1 -1
  39. package/dist/handlers/explore.js +56 -14
  40. package/dist/handlers/explore.js.map +1 -1
  41. package/dist/handlers/registry.d.ts.map +1 -1
  42. package/dist/handlers/registry.js +5 -1
  43. package/dist/handlers/registry.js.map +1 -1
  44. package/dist/handlers/reports.d.ts +6 -0
  45. package/dist/handlers/reports.d.ts.map +1 -1
  46. package/dist/handlers/reports.js +140 -26
  47. package/dist/handlers/reports.js.map +1 -1
  48. package/dist/handlers/search.d.ts.map +1 -1
  49. package/dist/handlers/search.js +80 -23
  50. package/dist/handlers/search.js.map +1 -1
  51. package/dist/handlers/timeline.d.ts.map +1 -1
  52. package/dist/handlers/timeline.js +14 -8
  53. package/dist/handlers/timeline.js.map +1 -1
  54. package/dist/http.js +25 -3
  55. package/dist/http.js.map +1 -1
  56. package/dist/index.js +2 -2
  57. package/dist/index.js.map +1 -1
  58. package/dist/provenance.d.ts +29 -2
  59. package/dist/provenance.d.ts.map +1 -1
  60. package/dist/provenance.js +63 -4
  61. package/dist/provenance.js.map +1 -1
  62. package/dist/server_core.d.ts +8 -1
  63. package/dist/server_core.d.ts.map +1 -1
  64. package/dist/server_core.js +90 -8
  65. package/dist/server_core.js.map +1 -1
  66. package/dist/speed.d.ts +40 -0
  67. package/dist/speed.d.ts.map +1 -0
  68. package/dist/speed.js +214 -0
  69. package/dist/speed.js.map +1 -0
  70. package/dist/surface.d.ts +7 -0
  71. package/dist/surface.d.ts.map +1 -0
  72. package/dist/surface.js +19 -0
  73. package/dist/surface.js.map +1 -0
  74. package/dist/types.d.ts +249 -15
  75. package/dist/types.d.ts.map +1 -1
  76. package/package.json +3 -2
@@ -1,22 +1,25 @@
1
1
  /** Timeline handler: get_timeline */
2
2
  import * as client from "../client.js";
3
3
  import { formatTimeline } from "../format.js";
4
- import { mcpWindowFooter } from "../provenance.js";
5
- import { wantsJson, jsonResult } from "../handler_types.js";
4
+ import { mcpWindowFooter, scopeFooter } from "../provenance.js";
5
+ import { wantsJson, jsonResult, collectionOf } from "../handler_types.js";
6
6
  export async function handleGetTimeline(params) {
7
7
  const topic = params.topic;
8
8
  if (!topic) {
9
- return { content: [{ type: "text", text: "Error: topic is required." }] };
9
+ return { content: [{ type: "text", text: "Error: topic is required." }], isError: true };
10
10
  }
11
11
  const days = params.days ?? 30;
12
- const startDate = params.start_date ?? new Date(Date.now() - days * 86400000).toISOString().slice(0, 10);
13
12
  const endDate = params.end_date ?? new Date().toISOString().slice(0, 10);
13
+ const endMs = Date.parse(endDate);
14
+ const startDate = params.start_date
15
+ ?? new Date((Number.isNaN(endMs) ? Date.now() : endMs) - days * 86400000).toISOString().slice(0, 10);
14
16
  const speakerName = (params.speaker ?? params.speaker_name);
15
17
  const channelName = (params.channel ?? params.channel_name);
16
18
  const channelNames = channelName?.split(",").map(s => s.trim()).filter(Boolean);
17
19
  const language = params.language;
18
20
  const granularity = params.granularity ?? "day";
19
21
  const minSimilarity = params.min_similarity;
22
+ const project = collectionOf(params);
20
23
  const data = await client.getTimeline({
21
24
  topic,
22
25
  speaker_name: speakerName,
@@ -26,14 +29,17 @@ export async function handleGetTimeline(params) {
26
29
  language,
27
30
  granularity,
28
31
  min_similarity: minSimilarity,
32
+ project,
29
33
  });
30
34
  if (wantsJson(params))
31
35
  return jsonResult(data);
36
+ const explicit = params.start_date != null || params.end_date != null;
32
37
  const footer = mcpWindowFooter({
33
- startDate, endDate,
34
- days: params.start_date == null ? days : undefined,
35
- defaultWindow: params.start_date == null && params.days == null,
38
+ startDate: data.window?.start_date ?? startDate,
39
+ endDate: data.window?.end_date ?? endDate,
40
+ days: explicit ? undefined : days,
41
+ defaultWindow: !explicit && params.days == null,
36
42
  });
37
- return { content: [{ type: "text", text: formatTimeline(data, footer) }] };
43
+ return { content: [{ type: "text", text: formatTimeline(data, footer + scopeFooter(data.scope, project)) }] };
38
44
  }
39
45
  //# sourceMappingURL=timeline.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"timeline.js","sourceRoot":"","sources":["../../src/handlers/timeline.ts"],"names":[],"mappings":"AAAA,qCAAqC;AAErC,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAG5D,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAA+B;IACrE,MAAM,KAAK,GAAG,MAAM,CAAC,KAAe,CAAC;IACrC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,2BAA2B,EAAE,CAAC,EAAE,CAAC;IAC5E,CAAC;IAED,MAAM,IAAI,GAAI,MAAM,CAAC,IAAe,IAAI,EAAE,CAAC;IAC3C,MAAM,SAAS,GAAI,MAAM,CAAC,UAAqB,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,GAAG,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACrH,MAAM,OAAO,GAAI,MAAM,CAAC,QAAmB,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACrF,MAAM,WAAW,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,YAAY,CAAuB,CAAC;IAClF,MAAM,WAAW,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,YAAY,CAAuB,CAAC;IAClF,MAAM,YAAY,GAAG,WAAW,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAChF,MAAM,QAAQ,GAAG,MAAM,CAAC,QAA8B,CAAC;IACvD,MAAM,WAAW,GAAI,MAAM,CAAC,WAAsB,IAAI,KAAK,CAAC;IAC5D,MAAM,aAAa,GAAG,MAAM,CAAC,cAAoC,CAAC;IAElE,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC;QACpC,KAAK;QACL,YAAY,EAAE,WAAW;QACzB,aAAa,EAAE,YAAY;QAC3B,UAAU,EAAE,SAAS;QACrB,QAAQ,EAAE,OAAO;QACjB,QAAQ;QACR,WAAW;QACX,cAAc,EAAE,aAAa;KAC9B,CAAC,CAAC;IAEH,IAAI,SAAS,CAAC,MAAM,CAAC;QAAE,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC;IAE/C,MAAM,MAAM,GAAG,eAAe,CAAC;QAC7B,SAAS,EAAE,OAAO;QAClB,IAAI,EAAE,MAAM,CAAC,UAAU,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;QAClD,aAAa,EAAE,MAAM,CAAC,UAAU,IAAI,IAAI,IAAI,MAAM,CAAC,IAAI,IAAI,IAAI;KAChE,CAAC,CAAC;IACH,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;AAC7E,CAAC"}
1
+ {"version":3,"file":"timeline.js","sourceRoot":"","sources":["../../src/handlers/timeline.ts"],"names":[],"mappings":"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"}
package/dist/http.js CHANGED
@@ -17,7 +17,7 @@ import { createServer } from "node:http";
17
17
  import { parseArgs } from "node:util";
18
18
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
19
19
  import { withApiKey } from "./client.js";
20
- import { buildServer, CachedManifest } from "./server_core.js";
20
+ import { buildServer, CachedManifest, loadInstructions } from "./server_core.js";
21
21
  // ---------------------------------------------------------------------------
22
22
  // Per-key manifest cache
23
23
  //
@@ -80,17 +80,19 @@ async function handleMcpRequest(req, res) {
80
80
  sendJson(res, 401, { detail: "Invalid API key format. Signal4 keys start with 'sk_'." });
81
81
  return;
82
82
  }
83
- const server = buildServer(manifestFor(key));
83
+ const provider = manifestFor(key);
84
84
  const transport = new StreamableHTTPServerTransport({
85
85
  sessionIdGenerator: undefined, // stateless mode
86
86
  });
87
+ let server;
87
88
  res.on("close", () => {
88
89
  void transport.close();
89
- void server.close();
90
+ void server?.close();
90
91
  });
91
92
  // Everything the MCP handlers do — manifest fetch, tool handler backend
92
93
  // calls — runs inside this key's context, so client.ts sends THIS key.
93
94
  await withApiKey(key, async () => {
95
+ server = buildServer(provider, await loadInstructions(provider));
94
96
  await server.connect(transport);
95
97
  await transport.handleRequest(req, res);
96
98
  });
@@ -129,4 +131,24 @@ httpServer.listen(port, args.host, () => {
129
131
  console.log(`Signal4 MCP (streamable-http) listening on http://${args.host}:${port}/mcp ` +
130
132
  `(backend: ${process.env.SIGNAL4_API_URL ?? "https://api.signal4.ca"})`);
131
133
  });
134
+ // ---------------------------------------------------------------------------
135
+ // Graceful stop
136
+ // ---------------------------------------------------------------------------
137
+ // Deploys restart one MCP instance at a time behind Caddy (signal4#306). On
138
+ // SIGINT/SIGTERM stop accepting — Caddy sends new requests to the other
139
+ // instance — and let in-flight tool calls finish (a paid analysis can run for
140
+ // minutes) before exiting. Node's default was to die mid-response. PM2's
141
+ // kill_timeout (160s) is the backstop above this 150s cap.
142
+ let stopping = false;
143
+ function shutdown(signal) {
144
+ if (stopping)
145
+ return;
146
+ stopping = true;
147
+ console.log(`Received ${signal}: finishing in-flight requests, then exiting`);
148
+ httpServer.close(() => process.exit(0));
149
+ httpServer.closeIdleConnections();
150
+ setTimeout(() => process.exit(0), 150_000).unref();
151
+ }
152
+ process.on("SIGINT", shutdown);
153
+ process.on("SIGTERM", shutdown);
132
154
  //# sourceMappingURL=http.js.map
package/dist/http.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@
8
8
  */
9
9
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
10
10
  import { applyConfig } from "./config.js";
11
- import { buildServer, CachedManifest } from "./server_core.js";
11
+ import { buildServer, CachedManifest, loadInstructions } from "./server_core.js";
12
12
  applyConfig();
13
13
  // Single global manifest cache keyed by the env key, cached for the session.
14
14
  const manifest = new CachedManifest({
@@ -17,8 +17,8 @@ const manifest = new CachedManifest({
17
17
  : "SIGNAL4_API_KEY environment variable is not set. " +
18
18
  "Get your API key from Signal4 and set it in your MCP server config.",
19
19
  });
20
- const server = buildServer(manifest);
21
20
  async function main() {
21
+ const server = buildServer(manifest, await loadInstructions(manifest));
22
22
  const transport = new StdioServerTransport();
23
23
  await server.connect(transport);
24
24
  // Eagerly fetch manifest so tools/list is populated on first call.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAE/D,WAAW,EAAE,CAAC;AAEd,6EAA6E;AAC7E,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC;IAClC,iBAAiB,EAAE,GAAG,EAAE,CACtB,OAAO,CAAC,GAAG,CAAC,eAAe;QACzB,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,mDAAmD;YACnD,qEAAqE;CAC5E,CAAC,CAAC;AAEH,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;AAErC,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,mEAAmE;IACnE,qEAAqE;IACrE,kCAAkC;IAClC,IAAI,CAAC;QACH,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC;QACvB,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,sCAAsC;IACxC,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,GAAG,CAAC,CAAC;IAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEjF,WAAW,EAAE,CAAC;AAEd,6EAA6E;AAC7E,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC;IAClC,iBAAiB,EAAE,GAAG,EAAE,CACtB,OAAO,CAAC,GAAG,CAAC,eAAe;QACzB,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,mDAAmD;YACnD,qEAAqE;CAC5E,CAAC,CAAC;AAEH,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,EAAE,MAAM,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC;IACvE,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,mEAAmE;IACnE,qEAAqE;IACrE,kCAAkC;IAClC,IAAI,CAAC;QACH,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC;QACvB,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,sCAAsC;IACxC,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,GAAG,CAAC,CAAC;IAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -7,6 +7,7 @@
7
7
  * thin results inside a default window are indistinguishable from a thin
8
8
  * corpus otherwise.
9
9
  */
10
+ import type { DateWindowEcho, SearchScope } from "./types.js";
10
11
  /** The concrete calendar window a days-based endpoint actually covered. */
11
12
  export declare function windowFromDays(days: number): {
12
13
  startDate: string;
@@ -14,8 +15,7 @@ export declare function windowFromDays(days: number): {
14
15
  };
15
16
  /**
16
17
  * One-line footer stating the date range a tool actually searched, in MCP
17
- * parameter vocabulary (`days` / `start_date`), matching the style of
18
- * format.ts's windowFooter.
18
+ * parameter vocabulary (`days` / `start_date`).
19
19
  */
20
20
  export declare function mcpWindowFooter(opts: {
21
21
  startDate?: string;
@@ -29,6 +29,16 @@ export declare function mcpWindowFooter(opts: {
29
29
  /** True for endpoints that only take `days` (no start_date parameter). */
30
30
  daysOnly?: boolean;
31
31
  }): string;
32
+ /**
33
+ * Footer for a tool that takes `days` OR `start_date`/`end_date` (signal4#226).
34
+ * Explicit dates win and are stated as the backend echoed them (`echo`, inclusive
35
+ * end) when it did; otherwise the rolling `days` window is stated.
36
+ */
37
+ export declare function dateWindowFooter(params: Record<string, unknown>, opts: {
38
+ days: number;
39
+ echo?: DateWindowEcho;
40
+ maxDays?: number;
41
+ }): string;
32
42
  /** For endpoints with no time filter at all (e.g. entity_claims). */
33
43
  export declare function allTimeFooter(): string;
34
44
  /**
@@ -38,4 +48,21 @@ export declare function allTimeFooter(): string;
38
48
  * (i.e. the emptiness is about the topic/window, not the name).
39
49
  */
40
50
  export declare function speakerEmptyStateNote(name: string): Promise<string | undefined>;
51
+ /**
52
+ * One-line footer stating the CORPUS SCOPE a tool actually searched.
53
+ *
54
+ * Sibling of `mcpWindowFooter`: that one bounds the search in time, this one
55
+ * bounds it in corpus. Both exist for the same reason — a thin result set is
56
+ * indistinguishable from a thin corpus unless the response says what it looked
57
+ * at. Until signal4-core#563 the MCP client sent `project="Big_Channels"` on
58
+ * nearly every search and said nothing about it, so a caller asking "who in
59
+ * American media discussed X" searched a curated subset of American media and
60
+ * had no way to find that out. Roughly three quarters of a recall gap an
61
+ * external client reported as a keyword-mode bug was this default.
62
+ *
63
+ * Prefer the API's own `scope` — it knows about dashboard aliases and API-key
64
+ * restrictions, which the client cannot see. `sentProject` is the fallback for
65
+ * a backend that predates the `scope` field.
66
+ */
67
+ export declare function scopeFooter(scope?: SearchScope, sentProject?: string): string;
41
68
  //# sourceMappingURL=provenance.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"provenance.d.ts","sourceRoot":"","sources":["../src/provenance.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAKnF;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8EAA8E;IAC9E,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GAAG,MAAM,CAUT;AAED,qEAAqE;AACrE,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAgBrF"}
1
+ {"version":3,"file":"provenance.d.ts","sourceRoot":"","sources":["../src/provenance.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9D,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAKnF;AAgBD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8EAA8E;IAC9E,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GAAG,MAAM,CAgBT;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,cAAc,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9D,MAAM,CASR;AAED,qEAAqE;AACrE,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAgBrF;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAI7E"}
@@ -15,10 +15,25 @@ export function windowFromDays(days) {
15
15
  endDate: new Date().toISOString().slice(0, 10),
16
16
  };
17
17
  }
18
+ /**
19
+ * True when `days` genuinely describes the [startDate, endDate] span, so the
20
+ * footer may say "(N days)". One day of slack absorbs the caller's own
21
+ * `Date.now() - days * 86400000` rounding and any UTC-vs-local date boundary.
22
+ */
23
+ function spanMatchesDays(startDate, endDate, days) {
24
+ if (days == null)
25
+ return false;
26
+ if (!startDate)
27
+ return true; // days is all we have; the span IS the days
28
+ const start = Date.parse(startDate);
29
+ const end = endDate ? Date.parse(endDate) : Date.now();
30
+ if (Number.isNaN(start) || Number.isNaN(end))
31
+ return false;
32
+ return Math.abs(Math.round((end - start) / 86400000) - days) <= 1;
33
+ }
18
34
  /**
19
35
  * One-line footer stating the date range a tool actually searched, in MCP
20
- * parameter vocabulary (`days` / `start_date`), matching the style of
21
- * format.ts's windowFooter.
36
+ * parameter vocabulary (`days` / `start_date`).
22
37
  */
23
38
  export function mcpWindowFooter(opts) {
24
39
  if (opts.fullHistory)
@@ -26,13 +41,34 @@ export function mcpWindowFooter(opts) {
26
41
  let { startDate, endDate } = opts;
27
42
  if (!startDate && opts.days != null)
28
43
  ({ startDate, endDate } = windowFromDays(opts.days));
29
- const daysStr = opts.days != null ? ` (${opts.days} days)` : "";
44
+ // "(N days)" is a claim about the window we searched, so only make it when N
45
+ // really is that window. Callers default `days` to 30 and then override the
46
+ // window with an explicit start_date; printing the default anyway put
47
+ // "(30 days)" under results spanning twenty months, which reads as "your
48
+ // dates were ignored" and cost a client re-runs of correct searches (#554).
49
+ // Checked here rather than in each caller so no future caller can lie either.
50
+ const daysStr = spanMatchesDays(startDate, endDate, opts.days) ? ` (${opts.days} days)` : "";
30
51
  const span = startDate ? `${startDate} → ${endDate ?? "today"}${daysStr}` : `last ${opts.days ?? 30} days`;
31
- const hint = opts.defaultWindow ? ` (default ${opts.days ?? 30}d window)` : "";
52
+ const hint = opts.defaultWindow && daysStr ? ` (default ${opts.days ?? 30}d window)` : "";
32
53
  const max = opts.maxDays ?? 365;
33
54
  const widen = opts.daysOnly ? `widen with days (≤${max})` : `widen with days (≤${max}) or start_date YYYY-MM-DD`;
34
55
  return `\n_Searched ${span}${hint} — older content may exist; ${widen}._`;
35
56
  }
57
+ /**
58
+ * Footer for a tool that takes `days` OR `start_date`/`end_date` (signal4#226).
59
+ * Explicit dates win and are stated as the backend echoed them (`echo`, inclusive
60
+ * end) when it did; otherwise the rolling `days` window is stated.
61
+ */
62
+ export function dateWindowFooter(params, opts) {
63
+ if (params.start_date != null || params.end_date != null) {
64
+ return mcpWindowFooter({
65
+ startDate: opts.echo?.start_date ?? params.start_date,
66
+ endDate: opts.echo?.end_date ?? params.end_date,
67
+ maxDays: opts.maxDays,
68
+ });
69
+ }
70
+ return mcpWindowFooter({ days: opts.days, defaultWindow: params.days == null, maxDays: opts.maxDays });
71
+ }
36
72
  /** For endpoints with no time filter at all (e.g. entity_claims). */
37
73
  export function allTimeFooter() {
38
74
  return "\n_Searched the full claim history — this tool has no time window._";
@@ -62,4 +98,27 @@ export async function speakerEmptyStateNote(name) {
62
98
  return undefined;
63
99
  return `No speaker matching "${name}" found in the corpus. Closest names: ${names.join(", ")}. Did you mean one of these? (Pass the canonical spelling as speaker.)`;
64
100
  }
101
+ /**
102
+ * One-line footer stating the CORPUS SCOPE a tool actually searched.
103
+ *
104
+ * Sibling of `mcpWindowFooter`: that one bounds the search in time, this one
105
+ * bounds it in corpus. Both exist for the same reason — a thin result set is
106
+ * indistinguishable from a thin corpus unless the response says what it looked
107
+ * at. Until signal4-core#563 the MCP client sent `project="Big_Channels"` on
108
+ * nearly every search and said nothing about it, so a caller asking "who in
109
+ * American media discussed X" searched a curated subset of American media and
110
+ * had no way to find that out. Roughly three quarters of a recall gap an
111
+ * external client reported as a keyword-mode bug was this default.
112
+ *
113
+ * Prefer the API's own `scope` — it knows about dashboard aliases and API-key
114
+ * restrictions, which the client cannot see. `sentProject` is the fallback for
115
+ * a backend that predates the `scope` field.
116
+ */
117
+ export function scopeFooter(scope, sentProject) {
118
+ if (scope?.description)
119
+ return `\n_Scope: ${scope.description}._`;
120
+ if (sentProject)
121
+ return `\n_Scope: collection ${sentProject} — the rest of the corpus was not searched._`;
122
+ return "\n_Scope: full corpus (no collection filter)._";
123
+ }
65
124
  //# sourceMappingURL=provenance.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"provenance.js","sourceRoot":"","sources":["../src/provenance.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AAEtC,2EAA2E;AAC3E,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO;QACL,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,GAAG,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;QAC5E,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;KAC/C,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,IAW/B;IACC,IAAI,IAAI,CAAC,WAAW;QAAE,OAAO,uCAAuC,CAAC;IACrE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAClC,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI;QAAE,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1F,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IAChE,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,MAAM,OAAO,IAAI,OAAO,GAAG,OAAO,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,IAAI,IAAI,EAAE,OAAO,CAAC;IAC3G,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,aAAa,IAAI,CAAC,IAAI,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/E,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,IAAI,GAAG,CAAC;IAChC,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,qBAAqB,GAAG,GAAG,CAAC,CAAC,CAAC,qBAAqB,GAAG,4BAA4B,CAAC;IACjH,OAAO,eAAe,IAAI,GAAG,IAAI,+BAA+B,KAAK,IAAI,CAAC;AAC5E,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,aAAa;IAC3B,OAAO,qEAAqE,CAAC;AAC/E,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,IAAY;IACtD,IAAI,OAAO,CAAC;IACZ,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC,CAAC,sDAAsD;IAC1E,CAAC;IACD,MAAM,KAAK,GAAG,OAAO;SAClB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,YAAY,CAAC;SACpC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACnC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QAClB,OAAO,wBAAwB,IAAI,2EAA2E,CAAC;IACjH,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;IAC/E,IAAI,KAAK;QAAE,OAAO,SAAS,CAAC;IAC5B,OAAO,wBAAwB,IAAI,yCAAyC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,wEAAwE,CAAC;AACvK,CAAC"}
1
+ {"version":3,"file":"provenance.js","sourceRoot":"","sources":["../src/provenance.ts"],"names":[],"mappings":"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"}
@@ -36,5 +36,12 @@ export declare class CachedManifest implements ManifestProvider {
36
36
  authError(): string | null;
37
37
  fetch(): Promise<ManifestResponse>;
38
38
  }
39
- export declare function buildServer(provider: ManifestProvider): McpServer;
39
+ /** Appended to the server instructions, so an agent knows how to read the speed tags. */
40
+ export declare const SPEED_NOTE: string;
41
+ export declare const FALLBACK_INSTRUCTIONS: string;
42
+ /** Fetch the manifest's instructions, giving up after `ms` so startup never hangs. */
43
+ export declare function loadInstructions(provider: ManifestProvider, ms?: number): Promise<string | undefined>;
44
+ /** Turn a FastAPI 422 body into "parameter <loc>: <msg>". */
45
+ export declare function translate422(raw: string): string;
46
+ export declare function buildServer(provider: ManifestProvider, instructions?: string): McpServer;
40
47
  //# sourceMappingURL=server_core.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server_core.d.ts","sourceRoot":"","sources":["../src/server_core.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAMpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGpD,eAAO,MAAM,iBAAiB,QAAS,CAAC;AAExC,MAAM,WAAW,gBAAgB;IAC/B,gEAAgE;IAChE,KAAK,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACnC,sDAAsD;IACtD,SAAS,IAAI,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;;;GAIG;AACH,qBAAa,cAAe,YAAW,gBAAgB;IAOnD,OAAO,CAAC,QAAQ,CAAC,IAAI;IANvB,OAAO,CAAC,QAAQ,CAAiC;IACjD,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,YAAY,CAAK;gBAGN,IAAI,GAAE;QACrB,8DAA8D;QAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,wEAAwE;QACxE,iBAAiB,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;KACpC;IAGR,SAAS,IAAI,MAAM,GAAG,IAAI;IAIpB,KAAK,IAAI,OAAO,CAAC,gBAAgB,CAAC;CA6BzC;AAkDD,wBAAgB,WAAW,CAAC,QAAQ,EAAE,gBAAgB,GAAG,SAAS,CA6EjE"}
1
+ {"version":3,"file":"server_core.d.ts","sourceRoot":"","sources":["../src/server_core.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAMpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAIpD,eAAO,MAAM,iBAAiB,QAAS,CAAC;AAExC,MAAM,WAAW,gBAAgB;IAC/B,gEAAgE;IAChE,KAAK,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACnC,sDAAsD;IACtD,SAAS,IAAI,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;;;GAIG;AACH,qBAAa,cAAe,YAAW,gBAAgB;IAOnD,OAAO,CAAC,QAAQ,CAAC,IAAI;IANvB,OAAO,CAAC,QAAQ,CAAiC;IACjD,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,YAAY,CAAK;gBAGN,IAAI,GAAE;QACrB,8DAA8D;QAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,wEAAwE;QACxE,iBAAiB,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;KACpC;IAGR,SAAS,IAAI,MAAM,GAAG,IAAI;IAIpB,KAAK,IAAI,OAAO,CAAC,gBAAgB,CAAC;CA6BzC;AA6CD,yFAAyF;AACzF,eAAO,MAAM,UAAU,QAK4C,CAAC;AAEpE,eAAO,MAAM,qBAAqB,QAI+E,CAAC;AAElH,sFAAsF;AACtF,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,EAAE,SAAO,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAazG;AAID,6DAA6D;AAC7D,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAkBhD;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,gBAAgB,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAuGxF"}
@@ -12,6 +12,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
12
12
  import { ListToolsRequestSchema, CallToolRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
13
13
  import * as client from "./client.js";
14
14
  import { HANDLERS } from "./handlers/registry.js";
15
+ import { decorateDescription, elapsedFooter, estimate, startNotice } from "./speed.js";
15
16
  export const RETRY_COOLDOWN_MS = 60_000;
16
17
  /**
17
18
  * Manifest cache with the 60s auth-failure cooldown. One instance per key
@@ -95,10 +96,57 @@ function diagnosticToolResponse(provider) {
95
96
  // ---------------------------------------------------------------------------
96
97
  // Server construction
97
98
  // ---------------------------------------------------------------------------
98
- const FALLBACK_INSTRUCTIONS = "Signal4 media intelligence platform. Authenticating...";
99
+ /** Appended to the server instructions, so an agent knows how to read the speed tags. */
100
+ export const SPEED_NOTE = "\n\nSPEED: every tool description starts with its speed at default settings — instant (<0.5s), " +
101
+ "fast (0.5–2.5s) or slow (>2.5s) — and, for search, counts and timelines, how it grows with the " +
102
+ "window (\"12 months ~3–6s, all time ~5–10s\"). A call expected to take a while sends a progress " +
103
+ "notice with its estimate as it starts; an answer that took over 2.5s ends with \"Took Ns\". " +
104
+ "Prefer a narrower window or a keyword search when time matters.";
105
+ export const FALLBACK_INSTRUCTIONS = "Signal4 media intelligence: searchable transcripts of podcasts, YouTube and broadcasts. " +
106
+ "Start here: list_collections (what you can scope to), then search_quotes (topic, optional speaker/channel/days), " +
107
+ "then get_segment or get_thread for context. Omit `collection` to search the whole corpus. " +
108
+ "Results show IDs like seg:123; pass those to get_segment. Analysis tools are slow and paid: use search first.";
109
+ /** Fetch the manifest's instructions, giving up after `ms` so startup never hangs. */
110
+ export async function loadInstructions(provider, ms = 3000) {
111
+ let timer;
112
+ try {
113
+ const m = await Promise.race([
114
+ provider.fetch(),
115
+ new Promise((_, rej) => { timer = setTimeout(() => rej(new Error("manifest timeout")), ms); }),
116
+ ]);
117
+ return m.instructions || undefined;
118
+ }
119
+ catch {
120
+ return undefined;
121
+ }
122
+ finally {
123
+ clearTimeout(timer);
124
+ }
125
+ }
99
126
  const { version: PKG_VERSION } = createRequire(import.meta.url)("../package.json");
100
- export function buildServer(provider) {
101
- const server = new McpServer({ name: "Signal4", version: PKG_VERSION }, { instructions: FALLBACK_INSTRUCTIONS });
127
+ /** Turn a FastAPI 422 body into "parameter <loc>: <msg>". */
128
+ export function translate422(raw) {
129
+ const i = raw.indexOf("[");
130
+ const j = raw.indexOf("{");
131
+ const at = i >= 0 && (j < 0 || i < j) ? i : j;
132
+ if (at >= 0) {
133
+ try {
134
+ const body = JSON.parse(raw.slice(at));
135
+ const items = Array.isArray(body) ? body : Array.isArray(body?.detail) ? body.detail : null;
136
+ if (items) {
137
+ return items.slice(0, 3).map((e) => {
138
+ const loc = Array.isArray(e.loc) ? e.loc.filter((x) => x !== "body" && x !== "query").join(".") : "";
139
+ return `parameter ${loc || "?"}: ${e.msg ?? "invalid"}`;
140
+ }).join("; ");
141
+ }
142
+ }
143
+ catch { /* fall through */ }
144
+ }
145
+ // A plain-text detail (e.g. a search that ran past its time limit) is the message.
146
+ return raw.replace(/^[\s\S]*?HTTP 422:?\s*/, "").slice(0, 400);
147
+ }
148
+ export function buildServer(provider, instructions) {
149
+ const server = new McpServer({ name: "Signal4", version: PKG_VERSION }, { instructions: (instructions || FALLBACK_INSTRUCTIONS) + SPEED_NOTE });
102
150
  // Register tool capabilities and custom handlers on the underlying Server
103
151
  // BEFORE any .tool() call — we own the tool protocol directly so we can
104
152
  // serve raw JSON Schema from the manifest without zod conversion.
@@ -109,7 +157,8 @@ export function buildServer(provider) {
109
157
  return {
110
158
  tools: m.tools.map((t) => ({
111
159
  name: t.name,
112
- description: t.description,
160
+ // Every description starts with how long the call takes (speed.ts).
161
+ description: decorateDescription(t.name, t.description),
113
162
  inputSchema: t.inputSchema,
114
163
  })),
115
164
  };
@@ -118,7 +167,7 @@ export function buildServer(provider) {
118
167
  return diagnosticToolList(provider);
119
168
  }
120
169
  });
121
- server.server.setRequestHandler(CallToolRequestSchema, async (request) => {
170
+ server.server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
122
171
  try {
123
172
  const { name, arguments: args } = request.params;
124
173
  if (name === AUTH_DIAGNOSTIC_TOOL) {
@@ -140,19 +189,52 @@ export function buildServer(provider) {
140
189
  isError: true,
141
190
  };
142
191
  }
143
- return await handler(args ?? {});
192
+ // A call expected to take more than a moment says so before it starts, to
193
+ // clients that asked for progress (an MCP progressToken).
194
+ const params = (args ?? {});
195
+ const expected = estimate(name, params);
196
+ const token = request.params._meta?.progressToken;
197
+ if (expected.tier !== "instant" && token !== undefined) {
198
+ await extra.sendNotification({
199
+ method: "notifications/progress",
200
+ params: { progressToken: token, progress: 0, message: startNotice(expected) },
201
+ }).catch(() => { });
202
+ }
203
+ const started = Date.now();
204
+ const result = await handler(params);
205
+ // A slow answer says how long it took, so an agent can plan the next call.
206
+ const footer = elapsedFooter(Date.now() - started);
207
+ const last = result.content[result.content.length - 1];
208
+ if (footer && last && !result.isError && params.response_format !== "json")
209
+ last.text += footer;
210
+ return result;
144
211
  }
145
212
  catch (err) {
146
213
  const raw = err instanceof Error ? err.message : String(err);
147
214
  let msg = raw;
148
- if (/HTTP 40[13]/.test(raw)) {
215
+ if (/HTTP 401/.test(raw)) {
149
216
  msg = "API key is invalid or expired. Check the SIGNAL4_API_KEY in your MCP server config.";
150
217
  }
218
+ else if (/HTTP 403/.test(raw)) {
219
+ const d = raw.replace(/^[\s\S]*?HTTP 403:?\s*/, "").trim();
220
+ msg = d ? `Forbidden: ${d.slice(0, 200)}` : "Forbidden: this key lacks access to that tool or collection.";
221
+ }
222
+ else if (/HTTP 400/.test(raw)) {
223
+ const d = raw.replace(/^[\s\S]*?HTTP 400:?\s*/, "").trim();
224
+ let detail = d;
225
+ try {
226
+ const j = JSON.parse(d);
227
+ if (typeof j.detail === "string")
228
+ detail = j.detail;
229
+ }
230
+ catch { /* raw */ }
231
+ msg = detail.slice(0, 300);
232
+ }
151
233
  else if (/HTTP 404/.test(raw)) {
152
234
  msg = "The requested resource was not found. Check that the ID came from a previous search or listing result.";
153
235
  }
154
236
  else if (/HTTP 422/.test(raw)) {
155
- msg = raw + " Check the tool description for valid parameter types and formats.";
237
+ msg = translate422(raw);
156
238
  }
157
239
  else if (raw.includes("expand_query must be called before")) {
158
240
  msg = "Analysis pipeline error — try workflow='simple_rag' or simplify your query.";
@@ -1 +1 @@
1
- {"version":3,"file":"server_core.js","sourceRoot":"","sources":["../src/server_core.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server_core.js","sourceRoot":"","sources":["../src/server_core.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /** How long a call should take — one source for tool descriptions, CLI help, the
2
+ * progress notice a slow call sends before it starts, and the "took Ns" footer.
3
+ *
4
+ * Tiers, by the typical time (geometric mean of the range):
5
+ * instant < 0.5s fast 0.5–2.5s slow > 2.5s
6
+ *
7
+ * Every number is measured, not guessed: the 100-plan replay against the live API
8
+ * (2026-10-15/16, ~/logs/search_eval/replay-2026-10-15.jsonl — per-tool p50/p90) and the
9
+ * VPS before/after runs for the counting engine (signal4#292, #296). Semantic tools pay
10
+ * ~1s for the query embedding before they scan; a scan costs roughly 0.15–0.35s per
11
+ * month of window over the whole corpus. Update the table when a tool gets faster. */
12
+ export type Tier = "instant" | "fast" | "slow";
13
+ export interface Estimate {
14
+ tier: Tier;
15
+ /** seconds */
16
+ lo: number;
17
+ hi: number;
18
+ /** what drives the time, for the progress notice (e.g. "semantic scan over 12 months") */
19
+ why?: string;
20
+ }
21
+ /** Responses that took longer than this say how long. */
22
+ export declare const REPORT_ELAPSED_OVER_S = 2.5;
23
+ export declare function tierOf(lo: number, hi: number): Tier;
24
+ /** Window length in months from days / start_date / end_date (YYYY, YYYY-MM, YYYY-MM-DD). */
25
+ export declare function windowMonths(params: Record<string, unknown>, defaultDays?: number): number;
26
+ /** The estimate for one call. Unknown tools are "fast" with a wide range. */
27
+ export declare function estimate(tool: string, params?: Record<string, unknown>): Estimate;
28
+ /** "instant" · "fast ~1–2s" · "slow ~3–8s". */
29
+ export declare function label(e: Estimate): string;
30
+ /** The speed line a tool description starts with, e.g. "[slow ~15–45s · paid LLM]".
31
+ * Tools whose time depends on the window carry a short scale ("…; 12 months ~3–6s"). */
32
+ export declare function descriptionTag(tool: string, paid?: boolean): string;
33
+ /** Replace the speed/price bracket a backend description starts with by ours,
34
+ * keeping the paid marker. */
35
+ export declare function decorateDescription(tool: string, description: string): string;
36
+ /** The notice a slow call sends before it starts (MCP progress, CLI stderr). */
37
+ export declare function startNotice(e: Estimate): string;
38
+ /** Footer for a response that took longer than REPORT_ELAPSED_OVER_S. */
39
+ export declare function elapsedFooter(ms: number): string;
40
+ //# sourceMappingURL=speed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"speed.d.ts","sourceRoot":"","sources":["../src/speed.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;sFAUsF;AAEtF,MAAM,MAAM,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;AAE/C,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,IAAI,CAAC;IACX,cAAc;IACd,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,0FAA0F;IAC1F,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAID,yDAAyD;AACzD,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAIzC,wBAAgB,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAKnD;AA+CD,6FAA6F;AAC7F,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,SAAK,GAAG,MAAM,CAiBtF;AAoBD,6EAA6E;AAC7E,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,QAAQ,CA2DrF;AAQD,+CAA+C;AAC/C,wBAAgB,KAAK,CAAC,CAAC,EAAE,QAAQ,GAAG,MAAM,CAGzC;AAED;wFACwF;AACxF,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,UAAQ,GAAG,MAAM,CAWjE;AAED;8BAC8B;AAC9B,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAK7E;AAED,gFAAgF;AAChF,wBAAgB,WAAW,CAAC,CAAC,EAAE,QAAQ,GAAG,MAAM,CAE/C;AAED,yEAAyE;AACzE,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAEhD"}