A powerful Model Context Protocol (MCP) server that provides comprehensive geolocation and network intelligence through MaxMindDB databases. Query GeoIP2, GeoLite2, and custom MMDB files with advanced filtering, stateful iteration, and automatic updates.
Important Notice: This is an unofficial project and is not endorsed by MaxMind Inc. This MCP server is an independent implementation. For official MaxMind products and support, please visit maxmind.com.
- Multiple Data Sources: MaxMind accounts, directory scanning, and GeoIP.conf compatibility
- Advanced Filtering: Query by any MMDB field with 11+ operators (equals, regex, comparisons, etc.)
- Stateful Iteration: Process large network ranges efficiently with resumable iterators
- Auto-updating: Automatic database downloads and updates from MaxMind
- File Watching: Dynamic loading of new/updated database files
- Flexible Configuration: TOML config with GeoIP.conf fallback support
go install github.com/oschwald/maxminddb-mcp/cmd/maxminddb-mcp@latest
git clone https://github.com/oschwald/maxminddb-mcp.git
cd maxminddb-mcp
go build -o maxminddb-mcp cmd/maxminddb-mcp/main.go
Create ~/.config/maxminddb-mcp/config.toml
:
mode = "maxmind"
auto_update = true
update_interval = "24h"
[maxmind]
account_id = 123456
license_key = "your_license_key_here"
editions = ["GeoLite2-City", "GeoLite2-Country", "GeoLite2-ASN"]
database_dir = "~/.cache/maxminddb-mcp/databases"
Claude Desktop
Add to your Claude Desktop configuration file:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%/Claude/claude_desktop_config.json
Linux: ~/.config/Claude/claude_desktop_config.json
{
"mcpServers": {
"maxminddb": {
"command": "maxminddb-mcp",
"env": {
"MAXMINDDB_MCP_CONFIG": "/path/to/your/config.toml"
}
}
}
}
Alternative with existing GeoIP.conf:
{
"mcpServers": {
"maxminddb": {
"command": "maxminddb-mcp"
}
}
}
Claude Code CLI
Add the MCP server to Claude Code CLI:
claude mcp add maxminddb maxminddb-mcp
To use with a custom config:
MAXMINDDB_MCP_CONFIG=/path/to/config.toml claude chat
Claude Code (VS Code Extension)
Install the Claude Code extension and add to VS Code settings:
{
"claude.mcpServers": {
"maxminddb": {
"command": "maxminddb-mcp",
"env": {
"MAXMINDDB_MCP_CONFIG": "/path/to/your/config.toml"
}
}
}
}
Continue
Install the Continue extension and add to your Continue configuration (~/.continue/config.json
):
{
"mcpServers": [
{
"name": "maxminddb",
"command": "maxminddb-mcp",
"env": {
"MAXMINDDB_MCP_CONFIG": "/path/to/your/config.toml"
}
}
]
}
Zed
Add to Zed settings (~/.config/zed/settings.json
):
{
"assistant": {
"mcp_servers": [
{
"name": "maxminddb",
"command": "maxminddb-mcp",
"env": {
"MAXMINDDB_MCP_CONFIG": "/path/to/your/config.toml"
}
}
]
}
}
Cline
Install Cline and add to VS Code settings:
{
"cline.mcpServers": {
"maxminddb": {
"command": "maxminddb-mcp",
"env": {
"MAXMINDDB_MCP_CONFIG": "/path/to/your/config.toml"
}
}
}
}
Gemini CLI
Add to your Gemini CLI configuration:
{
"mcpServers": {
"maxminddb": {
"command": "maxminddb-mcp",
"env": {
"MAXMINDDB_MCP_CONFIG": "/path/to/your/config.toml"
}
}
}
}
See the Gemini CLI MCP guide for more details.
Codex
Add to your Codex configuration file:
[mcp_servers.maxminddb]
command = "maxminddb-mcp"
env = { MAXMINDDB_MCP_CONFIG = "/path/to/your/config.toml" }
Or without custom config:
[mcp_servers.maxminddb]
command = "maxminddb-mcp"
Sourcegraph Cody
Add to Cody settings:
{
"cody.experimental.mcp": {
"servers": {
"maxminddb": {
"command": "maxminddb-mcp",
"env": {
"MAXMINDDB_MCP_CONFIG": "/path/to/your/config.toml"
}
}
}
}
}
LLM (Simon Willison)
Install the LLM tool and configure MCP:
# Install LLM
pip install llm
# Configure MCP server
llm mcp install maxminddb-mcp --command maxminddb-mcp
# Use with environment variable
MAXMINDDB_MCP_CONFIG=/path/to/config.toml llm chat -m claude-3.5-sonnet
Python SDK
pip install mcp
from mcp import ClientSession, StdioServerParameters
async with ClientSession(
StdioServerParameters(
command="maxminddb-mcp",
env={"MAXMINDDB_MCP_CONFIG": "/path/to/config.toml"}
)
) as session:
await session.initialize()
tools = await session.list_tools()
result = await session.call_tool("lookup_ip", {"ip": "8.8.8.8"})
TypeScript SDK
npm install @modelcontextprotocol/sdk
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
const transport = new StdioClientTransport({
command: "maxminddb-mcp",
env: { MAXMINDDB_MCP_CONFIG: "/path/to/config.toml" },
});
const client = new Client(
{
name: "maxminddb-client",
version: "1.0.0",
},
{ capabilities: {} }
);
await client.connect(transport);
const result = await client.callTool({
name: "lookup_ip",
arguments: { ip: "8.8.8.8" },
});
Go SDK
go get github.com/mark3labs/mcp-go
import (
"github.com/mark3labs/mcp-go/client"
"github.com/mark3labs/mcp-go/transport/stdio"
)
cmd := exec.Command("maxminddb-mcp")
cmd.Env = append(cmd.Env, "MAXMINDDB_MCP_CONFIG=/path/to/config.toml")
transport := stdio.NewTransport(cmd)
mcpClient := client.New(transport)
// ... use client
Command Line Testing
Test the server directly using JSON-RPC:
# List available tools
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | maxminddb-mcp
# Test IP lookup
echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"lookup_ip","arguments":{"ip":"8.8.8.8"}}}' | maxminddb-mcp
# Pretty output with jq
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | maxminddb-mcp | jq .
Path Requirements: Ensure maxminddb-mcp
is in your system PATH or provide the full path to the binary.
Environment Variables: All clients support these environment variables:
MAXMINDDB_MCP_CONFIG
: Path to configuration fileMAXMINDDB_MCP_LOG_LEVEL
: Logging level (debug
,info
,warn
,error
)MAXMINDDB_MCP_LOG_FORMAT
: Log format (text
,json
)
Security: Store sensitive configuration (API keys) in files with appropriate permissions (600) rather than environment variables in client configs.
The server supports three configuration modes (checked in order):
- Environment variable:
MAXMINDDB_MCP_CONFIG
- User config:
~/.config/maxminddb-mcp/config.toml
- GeoIP.conf compatibility:
/etc/GeoIP.conf
or~/.config/maxminddb-mcp/GeoIP.conf
Complete configuration example
# Operation mode: "maxmind", "directory", or "geoip_compat"
mode = "maxmind"
# Auto-update settings
auto_update = true
update_interval = "24h"
# Iterator settings
iterator_ttl = "10m"
iterator_cleanup_interval = "1m"
# Logging (optional)
log_level = "info" # debug, info, warn, error
log_format = "text" # text, json
[maxmind]
# MaxMind account credentials
account_id = 123456
license_key = "your_license_key_here"
# Databases to download
editions = [
"GeoLite2-City",
"GeoLite2-Country",
"GeoLite2-ASN",
"GeoIP2-City",
"GeoIP2-Country"
]
# Storage location
database_dir = "~/.cache/maxminddb-mcp/databases"
# Custom endpoint (optional)
# endpoint = "https://updates.maxmind.com"
[directory]
# For directory mode - scan these paths for MMDB files
paths = [
"/path/to/mmdb/files",
"/another/path"
]
[geoip_compat]
# For GeoIP.conf compatibility mode
config_path = "/etc/GeoIP.conf"
database_dir = "/var/lib/GeoIP"
Iterator Settings:
iterator_ttl
(default: "10m"): How long idle iterators are kept before cleanupiterator_cleanup_interval
(default: "1m"): How often to check for expired iterators
Existing GeoIP.conf users
The server automatically detects and uses existing GeoIP.conf files:
# Example GeoIP.conf
AccountID 123456
LicenseKey your_license_key_here
EditionIDs GeoLite2-Country GeoLite2-City GeoLite2-ASN
DatabaseDirectory /var/lib/GeoIP
No additional configuration needed - the server will automatically use compatibility mode.
Look up geolocation and network information for a specific IP address.
Parameters:
ip
(required): IP address to lookup (IPv4 or IPv6)database
(optional): Specific database filename to query
Example:
{
"name": "lookup_ip",
"arguments": {
"ip": "8.8.8.8",
"database": "GeoLite2-City.mmdb"
}
}
Response:
{
"ip": "8.8.8.8",
"network": "8.8.8.0/24",
"data": {
"country": {
"iso_code": "US",
"names": { "en": "United States" }
},
"location": {
"latitude": 37.4056,
"longitude": -122.0775
}
}
}
Query all IP addresses in a network range with powerful filtering capabilities.
Parameters:
network
(required): CIDR network to scan (e.g., "192.168.1.0/24")database
(optional): Specific database to queryfilters
(optional): Array of filter objects. Each object must includefield
,operator
, andvalue
.filter_mode
(optional): "and" (default) or "or"max_results
(optional): Maximum results to return (default: 1000)iterator_id
(optional): Resume existing iteratorresume_token
(optional): Fallback token for expired iterators
Filtering Examples
Filter by country:
{
"name": "lookup_network",
"arguments": {
"network": "10.0.0.0/8",
"filters": [
{
"field": "country.iso_code",
"operator": "in",
"value": ["US", "CA", "MX"]
}
]
}
}
Filter residential IPs:
{
"name": "lookup_network",
"arguments": {
"network": "192.168.0.0/16",
"filters": [
{
"field": "traits.user_type",
"operator": "equals",
"value": "residential"
}
]
}
}
Common mistakes and validation
- Do not pass filters as strings like
"traits.user_type=residential"
. The server rejects this withinvalid_filter
and a hint to use objects:{ "field": "traits.user_type", "operator": "equals", "value": "residential" }
. filters
must be an array of objects; other types are invalid.operator
must be supported (see list below). Short aliases (eq
,ne
,gt
,gte
,lt
,lte
) are also accepted.
Complex filtering (non-proxy IPs):
{
"name": "lookup_network",
"arguments": {
"network": "10.0.0.0/24",
"filters": [
{
"field": "traits.is_anonymous_proxy",
"operator": "equals",
"value": false
},
{
"field": "traits.is_satellite_provider",
"operator": "equals",
"value": false
}
],
"filter_mode": "and"
}
}
List all available MaxMind databases with metadata.
Example:
{
"name": "list_databases",
"arguments": {}
}
Response:
{
"databases": [
{
"name": "GeoLite2-City.mmdb",
"type": "City",
"description": "GeoLite2 City Database",
"last_updated": "2024-01-15T10:30:00Z",
"size": 67108864
}
]
}
Manually trigger database updates (MaxMind/GeoIP modes only).
Example:
{
"name": "update_databases",
"arguments": {}
}
Supported Operators:
equals
: Exact matchnot_equals
: Not equal to valuein
: Value is in provided arraynot_in
: Value is not in provided arraycontains
: String contains substringregex
: Matches regular expressiongreater_than
: Numeric comparisongreater_than_or_equal
: Numeric comparison (≥)less_than
: Numeric comparisonless_than_or_equal
: Numeric comparison (≤)exists
: Field exists (boolean value)
Operator Aliases: For convenience, short operator aliases are supported (case-insensitive):
eq
→equals
ne
→not_equals
gt
→greater_than
gte
→greater_than_or_equal
lt
→less_than
lte
→less_than_or_equal
All tools return structured error responses with machine-readable error codes:
{
"error": {
"code": "db_not_found",
"message": "Database not found: invalid_db.mmdb"
}
}
Common Error Codes:
db_not_found
: Specified database does not existinvalid_ip
: IP address format is invalidinvalid_network
: Network CIDR format is invalidinvalid_filter
: Filter validation failediterator_not_found
: Iterator ID not found or expiredparse_error
: Failed to parse request parameters
For large network queries, the server uses a stateful iterator system:
- Fast Path: Resume active iterations using
iterator_id
- Resilient Path: Resume from
resume_token
after expiration - Automatic Cleanup: Expired iterators cleaned up after TTL
- Efficient Skip: Skip to resume point without re-processing
Example iteration workflow:
// First call - creates iterator
{
"name": "lookup_network",
"arguments": {
"network": "10.0.0.0/8",
"max_results": 1000
}
}
// Response includes iterator_id for continuation
{
"results": [...],
"iterator_id": "iter_abc123",
"resume_token": "eyJ0eXAiOiJKV1Q...",
"has_more": true
}
// Continue with iterator_id (fast path)
{
"name": "lookup_network",
"arguments": {
"network": "10.0.0.0/8",
"iterator_id": "iter_abc123",
"max_results": 1000
}
}
Automatic database updates
Configure automatic updates in your TOML config:
auto_update = true
update_interval = "24h" # Check every 24 hours
The server will:
- Check for database updates on the specified interval
- Download only if MD5 checksums have changed
- Gracefully reload databases without interrupting active queries
- Log update status and any errors
Manual Updates:
Use the update_databases
tool to trigger immediate updates.
Directory mode with file watching
In directory mode, the server watches for filesystem changes:
mode = "directory"
[directory]
paths = ["/path/to/mmdb/files"]
Supported events:
- Create: Automatically loads new MMDB files
- Write: Reloads modified databases
- Remove: Removes databases from available list
- Rename: Handles file renames gracefully
Subdirectory support: Recursively watches all subdirectories for MMDB files.
Server not starting
Check configuration:
# Verify config file syntax
maxminddb-mcp --help
# Test configuration loading
MAXMINDDB_MCP_LOG_LEVEL=debug maxminddb-mcp
Common causes:
- Invalid TOML syntax in config file
- Missing MaxMind credentials
- Insufficient file permissions
- Invalid database directory path
Database loading failures
Check database status:
# Enable debug logging
MAXMINDDB_MCP_LOG_LEVEL=debug maxminddb-mcp
Common causes:
- Corrupt MMDB files (check file integrity)
- Insufficient disk space for downloads
- Network connectivity issues to updates.maxmind.com
- Expired MaxMind subscription
Claude Desktop integration
Verify server path:
# Check server is in PATH
which maxminddb-mcp
# Test server directly
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' | maxminddb-mcp
Configuration file locations:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json
- Windows:
%APPDATA%/Claude/claude_desktop_config.json
Enable detailed logging for troubleshooting:
# Environment variables
MAXMINDDB_MCP_LOG_LEVEL=debug
MAXMINDDB_MCP_LOG_FORMAT=json
# Or in config.toml
log_level = "debug"
log_format = "json"
The server validates all configuration on startup and provides detailed error messages:
- Required fields for each mode
- Valid duration formats (e.g., "24h", "10m")
- Path expansion and validation
- Network connectivity checks
- Base memory: ~50MB
- Database storage: 100-500MB depending on editions
- Avoid unnecessary iterations: use selective filters and appropriate
max_results
- Database selection: Only download needed editions to reduce memory usage
- Update frequency: Balance freshness vs. network usage with
update_interval
- Filter efficiency: Use selective filters early to reduce processing
- Concurrent iterators: No hard limit, managed by TTL cleanup
- Network query size: Limited by available memory and
max_results
- Database file size: Supports databases up to several GB
This project is licensed under the ISC License - see the LICENSE file for details.
Contributions are welcome! Please read our Contributing Guide for details on how to submit pull requests, report issues, and suggest improvements.
- Issues: GitHub Issues
- Discussions: GitHub Discussions