Install
$ agentstack add mcp-sharpsir-group-qobrix-crm-mcp ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Qobrix CRM MCP Server
Connect Claude, Cursor, and other MCP clients to your Qobrix real-estate CRM — listings, leads, viewings, offers, contracts, and activity in one read-only Model Context Protocol layer. 46 tools (CRM entities + analytics + cache controls), RESO Data Dictionary 2.0 workflows, optional Redis-backed response caching, and 167 automated tests.
GitHub · Qobrix CRM · MCP specification · RESO DD 2.0
Table of contents
- [What it does](#what-it-does)
- [Who it is for](#who-it-is-for)
- [Canonical real-estate workflows](#canonical-re-workflows)
- [Tools at a glance](#tools-at-a-glance)
- [Quick start](#quick-start)
- [Configuration](#configuration)
- [Caching](#caching)
- [Cursor IDE setup](#cursor-ide-setup)
- [Other MCP hosts](#other-mcp-hosts)
- [Search expression syntax](#search-expression-syntax)
- [Fetching related data](#fetching-related-data)
- [Testing](#testing)
- [Architecture](#architecture)
- [How the LLM learns](#how-the-llm-learns)
- [Technology](#technology)
- [License](#license)
What It Does
An AI assistant connected to this server can browse properties, qualify leads, track showings, review offers and contracts, audit follow-up activity, and discover CRM field schemas — all through natural language. Every tool description teaches the LLM which canonical real-estate workflow it belongs to, which RESO resource it maps to, and which tools to chain next.
Who it is for
- Brokerages & developers using Qobrix who want ChatGPT, Claude, or Cursor to answer questions grounded in live CRM data (not copy-pasted exports).
- Engineers wiring MCP into internal tools: stdio transport, typed Zod inputs, and no write surface — safe to experiment with prompts and agents.
- Data & operations teams running dashboards: use
qobrix_count/qobrix_top_valuesfor YoY-style metrics without custom scripts, and response caching to cut API load on repeat queries.
Canonical RE Workflows
The server is organized around six RESO-aligned business processes. The LLM receives these as built-in instructions so it can navigate the CRM without prior training.
| # | Workflow | RESO Mapping | Key Tools | |---|----------|-------------|-----------| | 1 | Listing Lifecycle | Property.StandardStatus | search_properties, get_property, list_media, get_property_coordinates | | 2 | Lead-Contact Lifecycle | Contacts.ContactType funnel | search_opportunities, get_contact, search_tasks | | 3 | Sales Pipeline | 8-stage buyer journey | get_leads_by_property, get_lead_properties, list_viewings, list_offers, list_contracts | | 4 | Showing / Viewing | ShowingAppointment | list_viewings, get_viewing, list_meetings | | 5 | Transaction / Offer | TransactionManagement | list_offers, get_offer, list_contracts, get_contract | | 6 | Activity / Follow-up | Engagement tracking | list_calls, list_meetings, list_email_messages, search_tasks |
Status Mappings
| Qobrix Property Status | RESO StandardStatus | |------------------------|---------------------| | available | Active | | reserved | Pending / Under Contract | | sold | Closed | | withdrawn | Withdrawn / Canceled |
| Qobrix Opportunity Status | RESO Lead Funnel | |--------------------------|------------------| | new | MQL / Raw Lead | | open | SQL / Active | | won | Closed Won | | closed_lost | Lost |
Tools at a Glance
56 read-only tools — CRM entities, schema discovery, analytics (qobrix_count, qobrix_top_values, qobrix_top_records, qobrix_aggregate), a flexible deals shortcut (qobrix_deals), reporting (qobrix_timeseries, qobrix_funnel, qobrix_rep_scorecard, qobrix_stale_leads, qobrix_win_loss, qobrix_days_on_market), customer intelligence (qobrix_cohort), and cache helpers (qobrix_cache_stats, qobrix_cache_clear):
| Entity Group | Tools | Capabilities | |-------------|-------|-------------| | Properties | 5 | List, Get, Search, Coordinates (map), Properties-by-Lead | | Contacts | 3 | List, Get, Search | | Agents | 3 | List, Get, Search | | Opportunities / Leads | 5 | List, Get, Search, Leads-by-Property, Lead-Properties | | Property Viewings | 3 | List, Get, Search | | Tasks | 3 | List, Get, Search | | Media | 2 | List (with entity filter), Get (with size variants) | | Projects | 4 | List, Get, Search, Coordinates | | Offers | 3 | List, Get, Search | | Contracts | 3 | List, Get, Search | | Calls | 2 | List, Get | | Meetings | 2 | List, Get | | Email Messages | 2 | List, Get | | Schema / Meta | 2 | Get Schema (field discovery), Get Field Options (enum values) | | Analytics | 4 | Counts, top-N field values, top-N records by numeric/date, and sum/avg/min/max/count aggregates (with single- or multi-dim grouping) — bypasses the Qobrix sort quirk on calculated/nullable fields | | Deals | 1 | Flexible domain shortcut over the Contracts table (sales, rentals, listings, pipeline) with kind / contracttypes[] / contractstatuses[] / datefield / minprice / party filters / summary block | | Reporting | 6 | Time-series with YoY (qobrix_timeseries), canonical sales funnel + conversion % (qobrix_funnel), per-rep scorecard / agent leaderboard (qobrix_rep_scorecard), silent-lead detection (qobrix_stale_leads), win-rate analytics (qobrix_win_loss), days-on-market (qobrix_days_on_market) | | Customers | 1 | Repeat-buyer / seller / lead cohorts (qobrix_cohort) — find contacts that appear on multiple closed deals or opportunities | | Cache | 2 | Stats and prefix or full invalidation for fresher reads |
Every tool description includes its canonical workflow role, RESO equivalent, verified include[] options, FK resolution guidance, and search expression examples.
Analytics & Deals usage examples
The Qobrix REST API silently ignores sort on some calculated/nullable numeric fields (notably contracts.final_selling_price_amount and opportunities.budget), and "closed deals" don't actually live as a single property flag — they're rows in the Contracts table. The three new tools remove the need for client-side scripting:
// 1) Top 5 closed 2026 sales, sorted by final_selling_price_amount,
// with property + agent + lawyers resolved to readable names.
{
"tool": "qobrix_top_records",
"args": {
"resource": "contracts",
"sort_by": "final_selling_price_amount",
"search": "contract_type == \"cos\" and contract_status == \"agreed\" and date_of_contract >= \"2026-01-01\" and date_of_contract = \"2026-01-01\" and date_of_contract = \"2026-01-01\" and date_of_contract /.cursor/mcp.json`** | You opened that project folder in Cursor; teammates can commit a template (without secrets) or you keep it local-only. |
| **`~/.cursor/mcp.json`** | Same MCP on every workspace on that machine. |
Merge your entry into the existing `"mcpServers"` object; do not replace the whole file if you already have other servers.
#### 4. Recommended: `node --env-file` (Node 20+)
Pass **absolute paths** so it works the same whether the workspace root is this repo or a parent folder (and so SSH remote paths resolve correctly).
```json
{
"mcpServers": {
"qobrix-crm-mcp": {
"command": "node",
"args": [
"--env-file=/absolute/path/to/qobrix-crm-mcp/.env",
"/absolute/path/to/qobrix-crm-mcp/dist/index.js"
],
"description": "Read-only Qobrix CRM MCP"
}
}
}
Why this pattern:
- Credentials stay in
.env, not in JSON. - Node loads the file before your server starts, so
process.envis populated even when the host’senvFilefield is ignored or behaves inconsistently for stdio servers.
5. Alternative: inline env
Useful if you cannot use --env-file (older Node). Secrets live in mcp.json — restrict file permissions and do not commit them.
{
"mcpServers": {
"qobrix-crm-mcp": {
"command": "node",
"args": ["/absolute/path/to/qobrix-crm-mcp/dist/index.js"],
"env": {
"QOBRIX_API_URL": "https://yourcrm.qobrix.com",
"QOBRIX_API_USER": "your-api-user-uuid",
"QOBRIX_API_KEY": "your-api-key",
"QOBRIX_LOCALE": "en-US"
}
}
}
}
You can also use Cursor’s config interpolation (for example ${env:QOBRIX_API_KEY}) so values are injected from your OS environment instead of literals.
6. Optional: envFile in MCP JSON
Cursor supports an envFile property for stdio servers. Some setups do not pass those variables into the child process reliably; if tools fail with “Missing required environment variables”, switch to --env-file as in step 4.
7. After editing mcp.json or .env
- Reload MCP — Command Palette → MCP restart, or reload the Cursor window.
- Check logs — View → Output → pick “MCP” / “MCP Logs” in the dropdown; fix path or Node errors there.
- Tool approval — By default Cursor asks before each tool call; you can allow auto-run for trusted tools in Cursor settings if you prefer.
Other MCP hosts
Claude Desktop — same stdio shape: command + args to node and either --env-file or env in the host’s MCP config file.
CI / headless — run node --env-file=.env dist/index.js with a stdio MCP client library; ensure .env is supplied via secrets, not committed.
Search Expression Syntax
Tools that accept a search parameter use Qobrix's expression language:
| Feature | Syntax | Example | |---------|--------|---------| | Equality | ==, != | status == "available" | | Comparison | `, = | listsellingpriceamount = DAYSAGO(30) | | Current user | CURRENTUSER | assignedto == CURRENT_USER | | Association path | Entity.field | Properties.price > 100000` |
> Tip: Call qobrix_get_schema with any resource name to discover all available field names before building search expressions.
Fetching Related Data
Three strategies to resolve foreign keys:
include[]parameter — expand associations inline in one call
qobrix_get_property({ id: "...", include: ["Agents", "PropertyViewings"] })
- Separate get call — take the UUID from an FK field and call the appropriate tool
// property.agent → UUID
qobrix_get_agent({ id: "" })
- Search by FK — find related records via search expression
qobrix_search_properties({ search: 'agent == ""' })
Only include[] values marked Verified in tool descriptions are guaranteed to work. When include[] is unavailable for an association, use search-by-FK.
Payload defaults
To keep tool outputs short enough for the calling LLM's context window, list / search / get tools default to compact payloads:
| Param | Default | Effect when default | |-------|---------|---------------------| | expand | false | Foreign keys come back as UUID strings instead of being expanded into nested objects. Resolve them on demand with the matching get tool or with a targeted include[]. | | media | false | Inline media (photos, floor plans, thumbnail URLs) is not attached to list rows. Use qobrix_list_media({ related_model: 'Properties', related_id: '' }) when media is actually needed. |
Override per call only when the caller actually needs the heavier payload:
// Cheap browse — recommended for most reporting / pipeline calls
qobrix_list_properties({ limit: 10 });
// Heavy detail — only when the LLM truly needs nested FKs + media URLs
qobrix_list_properties({ limit: 5, expand: true, media: true });
// Prefer surgical include[] over full expand=true:
qobrix_get_property({ id: "...", include: ["AgentAgents", "ProjectProjects"] });
This change typically shrinks qobrix_list_properties({ limit: 10 }) from ~300 KB to ~5–10 KB.
Output cap
Every tool result is capped at QOBRIX_MCP_MAX_RESULT_CHARS characters of rendered JSON (default 30 000, roughly 7.5 K tokens). Behaviour:
- Paginated payloads (
{ data: [...], pagination: {...} }): truncated to the largest prefix ofdata[]that fits, and a_truncatedblock is attached withkept_rows,omitted_rows,original_chars,max_chars, and ahinttelling the LLM how to scope the next call. - Non-paginated payloads (single
get, custom analytic shapes): the JSON is clipped at the cap and aQOBRIX_MCP TRUNCATEDtrailer is appended with the same guidance.
Override the cap with the env var (set to 0 to disable, not recommended in production):
QOBRIX_MCP_MAX_RESULT_CHARS=60000
If you regularly hit the cap, that's a signal to use fields[] (whitelist columns), a tighter search expression, a smaller limit, or keep expand=false / media=false.
Testing
The project includes 172 automated tests across 48 describe suites (integration, multi-step scenarios, RESO workflows, cache, and output-cap behaviour):
# Integration tests — individual tool mechanics
npm test
# Scenario tests — multi-step tool chains (18 real-world scenarios)
npm run test:scenarios
# Workflow tests — canonical RE business processes (8 RESO-aligned suites)
npm run test:workflows
# Cache tests — read-through, single-flight, LRU eviction (no API needed)
npm run test:cache
# Format tests — output cap + truncation behaviour (no API needed)
npm run test:format
# Run everything
npm run test:all
| Suite | Tests | Coverage | |-------|-------|----------| | Integration | 70 | Every tool, pagination edge cases, include/fields mechanics, analytics + reporting tools | | Scenarios | 54 | Agent morning brief, buyer search, lead triage, FK chains, pipeline reports | | Workflows | 39 | Listing lifecycle, lead funnel, sales pipeline, showing, transaction, media, activity, schema | | Cache | 19 | Read-through cache, single-flight coalescing, LRU eviction, key canonicalization (no live API) | | Format | 5 | formatResult output cap, paginated truncation with _truncated marker, fallback trailer, env override (no live API) |
Architecture
src/
├── index.ts # MCP server entry point + RESO workflow instructions
├── client.ts # QobrixClient — HTTP + read-through response cache
├── cache.ts # LRU memory tier, optional Redis, single-flight coalescing
├── types.ts # TypeScript interfaces
├── schemas.ts # Zod schemas with rich LLM-facing descriptions
└── tools/
├── index.ts # Tool registration hub
├── properties.ts # Listing Lifecycle tools
├── contacts.ts # Lead-Contact Lifecycle tools
├── agents.ts # RESO Member tools
├── opportunities.ts # Sales Pipeline tools
├── viewings.ts # Showing Lifecycle tools
├── tasks.ts # Follow-up & Pipeline Management tools
├── media.ts # Media Lifecycle tools
├── projects.ts # Project/Development tools
├── offers.ts # Transaction Lifecycle tools
├── contracts.ts # Transaction close tools
├── activities.ts # Activity Tracking (calls, meetings, emails)
├── analytics.ts # qobrix_count, qobrix_top_values, qobrix_top_records, qobrix_aggregate
├── deals.ts # qobrix_deals (flexible Contracts shortcut)
├── reports.ts # qobrix_timeseries (bucketed metric + YoY), qobrix_days_on_market
├── pipeline.ts # qobrix_funnel, qobrix_stale_leads, qobrix_win_loss
├── productivity.ts # qobrix_rep_scorecard
├── customers.ts # qobrix_cohort (repeat buyers/sellers/leads)
├── cache.ts # qobrix_cache_stats, qobrix_cache_clear
└── meta.ts # Schema Discovery tools
test-suite/
├── integration.test.mjs # 55 integration tests
├── scenarios.test.mjs # 54 scenario tests
├── workflows.test.mjs # 39 workflow tests
└── cache.test.mjs # 19 cache unit tests
How the L
…
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: sharpsir-group
- Source: sharpsir-group/qobrix-crm-mcp
- License: Apache-2.0
- Homepage: https://sharpsir.group
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.