Template

3D globe widget for MCP Apps

Put places on a WebGL globe inside the conversation. Each place becomes a marker sized by its value, the globe spins on its own and the person can drag it around.

Uses three.js

Add a UI to your MCP server

Where are our customers? Break it down by city, I want to see it on a map.

Used show_globe_3d

The house design: black outline, butter yellow and a marker swipe under the title.

When to use a 3D globe

A globe is for data where "where" is the point and the places are spread across continents. A flat list hides that; a globe shows it at a glance:

  • Customers, users or sales by city, with the value as the count or the revenue.
  • Offices, warehouses or stores of a company with a presence in several countries.
  • Event locations: a world tour, a conference series, meetups across regions.
  • Where sign-ups or attendees came from, after a webinar or a launch.

If your places sit in one country, the globe will crowd them into one spot: a bar chart of the same data reads better. For a striking set of options rather than places, see the 3D carousel.

How the model fills the globe

The data schema asks for a title, an optional subtitle and at least one entry in places. Each place needs a name, a lat (between -90 and 90) and a lon (between -180 and 180). The optional value sets the marker size and fills the list beside the globe.

Models usually know the coordinates of major cities, so a tool that returns "orders per city" is enough: the model adds latitude and longitude when it calls the widget's tool. If your places are not well known (a warehouse on an industrial estate), return the coordinates from your own tool. Marker size grows with the square root of the value, so one large city does not swallow the rest, and the globe starts turned toward the place with the largest value.

What it does in the chat

The globe is drawn with three.js in WebGL. Land is a cloud of dots built from coarse continent outlines that live inside the widget's script, so there are no map tiles and nothing to fetch beyond the library. It turns slowly on its own (not for people who prefer reduced motion), and the person can drag it to look around. Zoom and pan are off, so the globe never steals the chat's scroll.

Beside it, a list ranks each place with its value and a bar relative to the largest, plus the total. Each design changes the globe itself, not only its colors: Aurora and Neon raise markers on glowing stems whose height follows the value, Editorial draws an engraved graticule, Brutalist uses fat dots and a hard offset shadow.

three.js is a library from Widgetry's closed catalog, pinned to one version and loaded from jsDelivr through an import map. The widget's manifest declares https://cdn.jsdelivr.net in the resource CSP (resourceDomains and connectDomains), which is what hosts need to let it load. The MCP Apps CSP guide explains why a globe without that declaration shows up blank.

Make it yours

The globe reads every color from CSS custom properties, so it follows any of the twenty built-in designs and the ones your organization makes in the designer. The script is a module registered with widgetry.onRender that cleans up its WebGL renderer before every new render; you can edit it, along with the markup, styles and schema. Turn rotation speed up or down, or add a field such as a category and color markers by it.

Take it to your server

Link the published globe from your MCP server, or download its HTML and manifest, which already carries the CSP: add UI to your MCP server shows both. Agents can create one too with the Widgetry tools, as described in create MCP App widgets with your AI agent.

The data it takes

FieldTypeWhat it is
titlerequiredstring
subtitlestring
placesrequiredobject[]
└ namerequiredstring
└ latrequirednumber
└ lonrequirednumber
└ valuenumberSets the marker size

Sample data

{
  "title": "Customers by city",
  "subtitle": "Sample data",
  "places": [
    {
      "name": "Madrid",
      "lat": 40.42,
      "lon": -3.7,
      "value": 42
    },
    {
      "name": "New York",
      "lat": 40.71,
      "lon": -74.01,
      "value": 21
    },
    {
      "name": "London",
      "lat": 51.51,
      "lon": -0.13,
      "value": 18
    },
    {
      "name": "Mexico City",
      "lat": 19.43,
      "lon": -99.13,
      "value": 15
    },
    {
      "name": "Sydney",
      "lat": -33.87,
      "lon": 151.21,
      "value": 12
    },
    {
      "name": "Stockholm",
      "lat": 59.33,
      "lon": 18.07,
      "value": 9
    }
  ]
}

The tool that shows it

A widget made from this template is shown by one tool. The model reads its description to decide when to call it and fills the input schema with the data. This is the definition Widgetry exports:

{
  "name": "show_globe_3d",
  "title": "3D globe",
  "description": "Shows places on an interactive 3D globe: each place has a name, latitude, longitude and an optional value that sets the size of its marker. The list of places sits beside it. Use it for offices, customers, events or any data spread across the world.",
  "inputSchema": {
    "type": "object",
    "required": [
      "title",
      "places"
    ],
    "properties": {
      "title": {
        "type": "string"
      },
      "subtitle": {
        "type": "string"
      },
      "places": {
        "type": "array",
        "minItems": 1,
        "items": {
          "type": "object",
          "required": [
            "name",
            "lat",
            "lon"
          ],
          "properties": {
            "name": {
              "type": "string"
            },
            "lat": {
              "type": "number",
              "minimum": -90,
              "maximum": 90
            },
            "lon": {
              "type": "number",
              "minimum": -180,
              "maximum": 180
            },
            "value": {
              "type": "number",
              "minimum": 0,
              "description": "Sets the marker size"
            }
          }
        }
      }
    }
  }
}

Your first widget, in the chat in minutes

Pick a template, drop in your data and see it as ChatGPT or Claude will show it. Then link it from your MCP server, or let your agent build the next one.