feat(mcp): live airspace + maritime tools; fix OAuth consent UI#2442
feat(mcp): live airspace + maritime tools; fix OAuth consent UI#2442
Conversation
- CSS content:'\2192' (not HTML entity which doesn't work in CSS) - Rename logo/title to "WorldMonitor MCP" on both consent and error pages - Inject real news headlines into get_country_brief to prevent hallucination Fetches list-feed-digest (4s budget), passes top-15 headlines as ?context= to get-country-intel-brief; brief timeout reduced to 24s to stay under Edge ceiling
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThis PR delivers three focused fixes: corrects a CSS Key changes:
Confidence Score: 5/5Safe to merge — all three changes are correct and the only findings are P2 style suggestions that do not block correctness. The CSS fix is unambiguously correct, the branding rename is clean, and the context-injection logic has proper error isolation (try/catch fallback). No P0 or P1 issues found. The three P2 notes (type duplication, query-param vs. POST-body, tight timing budget) are improvement suggestions rather than defects. No files require special attention, though api/mcp.ts is worth a second read if the timing margin ever becomes a concern in production. Important Files Changed
Sequence DiagramsequenceDiagram
participant Client as MCP Client
participant Edge as mcp.ts (Edge Fn)
participant Digest as /api/news/v1/list-feed-digest
participant Brief as /api/intelligence/v1/get-country-intel-brief
Client->>Edge: tools/call get_country_brief {country_code, framework}
Edge->>Digest: GET ?variant=geo&lang=en (timeout 4s)
alt digest ok
Digest-->>Edge: {categories: {items: [{title}]}}
Note over Edge: Extract top-15 headlines, join with newline, slice(0,4000), encodeURIComponent
else digest fails / timeout
Digest-->>Edge: error (caught, contextParam='')
end
Edge->>Brief: POST ?context=<encoded> {country_code, framework} (timeout 24s)
Brief-->>Edge: intelligence brief JSON
Edge-->>Client: {content: [{type:"text", text: JSON}]}
Reviews (1): Last reviewed commit: "fix(oauth): fix CSS arrow bullets + add ..." | Re-trigger Greptile |
| signal: AbortSignal.timeout(4_000), | ||
| }); | ||
| if (digestRes.ok) { | ||
| type DigestPayload = { categories?: Record<string, { items?: { title?: string }[] }> }; |
There was a problem hiding this comment.
DigestPayload type is duplicated
The DigestPayload type declaration inside get_country_brief._execute is identical to the one inside get_world_brief._execute (line 272). Declaring it once at module level removes the duplication and keeps a single source of truth if the shape ever changes.
// At module level, before TOOL_REGISTRY:
type DigestPayload = { categories?: Record<string, { items?: { title?: string }[] }> };New tools answer real-time positional questions via existing bbox RPCs: - get_airspace: civilian ADS-B (OpenSky) + military flights over any country parallel-fetches track-aircraft + list-military-flights, capped at 100 each - get_maritime_activity: AIS density zones + disruptions for a country's waters calls get-vessel-snapshot with country bbox Country → bounding box resolved via shared/country-bboxes.json (167 entries, generated from public/data/countries.geojson by scripts/generate-country-bboxes.cjs). Both API calls use 8s AbortSignal.timeout; get_airspace uses Promise.allSettled so one failure doesn't block the other.
- JSON import: add 'with { type: json }' so node --test works without tsx loader
- get_airspace: surface upstream failures; partial outage => partial:true+warnings,
total outage => throw (prevents misleading zero-aircraft response)
- pre-push hook: add #!/usr/bin/env bash shebang (was no shebang, ran as /bin/sh
on Linux CI/contributors; process substitution + [[ ]] require bash)
Vercel's esbuild bundler does not support `with { type: 'json' }` import
attributes, causing builds to fail with "Expected ';' but found 'with'".
Fix: generate shared/country-bboxes.ts (typed TS module) alongside the
existing JSON file. The TS import has no attributes and bundles cleanly
with all esbuild versions.
Also extend the pre-push bundle check to include api/*.ts root-level files
so this class of error is caught locally before push.
…rgin) Digest pre-fetch: 4 s → 2 s (cached endpoint, silent fallback on miss) Brief call: 24 s → 22 s Total worst-case: 24 s vs Vercel Edge 30 s hard kill — was 28 s (2 s margin)
9 new tests: - get_airspace: happy path, unknown code, partial failure (mil down), total failure (-32603), type=civilian skips military fetch - get_maritime_activity: happy path, unknown code, API failure (-32603), empty snapshot handled gracefully Also fixes import to use .ts extension so Node --test resolver finds the country-bboxes module (tsx resolves .ts directly; .js alias only works under moduleResolution:bundler at typecheck time)
…orts Vercel edge bundler refuses .ts extension imports even from .ts edge functions. Plain .js is the only safe runtime import for edge functions. Pattern: generate shared/country-bboxes.js (pure ESM, no TS syntax) + shared/country-bboxes.d.ts (type declaration). TypeScript uses the .d.ts for tuple types at check time; Vercel and Node --test load the .js at runtime. The previous .ts module is removed.
Summary
New MCP Tools
get_airspace— live ADS-B aircraft over any country. Queries civilian flights (OpenSky track-aircraft) and military aircraft (list-military-flights) in parallel using country bbox. Supportstype: all|civilian|militaryfilter. Returns counts + flight lists with callsign, position, altitude, heading.get_maritime_activity— live AIS vessel density and disruptions for a country's waters. Returns density zones (ships/day, intensity), dark ship events, chokepoint congestion.shared/country-bboxes.json(167 entries, generated frompublic/data/countries.geojsonbyscripts/generate-country-bboxes.cjs).OAuth Consent Page Fixes
content:'→'→content:'\2192'(HTML entities don't work in CSScontent:)Country Brief Context Injection
get_country_briefnow fetcheslist-feed-digest?variant=geo&lang=enheadlines (4s budget) before calling the brief API?context=toget-country-intel-brief— grounds the LLM and prevents hallucinated eventsTest plan
get_airspace({ country_code: "AE" })— returns live flight counts + positions over UAEget_airspace({ country_code: "TW", type: "military" })— military onlyget_maritime_activity({ country_code: "AE" })— density zones + disruptions for Gulf→) render correctly on consent page