Skip to main content
Glama
mowaffak-alameen

armls-spark-mcp-server

ARMLS Spark MCP Server

Python proof-of-approach for connecting Claude to ARMLS Spark/FlexMLS data through MCP tools.

This project is scoped for an internal brokerage back-office Claude integration. It is not a public IDX display, and it does not include or claim access to live ARMLS data. Live operation requires valid ARMLS/Spark credentials, the client's license permissions, and field validation against the client's Spark metadata.

Current Status

This repository demonstrates the proposed MCP server shape before live ARMLS credentials are available:

  • FastMCP-based Python server with Streamable HTTP transport.

  • Starlette/Uvicorn ASGI deployment shape for Railway or Render.

  • Environment-based configuration for Spark credentials and an optional generic MCP bearer guard.

  • Spark API client abstraction with signed-session authentication helpers.

  • Mock mode with synthetic Spark-shaped responses for demos and tests.

  • Read-only MCP tool interfaces for listing search, listing lookup, comparable sales, market statistics, trends, and open houses.

  • Focused tests for filters, signing helper behavior, config behavior, bearer auth parsing, and mock outputs.

This is not a completed production integration against live ARMLS data. The live implementation step is to validate Spark field names, endpoint access, and license-safe output fields using client-provided credentials.

Related MCP server: mcp-server-attom

MCP Tools

The server exposes or scaffolds these tools:

  • search_active_listings: search by city, ZIP, list price range, property type, and status.

  • lookup_listing_by_mls_number: lookup by MLS number / ListingId.

  • pull_comparable_sales: closed-sale comps by address or coordinates, radius, date range, and property type.

  • get_market_statistics: price, DOM, sale-to-list ratio, and inventory statistics by city or ZIP.

  • pull_active_vs_sold_trend: active-vs-sold inventory trend by city or ZIP.

  • open_house_data_by_area: optional open-house lookup by city or ZIP using listing expansion.

Tool outputs are compacted before returning to Claude so responses stay usable in model context.

What Works In Mock Mode

Set SPARK_MOCK_MODE=true to run without Spark credentials. Mock mode returns synthetic data shaped like Spark responses and includes MockData=true markers in the payload.

Mock mode is useful for:

  • Inspecting the MCP server and tool schemas.

  • Testing Claude/Inspector connection behavior.

  • Demonstrating expected tool output shape.

  • Running local tests without ARMLS credentials.

Mock mode does not verify live ARMLS fields, live endpoint permissions, listing availability, or MLS compliance requirements.

What Requires Live Credentials

Set SPARK_MOCK_MODE=false and provide real Spark credentials to test live behavior:

  • Spark session creation and signed requests.

  • ARMLS Standard Fields names and searchable fields.

  • Property type/status values available to the client's Spark role.

  • Market statistics endpoint availability.

  • Open house data access and date-window behavior.

  • License-safe fields for internal brokerage use.

Setup

python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
cp .env.example .env

The default .env.example runs in mock mode and does not require credentials.

Environment Variables

Variable

Required

Notes

SPARK_MOCK_MODE

Yes

true for synthetic demo responses, false for live Spark calls.

SPARK_API_KEY

Live only

Client-provided Spark API key.

SPARK_API_SECRET

Live only

Client-provided Spark API secret.

SPARK_API_BASE_URL

Yes

Defaults to https://sparkapi.com.

SPARK_API_VERSION

Yes

Defaults to v1.

SPARK_TIMEOUT_SECONDS

Yes

HTTP timeout for Spark requests.

MCP_AUTH_TOKEN

Optional

Generic bearer guard for MCP clients that support custom Authorization headers. Not a direct Claude.ai static-token auth path.

PORT

Deploy/local

Defaults to 8000. Railway/Render may inject this.

CORS_ALLOW_ORIGINS

Optional

Comma-separated allowed browser origins if needed.

Never commit a real .env file or live Spark credentials.

Run Locally

source .venv/bin/activate
armls-mcp

The server starts on:

http://localhost:8000

Useful endpoints:

  • GET /health: service health.

  • GET /ready: lightweight readiness check.

  • POST/GET /mcp: Streamable HTTP MCP endpoint.

  • GET /sse: legacy SSE compatibility endpoint.

If MCP_AUTH_TOKEN is set, compatible MCP clients must send:

Authorization: Bearer <token>

This is useful for MCP Inspector, gateways, and clients that support custom headers. Claude.ai hosted custom connectors currently do not support user-pasted static bearer tokens.

Test

pytest

If using uv:

uv run pytest

Claude / MCP Connector Notes

For MCP Inspector:

npx -y @modelcontextprotocol/inspector

Choose Streamable HTTP and connect to:

http://localhost:8000/mcp

If MCP_AUTH_TOKEN is set for local testing, configure MCP Inspector with:

Authorization: Bearer <token>

For a hosted Claude connector, deploy the app over HTTPS and configure the connector URL as:

https://<service-host>/mcp

For Claude.ai hosted custom connectors, validate the connector authentication path before production. Current Claude connector documentation supports OAuth-style connector auth or no-auth servers; it does not support user-pasted static bearer tokens. The bearer guard in this repo should be treated as an interim proof-of-approach guard for Inspector, gateway testing, or non-Claude clients unless OAuth support is added.

Deployment Notes

Railway

  • Create a new service from this repository.

  • Set environment variables in Railway.

  • Use the included Procfile: web: armls-mcp.

  • Keep SPARK_MOCK_MODE=true until live credential testing begins.

  • For generic MCP clients, set MCP_AUTH_TOKEN before exposing the service URL.

  • For Claude.ai hosted connectors, validate OAuth-compatible auth or an approved no-auth/private access boundary before production.

Render

  • Runtime: Python 3.11+.

  • Build command: pip install -e ..

  • Start command: armls-mcp.

  • Set the same environment variables listed above.

  • Ensure the public endpoint is HTTPS.

  • Do not assume Claude.ai can pass a static bearer token; validate OAuth-compatible auth or an approved no-auth/private access boundary before production.

How To Add A New Tool

  1. Add a typed async function inside register_tools() in src/armls_mcp/tools.py.

  2. Decorate it with @mcp.tool().

  3. Keep inputs narrow and add Pydantic Field() descriptions.

  4. Use the Spark client abstraction instead of calling httpx from the tool.

  5. Compact large MLS responses before returning them to Claude.

  6. Add or update tests for filters, params, normalization, or mock output shape.

  7. Document any live Spark metadata assumptions.

Security Notes

  • Keep all credentials in environment variables.

  • Do not commit .env, private planning material, or credential screenshots.

  • Use MCP_AUTH_TOKEN only with clients or gateways that can send custom bearer headers.

  • For Claude.ai hosted connectors, implement an OAuth-compatible auth path or explicitly validate that no-auth mode is acceptable for the client's deployment boundary.

  • Keep tool outputs read-only and compact.

  • Do not expose private remarks, agent-only data, showing instructions, or other restricted MLS fields unless the client's ARMLS license explicitly permits it.

  • Review ARMLS/FBS rules before enabling any consumer-facing or IDX-like use.

  • Add rate limiting or gateway controls before broad team rollout.

Questions And Assumptions For Client Validation

  • Which Spark product/access level will be used, and does it allow the required listing, sold, market statistics, and open-house endpoints?

  • Which ARMLS Standard Fields should be used for status, MLS number, property type, address search, close date, close price, DOM, and ZIP/city filtering?

  • Are closed sales and market statistics available under the client's credentials?

  • Which fields are approved for internal Claude responses, and which must be suppressed?

  • Should comparable-sale search resolve addresses from MLS data only, or should a licensed geocoding service be added later?

  • What Claude connector auth mode should be used for production: OAuth/DCR/CIMD, Anthropic-held credentials, gateway-level controls, or a no-auth server behind an approved boundary?

  • What token rotation, access logging, and team access controls are required before production rollout?

Additional Documentation

F
license - not found
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mowaffak-alameen/armls-spark-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server