list_cities
Retrieve a list of available cities with metadata to identify valid city slugs for querying nightlife events and concerts.
Instructions
List all available cities with metadata. Use this to discover valid city slugs before calling other tools.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| cities | Yes |
Implementation Reference
- src/services/cities.ts:64-100 (handler)Core handler function that queries the 'cities' table from Supabase, filters out unknown slugs and optionally filters by topLevelCities config, then returns an array of city objects with slug, name, timezone, and country_code.
export async function listCities( supabase: SupabaseClient, topLevelCities?: string[], ): Promise<{ cities: Array<{ slug: string; name: string; timezone: string; country_code: string }>; }> { const { data, error } = await supabase .from("cities") .select("slug,name_en,timezone,country_code") .order("slug", { ascending: true }); if (error || !data) { return { cities: [] }; } let rows = data.filter( (row) => row.slug && !String(row.slug).startsWith("unknown"), ); if (topLevelCities && topLevelCities.length > 0) { const allowed = new Set( topLevelCities .map((v) => v.trim().toLowerCase()) .filter((v) => v.length > 0), ); rows = rows.filter((row) => allowed.has(String(row.slug).trim().toLowerCase())); } return { cities: rows.map((row) => ({ slug: String(row.slug).trim().toLowerCase(), name: row.name_en || row.slug, timezone: row.timezone || "UTC", country_code: row.country_code || "JP", })), }; } - src/tools/helpers.ts:55-64 (schema)Zod output schema for list_cities tool defining the shape: { cities: Array<{ slug, name, timezone, country_code }> }
const listCitiesOutputSchema = z.object({ cities: z.array( z.object({ slug: z.string(), name: z.string(), timezone: z.string(), country_code: z.string(), }), ), }); - src/tools/helpers.ts:84-97 (registration)MCP tool registration via server.registerTool('list_cities', ...), which wires the tool name, description, input/output schemas, and the handler callback that calls listCities from the service layer.
export function registerHelperTools(server: McpServer, deps: ToolDeps): void { server.registerTool( "list_cities", { description: "List all available cities with metadata. Use this to discover valid city slugs before calling other tools.", inputSchema: {}, outputSchema: listCitiesOutputSchema, }, async () => runTool("list_cities", listCitiesOutputSchema, async () => listCities(deps.supabase, deps.config.topLevelCities), ), ); - src/tools/helpers.ts:19-51 (helper)The runTool wrapper function that invokes the handler, parses output through the schema, records metrics, and handles errors with proper tool error responses.
async function runTool<Output>( toolName: string, outputSchema: z.ZodType<Output>, cb: () => Promise<Output>, ) { const startedAt = Date.now(); try { const output = outputSchema.parse(await cb()); const durationMs = Date.now() - startedAt; recordToolResult({ tool: toolName, durationMs }); logEvent("tool.success", { tool: toolName, duration_ms: durationMs }); return { content: [{ type: "text" as const, text: jsonText(output) }], structuredContent: output as unknown as Record<string, unknown>, }; } catch (error) { const normalized = toNightlifeError(error); const durationMs = Date.now() - startedAt; recordToolResult({ tool: toolName, durationMs, errorCode: normalized.code }); logEvent("tool.error", { tool: toolName, duration_ms: durationMs, code: normalized.code, message: normalized.message, }); return { isError: true, content: [{ type: "text" as const, text: jsonText(toolErrorResponse(normalized)) }], }; } } - src/openapi.ts:619-637 (schema)OpenAPI schema definition for ListCitiesOutput used by the REST endpoint, matching the same structure as the MCP tool.
ListCitiesOutput: { type: "object", properties: { cities: { type: "array", items: { type: "object", properties: { slug: { type: "string" }, name: { type: "string" }, timezone: { type: "string" }, country_code: { type: "string" }, }, required: ["slug", "name", "timezone", "country_code"], }, }, }, required: ["cities"], },