{"$schema":"https://static.modelcontextprotocol.io/schemas/mcp-server-card/v1.json","version":"1.0","protocolVersion":"2025-06-18","serverInfo":{"name":"geocode","title":"Geocode AI","version":"1.0.0","websiteUrl":"https://geo-coder-service.vercel.app/"},"description":"Look up any administrative boundary in the world (country, state, county, city, district, postcode) by name or point and get its polygon in one call, or describe an area in plain language and get a validated polygon back. REST, MCP, CLI and plugins for Claude and Codex.","documentationUrl":"https://geo-coder-service.vercel.app/llms.txt","transport":{"type":"streamable-http","endpoint":"https://geo-coder-service.vercel.app/mcp"},"endpoints":{"api_key_or_anonymous":"https://geo-coder-service.vercel.app/mcp","oauth":"https://geo-coder-service.vercel.app/mcp?auth=required","stdio":"npx -y @meterapp/geocode mcp"},"authentication":{"required":false,"schemes":["bearer","oauth2"],"api_key":{"header":"Authorization: Bearer","prefix":"geo_","get_one":"https://geo-coder-service.vercel.app/dashboard"},"oauth_protected_resource":"https://geo-coder-service.vercel.app/.well-known/oauth-protected-resource"},"capabilities":{"tools":{"listChanged":false}},"tools":[{"name":"search_boundaries","title":"Search boundaries","description":"Finds administrative boundaries (countries, states, counties, cities, districts) and postcode areas by name, in any language. Filter by country, kind or admin_level; bias toward a point with near. Free and public. Returns candidates with id, kind, admin_level, country, parents, bbox, centroid and population, but no polygon: pass the id to get_boundary for that.","public":true,"readOnly":true},{"name":"get_boundary","title":"Get boundary polygon","description":"Returns one boundary as a GeoJSON Feature: its polygon at a chosen detail plus properties (name, kind, admin_level, parents, bbox, area_km2, population, wikidata). Fetched from OpenStreetMap the first time anyone asks, then served from cache. Costs 1 unit; detail=low is also public without a key (for map previews). include=parents adds the full hierarchy, include=children the direct subdivisions. If the polygon is too big for one response, geometry is null and download_url points to the file.","public":true,"readOnly":true},{"name":"export_boundary","title":"Export boundary file","description":"Builds a boundary's polygon as a file (geojson, kml, wkt, svg or gml) at a detail level and returns a permanent public URL on our CDN; the REST route redirects straight to it. Use it for large polygons, GIS tools and bulk downloads. Costs 1 unit; each file is built once and then shared.","public":false,"readOnly":true},{"name":"reverse_boundaries","title":"Boundaries at a point","description":"Every administrative boundary containing a point, country first down to the smallest district, plus postcode areas. Use it to tag an address, a store or a delivery with its country, state, county and city in one call. Costs 1 unit. Returns ids you can pass to get_boundary.","public":false,"readOnly":true},{"name":"list_children","title":"List subdivisions","description":"The direct subdivisions of a boundary: a country's states, a state's counties, a city's districts. Without admin_level it picks the next level that exists. Free and public. Use it to build drill-down pickers or to cover a region with its parts.","public":true,"readOnly":true},{"name":"contains_points","title":"Points in boundary","description":"Tests up to 10,000 points ([lon, lat] pairs) against one boundary and returns a boolean per point plus the inside count. Use it for geofencing, service-area checks and filtering customer lists. Costs 1 unit per 1,000 points.","public":false,"readOnly":true},{"name":"union_boundaries","title":"Merge boundaries","description":"Merges boundaries into one polygon: the union of include minus the union of exclude (e.g. three counties minus one city). Use it for sales territories, delivery zones and service areas. Up to 50 boundaries; costs 1 unit per boundary. Returns a GeoJSON Feature with area_km2. To describe an area in words instead, use create_area.","public":false,"readOnly":true},{"name":"create_area","title":"Create area from a description","description":"Turns a plain-language description of an area (\"Alameda and Contra Costa counties excluding San Jose, plus SFO\") or wording from a contract or policy into one validated land-only polygon. An AI agent plans includes/excludes from real administrative boundaries; you get GeoJSON plus each part's source, or a 422 explaining what could not be mapped. Takes 30 s to a few minutes. For a single named place use search_boundaries + get_boundary instead: it is instant and costs 1 unit.","public":false,"readOnly":false},{"name":"get_account","title":"Get account","description":"The signed-in account: email, plan, this month's usage against the plan's limit, and rate limit. Call it to check remaining quota before a large batch.","public":false,"readOnly":true},{"name":"update_profile","title":"Update profile","description":"Sets the account's name, company and use case (what you are building). Send only the fields to change; an empty string clears one. Free. Returns the updated profile.","public":false,"readOnly":false},{"name":"get_usage","title":"Get usage","description":"Daily usage for the last N days (default 30), by op, with cache hit counts. Use it to explain a bill or spot a runaway client.","public":false,"readOnly":true},{"name":"list_api_keys","title":"List API keys","description":"The account's API keys (prefix, name, last use; never the secret).","public":false,"readOnly":true},{"name":"create_api_key","title":"Create API key","description":"Creates an API key and returns the secret once. Store it in an environment variable (GEOCODE_API_KEY); it cannot be shown again.","public":false,"readOnly":false},{"name":"revoke_api_key","title":"Revoke API key","description":"Revokes an API key by id. Requests with it fail with 401 immediately.","public":false,"readOnly":false},{"name":"get_email_preferences","title":"Get email preferences","description":"Which automated emails the account receives: the global subscription and one switch per kind (getting-started notes, first boundary, usage milestones, quota warnings, check-ins, monthly digest). Free. Sign-in codes are always sent.","public":false,"readOnly":true},{"name":"update_email_preferences","title":"Update email preferences","description":"Turns automated emails on or off: `subscribed: false` stops all of them (the same as the unsubscribe link), `subscribed: true` resubscribes, and `kinds` switches individual kinds. Kinds not named keep their setting. Free. Returns the preferences after the change.","public":false,"readOnly":false},{"name":"list_feedback","title":"List feature requests and issues","description":"The public feedback board: feature requests and issue reports with their status and upvotes, most upvoted first. Free and needs no key (with a key, each item says whether you voted). Call it before request_feature or report_issue to find an existing item to upvote instead of filing a duplicate, or when the human asks what is planned.","public":true,"readOnly":true},{"name":"get_feedback","title":"Get a feature request or issue","description":"One feedback item with its status, upvotes and comments. Free and needs no key.","public":true,"readOnly":true},{"name":"request_feature","title":"Request a feature","description":"Files a feature request on the public board and upvotes it for you. Use it when the human wants something the API cannot do yet (a boundary type, export format, op or option). Check list_feedback first and upvote an existing request instead of filing a duplicate. Free; needs a key; 10 new items per account a day. Returns the item and similar existing requests. Everything on the board is public (never the author's email). Do not include API keys, personal data or customer data.","public":false,"readOnly":false},{"name":"report_issue","title":"Report an issue","description":"Reports a problem on the public board: a failing or wrong API call (pass its request_id from the X-Request-Id header or the error's request_id, and the op), a wrong or missing boundary, a docs error, or anything else broken. Check list_feedback with kind=issue first and upvote a matching report instead. Free; needs a key; 10 new items per account a day. Only you see the request_id. Everything on the board is public (never the author's email). Do not include API keys, personal data or customer data.","public":false,"readOnly":false},{"name":"upvote_feedback","title":"Upvote a feature request or issue","description":"Adds your upvote to a feature request or issue; votes decide what gets built and fixed first. Idempotent: one vote per account. A vote on a duplicate goes to the original. Free; needs a key. Returns the item with its new vote count.","public":false,"readOnly":false},{"name":"remove_feedback_vote","title":"Remove an upvote","description":"Takes back your upvote on a feature request or issue. Free; needs a key. Returns the item with its new vote count.","public":false,"readOnly":false},{"name":"comment_on_feedback","title":"Comment on a feature request or issue","description":"Adds context to an existing feature request or issue: your use case, another failing request, a workaround. Prefer it (with upvote_feedback) over filing a near-duplicate. Free; needs a key; 50 comments per account a day. Everything on the board is public (never the author's email). Do not include API keys, personal data or customer data.","public":false,"readOnly":false},{"name":"get_pricing","title":"Get plans and prices","description":"The plans (monthly price, included units, rate limit) and what each kind of call costs in units. Free and needs no key. Call it before a large batch, or when the human asks what something costs; never quote prices from memory.","public":true,"readOnly":true}]}