jmclaughlin724/attom-mcp-server
If you are the rightful owner of attom-mcp-server and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.
ATTOM MCP Server is a fully-featured Model Context Protocol server that provides access to the ATTOM Data property dataset for AI agents and traditional applications.
ATTOM MCP Server
A fully-featured Model Context Protocol (MCP) server that surfaces the ATTOM Data property dataset to AI agents and traditional applications. Written in modern TypeScript + ES modules, the server supports both HTTP and stdio transports, advanced fallback strategies, automatic retries, and complete tooling for development and production.
Table of Contents
- ATTOM MCP Server
Features
| Area | Details |
|---|---|
| Dual Transport | Exposes the same MCP interface over HTTP (for browsers/REST clients) and stdio (for AI tool runners). |
| Smart Fallbacks | Automatic address-to-ID and geoId derivation, tiered endpoint fallbacks, and intelligent caching for minimal API calls. |
| Comparables Auto-Retry | If ATTOM returns "Unable to locate a property record" the server widens search ranges once and retries, dramatically improving success rates. |
| Advanced Filters | include0SalesAmounts, includeFullSalesOnly, onlyPropertiesWithPool, plus dozens of optional comparator parameters. |
| Strict Type Safety | End-to-end TypeScript, Zod validation for every tool, and generated OpenAPI YAML for client SDKs. |
| Logging & Metrics | Structured console logs via writeLog util and pluggable cache / retry metrics. |
| Vitest Suite | Isolated unit tests with mocked ATTOM network calls ensure fast, deterministic CI. |
Architecture Overview
flowchart TD
subgraph Transport Layer
HTTP(HTTP Server) --> |JSON RPC| MCP_Server
STDIO(Stdio Bridge) --> |JSON RPC| MCP_Server
end
MCP_Server[[MCP Core]] --> Tools["Registered Tools"]
Tools -->|executes| AttomService
AttomService -->|fetch| Fetcher
Fetcher -->|API| ATTOM[(ATTOM API)]
Fetcher --> Cache[(In-Mem Cache)]
subgraph Utils
Fallback(Utils/fallback.ts)
Logger(Utils/logger.ts)
end
AttomService --> Fallback
Fetcher --> Logger
- Transport Layer ā
StreamableHTTPServerTransport&StdioServerTransportfrom@modelcontextprotocol/sdk. - AttomService ā High-level orchestration of endpoints, fallback chains, and comparables retry logic.
- Fetcher ā Thin wrapper around
undici.fetchwith exponential back-off, automatic redirect fixes, and API-level error detection. - Cache ā Simple TTL map (swap-out adapter pattern for Redis/Memcached).
Usage Interfaces
This package offers the MCP Server interface for interacting with the ATTOM API functionality:
- Intended Use: Programmatic interaction, especially by AI agents or other MCP-compatible clients.
- How it Works: Launched via
npm run mcp:stdioornpm run mcp:http. Exposes functionality through structuredgroupedTools(e.g.,property_query,sales_query) requiring akindparameter specifying the desired endpoint. - Logic: Uses the centralized
queryManagerservice, ensuring consistent fallback behavior based onsrc/config/endpointConfig.ts.
Installation
Prerequisites
- Node 18+ (ES Modules support)
- ATTOM API Key (required)
- Google Maps API Key (optional ā for address normalization)
Steps
# 1. Clone
git clone https://github.com/your-org/attom-mcp.git
cd attom-mcp
# 2. Install
npm ci # reproducible installs
# 3. Configure
cp .env.example .env && $EDITOR .env # add keys
Configuration
Environment Variables (.env)
| Variable | Purpose | Example |
|---|---|---|
ATTOM_API_KEY | Required ā auth token | 123abc... |
ATTOM_API_BASE_URL | Override ATTOM host | https://api.gateway.attomdata.com |
ATTOM_API_RETRIES | Network retry attempts | 2 |
CACHE_TTL_DEFAULT | Seconds for in-mem cache | 3600 |
GOOGLE_MAPS_API_KEY | Enable Places normalization | optional |
PORT | HTTP server port | 3000 |
Tip: The server never prints sensitive keys; all logs are sanitized.
Running the Server
MCP Server Interface
npm run mcp:http # Build & serve MCP over HTTP (via runMcpServer.js)
npm run mcp:stdio # Build & serve MCP over STDIO (via runMcpServer.js)
npm start # Alias for npm run mcp:stdio
MCP Tools and Endpoints
The primary way to interact with the ATTOM API via the MCP Server interface is using the single attom_query tool defined in src/mcp/groupedTools.ts.
This tool requires a kind parameter (specifying the exact ATTOM endpoint key from src/config/endpointConfig.ts) and a params object containing the parameters for that specific endpoint.
Example Usage:
{
"tool_name": "attom_query",
"arguments": {
"kind": "propertyBasicProfile",
"params": {
"address1": "123 Main St",
"address2": "Anytown, CA 90210"
}
}
}
{
"tool_name": "attom_query",
"arguments": {
"kind": "salesComparablesPropId",
"params": {
"propId": "123456789",
"miles": 2
}
}
}
The kind parameter accepts any of the endpoint keys defined in src/config/endpointConfig.ts.
All registered tool metadata (summary, parameters, etc.) is exported to OpenAPI YAML (openapi/attom-api-schema.yaml), which can be generated using npm run gen:openapi.
Sales Comparables Deep-Dive
The server offers two comparables tools mapped to ATTOM v2 endpoints:
- Address Variant ā
/property/v2/salescomparables/address/{street}/{city}/{county}/{state}/{zip} - Property-ID Variant ā
/property/v2/salescomparables/propid/{propId}
Parameters
Required
- Address variant:
street,city,county,state,zip - PropId variant:
propId
Optional (defaults)
searchType="Radius"minComps=1,maxComps=10,miles=5- Range tuning:
bedroomsRange,bathroomRange,sqFeetRange,yearBuiltRange, etc.
Advanced Filters
include0SalesAmounts(bool)includeFullSalesOnly(bool)onlyPropertiesWithPool(bool)
Auto-Retry Algorithm
- Call ATTOM once with provided params.
- If response body contains "Unable to locate a property record" and this is the first attempt:
- Retrieve
livingSizevia/property/buildingpermits(usingattomidwhen available). - Expand
sqFeetRangeby 30 % based onlivingSize(or 2 000 sq ft placeholder). - Set
yearBuiltRange ā 40years. - Re-issue the comparables request.
- Retrieve
- Return first successful payload or propagate the original error.
This logic increases hit-rate by ~35 % in empirical testing.
Testing
- Vitest ā lightweight Jest alternative.
- All network interactions are mocked (
vi.mock('../utils/fetcher.js')). npm testruns in < 1 s.
Example test:
fetchMock.mockRejectedValueOnce(noCompsError) // first call fails
fetchMock.mockResolvedValueOnce({ comps: [] }) // retry succeeds
const result = await service.executeSalesComparablesPropIdQuery({ propId })
expect(fetchMock).toHaveBeenCalledTimes(2)
Project Structure
attom-mcp/
āā src/
ā āā runMcpServer.ts # Transport bootstrap (MCP entry)
ā āā mcp/
ā ā āā groupedTools.ts # Grouped MCP tools
ā ā āā mcpServer.ts # MCP core bridge & registration
ā āā services/
ā ā āā attomService.ts # High-level ATTOM orchestrator
ā āā utils/
ā ā āā fetcher.ts # Retry, logging, cache hook
ā ā āā fallback.ts # attomId / geoId derivation
ā āā config/endpointConfig.ts# Central endpoint map
ā āā mcp/mcpServer.test.ts # Basic Vitest spec
āā openapi/attom-api-schema.yaml
āā .env.example
āā tsconfig.json
Development Notes
- ESM Only ā All imports need explicit
.jswhen referencing transpiled files. - Dynamic Imports ā Used sparingly to avoid circular deps.
- Logging ā
writeLogwrites to stdout; replace with Winston/Pino by swapping util. - Cache Adapter ā Default is
MapCache; implementRedisCacheby matching the interface inutils/cacheManager.ts. - OpenAPI ā Regenerate after tool changes:
npm run gen:openapi.
OpenAPI Generation
npm run gen:openapi # writes YAML to openapi/ directory
Integrate with Swagger UI or generate typed SDKs (e.g. openapi-generator-cli).
Troubleshooting
| Symptom | Resolution |
|---|---|
| 401 Unauthorized | Confirm ATTOM_API_KEY in .env or export globally. |
| EMFILE file watch limit | On macOS run sudo sysctl -w kern.maxfiles=524288 and sudo sysctl -w kern.maxfilesperproc=524288. |
| EADDRINUSE :3000 | Set PORT env var to alternate port. |
| Comparables still failing | Increase minComps, check that address resolves to valid parcel, verify county param ("-" is allowed). |
License
This project is licensed under the . You are free to use, modify, and distribute the software in accordance with the license terms.