Skip to main content
Glama
sanjibani

storedge-mcp

by sanjibani

storedge-mcp

Tests Python License MCP

The first MCP server for StorEdge (Storable Edge) - the self-storage management platform that 5,000+ storage facilities rely on.

Read and write tenants, units, leads, ledgers, move-ins/outs, insurance, tasks, and surcharge calculations for a self-storage facility - straight from Claude, Cursor, or any MCP client.


Why this exists

StorEdge is the operations backbone for tens of thousands of self-storage facilities (under the Storable / Red Nova Labs umbrella). Its REST API at api.storedgefms.com powers tenant management, lead tracking, billing, insurance enrollment, task workflows, and move-in/out pipelines.

The existing integration options all require building OAuth 1.0 signing + paginated list handling + typed-error mapping from scratch every time:

  • Tray.ai connector - locked inside Tray's walled garden, no MCP, no local-first.

  • Twilio integration - single-purpose, voice-channel only.

  • Java/PHP/.NET sample clients (rednovalabs/storedge-api-client-*) - boilerplate code, no Claude tool surface.

  • No first-party MCP server - StorEdge has not shipped one.

storedge-mcp is the open MCP surface. One stdio call away, agents can answer "what 10x10 units are available right now?", "create a reservation for unit A-12", "show me who's past due this week", and "calculate the surcharge for a $125 Visa payment".


Quick start

pip install -e .
export STOREDGE_CONSUMER_KEY=...      # from StorEdge dashboard
export STOREDGE_CONSUMER_SECRET=...   # from StorEdge dashboard
export STOREDGE_FACILITY_ID=<uuid>    # optional; tools accept it as arg too
storedge-mcp

In Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "storedge": {
      "command": "storedge-mcp",
      "env": {
        "STOREDGE_CONSUMER_KEY": "...",
        "STOREDGE_CONSUMER_SECRET": "...",
        "STOREDGE_FACILITY_ID": "..."
      }
    }
  }
}

Tools (26)

Diagnostic

  • health_check(facility_id?) - verify credentials by listing one tenant. Returns fast-fail if OAuth signing is wrong.

Tenants

  • list_tenants(facility_id?, per_page?, page?, created_after?, created_before?, updated_since?, only_ids?)

  • list_current_tenants(facility_id?, per_page?, page?) - only currently-active tenants

  • search_tenants(account_code?, phone_number?, facility_id?) - by account code OR phone (exactly one)

  • get_tenant(tenant_id, facility_id?)

  • get_tenant_ledgers(tenant_id, facility_id?) - list of a tenant's rental agreements

  • get_tenant_notes(tenant_id, facility_id?) - operator notes attached to a tenant

Units

  • list_units(facility_id?, per_page?, page?, only_ids?) - every unit (rented + vacant + offline)

  • list_available_units(facility_id?, per_page?, page?) - only units available for move-in

  • get_unit(unit_id, facility_id?)

  • list_unit_groups(facility_id?, per_page?, page?) - size buckets (5x5, 10x10, etc.)

  • list_unit_types(facility_id?, per_page?, page?) - Parking, Climate, Drive-Up, etc.

Leads

  • list_leads(view="current", facility_id?, per_page?, page?) - view ∈ {current, reservations, inquiries, follow_up, waitlist, missed_move_ins}

  • get_lead_counts(facility_id?) - open lead counts by status

  • get_lead(lead_id, facility_id?)

  • create_lead(lead, facility_id?) - create a reservation or inquiry

  • update_lead(lead_id, lead, facility_id?) - PATCH an existing lead

Ledgers (rental agreements)

  • list_current_ledgers(facility_id?, per_page?, page?)

  • get_ledger(ledger_id, facility_id?)

  • get_ledger_delinquency(ledger_id, facility_id?) - overdue balance + days late

  • get_ledger_invoices(ledger_id, facility_id?)

Insurance

  • get_insurance_summary(facility_id?) - counts + revenue rollup

  • get_insurance_activity(facility_id?, per_page?, page?)

Tasks

  • list_tasks(category_id?, facility_id?, per_page?, page?)

  • list_task_categories(facility_id?)

  • create_task(task, facility_id?)

  • complete_task(task_id, facility_id?)

Move-in / move-out pipeline

  • list_move_ins(facility_id?, per_page?, page?) - in-progress move-ins

  • list_move_outs(facility_id?, per_page?, page?) - scheduled move-outs

Surcharge + invoices

  • calculate_surcharge(amount_cents, card_type?, facility_id?) - credit-card convenience fee quote

  • list_invoices_and_ledgers(facility_id?, per_page?, page?)


Auth

OAuth 1.0 one-legged (RFC 5849). Get your consumer key + secret from StorEdge dashboard → Corporate → Settings → API.

storedge-mcp ships its own OAuth 1.0 signer - not authlib's - because authlib's stock OAuth1Auth strips JSON request bodies during signing (silently breaking POST/PATCH/PUT). Our signer computes oauth_body_hash for non-form bodies and includes it in the signature per RFC 5849 §3.4.1.3.


Architecture

Built on industry-leading patterns from encode/httpx, stripe-python, lepture/authlib, boto3, pytest-dev/pytest, and astral-sh/ruff:

  • Shared httpx.AsyncClient with pooling + transport-level retries.

  • Typed exception hierarchy (StoredgeAuthError, StoredgeNotFoundError, StoredgeRateLimitError, StoredgeAPIError, StoredgeConnectionError) carrying structured error_code (from StorEdge's meta.error_code envelope) and request_id.

  • Application-level retry with exponential backoff + full jitter on 429/5xx, honoring Retry-After.

  • isError-compliance - every tool re-raises on failure so FastMCP sets isError: true on the wire (Blackwell audit / MCPTox).

  • JSONL audit logging via STOREDGE_AUDIT_LOG env var (or stderr default) - every tool call emits a structured record with redaction for password/api_key/token fields.

  • Property-based tests (Hypothesis) for JSON round-trips.

  • respx for httpx mocking - no live API calls in tests.

See engineering-playbook.md for the full pattern reference.


Development

python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

# Lint + type check + test
ruff check src tests
mypy src tests
pytest

# Coverage
pytest --cov=storedge_mcp --cov-report=term-missing

CI matrix (Python 3.10-3.13 on ubuntu/macos/windows) lives in .github/workflows/ci.yml.


Sister projects

sanjibani publishes MCP servers for one niche vertical SaaS per day. See the full list for the rest:

  • hawksoft-mcp - independent insurance agencies

  • open-dental-mcp - dental practice mgmt

  • ezyvet-mcp - veterinary

  • jobber-mcp - home service / field service

  • practicepanther-mcp - legal practice (solo/small)

  • realm-mp-mcp - church / nonprofit

  • fieldroutes-mcp - pest control / lawn care

  • cox-automotive-mcp - auto dealership

  • qualia-mcp - title and escrow

  • campspot-mcp - outdoor hospitality (campgrounds)

  • cleancloud-mcp - laundry / dry cleaning

  • playmetrics-mcp - youth sports clubs

  • foreup-mcp - golf course management

Need a custom MCP for your vertical SaaS stack? → mcp-services.landing.


License

MIT


References

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/sanjibani/storedge-mcp'

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