refactor: name the view tool show_in_gods_eye_view

The tool and its panel now say "Show in God's Eye View" rather than
"show on the globe", in tool names, descriptions, server instructions and
docs.
This commit is contained in:
Sameh Khamis committed 2026-10-02 15:21:36 -07:00
1 parent 216a75ac71
commit 47ef168815
12 files changed
+48 -44

No files matched your search

+1 -1
View File
@@ -220,7 +220,7 @@ test('Realtime sessions carry supplied tools, and the standalone voice adds the
);
assert.ok(names.includes('get_weather'));
assert.ok(names.includes('military_awareness'));
assert.ok(!names.includes('show_on_globe'));
assert.ok(!names.includes('show_in_gods_eye_view'));
assert.ok(!names.includes('aircraft_in_area'));
assert.ok(!names.includes('get_weather_map'));
// The action of the same name answers satellite passes.
+2 -2
View File
@@ -4,10 +4,10 @@ import { coreTools, toFunctionOutput, toFunctionTools } from './index.js';
test('catalog tools become independent function records', () => {
const records = toFunctionTools(coreTools, {
exclude: ['show_on_globe'],
exclude: ['show_in_gods_eye_view'],
});
assert.equal(records.length, coreTools.length - 1);
assert.ok(!records.some((tool) => tool.name === 'show_on_globe'));
assert.ok(!records.some((tool) => tool.name === 'show_in_gods_eye_view'));
const weather = records.find((tool) => tool.name === 'get_weather');
const source = coreTools.find((tool) => tool.name === 'get_weather');
assert.deepEqual(Object.keys(weather), [
+5 -5
View File
@@ -1,7 +1,7 @@
/**
* The globe panel: an MCP Apps view (`io.modelcontextprotocol/ui`) that shows
* The God's Eye View panel: an MCP Apps view (`io.modelcontextprotocol/ui`) that shows
* God's Eye View inside a conversation. The panel is a small page that loads
* the app in embed mode and sends it each view the show_on_globe tool
* the app in embed mode and sends it each view the show_in_gods_eye_view tool
* returns; see docs/TOOLS.md.
*/
@@ -33,7 +33,7 @@ function panelHtml(appOrigin) {
</style>
</head>
<body>
<div id="status">Waiting for a view of the globe…</div>
<div id="status">Waiting for a view…</div>
<button id="open" type="button" hidden>Open in God's Eye View</button>
<script>
(() => {
@@ -82,7 +82,7 @@ function panelHtml(appOrigin) {
frame.allow = 'fullscreen';
frame.src = embedUrl(url);
document.body.appendChild(frame);
status.textContent = 'Loading the globe…';
status.textContent = "Loading God's Eye View…";
return;
}
if (frameReady) postView(view);
@@ -148,7 +148,7 @@ export function createGlobePanelResource({ appUrl }) {
uri: GLOBE_PANEL_URI,
name: 'globe',
title: "God's Eye View globe",
description: 'The live globe, showing the view a tool returns.',
description: "Live God's Eye View, showing the view a tool returns.",
mimeType: MCP_APP_MIME_TYPE,
text: panelHtml(appOrigin),
_meta: {
+4 -4
View File
@@ -23,12 +23,12 @@ test('the globe panel is an MCP Apps resource that may frame only the app', () =
assert.match(resource.text, /protocolVersion: "2026-01-26"/);
});
test('show_on_globe names the panel and shows a view another answer returned', async () => {
test('show_in_gods_eye_view names the panel and shows a view another answer returned', async () => {
const catalog = composeCatalog({
tools: coreTools,
services: { app: { baseUrl: 'http://localhost:5173/' } },
});
assert.deepEqual(catalog.get('show_on_globe').ui, {
assert.deepEqual(catalog.get('show_in_gods_eye_view').ui, {
resourceUri: GLOBE_PANEL_URI,
});
const earlier = {
@@ -46,7 +46,7 @@ test('show_on_globe names the panel and shows a view another answer returned', a
annotations: [],
url: 'http://localhost:5173/#v=2',
};
const shown = await catalog.call('show_on_globe', {
const shown = await catalog.call('show_in_gods_eye_view', {
view: earlier,
layers: ['ais-live-vessels', 'military'],
style: 'thermal',
@@ -55,7 +55,7 @@ test('show_on_globe names the panel and shows a view another answer returned', a
assert.deepEqual(shown.data.view.layers, ['ais-live-vessels', 'military']);
assert.equal(shown.data.view.style, 'thermal');
await assert.rejects(
catalog.call('show_on_globe', { view: { camera: { lat: 'x' } } }),
catalog.call('show_in_gods_eye_view', { view: { camera: { lat: 'x' } } }),
(error) => error.code === 'invalid_arguments',
);
});
+2 -2
View File
@@ -40,7 +40,7 @@ import {
getTransitVehicles,
} from './queries/mobility.js';
import { placesNearby, planRoute, searchPlaces } from './queries/places.js';
import { showOnGlobe } from './queries/share.js';
import { showInGodsEyeView } from './queries/share.js';
import { findAlprCameras } from './queries/surveillance.js';
import {
findCctvCameras,
@@ -121,5 +121,5 @@ export const coreTools = Object.freeze([
situationBrief,
militaryAwareness,
getHudCaption,
showOnGlobe,
showInGodsEyeView,
]);
+9 -9
View File
@@ -77,16 +77,16 @@ function appBase(services) {
}
}
export const showOnGlobe = defineTool({
name: 'show_on_globe',
title: 'Show on the globe',
export const showInGodsEyeView = defineTool({
name: 'show_in_gods_eye_view',
title: "Show in God's Eye View",
description:
"Shows a view of God's Eye View's globe: in clients that display apps, " +
'the live globe in the conversation; everywhere, a link that opens it. ' +
'Pass the view another answer returned, or describe one: an area framed from above ' +
'or a camera position, with chosen data layers, visual style and map, ' +
'optionally following an aircraft or satellite and with marks drawn on ' +
'the globe.',
"Shows a view in God's Eye View: in clients that display apps, the live " +
"God's Eye View globe in the conversation; everywhere, a link that opens " +
'it. Pass the view another answer returned, or describe one: an area ' +
'framed from above or a camera position, with chosen data layers, visual ' +
'style and map, optionally following an aircraft or satellite and with ' +
'marks drawn on the map.',
inputSchema: {
type: 'object',
properties: VIEW_ARGUMENTS,
+9 -9
View File
@@ -7,7 +7,7 @@ test('links open the app looking straight down on the area', async () => {
tools: coreTools,
services: { app: { baseUrl: 'https://maps.example/view?x=1' } },
});
const result = await catalog.call('show_on_globe', {
const result = await catalog.call('show_in_gods_eye_view', {
area: { lat: 30.2672, lon: -97.7431, radius_km: 5 },
});
const url = new URL(result.data.url);
@@ -35,11 +35,11 @@ test('altitude is bounded for tiny and planet-sized areas', async () => {
tools: coreTools,
services: { app: { baseUrl: 'http://localhost:4173/' } },
});
const tiny = await catalog.call('show_on_globe', {
const tiny = await catalog.call('show_in_gods_eye_view', {
area: { lat: 0, lon: 0, radius_km: 0.1 },
});
assert.equal(tiny.data.view.camera.altitude_m, 500);
const world = await catalog.call('show_on_globe', {
const world = await catalog.call('show_in_gods_eye_view', {
area: { bbox: [-180, -85, 180, 85] },
});
assert.equal(world.data.view.camera.altitude_m, 15000000);
@@ -48,7 +48,7 @@ test('altitude is bounded for tiny and planet-sized areas', async () => {
services: { app: { baseUrl: 'not a url' } },
});
await assert.rejects(
broken.call('show_on_globe', {
broken.call('show_in_gods_eye_view', {
area: { lat: 0, lon: 0, radius_km: 1 },
}),
(error) => error.code === 'unavailable',
@@ -61,7 +61,7 @@ test('links turn on the requested layers with the app share-link codec', async (
tools: coreTools,
services: { app: { baseUrl: 'http://localhost:4173/' } },
});
const result = await catalog.call('show_on_globe', {
const result = await catalog.call('show_in_gods_eye_view', {
area: { lat: 30.27, lon: -97.74, radius_km: 10 },
layers: ['earthquakes', 'flights', 'flights'],
});
@@ -72,7 +72,7 @@ test('links turn on the requested layers with the app share-link codec', async (
'flights',
]);
await assert.rejects(
catalog.call('show_on_globe', {
catalog.call('show_in_gods_eye_view', {
area: { lat: 0, lon: 0, radius_km: 1 },
layers: ['not-a-layer'],
}),
@@ -86,7 +86,7 @@ test('links carry a camera, style, map and an entity to follow', async () => {
tools: coreTools,
services: { app: { baseUrl: 'http://localhost:4173/' } },
});
const result = await catalog.call('show_on_globe', {
const result = await catalog.call('show_in_gods_eye_view', {
area: { lat: 25, lon: 121, radius_km: 200 },
camera: { pitch_deg: -40, heading_deg: 350 },
layers: ['ais-live-vessels'],
@@ -103,13 +103,13 @@ test('links carry a camera, style, map and an entity to follow', async () => {
id: 'ae1234',
});
assert.equal(result.data.view.camera.pitch_deg, -40);
const camera = await catalog.call('show_on_globe', {
const camera = await catalog.call('show_in_gods_eye_view', {
camera: { lat: 48.8584, lon: 2.2945, altitude_m: 1200, pitch_deg: -30 },
});
assert.equal(camera.data.view.camera.altitude_m, 1200);
assert.match(camera.summary, /^Open 48\.858, 2\.295 in God's Eye View: /);
await assert.rejects(
catalog.call('show_on_globe', { layers: ['flights'] }),
catalog.call('show_in_gods_eye_view', { layers: ['flights'] }),
/Give a view, an area, or a camera with lat and lon/,
);
});
+1 -1
View File
@@ -15,7 +15,7 @@ const mcpOff = Object.freeze({ mcp: false });
export const TOOL_SURFACES = Object.freeze({
// Voice runs inside the app, so a link to it adds nothing.
show_on_globe: voiceOff,
show_in_gods_eye_view: voiceOff,
// Voice has an app action of the same name.
next_satellite_pass: voiceOff,
// Voice receives text only, so tools that answer with an image are off.
+5 -1
View File
@@ -20,7 +20,11 @@ test('each surface offers the tools the table does not turn off', () => {
assert.deepEqual(offered, expected, surface);
}
const mcp = names(toolsForSurface(coreTools, 'mcp'));
for (const name of ['show_on_globe', 'situation_brief', 'aircraft_in_area'])
for (const name of [
'show_in_gods_eye_view',
'situation_brief',
'aircraft_in_area',
])
assert.ok(mcp.includes(name), name);
for (const name of [
'search_places',