offnadir-delta-mcp 1.3.13 → 1.3.15

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/catalog.js CHANGED
@@ -52,7 +52,30 @@ const BBOX = {
52
52
  export const TOOLS = [
53
53
  {
54
54
  name: 'query_signals',
55
- annotations: { readOnlyHint: true },
55
+ annotations: { "readOnlyHint": false, "openWorldHint": false, "destructiveHint": true },
56
+ outputSchema: {
57
+ "type": "object",
58
+ "properties": {
59
+ "meta": {
60
+ "type": "object",
61
+ "description": "Query echo, token charge/balance (meta.tokens), and pagination where applicable."
62
+ },
63
+ "summary": {
64
+ "type": "string",
65
+ "description": "One-line natural-language summary of the result, ready to relay to a user."
66
+ },
67
+ "signals": {
68
+ "type": "array",
69
+ "items": {
70
+ "type": "object"
71
+ }
72
+ }
73
+ },
74
+ "required": [
75
+ "meta",
76
+ "signals"
77
+ ]
78
+ },
56
79
  description: 'Query geolocated world event signals (Delta Signals: geopolitical, security, disaster, and ' +
57
80
  'infrastructure events distilled from global news media, AI-enriched with severity/GEOINT scores ' +
58
81
  'and satellite-collection recommendations). Filter by bounding box, date window, and category. ' +
@@ -89,7 +112,27 @@ export const TOOLS = [
89
112
  },
90
113
  {
91
114
  name: 'query_stats',
92
- annotations: { readOnlyHint: true },
115
+ annotations: { "readOnlyHint": false, "openWorldHint": false, "destructiveHint": true },
116
+ outputSchema: {
117
+ "type": "object",
118
+ "properties": {
119
+ "meta": {
120
+ "type": "object",
121
+ "description": "Query echo, token charge/balance (meta.tokens), and pagination where applicable."
122
+ },
123
+ "summary": {
124
+ "type": "string",
125
+ "description": "One-line natural-language summary of the result, ready to relay to a user."
126
+ },
127
+ "stats": {
128
+ "type": "object"
129
+ }
130
+ },
131
+ "required": [
132
+ "meta",
133
+ "stats"
134
+ ]
135
+ },
93
136
  description: 'Aggregate statistics over the signal corpus — total event count plus per-category and per-day ' +
94
137
  'breakdown (trend) for a bounding box and date window. Cheaper than query_signals (returns ' +
95
138
  'roll-ups, not rows). NOTE the unit: `total` counts article-deduped events (meta.population = ' +
@@ -107,7 +150,30 @@ export const TOOLS = [
107
150
  },
108
151
  {
109
152
  name: 'query_hotspots',
110
- annotations: { readOnlyHint: true },
153
+ annotations: { "readOnlyHint": false, "openWorldHint": false, "destructiveHint": true },
154
+ outputSchema: {
155
+ "type": "object",
156
+ "properties": {
157
+ "meta": {
158
+ "type": "object",
159
+ "description": "Query echo, token charge/balance (meta.tokens), and pagination where applicable."
160
+ },
161
+ "summary": {
162
+ "type": "string",
163
+ "description": "One-line natural-language summary of the result, ready to relay to a user."
164
+ },
165
+ "hotspots": {
166
+ "type": "array",
167
+ "items": {
168
+ "type": "object"
169
+ }
170
+ }
171
+ },
172
+ "required": [
173
+ "meta",
174
+ "hotspots"
175
+ ]
176
+ },
111
177
  description: 'Geographic hotspots — signal density grid-binned into cells, ranked by event count, each with ' +
112
178
  'peak severity, the categories present, and up to 5 representative event_ids (trace a cell back ' +
113
179
  'to its signals). Use to find WHERE activity is concentrating. NOTE the unit: cells count ' +
@@ -129,7 +195,22 @@ export const TOOLS = [
129
195
  },
130
196
  {
131
197
  name: 'get_world_brief',
132
- annotations: { readOnlyHint: true },
198
+ annotations: { "readOnlyHint": true, "openWorldHint": false, "destructiveHint": false },
199
+ outputSchema: {
200
+ "type": "object",
201
+ "properties": {
202
+ "brief": {
203
+ "type": "object"
204
+ },
205
+ "freshness": {
206
+ "type": "object",
207
+ "description": "Freshness of the returned brief: brief_date, generated_at, age_hours, freshness (operational|delayed|degraded), is_stale, note."
208
+ }
209
+ },
210
+ "required": [
211
+ "brief"
212
+ ]
213
+ },
133
214
  description: "Fetch the Daily World Brief — an AI-synthesized OSINT/GEOINT digest of the previous UTC day's " +
134
215
  'worldwide event signals (headline, executive summary, top developments with why-it-matters and ' +
135
216
  'what-to-watch, per-theme roll-up, ranked signals). Free of token charges.',
@@ -142,7 +223,50 @@ export const TOOLS = [
142
223
  },
143
224
  {
144
225
  name: 'get_usage',
145
- annotations: { readOnlyHint: true },
226
+ annotations: { "readOnlyHint": true, "openWorldHint": false, "destructiveHint": false },
227
+ outputSchema: {
228
+ "type": "object",
229
+ "properties": {
230
+ "tokens": {
231
+ "type": "object",
232
+ "properties": {
233
+ "allocation": {
234
+ "type": "number",
235
+ "description": "Monthly token allocation for the plan."
236
+ },
237
+ "used": {
238
+ "type": "number",
239
+ "description": "Tokens used in the current period."
240
+ },
241
+ "remaining": {
242
+ "type": "number",
243
+ "description": "Tokens remaining this period."
244
+ }
245
+ },
246
+ "required": [
247
+ "allocation",
248
+ "used",
249
+ "remaining"
250
+ ]
251
+ },
252
+ "plan": {
253
+ "type": "object",
254
+ "properties": {
255
+ "api_llm_access": {
256
+ "type": "boolean",
257
+ "description": "Whether AI tools over the API are enabled."
258
+ }
259
+ },
260
+ "required": [
261
+ "api_llm_access"
262
+ ]
263
+ }
264
+ },
265
+ "required": [
266
+ "tokens",
267
+ "plan"
268
+ ]
269
+ },
146
270
  description: "Check the calling key's remaining token balance and plan capabilities — monthly allocation, " +
147
271
  'tokens used this period, tokens remaining, and whether the plan includes AI tools over the API ' +
148
272
  '(assess_signal / ask_analyst). Use this to pre-flight a metered call: decide whether enough ' +
@@ -151,16 +275,40 @@ export const TOOLS = [
151
275
  },
152
276
  {
153
277
  name: 'search_imagery',
154
- annotations: { readOnlyHint: true },
278
+ annotations: { "readOnlyHint": false, "openWorldHint": false, "destructiveHint": true },
279
+ outputSchema: {
280
+ "type": "object",
281
+ "properties": {
282
+ "meta": {
283
+ "type": "object",
284
+ "description": "Query echo, token charge/balance (meta.tokens), and pagination where applicable."
285
+ },
286
+ "summary": {
287
+ "type": "string",
288
+ "description": "One-line natural-language summary of the result, ready to relay to a user."
289
+ },
290
+ "scenes": {
291
+ "type": "array",
292
+ "items": {
293
+ "type": "object"
294
+ }
295
+ }
296
+ },
297
+ "required": [
298
+ "meta",
299
+ "scenes"
300
+ ]
301
+ },
155
302
  description: 'Search the satellite imagery catalog (Sentinel-1/2, OPERA RTC-S1) for scenes over an area and ' +
156
303
  'date window — the natural follow-up to a signal (find imagery over the event location). Returns ' +
157
304
  'scene metadata (id, datetime, footprint, cloud cover, platform, orbit geometry, coverage, catalog ' +
158
305
  'link) — no imagery bytes. Pass eventDate to classify each scene timing=pre/post/same_day_unknown ' +
159
306
  '(a same-day scene is same_day_unknown, never post, without a real event time) and get pre/post ' +
160
307
  'bracketing + window_status + SAR sar_pair_status in meta. Pass eventPoint [lon,lat] and/or eventAoi ' +
161
- '[minLon,minLat,maxLon,maxLat] to get each scene\'s target_relation (covers_event_point / ' +
162
- 'intersects_event_aoi / usable_for_event) — so a scene that only clips the wide bbox is not mistaken ' +
163
- 'for covering the event. Costs 2 token(s) per call.',
308
+ '[minLon,minLat,maxLon,maxLat] to get each scene\'s target_relation (covers_event_geometry = pure ' +
309
+ 'geometry gate; usable_for_analysis additionally requires acceptable cloud for optical, so a ' +
310
+ '99%-cloud scene is geometry-covering but not analysis-usable) — so a scene that only clips the wide ' +
311
+ 'bbox is not mistaken for covering the event. Costs 2 token(s) per call.',
164
312
  inputSchema: {
165
313
  type: 'object',
166
314
  properties: {
@@ -181,7 +329,33 @@ export const TOOLS = [
181
329
  },
182
330
  {
183
331
  name: 'assess_signal',
184
- annotations: { readOnlyHint: true, idempotentHint: true },
332
+ annotations: { "readOnlyHint": false, "openWorldHint": false, "destructiveHint": true, "idempotentHint": true },
333
+ outputSchema: {
334
+ "type": "object",
335
+ "properties": {
336
+ "kind": {
337
+ "type": "string"
338
+ },
339
+ "cached": {
340
+ "type": "boolean"
341
+ },
342
+ "model": {
343
+ "type": "string"
344
+ },
345
+ "content": {
346
+ "type": "object"
347
+ },
348
+ "meta": {
349
+ "type": "object",
350
+ "description": "Query echo, token charge/balance (meta.tokens), and pagination where applicable."
351
+ }
352
+ },
353
+ "required": [
354
+ "kind",
355
+ "content",
356
+ "meta"
357
+ ]
358
+ },
185
359
  description: 'Run an AI RS (remote-sensing) deep-dive assessment for a specific signal: what to observe, ' +
186
360
  'recommended sensors, and a collection window. `eventId` is the `id` from query_signals. ' +
187
361
  'The result also carries a deterministic `context` block (event id/date, normalized target, AOI ' +
@@ -204,7 +378,30 @@ export const TOOLS = [
204
378
  },
205
379
  {
206
380
  name: 'ask_analyst',
207
- annotations: { readOnlyHint: true },
381
+ annotations: { "readOnlyHint": false, "openWorldHint": false, "destructiveHint": true },
382
+ outputSchema: {
383
+ "type": "object",
384
+ "properties": {
385
+ "brief": {
386
+ "type": "object"
387
+ },
388
+ "meta": {
389
+ "type": "object",
390
+ "description": "Query echo, token charge/balance (meta.tokens), and pagination where applicable."
391
+ },
392
+ "status": {
393
+ "type": "string",
394
+ "description": "\"processing\" when the run is still going (poll get_analyst_job or re-send the same idempotencyKey)."
395
+ },
396
+ "job_id": {
397
+ "type": "string",
398
+ "description": "Id of the analyst run — pass to get_analyst_job (also at GET /api/v1/analyst/{job_id})."
399
+ },
400
+ "message": {
401
+ "type": "string"
402
+ }
403
+ }
404
+ },
208
405
  description: 'Ask the Delta Analyst an OSINT/GEOINT question. Runs an agentic multi-step analysis over the ' +
209
406
  'signal corpus and returns a structured brief (summary, findings with collection recommendations, ' +
210
407
  'assessment, citations). Costs 5–123 tokens (usage-based, metered by the compute the question actually ' +
@@ -226,7 +423,39 @@ export const TOOLS = [
226
423
  },
227
424
  {
228
425
  name: 'get_analyst_job',
229
- annotations: { readOnlyHint: true },
426
+ annotations: { "readOnlyHint": true, "openWorldHint": false, "destructiveHint": false },
427
+ outputSchema: {
428
+ "type": "object",
429
+ "properties": {
430
+ "job_id": {
431
+ "type": "string"
432
+ },
433
+ "status": {
434
+ "type": "string",
435
+ "description": "\"processing\" | \"done\" | \"error\"."
436
+ },
437
+ "brief": {
438
+ "type": "object"
439
+ },
440
+ "meta": {
441
+ "type": "object",
442
+ "description": "Query echo, token charge/balance (meta.tokens), and pagination where applicable."
443
+ },
444
+ "error": {
445
+ "type": "string",
446
+ "description": "Failure reason when status is \"error\"."
447
+ },
448
+ "message": {
449
+ "type": "string"
450
+ },
451
+ "created_at": {
452
+ "type": "string"
453
+ },
454
+ "updated_at": {
455
+ "type": "string"
456
+ }
457
+ }
458
+ },
230
459
  description: 'Fetch the status and result of an ask_analyst run by job_id. Returns status "processing" (still ' +
231
460
  'running — poll again in ~10-20s), "done" (with the finished brief and meta.tokens), or "error". ' +
232
461
  'Free of token charges — the run itself is charged once on completion. A job is visible only to the ' +
package/dist/index.js CHANGED
@@ -21,7 +21,7 @@ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
21
21
  import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
22
22
  import { CallToolRequestSchema, GetPromptRequestSchema, ListPromptsRequestSchema, ListResourcesRequestSchema, ListResourceTemplatesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
23
23
  import { PROMPTS, RESOURCES, RESOURCE_TEMPLATES, TOOLS } from './catalog.js';
24
- const VERSION = '1.3.13';
24
+ const VERSION = '1.3.15';
25
25
  const REMOTE_URL = new URL(process.env.OFFNADIR_DELTA_MCP_URL ?? 'https://offnadir-delta.com/api/v1/mcp');
26
26
  /** Lazily-connected client to the hosted remote MCP server. */
27
27
  let remote = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "offnadir-delta-mcp",
3
- "version": "1.3.13",
3
+ "version": "1.3.15",
4
4
  "description": "Local (stdio) MCP server for Off-Nadir Delta — live, geolocated world-event intelligence, a Daily World Brief, satellite-imagery search, and an OSINT/GEOINT analyst. Forwards to the hosted server with your API key.",
5
5
  "type": "module",
6
6
  "bin": {