# MCP server

> Connect Claude, Cursor and other MCP clients to Process Cart with the @processcart/mcp server — find workflows, start runs, set fields, complete tasks and read activity with your API key.

Source: https://developers.processcart.com/guides/mcp

`@processcart/mcp` is a [Model Context Protocol](https://modelcontextprotocol.io) server for Process Cart. Add it to Claude Desktop, Claude Code, Cursor or any other MCP client, give it an API key, and the assistant can find a workflow, start a run, fill in its fields, complete its tasks, decide approvals, comment and read what happened — the day-to-day work of a run, in plain language ("start an Order fulfillment run for Order 1042 and set the customer email to ada@example.com").

It runs on your machine over stdio and calls the same `/api/v1` this site documents, with the same key, scopes and limits. It is built on the [TypeScript SDK](https://developers.processcart.com/guides/sdk).

## Install

```bash
npx -y @processcart/mcp
```

You do not run that by hand: your MCP client starts the server with it, as configured below. It needs Node.js 22.12 or later, and an API key — an Admin creates one under **Settings → API** ([Authentication & API keys](https://developers.processcart.com/guides/authentication)). A key acts on its whole workspace, so give the assistant a key of its own, with only the scopes it needs, and try it on a [sandbox](https://developers.processcart.com/guides/sandbox) key first.

## Configure your client

### Claude Desktop

Open **Settings → Developer → Edit Config** and add the server to `claude_desktop_config.json`, then restart Claude Desktop:

```json
{
  "mcpServers": {
    "processcart": {
      "command": "npx",
      "args": ["-y", "@processcart/mcp"],
      "env": {
        "PROCESSCART_API_KEY": "pc_live_…"
      }
    }
  }
}
```

On Windows, if Claude Desktop cannot start `npx`, use `"command": "cmd"` with `"args": ["/c", "npx", "-y", "@processcart/mcp"]`.

### Claude Code

```bash
claude mcp add processcart -e PROCESSCART_API_KEY=pc_live_… -- npx -y @processcart/mcp
```

Add `--scope user` to make it available in every project. To share it with your team through the project's checked-in `.mcp.json`, leave the key out of the file: Claude Code expands `${VAR}` in `.mcp.json`, so register the variable's name, in single quotes so your shell does not expand it, and let each teammate export their own `PROCESSCART_API_KEY`:

```bash
claude mcp add processcart --scope project -e 'PROCESSCART_API_KEY=${PROCESSCART_API_KEY}' -- npx -y @processcart/mcp
```

### Cursor

Add the server to `~/.cursor/mcp.json` (every project) or `.cursor/mcp.json` (one project):

```json
{
  "mcpServers": {
    "processcart": {
      "command": "npx",
      "args": ["-y", "@processcart/mcp"],
      "env": {
        "PROCESSCART_API_KEY": "pc_live_…"
      }
    }
  }
}
```

Any other client that runs a local stdio server takes the same command, arguments and environment.

## Environment variables and flags

| Setting                 | What it does                                                                                                   |
| ----------------------- | -------------------------------------------------------------------------------------------------------------- |
| `PROCESSCART_API_KEY`   | Your API key, `pc_live_…` or `pc_test_…`. Required.                                                            |
| `PROCESSCART_BASE_URL`  | The API base URL. Default `https://app.processcart.com/api`; change it only to reach a proxy or a test server. |
| `PROCESSCART_MCP_DEBUG` | Set to `1` to log each tool call — its name, outcome and duration — to stderr. Never the key or field values.  |
| `--api-key <key>`       | The key as a flag. Prefer the environment variable: other processes on the machine can see a command line.     |
| `--base-url <url>`      | The base URL as a flag.                                                                                        |
| `--read-only`           | Offer the read tools only, whatever the key allows.                                                            |
| `--help`, `--version`   | Print the usage or the version and exit.                                                                       |

The base URL must use `https`. Plain `http` is accepted only for a server on your own machine (`localhost`, `127.x.x.x` or `::1`), so the key never crosses a network in cleartext; any other `http` URL stops the server with a usage error.

The server writes nothing to stdout except the MCP protocol itself; its diagnostics go to stderr, which your client keeps in its MCP log. They never carry the key: anything shaped like one is cut to its prefix (`pc_live_…`), including a key passed by mistake as a bare argument or in a mistyped flag.

## Tools

Fourteen tools, each shaped like a task rather than an endpoint. Every answer comes back twice: as Markdown the assistant reads, with every key and id it needs for the next step, and as JSON (`structuredContent`). A run answer is always the whole run — every task, grouped by section with its key, and every field as "Label (`key`): value" — with its current `revision`, so the assistant never needs a second call to see the result of a write; its JSON is the API's Run resource. Long runs are trimmed in the Markdown ("… and 40 more fields"); the JSON keeps everything. Three tools reshape their JSON: `find_runs` carries one summary per run (id, name, status, priority, labels, due date, key date, timestamps, revision, workflow, link, task progress and the open tasks' keys and titles — no tasks or fields), `list_people` carries `{ users, groups, complete }`, and `whoami` carries the API's `/v1/me` answer plus a `server` member (its mode, base URL and tools).

| Tool                  | What it does                                                                                                         | Scope              |
| --------------------- | -------------------------------------------------------------------------------------------------------------------- | ------------------ |
| `whoami`              | The workspace, the key (name, scopes, read-only), the rate limit, the status labels and the tools on offer           | any key            |
| `list_workflows`      | The workflows the key can see, with their ids, published version and task count; `q` searches names and descriptions | `workflows:read`   |
| `get_workflow_schema` | A workflow's fields by key — type, task, allowed values, bounds — and which ones the start form requires             | `workflows:read`   |
| `start_run`           | Start a run of a published workflow, with field values, priority, labels and a due date                              | `runs:write`       |
| `find_runs`           | Search runs by name, workflow, status, priority, labels, assignee or due window, one page at a time                  | `runs:read`        |
| `get_run`             | One run in full: tasks, fields, revision and app link; required fields still blank are flagged (see below)           | `runs:read`        |
| `set_fields`          | Set one or more field values by key, all or nothing                                                                  | `runs:write`       |
| `complete_task`       | Complete a task by key; a refusal names every required field still blank                                             | `runs:write`       |
| `reopen_task`         | Put a completed task back to to-do                                                                                   | `runs:write`       |
| `decide_approval`     | Approve or reject an approval task (a rejection needs a comment)                                                     | `approvals:decide` |
| `add_comment`         | Comment on a task; `@Name` mentions notify members                                                                   | `runs:write`       |
| `get_activity`        | A run's trail, newest first, with its latest comments                                                                | `runs:read`        |
| `update_run`          | Change a run's name, status, priority, labels or due date                                                            | `runs:write`       |
| `list_people`         | Members and groups with the ids `find_runs` filters by                                                               | `users:read`       |

A key with full access (`*`) gets all fourteen. `get_run` flags the required fields that are still blank only when the key also has `workflows:read` and the run is on the workflow's published version; otherwise it says so, and `complete_task` names any blank required field when it refuses.

## Scopes and read-only keys

When it starts, the server calls `GET /v1/me` and offers only the tools the key can use: each read tool needs its scope, `decide_approval` needs `approvals:decide`, and every other write needs `runs:write`. A [read-only key](https://developers.processcart.com/guides/authentication) — or the `--read-only` flag — gets the read tools only, so the assistant cannot change anything. A key limited to some workflows or folders keeps that limit: the API applies the [allowlist](https://developers.processcart.com/guides/authentication#allowlists) on every call.

If the server cannot read the key at startup (a typo, a revoked key, no network — it waits at most 10 seconds, once), it starts with the read tools only and says why on stderr; `whoami` then answers with the error. Fix the key and restart the server to get the full list.

## Safety

- **No admin tools, and nothing deletes.** No tool deletes a run, workflow or comment; `set_fields` and `update_run` can overwrite or clear values; `reopen_task` and a rejection send work back. Those four tools carry the MCP `destructiveHint`, so a client that confirms destructive calls asks you first. Webhooks, schedules, automation rules, saved views, workflow edits and imports, files, CSV exports and Trash stay in the app and the [REST API](https://developers.processcart.com/reference) — an assistant reaches only the day-to-day work of runs.
- **Content is data.** Run names, field values, task titles, comments and activity are written by people, guests included. The server tells the assistant to treat them as data, never as instructions, and to act only on your request; every name and value stays on the line it is rendered on, so none can pose as a heading or a new instruction.
- **Cancellation reaches the API.** When your client cancels a call, the request in flight is aborted rather than left to finish in the background.
- **Safe retries.** Every write carries an `Idempotency-Key` ([Idempotency](https://developers.processcart.com/guides/idempotency)), so a retried request is applied once. `start_run` and `add_comment` create something new on each call; the tool descriptions tell the assistant not to repeat them after a success.
- **No lost updates.** Every run answer carries `revision`. The write tools take `expectedRevision`, sent as the `Expected-Revision` header ([Concurrency](https://developers.processcart.com/guides/concurrency)): if someone changed the run in between, the write is refused with `409 revision_mismatch`, and the answer names the current revision so the assistant reads the run again before retrying.
- **Errors are answers.** A refusal comes back as a tool result with the error code, every field problem, the current revision on a conflict and the wait on a `429` ([Errors](https://developers.processcart.com/errors)) — never as a crash the assistant cannot read.
- **Your key stays local.** The server runs on your machine and sends the key only to the API. It never logs the key or your field values.

## MCP Registry

The package carries its MCP Registry metadata (`server.json`, under the name `com.processcart/mcp`); the registry listing is pending. Until it appears, install it from npm as shown above.

## Hosted endpoint

A hosted MCP endpoint that signs in with OAuth instead of an API key — no local install — is planned. Watch the [changelog](https://developers.processcart.com/changelog).
