Receive the opt-in daily totals of the local npm package
For the local npm package (@buun_group/plotwork-mcp) only, and only when the person who runs it has set PLOTWORK_USAGE=share; it is off by default, and setting DO_NOT_TRACK=1 stops the package from ever sending.
/telemetry/usageTL;DR
| Question | Answer |
|---|---|
| What does it do? | Receive the opt-in daily totals of the local npm package. |
| What does it take? | A JSON body of type LocalUsageBody. |
| What does it return? | Status 200 with a body of type LocalUsageAck. |
| What can go wrong? | 400 the body is not valid json, has a field the schema does not name, or breaks a bound. the answer lists the first problems; 413 the body is larger than 64 kib; 429 too many requests; 503 this server has no database. Every failure uses the one error envelope. |
What it does
For the local npm package (@buun_group/plotwork-mcp) only, and only when the person who runs it has set PLOTWORK_USAGE=share; it is off by default, and setting DO_NOT_TRACK=1 stops the package from ever sending. The body is pseudonymous daily totals for finished days: a random install id that changes every month, counts of how often each local tool ended in each way for each kind of diagram, the package version, the operating system family, and the Node major version. It never carries diagram source, tool arguments or results, names, folders, paths, error text, host names, user names, environment variables, or the time of day. Plotwork stores no address, header, account, or time beyond the day with it. The route is rate limited by the caller's address, which Cloudflare's rate limiter holds as a counter key for 60 seconds; Plotwork's own code does not store it. There is no session, key, or cookie. A count whose tool or kind the server does not know is dropped and counted as ignored. A count sent again replaces the one stored. The totals are indicative: anyone can post to a public route, so they are never used for limits, billing, or anything about an account. Rows are kept for 400 days.
Request body
The body has the type LocalUsageBody.
| Field | Type | Required | Description |
|---|---|---|---|
schema | 1 | yes | The version of this request shape. Always 1. |
client | LocalUsageClient | yes | |
client.name | "plotwork-mcp" | yes | Always plotwork-mcp. |
client.version | string | yes | The package version, in semver form. at most 40 characters; pattern ^\d{1,6}\.\d{1,6}\.\d{1,6}(?:-[0-9A-Za-z.-]{1,32})?(?:\+[0-9A-Za-z.-]{1,32})?$. |
client.os | "linux" | "darwin" | "win32" | "other" | yes | The operating system family. Anything else is other. |
client.node | integer | yes | The Node major version, a whole number. minimum 18; maximum 99. |
days | LocalUsageDay[] | yes | At most 31 finished days. |
days[].day | string | yes | A UTC date from 40 days ago to yesterday. Nothing is accepted for today. pattern ^\d{4}-\d{2}-\d{2}$. |
days[].id | string | yes | A pseudonym for one install for one month: the first 128 bits of an HMAC-SHA-256 of plotwork-usage: and the month, keyed with a secret that never leaves the device. It changes every month, so installs can be counted within a month and cannot be followed from one month to the next. pattern ^[0-9a-f]{32}$. |
days[].counts | LocalUsageCount[] | yes | At most 400 counts. A tool, kind, and outcome may appear once a day. |
days[].counts[].tool | string | yes | The name of the local MCP tool, such as draw_diagram. A name this server does not know is ignored, not refused, so an older server accepts a newer package. pattern ^[a-z][a-z0-9_]{0,63}$. |
days[].counts[].kind | string | yes | The diagram kind the source declared, such as flow, or none for a call with no source or one that names no kind. A kind this server does not know is ignored, not refused, so an older server accepts a newer package. pattern ^[a-z][a-z0-9]{0,31}$. |
days[].counts[].outcome | "ok" | "rejected" | "error" | yes | ok produced its answer, rejected was refused because of its input, error failed inside the tool. |
days[].counts[].count | integer | yes | A whole number from 1 to 1,000,000. minimum 1; maximum 1000000. |
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 | The request was understood: how many counts were stored, and how many were ignored because their tool is not known. | LocalUsageAck |
| 400 | The body is not valid JSON, has a field the schema does not name, or breaks a bound. The answer lists the first problems. | ErrorResponse |
| 413 | The body is larger than 64 KiB. | ErrorResponse |
| 429 | Too many requests. | ErrorResponse |
| 503 | This server has no database. | ErrorResponse |
Response body
A 200 answer has the type LocalUsageAck.
| Field | Type | Required | Description |
|---|---|---|---|
accepted | integer | yes | How many counts were stored. A count sent again replaces the one stored, so a retry never adds twice. minimum 0. |
ignored | integer | yes | How many counts were dropped because their tool or kind is not one this server knows. A 200 means the client may treat the days as sent. minimum 0. |
See also
| Doc | Why |
|---|---|
| API reference | Every endpoint, and the error envelope |
| Schemas | Every request and response type |
| Tool reference | The operations as callable tools |