GAIA-431: require countryCode in KKTC-aware city listing tools and ADMINISTRATIVE boundaries
The backend now serves city catalogs per country, so the list_cities tools for forecast and geo alarms take a required countryCode (TUR or CTR) and call /v1/alarms/{forecasts|geometries}/{countryCode}/cities instead of the removed country-less path, which the MCP could no longer reach.
The boundary schema of both register and update tools now rejects ADMINISTRATIVE boundaries without a countryCode of TUR or CTR, mirroring the server-side validation so the client gets a clear error before the request is sent, since city and district ids are only unique within a country. Tool descriptions also explain that KKTC neighbourhoods are sub-districts.
This commit is contained in:
@@ -6,7 +6,7 @@ const webhookDescription =
|
|||||||
|
|
||||||
const boundaryDescription =
|
const boundaryDescription =
|
||||||
"Boundary definition. One of:\n" +
|
"Boundary definition. One of:\n" +
|
||||||
"- Administrative: { type: 'ADMINISTRATIVE', cityId: 6, districtId: 557 }\n" +
|
"- Administrative: { type: 'ADMINISTRATIVE', countryCode: 'TUR', cityId: 6, districtId: 557 } (countryCode is required: TUR for Türkiye, CTR for Northern Cyprus; city and district IDs come from forecast_alarm_list_cities / forecast_alarm_list_districts for that country)\n" +
|
||||||
"- Point: { type: 'POINT', point: { lat: 39.93, lng: 32.85 } }";
|
"- Point: { type: 'POINT', point: { lat: 39.93, lng: 32.85 } }";
|
||||||
|
|
||||||
export const forecastAlarmTools = [
|
export const forecastAlarmTools = [
|
||||||
@@ -167,11 +167,17 @@ export const forecastAlarmTools = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "forecast_alarm_list_cities",
|
name: "forecast_alarm_list_cities",
|
||||||
description: "List all cities in Türkiye available for forecast alarm boundaries.",
|
description: "List all cities of a country available for forecast alarm boundaries. Supported countries: TUR (Türkiye) and CTR (Northern Cyprus).",
|
||||||
inputSchema: {
|
inputSchema: {
|
||||||
type: "object" as const,
|
type: "object" as const,
|
||||||
properties: {},
|
properties: {
|
||||||
required: [],
|
countryCode: {
|
||||||
|
type: "string",
|
||||||
|
enum: ["TUR", "CTR"],
|
||||||
|
description: "ISO 3166 alpha-3 country code: TUR (Türkiye) or CTR (Northern Cyprus)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ["countryCode"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -222,7 +228,10 @@ const WebhookSchema = z.object({
|
|||||||
|
|
||||||
const ForecastBoundarySchema = z.object({
|
const ForecastBoundarySchema = z.object({
|
||||||
type: z.enum(["ADMINISTRATIVE", "POINT"]),
|
type: z.enum(["ADMINISTRATIVE", "POINT"]),
|
||||||
}).passthrough();
|
}).passthrough().refine(
|
||||||
|
(boundary) => boundary.type !== "ADMINISTRATIVE" || boundary.countryCode === "TUR" || boundary.countryCode === "CTR",
|
||||||
|
{ message: "countryCode (TUR or CTR) is required for ADMINISTRATIVE boundaries", path: ["countryCode"] }
|
||||||
|
);
|
||||||
|
|
||||||
const ForecastRegisterSchema = z.object({
|
const ForecastRegisterSchema = z.object({
|
||||||
recipientId: z.string(),
|
recipientId: z.string(),
|
||||||
@@ -327,8 +336,10 @@ export async function handleForecastAlarmTool(
|
|||||||
case "forecast_alarm_list":
|
case "forecast_alarm_list":
|
||||||
return apiPost("/v1/alarms/forecasts/page", ListSchema.parse(args));
|
return apiPost("/v1/alarms/forecasts/page", ListSchema.parse(args));
|
||||||
|
|
||||||
case "forecast_alarm_list_cities":
|
case "forecast_alarm_list_cities": {
|
||||||
return apiGet("/v1/alarms/forecasts/cities");
|
const countryCode = z.enum(["TUR", "CTR"]).parse(args.countryCode);
|
||||||
|
return apiGet(`/v1/alarms/forecasts/${countryCode}/cities`);
|
||||||
|
}
|
||||||
|
|
||||||
case "forecast_alarm_get_city": {
|
case "forecast_alarm_get_city": {
|
||||||
const cityId = z.number().parse(args.cityId);
|
const cityId = z.number().parse(args.cityId);
|
||||||
|
|||||||
+20
-9
@@ -6,7 +6,7 @@ const webhookDescription =
|
|||||||
|
|
||||||
const boundaryDescription =
|
const boundaryDescription =
|
||||||
"Boundary definition. One of:\n" +
|
"Boundary definition. One of:\n" +
|
||||||
"- Administrative: { type: 'ADMINISTRATIVE', cityId: 6, districtId: 557, neighborhoodId: 55766 }\n" +
|
"- Administrative: { type: 'ADMINISTRATIVE', countryCode: 'TUR', cityId: 6, districtId: 557, neighborhoodId: 55766 } (countryCode is required: TUR for Türkiye, CTR for Northern Cyprus; IDs come from the catalog tools for that country. For CTR the neighborhood level is the sub-district)\n" +
|
||||||
"- Polygon: { type: 'POLYGON', polygon: { exterior: [{lat, lng}, ...] } }\n" +
|
"- Polygon: { type: 'POLYGON', polygon: { exterior: [{lat, lng}, ...] } }\n" +
|
||||||
"- H3 Index: { type: 'H3INDEX', h3Address: '8928308280fffff' }";
|
"- H3 Index: { type: 'H3INDEX', h3Address: '8928308280fffff' }";
|
||||||
|
|
||||||
@@ -133,11 +133,17 @@ export const geoAlarmTools = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "geo_alarm_list_cities",
|
name: "geo_alarm_list_cities",
|
||||||
description: "List all cities in Türkiye available for geo alarm boundaries.",
|
description: "List all cities of a country available for geo alarm boundaries. Supported countries: TUR (Türkiye) and CTR (Northern Cyprus).",
|
||||||
inputSchema: {
|
inputSchema: {
|
||||||
type: "object" as const,
|
type: "object" as const,
|
||||||
properties: {},
|
properties: {
|
||||||
required: [],
|
countryCode: {
|
||||||
|
type: "string",
|
||||||
|
enum: ["TUR", "CTR"],
|
||||||
|
description: "ISO 3166 alpha-3 country code: TUR (Türkiye) or CTR (Northern Cyprus)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ["countryCode"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -175,7 +181,7 @@ export const geoAlarmTools = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "geo_alarm_list_neighborhoods",
|
name: "geo_alarm_list_neighborhoods",
|
||||||
description: "List all neighborhoods for a given district.",
|
description: "List all neighborhoods for a given district. For CTR (Northern Cyprus) neighborhoods are the sub-district level.",
|
||||||
inputSchema: {
|
inputSchema: {
|
||||||
type: "object" as const,
|
type: "object" as const,
|
||||||
properties: {
|
properties: {
|
||||||
@@ -186,7 +192,7 @@ export const geoAlarmTools = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "geo_alarm_get_neighborhood",
|
name: "geo_alarm_get_neighborhood",
|
||||||
description: "Get boundary details for a specific neighborhood by its ID.",
|
description: "Get boundary details for a specific neighborhood by its ID. For CTR (Northern Cyprus) neighborhoods are the sub-district level.",
|
||||||
inputSchema: {
|
inputSchema: {
|
||||||
type: "object" as const,
|
type: "object" as const,
|
||||||
properties: {
|
properties: {
|
||||||
@@ -210,7 +216,10 @@ const WebhookSchema = z.object({
|
|||||||
|
|
||||||
const GeoBoundarySchema = z.object({
|
const GeoBoundarySchema = z.object({
|
||||||
type: z.enum(["ADMINISTRATIVE", "POLYGON", "H3INDEX"]),
|
type: z.enum(["ADMINISTRATIVE", "POLYGON", "H3INDEX"]),
|
||||||
}).passthrough();
|
}).passthrough().refine(
|
||||||
|
(boundary) => boundary.type !== "ADMINISTRATIVE" || boundary.countryCode === "TUR" || boundary.countryCode === "CTR",
|
||||||
|
{ message: "countryCode (TUR or CTR) is required for ADMINISTRATIVE boundaries", path: ["countryCode"] }
|
||||||
|
);
|
||||||
|
|
||||||
const GeoRegisterSchema = z.object({
|
const GeoRegisterSchema = z.object({
|
||||||
recipientId: z.string(),
|
recipientId: z.string(),
|
||||||
@@ -302,8 +311,10 @@ export async function handleGeoAlarmTool(
|
|||||||
case "geo_alarm_list":
|
case "geo_alarm_list":
|
||||||
return apiPost("/v1/alarms/geometries/page", ListSchema.parse(args));
|
return apiPost("/v1/alarms/geometries/page", ListSchema.parse(args));
|
||||||
|
|
||||||
case "geo_alarm_list_cities":
|
case "geo_alarm_list_cities": {
|
||||||
return apiGet("/v1/alarms/geometries/cities");
|
const countryCode = z.enum(["TUR", "CTR"]).parse(args.countryCode);
|
||||||
|
return apiGet(`/v1/alarms/geometries/${countryCode}/cities`);
|
||||||
|
}
|
||||||
|
|
||||||
case "geo_alarm_get_city": {
|
case "geo_alarm_get_city": {
|
||||||
const cityId = z.number().parse(args.cityId);
|
const cityId = z.number().parse(args.cityId);
|
||||||
|
|||||||
Reference in New Issue
Block a user