Skip to main content
Glama
cindyhsugit

mcp-server-simpsons-cities

by cindyhsugit

🏘️ mcp-server-simpsons-cities

An MCP (Model Context Protocol) server that finds real U.S. cities near a given zip code whose names match anything from The Simpsons β€” not just towns like Springfield and Shelbyville, but character names, businesses, and other references from the show. If there's a real town near you called "Maggie," this tool finds it.

Built as an end-to-end MCP integration: a Python server exposing a live tool to Claude Desktop, backed by a real geospatial API and a self-scraped reference dataset.


Why this project

This started as a fun, low-stakes way to explore the full MCP development lifecycle β€” from writing and debugging a Python server, to authenticating against a third-party API, to wiring it into a real LLM client and iterating based on live tool-call failures. It touches:

  • API integration β€” authenticated third-party REST API (GeoNames), with real debugging around HTTPS certificate mismatches, auth propagation delays, and rate limits

  • Data engineering β€” a standalone scraper that paginates a MediaWiki API, dedupes, and filters noisy category data into a clean reference dataset

  • Protocol-level tool design β€” exposing a single well-scoped tool via FastMCP rather than forcing an LLM client to chain multiple raw API calls itself

  • Environment & secrets management β€” .env-based config, gitignored credentials, environment variables passed cleanly into a subprocess-launched server

  • Client integration & debugging β€” wiring the server into Claude Desktop's claude_desktop_config.json, and using the MCP Inspector plus stderr logging to diagnose failures that only appeared once the tool was actually called end-to-end


Demo

Live tool call in Claude Desktop (used here as the MCP client) β€” a natural-language question, routed automatically to the right tool, answered with a live API result:

βœ… True positive β€” a real match found

Claude Desktop finds a real Springfield, IL match for zip code 62701

❌ Correct negative β€” no match, and Claude proactively offers next steps

Claude Desktop correctly finds no Simpsons-named cities near zip code 92840


Architecture

                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   "Any Simpsons-   β”‚   Claude Desktop     β”‚
    named cities     β”‚   (MCP Client)       β”‚
    near 62701?" ───▢│                       β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               β”‚ MCP protocol (stdio)
                               β–Ό
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚ find_simpsons_       β”‚
                    β”‚ cities.py            β”‚
                    β”‚  (FastMCP server)    β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               β”‚
                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                 β–Ό                             β–Ό
      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
      β”‚   GeoNames API      β”‚      β”‚  data/simpsons_       β”‚
      β”‚ (nearby cities by   β”‚      β”‚  names.json            β”‚
      β”‚  zip + radius)      β”‚      β”‚  (pre-built, scraped   β”‚
      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚  from Wikisimpsons)     β”‚
                                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Request flow:

  1. User asks a natural-language question in Claude Desktop.

  2. Claude Desktop, acting as the MCP client, recognizes the intent and calls the get_simpsons_city tool over the MCP protocol.

  3. The server queries GeoNames for real cities within a radius of the given zip code.

  4. Each city name is checked (case-insensitively) against a locally-cached Simpsons name database.

  5. Matches β€” or a clear "no matches" result β€” are returned to Claude, which formats a natural-language response.


Tools exposed

Tool

Description

get_simpsons_city(zipcode, radius_km=30)

Finds real cities near a U.S. zip code that share a name with a character, location, or business from The Simpsons.


Tech stack

  • FastMCP (mcp[cli], pinned to v1.x) β€” MCP server framework

  • httpx β€” async HTTP client for both the GeoNames API and the Wikisimpsons scraper

  • uv β€” Python dependency & environment management

  • GeoNames β€” free geospatial API for zip-code-radius city lookups

  • Wikisimpsons (Fandom) β€” source data via the MediaWiki categorymembers API

  • Claude Desktop β€” MCP client used for testing and live usage

  • MCP Inspector β€” interactive tool-testing UI during development


Getting started

Prerequisites

  • Python 3.13+

  • uv

  • A free GeoNames account with the free web service enabled on your account page β€” this is a separate step from registering, and easy to miss.

Install

git clone https://github.com/cindyhsugit/mcp-server-simpsons-cities.git
cd mcp-server-simpsons-cities
uv sync

Configure

Create a .env file in the project root:

GEONAMES_USERNAME=your_geonames_username

.env is gitignored β€” never commit real credentials.

(Optional) Rebuild the Simpsons name database

A pre-built data/simpsons_names.json ships with the repo. To refresh it from Wikisimpsons:

uv run build_data.py

This paginates through Category:Characters, Category:Locations, and Category:Businesses via the Fandom MediaWiki API, dedupes results, and writes a clean JSON list.


Running & testing

Standalone (sanity-check startup):

uv run find_simpsons_cities.py

Interactive testing (requires Node.js):

uv run mcp dev find_simpsons_cities.py

Opens the MCP Inspector in your browser for calling get_simpsons_city directly with real inputs and inspecting raw responses.


Connecting to Claude Desktop

This project was built and tested using Claude Desktop as the MCP client.

Open your config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Add:

{
  "mcpServers": {
    "simpsons-cities": {
      "command": "uv",
      "args": [
        "--directory",
        "/absolute/path/to/mcp-server-simpsons-cities",
        "run",
        "find_simpsons_cities.py"
      ],
      "env": {
        "GEONAMES_USERNAME": "your_geonames_username"
      }
    }
  }
}

Fully quit and reopen Claude Desktop, then just ask:

"Are there any Simpsons-named cities near zip code 62701?"


Project structure

mcp-server-simpsons-cities/
β”œβ”€β”€ find_simpsons_cities.py   # MCP server β€” defines get_simpsons_city tool
β”œβ”€β”€ build_data.py             # Standalone scraper β€” builds data/simpsons_names.json
β”œβ”€β”€ data/
β”‚   └── simpsons_names.json   # Scraped Simpsons character/location/business names
β”œβ”€β”€ screenshots/
β”‚   β”œβ”€β”€ example-match-springfield.png
β”‚   └── example-no-match-92840.png
β”œβ”€β”€ pyproject.toml
β”œβ”€β”€ .env                      # (gitignored) GeoNames credentials
└── README.md

Engineering notes / lessons learned

A few real issues hit and resolved during development, kept here for transparency:

  • mcp v2 breaking change β€” a new major SDK release renamed FastMCP to MCPServer, silently breaking from mcp.server.fastmcp import FastMCP. Fixed by pinning mcp[cli]>=1.28,<2 in pyproject.toml.

  • GeoNames certificate mismatch β€” https://api.geonames.org serves a certificate valid for geonames.net, not .org, causing browser/TLS warnings. Resolved by using plain HTTP for the free-tier endpoint (the pattern GeoNames' own official examples use).

  • GeoNames "premium-only" trap β€” secure.geonames.org looks like the natural HTTPS alternative, but it's a premium-tier-only endpoint and returns 401 for free accounts.

  • Silent account activation delay β€” enabling the free web service on a GeoNames account doesn't always propagate instantly; requests can 401 for several minutes after enabling before working.

  • Debuggability β€” added structured stderr logging in the HTTP layer specifically so failures surface in the MCP Inspector / Claude Desktop's developer log instead of collapsing into a generic error message.


Known limitations

  • 30 km search radius β€” the free-tier cap on GeoNames' findNearbyPostalCodes endpoint.

  • Exact-match only β€” a city name must match a Simpsons name exactly (case-insensitive). "Springfield Heights" would not match "Springfield." Fuzzy/substring matching is a natural next step.

  • US zip codes only β€” scoped to country=US for now.


License

MIT