Skip to content

Conversation

@ochafik
Copy link
Collaborator

@ochafik ochafik commented Jan 11, 2026

Summary

Adds a CesiumJS 3D globe example that demonstrates WebGL rendering in sandboxed iframes.

Screenshot 2026-01-11 at 13 36 55

What this adds

  • examples/map-server/ - A complete MCP server with:
    • geocode tool - Search for locations using OpenStreetMap Nominatim
    • show-map tool - Display an interactive 3D globe with CesiumJS

Why this matters

CesiumJS is a good stress test for the CSP and iframe handling because it:

Testing

cd examples/map-server
npm install
npm start

Then run the basic-host example which will automatically discover and connect to all example servers.

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 11, 2026

Open in StackBlitz

@modelcontextprotocol/ext-apps

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/ext-apps@235

@modelcontextprotocol/server-basic-react

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-basic-react@235

@modelcontextprotocol/server-basic-vanillajs

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-basic-vanillajs@235

@modelcontextprotocol/server-budget-allocator

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-budget-allocator@235

@modelcontextprotocol/server-cohort-heatmap

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-cohort-heatmap@235

@modelcontextprotocol/server-customer-segmentation

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-customer-segmentation@235

@modelcontextprotocol/server-scenario-modeler

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-scenario-modeler@235

@modelcontextprotocol/server-system-monitor

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-system-monitor@235

@modelcontextprotocol/server-threejs

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-threejs@235

@modelcontextprotocol/server-wiki-explorer

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-wiki-explorer@235

commit: d9a16d8

ochafik and others added 4 commits January 11, 2026 14:34
A WebGL-based 3D globe example that demonstrates:
- CesiumJS integration with MCP Apps
- CSP configuration for external tile servers
- worker-src directive usage for tile decoding

Tools:
- geocode: Search places via OpenStreetMap Nominatim
- show-map: Display interactive 3D globe at coordinates

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@ochafik ochafik force-pushed the fix/webgl-document-write branch from 67b9ec9 to e841af3 Compare January 11, 2026 14:34
@ochafik ochafik changed the base branch from ochafik/fix-csp to main January 11, 2026 14:34
@ochafik ochafik marked this pull request as ready for review January 11, 2026 14:34
- Rename examples/cesium-map-server to examples/map-server
- Update package name to @modelcontextprotocol/server-map
- Add README.md with documentation
@ochafik ochafik force-pushed the fix/webgl-document-write branch from 39154b4 to 484615f Compare January 11, 2026 15:30
- Add fullscreen toggle button (only shown if host supports it)
- Use autoResize: false and manually send height of 400px
- Hide Cesium UI controls (home, scene mode picker)
- Remove location label (gets stale quickly)
- Use full device pixel ratio for sharp rendering on high-DPI displays
- Resize Cesium viewer when display mode changes
@ochafik ochafik force-pushed the fix/webgl-document-write branch from 484615f to 3ffa9b6 Compare January 11, 2026 15:32
…rners

- Add camera move end listener for reverse geocoding
- Debounce Nominatim API calls (1.5s) to respect rate limits
- Log location name to console on camera move
- Add nominatim.openstreetmap.org to CSP connectDomains
- Add 8px rounded corners to map container
- Set canvas imageRendering to 'auto' (CesiumJS defaults to pixelated)
- Set resolutionScale to window.devicePixelRatio for native resolution
…ging

Rendering fixes:
- Remove incorrect resolutionScale = devicePixelRatio which was doubling
  the scaling factor on Retina displays (2x2=4x), causing blurriness
- Disable FXAA anti-aliasing which can cause blurriness on high-DPI displays
- Keep useBrowserRecommendedResolution: false to use native devicePixelRatio

Reverse geocoding improvements:
- Add getVisibleExtent() using camera.computeViewRectangle() to get the
  visible bounding box (west, south, east, north)
- Add getScaleDimensions() to calculate visible area in km
- Add calculateNominatimZoom() to map visible extent to appropriate
  Nominatim zoom level (3=country to 18=building)
- Log visible extent with dimensions on each camera move
- Pass zoom parameter to Nominatim for context-aware geocoding results
- Update model context with visible area dimensions
Changes:
- Remove zoom granularity logic from reverse geocoding (was not working)
- Keep extent logging in both console and model context
- Replace flyTo animation with instant setView positioning
- Add waitForTilesLoaded() to detect when tiles finish loading
- Keep loading spinner visible until:
  1. Tool input positions camera to destination
  2. Tiles at destination are fully loaded
- Add 5-second fallback timeout if no tool input received
- Add 10-second timeout for tile loading to prevent infinite wait
Replace center-point reverse geocoding with Nominatim viewbox search:
- Add searchPlacesInBox() that queries Nominatim with bounded viewbox
- Uses layer=address&featuretype=settlement to find cities/towns
- Returns up to 5 visible places in the current view
- Update model context with 'Visible places: City1, City2, ...'
- Still includes center coordinates and extent dimensions

This provides better context about what's actually visible on the map
rather than just the address at the center point.
Root cause: Standard OSM tiles are 256x256 pixels. On Retina displays
(devicePixelRatio=2), these get scaled up 2x, making them look pixelated.

Solution: Switch to CARTO Voyager tiles which provide @2x retina support:
- Detect high-DPI displays using window.devicePixelRatio
- Use 512x512 tiles with @2x suffix on Retina displays
- Use 256x256 tiles on standard displays
- Set tileWidth/tileHeight to match actual tile size
- Use CARTO subdomains (a,b,c,d) for load balancing
- Update CSP to allow CARTO tile domains

CARTO Voyager provides clean OSM-based tiles with free @2x retina support,
no API key required.
- Switch back from CARTO to standard OSM tiles (tile.openstreetmap.org)
  for better detail and label rendering
- Fix geocoding: use reverse geocode API instead of search API
  (search API requires a q= parameter, returns 400 without it)
- Update CSP domains for OSM tile server
Simplify CSP to use wildcard for both tiles and geocoding:
- connectDomains: *.openstreetmap.org covers tile.* and nominatim.*
- resourceDomains: *.openstreetmap.org for tile images
- Sample multiple points in visible extent to discover places
- Adaptive sampling based on extent size:
  - < 30km: center only (city zoom)
  - 30-100km: center + 2 corners
  - > 100km: center + 4 quadrants
- Proper rate limiting for Nominatim (1.1s between requests)
- Shows 'Visible places: City1, City2, ...' in model context
- Fix: move geocode tool registration inside createServer()
@ochafik ochafik changed the title feat: Add CesiumJS map server example examples: Add CesiumJS Map App example Jan 11, 2026
- Fix incorrect Express listen() callback signature (err param doesn't exist)
- Add map-server to e2e test suite with SLOW_SERVERS timeout (5s for tiles)
- Improve comment about experimental ui/update-model-context API

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants