mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
refactor: share the default tool services between surfaces
Move the composition of the default tool services from the Node MCP server into gods-eye-view/tools/services, a portable export. Given a fetch that resolves the sources' /api paths, it builds the same services in a browser as on the local MCP server, so other surfaces can compose the same catalog. Queries still read only their services.
This commit is contained in:
1 parent
0dbd6375fc
commit
a8b5860e9f
6 files changed
+141
-65
No files matched your search
+3
-1
@@ -11,6 +11,7 @@ They are defined once and exposed through adapters; the Model Context Protocol
|
|||||||
| `src/tools/` | Tool definitions, catalog composition, argument validation, shared `area` and result helpers |
|
| `src/tools/` | Tool definitions, catalog composition, argument validation, shared `area` and result helpers |
|
||||||
| `src/tools/queries/` | Queries, one file per domain, reading only portable source contracts |
|
| `src/tools/queries/` | Queries, one file per domain, reading only portable source contracts |
|
||||||
| `src/tools/mcp/` | MCP protocol (JSON-RPC) and a stateless HTTP transport; knows the catalog interface, not queries |
|
| `src/tools/mcp/` | MCP protocol (JSON-RPC) and a stateless HTTP transport; knows the catalog interface, not queries |
|
||||||
|
| `src/tools/services.js` | The default services: the layers' source factories and request services, given a resolving fetch |
|
||||||
| `server/mcp/` | Node composition: points the sources at a running app's `/api` routes; serves stdio and `/mcp` |
|
| `server/mcp/` | Node composition: points the sources at a running app's `/api` routes; serves stdio and `/mcp` |
|
||||||
|
|
||||||
Dependencies point downward only. `gods-eye-view/tools` and
|
Dependencies point downward only. `gods-eye-view/tools` and
|
||||||
@@ -44,7 +45,8 @@ reported to clients without details.
|
|||||||
|
|
||||||
## Services
|
## Services
|
||||||
|
|
||||||
Services are the portable source factories the layers already use, such as
|
`gods-eye-view/tools/services` builds the default set with
|
||||||
|
`createToolServices({ fetchImpl, appUrl })`. Services are the portable source factories the layers already use, such as
|
||||||
`createUsgsEarthquakeSource`, `createFirmsSource` and `createLaunchSource`,
|
`createUsgsEarthquakeSource`, `createFirmsSource` and `createLaunchSource`,
|
||||||
plus a `places` service with `resolve(name, { signal })`. Sources request
|
plus a `places` service with `resolve(name, { signal })`. Sources request
|
||||||
relative `/api/...` paths through an injected `fetchImpl`, so the same tool
|
relative `/api/...` paths through an injected `fetchImpl`, so the same tool
|
||||||
|
|||||||
+2
-1
@@ -253,6 +253,7 @@
|
|||||||
"./sources/transit-service": "./src/sources/transitService.js",
|
"./sources/transit-service": "./src/sources/transitService.js",
|
||||||
"./sources/map-features": "./src/sources/overpassFeatures.js",
|
"./sources/map-features": "./src/sources/overpassFeatures.js",
|
||||||
"./tools": "./src/tools/index.js",
|
"./tools": "./src/tools/index.js",
|
||||||
"./tools/mcp": "./src/tools/mcp/index.js"
|
"./tools/mcp": "./src/tools/mcp/index.js",
|
||||||
|
"./tools/services": "./src/tools/services.js"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -39,6 +39,7 @@ const portableExport = (key) =>
|
|||||||
'./director',
|
'./director',
|
||||||
'./tools',
|
'./tools',
|
||||||
'./tools/mcp',
|
'./tools/mcp',
|
||||||
|
'./tools/services',
|
||||||
'./voice/action-schemas',
|
'./voice/action-schemas',
|
||||||
'./voice/session',
|
'./voice/session',
|
||||||
'./data/lifecycle',
|
'./data/lifecycle',
|
||||||
|
|||||||
@@ -3114,5 +3114,59 @@
|
|||||||
"src/tools/schema.js"
|
"src/tools/schema.js"
|
||||||
],
|
],
|
||||||
"external": []
|
"external": []
|
||||||
|
},
|
||||||
|
"tools-services": {
|
||||||
|
"exports": ["./tools/services"],
|
||||||
|
"modules": [
|
||||||
|
"src/tools/services.js",
|
||||||
|
"src/layers/bikeshare/registry.js",
|
||||||
|
"src/layers/bikeshare/source.js",
|
||||||
|
"src/layers/cctv/source.js",
|
||||||
|
"src/layers/cctv/sourcePolicy.js",
|
||||||
|
"src/layers/cyclones/source.js",
|
||||||
|
"src/sources/httpBody.js",
|
||||||
|
"src/layers/earthquakes/source.js",
|
||||||
|
"src/layers/earthquakes/records.js",
|
||||||
|
"src/layers/firms/source.js",
|
||||||
|
"src/layers/installations/source.js",
|
||||||
|
"src/sources/requestDeadline.js",
|
||||||
|
"src/data/militaryNames.js",
|
||||||
|
"src/sources/militaryTileGeometry.js",
|
||||||
|
"src/data/bundledJson.js",
|
||||||
|
"src/data/retryableLoad.js",
|
||||||
|
"src/data/local_data/osm_military_names/names.json",
|
||||||
|
"src/sources/openFreeMap.js",
|
||||||
|
"src/sources/vectorTiles.js",
|
||||||
|
"src/sources/phaseTiming.js",
|
||||||
|
"src/data/tomtomTiles.js",
|
||||||
|
"src/sources/capability.js",
|
||||||
|
"src/data/militaryInstallationData.js",
|
||||||
|
"src/layers/launches/source.js",
|
||||||
|
"src/layers/perimeters/source.js",
|
||||||
|
"src/layers/radio/source.js",
|
||||||
|
"src/layers/radio/policy.js",
|
||||||
|
"src/layers/satellites/source.js",
|
||||||
|
"src/layers/traffic/source.js",
|
||||||
|
"src/layers/traffic/roadModes.js",
|
||||||
|
"src/data/flowMatch.js",
|
||||||
|
"src/layers/traffic/flowSource.js",
|
||||||
|
"src/layers/traffic/flowDecode.js",
|
||||||
|
"src/sources/overpassRoads.js",
|
||||||
|
"src/layers/transit/source.js",
|
||||||
|
"src/sources/transitHistory.js",
|
||||||
|
"src/services/requests.js",
|
||||||
|
"src/sources/overpassFeatures.js",
|
||||||
|
"src/sources/featureSource.js",
|
||||||
|
"src/sources/overpassFeaturesRecords.js",
|
||||||
|
"src/sources/featureGeometry.js",
|
||||||
|
"src/sources/live/standalone.js",
|
||||||
|
"src/sources/live/contract.js",
|
||||||
|
"src/sources/live/aircraft.js",
|
||||||
|
"src/sources/live/vessels.js",
|
||||||
|
"src/tools/places.js",
|
||||||
|
"src/tools/catalog.js",
|
||||||
|
"src/tools/schema.js"
|
||||||
|
],
|
||||||
|
"external": ["@mapbox/vector-tile", "pbf"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
-63
@@ -1,32 +1,9 @@
|
|||||||
/**
|
/**
|
||||||
* Local composition of tool services: the portable source factories, pointed
|
* Local composition of tool services: Core's default services, pointed at a
|
||||||
* at a running God's Eye View server's `/api` routes.
|
* running God's Eye View server's `/api` routes.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { GBFS_CITY_REGISTRY } from '../../src/layers/bikeshare/registry.js';
|
import { createToolServices } from '../../src/tools/services.js';
|
||||||
import { createBikeshareSource } from '../../src/layers/bikeshare/source.js';
|
|
||||||
import { createCctvSource } from '../../src/layers/cctv/source.js';
|
|
||||||
import { createCycloneSource } from '../../src/layers/cyclones/source.js';
|
|
||||||
import { createUsgsEarthquakeSource } from '../../src/layers/earthquakes/source.js';
|
|
||||||
import { createFirmsSource } from '../../src/layers/firms/source.js';
|
|
||||||
import { createInstallationSource } from '../../src/layers/installations/source.js';
|
|
||||||
import { createLaunchSource } from '../../src/layers/launches/source.js';
|
|
||||||
import { createWfigsPerimeterSource } from '../../src/layers/perimeters/source.js';
|
|
||||||
import { createRadioSource } from '../../src/layers/radio/source.js';
|
|
||||||
import { createSatelliteSource } from '../../src/layers/satellites/source.js';
|
|
||||||
import { createTrafficSource } from '../../src/layers/traffic/source.js';
|
|
||||||
import { createTransitSource } from '../../src/layers/transit/source.js';
|
|
||||||
import { createApplicationRequestServices } from '../../src/services/requests.js';
|
|
||||||
import {
|
|
||||||
createAdsbLolSource,
|
|
||||||
createAisStreamSource,
|
|
||||||
createOpenSkySource,
|
|
||||||
} from '../../src/sources/live/standalone.js';
|
|
||||||
import {
|
|
||||||
createGeocodePlaceService,
|
|
||||||
createPlaceSearchService,
|
|
||||||
createRouteService,
|
|
||||||
} from '../../src/tools/places.js';
|
|
||||||
|
|
||||||
export const DEFAULT_API_BASE = 'http://localhost:4173';
|
export const DEFAULT_API_BASE = 'http://localhost:4173';
|
||||||
|
|
||||||
@@ -49,41 +26,8 @@ export function createApiFetch({
|
|||||||
|
|
||||||
/** Construct every service Core's tools read, backed by the local server. */
|
/** Construct every service Core's tools read, backed by the local server. */
|
||||||
export function createLocalToolServices(options = {}) {
|
export function createLocalToolServices(options = {}) {
|
||||||
const fetchImpl = createApiFetch(options);
|
return createToolServices({
|
||||||
const requests = createApplicationRequestServices({ fetchImpl });
|
fetchImpl: createApiFetch(options),
|
||||||
return {
|
appUrl: options.apiBase ?? DEFAULT_API_BASE,
|
||||||
app: { baseUrl: options.apiBase ?? DEFAULT_API_BASE },
|
});
|
||||||
earthquakes: createUsgsEarthquakeSource({ fetchImpl }),
|
|
||||||
fires: createFirmsSource({ fetchImpl }),
|
|
||||||
launches: createLaunchSource({ fetchImpl }),
|
|
||||||
aircraft: createOpenSkySource({ fetchImpl }),
|
|
||||||
military: createAdsbLolSource({ fetchImpl }),
|
|
||||||
vessels: createAisStreamSource({
|
|
||||||
fetchImpl,
|
|
||||||
origin: () => new URL(options.apiBase ?? DEFAULT_API_BASE).origin,
|
|
||||||
}),
|
|
||||||
satellites: createSatelliteSource({ fetchImpl }),
|
|
||||||
cctv: createCctvSource({ fetchImpl }),
|
|
||||||
radio: createRadioSource({ fetchImpl }),
|
|
||||||
placeSearch: createPlaceSearchService({ fetchImpl }),
|
|
||||||
routing: createRouteService({ fetchImpl }),
|
|
||||||
bikeshare: {
|
|
||||||
systems: GBFS_CITY_REGISTRY,
|
|
||||||
getStations: createBikeshareSource({ fetchImpl }).getStations,
|
|
||||||
},
|
|
||||||
transit: createTransitSource({ fetchImpl }),
|
|
||||||
traffic: createTrafficSource({ fetchImpl, tileFetchImpl: fetchImpl }),
|
|
||||||
weather: requests.weather,
|
|
||||||
regional: requests.regional,
|
|
||||||
terrain: requests.terrain,
|
|
||||||
summary: requests.summary,
|
|
||||||
features: requests.features,
|
|
||||||
cyclones: createCycloneSource({ fetchImpl }),
|
|
||||||
perimeters: createWfigsPerimeterSource({ fetchImpl }),
|
|
||||||
installations: createInstallationSource({
|
|
||||||
fetchImpl,
|
|
||||||
tileFetchImpl: fetchImpl,
|
|
||||||
}),
|
|
||||||
places: createGeocodePlaceService({ fetchImpl }),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
/**
|
||||||
|
* The default services Core's tools read: the layers' portable source
|
||||||
|
* factories and the application request services. `fetchImpl` must resolve
|
||||||
|
* the sources' relative `/api/...` paths; in a browser the page's own fetch
|
||||||
|
* does, and elsewhere a caller supplies a resolving fetch. `appUrl` is the
|
||||||
|
* address the app is served from.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { GBFS_CITY_REGISTRY } from '../layers/bikeshare/registry.js';
|
||||||
|
import { createBikeshareSource } from '../layers/bikeshare/source.js';
|
||||||
|
import { createCctvSource } from '../layers/cctv/source.js';
|
||||||
|
import { createCycloneSource } from '../layers/cyclones/source.js';
|
||||||
|
import { createUsgsEarthquakeSource } from '../layers/earthquakes/source.js';
|
||||||
|
import { createFirmsSource } from '../layers/firms/source.js';
|
||||||
|
import { createInstallationSource } from '../layers/installations/source.js';
|
||||||
|
import { createLaunchSource } from '../layers/launches/source.js';
|
||||||
|
import { createWfigsPerimeterSource } from '../layers/perimeters/source.js';
|
||||||
|
import { createRadioSource } from '../layers/radio/source.js';
|
||||||
|
import { createSatelliteSource } from '../layers/satellites/source.js';
|
||||||
|
import { createTrafficSource } from '../layers/traffic/source.js';
|
||||||
|
import { createTransitSource } from '../layers/transit/source.js';
|
||||||
|
import { createApplicationRequestServices } from '../services/requests.js';
|
||||||
|
import {
|
||||||
|
createAdsbLolSource,
|
||||||
|
createAisStreamSource,
|
||||||
|
createOpenSkySource,
|
||||||
|
} from '../sources/live/standalone.js';
|
||||||
|
import {
|
||||||
|
createGeocodePlaceService,
|
||||||
|
createPlaceSearchService,
|
||||||
|
createRouteService,
|
||||||
|
} from './places.js';
|
||||||
|
|
||||||
|
/** Construct every service Core's tools read. */
|
||||||
|
export function createToolServices({ fetchImpl, appUrl }) {
|
||||||
|
if (typeof fetchImpl !== 'function')
|
||||||
|
throw new TypeError('A fetch implementation is required');
|
||||||
|
const requests = createApplicationRequestServices({ fetchImpl });
|
||||||
|
return {
|
||||||
|
app: { baseUrl: appUrl },
|
||||||
|
earthquakes: createUsgsEarthquakeSource({ fetchImpl }),
|
||||||
|
fires: createFirmsSource({ fetchImpl }),
|
||||||
|
launches: createLaunchSource({ fetchImpl }),
|
||||||
|
aircraft: createOpenSkySource({ fetchImpl }),
|
||||||
|
military: createAdsbLolSource({ fetchImpl }),
|
||||||
|
vessels: createAisStreamSource({
|
||||||
|
fetchImpl,
|
||||||
|
origin: () => new URL(appUrl).origin,
|
||||||
|
}),
|
||||||
|
satellites: createSatelliteSource({ fetchImpl }),
|
||||||
|
cctv: createCctvSource({ fetchImpl }),
|
||||||
|
radio: createRadioSource({ fetchImpl }),
|
||||||
|
placeSearch: createPlaceSearchService({ fetchImpl }),
|
||||||
|
routing: createRouteService({ fetchImpl }),
|
||||||
|
bikeshare: {
|
||||||
|
systems: GBFS_CITY_REGISTRY,
|
||||||
|
getStations: createBikeshareSource({ fetchImpl }).getStations,
|
||||||
|
},
|
||||||
|
transit: createTransitSource({ fetchImpl }),
|
||||||
|
traffic: createTrafficSource({ fetchImpl, tileFetchImpl: fetchImpl }),
|
||||||
|
weather: requests.weather,
|
||||||
|
regional: requests.regional,
|
||||||
|
terrain: requests.terrain,
|
||||||
|
summary: requests.summary,
|
||||||
|
features: requests.features,
|
||||||
|
cyclones: createCycloneSource({ fetchImpl }),
|
||||||
|
perimeters: createWfigsPerimeterSource({ fetchImpl }),
|
||||||
|
installations: createInstallationSource({
|
||||||
|
fetchImpl,
|
||||||
|
tileFetchImpl: fetchImpl,
|
||||||
|
}),
|
||||||
|
places: createGeocodePlaceService({ fetchImpl }),
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in new issue
Block a user