Files
nocobase-mcp/README.md
T
nac 7385d1de82 Merge branch 'feat/project-write-upload'
# Conflicts:
#	README.md
#	nocobase_crm_mcp/server.py
#	scripts/manage_mcp_service.py
#	tests/test_mcp_service.py
#	tests/test_nb_client.py
#	tests/test_server.py
2026-07-13 03:00:21 +00:00

199 lines
8.8 KiB
Markdown

# 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:
```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
}
}
```
## 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 these server-side NocoBase credentials. Do not put them in `config.json`, pass them to MCP clients, or log them:
- `NOCOBASE_MCP_UPLOAD_API_BASE_URL` (for example `https://nocobase.example/api`)
- `NOCOBASE_MCP_UPLOAD_JWT` (a NocoBase user JWT)
`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.
First-install flow:
```bash
# Creates the private env file; the service is expected to fail until credentials are added.
bash scripts/mcp_service.sh start
# Add server-side NocoBase credentials to the systemd EnvironmentFile.
cat >> .runtime/nocobase-crm-mcp.env <<'EOF'
NOCOBASE_MCP_UPLOAD_API_BASE_URL=https://nocobase.example/api
NOCOBASE_MCP_UPLOAD_JWT=<user-jwt>
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. Token rotation preserves these operator-managed env lines. 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 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 <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 update
- `attachments`: upload/create
- `t_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:
```bash
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:
```http
Authorization: Bearer <long-random-token>
```
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
```
The generated env file also includes the non-secret 25 MiB upload limit. The service fails at startup until the operator adds `NOCOBASE_MCP_UPLOAD_API_BASE_URL` and `NOCOBASE_MCP_UPLOAD_JWT` 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
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.