offnadir-delta-mcp 2.0.0 → 3.0.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.
package/README.md CHANGED
@@ -16,7 +16,7 @@ satellite can actually resolve it, and produce a collection-ready plan.
16
16
  Real-time event and geospatial intelligence for OSINT, geopolitical risk, and GEOINT work —
17
17
  source-linked, geolocated, and current, not a training snapshot.
18
18
 
19
- `35` tools · MCP server version `2.0.0` · [full reference](https://offnadir-delta.com/docs/mcp)
19
+ `21` tools · MCP server version `3.0.0` · [full reference](https://offnadir-delta.com/docs/mcp)
20
20
 
21
21
  ## What it does
22
22
 
@@ -77,7 +77,7 @@ locally from a generated catalog, so registries can introspect it without creden
77
77
 
78
78
  ### First call — free
79
79
 
80
- 21 of the 35 tools cost nothing, so the first thing you run is free:
80
+ 11 of the 21 tools cost nothing, so the first thing you run is free:
81
81
 
82
82
  > Give me the latest Daily World Brief. Lead with the three most significant developments,
83
83
  > explain why each matters, and cite the supporting signals.
@@ -101,7 +101,6 @@ What is happening, what changed, and what today looks like.
101
101
  | `get_event_thread` | One event end to end: state plus every change in order — the "new event or update" distinction a feed cannot make. | free |
102
102
  | `search_entities` | Find a named place (airport, base, plant, port, dam, strait…) in any language or by IATA/ICAO code. | 1 tok |
103
103
  | `get_entity` | What has happened at one place: the registry record plus its most recent linked events, each with HOW it was linked. | 1 tok |
104
- | `get_related_events` | The relations recorded for one event: others at the same registry facility, naming the same place, or stored as the same campaign, each saying what is shared; plus reports merged into it. | 1 tok |
105
104
 
106
105
  ### Plan
107
106
 
@@ -112,10 +111,7 @@ Whether a satellite can resolve it, which one, and when it next passes.
112
111
  | `search_imagery` | Search the imagery catalog over an area and window. | 2 tok |
113
112
  | `plan_event_imagery` | The deterministic imagery plan for ONE event: checks BOTH sensors exactly once — sentinel-1-grd (SAR, the only look that survives cloud and night) and sentinel-2-l2a — against the event footprint and a pre/post window. | 4 tok |
114
113
  | `rank_imaging_priority` | WHERE, and with what class of satellite, observation is most worthwhile now: composite IMPORTANCE crossed with the SPEC CLASS the required resolution demands — coarse, hr (free Sentinel-class) or vhr. | 1 tok |
115
- | `survey_observable_events` | Which events a sensor can actually RESOLVE, over the FULL set. | 1 tok |
116
114
  | `predict_satellite_passes` | WHEN a place can next be imaged and by WHAT: 13 free-systematic and commercial-taskable families. | 2 tok |
117
- | `lookup_elevation` | Terrain height from the Copernicus DEM GLO-30 for a point, bbox or polygon, with relief — the number that governs SAR layover and shadow. | free |
118
- | `analyze_terrain` | Compute FROM the terrain. | free |
119
115
 
120
116
  ### Analyze
121
117
 
@@ -126,8 +122,6 @@ Turn reporting into a cited assessment you can audit afterwards.
126
122
  | `assess_signal` | AI remote-sensing deep-dive for one signal: what to observe, sensors, a collection window. | 5/15 tok |
127
123
  | `ask_analyst` | Ask the Delta Analyst an OSINT/GEOINT question; returns a structured brief. | 5–123 tok |
128
124
  | `get_analyst_job` | Status and result of an ask_analyst run. | free |
129
- | `measure_index_series` | Measure a spectral index over an area scene by scene through the Sentinel-2 archive. | 0.5 tok |
130
- | `detect_ships` | Count vessel-like targets in ONE Sentinel-1 SAR scene by CFAR detection — radar sees through cloud and at night. | 5 tok |
131
125
 
132
126
  ### Watch
133
127
 
@@ -135,28 +129,13 @@ Stand up continuous coverage and be told only when the answer changes. Creating
135
129
 
136
130
  | Tool | What it does | Cost |
137
131
  | --- | --- | --- |
138
- | `create_standing_order` | Put an area under CONTINUOUS watch (the app’s "Watch this area"): checked weekly, notifying only when new events cross the bar. | free |
139
- | `list_standing_orders` | The standing orders on this key: cadence, area, last check, last actual fire, and quiet_checks — a high quiet_checks means the watch is not earning its place. | free |
140
- | `list_monitored_areas` | Places under continuous satellite measurement: metric, latest value, change, anomaly flag, coverage. | free |
141
- | `get_monitored_area` | One monitored area with its full measurement history. | free |
142
- | `create_monitored_area` | Put a place under continuous satellite measurement — every new Sentinel-1/2 or VIIRS acquisition (or FIRMS fire detection) is measured. | free |
143
132
  | `list_watches` | The Watchlist as one list, each entry with a state bucket. | free |
133
+ | `list_notifications` | What changed across the Watchlist, newest first: one row per change a watch reported, with read state. | free |
144
134
  | `get_watch` | One watch end to end: target, state, latest change, measurements with recent series, standing-order questions, and for an event watch its stage, developments and thread, plus this account's notes. | free |
145
135
  | `create_watch` | Add a target to the Watchlist. | free |
146
136
  | `update_watch` | Pause, resume or close a watch. | free |
147
137
  | `delete_watch` | Delete a watch and its underlying resources — bound monitored areas with their history, and standing orders. | free |
148
138
  | `add_note` | Add a note to a watch, start a thread, or reply. | free |
149
- | `delete_note` | Delete one note from a watch. | free |
150
-
151
- ### Workspace
152
-
153
- The map assets you own — saved layer sets and your own uploaded data.
154
-
155
- | Tool | What it does | Cost |
156
- | --- | --- | --- |
157
- | `list_layer_sets` | The layer sets saved on this account. | free |
158
- | `get_layer_set` | One saved layer set by id. | free |
159
- | `list_uploaded_layers` | The data this account uploaded to the map, plus the formats the uploader accepts. | free |
160
139
 
161
140
  ### Account
162
141
 
package/dist/catalog.js CHANGED
@@ -13,7 +13,7 @@
13
13
  * Actual `tools/call` / `resources/read` / `prompts/get` requests are forwarded
14
14
  * to the remote server with the caller's OFFNADIR_DELTA_API_KEY (see index.ts).
15
15
  */
16
- // Generated for Off-Nadir Delta MCP 2.0.0.
16
+ // Generated for Off-Nadir Delta MCP 3.0.0.
17
17
  export const TOOLS = [
18
18
  {
19
19
  "name": "query_signals",
@@ -116,7 +116,7 @@ export const TOOLS = [
116
116
  "equities"
117
117
  ]
118
118
  },
119
- "description": "Markets exposed via a physical/supply channel."
119
+ "description": "Exposed markets (physical/supply channel)."
120
120
  },
121
121
  "placement": {
122
122
  "type": "string",
@@ -127,58 +127,13 @@ export const TOOLS = [
127
127
  ],
128
128
  "description": "map=a point; list=country/province only."
129
129
  },
130
- "observable": {
130
+ "linkedTo": {
131
131
  "type": "string",
132
- "enum": [
133
- "any",
134
- "yes",
135
- "no"
136
- ],
137
- "description": "A satellite could see it."
138
- },
139
- "sensors": {
140
- "type": "array",
141
- "items": {
142
- "type": "string",
143
- "enum": [
144
- "sentinel-2",
145
- "sentinel-1-sar",
146
- "viirs-thermal",
147
- "planet",
148
- "vhr-optical",
149
- "multi-sensor",
150
- "none"
151
- ]
152
- },
153
- "description": "Recommended sensor (unassessed passes)."
154
- },
155
- "collectionLevels": {
156
- "type": "array",
157
- "items": {
158
- "type": "string",
159
- "enum": [
160
- "GSD<0.1m",
161
- "GSD<0.5m",
162
- "GSD<1m",
163
- "GSD<10m",
164
- "GSD<100m",
165
- "Impossible"
166
- ]
167
- },
168
- "description": "Resolution needed (unassessed passes)."
132
+ "description": "Shares a connector: facility:<entity_id>, place:<place_key>, actor:<name>. Plan-gated."
169
133
  },
170
- "escalationTrends": {
171
- "type": "array",
172
- "items": {
173
- "type": "string",
174
- "enum": [
175
- "escalating",
176
- "de-escalating",
177
- "stable",
178
- "new"
179
- ]
180
- },
181
- "description": "Trend (unassessed passes)."
134
+ "watchId": {
135
+ "type": "string",
136
+ "description": "Events linked to this watch (list_watches id)."
182
137
  },
183
138
  "sort": {
184
139
  "type": "string",
@@ -187,21 +142,21 @@ export const TOOLS = [
187
142
  "oldest",
188
143
  "geoint"
189
144
  ],
190
- "description": "Default latest. geoint: visible first, then geoint_score, stage."
145
+ "description": "Default latest. geoint (plan-gated): observable, then geoint_score."
191
146
  },
192
147
  "updatedSince": {
193
148
  "type": "string",
194
- "description": "Refolded at/after (ISO); narrows the window."
149
+ "description": "Refolded at/after (ISO)."
195
150
  },
196
151
  "limit": {
197
152
  "type": "integer",
198
153
  "minimum": 1,
199
- "maximum": 500,
200
- "description": "Max rows per page. Default 100."
154
+ "maximum": 50,
155
+ "description": "Page size (default 20). Rows are digests; full rows: full_records."
201
156
  },
202
157
  "cursor": {
203
158
  "type": "string",
204
- "description": "Cursor from meta.next_cursor."
159
+ "description": "From meta.next_cursor."
205
160
  }
206
161
  }
207
162
  },
@@ -221,6 +176,24 @@ export const TOOLS = [
221
176
  "items": {
222
177
  "type": "object"
223
178
  }
179
+ },
180
+ "full_records": {
181
+ "type": "object",
182
+ "description": "The same query on the REST API and the Python SDK, which return every field and larger pages.",
183
+ "properties": {
184
+ "note": {
185
+ "type": "string"
186
+ },
187
+ "rest": {
188
+ "type": "string"
189
+ },
190
+ "sdk": {
191
+ "type": "string"
192
+ },
193
+ "docs": {
194
+ "type": "string"
195
+ }
196
+ }
224
197
  }
225
198
  },
226
199
  "required": [
@@ -399,8 +372,8 @@ export const TOOLS = [
399
372
  "limit": {
400
373
  "type": "integer",
401
374
  "minimum": 1,
402
- "maximum": 100,
403
- "description": "Max scenes. Default 25."
375
+ "maximum": 25,
376
+ "description": "Max scenes. Default 10."
404
377
  }
405
378
  },
406
379
  "required": [
@@ -423,6 +396,24 @@ export const TOOLS = [
423
396
  "items": {
424
397
  "type": "object"
425
398
  }
399
+ },
400
+ "full_records": {
401
+ "type": "object",
402
+ "description": "The same query on the REST API and the Python SDK, which return every field and larger pages.",
403
+ "properties": {
404
+ "note": {
405
+ "type": "string"
406
+ },
407
+ "rest": {
408
+ "type": "string"
409
+ },
410
+ "sdk": {
411
+ "type": "string"
412
+ },
413
+ "docs": {
414
+ "type": "string"
415
+ }
416
+ }
426
417
  }
427
418
  },
428
419
  "required": [
@@ -560,83 +551,6 @@ export const TOOLS = [
560
551
  "destructiveHint": true
561
552
  }
562
553
  },
563
- {
564
- "name": "survey_observable_events",
565
- "description": "Which events a sensor can actually RESOLVE, over the FULL set. **The population is ungated by tasking readiness**, so its total sits above rank_imaging_priority and counts a different unit from query_signals clusters.",
566
- "inputSchema": {
567
- "type": "object",
568
- "properties": {
569
- "sensor": {
570
- "type": "string",
571
- "enum": [
572
- "sentinel-2",
573
- "sentinel-1"
574
- ],
575
- "description": "sentinel-2 = ~10 m optical (needs daylight and clear sky); sentinel-1 = SAR."
576
- },
577
- "bbox": {
578
- "type": "array",
579
- "items": {
580
- "type": "number"
581
- },
582
- "minItems": 4,
583
- "maxItems": 4,
584
- "description": "[west, south, east, north] WGS84. Omit for global."
585
- },
586
- "start_date": {
587
- "type": "string",
588
- "description": "YYYY-MM-DD, inclusive. Default today. Records start 2026-09-23 (earlier: unrecorded, not quiet). Plan-bounded: meta.window_clamp."
589
- },
590
- "end_date": {
591
- "type": "string",
592
- "description": "YYYY-MM-DD, inclusive. Default today; capped at 30 days."
593
- },
594
- "categories": {
595
- "type": "array",
596
- "items": {
597
- "type": "string"
598
- },
599
- "description": "Restrict to these Delta categories."
600
- },
601
- "min_geoint_score": {
602
- "type": "number",
603
- "description": "Drop events below this GEOINT score before surveying."
604
- },
605
- "top_n": {
606
- "type": "number",
607
- "minimum": 1,
608
- "maximum": 50,
609
- "description": "How many observable events to return (default 20)."
610
- }
611
- },
612
- "required": []
613
- },
614
- "outputSchema": {
615
- "type": "object",
616
- "properties": {
617
- "meta": {
618
- "type": "object",
619
- "description": "Query echo, token charge/balance (meta.tokens), and pagination where applicable."
620
- },
621
- "summary": {
622
- "type": "string",
623
- "description": "One-line natural-language summary of the result, ready to relay to a user."
624
- },
625
- "survey": {
626
- "type": "object"
627
- }
628
- },
629
- "required": [
630
- "meta",
631
- "survey"
632
- ]
633
- },
634
- "annotations": {
635
- "readOnlyHint": false,
636
- "openWorldHint": false,
637
- "destructiveHint": true
638
- }
639
- },
640
554
  {
641
555
  "name": "predict_satellite_passes",
642
556
  "description": "WHEN a place can next be imaged and by WHAT: 13 free-systematic and commercial-taskable families. **Every pass is a GEOMETRIC access opportunity** — no operator plan is consulted. retrieval_ok:false means timing is UNAVAILABLE, never \"no passes\".",
@@ -1311,8 +1225,8 @@ export const TOOLS = [
1311
1225
  "limit": {
1312
1226
  "type": "number",
1313
1227
  "minimum": 1,
1314
- "maximum": 200,
1315
- "description": "Developments to return (default 50)."
1228
+ "maximum": 50,
1229
+ "description": "Developments to return (default 20)."
1316
1230
  },
1317
1231
  "offset": {
1318
1232
  "type": "number",
@@ -1400,65 +1314,24 @@ export const TOOLS = [
1400
1314
  }
1401
1315
  },
1402
1316
  {
1403
- "name": "create_standing_order",
1404
- "description": "Put an area under CONTINUOUS watch (the app’s \"Watch this area\"): checked weekly, notifying only when new events cross the bar. **Cost is per CHANGE, not per check.**",
1317
+ "name": "list_watches",
1318
+ "description": "The Watchlist as one list, each entry with a state bucket. `updated_since` returns only watches whose CONTENT changed after that instant — what a synchronised copy should poll.",
1405
1319
  "inputSchema": {
1406
1320
  "type": "object",
1407
1321
  "properties": {
1408
- "bbox": {
1409
- "type": "array",
1410
- "items": {
1411
- "type": "number"
1412
- },
1413
- "minItems": 4,
1414
- "maxItems": 4,
1415
- "description": "[west, south, east, north] WGS84. Required — a global order would fire on everything."
1416
- },
1417
- "name": {
1322
+ "updated_since": {
1418
1323
  "type": "string",
1419
- "description": "Label for the order (default \"Standing order\")."
1324
+ "description": "ISO 8601. Only watches whose CONTENT changed after it — the evidence, not renames."
1420
1325
  },
1421
- "notify_email": {
1422
- "type": "boolean",
1423
- "description": "Email on fire (default true); readable via list_standing_orders anyway."
1424
- }
1425
- },
1426
- "required": [
1427
- "bbox"
1428
- ]
1429
- },
1430
- "outputSchema": {
1431
- "type": "object",
1432
- "properties": {
1433
- "summary": {
1326
+ "cursor": {
1434
1327
  "type": "string",
1435
- "description": "One-line natural-language summary of the result, ready to relay to a user."
1328
+ "description": "Cursor from meta.next_cursor."
1436
1329
  },
1437
- "order": {
1438
- "type": "object"
1439
- }
1440
- },
1441
- "required": [
1442
- "order"
1443
- ]
1444
- },
1445
- "annotations": {
1446
- "readOnlyHint": false,
1447
- "openWorldHint": false,
1448
- "destructiveHint": false
1449
- }
1450
- },
1451
- {
1452
- "name": "list_layer_sets",
1453
- "description": "The layer sets saved on this account. The layer tree itself is not returned: it is an internal format, and opening it is the map's job.",
1454
- "inputSchema": {
1455
- "type": "object",
1456
- "properties": {
1457
1330
  "limit": {
1458
1331
  "type": "integer",
1332
+ "description": "Watches per page when paging (1..500, default 100).",
1459
1333
  "minimum": 1,
1460
- "maximum": 100,
1461
- "description": "Max layer sets to return (default 50)."
1334
+ "maximum": 500
1462
1335
  }
1463
1336
  },
1464
1337
  "required": []
@@ -1470,18 +1343,24 @@ export const TOOLS = [
1470
1343
  "type": "string",
1471
1344
  "description": "One-line natural-language summary of the result, ready to relay to a user."
1472
1345
  },
1473
- "layer_sets": {
1346
+ "watches": {
1474
1347
  "type": "array",
1475
1348
  "items": {
1476
1349
  "type": "object"
1477
1350
  }
1478
1351
  },
1479
- "total": {
1480
- "type": "integer"
1352
+ "buckets": {
1353
+ "type": "object"
1354
+ },
1355
+ "limits": {
1356
+ "type": "object"
1357
+ },
1358
+ "meta": {
1359
+ "type": "object"
1481
1360
  }
1482
1361
  },
1483
1362
  "required": [
1484
- "layer_sets"
1363
+ "watches"
1485
1364
  ]
1486
1365
  },
1487
1366
  "annotations": {
@@ -1491,52 +1370,39 @@ export const TOOLS = [
1491
1370
  }
1492
1371
  },
1493
1372
  {
1494
- "name": "get_layer_set",
1495
- "description": "One saved layer set by id. The serialized layer tree is deliberately not exposed — an internal representation, not a public contract.",
1373
+ "name": "list_notifications",
1374
+ "description": "What changed across the Watchlist, newest first: one row per change a watch reported, with read state. Reading does not mark them read. A value the plan does not open is `locked`, never filled in.",
1496
1375
  "inputSchema": {
1497
1376
  "type": "object",
1498
1377
  "properties": {
1499
- "layer_set_id": {
1378
+ "unread_only": {
1379
+ "type": "boolean",
1380
+ "description": "Only notifications not yet read."
1381
+ },
1382
+ "kind": {
1500
1383
  "type": "string",
1501
- "description": "The layer set id."
1502
- }
1503
- },
1504
- "required": [
1505
- "layer_set_id"
1506
- ]
1507
- },
1508
- "outputSchema": {
1509
- "type": "object",
1510
- "properties": {
1511
- "summary": {
1384
+ "enum": [
1385
+ "event_development",
1386
+ "related_event",
1387
+ "monitoring_anomaly",
1388
+ "site_event",
1389
+ "new_imagery",
1390
+ "standing_order"
1391
+ ]
1392
+ },
1393
+ "watch_id": {
1512
1394
  "type": "string",
1513
- "description": "One-line natural-language summary of the result, ready to relay to a user."
1395
+ "description": "Id from list_watches."
1396
+ },
1397
+ "cursor": {
1398
+ "type": "string",
1399
+ "description": "Cursor from meta.next_cursor."
1514
1400
  },
1515
- "layer_set": {
1516
- "type": "object"
1517
- }
1518
- },
1519
- "required": [
1520
- "layer_set"
1521
- ]
1522
- },
1523
- "annotations": {
1524
- "readOnlyHint": true,
1525
- "openWorldHint": false,
1526
- "destructiveHint": false
1527
- }
1528
- },
1529
- {
1530
- "name": "list_uploaded_layers",
1531
- "description": "The data this account uploaded to the map, plus the formats the uploader accepts. Uploading happens in the app; GeoJSON and GeoTIFF only.",
1532
- "inputSchema": {
1533
- "type": "object",
1534
- "properties": {
1535
1401
  "limit": {
1536
1402
  "type": "integer",
1403
+ "description": "Rows per page (1..25, default 10).",
1537
1404
  "minimum": 1,
1538
- "maximum": 100,
1539
- "description": "Max uploads to return (default 50)."
1405
+ "maximum": 25
1540
1406
  }
1541
1407
  },
1542
1408
  "required": []
@@ -1548,24 +1414,36 @@ export const TOOLS = [
1548
1414
  "type": "string",
1549
1415
  "description": "One-line natural-language summary of the result, ready to relay to a user."
1550
1416
  },
1551
- "uploads": {
1417
+ "notifications": {
1552
1418
  "type": "array",
1553
1419
  "items": {
1554
1420
  "type": "object"
1555
1421
  }
1556
1422
  },
1557
- "total": {
1558
- "type": "integer"
1423
+ "meta": {
1424
+ "type": "object"
1559
1425
  },
1560
- "accepted_formats": {
1561
- "type": "array",
1562
- "items": {
1563
- "type": "string"
1426
+ "full_records": {
1427
+ "type": "object",
1428
+ "description": "The same query on the REST API and the Python SDK, which return every field and larger pages.",
1429
+ "properties": {
1430
+ "note": {
1431
+ "type": "string"
1432
+ },
1433
+ "rest": {
1434
+ "type": "string"
1435
+ },
1436
+ "sdk": {
1437
+ "type": "string"
1438
+ },
1439
+ "docs": {
1440
+ "type": "string"
1441
+ }
1564
1442
  }
1565
1443
  }
1566
1444
  },
1567
1445
  "required": [
1568
- "uploads"
1446
+ "notifications"
1569
1447
  ]
1570
1448
  },
1571
1449
  "annotations": {
@@ -1575,12 +1453,23 @@ export const TOOLS = [
1575
1453
  }
1576
1454
  },
1577
1455
  {
1578
- "name": "list_standing_orders",
1579
- "description": "The standing orders on this key: cadence, area, last check, last actual fire, and quiet_checks — a high quiet_checks means the watch is not earning its place.",
1456
+ "name": "get_watch",
1457
+ "description": "One watch end to end: target, state, latest change, measurements with recent series, standing-order questions, and for an event watch its stage, developments and thread, plus this account's notes.",
1580
1458
  "inputSchema": {
1581
1459
  "type": "object",
1582
- "properties": {},
1583
- "required": []
1460
+ "properties": {
1461
+ "watch_id": {
1462
+ "type": "string",
1463
+ "description": "Id from list_watches."
1464
+ },
1465
+ "include_passes": {
1466
+ "type": "boolean",
1467
+ "description": "Add the collection outlook. Costs the same as predict_satellite_passes; omit it and the call is free."
1468
+ }
1469
+ },
1470
+ "required": [
1471
+ "watch_id"
1472
+ ]
1584
1473
  },
1585
1474
  "outputSchema": {
1586
1475
  "type": "object",
@@ -1589,255 +1478,15 @@ export const TOOLS = [
1589
1478
  "type": "string",
1590
1479
  "description": "One-line natural-language summary of the result, ready to relay to a user."
1591
1480
  },
1592
- "orders": {
1593
- "type": "array",
1594
- "items": {
1595
- "type": "object"
1596
- }
1481
+ "watch": {
1482
+ "type": "object"
1597
1483
  },
1598
- "limits": {
1484
+ "thread": {
1599
1485
  "type": "object"
1600
1486
  }
1601
1487
  },
1602
1488
  "required": [
1603
- "orders"
1604
- ]
1605
- },
1606
- "annotations": {
1607
- "readOnlyHint": true,
1608
- "openWorldHint": false,
1609
- "destructiveHint": false
1610
- }
1611
- },
1612
- {
1613
- "name": "list_monitored_areas",
1614
- "description": "Places under continuous satellite measurement: metric, latest value, change, anomaly flag, coverage. **coverage.window_total is null when the catalog total is UNKNOWN; null never means zero.**",
1615
- "inputSchema": {
1616
- "type": "object",
1617
- "properties": {},
1618
- "required": []
1619
- },
1620
- "outputSchema": {
1621
- "type": "object",
1622
- "properties": {
1623
- "summary": {
1624
- "type": "string",
1625
- "description": "One-line natural-language summary of the result, ready to relay to a user."
1626
- },
1627
- "areas": {
1628
- "type": "array",
1629
- "items": {
1630
- "type": "object"
1631
- }
1632
- },
1633
- "limits": {
1634
- "type": "object"
1635
- },
1636
- "metering": {
1637
- "type": "object"
1638
- }
1639
- },
1640
- "required": [
1641
- "areas"
1642
- ]
1643
- },
1644
- "annotations": {
1645
- "readOnlyHint": true,
1646
- "openWorldHint": false,
1647
- "destructiveHint": false
1648
- }
1649
- },
1650
- {
1651
- "name": "get_monitored_area",
1652
- "description": "One monitored area with its full measurement history. Anomaly flags come from a median-absolute-deviation test, not a fixed threshold. Needs a plan that includes data export.",
1653
- "inputSchema": {
1654
- "type": "object",
1655
- "properties": {
1656
- "area_id": {
1657
- "type": "string",
1658
- "description": "From list_monitored_areas; a metric's polygon_id also resolves."
1659
- }
1660
- },
1661
- "required": [
1662
- "area_id"
1663
- ]
1664
- },
1665
- "outputSchema": {
1666
- "type": "object",
1667
- "properties": {
1668
- "summary": {
1669
- "type": "string",
1670
- "description": "One-line natural-language summary of the result, ready to relay to a user."
1671
- },
1672
- "area": {
1673
- "type": "object"
1674
- },
1675
- "metering": {
1676
- "type": "object"
1677
- }
1678
- },
1679
- "required": [
1680
- "area"
1681
- ]
1682
- },
1683
- "annotations": {
1684
- "readOnlyHint": true,
1685
- "openWorldHint": false,
1686
- "destructiveHint": false
1687
- }
1688
- },
1689
- {
1690
- "name": "create_monitored_area",
1691
- "description": "Put a place under continuous satellite measurement — every new Sentinel-1/2 or VIIRS acquisition (or FIRMS fire detection) is measured. For a QUANTITY at a fixed place; for events use create_standing_order.",
1692
- "inputSchema": {
1693
- "type": "object",
1694
- "properties": {
1695
- "bbox": {
1696
- "type": "array",
1697
- "items": {
1698
- "type": "number"
1699
- },
1700
- "minItems": 4,
1701
- "maxItems": 4,
1702
- "description": "[west, south, east, north] WGS84, under 5,000 km² — a larger box is rejected, not sampled."
1703
- },
1704
- "metric": {
1705
- "type": "string",
1706
- "description": "Plain words (ships, fires, vegetation, water, burn, snow, built_up, moisture, night_lights) or index ids (ndvi, ndwi, nbr, vv, vh …). The sensor follows."
1707
- },
1708
- "satellite": {
1709
- "type": "string",
1710
- "description": "Pick the sensor like the app does (e.g. ship detection on NISAR_L2_GCOV_PROVISIONAL_V1). Default: the metric’s first."
1711
- },
1712
- "name": {
1713
- "type": "string",
1714
- "description": "Label for the area (default \"Monitored area\")."
1715
- },
1716
- "start_date": {
1717
- "type": "string",
1718
- "description": "YYYY-MM-DD to backfill from. Default 3 months ago; longer costs more on the first check."
1719
- }
1720
- },
1721
- "required": [
1722
- "bbox",
1723
- "metric"
1724
- ]
1725
- },
1726
- "outputSchema": {
1727
- "type": "object",
1728
- "properties": {
1729
- "summary": {
1730
- "type": "string",
1731
- "description": "One-line natural-language summary of the result, ready to relay to a user."
1732
- },
1733
- "area": {
1734
- "type": "object"
1735
- },
1736
- "metering": {
1737
- "type": "object"
1738
- }
1739
- },
1740
- "required": [
1741
- "area"
1742
- ]
1743
- },
1744
- "annotations": {
1745
- "readOnlyHint": false,
1746
- "openWorldHint": false,
1747
- "destructiveHint": false
1748
- }
1749
- },
1750
- {
1751
- "name": "list_watches",
1752
- "description": "The Watchlist as one list, each entry with a state bucket. `updated_since` returns only watches whose CONTENT changed after that instant — what a synchronised copy should poll.",
1753
- "inputSchema": {
1754
- "type": "object",
1755
- "properties": {
1756
- "updated_since": {
1757
- "type": "string",
1758
- "description": "ISO 8601. Only watches whose CONTENT changed after it — the evidence, not renames."
1759
- },
1760
- "cursor": {
1761
- "type": "string",
1762
- "description": "Cursor from meta.next_cursor."
1763
- },
1764
- "limit": {
1765
- "type": "integer",
1766
- "description": "Watches per page when paging (1..500, default 100).",
1767
- "minimum": 1,
1768
- "maximum": 500
1769
- }
1770
- },
1771
- "required": []
1772
- },
1773
- "outputSchema": {
1774
- "type": "object",
1775
- "properties": {
1776
- "summary": {
1777
- "type": "string",
1778
- "description": "One-line natural-language summary of the result, ready to relay to a user."
1779
- },
1780
- "watches": {
1781
- "type": "array",
1782
- "items": {
1783
- "type": "object"
1784
- }
1785
- },
1786
- "buckets": {
1787
- "type": "object"
1788
- },
1789
- "limits": {
1790
- "type": "object"
1791
- },
1792
- "meta": {
1793
- "type": "object"
1794
- }
1795
- },
1796
- "required": [
1797
- "watches"
1798
- ]
1799
- },
1800
- "annotations": {
1801
- "readOnlyHint": true,
1802
- "openWorldHint": false,
1803
- "destructiveHint": false
1804
- }
1805
- },
1806
- {
1807
- "name": "get_watch",
1808
- "description": "One watch end to end: target, state, latest change, measurements with recent series, standing-order questions, and for an event watch its stage, developments and thread, plus this account's notes.",
1809
- "inputSchema": {
1810
- "type": "object",
1811
- "properties": {
1812
- "watch_id": {
1813
- "type": "string",
1814
- "description": "Id from list_watches."
1815
- },
1816
- "include_passes": {
1817
- "type": "boolean",
1818
- "description": "Add the collection outlook. Costs the same as predict_satellite_passes; omit it and the call is free."
1819
- }
1820
- },
1821
- "required": [
1822
- "watch_id"
1823
- ]
1824
- },
1825
- "outputSchema": {
1826
- "type": "object",
1827
- "properties": {
1828
- "summary": {
1829
- "type": "string",
1830
- "description": "One-line natural-language summary of the result, ready to relay to a user."
1831
- },
1832
- "watch": {
1833
- "type": "object"
1834
- },
1835
- "thread": {
1836
- "type": "object"
1837
- }
1838
- },
1839
- "required": [
1840
- "watch"
1489
+ "watch"
1841
1490
  ]
1842
1491
  },
1843
1492
  "annotations": {
@@ -1871,7 +1520,7 @@ export const TOOLS = [
1871
1520
  },
1872
1521
  "minItems": 4,
1873
1522
  "maxItems": 4,
1874
- "description": "AREA: [W,S,E,N] WGS84."
1523
+ "description": "AREA: [W,S,E,N] WGS84, at most 100,000 km² (larger → 400)."
1875
1524
  },
1876
1525
  "entity_id": {
1877
1526
  "type": "string",
@@ -2117,45 +1766,6 @@ export const TOOLS = [
2117
1766
  "destructiveHint": false
2118
1767
  }
2119
1768
  },
2120
- {
2121
- "name": "delete_note",
2122
- "description": "Delete one note from a watch. The deletion itself stays in the account's action log.",
2123
- "inputSchema": {
2124
- "type": "object",
2125
- "properties": {
2126
- "watch_id": {
2127
- "type": "string",
2128
- "description": "Id from list_watches."
2129
- },
2130
- "note_id": {
2131
- "type": "string",
2132
- "description": "Note id from get_watch."
2133
- }
2134
- },
2135
- "required": [
2136
- "watch_id",
2137
- "note_id"
2138
- ]
2139
- },
2140
- "outputSchema": {
2141
- "type": "object",
2142
- "properties": {
2143
- "summary": {
2144
- "type": "string",
2145
- "description": "One-line natural-language summary of the result, ready to relay to a user."
2146
- },
2147
- "deleted": {
2148
- "type": "string"
2149
- }
2150
- }
2151
- },
2152
- "annotations": {
2153
- "readOnlyHint": false,
2154
- "openWorldHint": false,
2155
- "destructiveHint": true,
2156
- "idempotentHint": true
2157
- }
2158
- },
2159
1769
  {
2160
1770
  "name": "search_entities",
2161
1771
  "description": "Find a named place (airport, base, plant, port, dam, strait…) in any language or by IATA/ICAO code. Max 50.",
@@ -2269,415 +1879,6 @@ export const TOOLS = [
2269
1879
  "openWorldHint": false,
2270
1880
  "destructiveHint": false
2271
1881
  }
2272
- },
2273
- {
2274
- "name": "get_related_events",
2275
- "description": "The relations recorded for one event: others at the same registry facility, naming the same place, or stored as the same campaign, each saying what is shared; plus reports merged into it. Merely-nearby events are not relations and are not returned. Plan-dependent: see `plan_lock`.",
2276
- "inputSchema": {
2277
- "type": "object",
2278
- "properties": {
2279
- "event_id": {
2280
- "type": "string",
2281
- "description": "The event id (a UUID) from query_signals."
2282
- }
2283
- },
2284
- "required": [
2285
- "event_id"
2286
- ]
2287
- },
2288
- "outputSchema": {
2289
- "type": "object",
2290
- "properties": {
2291
- "summary": {
2292
- "type": "string",
2293
- "description": "One-line natural-language summary of the result, ready to relay to a user."
2294
- },
2295
- "anchor": {
2296
- "type": "object"
2297
- },
2298
- "facilities": {
2299
- "type": "array",
2300
- "items": {
2301
- "type": "object"
2302
- }
2303
- },
2304
- "places": {
2305
- "type": "array",
2306
- "items": {
2307
- "type": "object"
2308
- }
2309
- },
2310
- "related": {
2311
- "type": "array",
2312
- "items": {
2313
- "type": "object"
2314
- }
2315
- },
2316
- "merged_in": {
2317
- "type": "array",
2318
- "items": {
2319
- "type": "object"
2320
- }
2321
- },
2322
- "accounting": {
2323
- "type": "object"
2324
- }
2325
- },
2326
- "required": [
2327
- "related"
2328
- ]
2329
- },
2330
- "annotations": {
2331
- "readOnlyHint": true,
2332
- "openWorldHint": false,
2333
- "destructiveHint": false
2334
- }
2335
- },
2336
- {
2337
- "name": "lookup_elevation",
2338
- "description": "Terrain height from the Copernicus DEM GLO-30 for a point, bbox or polygon, with relief — the number that governs SAR layover and shadow. A SURFACE model; `covered: false` is no data, not 0 m. Cite the `attribution`.",
2339
- "inputSchema": {
2340
- "type": "object",
2341
- "properties": {
2342
- "lat": {
2343
- "type": "number",
2344
- "minimum": -90,
2345
- "maximum": 90,
2346
- "description": "Latitude of a single point to measure (use with lon)."
2347
- },
2348
- "lon": {
2349
- "type": "number",
2350
- "minimum": -180,
2351
- "maximum": 180,
2352
- "description": "Longitude of a single point to measure (use with lat)."
2353
- },
2354
- "bbox": {
2355
- "type": "array",
2356
- "items": {
2357
- "type": "number"
2358
- },
2359
- "minItems": 4,
2360
- "maxItems": 4,
2361
- "description": "[lon_min, lat_min, lon_max, lat_max] WGS84."
2362
- },
2363
- "polygon": {
2364
- "type": "array",
2365
- "items": {
2366
- "type": "array",
2367
- "items": {
2368
- "type": "number"
2369
- },
2370
- "minItems": 2,
2371
- "maxItems": 2
2372
- },
2373
- "minItems": 3,
2374
- "description": "WGS84 ring [[lon, lat], …]. Statistics cover only the samples inside it."
2375
- }
2376
- }
2377
- },
2378
- "outputSchema": {
2379
- "type": "object",
2380
- "properties": {
2381
- "mode": {
2382
- "type": "string",
2383
- "description": "Which form was measured: 'point', 'bbox' or 'polygon'."
2384
- },
2385
- "elevation": {
2386
- "type": "object"
2387
- },
2388
- "attribution": {
2389
- "type": "string",
2390
- "description": "Required Copernicus DEM credit (licence Article 6(b))."
2391
- }
2392
- },
2393
- "required": [
2394
- "elevation"
2395
- ]
2396
- },
2397
- "annotations": {
2398
- "readOnlyHint": true,
2399
- "openWorldHint": false,
2400
- "destructiveHint": false
2401
- }
2402
- },
2403
- {
2404
- "name": "analyze_terrain",
2405
- "description": "Compute FROM the terrain. `sar_geometry` returns layover, shadow, foreshortening and mean LOCAL incidence — **required, not assumed, because it changes with pass direction**. `profile` returns ground along a line and a line-of-sight verdict. Cite the `attribution`.",
2406
- "inputSchema": {
2407
- "type": "object",
2408
- "required": [
2409
- "operation"
2410
- ],
2411
- "properties": {
2412
- "operation": {
2413
- "type": "string",
2414
- "enum": [
2415
- "sar_geometry",
2416
- "profile"
2417
- ],
2418
- "description": "'sar_geometry' = layover/shadow over an area; 'profile' = ground along a line + line-of-sight."
2419
- },
2420
- "bbox": {
2421
- "type": "array",
2422
- "items": {
2423
- "type": "number"
2424
- },
2425
- "minItems": 4,
2426
- "maxItems": 4,
2427
- "description": "For 'sar_geometry': [lon_min, lat_min, lon_max, lat_max] WGS84."
2428
- },
2429
- "incidence_deg": {
2430
- "type": "number",
2431
- "minimum": 10,
2432
- "maximum": 80,
2433
- "description": "For 'sar_geometry'. Sentinel-1 IW spans ~29-46°."
2434
- },
2435
- "look_azimuth_deg": {
2436
- "type": "number",
2437
- "minimum": 0,
2438
- "maximum": 360,
2439
- "description": "For 'sar_geometry': bearing along ground range. Right-looking descending ≈ 270."
2440
- },
2441
- "lat": {
2442
- "type": "number",
2443
- "minimum": -90,
2444
- "maximum": 90,
2445
- "description": "For 'profile': latitude of the observer end."
2446
- },
2447
- "lon": {
2448
- "type": "number",
2449
- "minimum": -180,
2450
- "maximum": 180,
2451
- "description": "For 'profile': longitude of the observer end."
2452
- },
2453
- "to_lat": {
2454
- "type": "number",
2455
- "minimum": -90,
2456
- "maximum": 90,
2457
- "description": "For 'profile': latitude of the far end."
2458
- },
2459
- "to_lon": {
2460
- "type": "number",
2461
- "minimum": -180,
2462
- "maximum": 180,
2463
- "description": "For 'profile': longitude of the far end."
2464
- },
2465
- "observer_height_m": {
2466
- "type": "number",
2467
- "minimum": 0,
2468
- "description": "For 'profile': eye height above ground, default 2 m."
2469
- }
2470
- }
2471
- },
2472
- "outputSchema": {
2473
- "type": "object",
2474
- "properties": {
2475
- "operation": {
2476
- "type": "string"
2477
- },
2478
- "sar_geometry": {
2479
- "type": "object"
2480
- },
2481
- "profile": {
2482
- "type": "object"
2483
- },
2484
- "attribution": {
2485
- "type": "string",
2486
- "description": "Required Copernicus DEM credit (licence Article 6(b))."
2487
- }
2488
- }
2489
- },
2490
- "annotations": {
2491
- "readOnlyHint": true,
2492
- "openWorldHint": false,
2493
- "destructiveHint": false
2494
- }
2495
- },
2496
- {
2497
- "name": "measure_index_series",
2498
- "description": "Measure a spectral index over an area scene by scene through the Sentinel-2 archive. **Call `estimate_only: true` first** — free, and returns the scene count, real date span and cost. At most 24 scenes, so a longer period is a SAMPLE. Cite the `attribution`.",
2499
- "inputSchema": {
2500
- "type": "object",
2501
- "required": [
2502
- "index",
2503
- "start",
2504
- "end"
2505
- ],
2506
- "properties": {
2507
- "polygon": {
2508
- "type": "array",
2509
- "items": {
2510
- "type": "array",
2511
- "items": {
2512
- "type": "number"
2513
- }
2514
- },
2515
- "description": "WGS84 ring [[lon, lat], …], 3+ vertices. Statistics cover the samples inside it."
2516
- },
2517
- "bbox": {
2518
- "type": "array",
2519
- "items": {
2520
- "type": "number"
2521
- },
2522
- "minItems": 4,
2523
- "maxItems": 4,
2524
- "description": "Alternative to polygon: [lon_min, lat_min, lon_max, lat_max] WGS84."
2525
- },
2526
- "index": {
2527
- "type": "string",
2528
- "enum": [
2529
- "ndvi",
2530
- "evi",
2531
- "savi",
2532
- "ndmi",
2533
- "ndwi",
2534
- "mndwi",
2535
- "ndbi",
2536
- "ndsi",
2537
- "nbr",
2538
- "iron-oxide",
2539
- "clay",
2540
- "ferrous"
2541
- ],
2542
- "description": "Which optical index to measure."
2543
- },
2544
- "start": {
2545
- "type": "string",
2546
- "description": "YYYY-MM-DD (UTC). Clamped forward to 2015-06-27 if earlier."
2547
- },
2548
- "end": {
2549
- "type": "string",
2550
- "description": "End date YYYY-MM-DD (UTC)."
2551
- },
2552
- "max_scenes": {
2553
- "type": "integer",
2554
- "minimum": 1,
2555
- "maximum": 24,
2556
- "description": "Cap on scenes measured in this call. Server maximum 24."
2557
- },
2558
- "max_cloud_cover": {
2559
- "type": "number",
2560
- "minimum": 1,
2561
- "maximum": 100,
2562
- "description": "Scene cloud-cover ceiling in percent. Default 30."
2563
- },
2564
- "estimate_only": {
2565
- "type": "boolean",
2566
- "description": "True = free: scene count, date span and cost, without measuring."
2567
- }
2568
- }
2569
- },
2570
- "outputSchema": {
2571
- "type": "object",
2572
- "properties": {
2573
- "summary": {
2574
- "type": "string",
2575
- "description": "One-line natural-language summary of the result, ready to relay to a user."
2576
- },
2577
- "estimate": {
2578
- "type": "object"
2579
- },
2580
- "series": {
2581
- "type": "object"
2582
- },
2583
- "meta": {
2584
- "type": "object",
2585
- "description": "Query echo, token charge/balance (meta.tokens), and pagination where applicable."
2586
- },
2587
- "attribution": {
2588
- "type": "string"
2589
- }
2590
- }
2591
- },
2592
- "annotations": {
2593
- "readOnlyHint": false,
2594
- "openWorldHint": false,
2595
- "destructiveHint": true
2596
- }
2597
- },
2598
- {
2599
- "name": "detect_ships",
2600
- "description": "Count vessel-like targets in ONE Sentinel-1 SAR scene by CFAR detection — radar sees through cloud and at night. **Read `caveats` before reporting the number**: land mask, offshore exclusion and partial coverage change what it means.",
2601
- "inputSchema": {
2602
- "type": "object",
2603
- "required": [
2604
- "collection",
2605
- "item_id"
2606
- ],
2607
- "properties": {
2608
- "collection": {
2609
- "type": "string",
2610
- "enum": [
2611
- "sentinel-1-grd",
2612
- "sentinel-1-rtc",
2613
- "NISAR_L2_GCOV_PROVISIONAL_V1"
2614
- ],
2615
- "description": "Collection of the scene (Sentinel-1, or NISAR L-band — converted first, extra tokens)."
2616
- },
2617
- "item_id": {
2618
- "type": "string",
2619
- "description": "STAC item id from search_imagery."
2620
- },
2621
- "bbox": {
2622
- "type": "array",
2623
- "items": {
2624
- "type": "number"
2625
- },
2626
- "minItems": 4,
2627
- "maxItems": 4,
2628
- "description": "[lon_min, lat_min, lon_max, lat_max] WGS84, within the scene."
2629
- },
2630
- "geometry": {
2631
- "type": "object"
2632
- },
2633
- "algorithm_version": {
2634
- "type": "string",
2635
- "enum": [
2636
- "auto",
2637
- "v2",
2638
- "v3"
2639
- ],
2640
- "description": "'auto' (default) picks the recommended version for the sensor."
2641
- }
2642
- }
2643
- },
2644
- "outputSchema": {
2645
- "type": "object",
2646
- "properties": {
2647
- "summary": {
2648
- "type": "string",
2649
- "description": "One-line natural-language summary of the result, ready to relay to a user."
2650
- },
2651
- "count": {
2652
- "type": "integer",
2653
- "description": "Vessel-like targets detected. Read `caveats` before quoting it."
2654
- },
2655
- "ships": {
2656
- "type": "object"
2657
- },
2658
- "caveats": {
2659
- "type": "array",
2660
- "items": {
2661
- "type": "string"
2662
- }
2663
- },
2664
- "scene": {
2665
- "type": "object"
2666
- },
2667
- "processing": {
2668
- "type": "object"
2669
- },
2670
- "meta": {
2671
- "type": "object",
2672
- "description": "Query echo, token charge/balance (meta.tokens), and pagination where applicable."
2673
- }
2674
- }
2675
- },
2676
- "annotations": {
2677
- "readOnlyHint": false,
2678
- "openWorldHint": false,
2679
- "destructiveHint": true
2680
- }
2681
1882
  }
2682
1883
  ];
2683
1884
  export const RESOURCES = [
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, ListResourcesRequestSchema, ListResourceTemplatesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
23
23
  import { RESOURCES, RESOURCE_TEMPLATES, TOOLS } from './catalog.js';
24
- const VERSION = '2.0.0';
24
+ const VERSION = '3.0.0';
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": "2.0.0",
3
+ "version": "3.0.0",
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": {