gtfs-one-mcp 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +15 -0
- package/README.md +190 -0
- package/dist/api-client.d.ts +38 -0
- package/dist/api-client.js +133 -0
- package/dist/api-client.js.map +1 -0
- package/dist/config.d.ts +24 -0
- package/dist/config.js +56 -0
- package/dist/config.js.map +1 -0
- package/dist/http.d.ts +17 -0
- package/dist/http.js +121 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +15 -0
- package/dist/server.js +27 -0
- package/dist/server.js.map +1 -0
- package/dist/tools.d.ts +9 -0
- package/dist/tools.js +431 -0
- package/dist/tools.js.map +1 -0
- package/dist/types.d.ts +229 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -0
- package/gtfs-one.config.example.json +7 -0
- package/package.json +58 -0
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared MCP server factory. Both transports — stdio (`index.ts`) and
|
|
3
|
+
* Streamable HTTP (`http.ts`) — build their server through here, so the two
|
|
4
|
+
* surfaces expose the identical 9 tools and instructions.
|
|
5
|
+
*/
|
|
6
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
7
|
+
import type { Config } from "./config.js";
|
|
8
|
+
import { ApiClient } from "./api-client.js";
|
|
9
|
+
/** The server-level instructions shown to the AI client. */
|
|
10
|
+
export declare function buildInstructions(config: Config): string;
|
|
11
|
+
/**
|
|
12
|
+
* Create a fully-wired McpServer. Pass a shared ApiClient so multiple HTTP
|
|
13
|
+
* sessions reuse one response cache; omit it for a standalone (stdio) process.
|
|
14
|
+
*/
|
|
15
|
+
export declare function createServer(config: Config, api?: ApiClient): McpServer;
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared MCP server factory. Both transports — stdio (`index.ts`) and
|
|
3
|
+
* Streamable HTTP (`http.ts`) — build their server through here, so the two
|
|
4
|
+
* surfaces expose the identical 9 tools and instructions.
|
|
5
|
+
*/
|
|
6
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
7
|
+
import { ApiClient } from "./api-client.js";
|
|
8
|
+
import { registerTools } from "./tools.js";
|
|
9
|
+
/** The server-level instructions shown to the AI client. */
|
|
10
|
+
export function buildInstructions(config) {
|
|
11
|
+
return (`This server provides real-time transit information for ${config.agencyName}.` +
|
|
12
|
+
(config.agencyDescription ? ` ${config.agencyDescription}` : "") +
|
|
13
|
+
` Use the tools to look up bus stops, schedules, routes, live vehicle positions, ` +
|
|
14
|
+
`and service alerts. Always use the tools for schedule and stop data — never guess ` +
|
|
15
|
+
`times. Note: realtime tools (get_service_alerts, get_live_vehicles) returning an ` +
|
|
16
|
+
`empty result is normal and means "nothing active right now," not "no service."`);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Create a fully-wired McpServer. Pass a shared ApiClient so multiple HTTP
|
|
20
|
+
* sessions reuse one response cache; omit it for a standalone (stdio) process.
|
|
21
|
+
*/
|
|
22
|
+
export function createServer(config, api = new ApiClient(config)) {
|
|
23
|
+
const server = new McpServer({ name: "gtfs-one-transit", version: "1.0.0" }, { instructions: buildInstructions(config) });
|
|
24
|
+
registerTools(server, api);
|
|
25
|
+
return server;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,4DAA4D;AAC5D,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,OAAO,CACL,0DAA0D,MAAM,CAAC,UAAU,GAAG;QAC9E,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,kFAAkF;QAClF,oFAAoF;QACpF,mFAAmF;QACnF,gFAAgF,CACjF,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,MAAiB,IAAI,SAAS,CAAC,MAAM,CAAC;IACjF,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,OAAO,EAAE,EAC9C,EAAE,YAAY,EAAE,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAC5C,CAAC;IACF,aAAa,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/tools.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The nine GTFS One MCP tools. Each wraps one REST endpoint, formats the result
|
|
3
|
+
* as readable text (IDs included so the AI can chain calls), and surfaces failures
|
|
4
|
+
* as prose. Tool descriptions are written for the *model* — they spell out when an
|
|
5
|
+
* empty result is normal so the AI never reads "no alerts" as "no service."
|
|
6
|
+
*/
|
|
7
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
8
|
+
import { ApiClient } from "./api-client.js";
|
|
9
|
+
export declare function registerTools(server: McpServer, api: ApiClient): void;
|
package/dist/tools.js
ADDED
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The nine GTFS One MCP tools. Each wraps one REST endpoint, formats the result
|
|
3
|
+
* as readable text (IDs included so the AI can chain calls), and surfaces failures
|
|
4
|
+
* as prose. Tool descriptions are written for the *model* — they spell out when an
|
|
5
|
+
* empty result is normal so the AI never reads "no alerts" as "no service."
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import { GtfsApiError } from "./api-client.js";
|
|
9
|
+
/* ----------------------------- GTFS-RT enum maps ----------------------------- */
|
|
10
|
+
// https://gtfs.org/realtime/reference/ — surface human labels, never raw integers.
|
|
11
|
+
const CAUSE = {
|
|
12
|
+
1: "Unknown cause", 2: "Other cause", 3: "Technical problem", 4: "Strike",
|
|
13
|
+
5: "Demonstration", 6: "Accident", 7: "Holiday", 8: "Weather",
|
|
14
|
+
9: "Maintenance", 10: "Construction", 11: "Police activity", 12: "Medical emergency",
|
|
15
|
+
};
|
|
16
|
+
const EFFECT = {
|
|
17
|
+
1: "No service", 2: "Reduced service", 3: "Significant delays", 4: "Detour",
|
|
18
|
+
5: "Additional service", 6: "Modified service", 7: "Other effect",
|
|
19
|
+
8: "Unknown effect", 9: "Stop moved", 10: "No effect", 11: "Accessibility issue",
|
|
20
|
+
};
|
|
21
|
+
const SEVERITY = {
|
|
22
|
+
1: "Unknown severity", 2: "Info", 3: "Warning", 4: "Severe",
|
|
23
|
+
};
|
|
24
|
+
/* --------------------------------- helpers ---------------------------------- */
|
|
25
|
+
const text = (s) => ({ content: [{ type: "text", text: s }] });
|
|
26
|
+
const errText = (s) => ({
|
|
27
|
+
content: [{ type: "text", text: s }],
|
|
28
|
+
isError: true,
|
|
29
|
+
});
|
|
30
|
+
/** Run a tool body, converting GtfsApiError into a visible (isError) tool result. */
|
|
31
|
+
async function guard(run) {
|
|
32
|
+
try {
|
|
33
|
+
return await run();
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
if (err instanceof GtfsApiError)
|
|
37
|
+
return errText(err.message);
|
|
38
|
+
return errText(`Something went wrong reaching the transit data service: ${err.message}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const fmtCoord = (n) => n.toFixed(5);
|
|
42
|
+
/* --------------------------------- tools ------------------------------------ */
|
|
43
|
+
export function registerTools(server, api) {
|
|
44
|
+
const feedArg = {
|
|
45
|
+
feed_id: z
|
|
46
|
+
.string()
|
|
47
|
+
.optional()
|
|
48
|
+
.describe(`Feed identifier for multi-agency sites. Defaults to "${api.defaultFeedId}". ` +
|
|
49
|
+
`Call list_feeds first if unsure which feeds exist.`),
|
|
50
|
+
};
|
|
51
|
+
const feed = (id) => id || api.defaultFeedId;
|
|
52
|
+
/* 1. list_feeds */
|
|
53
|
+
server.registerTool("list_feeds", {
|
|
54
|
+
title: "List transit feeds",
|
|
55
|
+
description: "List all transit feeds (agencies) configured on this GTFS One site. Most " +
|
|
56
|
+
"sites have a single feed. Use this to discover feed_id values when a site " +
|
|
57
|
+
"serves more than one agency.",
|
|
58
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
59
|
+
inputSchema: {},
|
|
60
|
+
}, () => guard(async () => {
|
|
61
|
+
const feeds = await api.get("/feeds");
|
|
62
|
+
if (!feeds.length)
|
|
63
|
+
return text("No transit feeds are configured on this site.");
|
|
64
|
+
const lines = feeds.map((f) => `• ${f.name} — feed_id: "${f.id}"${f.active ? "" : " (inactive)"}` +
|
|
65
|
+
(f.url ? `\n GTFS source: ${f.url}` : ""));
|
|
66
|
+
return text(`Configured transit feeds:\n${lines.join("\n")}`);
|
|
67
|
+
}));
|
|
68
|
+
/* 2. find_nearby_stops */
|
|
69
|
+
server.registerTool("find_nearby_stops", {
|
|
70
|
+
title: "Find nearby stops",
|
|
71
|
+
description: "Find the nearest transit stops to a latitude/longitude. Returns each stop " +
|
|
72
|
+
"with its distance, the routes that serve it, and the next scheduled " +
|
|
73
|
+
"departure times per route. If you only have an address or place name, call " +
|
|
74
|
+
"geocode_address first to get coordinates.",
|
|
75
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
76
|
+
inputSchema: {
|
|
77
|
+
latitude: z.number().min(-90).max(90).describe("Latitude (-90 to 90)."),
|
|
78
|
+
longitude: z.number().min(-180).max(180).describe("Longitude (-180 to 180)."),
|
|
79
|
+
radius_meters: z
|
|
80
|
+
.number()
|
|
81
|
+
.int()
|
|
82
|
+
.positive()
|
|
83
|
+
.max(5000)
|
|
84
|
+
.optional()
|
|
85
|
+
.describe("Search radius in meters (default 800, max 5000)."),
|
|
86
|
+
limit: z
|
|
87
|
+
.number()
|
|
88
|
+
.int()
|
|
89
|
+
.positive()
|
|
90
|
+
.max(10)
|
|
91
|
+
.optional()
|
|
92
|
+
.describe("Max stops to return (default 5, max 10)."),
|
|
93
|
+
...feedArg,
|
|
94
|
+
},
|
|
95
|
+
}, (args) => guard(async () => {
|
|
96
|
+
const data = await api.get("/stops/nearby", {
|
|
97
|
+
lat: args.latitude,
|
|
98
|
+
lon: args.longitude,
|
|
99
|
+
radius: args.radius_meters ?? 800,
|
|
100
|
+
limit: args.limit ?? 5,
|
|
101
|
+
feed_id: feed(args.feed_id),
|
|
102
|
+
});
|
|
103
|
+
if (!data.stops?.length) {
|
|
104
|
+
return text("No transit stops were found within the search radius. Try a larger " +
|
|
105
|
+
"radius_meters, or confirm the coordinates are inside the agency's service area.");
|
|
106
|
+
}
|
|
107
|
+
const blocks = data.stops.map((s) => {
|
|
108
|
+
const head = `${s.name} (stop_id: ${s.id}${s.code ? `, code ${s.code}` : ""}) — ${s.distance_text}`;
|
|
109
|
+
const routes = s.routes.length
|
|
110
|
+
? s.routes
|
|
111
|
+
.map((r) => {
|
|
112
|
+
const next = r.next.length ? r.next.join(", ") : "no upcoming scheduled departures";
|
|
113
|
+
return ` - Route ${r.name} (route_id: ${r.route_id}): ${next}`;
|
|
114
|
+
})
|
|
115
|
+
.join("\n")
|
|
116
|
+
: " - No routes currently scheduled here.";
|
|
117
|
+
return `${head}\n${routes}`;
|
|
118
|
+
});
|
|
119
|
+
return text(`Nearest stops:\n${blocks.join("\n")}`);
|
|
120
|
+
}));
|
|
121
|
+
/* 3. search_stops */
|
|
122
|
+
server.registerTool("search_stops", {
|
|
123
|
+
title: "Search stops by name",
|
|
124
|
+
description: "Search for transit stops by name, landmark, or stop code. Use this when the " +
|
|
125
|
+
"rider names a place (\"Big Bear Village\", \"Goodwin's Market\") rather than " +
|
|
126
|
+
"giving coordinates. Returns matching stops with their stop_id, which you can " +
|
|
127
|
+
"pass to get_stop_departures.",
|
|
128
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
129
|
+
inputSchema: {
|
|
130
|
+
query: z.string().min(2).describe("Stop name, landmark, or stop code (min 2 chars)."),
|
|
131
|
+
limit: z.number().int().positive().max(12).optional().describe("Max results (default 6, max 12)."),
|
|
132
|
+
...feedArg,
|
|
133
|
+
},
|
|
134
|
+
}, (args) => guard(async () => {
|
|
135
|
+
const data = await api.get("/stops/search", {
|
|
136
|
+
q: args.query,
|
|
137
|
+
limit: args.limit ?? 6,
|
|
138
|
+
feed_id: feed(args.feed_id),
|
|
139
|
+
});
|
|
140
|
+
if (!data.stops?.length) {
|
|
141
|
+
return text(`No stops matched "${args.query}". Try a shorter or different term, or use ` +
|
|
142
|
+
`find_nearby_stops with coordinates from geocode_address.`);
|
|
143
|
+
}
|
|
144
|
+
const lines = data.stops.map((s) => `• ${s.label || s.name} — stop_id: ${s.id}` +
|
|
145
|
+
`, location: ${fmtCoord(s.lat)}, ${fmtCoord(s.lon)}`);
|
|
146
|
+
return text(`Matching stops:\n${lines.join("\n")}`);
|
|
147
|
+
}));
|
|
148
|
+
/* 4. get_stop_departures */
|
|
149
|
+
server.registerTool("get_stop_departures", {
|
|
150
|
+
title: "Get stop departures",
|
|
151
|
+
description: "Get the next departures from a specific stop, merged across all routes that " +
|
|
152
|
+
"serve it. Use after finding a stop via find_nearby_stops or search_stops. " +
|
|
153
|
+
"Times are in the agency's local timezone; 'minutes' is minutes from now.",
|
|
154
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
155
|
+
inputSchema: {
|
|
156
|
+
stop_id: z.string().min(1).describe("GTFS stop_id (from a stop search/nearby result)."),
|
|
157
|
+
limit: z.number().int().positive().max(20).optional().describe("Max departures (default 8, max 20)."),
|
|
158
|
+
...feedArg,
|
|
159
|
+
},
|
|
160
|
+
}, (args) => guard(async () => {
|
|
161
|
+
const data = await api.get("/stops/departures", {
|
|
162
|
+
stop_id: args.stop_id,
|
|
163
|
+
limit: args.limit ?? 8,
|
|
164
|
+
feed_id: feed(args.feed_id),
|
|
165
|
+
});
|
|
166
|
+
const stopName = data.stop?.name || `stop ${args.stop_id}`;
|
|
167
|
+
if (!data.departures?.length) {
|
|
168
|
+
return text(`No upcoming departures are scheduled from ${stopName} right now. There may ` +
|
|
169
|
+
`be no more service today — suggest checking the agency website for the full schedule.`);
|
|
170
|
+
}
|
|
171
|
+
const lines = data.departures.map((d) => `• ${d.time} (in ${d.minutes} min) — Route ${d.name}` +
|
|
172
|
+
`${d.headsign ? ` toward ${d.headsign}` : ""} (route_id: ${d.route_id})`);
|
|
173
|
+
return text(`Next departures from ${stopName}:\n${lines.join("\n")}`);
|
|
174
|
+
}));
|
|
175
|
+
/* 5. get_route_map */
|
|
176
|
+
server.registerTool("get_route_map", {
|
|
177
|
+
title: "Get route map data",
|
|
178
|
+
description: "Get geographic data for a single route: its shape (an ordered list of " +
|
|
179
|
+
"lat/lon points forming the path) and the stops it serves. Useful for " +
|
|
180
|
+
"describing where a route goes. The shape can be long; the summary reports " +
|
|
181
|
+
"its size and lists the stops.",
|
|
182
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
183
|
+
inputSchema: {
|
|
184
|
+
route_id: z.string().min(1).describe("GTFS route_id."),
|
|
185
|
+
...feedArg,
|
|
186
|
+
},
|
|
187
|
+
}, (args) => guard(async () => {
|
|
188
|
+
const data = await api.get(`/map/route/${encodeURIComponent(args.route_id)}`, { feed_id: feed(args.feed_id) });
|
|
189
|
+
const stops = data.stops || [];
|
|
190
|
+
if (!stops.length && !(data.shapes || []).length) {
|
|
191
|
+
return text(`No map data was found for route_id "${args.route_id}".`);
|
|
192
|
+
}
|
|
193
|
+
const stopLines = stops.map((s) => ` - ${s.name} (stop_id: ${s.id}) at ${fmtCoord(s.lat)}, ${fmtCoord(s.lon)}`);
|
|
194
|
+
return text(`Route ${args.route_id} has ${stops.length} stops and a path of ` +
|
|
195
|
+
`${(data.shapes || []).length} shape points.\nStops:\n${stopLines.join("\n")}`);
|
|
196
|
+
}));
|
|
197
|
+
/* 6. get_system_map */
|
|
198
|
+
server.registerTool("get_system_map", {
|
|
199
|
+
title: "Get system map",
|
|
200
|
+
description: "Get every route in the transit system with its name, color, and the stops it " +
|
|
201
|
+
"serves. Use when the rider asks what routes exist or wants an overview of the " +
|
|
202
|
+
"network. Shape geometry is omitted from the summary to keep it readable.",
|
|
203
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
204
|
+
inputSchema: { ...feedArg },
|
|
205
|
+
}, (args) => guard(async () => {
|
|
206
|
+
const data = await api.get("/map/system", {
|
|
207
|
+
feed_id: feed(args.feed_id),
|
|
208
|
+
});
|
|
209
|
+
if (!data.routes?.length)
|
|
210
|
+
return text("No routes are configured for this feed.");
|
|
211
|
+
const lines = data.routes.map((r) => {
|
|
212
|
+
const label = r.long_name && r.long_name !== r.name ? `${r.name} — ${r.long_name}` : r.name;
|
|
213
|
+
return `• Route ${label} (route_id: ${r.route_id}) — ${r.stops?.length ?? 0} stops`;
|
|
214
|
+
});
|
|
215
|
+
return text(`The system has ${data.routes.length} routes:\n${lines.join("\n")}`);
|
|
216
|
+
}));
|
|
217
|
+
/* 7. get_service_alerts */
|
|
218
|
+
server.registerTool("get_service_alerts", {
|
|
219
|
+
title: "Get service alerts",
|
|
220
|
+
description: "Get active service alerts (delays, detours, cancellations) from GTFS-Realtime. " +
|
|
221
|
+
"IMPORTANT: an empty result is normal and means there are currently NO active " +
|
|
222
|
+
"alerts — it does NOT mean buses aren't running. Many agencies have no alerts " +
|
|
223
|
+
"most of the time, and some have no realtime feed at all.",
|
|
224
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
225
|
+
inputSchema: {
|
|
226
|
+
route_id: z.string().optional().describe("Optional: filter alerts to one route_id."),
|
|
227
|
+
...feedArg,
|
|
228
|
+
},
|
|
229
|
+
}, (args) => guard(async () => {
|
|
230
|
+
const data = await api.get("/rt/alerts", {
|
|
231
|
+
feed_id: feed(args.feed_id),
|
|
232
|
+
route_id: args.route_id,
|
|
233
|
+
});
|
|
234
|
+
const alerts = data.alerts || [];
|
|
235
|
+
if (!alerts.length) {
|
|
236
|
+
return text("There are no active service alerts right now. Normal service is in effect " +
|
|
237
|
+
"(no delays, detours, or cancellations are being reported).");
|
|
238
|
+
}
|
|
239
|
+
const blocks = alerts.map((a) => {
|
|
240
|
+
const tags = [
|
|
241
|
+
a.severity != null ? SEVERITY[a.severity] : null,
|
|
242
|
+
a.effect != null ? EFFECT[a.effect] : null,
|
|
243
|
+
a.cause != null ? CAUSE[a.cause] : null,
|
|
244
|
+
].filter(Boolean);
|
|
245
|
+
const head = `⚠ ${a.header || "Service alert"}${tags.length ? ` [${tags.join(" · ")}]` : ""}`;
|
|
246
|
+
const body = a.description ? `\n ${a.description}` : "";
|
|
247
|
+
const routes = a.routes?.length ? `\n Affected routes: ${a.routes.join(", ")}` : "";
|
|
248
|
+
const more = a.url ? `\n More info: ${a.url}` : "";
|
|
249
|
+
return head + body + routes + more;
|
|
250
|
+
});
|
|
251
|
+
return text(`Active service alerts:\n${blocks.join("\n\n")}`);
|
|
252
|
+
}));
|
|
253
|
+
/* 8. get_live_vehicles */
|
|
254
|
+
server.registerTool("get_live_vehicles", {
|
|
255
|
+
title: "Get live vehicles",
|
|
256
|
+
description: "Get real-time vehicle positions from GTFS-Realtime: each bus's location, " +
|
|
257
|
+
"heading, the route it's on, and its next stop. IMPORTANT: an empty result is " +
|
|
258
|
+
"normal — it means no vehicles are currently reporting (off-hours, or the " +
|
|
259
|
+
"agency has no realtime vehicle feed). It does NOT imply the schedule is wrong.",
|
|
260
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
261
|
+
inputSchema: {
|
|
262
|
+
route_id: z.string().optional().describe("Optional: filter to vehicles on one route_id."),
|
|
263
|
+
...feedArg,
|
|
264
|
+
},
|
|
265
|
+
}, (args) => guard(async () => {
|
|
266
|
+
const data = await api.get("/rt/vehicles", {
|
|
267
|
+
feed_id: feed(args.feed_id),
|
|
268
|
+
route_id: args.route_id,
|
|
269
|
+
});
|
|
270
|
+
const vehicles = data.vehicles || [];
|
|
271
|
+
if (!vehicles.length) {
|
|
272
|
+
return text("No vehicles are reporting their position right now. This is normal outside " +
|
|
273
|
+
"service hours or for agencies without a realtime vehicle feed; it doesn't " +
|
|
274
|
+
"mean scheduled service isn't running. Use get_stop_departures for the schedule.");
|
|
275
|
+
}
|
|
276
|
+
const lines = vehicles.map((v) => {
|
|
277
|
+
const where = v.next_stop
|
|
278
|
+
? ` — next stop: ${v.next_stop}${v.next_eta != null ? ` (~${v.next_eta} min)` : ""}`
|
|
279
|
+
: "";
|
|
280
|
+
return (`• Route ${v.route_name || v.route_id} bus ${v.id} at ` +
|
|
281
|
+
`${fmtCoord(v.lat)}, ${fmtCoord(v.lon)}` +
|
|
282
|
+
`${v.bearing != null ? `, heading ${Math.round(v.bearing)}°` : ""}${where}`);
|
|
283
|
+
});
|
|
284
|
+
return text(`Live vehicles (${vehicles.length}):\n${lines.join("\n")}`);
|
|
285
|
+
}));
|
|
286
|
+
/* 9. geocode_address */
|
|
287
|
+
server.registerTool("geocode_address", {
|
|
288
|
+
title: "Geocode an address",
|
|
289
|
+
description: "Convert an address, landmark, or place name into coordinates, biased to the " +
|
|
290
|
+
"agency's service area. Use this to get a latitude/longitude you can then pass " +
|
|
291
|
+
"to find_nearby_stops.",
|
|
292
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
293
|
+
inputSchema: {
|
|
294
|
+
address: z.string().min(1).describe("Address, landmark, or place name."),
|
|
295
|
+
...feedArg,
|
|
296
|
+
},
|
|
297
|
+
}, (args) => guard(async () => {
|
|
298
|
+
const data = await api.get("/geocode", {
|
|
299
|
+
q: args.address,
|
|
300
|
+
feed_id: feed(args.feed_id),
|
|
301
|
+
});
|
|
302
|
+
if (data == null || typeof data.lat !== "number" || typeof data.lon !== "number") {
|
|
303
|
+
return text(`Could not find coordinates for "${args.address}". Try a more specific or ` +
|
|
304
|
+
`nearby place name, or search by stop name with search_stops.`);
|
|
305
|
+
}
|
|
306
|
+
return text(`${data.label || args.address}\nCoordinates: ${fmtCoord(data.lat)}, ${fmtCoord(data.lon)}\n` +
|
|
307
|
+
`Pass these to find_nearby_stops to find the closest stops.`);
|
|
308
|
+
}));
|
|
309
|
+
/* 10. plan_trip */
|
|
310
|
+
server.registerTool("plan_trip", {
|
|
311
|
+
title: "Plan a trip (A → B)",
|
|
312
|
+
description: "Find every transit route that connects two places: each route, the days " +
|
|
313
|
+
"it runs, that day's departure/arrival times, the trip duration, transfers, " +
|
|
314
|
+
"and the fare. This is the definitive way to answer 'how do I get from A to " +
|
|
315
|
+
"B?' — do NOT assemble a trip yourself from find_nearby_stops/" +
|
|
316
|
+
"get_stop_departures. `from` and `to` may be a stop name, an address/" +
|
|
317
|
+
"landmark, or a 'lat,lon' pair. By default it shows today's options; pass " +
|
|
318
|
+
"depart_at to filter to times on/after a moment, or arrive_by, in local " +
|
|
319
|
+
"agency time (ISO 8601 like 2026-06-08T08:00:00). When a route doesn't run " +
|
|
320
|
+
"on the chosen day, its next service day is given. An empty result is " +
|
|
321
|
+
"normal and carries a reason + a helpful message — relay it; it does NOT " +
|
|
322
|
+
"mean the tool failed.",
|
|
323
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
324
|
+
inputSchema: {
|
|
325
|
+
from: z.string().min(1).describe("Origin: a stop name, address/landmark, or 'lat,lon'."),
|
|
326
|
+
to: z.string().min(1).describe("Destination: a stop name, address/landmark, or 'lat,lon'."),
|
|
327
|
+
depart_at: z
|
|
328
|
+
.string()
|
|
329
|
+
.optional()
|
|
330
|
+
.describe("Leave at this local time (ISO 8601, e.g. 2026-06-04T15:00:00). Omit to leave now. Mutually exclusive with arrive_by."),
|
|
331
|
+
arrive_by: z
|
|
332
|
+
.string()
|
|
333
|
+
.optional()
|
|
334
|
+
.describe("Arrive by this local time (ISO 8601). Mutually exclusive with depart_at."),
|
|
335
|
+
accessible_only: z
|
|
336
|
+
.boolean()
|
|
337
|
+
.optional()
|
|
338
|
+
.describe("Only wheelchair-accessible trips and stops."),
|
|
339
|
+
bikes: z.boolean().optional().describe("Only trips that allow bikes."),
|
|
340
|
+
rider_category: z
|
|
341
|
+
.string()
|
|
342
|
+
.optional()
|
|
343
|
+
.describe("Fare category for pricing: adult (default), senior, youth, or disabled."),
|
|
344
|
+
...feedArg,
|
|
345
|
+
},
|
|
346
|
+
}, (args) => guard(async () => {
|
|
347
|
+
const data = await api.post("/trips/plan", {
|
|
348
|
+
feed_id: feed(args.feed_id),
|
|
349
|
+
from: asPlace(args.from),
|
|
350
|
+
to: asPlace(args.to),
|
|
351
|
+
depart_at: args.depart_at,
|
|
352
|
+
arrive_by: args.arrive_by,
|
|
353
|
+
accessible_only: args.accessible_only ?? false,
|
|
354
|
+
bikes: args.bikes ?? false,
|
|
355
|
+
rider_category: args.rider_category ?? "adult",
|
|
356
|
+
results: 8,
|
|
357
|
+
});
|
|
358
|
+
if (!data.options?.length) {
|
|
359
|
+
let msg = data.message || "No routes were found connecting those places.";
|
|
360
|
+
if (data.reason === "outside_service_area" && data.nearest_stop) {
|
|
361
|
+
msg += ` The nearest served stop is ${data.nearest_stop.name}` +
|
|
362
|
+
(data.nearest_stop_distance ? ` (${data.nearest_stop_distance} away)` : "") + ".";
|
|
363
|
+
}
|
|
364
|
+
if (data.next_service_date)
|
|
365
|
+
msg += ` Next service: ${data.next_service_date}.`;
|
|
366
|
+
return text(msg);
|
|
367
|
+
}
|
|
368
|
+
const dateNote = data.date ? ` (times shown for ${data.date})` : "";
|
|
369
|
+
const blocks = data.options.map((o, i) => formatOption(o, i + 1));
|
|
370
|
+
const header = `Routes from ${args.from} to ${args.to}${dateNote}:`;
|
|
371
|
+
return text(`${header}\n\n${blocks.join("\n\n")}`);
|
|
372
|
+
}));
|
|
373
|
+
}
|
|
374
|
+
/** Parse a from/to argument into the REST contract's place object. */
|
|
375
|
+
function asPlace(v) {
|
|
376
|
+
const m = v.trim().match(/^(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)$/);
|
|
377
|
+
if (m) {
|
|
378
|
+
return { lat: parseFloat(m[1]), lon: parseFloat(m[2]) };
|
|
379
|
+
}
|
|
380
|
+
return { address: v.trim() };
|
|
381
|
+
}
|
|
382
|
+
/** Render one connecting route (or route pair) as readable prose. */
|
|
383
|
+
function formatOption(o, n) {
|
|
384
|
+
if (o.walk_only) {
|
|
385
|
+
return `Option ${n} — Walk ${o.duration_min} min${o.walk ? ` (${o.walk.display})` : ""}. ` +
|
|
386
|
+
`It's a short walk, likely faster than waiting for transit.`;
|
|
387
|
+
}
|
|
388
|
+
const routeNames = (o.routes || []).map((r) => `Route ${r.name || r.id}`).join(" → ");
|
|
389
|
+
const xfer = o.transfers === 0
|
|
390
|
+
? "direct"
|
|
391
|
+
: `${o.transfers} transfer${o.transfers === 1 ? "" : "s"}${o.transfer_at ? ` at ${o.transfer_at.name}` : ""}`;
|
|
392
|
+
const days = o.service_days?.length ? ` Runs ${o.service_days.join(", ")}.` : "";
|
|
393
|
+
const head = `Option ${n} — ${routeNames} (${xfer}), ~${o.duration_min} min.${days} Fare: ${formatFare(o.fare)}.`;
|
|
394
|
+
const lines = [];
|
|
395
|
+
if (o.from_stop?.name && o.to_stop?.name) {
|
|
396
|
+
lines.push(` Board ${o.from_stop.name} → get off at ${o.to_stop.name}.`);
|
|
397
|
+
}
|
|
398
|
+
if (o.times?.length) {
|
|
399
|
+
lines.push(` Departures: ${formatTimes(o.times)}`);
|
|
400
|
+
}
|
|
401
|
+
else if (o.next_service_date) {
|
|
402
|
+
const nt = o.next_times?.length ? ` — ${formatTimes(o.next_times)}` : "";
|
|
403
|
+
lines.push(` No departures on the selected day. Next service ${o.next_service_date}${nt}.`);
|
|
404
|
+
}
|
|
405
|
+
return `${head}\n${lines.join("\n")}`;
|
|
406
|
+
}
|
|
407
|
+
/** Compact departure list: "8:16 AM → 8:40 AM; 10:00 AM → 10:24 AM, +2 more". */
|
|
408
|
+
function formatTimes(times) {
|
|
409
|
+
const shown = times.slice(0, 6).map((t) => {
|
|
410
|
+
const conn = t.connection ? ` (${t.connection.wait_min} min connection)` : "";
|
|
411
|
+
return `${t.depart} → ${t.arrive}${conn}`;
|
|
412
|
+
});
|
|
413
|
+
const more = times.length > 6 ? `, +${times.length - 6} more` : "";
|
|
414
|
+
return shown.join("; ") + more;
|
|
415
|
+
}
|
|
416
|
+
/** Fare summary line; honest about partial/unavailable (never a false $0). */
|
|
417
|
+
function formatFare(fare) {
|
|
418
|
+
if (!fare)
|
|
419
|
+
return "not available";
|
|
420
|
+
if (fare.status === "exact" || fare.status === "partial") {
|
|
421
|
+
if (fare.total === "0.00")
|
|
422
|
+
return "Fare-free";
|
|
423
|
+
const amount = `${fare.currency ? fare.currency + " " : ""}${fare.total}`;
|
|
424
|
+
const extra = fare.status === "partial" ? " (partial — see route fares)" : fare.note ? ` (${fare.note})` : "";
|
|
425
|
+
return amount + extra;
|
|
426
|
+
}
|
|
427
|
+
// unavailable / cross_agency
|
|
428
|
+
const routes = fare.fallback_routes?.length ? ` — see fares for routes ${fare.fallback_routes.join(", ")}` : "";
|
|
429
|
+
return `not available${routes}`;
|
|
430
|
+
}
|
|
431
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
|