# Directory Structure
```
├── .gitignore
├── .python-version
├── LICENSE
├── main.py
├── pyproject.toml
├── README.md
└── uv.lock
```
# Files
--------------------------------------------------------------------------------
/.python-version:
--------------------------------------------------------------------------------
```
3.13
```
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
```
__pycache__
.venv
```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
```markdown
# WhereAmI MCP Server



A lightweight mcp server that tells you exactly where you are based on your current IP, powered by [ipapi.co](https://ipapi.co/).
## Features
- **Dynamic Resources**: Fetch specific data (e.g., IP, country, city) via `location://{type}`.
- **Detailed Tool**: Generate a comprehensive location report with `get_location()`.
- **Natural Language Prompt**: Ask "Where am I?" to get detailed results.
- **Robust Error Handling**: Gracefully manages API and network issues.
- **Minimal Dependencies**: Requires only `mcp` and `httpx`.
## Installation
### Prerequisites
- Python 3.10+
- `pip`
### Setup
1. Clone the repository:
```bash
git clone https://github.com/kukapay/whereami-mcp.git
cd whereami-mcp
```
2. Install dependencies:
```bash
pip install mcp httpx
```
3. (Optional) Install as an MCP service:
```bash
mcp install whereami_mcp.py --name "WhereAmI"
```
## Usage
### Running the Server
- Direct execution:
```bash
python whereami_mcp.py
```
- Development mode:
```bash
mcp dev whereami_mcp.py
```
### Components
#### Resource: `location://{type}`
Returns a specific location detail based on `{type}`.
- **Supported Types**: `ip`, `country`, `country_code`, `region`, `city`, `latitude`, `longitude`, `timezone`, `isp`, `asn`
- **Examples**:
- `@location://ip` → `"8.8.8.8"`
- `@location://city` → `"Mountain View"`
- `@location://country` → `"United States"`
#### Tool: `get_location()`
Generates a detailed Markdown table of geolocation data.
- **Fields**:
- IP
- Country
- Country Code
- Region
- City
- Latitude
- Longitude
- Timezone
- ISP
- ASN
- **Sample Output**:
```
| Field | Value |
|----------------|-------------------|
| IP | 8.8.8.8 |
| Country | United States |
| Country Code | US |
| Region | California |
| City | Mountain View |
| Latitude | 37.4223 |
| Longitude | -122.0848 |
| Timezone | America/Los_Angeles |
| ISP | GOOGLE |
| ASN | AS15169 |
```
#### Prompt: `where_am_i_prompt`
Predefined query: "Please tell me where I am based on my current IP address." Triggers `get_location()`.
### Examples in Claude Desktop
1. Install the server:
```bash
mcp install whereami_mcp.py --name "WhereAmI"
```
2. Query data:
- "My IP is `@location://ip`"
- "I’m in `@location://city`, `@location://country`"
3. Get full report:
- "Where am I?"
- `get_location()`
## License
MIT License. See [LICENSE](LICENSE) for details.
```
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
```toml
[project]
name = "whereami-mcp"
version = "0.1.0"
description = "A lightweight mcp server that tells you exactly where you are."
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
"httpx>=0.28.1",
"mcp[cli]>=1.4.1",
]
```
--------------------------------------------------------------------------------
/main.py:
--------------------------------------------------------------------------------
```python
# whereami_mcp.py
import httpx
from mcp.server.fastmcp import FastMCP, Context
# Initialize the MCP server
mcp = FastMCP("WhereAmI", dependencies=["httpx"])
# API endpoint from ipapi.co
API_URL = "https://ipapi.co/json/"
# Mapping of type to API field names
LOCATION_FIELDS = {
"ip": "ip",
"country": "country_name",
"country_code": "country_code",
"region": "region",
"city": "city",
"latitude": "latitude",
"longitude": "longitude",
"timezone": "timezone",
"isp": "org",
"asn": "asn"
}
@mcp.resource("location://{type}")
def get_location_data(type: str) -> str:
"""
Get specific location data based on the type parameter.
Supported types: ip, country, country_code, region, city, latitude, longitude, timezone, isp, asn
"""
if type not in LOCATION_FIELDS:
return f"Error: Invalid type '{type}'. Supported types: {', '.join(LOCATION_FIELDS.keys())}"
try:
response = httpx.get(API_URL)
response.raise_for_status()
data = response.json()
field = LOCATION_FIELDS[type]
return str(data[field])
except httpx.HTTPError as e:
return f"Error fetching location data: {str(e)}"
except KeyError:
return f"Error: Field '{field}' not found in API response"
@mcp.tool()
def get_location(ctx: Context) -> str:
"""
Get detailed location information based on current IP.
Returns a Markdown table containing:
- IP: The current public IP address
- Country: Full country name
- Country Code: Two-letter country code (ISO 3166-1 alpha-2)
- Region: State or region name
- City: City name
- Latitude: Geographic latitude coordinate
- Longitude: Geographic longitude coordinate
- Timezone: IANA timezone identifier
- ISP: Internet Service Provider name
- ASN: Autonomous System Number
"""
try:
# Make API request
response = httpx.get(API_URL)
response.raise_for_status()
data = response.json()
# Construct Markdown table
table = [
"| Field | Value |",
"|----------------|-------------------|",
f"| IP | {data['ip']} |",
f"| Country | {data['country_name']} |",
f"| Country Code | {data['country_code']} |",
f"| Region | {data['region']} |",
f"| City | {data['city']} |",
f"| Latitude | {data['latitude']} |",
f"| Longitude | {data['longitude']}|",
f"| Timezone | {data['timezone']} |",
f"| ISP | {data['org']} |",
f"| ASN | {data['asn']} |"
]
markdown_table = "\n".join(table)
ctx.info(f"Successfully retrieved location for IP: {data['ip']}")
return markdown_table
except httpx.HTTPError as e:
ctx.error(f"Failed to fetch location data: {str(e)}")
return f"Error: HTTP error occurred - {str(e)}"
except Exception as e:
ctx.error(f"Unexpected error: {str(e)}")
return f"Error: Unexpected error occurred - {str(e)}"
@mcp.prompt()
def where_am_i_prompt() -> str:
"""Prompt template for asking about current location"""
return "Please tell me where I am based on my current IP address."
if __name__ == "__main__":
mcp.run()
```