@sanity/workflow-mcp 0.33.0 → 0.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @sanity/workflow-mcp
2
2
 
3
+ ## 0.35.0
4
+
5
+ ### Patch Changes
6
+
7
+ - a43248f: The MCP server now sends queued adoption telemetry when a client disconnects normally by closing stdin.
8
+
9
+ **No upgrade action required.** Existing MCP client configurations receive the fix when they update the server package.
10
+
11
+ **Docs impact: None** because this corrects telemetry delivery without changing the MCP tools or their public behavior.
12
+
13
+ - Updated dependencies [7e24e4a]
14
+ - Updated dependencies [ab8754a]
15
+ - @sanity/workflow-engine@0.35.0
16
+
17
+ ## 0.34.0
18
+
19
+ ### Patch Changes
20
+
21
+ - @sanity/workflow-engine@0.34.0
22
+
3
23
  ## 0.33.0
4
24
 
5
25
  ### Patch Changes
package/README.md CHANGED
@@ -105,20 +105,21 @@ Definition content is unaffected (deploy expands and vets it).
105
105
 
106
106
  ### Telemetry
107
107
 
108
- The stdio server reports adoption telemetry to Sanity: one
109
- `Workflows MCP Tool Called` event per tool invocation carrying the
110
- tool name, a success flag, and whether a list cursor was supplied — from every
111
- tool it registers, `workflows_list_tags` included, through one shared outcome
112
- path. Cursor
113
- values, other tool arguments, and results are never sent. This makes continued
114
- page usage measurable without collecting customer content. The org-authed boot
115
- has no project to attribute intake to, so the store initializes with the first
116
- call that names a dataset resource; calls before that one send nothing. The
117
- server also reports the engine's own adoption
118
- events. Nothing is sent unless the account's telemetry consent resolves to
119
- granted (the account-wide status `sanity telemetry status` shows). Set
120
- `DO_NOT_TRACK=1` to opt a process out; CI environments (`CI` set) never
121
- send. Separately from consent, every Content Lake request the server issues
108
+ The stdio server reports adoption telemetry to Sanity. Nothing is sent unless
109
+ the account's telemetry consent resolves to granted (the account-wide status
110
+ `sanity telemetry status` shows). Set `DO_NOT_TRACK=1` to opt a process out;
111
+ CI environments (`CI` set) never send. The org-authed boot has no project to
112
+ attribute intake to, so the store initializes with the first call that names
113
+ a dataset resource; calls before that one send nothing. Address-free tools
114
+ (`workflows_get_authoring_guide`, `workflows_validate_definition`) therefore
115
+ emit nothing until some earlier call has addressed a dataset.
116
+
117
+ Payloads never include customer-authored strings: no tool arguments, cursor
118
+ values, results, definition names, stage names, GROQ, or document content.
119
+ The one instance-scoped exception the engine already ships is `instanceId`
120
+ (the instance document `_id`).
121
+
122
+ Separately from consent, every Content Lake request the server issues
122
123
  carries a request tag under the `sanity.workflows-mcp` prefix (composing as
123
124
  `sanity.workflows-mcp.<op>`) for request-log attribution — deliberately outside
124
125
  the zero-rated `sanity.workflows.*` family, so agent-driven traffic bills.
@@ -134,6 +135,72 @@ alongside `context.environment`. Environment does not identify a production
134
135
  dataset or deployment; the API host, dataset name, and workflow tag do not
135
136
  set it. Existing telemetry consent and opt-out settings still apply.
136
137
 
138
+ An embedding host that calls `registerWorkflowTools` without a `telemetry`
139
+ logger records no MCP events. Engine events still require that host to pass
140
+ the same logger into `createEngine({telemetry})`.
141
+
142
+ #### Session properties
143
+
144
+ The built-in store attaches these user properties once, when the first dataset
145
+ resource is addressed (joined to events by session id). User identity is not
146
+ in the payload; the intake service resolves the sender from the authenticated
147
+ session. There is no `orgId`: attribution uses the project-to-org join
148
+ downstream.
149
+
150
+ | Property | What it is |
151
+ | ----------------- | --------------------------------------------------- |
152
+ | `surface` | Always `'mcp'`. |
153
+ | `machinePlatform` | Node `process.platform`. |
154
+ | `cpuArchitecture` | Node `process.arch`. |
155
+ | `runtime` | Always `'node'` for the stdio server. |
156
+ | `runtimeVersion` | Node `process.version`. |
157
+ | `packageVersion` | This package's version. |
158
+ | `projectId` | Project id of the first addressed dataset resource. |
159
+ | `dataset` | Dataset of that same resource. |
160
+
161
+ #### MCP events
162
+
163
+ This package defines one event. Every tool it registers — the `WORKFLOW_TOOLS`
164
+ defs and host-registered `workflows_list_tags` — shares one outcome path, so
165
+ adoption, the result envelope, and error rendering cannot diverge.
166
+
167
+ ##### `Workflows MCP Tool Called` (version 2)
168
+
169
+ One event per tool invocation after the handler settles, including failed
170
+ calls that return an `isError` result.
171
+
172
+ | Field | Type | What is collected |
173
+ | ------------ | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
174
+ | `tool` | `string` | Registered tool name (`workflows_list_instances`, `workflows_fire_action`, …). The MCP SDK rejects unregistered names before dispatch. |
175
+ | `success` | `boolean` | `true` when the handler returned; `false` when it threw (rendered as `isError`). |
176
+ | `cursorUsed` | `boolean` | `true` only for `workflows_list_instances` when `cursor` is a non-empty string. Always `false` for every other tool. The cursor value is never sent. |
177
+
178
+ #### Engine events the MCP server records
179
+
180
+ Addressed write tools pass the MCP logger into the engine. Read tools and
181
+ address-free tools do not emit engine events.
182
+
183
+ Every engine event includes `executionRuntime` (the JavaScript runtime the
184
+ engine detected around itself, always `'node'` for the stdio server) and
185
+ `executionKind` (the host the engine was told it is running in, always
186
+ `'mcp'`). Every instance-scoped engine event additionally includes
187
+ `definitionContentHash` (omitted when the definition predates fingerprinting)
188
+ and `instanceId`.
189
+
190
+ | Event | Version | When the MCP server emits it | Additional payload |
191
+ | ------------------------------- | ------- | ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
192
+ | `Workflows Definition Deployed` | 2 | `workflows_deploy_definition` (created or unchanged) | `contentHash`, `status` (`'created'` or `'unchanged'`), `deployId` (random run id, not the workflow tag), `stageCount`, `activityCount`, `actionCount`, `transitionCount`, `fieldCount`, `activityKinds`, `fieldKinds`, `guardCount`, `effectCount`, `subworkflowCount`, `lifecycle` (`'standalone'` or `'child'`). Counts and kinds only — never names or GROQ. |
193
+ | `Workflows Instance Started` | 2 | `workflows_start`, and a fire that spawns a child | `initialFieldCount`, `viaSpawn` (`true` only for a spawned child), `lifecycle`. |
194
+ | `Workflows Stage Transitioned` | 2 | A committed hop from start or fire (cascades included) | `fromStageIndex`, `toStageIndex` (indexes into `stages[]`, never names), `toIsTerminal`, `isRevisit`, `dwellMs` (milliseconds in the exited stage, omitted if that entry is missing), `via`: `'transition'`. Unsampled. |
195
+ | `Workflows Action Fired` | 2 | `workflows_fire_action` | `activityKind` (optional), `hasParams` (whether params were supplied — not the params), `cascaded`. |
196
+
197
+ This MCP surface has no abort, set-stage, reset-activity, delete, tick, drain,
198
+ or generic field-edit tools, so it does not record `Workflows Instance Aborted`,
199
+ `Workflows Stage Set`, `Workflows Activity Reset`, `Workflows Definition Deleted`,
200
+ `Workflows Field Edited`, `Workflows Instance Ticked`, `Workflows Effects Drained`,
201
+ `Workflows Effect Completed`, or `Workflows Effect State Reported`. Those remain
202
+ engine events for shells that call those verbs.
203
+
137
204
  ## API
138
205
 
139
206
  The package is a host-neutral library: it never builds an engine, reads
package/dist/stdio.js CHANGED
@@ -6,7 +6,7 @@ import { deployedTagsGroq, parseResourceGdr, datasetResourceParts, EXECUTION_KIN
6
6
 
7
7
  import { LIST_WORKFLOW_TAGS_TOOL_NAME, workflowAddressFields, LIST_WORKFLOW_TAGS_DESCRIPTION, withToolTelemetry, clientForResource, registerWorkflowTools, workflowAddressFromInput, createMcpTelemetry, createEngineCache } from "./_chunks-es/index.js";
8
8
 
9
- var version = "0.33.0", packageJson = {
9
+ var version = "0.35.0", packageJson = {
10
10
  version: version
11
11
  };
12
12
 
@@ -120,7 +120,9 @@ async function runStdioServer() {
120
120
  shutdown();
121
121
  }), server.server.onclose = () => {
122
122
  shutdown();
123
- };
123
+ }, process.stdin.once("end", () => {
124
+ shutdown();
125
+ });
124
126
  const transport = new StdioServerTransport;
125
127
  await server.connect(transport);
126
128
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/workflow-mcp",
3
- "version": "0.33.0",
3
+ "version": "0.35.0",
4
4
  "description": "MCP server exposing Sanity workflow tools to agents — operate running workflow instances and author new definitions.",
5
5
  "keywords": [
6
6
  "agent",
@@ -62,15 +62,15 @@
62
62
  "@types/node": "^24.12.4",
63
63
  "vitest": "^4.1.8",
64
64
  "zod": "^4.4.3",
65
- "@sanity/workflow-engine": "0.33.0",
66
- "@sanity/workflow-engine-test": "0.33.0",
67
- "@sanity/workflow-examples": "0.12.1",
65
+ "@sanity/workflow-engine": "0.35.0",
66
+ "@sanity/workflow-engine-test": "0.35.0",
67
+ "@sanity/workflow-examples": "0.12.3",
68
68
  "@sanity/workflow-test-fixtures": "0.0.0"
69
69
  },
70
70
  "peerDependencies": {
71
71
  "@modelcontextprotocol/sdk": "^1.29.0",
72
72
  "zod": "^3.25.28 || ^4",
73
- "@sanity/workflow-engine": "0.33.0"
73
+ "@sanity/workflow-engine": "0.35.0"
74
74
  },
75
75
  "engines": {
76
76
  "node": ">=20"
@@ -80,6 +80,7 @@
80
80
  "docs": "node ../../scripts/run-typedoc.mjs",
81
81
  "typecheck": "tsc --noEmit -p tsconfig.json",
82
82
  "test": "vitest run",
83
+ "test:packaging": "vitest run --config vitest.packaging.config.ts",
83
84
  "test:watch": "vitest",
84
85
  "dev": "NODE_OPTIONS='--conditions=development' tsx --env-file-if-exists=../../.env bin/workflow-mcp.ts"
85
86
  }