# NocoBase CRM MCP Read-only MCP server for remote agents that need customer, contact, follow-up, and CRM overview data from NocoBase. The server calls the official `nb api resource list|get|query` commands. It does not expose create, update, destroy, or arbitrary command execution tools. ## Configure This repository already includes a local `config.json` generated for the current CRM. To regenerate it from the example: ```bash cp config.example.json config.json ``` The known CRM collection names in this environment are: - customers: `t_nt3pjadelqi` (`客户`) - contacts: `t_j77ftx1rf84` (`客户联系人`) - followups: `t_07667a5evtr` (`跟进记录`) The checked-in example config uses the confirmed mapping: - customer owner: `kehu_followup_person` (`跟进人`) - customer status/progress: `kh_progress` (`进度`) - customer source: `f_225h6n6v654` (`客户来源`) - contact-to-customer relation: `kehulianxiren_client` - follow-up-to-customer relation: `gjjl_client` - follow-up-to-contact relation: `gjjl_client_contacts` - follow-up owner fields: `gjjl_followup_person` and `createdBy` - follow-up date/content: `f_srysmjkwfq1` and `f_19iplxz0nds` The default NocoBase CLI env is `nb-mcp`. Override it with: ```bash export NOCOBASE_MCP_ENV=nb-mcp export NOCOBASE_MCP_CONFIG=/home/nac/repo/nocobase-mcp/config.json ``` ## Local stdio MCP ```bash uv run nocobase-crm-mcp --config config.json ``` Exposed tools: - `crm_health` - `crm_schema` - `crm_overview` - `crm_filter_options` - `resolve_owner` - `list_customers` - `get_customer` - `list_contacts` - `list_followups` `crm_config_template` is hidden by default because it needs NocoBase data-modeling metadata permissions. Enable it only during configuration work: ```bash NOCOBASE_MCP_ENABLE_CONFIG_TOOLS=1 uv run nocobase-crm-mcp --config config.json ``` The `owner` parameter on `crm_overview`, `list_customers`, and `list_followups` accepts a user's username, nickname, email, or English name. The server resolves that value through the `users` resource, then filters CRM relation fields by user id. If the value is missing or ambiguous, the tool returns a structured `error` object with candidate users instead of throwing an MCP error. Remote agents should call `resolve_owner` first when they are unsure which user the requester means. Use `crm_filter_options` to discover status/source values and owner candidates before constructing filtered queries. Status/source options are sorted by count descending, with blank source values last. List tools clamp `limit` to `1..100` and normalize negative offsets to `0`. `list_customers`, `list_contacts`, and `list_followups` return compact rows by default so remote agents do not receive large nested NocoBase relation payloads. Pass `include_raw=true` only when the original NocoBase row is needed; the raw row is then attached under `raw`. `list_followups` returns `content_preview` in compact mode. Use `include_raw=true` when the full follow-up text is needed. `get_customer` keeps the customer detail record intact, and its related follow-ups stay compact unless `include_raw_followups=true`. Tool runtime failures are returned as structured errors: ```json { "error": { "code": "nb_command_failed", "message": "...", "hint": "...", "retryable": false } } ``` ## Permissions Runtime tools are read-only, but the role behind `nb-mcp` needs these read permissions: - CRM collections: `t_nt3pjadelqi`, `t_j77ftx1rf84`, `t_07667a5evtr` - user lookup collection: `users`, at least `id`, `username`, `nickname`, `email`, `f_yh_english_name` `crm_schema(include_fields=true)` and the opt-in `crm_config_template` are configuration helpers. They use this read-only NocoBase data-modeling command: ```bash nb api data-modeling collections fields list --collection-name --env nb-mcp --yes ``` Use a super-admin or configuration-capable role for this one-time discovery step. The remote Agent does not need data-modeling access after `config.json` is generated. Do not grant write permissions such as collection apply/destroy, fields apply, or business data create/update/destroy for this MCP. ## Remote HTTP MCP HTTP mode uses streamable HTTP with a separate bearer token for MCP access: ```bash export NOCOBASE_MCP_TOKEN='' uv run nocobase-crm-mcp --transport streamable-http --config config.json ``` Default bind is `0.0.0.0:10087` with path `/mcp`. Remote clients must send: ```http Authorization: Bearer ``` For a managed user-level systemd service: ```bash bash scripts/mcp_service.sh start ``` The first `start` creates `.runtime/nocobase-crm-mcp.env` with a random bearer token automatically. It also discovers the current `nb` executable and saves it as `NOCOBASE_MCP_NB_BIN`, because the systemd user service does not inherit an interactive shell or nvm PATH. Use `new-token` only when rotating the token later. If `nb` is installed somewhere unusual, set its absolute path before starting: ```bash NOCOBASE_MCP_NB_BIN=/absolute/path/to/nb bash scripts/mcp_service.sh start ``` Show the saved URL/header/client config: ```bash bash scripts/mcp_service.sh show-config ``` Check service state, saved paths, saved `nb` executable, URL, and local HTTP probe: ```bash bash scripts/mcp_service.sh status ``` Stop or uninstall: ```bash bash scripts/mcp_service.sh stop bash scripts/mcp_service.sh uninstall ``` The systemd unit references `.runtime/nocobase-crm-mcp.env`; it does not embed the bearer token. The env file is written with `0600` permissions and `.runtime/` is ignored.