NocoBase CRM MCP
MCP server for remote agents that need customer, contact, follow-up, CRM overview, and tightly scoped project write access in NocoBase.
The default stdio server remains read-only. Its managed HTTP mode adds only fixed-schema project create/update tools and authenticated attachment uploads; it never exposes arbitrary collections, fields, commands, or delete operations.
Configure
This repository already includes a local config.json generated for the current CRM. To regenerate it from the example:
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_personandcreatedBy - follow-up date/content:
f_srysmjkwfq1andf_19iplxz0nds
The default NocoBase CLI env is nb-mcp. Override it with:
export NOCOBASE_MCP_ENV=nb-mcp
export NOCOBASE_MCP_CONFIG=/home/nac/repo/nocobase-mcp/config.json
Local stdio MCP
uv run nocobase-crm-mcp --config config.json
Exposed tools:
crm_healthcrm_schemacrm_overviewcrm_filter_optionsresolve_ownerlist_customersget_customerlist_contactslist_followups
crm_config_template is hidden by default because it needs NocoBase data-modeling metadata permissions. Enable it only during configuration work:
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:
{
"error": {
"code": "nb_command_failed",
"message": "...",
"hint": "...",
"retryable": false
}
}
Project writes and uploads
Managed HTTP mode exposes two additional MCP tools:
create_project(name, customer_id?, inquiry_date?, progress?, applications?, part_numbers?, period_usage?, details?, attachment_ids?)update_project(project_id, name?, customer_id?, inquiry_date?, progress?, applications?, part_numbers?, period_usage?, details?, add_attachment_ids?, remove_attachment_ids?)
They target only t_projects and the fixed field mapping in projects in config.json. A project name is required for creation; inquiry_date uses YYYY-MM-DD; progress accepts only 询价阶段, 已报价, 送样, 已定点, SOP, or 终止. Attachments are added or removed incrementally—there is no replacement attachment-list operation.
The same HTTP service exposes authenticated POST /uploads. Submit exactly one multipart field named file; the default single-file limit is 25 MiB (NOCOBASE_MCP_UPLOAD_MAX_BYTES=26214400). A successful upload returns an upload_id, which callers can pass to either project tool. The upload route and /mcp use the same MCP bearer token.
HTTP write mode also requires one server-side NocoBase API key. The same key is supplied explicitly to every nb api CRM query and every direct HTTP upload/association request, so the service does not depend on the saved nb-mcp basic login session. Do not put these values in config.json, pass them to MCP clients, or log them:
NOCOBASE_MCP_API_BASE_URL(for examplehttps://nocobase.example/api)NOCOBASE_MCP_API_TOKEN(a scoped NocoBase API key)
Use a dedicated NocoBase account and role with only the permissions listed below. Choose an appropriate API-key validity period and rotate the key deliberately; if NocoBase rejects the key, MCP tools return nb_auth_failed or nb_upload_unauthorized instead of attempting a password login or retry loop.
scripts/mcp_service.sh start creates .runtime/nocobase-crm-mcp.env with mode 0600, its parent directory with mode 0700, and only the non-secret upload size setting. HTTP write mode fails at startup with the missing variable name when either credential is absent. For migration, the legacy pair NOCOBASE_MCP_UPLOAD_API_BASE_URL / NOCOBASE_MCP_UPLOAD_JWT remains accepted when both are present; conflicting canonical and legacy values are rejected.
First-install flow:
# Creates the private env file; the service is expected to fail until credentials are added.
bash scripts/mcp_service.sh start
# Add the server-side NocoBase API key to the systemd EnvironmentFile.
cat >> .runtime/nocobase-crm-mcp.env <<'EOF'
NOCOBASE_MCP_API_BASE_URL=https://nocobase.example/api
NOCOBASE_MCP_API_TOKEN=<scoped-api-key>
EOF
# Start the service with the newly configured private env file.
bash scripts/mcp_service.sh start
curl -X POST -H "Authorization: Bearer <mcp-token>" -F "file=@quote.pdf" http://<host>:10087/uploads
The NocoBase credentials belong in .runtime/nocobase-crm-mcp.env, not in shell-local variables or client configuration. MCP bearer-token rotation preserves these operator-managed env lines. scripts/mcp_service.sh status reports whether canonical or legacy NocoBase credentials are configured without printing their values. An uploaded attachment that is not yet associated with a project is intentionally retained; this release does not auto-clean orphan attachments. It also provides no delete operation for projects or attachments.
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 leastid,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:
nb api data-modeling collections fields list --collection-name <collection> --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.
For the read-only stdio/default server, do not grant write permissions such as collection apply/destroy, fields apply, or business data create/update/destroy.
For the managed HTTP write mode only, the NocoBase JWT role additionally needs:
t_projects: create and updateattachments: upload/createt_projects.f_projects_attachments: add and remove attachment relations
Do not grant project or attachment delete permissions. This server does not offer deletes, and it retains uploaded but unassociated attachments.
Remote HTTP MCP
HTTP mode uses streamable HTTP with a separate bearer token for MCP access:
export NOCOBASE_MCP_TOKEN='<long-random-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:
Authorization: Bearer <long-random-token>
For a managed user-level systemd service:
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:
NOCOBASE_MCP_NB_BIN=/absolute/path/to/nb bash scripts/mcp_service.sh start
The generated env file also includes the non-secret 25 MiB upload limit. The service fails at startup until the operator adds NOCOBASE_MCP_API_BASE_URL and NOCOBASE_MCP_API_TOKEN to that private file. Run start again after adding them; new-token preserves those operator-managed credential lines.
Show the saved URL/header/client config:
bash scripts/mcp_service.sh show-config
Check service state, saved paths, saved nb executable, URL, and local HTTP probe:
bash scripts/mcp_service.sh status
Stop or uninstall:
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.