suitecrm-mcp

by anirudhx7

Not rated
GitHub

About

MCP gateway for SuiteCRM : SSE transport, 13 tools, single and multi-entity install with systemd + nginx

Details

Author
anirudhx7
Categories
Productivity, Other, Automation

Setup

Install suitecrm-mcp in your MCP client (Claude Desktop, Cursor, Windsurf, and others).

Repository: https://github.com/anirudhx7/suitecrm-mcp

Follow the installation instructions in the repository README, then restart your MCP client.

Securely connect AI agents to your enterprise CRM in under 5 minutes. Production-ready.

An open-source MCP (Model Context Protocol) gateway for SuiteCRM. Lets AI assistants likeClaude Desktop,Claude Code, andOpenClawread and write your CRM data via a secure, persistent SSE connection.

Built from a real production deployment. Commercial alternatives are expensive; this one is free and open-source.

Ships with astateless architecture powered by Redisfor horizontal scaling, and a full observability stack: Prometheus metrics, Grafana dashboards (33 panels), and Loki log aggregation.

Built for production environments where data integrity and privacy are non-negotiable.

- Zero-Trust for Credentials:CRM passwordsneverleave the gateway server. MCP clients (like Claude) hold only an opaque, revocable API key.
- Identity First:Seamlessly integrates withAuth0,Azure AD, or any OIDC provider.
- Audit Ready:Every tool call is logged with structured JSON (Loki), allowing you to see exactly what your AI agents are doing in real-time.
- Circuit Breaker Protection:Automatically shields your CRM from cascading failures if the backend becomes unresponsive.

- 24 toolscovering full CRUD, activity logging (calls, tasks, notes), bulk operations, file attachments, dropdown introspection, and more
- SSE transport- compatible with Claude Desktop, Claude Code, OpenClaw, and any MCP client that supports HTTP+SSE
- OAuth2/OIDC authentication- users log in via Auth0, Azure AD, or any OIDC provider; the gateway issues personal, revocable API keys
- No credentials on client machines- MCP clients hold only an opaque API key; CRM passwords live on the gateway
- Group-based entity access- JWT group claims gate which CRM instances each user can reach
- Session auto-renewal- CRM sessions re-authenticate transparently on expiry
- Stateless & Scalable- auth sessions and profiles cached in Redis, enabling zero-downtime restarts and horizontal scaling behind a load balancer with sticky session routing (SSE connections are per-process; the/messagesendpoint must reach the same process that owns the SSE transport)
- Unified installer- one script handles single CRM (no nginx) or N CRMs behind nginx, with interactive OAuth setup
- Entity-prefixed tools- run multiple CRM instances side-by-side without name collisions
- Admin reporting-mcp-admin reportgenerates browsable HTML activity reports from Loki and SQLite, with per-user drill-down showing call history, dry runs, and errors with module and field detail

Replace{prefix}with your configuredSUITECRM_PREFIX(default:suitecrm).

Supported modules include: Accounts, Contacts, Leads, Opportunities, Cases, Calls, Meetings, Tasks, Notes, Emails, Documents, Campaigns, AOS_Quotes, AOS_Invoices, AOS_Products, AOS_Contracts, AOR_Reports, AOW_WorkFlow, SecurityGroups - and any custom modules in your instance.

%%{init: {"flowchart": {"curve": "linear"}}}%% flowchart TB IdP["🔐 Auth0 / Azure AD\nIdentity Provider"] subgraph Clients["MCP Clients"] CD["Claude Desktop"] ~~~ CC["Claude Code"] ~~~ OC["OpenClaw"] end GW["⚡ suitecrm-mcp gateway\nOAuth2 · API keys · SSE"] subgraph CRMs["SuiteCRM Instances"] C1[("CRM A")] ~~~ C2[("CRM B")] ~~~ CX[("CRM X")] end IdP -.->|"confirms identity (OAuth2 callback)"| GW GW -.->|"issues API key"| Clients Clients -->|"Bearer token"| GW GW -->|"Hybrid v8 GraphQL\n(v4_1 Fallback)"| CRMs style GW fill:#2b6cb0,stroke:#63b3ed,stroke-width:2px,color:#fff style IdP fill:#2d3748,stroke:#718096,color:#e2e8f0 style CD fill:#2a4a7f,stroke:#63b3ed,stroke-width:1px,color:#ebf8ff style CC fill:#2a4a7f,stroke:#63b3ed,stroke-width:1px,color:#ebf8ff style OC fill:#2a4a7f,stroke:#63b3ed,stroke-width:1px,color:#ebf8ff style C1 fill:#553c9a,stroke:#b794f4,stroke-width:1px,color:#faf5ff style C2 fill:#553c9a,stroke:#b794f4,stroke-width:1px,color:#faf5ff style CX fill:#553c9a,stroke:#b794f4,stroke-width:1px,color:#faf5ff style Clients fill:#0d1b2e,stroke:#4299e1,stroke-width:1px,color:#90cdf4 style CRMs fill:#1a0533,stroke:#9f7aea,stroke-width:1px,color:#d6bcfa

Users log in once via Auth0 or Azure AD; the gateway issues a personal API key. MCP clients attach it asAuthorization: Bearer <key>on every request. CRM credentials never leave the gateway. Multiple CRM instances are supported - each gets its own port and tool namespace (suitecrm_crm1_,suitecrm_crm2_).

Smart Hybrid Routing:The gateway automatically routes basic CRUD operations and record fetching through the blazing-fast SuiteCRM 8 GraphQL API. If an AI requests a complex search requiring raw SQL filters (which GraphQL does not support), the gateway intercepts it and transparently fails over to the legacy v4.1 REST API-ensuring absolute 100% feature parity with no manual intervention.

Stateless Persistence:By moving auth sessions and user profiles from local memory/files to Redis, the gateway is completely stateless. This allows for horizontal scaling (running multiple gateway instances behind a load balancer), global rate limiting, and seamless restarts without dropping active AI connections. When running multiple instances behind a load balancer, sticky session routing is required: SSE transports and their/messagesendpoint must land on the same process.

Ships with a complete observability stack indocker-compose.yml- one command starts everything alongside the gateway.

Alerting rules included for: circuit breaker open, high auth failure rate, latency SLO breach, session expiry storms.

mcp-admin reportgenerates an HTML activity report from both sources - Loki supplies historical calls, SQLite covers the current period, and the two are merged automatically. Default period is daily;--period weeklyand--period monthlyare also supported.--servepublishes the report at/reportvia nginx.--user <email>drills down to a single user's calls, dry runs, and errors with module and field detail.

- Ubuntu 20.04+ or Debian 11+ (the installers useapt,systemd, andnginx)
- Python 3.8+
- Root / sudo access
- Node.js is installed automatically if missing
- Redis 6.0+(required for session and profile persistence)

Before connecting, make sure your CRM user has API access enabled:
- Log into SuiteCRM as admin
- Go toAdmin → User Management→ open the user you'll authenticate with
- Check"Is Admin"OR set"API User"to Yes (the field name varies by SuiteCRM version)
- Save

If API access isn't enabled, the gateway returns HTTP 401 withCRM authentication failed: Invalid Loginimmediately on connection - this is the most common first-run failure.

For production: create a dedicated API user with only the module permissions your AI assistant needs. Don't use the admin account.

For one CRM with automatic HTTPS and OAuth login.

Requirements:Ubuntu/Debian, Python 3.8+, root access, a domain pointing to this server, OAuth app credentials (seedocs/auth0-setup.md)

git clone https://github.com/anirudhx7/suitecrm-mcp.git cd suitecrm-mcp sudo python3 install.py \ --url https://your-crm.example.com \ --domain mcp.yourserver.com \ --email you@example.com

The installer will prompt for OAuth configuration (issuer, client ID/secret, audience, gateway URL), then set up nginx, certbot, and systemd automatically.

After install, users authenticate athttps://mcp.yourserver.com/auth/loginto get their API key.

Verify it's working in Claude Desktop:

After adding the MCP server config (seedocs/connect-claude-desktop.md) and restarting Claude Desktop, click the hammer icon. You should see 24 tools:suitecrm_search,suitecrm_get, etc.

Try a test prompt:"List the first 5 accounts in the CRM"- Claude should callsuitecrm_searchautomatically.

For N CRM instances behind nginx - each gets its own port and path.

cp entities.example.json entities.json # Edit entities.json with your CRM endpoints and ports
sudo python3 install.py --config entities.json

3. Enable HTTPS (recommended for production):

Pass--domainand--email. The installer updates the nginx config with your domain and runs certbot automatically.

sudo python3 install.py --config entities.json \ --domain mcp.yourserver.com \ --email you@example.com

The domain must already point to this server's public IP, and ports 80 and 443 must be open. After this step the gateway is available athttps://mcp.yourserver.com/<code>/sse.

Once configured, the domain is saved automatically. Later--addand--removeruns preserve HTTPS without needing--domainagain.

4. Open the nginx port(if using ufw, HTTP-only installs only):

5. Test a specific entity:After authenticating at/auth/loginand getting an API key:

curl -s -H "Authorization: Bearer your_api_key_here" \ http://YOUR_SERVER:8080/crm1/test # Expected: {"success":true,"crm_user":"...","email":"...","entity":"crm1"}

6. Connect at:http://YOUR_SERVER:8080/<code>/sse(orhttps://your-domain/<code>/sseif HTTPS is enabled)

Verify it's working in Claude Desktop:After restarting Claude Desktop, click the hammer icon. You should see 24 tools per entity:suitecrm_crm1_search,suitecrm_crm2_search, etc.

Add entities later (no downtime on existing):

sudo python3 install.py --add --config entities.json

The fastest way to run the gateway without touching Node.js or system packages. A pre-built image is published to GitHub Container Registry on every push tomain.

For production, pin to a release tag such asv5.4.0instead of floating onlatest.

curl -o docker-compose.yml https://raw.githubusercontent.com/anirudhx7/suitecrm-mcp/v5.4.0/docker-compose.yml

Create your entity config (the auth service reads this to build MCP client commands):

cp entities.example.json entities.json # edit entities.json - set endpoint, port, group for your CRM

Editdocker-compose.ymland fill inSUITECRM_ENDPOINT,AUTH0_*vars, andGATEWAY_PUBLIC_URL, then:

The gateway runs athttp://localhost:3101. Visit/auth/loginto authenticate and get an API key.

To update to a newer pinned release, change the image tag indocker-compose.ymland redeploy:

docker compose pull && docker compose up -d

Upgrading from pre-v5.0.0:v5.0.0 introduced a stateless Redis architecture. If you have an existingsuitecrm-statenamed volume created by an older image, it is no longer used for SQLite. A new Redis container and volume will be provisioned automatically.

docker compose down docker volume rm suitecrm-mcp_suitecrm-state docker compose up -d

All persistent state (sessions, profiles) lives in this volume. Recreating it clears those files - users will need to log in again.

For self-signed CRM certificates, addNODE_TLS_REJECT_UNAUTHORIZED: "0"to the environment block. For HTTPS termination (required for OAuth in production), put a reverse proxy (nginx, Caddy) in front.

Each container handles exactly one CRM entity. For N entities, add N service blocks todocker-compose.yml, each on its own port.

Full multi-entity compose example (two entities)

services: suitecrm-mcp-auth: image: ghcr.io/anirudhx7/suitecrm-mcp:v5.4.0 command: node auth.mjs working_dir: /app ports: - "127.0.0.1:3100:3100" - "127.0.0.1:9091:9091" # auth metrics (Prometheus) environment: AUTH0_DOMAIN: your-tenant.auth0.com AUTH0_CLIENT_ID: your-client-id AUTH0_CLIENT_SECRET: your-client-secret AUTH0_AUDIENCE: https://your-api-identifier GATEWAY_PUBLIC_URL: https://mcp.yourdomain.com SESSION_TTL_DAYS: "30" PORT: "3100" METRICS_PORT: "9091" METRICS_BIND: "0.0.0.0" # 0.0.0.0 required so the Prometheus container can reach it by service name restart: unless-stopped suitecrm-mcp-crm1: image: ghcr.io/anirudhx7/suitecrm-mcp:v5.4.0 ports: - "127.0.0.1:3101:3101" # expose via reverse proxy only - "127.0.0.1:9101:9090" # entity metrics (Prometheus) environment: SUITECRM_ENDPOINT: https://crm1.example.com/legacy/service/v4_1/rest.php SUITECRM_PREFIX: suitecrm_crm1 SUITECRM_CODE: crm1 AUTH0_DOMAIN: your-tenant.auth0.com AUTH0_AUDIENCE: https://your-api-identifier REQUIRED_GROUP: crm1_users PORT: "3101" METRICS_PORT: "9090" METRICS_BIND: "0.0.0.0" depends_on: suitecrm-mcp-auth: condition: service_healthy restart: unless-stopped suitecrm-mcp-crm2: image: ghcr.io/anirudhx7/suitecrm-mcp:v5.4.0 ports: - "127.0.0.1:3102:3102" # expose via reverse proxy only - "127.0.0.1:9102:9090" # entity metrics (Prometheus) environment: SUITECRM_ENDPOINT: https://crm2.example.com/legacy/service/v4_1/rest.php SUITECRM_PREFIX: suitecrm_crm2 SUITECRM_CODE: crm2 AUTH0_DOMAIN: your-tenant.auth0.com AUTH0_AUDIENCE: https://your-api-identifier REQUIRED_GROUP: crm2_users PORT: "3102" METRICS_PORT: "9090" METRICS_BIND: "0.0.0.0" depends_on: suitecrm-mcp-auth: condition: service_healthy restart: unless-stopped

- Service name (suitecrm-mcp-crm1,suitecrm-mcp-crm2,...)
- SUITECRM_ENDPOINT- the REST API URL for that specific CRM (the path after the domain varies by SuiteCRM installation)
- SUITECRM_CODE- short identifier used in tool names and URL routing (e.g.crm1gives tools namedsuitecrm_crm1_search,suitecrm_crm1_get, etc.)
- PORTand the host port mapping - each entity needs its own port (3101, 3102,...)

What stays the same across all entities:

- AUTH0_DOMAINandAUTH0_AUDIENCE- one Auth0 app handles all entities
- The auth service (suitecrm-mcp-auth) is shared; entity containers depend on it

Put a reverse proxy (nginx, Caddy) in front to route/crm1/to port 3101,/crm2/to port 3102, and/auth/to any one instance. For production use with multiple CRMs,install.py --config entities.jsonhandles all of this automatically on a Linux host.

{ "crm1": { "label": "My Company CRM", "endpoint": "https://crm.mycompany.com/service/v4_1/rest.php", "port": 3101 }, "crm2": { "label": "Client B CRM", "endpoint": "https://crm.clientb.com/service/v4_1/rest.php", "port": 3102, "tls_skip": true } }

Keys become the entity code (nginx path prefix, tool prefix suffix, service name). Ports must be unique.

Pass--domainand--emailto the installer to enable HTTPS on the gateway itself. The installer sets up nginx as a TLS-terminating reverse proxy and runs certbot to obtain and auto-renew a certificate.

- Domain must already point to this server's public IP
- Ports 80 (ACME challenge) and 443 (HTTPS) must be open

If certbot fails during install, the gateway still runs over HTTP. Fix DNS/firewall and re-run:

certbot --nginx -d your.domain.com -m you@example.com --agree-tos --redirect

If your SuiteCRM uses a self-signed certificate, add"tls_skip": trueto the entity config (multi) or pass--tls-skip(single). This setsNODE_TLS_REJECT_UNAUTHORIZED=0.

Only use this on trusted internal networks. Never expose a TLS-skipping gateway to the public internet.

Any MCP client that supports SSE transport with custom request headers will work. Each client has a different setup process - see the dedicated guide for your client:

Claude Desktop and Claude Codeconnect directly to the gateway URL over SSE. After installing the gateway, add the SSE endpoint and your CRM credentials to your client config. Full steps including single/multi entity configs, HTTPS variants, and verification are in the guides above.

OpenClawuses a two-component setup: the gateway runs on a remote server (installed viainstall.py) and a bridge plugin runs locally on the OpenClaw machine (installed viainstall-bridge.py). The bridge proxies all 24 SuiteCRM tools through to the gateway. The OpenClaw guide covers both components end to end.

# Shallow health curl http://YOUR_SERVER:3101/health # {"status":"ok","entity":"crm1","port":3101,"active":2,"circuit_breaker":"closed"} # Deep health (pings CRM, returns latency) curl http://YOUR_SERVER:3101/health/deep # {"status":"healthy","entity":"crm1","uptime":3600,"connections":2,"circuit_breaker":"closed", # "checks":{"endpoint":{"status":"ok","url":"https://crm.example.com"}, # "api":{"status":"ok","latency_ms":45}, # "sessions":{"status":"ok","active":2}},"duration_ms":47}

/health/deepreturns HTTP 200 when healthy, 503 when the CRM is unreachable. Rate-limited to 10 requests/minute.

Two components expose Prometheus metrics on separate ports (localhost only).

Gateway entity metrics(default port 9090)

No reviews yet — be the first

Sign in to leave a review

Use Google, GitHub, or an email account so ratings stay tied to real people.

Email sign in

No reviews posted yet.