Skip to main content
Glama
gca-ltd

Qobrix CRM MCP Server

by gca-ltd

Índice de contenidos


Qué hace

Un asistente de IA conectado a este servidor puede explorar propiedades, cualificar clientes potenciales, hacer seguimiento de visitas, revisar ofertas y contratos, auditar la actividad de seguimiento y descubrir los esquemas de campos del CRM — todo mediante lenguaje natural. Cada descripción de herramienta enseña al LLM a qué flujo de trabajo inmobiliario canónico pertenece, a qué recurso de RESO se asigna y qué herramientas debe encadenar a continuación.

Para quién es

  • Corredores y desarrolladores que usan Qobrix y quieren que Claude.ai, Dust.tt, ChatGPT o Cursor respondan preguntas basadas en datos en vivo del CRM (no copias y pegas de exportaciones).

  • Ingenieros que integran MCP en herramientas internas: transporte stdio, entradas tipadas con Zod y sin superficie de escritura — seguro para experimentar con prompts y agentes.

  • Equipos de datos y operaciones que gestionan paneles: usa qobrix_count / qobrix_top_values para métricas interanuales sin scripts personalizados, y caché de respuestas para reducir la carga de la API en consultas repetidas.

  • TI empresarial preparado para identidad por agente: ejecuta los Modos A/B desde este paquete y luego combina el Modo C con el producto Enterprise OAuth de SharpSir cuando cada usuario deba autenticarse como él mismo — consulta OAuth empresarial.

Flujos de trabajo inmobiliarios canónicos

El servidor se organiza en torno a seis procesos de negocio alineados con RESO. El LLM recibe estos flujos como instrucciones integradas para poder navegar por el CRM sin formación previa.

#

Flujo de trabajo

Asignación RESO

Herramientas clave

1

Ciclo de vida de la propiedad

Property.StandardStatus

search_properties, get_property, list_media, get_property_coordinates

2

Ciclo de vida del cliente potencial

Contacts.ContactType funnel

search_opportunities, get_contact, search_tasks

3

Canal de ventas

Recorrido del comprador en 8 etapas

get_leads_by_property, get_lead_properties, list_viewings, list_offers, list_contracts

4

Visitas / Presentaciones

ShowingAppointment

list_viewings, get_viewing, list_meetings

5

Transacciones / Ofertas

TransactionManagement

list_offers, get_offer, list_contracts, get_contract

6

Actividad / Seguimiento

Seguimiento de interacciones

list_calls, list_meetings, list_email_messages, search_tasks

Asignaciones de estados

Estado de propiedad en Qobrix

RESO StandardStatus

available

Active

reserved

Pending / Under Contract

sold

Closed

withdrawn

Withdrawn / Canceled

Estado de oportunidad en Qobrix

Embudo de clientes potenciales RESO

new

MQL / Raw Lead

open

SQL / Active

won

Closed Won

closed_lost

Lost


Herramientas de un vistazo

64 herramientas — entidades CRM, descubrimiento de esquemas, analítica (qobrix_count, qobrix_top_values, qobrix_top_records, qobrix_aggregate), un acceso directo flexible para ofertas (qobrix_deals), informes (qobrix_timeseries, qobrix_funnel, qobrix_rep_scorecard, qobrix_stale_leads, qobrix_win_loss, qobrix_days_on_market), inteligencia de clientes (qobrix_cohort), auditoría / historial de cambios (qobrix_get_changes, qobrix_search_changes, qobrix_field_change_history, qobrix_top_field_changers), utilidades de caché (qobrix_cache_stats, qobrix_cache_clear) y sesión e identidad (qobrix_sign_in, qobrix_sign_out, qobrix_whoami):

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, Leals-by-Property, Properies-Lead

Property Viewings

3

List, Get, Search

Tasks

3

List, Get, Search

Media

2

List (con filtro de entidad), Get (con variantes de aábulo)

Projects

4

List, Get, Search, Coordinates

Offers

3

List, Get, Search

Contracts

3

List, Get, Search

Calls

2

List, Get

Mettings

2

List, Get

Emails

2

List, Get

Schem / Meta

3

Get Schema (descubrimiento de campos), Get Meta (valores de enum), Search DSL Help (gramática completa + ofens)

Analytics

4

Counts, top-N valors de campo, full-scan comple de N valores por numéric/date yarda, agrupación por un/multiple dim. Prefiera sort de list/search para una sola página; use top_records/aggregate para recorridos de set completo o campos nulibos

Deals

1

Atajo de dominio flexible sobre la tabla de Contratos (ventas, alquileres, listados, pipelines) con contract\_types\[] / contract\_statuses\[] / date\_field / min\_price / filtors de pare / block de resumen

Reportes

6

Series temporales interanual (YoY) (qobrix_timeseries), embudo de ventas canico + % de conversión (qobrix_funnel), marcador por representante (qobrix_rep_scorecard), detección de leads silenciar (qobrix_stale_leads), analítica de gan/pidas (qobrix_win_los), días en el mercado (qobrix_days_on_market)

Clientes

1

Recorrentes compradors / vendedors / cohorts de leads (qobrix_cohort) — ver contactos de dealers cerrados

Auditoría

4

Regístelo de cambios por registro (qobrix_get_changes), búsqueda de cambios entre recursos (qobrix_search_changes), histórico por campo (qobrix_field_change_history), responsables de cambios (qobrix_top_field_changers)

Cache

2

Estadàsticas y invalidació parcial o totale para lecturas más actuales

Sesión e identidad

3

Inicio de sesión interactivo (qobrix_sign_in), cierre de sesión (qobrix_sign_out), perfil de usuário actual (qobrix_whoami) — Modo C; no-op sensatos en Modos A/B

Cada descripción de herramienta incluye su rol de flujo de trabajo canónico, el equivalente RESO, las opciones include[] verificadas, la guía de resolución de FK y ejemplos de expresiones de búsqueda.

Ejemplos de uso de Analytics y Deals

El sort del lado servidor (OpenAPI sort[]) funciona para la mayoría de campos — p. ej., sort: "-list_selling_price_amout" sobre propiedades. Usa qobrix_top_records / qobrix_aggregate cuando necesites un análisis de todo el dataset u cuando un campo anulable (p. ej., opportunities.budget) no devuelva filas con el sort del servidor. Los «cios» cerrados no son un indicador de propiedad: son filas de la tabla Contractes. Las herramientas de Analytics/Deals eliminan la necesida de scriptádo del lado del cliente:

// 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 < \"2027-01-01\"",
    "top": 5
  }
}

// 2) 2026 sales volume, plus an agent leaderboard in one extra call.
{
  "tool": "qobrix_aggregate",
  "args": {
    "resource": "contracts",
    "field": "final_selling_price_amount",
    "op": "sum",
    "search": "contract_type == \"cos\" and contract_status == \"agreed\" and date_of_contract >= \"2026-01-01\" and date_of_contract < \"2027-01-01\"",
    "group_by": "commission_to_2",
    "top": 10
  }
}

// 3) Flexible "deals" shortcut — same answer as (1) with one default-laden call,
//    plus a full-set summary block (by_status, by_type, totals, median).
{ "tool": "qobrix_deals", "args": { "year": 2026, "top": 5 } }

// 4) Best 2026 rental contracts by final rental price.
{ "tool": "qobrix_deals", "args": { "kind": "rental", "year": 2026, "top": 5 } }

// 5) Under-contract reservations + closed sales together (pipeline + actuals).
{
  "tool": "qobrix_deals",
  "args": { "contract_statuses": ["reserved", "agreed"], "year": 2026 }
}

// 6) "My deals this year": uses the CURRENT_USER special var.
{
  "tool": "qobrix_deals",
  "args": { "assigned_to": "CURRENT_USER", "year": 2026 }
}

// 7) Monthly 2026 closed-sale volume with prior-year YoY %.
{
  "tool": "qobrix_timeseries",
  "args": {
    "resource": "contracts",
    "bucket": "month",
    "metric": "sum",
    "field": "final_selling_price_amount",
    "year": 2026,
    "search": "contract_type == \"cos\" and contract_status == \"agreed\"",
    "compare_to_prior": true
  }
}

// 8) Full 2026 sales funnel (Leads → Qualified → Viewing → Offer → Reserved → Closed).
{ "tool": "qobrix_funnel", "args": { "year": 2026 } }

// 9) 2026 agent leaderboard by volume (omit `user` for leaderboard mode).
{ "tool": "qobrix_rep_scorecard", "args": { "year": 2026, "sort_by": "volume", "top": 10 } }

// 10) Silent leads — open opportunities with no activity in 30 days.
{ "tool": "qobrix_stale_leads", "args": { "since_days": 30 } }

// 11) Multi-dim pivot: 2026 closed-sale volume by city × property_type.
{
  "tool": "qobrix_aggregate",
  "args": {
    "resource": "contracts",
    "field": "final_selling_price_amount",
    "op": "sum",
    "search": "contract_type == \"cos\" and contract_status == \"agreed\" and date_of_contract >= \"2026-01-01\" and date_of_contract < \"2027-01-01\"",
    "group_by": ["property_id", "contract_type"],
    "top": 10
  }
}

// 12) Repeat buyers — contacts behind 2+ closed sales in 2026.
{ "tool": "qobrix_cohort", "args": { "kind": "buyers", "year": 2026, "min_count": 2 } }

// 13) Win-rate by lead source in 2026, with top loss reasons resolved.
{
  "tool": "qobrix_win_loss",
  "args": { "year": 2026, "group_by": "source", "include_top_losses": true }
}

// 14) 2026 days-on-market by property type, with longest/shortest outliers.
{
  "tool": "qobrix_days_on_market",
  "args": { "kind": "sold", "year": 2026, "group_by": "property_type", "include_outliers": true }
}

Inicio rápidido

git clone https://github.com/gca-ltd/qobrix-crm-mcp.git
cd qobrix-crm-mcp
npm install
npm run build

Configuración

Crea un archivo .env en la raíz del proyecto:

QOBRIX_API_URL=https://yourcrm.qobrix.com
QOBRIX_API_USER=your-api-user-uuid
QOBRIX_API_KEY=your-api-key
QOBRIX_LOCALE=en-US          # optional

Variable

Requerido

Descripción

QOBRIX_API_URL

Sí (Modo A)

URL base de la instancia Qobrix

QOBRIX_API_USER

Sí (Modo A)

Valor de la cabeceera X-Api-User (UUID)

QOBRIX_API_KEY

Sí (Modo A)

Valor de la cabeceera X-Api-Key

QOBRIX_LOCALE

No

Cabeceera X-Locale (p.ej., en-US, el-GR)

Modos de autenticación

Clona este paquete, ejecúa el modo A o B, y coloca datos reales delante de Claude, Cursor u cualquier cliente de MCP. — Apache 2.0.

| Modo | ¿Included in this package? | Cuándo | Cómo llegan las credenciales | | A (default) | Sí | QOBRIX_MCP_TRANSPORT=stdio (o sin configurar) | QOBRIX_API_* comúns desde env del proceso | | B | Sí | TRANSPORT=http + QOBRIX_MCP_AUTH=headers | X-Api-User / X-Api-Key per request (callors of confianza; bind to localhost) | | C | Needs AS companion | TRANSPORT=http + QOBRIX_MCP_AUTH=oauth | OAuth autoservicio: MCP devuelve una URL /connect; el usuario inicia sesión en el servidor de autorización Enterprise OAuth de SharpSir; ese servidor guarda la session | | D (opt-in) | Necesita AS | TRANSPORT=http + QOBRIX_MCP_AUTH=oauth-claude | Program User OAuth (RFC 9728 PRM + Bearer on /mcp) par Claude.ai / Desktop custom connectors and Dusty Spaces tools — la misma URL de recurso, login per-user |

Modes A y B son totalmente soportados este this paquete. Los modos C y D require the complemento the Enterprise OAuth / SSO product separate, no distribued in this repo. Mode D does not change Modes A/B/C — selector ito when quieras que host remotos como Claude.o o Dust.elt piloten OAuth.

Enterprise OAuth

¿Necesitas el agente actue como un usuário Qubrix loguedo — not a shared API key? Modo C está diseñado para eso. Require la solución Enterprise OAuth of SharpSir: a bundled hostal of Authorization Server (login + 2FA + consentimento, acuñación de API-keys de user, credentiales encriptadas, tokens de audiencia bound) that only works with this MCP server.

Cómo funciona el Modo C (MCP self-auth — clientes sentdantest without chages)

  1. Una herramienta se ejecuta sin sesión → el MCP devuelve una URL de autorización:

    • Elicitación en modo URL (JSON-RPC -32042) cuando el cliente admite elicitation.url (Claude, Cursor, etc.)

    • Un enlace Markdown [Sign In to Qobrix](/connect?e=…) en el resultado de la herramienta para clientes sin elicitación (p. ej. ragchat / LangChain) — el LLM debe transmitirlo literalmente (único / de un solo uso; no reutilizar nunca un enlace antiguo)

  2. El usuario abre /connect en este servidor (indirección antiphishing) → cookie firmada + redirección a la página de inicio de sesión de Enterprise OAuth

  3. Tras el inicio de sesión + 2FA + consentimiento, el AS redirige a /oauth/callback; este MCP intercambia el código (PKCE), realiza la introspección de las credenciales de Qobrix y las almacena en una bóveda de sesión cifrada

  4. La siguiente llamada a la herramienta se ejecuta autenticada. Ante un 401/403 de Qobrix, se limpia la bóveda y se devuelve una nueva URL /connect

  5. Los agentes también pueden llamar a qobrix_sign_in, qobrix_whoami y qobrix_sign_out (revocación completa mediante /disconnect del AS + eliminación de la clave de API de Qobrix)

  • No está disponible como descarga pública y no es algo que puedas clonar desde GitHub.

  • Nuestro equipo lo entrega y configura bajo petición como paquete de solución empresarial.

  • Sin servidores OAuth de terceros: el Modo C está conectado de forma exclusiva a esta solución Enterprise OAuth.

  • Seguridad: el Modo C utiliza bóvedas de sesión cifradas por usuario (identificadas por cabeceras de identidad del chat) y deja /mcp sin bearer de cliente. Vincula QOBRIX_MCP_HOST=127.0.0.1 y establece QOBRIX_MCP_IDENTITY_SECRET (compartido solo con el host MCP de confianza como ragchat) para que las cabeceras de identidad no puedan falsificarse. Mantén el cifrado de la bóveda en QOBRIX_MCP_STATE_SECRET (solo MCP). Si utilizas un proxy inverso para navegadores, publica solo /connect y /oauth/callback — deniega el acceso público a /mcp y /health. Los agentes locales (ragchat) llaman a http://127.0.0.1:<port>/mcp. Cuando ALLOWED_HOSTS solo incluye el nombre de host público, los valores de Host de bucle local (127.0.0.1 / localhost / ::1) se añaden automáticamente si el servidor se vincula al bucle local. La cookie de conexión Path sigue el pathname de PUBLIC_URL; Express trust proxy es 2 detrás de Cloudflare→Apache. Entrega los enlaces /connect solo al usuario individual — nunca en un hilo compartido/grupal.

¿Listo para actualizar? Contacta con SharpSir Group · dev@sharpsir.group y solicita el paquete Qobrix CRM MCP Enterprise OAuth.

Una vez entregado, apunta este servidor al emisor que recibas:

export QOBRIX_MCP_TRANSPORT=http
export QOBRIX_MCP_AUTH=oauth
export QOBRIX_MCP_HOST=127.0.0.1
export QOBRIX_MCP_PORT=3502
export QOBRIX_MCP_PUBLIC_URL=http://127.0.0.1:3502
export QOBRIX_MCP_RESOURCE_URL=http://127.0.0.1:3502/mcp
export QOBRIX_OAUTH_ISSUER=<issuer-from-enterprise-bundle>
export QOBRIX_OAUTH_INTROSPECTION_SECRET=<shared-secret-from-bundle>
export QOBRIX_MCP_STATE_SECRET=<16+-char-secret>
export QOBRIX_MCP_IDENTITY_SECRET=<16+-char-secret-shared-with-ragchat>
export QOBRIX_MCP_DATA_DIR=./data/mcp-oauth
export QOBRIX_MCP_ALLOWED_HOSTS=qobrix-mcp.example.com   # loopback Hosts auto-added when HOST is 127.0.0.1
npm start

Endpoints del Modo C (una vez emparejada la solución Enterprise OAuth):

  • GET /connect?e=… — inicia la autorización (establece cookie, 302 al AS)

  • GET /oauth/callback — intercambio de código PKCE + escritura en la bóveda de sesión por usuario

  • GET /health — incluye el recuento de connected y session_vaults

  • /mcp sin autenticación es intencional para clientes northbound: las herramientas muestran la URL de conexión cuando es necesario — mantén /mcp en localhost en producción

Consulta docs/USER_GUIDE.md para el paso a paso del Modo A → B → C, el bloqueo del proxy inverso y los detalles de la lista de permitidos de Host.

Para ragchat / Modo C, registra la URL MCP remota (…/mcp) como un servidor HTTP Streamable normal (no se requiere proveedor OAuth del lado del cliente); el MCP gestiona la autenticación mediante /connect. Mantén /mcp en localhost en esa topología.

Modo D — MCP remoto de Claude.ai y Dust.tt (recurso compartido)

Usa un proceso (u host) MCP separado con QOBRIX_MCP_AUTH=oauth-claude. Los hosts remotos gestionan OAuth por sí mismos contra la misma URL HTTPS /mcp:

Host

How to connect

Auth

Claude.ai / Claude Desktop

Settings → Connectors → Add custom connector

Automatic DCR + PKCE (redirect https://claude.ai/api/mcp/auth_callback)

Dust.tt

Spaces → Tools → Add MCP Server

Prefer Automatic; Static OAuth fallback — see INSTALL — Connect Dust

  1. El usuario pega https://intranet.sharpsir.group/qobrix-crm/mcp en Claude o Dust

  2. El host llama a /mcp → recibe 401 + WWW-Authenticate: Bearer resource_metadata=…

  3. El host obtiene /.well-known/oauth-protected-resource → descubre QOBRIX_OAUTH_ISSUER

  4. El host completa OAuth (DCR o Static) + PKCE contra el AS de Enterprise OAuth

  5. Las llamadas posteriores a /mcp envían Authorization: Bearer <access_token>; este servidor realiza la introspección y ejecuta las herramientas como ese usuario de Qobrix

Claude y Dust comparten una misma pila del Modo D (mismo recurso MCP + mismo servidor de autorización). Cada host registra su propio cliente OAuth; cada miembro inicia sesión en Qobrix como sí mismo.

export QOBRIX_MCP_TRANSPORT=http
export QOBRIX_MCP_AUTH=oauth-claude
export QOBRIX_MCP_HOST=127.0.0.1
export QOBRIX_MCP_PORT=3502
export QOBRIX_MCP_ALLOWED_HOSTS=intranet.sharpsir.group
export QOBRIX_MCP_PUBLIC_URL=https://intranet.sharpsir.group/qobrix-crm
export QOBRIX_MCP_RESOURCE_URL=https://intranet.sharpsir.group/qobrix-crm/mcp
export QOBRIX_OAUTH_ISSUER=https://intranet.sharpsir.group/qobrix-crm/mcp-oauth
export QOBRIX_OAUTH_INTROSPECTION_SECRET=<shared-secret-from-bundle>
npm start

En el AS, cuando uses una lista de permitidos de redirección, conserva el callback de Claude y añade las URL finales exactas de Dust (nunca sustituyas la entrada de Claude):

export QOBRIX_OAUTH_REDIRECT_ALLOWLIST=https://claude.ai/api/mcp/auth_callback,http://127.0.0.1,http://localhost,cursor://,https://eu.dust.tt/oauth/mcp/finalize,https://eu.dust.tt/oauth/mcp_static/finalize,https://dust.tt/oauth/mcp/finalize,https://dust.tt/oauth/mcp_static/finalize,https://app.dust.tt/oauth/mcp/finalize,https://app.dust.tt/oauth/mcp_static/finalize

Publica HTTPS /mcp + PRM (y el AS) en internet público; incluye en la lista de permitidos la salida de Anthropic 160.79.104.0/21 si hay WAF, y permite también la salida de Dust — no elimines la lista de permitidos de Claude. La guía del Modo C sobre loopback/deny public /mcp sigue siendo válida para despliegues con ragchat — no cambies esa topología para los procesos del Modo C.

Pasos completos: INSTALL — Connect Claude · INSTALL — Connect Dust · Dust: Adding an MCP Server.

Caché

Todas las herramientas MCP son GET de solo lectura, por lo que una caché de respuestas no puede corromper el estado del CRM. El servidor envuelve un único punto de paso (QobrixClient.request()) con una caché de lectura directa, de modo que todas las llamadas list/get/search/schema — incluida cada página de un max_scan de relevancia — quedan en caché. La puntuación de boost se aplica tras la obtención y no cambia la clave de caché, por lo que reordenar con distintos boost[] reutiliza las mismas páginas candidatas.

Diseño — cache-aside con coalescencia single-flight:

  • Nivel 1 — LRU en memoria (siempre activo, cero dependencias): por proceso, con TTL y límite de tamaño.

  • Nivel 2 — Redis (opcional, cargado de forma diferida mediante import() dinámico): configura QOBRIX_REDIS_URL para activarlo; el servidor vuelve a solo memoria ante cualquier error de Redis.

  • Single-flight: cuando el LLM lanza llamadas paralelas a herramientas que coinciden en la misma clave de caché fría (habitual con qobrix_top_values), todos los llamadores del mismo proceso comparten una única consulta al upstream.

  • Los errores nunca se almacenan en caché — un 5xx transitorio no se quedará atascado.

  • Solo TTL, sin stale-while-revalidate en v1.

Variables de entorno:

Variable

Default

Description

QOBRIX_CACHE_ENABLED

true

Set to false to bypass the cache entirely

QOBRIX_CACHE_TTL

300

TTL in seconds; CRM edits visible within this window

QOBRIX_CACHE_MAX_ENTRIES

5000

LRU cap for the in-memory tier

QOBRIX_REDIS_URL

(empty)

redis:// / rediss:// URL; empty = memory only

QOBRIX_REDIS_KEY_PREFIX

qobrix:

Namespace when sharing a Redis instance

Herramientas de caché (expuestas al LLM):

Tool

Use

qobrix_cache_stats

Hits/misses/size/in-flight/Redis status — verify the cache is paying off

qobrix_cache_clear

Invalidate all keys or by prefix (e.g. v1:request:opportunities) for instant refresh before TTL

Configuración recomendada del servidor Redis (para un Redis dedicado solo a caché, según la documentación de Redis):

maxmemory 256mb
maxmemory-policy allkeys-lru
maxmemory-samples 10

Orientación sobre TTL — la documentación de Redis recomienda TTL cortos para datos que cambian con frecuencia (60–120s) y más largos para datos estables (horas). 300s es un valor por defecto conservador para un CRM que combina el pipeline de leads (cambia cada minuto) con anuncios de propiedades (cambian cada hora). Usa qobrix_cache_clear cuando necesites una actualización instantánea.

Compromiso / límite conocido: la coalescencia single-flight es solo dentro del proceso. Los despliegues multi-instancia detrás de un Redis compartido aún pueden experimentar una estampida moderada en claves frías; un bloqueo distribuido SETNX es trabajo futuro y no es necesario para clientes MCP de un solo usuario.

Alineación con las mejores prácticas:

Best practice

Where honored

Cache-aside / read-through (Redis docs, MCP caching guides)

QobrixClient.request() wrap

Canonical, versioned cache key

cacheKey("v1", ...) with sorted params

Conservative TTL

300s default, env-overridable

Errors not cached

Wrap stores only on resolved upstream success

Single-flight stampede prevention

In-process inflight map

allkeys-lru for cache-only Redis

Documented above for self-hosters

Observability + manual invalidation

qobrix_cache_stats, qobrix_cache_clear

Official Node.js Redis client

redis (node-redis), as optionalDependencies

Configuración del IDE Cursor

Este servidor usa MCP stdio (un proceso node local). Cursor descubre los servidores desde el mcp.json del proyecto o del usuario: .cursor/mcp.json dentro de la carpeta que hayas abierto, o ~/.cursor/mcp.json para todos los espacios de trabajo.

1. Requisitos previos

  • Node.js 20+ en la máquina donde Cursor ejecuta el MCP (portátil local o host SSH remoto).

  • Clona este repositorio, instala y compila (ver Quick Start).

  • dist/index.js debe existir (npm run build) antes de añadir la entrada MCP.

2. Credenciales

  1. Copia la plantilla: cp .env.example .env

  2. Edita .env y establece al menos QOBRIX_API_URL, QOBRIX_API_USER y QOBRIX_API_KEY (ver Configuration).

  3. Mantén .env fuera de git; está listado en .gitignore.

3. Dónde colocar el JSON

Location

When to use

<project>/.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.

Fusiona tu entrada en el objeto "mcpServers" existente; no reemplaces todo el archivo si ya tienes otros servidores.

4. Recomendado: node --env-file (Node 20+)

Usa rutas absolutas para que funcione igual tanto si la raíz del espacio de trabajo es este repositorio como si es una carpeta superior (y para que las rutas remotas SSH se resuelvan correctamente).

{
  "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"
    }
  }
}

Por qué este patrón:

  • Las credenciales permanecen en .env, no en JSON.

  • Node carga el archivo antes de que tu servidor arranque, por lo que process.env se rellena incluso cuando el campo envFile del host se ignora o se comporta de forma inconsistente con los servidores stdio.

5. Alternativa: env en línea

Útil si no puedes usar --env-file (Node más antiguo). Los secretos viven en mcp.json — restringe los permisos del archivo y no los hagas commit.

{
  "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"
      }
    }
  }
}

También puedes usar la interpolación de configuración de Cursor (por ejemplo ${env:QOBRIX_API_KEY}) para que los valores se inyecten desde el entorno de tu sistema operativo en lugar de literales.

6. Opcional: envFile en el JSON de MCP

Cursor admite una propiedad envFile para servidores stdio. Algunas configuraciones no pasan esas variables al proceso hijo de forma fiable; si las herramientas fallan con «Faltan variables de entorno obligatorias», cambia a --env-file como en el paso 4.

7. Después de editar mcp.json o .env

  1. Recargar MCP — Paleta de comandos → reiniciar MCP, o recargar la ventana de Cursor.

  2. Revisar los registros — Ver → Salida → elige «MCP» / «Registros de MCP» en el menú desplegable; corrige allí los errores de ruta o de Node.

  3. Aprobación de herramientas — Por defecto, Cursor pregunta antes de cada llamada a herramienta; puedes permitir la ejecución automática de herramientas de confianza en la configuración de Cursor si lo prefieres.

Otros hosts de MCP

Claude.ai / Claude Desktop (Modo D) — conector personalizado remoto en https://intranet.sharpsir.group/qobrix-crm/mcp. Consulta Modo D e INSTALL — Conectar Claude.

Dust.tt (Modo D) — Spaces → Tools → Añadir servidor MCP con la misma URL. Prefiere la autenticación automática y las cuentas personales. Consulta INSTALL — Conectar Dust.

Claude Desktop / Cursor (Modo A stdio) — misma forma stdio: command + args hacia node y ya sea --env-file o env en el archivo de configuración MCP del host.

CI / sin interfaz — ejecuta node --env-file=.env dist/index.js con una biblioteca cliente MCP stdio; asegúrate de que .env se suministre mediante secretos, no se suba al repositorio.


Sintaxis de expresiones de búsqueda

Las herramientas que aceptan un parámetro search usan el lenguaje de expresiones Symfony de Qobrix (OpenAPI SearchExpression). Llama a qobrix_search_dsl_help para obtener la gramática completa y las hojas de referencia de campos de propiedades/proyectos (opcionalmente con nombres de campos de esquema en vivo).

Característica

Sintaxis

Ejemplo

Igualdad

==, !=, <>

status == "available"

Comparación

<, >, <=, >=

list_selling_price_amount <= 500000

Contiene

contains, starts with, ends with

city contains "Limas"

Pertenencia a conjunto

in [...], not in [...]

property_type in ["villa","house"]

Rango

in min..max

bedrooms in 2..4

Lógico

and, or, not, paréntesis

status == "available" and sale_rent == "for_sale"

Helpers de fecha

DAYS_AGO(n), MONTHS_AGO(n), DAYS_FROM_NOW(n), …

created >= DAYS_AGO(30)

Atajos de tiempo

NOW, TODAY, THIS_WEEK, LAST_MONTH, THIS_YEAR, …

created >= LAST_MONTH

Usuario actual

CURRENT_USER

assigned_to == CURRENT_USER

Geo / varios

DISTANCE_FROM, IN_POLYGON, TRANSLATED, MIN/MAX

DISTANCE_FROM(coordinates, "34.43,32.13") <= 5000

Ruta de asociación

Entity.field

SalespersonUsers.Contacts.country == "CY"

Consejo: Llama a qobrix_search_dsl_help({ resource: "Properties" }) antes de convertir una demanda en lenguaje libre en una consulta. Usa qobrix_get_field_options para los valores de enumeración y qobrix_get_schema para la lista completa de campos.

Búsqueda relevante en todos los recursos (F1)

Cada herramienta qobrix_search_* (propiedades, proyectos, contactos, agentes, oportunidades, visitas, tareas, ofertas, contratos) usa un diseño de dos niveles para que la demanda en lenguaje libre se asigne con alta precisión y alta exhaustividad:

  1. search — requisitos obligatorios estrictos (filtro DSL del lado del servidor → suelo de precisión).

  2. boost[] — deseables ponderados suaves puntuados en proceso sobre un conjunto de candidatos (exhaustividad + clasificación).

  3. limit — cuántas filas clasificadas devolver (por defecto 10, máximo 100). Auméntalo para tener más opciones; mantenlo moderado para evitar sobrecargar el contexto.

  4. max_scan — conjunto de candidatos al usar boost (por defecto 100, límite máximo 500). Un valor más alto mejora la exhaustividad; cada página escaneada se almacena en caché de respuesta.

Con boost, cada fila incluye _relevance (puntuación) y _matched (qué cláusulas coinciden); pagination.mode es "ranked". Sin boost, se devuelve una sola página de lista en caché (mode: "fast").

qobrix_search_properties({
  search: 'status == "available" and sale_rent == "for_sale"',
  boost: [
    { field: "sea_view", op: "==", value: true, weight: 3 },
    { field: "bedrooms", op: ">=", value: 3, weight: 2 },
    { field: "list_selling_price_amount", op: "in", value: "200000..600000", weight: 2 },
  ],
  limit: 15,
  max_scan: 200,
});

Coincidencia de leads ↔ listados mediante búsqueda (bidireccional)

  • Demanda → oferta: toma los criterios de un lead → qobrix_search_properties / qobrix_search_projects con search+boost. Nativo: qobrix_get_properties_by_lead / qobrix_get_lead_properties.

  • Oferta → demanda: qobrix_search_opportunities con search + boost de lead abierto contra el listado (también funciona para proyectos). Nativo solo para propiedades: qobrix_get_leads_by_property.

// Who wants a Limassol 3-bed ~€400k listing?
qobrix_search_opportunities({
  search: 'status in ["new","open"] and buy_rent == "buy"',
  boost: [
    { field: "area_of_interest", op: "contains", value: "Limassol", weight: 3 },
    { field: "bedrooms_from", op: "<=", value: 3, weight: 2 },
    { field: "list_selling_price_to", op: ">=", value: 400000, weight: 2 },
  ],
  limit: 15,
  max_scan: 200,
});

Operadores de boost: == != < > <= >= in contains starts_with ends_with. Para rangos usa op: "in" con value: "min..max".

La búsqueda (y cualquier otra lista/consulta) comparte el TTL global de caché (QOBRIX_CACHE_TTL, por defecto 300 s). Tras ediciones en el CRM, actualiza con qobrix_cache_clear({ prefix: "v1:request:properties" }) (o opportunities, projects, …).


Obtención de datos relacionados

Tres estrategias para resolver claves foráneas:

  1. Parámetro include[] — expande las asociaciones en línea en una sola llamada

qobrix_get_property({ id: "...", include: ["Agents", "PropertyViewings"] })
  1. Llamada get separada — toma el UUID de un campo FK y llama a la herramienta adecuada

// property.agent → UUID
qobrix_get_agent({ id: "<agent-uuid>" })
  1. Búsqueda por FK — encuentra registros relacionados mediante una expresión de búsqueda

qobrix_search_properties({ search: 'agent == "<agent-uuid>"' })

Solo los valores include[] marcados como Verificados en las descripciones de herramientas están garantizados. Cuando include[] no esté disponible para una asociación, usa la búsqueda por FK.


Valores predeterminados de payload

Para mantener las salidas de las herramientas lo suficientemente cortas para la ventana de contexto del LLM que llama, las herramientas de listado / búsqueda / obtención usan por defecto payloads compactos:

Parámetro

Por defecto

Efecto cuando es el predeterminado

expand

false

Las claves foráneas vuelven como cadenas UUID en lugar de expandirse en objetos anidados. Resuélvelas bajo demanda con la herramienta get correspondiente o con un include[] específico.

media

false

Los medios en línea (fotos, planos, URLs de miniaturas) no se adjuntan a las filas de lista. Usa qobrix_list_media({ related_model: 'Properties', related_id: '<uuid>' }) cuando realmente se necesiten medios.

Anula por llamada solo cuando el llamador realmente necesite el payload más pesado:

// 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"] });

Este cambio normalmente reduce qobrix_list_properties({ limit: 10 }) de ~300 KB a ~5–10 KB.


Límite de salida

Cada resultado de herramienta está limitado a QOBRIX_MCP_MAX_RESULT_CHARS caracteres de JSON renderizado (por defecto 30 000, aproximadamente 7,5 K tokens). Comportamiento:

  • Payloads paginados ({ data: [...], pagination: {...} }): se truncan al prefijo más grande de data[] que quepa, y se adjunta un bloque _truncated con kept_rows, omitted_rows, original_chars, max_chars y un hint que le dice al LLM cómo acotar la siguiente llamada. Si los objetos expandidos o de medios anidados por sí solos superan el límite, las filas se compactan a escalares (_truncated.compacted: true) para que se devuelva al menos una fila utilizable.

  • Excesivamente grandes (por defecto: tamaño original > 8 × el límite, anulable con QOBRIX_MCP_REFINE_MULTIPLIER): devuelve status: "result_too_large" con _refine_required (instrucción del asistente + estrechamiento sugerido + returned_sample pequeño) para que el LLM pida al usuario que reformule, no que vuelque.

  • Payloads no paginados (un solo get, formas analíticas personalizadas): el JSON se recorta en el límite y se adjunta un marcador final QOBRIX_MCP TRUNCATED (o la misma directiva de refinamiento cuando es excesivamente grande).

Cuando se usa boost con expand=true o media=true, max_scan se limita automáticamente a 100 y pagination.scan_capped_reason puede ser "expand/media".

Anula el límite / umbral de refinamiento:

QOBRIX_MCP_MAX_RESULT_CHARS=60000
QOBRIX_MCP_REFINE_MULTIPLIER=8

Si alcanzas con frecuencia el límite o la protección de refinamiento, usa fields[] (columnas de lista blanca), una expresión search más estricta, un limit más pequeño o mantén expand=false / media=false.


Pruebas

El proyecto incluye 226 pruebas automatizadas en 63 suites describe (integración, escenarios de múltiples pasos, flujos de trabajo RESO, caché, relevancia, límite de salida, ordenación del cliente y pruebas de humo del modo OAuth):

# Integration tests — individual tool mechanics
npm test

# Scenario tests — multi-step tool chains (19 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, search-page keys (no API needed)
npm run test:cache

# Relevance tests — boost scoring, DSL help, search cache keys (no API needed)
npm run test:relevance

# Format tests — output cap + truncation behaviour (no API needed)
npm run test:format

# OAuth modes smoke — Mode B header rejection + Mode C /connect elicitation path
npm run test:oauth-modes

# Run everything
npm run test:all

Suite

Pruebas

Cobertura

Integración

70

Cada herramienta, casos límite de paginación, mecánica de include/fields, herramientas de análisis e informes

Escenarios

55

Resumen matutino del agente, búsqueda de comprador, triaje de leads, cadenas de FK, informes de pipeline

Flujos de trabajo

39

Ciclo de vida del listado, embudo de leads, pipeline de ventas, visitas, transacciones, medios, actividad, esquema

Caché

22

Caché de lectura, coalescencia de un solo vuelo, evicción LRU, canonicalización de claves, claves de páginas de búsqueda (sin API en vivo)

Relevancia

23

Evaluación/puntuación/clasificación de boost (incl. formas de oportunidad/contacto), unión de fields[]+boost, texto de ayuda DSL, estabilidad de claves de caché de búsqueda (sin API en vivo)

Formato

7

Límite de salida de formatResult, truncamiento paginado, compactación de expand/media (kept_rows>=1), guarda de refinamiento result_too_large, marcador final de respaldo, anulación de entorno (sin API en vivo)

Ordenación del cliente

7

normalizeSort + buildQobrixUrl emiten sort[]= de OpenAPI (no sort= escalar que Qobrix ignora)

Modos OAuth

4

Encabezados del Modo B, /connect del Modo C, PRM/401/Bearer del Modo D


Arquitectura

src/
├── index.ts          # MCP server entry point + RESO workflow instructions
├── http.ts           # Streamable HTTP transport (Modes B / C)
├── modes.ts          # Auth mode resolution (env / headers / oauth / oauth-claude)
├── client.ts         # QobrixClient — HTTP + read-through response cache
├── auth-context.ts   # AsyncLocalStorage per-request credentials
├── oauth-client.ts   # Mode C self-service OAuth client + session vault
├── oauth-rs.ts       # Companion AS metadata + introspection helpers
├── request-context.ts# ALS for McpServer (elicitation capability detection)
├── cache.ts          # LRU memory tier, optional Redis, single-flight coalescing
├── relevance.ts      # Boost scoring + cached candidate pager for search
├── search-dsl.ts     # Full SearchExpression DSL reference + field cheatsheets
├── types.ts          # TypeScript interfaces
├── schemas.ts        # Zod schemas with rich LLM-facing descriptions
└── tools/
    ├── index.ts      # Tool registration hub + formatResult / errorResult
    ├── properties.ts # Listing Lifecycle + relevance search
    ├── 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 + relevance search
    ├── 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
    ├── audit.ts      # change log / field history / top changers
    └── meta.ts       # Schema discovery + qobrix_search_dsl_help
test-suite/
├── integration.test.mjs  # Live API smoke tests
├── scenarios.test.mjs    # Multi-step CRM scenarios
├── workflows.test.mjs    # RESO workflow coverage
├── cache.test.mjs        # Cache unit tests (incl. search-page keys)
├── relevance.test.mjs    # Boost scoring + DSL help unit tests
├── format.test.mjs       # Output-cap / truncation tests
└── oauth-modes.test.mjs  # Mode B/C auth smoke tests

Cómo aprende el LLM

El servidor enseña al LLM en tres niveles:

  1. Instrucciones del servidor — el campo instructions de nivel superior en la respuesta initialize de MCP proporciona el modelo de datos completo, seis flujos de trabajo canónicos con recetas de herramientas, sintaxis de búsqueda, estrategias de resolución de FK y peculiaridades conocidas.

  2. Descripciones de herramientas — cada descripción de herramienta incluye su rol canónico en el flujo de trabajo, equivalente RESO, opciones include[] verificadas, mapeos de campos FK, forma de respuesta y ejemplos de búsqueda. Las herramientas de búsqueda por relevancia documentan la receta de dos niveles search + boost; qobrix_search_dsl_help expone el DSL completo bajo demanda.

  3. Descripciones de parámetros — los esquemas Zod proporcionan ayuda por parámetro con ejemplos concretos, valores de enumeración válidos y referencias entre herramientas.


Tecnología

Componente

Tecnología

Runtime

Node.js ≥ 20

Lenguaje

TypeScript 5.7

MCP SDK

@modelcontextprotocol/sdk 1.26

Validación

Zod 3.24

Caché opcional

redis 4.x (node-redis) cuando QOBRIX_REDIS_URL está definida

Transporte

stdio (predeterminado) · Streamable HTTP (Modos B / C)

Autenticación de API

Modo A/B: X-Api-User + X-Api-Key · Modo C: Enterprise OAuth de autoservicio (URL /connect)

Pruebas

Ejecutor de pruebas integrado de Node.js (node:test)

Licencia

Apache License 2.0 — Copyright 2025–2026 SharpSir Group

Los modos A y B están incluidos en este paquete de código abierto. Modo C se complementa con el servidor de autorización Enterprise OAuth de SharpSir (SSO / identidad por usuario) — un producto comercial independiente que se entrega bajo petición — sharpsir.group · dev@sharpsir.group.


Install Server
A
license - permissive license
A
quality
A
maintenance

Maintenance

Maintainers
Response time
4dRelease cycle
8Releases (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.

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    A comprehensive Model Context Protocol server for real estate data management that provides tools and resources for property listings, agent management, market analysis, client relationships, and area intelligence.
    52
    AGPL 3.0
  • A
    license
    A
    quality
    C
    maintenance
    Read-only MCP server for the Daktela contact center REST API, providing 40 tools to access tickets, calls, emails, chats, contacts, CRM records, campaigns, and real-time agent status.
    45
    1
    MIT
  • A
    license
    C
    quality
    D
    maintenance
    Enterprise-level MCP server integrating with Vista CRM (Loft Edition) for real estate operations, offering 40+ tools for property search, pipeline management, lead capture, and agenda control.
    42
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    MCP server for Moody's Commercial Real Estate API, providing 37 tools for property lookups, market analytics, comps, CMBS data, tax records, and more.

View all related MCP servers

Related MCP Connectors

  • RealEstateAPI MCP — property search, detail, and skip-trace (realestateapi.com)

  • Read-only MCP server for ClassQuill, a tutoring-business-management platform.

  • 350+ production-ready APIs through one MCP server — weather, geocoding, validation, financial data.

View all MCP Connectors

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/gca-ltd/qobrix-crm-mcp'

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