@sanity/workflow-mcp 0.24.0 → 0.26.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/dist/index.d.cts CHANGED
@@ -1,19 +1,47 @@
1
1
  import type { ActionParam } from "@sanity/workflow-engine";
2
2
  import type { AutonomyVerdict } from "@sanity/workflow-engine";
3
+ import { DeclaredExecutionContext } from "@sanity/workflow-engine";
3
4
  import type { Diagnosis } from "@sanity/workflow-engine";
4
- import type { Engine } from "@sanity/workflow-engine";
5
+ import { Engine } from "@sanity/workflow-engine";
5
6
  import type { ExecutorClassification } from "@sanity/workflow-engine";
6
7
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
8
  import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
8
9
  import type { ServerNotification } from "@modelcontextprotocol/sdk/types.js";
9
10
  import type { ServerRequest } from "@modelcontextprotocol/sdk/types.js";
11
+ import type { StartKind } from "@sanity/workflow-engine";
10
12
  import type { StuckCause } from "@sanity/workflow-engine";
11
13
  import type { SuggestedRemediation } from "@sanity/workflow-engine";
12
14
  import type { TelemetryLogger } from "@sanity/telemetry";
13
15
  import type { ToolAnnotations } from "@modelcontextprotocol/sdk/types.js";
16
+ import { WorkflowClient } from "@sanity/workflow-engine";
14
17
  import type { WorkflowDefinition } from "@sanity/workflow-engine";
15
18
  import { WorkflowResource } from "@sanity/workflow-engine";
16
- import { ZodRawShape } from "zod";
19
+ import { WorkflowTelemetryLogger } from "@sanity/workflow-engine";
20
+ import { ZodRawShape } from "zod/v3";
21
+
22
+ /**
23
+ * An engine bound to one workflow environment. `executionContext` is the host's
24
+ * declaration of the advisory "via what" stamped on history entries; identity is
25
+ * whatever token backs the supplied client.
26
+ */
27
+ export declare function createWorkflowEngine(args: {
28
+ address: WorkflowEnvironmentAddress;
29
+ client: WorkflowClient;
30
+ executionContext?: DeclaredExecutionContext;
31
+ telemetry?: WorkflowTelemetryLogger;
32
+ }): Engine;
33
+
34
+ export declare const deployWorkflowDefinitionTool: WorkflowToolDef;
35
+
36
+ export declare const diagnoseWorkflowTool: WorkflowToolDef;
37
+
38
+ export declare const fireActionTool: WorkflowToolDef;
39
+
40
+ export declare const getWorkflowAuthoringGuideTool: WorkflowToolDef;
41
+
42
+ export declare const getWorkflowDefinitionTool: WorkflowToolDef;
43
+
44
+ export declare const getWorkflowStateTool: WorkflowToolDef;
17
45
 
18
46
  /**
19
47
  * The host seam: produce the {@link WorkflowToolContext} for one tool
@@ -30,6 +58,25 @@ export declare type GetWorkflowToolContext = (
30
58
  input: unknown,
31
59
  ) => WorkflowToolContext | Promise<WorkflowToolContext>;
32
60
 
61
+ /**
62
+ * The model-facing description of the tag-discovery capability. Hosts can't
63
+ * share the implementation — each owns its client and its resource spelling —
64
+ * so what the model is told about the answer lives here instead: what the list
65
+ * means, and that finding a tag is not the same as being allowed to choose one.
66
+ */
67
+ export declare const LIST_WORKFLOW_TAGS_DESCRIPTION: string;
68
+
69
+ /**
70
+ * The wire name of the tag-discovery tool. Declared here rather than at the
71
+ * registration site because the address vocabulary refers to it in prose a model
72
+ * reads — a rename must not leave that prose naming a tool nobody registers.
73
+ */
74
+ export declare const LIST_WORKFLOW_TAGS_TOOL_NAME = "list_workflow_tags";
75
+
76
+ export declare const listWorkflowDefinitionsTool: WorkflowToolDef;
77
+
78
+ export declare const listWorkflowInstancesTool: WorkflowToolDef;
79
+
33
80
  /**
34
81
  * One invocable (fireAction-fired) action. Two whole classes of action never
35
82
  * appear here: an action whose `filter` scoped it out for this actor is
@@ -38,7 +85,7 @@ export declare type GetWorkflowToolContext = (
38
85
  * {@link ProjectedAutomation} instead — the engine fires it, no caller can.
39
86
  */
40
87
  export declare interface ProjectedActionVerdict {
41
- /** Action name — what to pass to `fire_action` as `action`. */
88
+ /** Action name — what to pass to `fire_workflow_action` as `action`. */
42
89
  action: string;
43
90
  /** Human label for the action, if the definition provides one. */
44
91
  title?: string;
@@ -46,14 +93,14 @@ export declare interface ProjectedActionVerdict {
46
93
  allowed: boolean;
47
94
  /** When `allowed` is false, a short reason describing why. */
48
95
  disabledReason?: string;
49
- /** The action's declared params — what `fire_action`'s `params` object must
96
+ /** The action's declared params — what `fire_workflow_action`'s `params` object must
50
97
  * satisfy (each entry names the param and whether it is required). Absent
51
98
  * when the action declares none. */
52
99
  params?: ActionParam[];
53
100
  }
54
101
 
55
102
  export declare interface ProjectedActivity {
56
- /** Activity name — what to pass to `fire_action` as `activity`. */
103
+ /** Activity name — what to pass to `fire_workflow_action` as `activity`. */
57
104
  activity: string;
58
105
  /** Human label, if provided. */
59
106
  title?: string;
@@ -94,10 +141,10 @@ export declare interface ProjectedActivity {
94
141
  /**
95
142
  * One cascade-fired (`when`) action, narrated as automation: the engine fires
96
143
  * it on its own the moment the trigger holds — it is never invocable via
97
- * `fire_action`, so it must not read as a button.
144
+ * `fire_workflow_action`, so it must not read as a button.
98
145
  */
99
146
  export declare interface ProjectedAutomation {
100
- /** The cascade-fired action's name. Not accepted by `fire_action`. */
147
+ /** The cascade-fired action's name. Not accepted by `fire_workflow_action`. */
101
148
  action: string;
102
149
  /** Human label, if provided. */
103
150
  title?: string;
@@ -126,6 +173,30 @@ export declare interface ProjectedDefinition {
126
173
  definition: WorkflowDefinition;
127
174
  }
128
175
 
176
+ /**
177
+ * One deployed workflow definition, latest version only — what
178
+ * `list_workflow_definitions` returns per name. Deploys are create-only
179
+ * (every deploy mints a new version), but the LLM only ever needs the
180
+ * head: it's the version `startInstance` picks by default.
181
+ */
182
+ export declare interface ProjectedDefinitionSummary {
183
+ /** Definition `name` — the value `list_workflow_instances` filters on. */
184
+ name: string;
185
+ /** Human-readable workflow title. */
186
+ title: string;
187
+ /** Author-supplied description, when the definition carries one. */
188
+ description?: string;
189
+ /** Latest deployed version. */
190
+ version: number;
191
+ /** Whether new instances can be started directly. `false` for spawn-only
192
+ * child workflows — those only come to exist under a parent instance. */
193
+ startable: boolean;
194
+ /** Who initiates standalone runs: `'interactive'` (a person, from a start
195
+ * surface) or `'autonomous'` (a system reacting to a document).
196
+ * Classification only — the engine starts either kind for any caller. */
197
+ startKind: StartKind;
198
+ }
199
+
129
200
  /**
130
201
  * The diagnosis projection — why an instance is or isn't progressing.
131
202
  *
@@ -242,6 +313,8 @@ export declare function registerWorkflowTools(
242
313
  },
243
314
  ): void;
244
315
 
316
+ export declare const startWorkflowTool: WorkflowToolDef;
317
+
245
318
  /**
246
319
  * JSON-schema descriptor for consumers that don't speak zod — e.g. the
247
320
  * Anthropic Messages API `input_schema` field. `properties`/`required`
@@ -255,7 +328,16 @@ export declare interface ToolInputJsonSchema {
255
328
  [key: string]: unknown;
256
329
  }
257
330
 
258
- /** Derive the JSON-schema descriptor from a def's zod shape. */
331
+ /**
332
+ * Derive the JSON-schema descriptor from a def's own zod shape. The converter
333
+ * options mirror the ones the MCP SDK derives its wire schema with, so one
334
+ * shape can't derive two ways.
335
+ *
336
+ * A def's own shape is not the whole advertised input: a consumer of a def
337
+ * declaring {@link WorkflowToolDef.requiresAddress} merges its own workflow
338
+ * environment parameters in, the way {@link registerWorkflowTools} does for
339
+ * this package's host.
340
+ */
259
341
  export declare function toolInputJsonSchema(
260
342
  def: WorkflowToolDef,
261
343
  ): ToolInputJsonSchema;
@@ -285,6 +367,16 @@ export declare interface ValidateDefinitionsResult {
285
367
  results: ValidateDefinitionResult[];
286
368
  }
287
369
 
370
+ export declare const validateWorkflowDefinitionTool: WorkflowToolDef;
371
+
372
+ /**
373
+ * What the model is told about the `tag` parameter itself. Lives here beside the
374
+ * tool name it cites because every host declares this parameter in its own
375
+ * vocabulary — a host that paraphrases weakens a caveat that was tuned
376
+ * deliberately, and nothing warns you it has drifted.
377
+ */
378
+ export declare const WORKFLOW_TAG_DESCRIPTION: string;
379
+
288
380
  export declare const WORKFLOW_TOOLS: readonly WorkflowToolDef[];
289
381
 
290
382
  /**
@@ -297,12 +389,64 @@ export declare function workflowAddressFromInput(
297
389
  input: unknown,
298
390
  ): WorkflowEnvironmentAddress;
299
391
 
392
+ /**
393
+ * The client configuration engine traffic requires, layered over whatever base
394
+ * config the host supplies — its requester, its headers, its `apiHost`. Engine
395
+ * policy deliberately wins over that base: a host's own defaults are tuned for
396
+ * content reads, not for the engine's documents.
397
+ *
398
+ * The base is generic rather than `@sanity/client`'s `ClientConfig` so that a
399
+ * host resolving a different copy of that package still type-checks — the same
400
+ * reason the engine states its client structurally. The host's own config type
401
+ * flows through to the result, which stays assignable to it.
402
+ */
403
+ export declare function workflowClientConfig<Base extends object>(args: {
404
+ resource: WorkflowResource;
405
+ token?: string;
406
+ /** The host's own client config. Pass `{}` if it has no opinions to preserve. */
407
+ base: Base;
408
+ }): Base & WorkflowClientPolicy & WorkflowResourceAddressing;
409
+
410
+ /**
411
+ * The client settings engine traffic pins, whatever base a host layers them over.
412
+ * Literal types so the result stays assignable to a host's own client config.
413
+ */
414
+ declare interface WorkflowClientPolicy {
415
+ apiVersion: string;
416
+ useCdn: false;
417
+ requestTagPrefix: string;
418
+ perspective: "published";
419
+ }
420
+
300
421
  /** Where one tool call reads/writes workflow data: resource + tag. */
301
422
  export declare interface WorkflowEnvironmentAddress {
302
423
  workflowResource: WorkflowResource;
303
424
  tag: string;
304
425
  }
305
426
 
427
+ /**
428
+ * One rendering of a failed tool call, shared by every host. A structured
429
+ * error's stable `kind` leads the text so the model can branch on the failure
430
+ * without parsing the human-readable message — a host that re-derives this
431
+ * prefix drifts from the wording the descriptions and evals were tuned against.
432
+ */
433
+ export declare function workflowErrorText(error: unknown): string;
434
+
435
+ /**
436
+ * How the resulting config names the environment. Exactly one branch is
437
+ * populated — a dataset target carries the classic pair, anything else carries
438
+ * the resource — but both are stated optional so the result assigns to a host's
439
+ * client config without narrowing the union first. The unused branch is removed
440
+ * from the result so a leftover from the host's base cannot survive the merge:
441
+ * `@sanity/client` prefers `resource` over `projectId`/`dataset` whenever both
442
+ * are present, which would otherwise silently address the wrong environment.
443
+ */
444
+ declare interface WorkflowResourceAddressing {
445
+ projectId?: string;
446
+ dataset?: string;
447
+ resource?: WorkflowResource;
448
+ }
449
+
306
450
  /**
307
451
  * Everything a tool call needs from its host: the engine to operate on.
308
452
  * Identity is the token behind the engine's client (`/users/me`) — a host
@@ -339,6 +483,15 @@ export declare interface WorkflowToolDef {
339
483
  * descriptor for non-MCP consumers.
340
484
  */
341
485
  readonly inputSchema: ZodRawShape;
486
+ /**
487
+ * Whether this tool operates on a workflow environment, and so needs the
488
+ * engine it is handed to address the one the caller means. How a host
489
+ * satisfies that is its own choice: one that names an environment per call
490
+ * adds its own address parameters to this tool's schema, one that binds a
491
+ * single environment when it builds the engine adds nothing. `false` marks
492
+ * an engine-independent tool — there is no environment to name.
493
+ */
494
+ readonly requiresAddress: boolean;
342
495
  readonly annotations: ToolAnnotations;
343
496
  /**
344
497
  * Returns plain projected data (the `Projected*` shapes) — hosts own
package/dist/index.d.ts CHANGED
@@ -1,19 +1,47 @@
1
1
  import type { ActionParam } from "@sanity/workflow-engine";
2
2
  import type { AutonomyVerdict } from "@sanity/workflow-engine";
3
+ import { DeclaredExecutionContext } from "@sanity/workflow-engine";
3
4
  import type { Diagnosis } from "@sanity/workflow-engine";
4
- import type { Engine } from "@sanity/workflow-engine";
5
+ import { Engine } from "@sanity/workflow-engine";
5
6
  import type { ExecutorClassification } from "@sanity/workflow-engine";
6
7
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
8
  import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
8
9
  import type { ServerNotification } from "@modelcontextprotocol/sdk/types.js";
9
10
  import type { ServerRequest } from "@modelcontextprotocol/sdk/types.js";
11
+ import type { StartKind } from "@sanity/workflow-engine";
10
12
  import type { StuckCause } from "@sanity/workflow-engine";
11
13
  import type { SuggestedRemediation } from "@sanity/workflow-engine";
12
14
  import type { TelemetryLogger } from "@sanity/telemetry";
13
15
  import type { ToolAnnotations } from "@modelcontextprotocol/sdk/types.js";
16
+ import { WorkflowClient } from "@sanity/workflow-engine";
14
17
  import type { WorkflowDefinition } from "@sanity/workflow-engine";
15
18
  import { WorkflowResource } from "@sanity/workflow-engine";
16
- import { ZodRawShape } from "zod";
19
+ import { WorkflowTelemetryLogger } from "@sanity/workflow-engine";
20
+ import { ZodRawShape } from "zod/v3";
21
+
22
+ /**
23
+ * An engine bound to one workflow environment. `executionContext` is the host's
24
+ * declaration of the advisory "via what" stamped on history entries; identity is
25
+ * whatever token backs the supplied client.
26
+ */
27
+ export declare function createWorkflowEngine(args: {
28
+ address: WorkflowEnvironmentAddress;
29
+ client: WorkflowClient;
30
+ executionContext?: DeclaredExecutionContext;
31
+ telemetry?: WorkflowTelemetryLogger;
32
+ }): Engine;
33
+
34
+ export declare const deployWorkflowDefinitionTool: WorkflowToolDef;
35
+
36
+ export declare const diagnoseWorkflowTool: WorkflowToolDef;
37
+
38
+ export declare const fireActionTool: WorkflowToolDef;
39
+
40
+ export declare const getWorkflowAuthoringGuideTool: WorkflowToolDef;
41
+
42
+ export declare const getWorkflowDefinitionTool: WorkflowToolDef;
43
+
44
+ export declare const getWorkflowStateTool: WorkflowToolDef;
17
45
 
18
46
  /**
19
47
  * The host seam: produce the {@link WorkflowToolContext} for one tool
@@ -30,6 +58,25 @@ export declare type GetWorkflowToolContext = (
30
58
  input: unknown,
31
59
  ) => WorkflowToolContext | Promise<WorkflowToolContext>;
32
60
 
61
+ /**
62
+ * The model-facing description of the tag-discovery capability. Hosts can't
63
+ * share the implementation — each owns its client and its resource spelling —
64
+ * so what the model is told about the answer lives here instead: what the list
65
+ * means, and that finding a tag is not the same as being allowed to choose one.
66
+ */
67
+ export declare const LIST_WORKFLOW_TAGS_DESCRIPTION: string;
68
+
69
+ /**
70
+ * The wire name of the tag-discovery tool. Declared here rather than at the
71
+ * registration site because the address vocabulary refers to it in prose a model
72
+ * reads — a rename must not leave that prose naming a tool nobody registers.
73
+ */
74
+ export declare const LIST_WORKFLOW_TAGS_TOOL_NAME = "list_workflow_tags";
75
+
76
+ export declare const listWorkflowDefinitionsTool: WorkflowToolDef;
77
+
78
+ export declare const listWorkflowInstancesTool: WorkflowToolDef;
79
+
33
80
  /**
34
81
  * One invocable (fireAction-fired) action. Two whole classes of action never
35
82
  * appear here: an action whose `filter` scoped it out for this actor is
@@ -38,7 +85,7 @@ export declare type GetWorkflowToolContext = (
38
85
  * {@link ProjectedAutomation} instead — the engine fires it, no caller can.
39
86
  */
40
87
  export declare interface ProjectedActionVerdict {
41
- /** Action name — what to pass to `fire_action` as `action`. */
88
+ /** Action name — what to pass to `fire_workflow_action` as `action`. */
42
89
  action: string;
43
90
  /** Human label for the action, if the definition provides one. */
44
91
  title?: string;
@@ -46,14 +93,14 @@ export declare interface ProjectedActionVerdict {
46
93
  allowed: boolean;
47
94
  /** When `allowed` is false, a short reason describing why. */
48
95
  disabledReason?: string;
49
- /** The action's declared params — what `fire_action`'s `params` object must
96
+ /** The action's declared params — what `fire_workflow_action`'s `params` object must
50
97
  * satisfy (each entry names the param and whether it is required). Absent
51
98
  * when the action declares none. */
52
99
  params?: ActionParam[];
53
100
  }
54
101
 
55
102
  export declare interface ProjectedActivity {
56
- /** Activity name — what to pass to `fire_action` as `activity`. */
103
+ /** Activity name — what to pass to `fire_workflow_action` as `activity`. */
57
104
  activity: string;
58
105
  /** Human label, if provided. */
59
106
  title?: string;
@@ -94,10 +141,10 @@ export declare interface ProjectedActivity {
94
141
  /**
95
142
  * One cascade-fired (`when`) action, narrated as automation: the engine fires
96
143
  * it on its own the moment the trigger holds — it is never invocable via
97
- * `fire_action`, so it must not read as a button.
144
+ * `fire_workflow_action`, so it must not read as a button.
98
145
  */
99
146
  export declare interface ProjectedAutomation {
100
- /** The cascade-fired action's name. Not accepted by `fire_action`. */
147
+ /** The cascade-fired action's name. Not accepted by `fire_workflow_action`. */
101
148
  action: string;
102
149
  /** Human label, if provided. */
103
150
  title?: string;
@@ -126,6 +173,30 @@ export declare interface ProjectedDefinition {
126
173
  definition: WorkflowDefinition;
127
174
  }
128
175
 
176
+ /**
177
+ * One deployed workflow definition, latest version only — what
178
+ * `list_workflow_definitions` returns per name. Deploys are create-only
179
+ * (every deploy mints a new version), but the LLM only ever needs the
180
+ * head: it's the version `startInstance` picks by default.
181
+ */
182
+ export declare interface ProjectedDefinitionSummary {
183
+ /** Definition `name` — the value `list_workflow_instances` filters on. */
184
+ name: string;
185
+ /** Human-readable workflow title. */
186
+ title: string;
187
+ /** Author-supplied description, when the definition carries one. */
188
+ description?: string;
189
+ /** Latest deployed version. */
190
+ version: number;
191
+ /** Whether new instances can be started directly. `false` for spawn-only
192
+ * child workflows — those only come to exist under a parent instance. */
193
+ startable: boolean;
194
+ /** Who initiates standalone runs: `'interactive'` (a person, from a start
195
+ * surface) or `'autonomous'` (a system reacting to a document).
196
+ * Classification only — the engine starts either kind for any caller. */
197
+ startKind: StartKind;
198
+ }
199
+
129
200
  /**
130
201
  * The diagnosis projection — why an instance is or isn't progressing.
131
202
  *
@@ -242,6 +313,8 @@ export declare function registerWorkflowTools(
242
313
  },
243
314
  ): void;
244
315
 
316
+ export declare const startWorkflowTool: WorkflowToolDef;
317
+
245
318
  /**
246
319
  * JSON-schema descriptor for consumers that don't speak zod — e.g. the
247
320
  * Anthropic Messages API `input_schema` field. `properties`/`required`
@@ -255,7 +328,16 @@ export declare interface ToolInputJsonSchema {
255
328
  [key: string]: unknown;
256
329
  }
257
330
 
258
- /** Derive the JSON-schema descriptor from a def's zod shape. */
331
+ /**
332
+ * Derive the JSON-schema descriptor from a def's own zod shape. The converter
333
+ * options mirror the ones the MCP SDK derives its wire schema with, so one
334
+ * shape can't derive two ways.
335
+ *
336
+ * A def's own shape is not the whole advertised input: a consumer of a def
337
+ * declaring {@link WorkflowToolDef.requiresAddress} merges its own workflow
338
+ * environment parameters in, the way {@link registerWorkflowTools} does for
339
+ * this package's host.
340
+ */
259
341
  export declare function toolInputJsonSchema(
260
342
  def: WorkflowToolDef,
261
343
  ): ToolInputJsonSchema;
@@ -285,6 +367,16 @@ export declare interface ValidateDefinitionsResult {
285
367
  results: ValidateDefinitionResult[];
286
368
  }
287
369
 
370
+ export declare const validateWorkflowDefinitionTool: WorkflowToolDef;
371
+
372
+ /**
373
+ * What the model is told about the `tag` parameter itself. Lives here beside the
374
+ * tool name it cites because every host declares this parameter in its own
375
+ * vocabulary — a host that paraphrases weakens a caveat that was tuned
376
+ * deliberately, and nothing warns you it has drifted.
377
+ */
378
+ export declare const WORKFLOW_TAG_DESCRIPTION: string;
379
+
288
380
  export declare const WORKFLOW_TOOLS: readonly WorkflowToolDef[];
289
381
 
290
382
  /**
@@ -297,12 +389,64 @@ export declare function workflowAddressFromInput(
297
389
  input: unknown,
298
390
  ): WorkflowEnvironmentAddress;
299
391
 
392
+ /**
393
+ * The client configuration engine traffic requires, layered over whatever base
394
+ * config the host supplies — its requester, its headers, its `apiHost`. Engine
395
+ * policy deliberately wins over that base: a host's own defaults are tuned for
396
+ * content reads, not for the engine's documents.
397
+ *
398
+ * The base is generic rather than `@sanity/client`'s `ClientConfig` so that a
399
+ * host resolving a different copy of that package still type-checks — the same
400
+ * reason the engine states its client structurally. The host's own config type
401
+ * flows through to the result, which stays assignable to it.
402
+ */
403
+ export declare function workflowClientConfig<Base extends object>(args: {
404
+ resource: WorkflowResource;
405
+ token?: string;
406
+ /** The host's own client config. Pass `{}` if it has no opinions to preserve. */
407
+ base: Base;
408
+ }): Base & WorkflowClientPolicy & WorkflowResourceAddressing;
409
+
410
+ /**
411
+ * The client settings engine traffic pins, whatever base a host layers them over.
412
+ * Literal types so the result stays assignable to a host's own client config.
413
+ */
414
+ declare interface WorkflowClientPolicy {
415
+ apiVersion: string;
416
+ useCdn: false;
417
+ requestTagPrefix: string;
418
+ perspective: "published";
419
+ }
420
+
300
421
  /** Where one tool call reads/writes workflow data: resource + tag. */
301
422
  export declare interface WorkflowEnvironmentAddress {
302
423
  workflowResource: WorkflowResource;
303
424
  tag: string;
304
425
  }
305
426
 
427
+ /**
428
+ * One rendering of a failed tool call, shared by every host. A structured
429
+ * error's stable `kind` leads the text so the model can branch on the failure
430
+ * without parsing the human-readable message — a host that re-derives this
431
+ * prefix drifts from the wording the descriptions and evals were tuned against.
432
+ */
433
+ export declare function workflowErrorText(error: unknown): string;
434
+
435
+ /**
436
+ * How the resulting config names the environment. Exactly one branch is
437
+ * populated — a dataset target carries the classic pair, anything else carries
438
+ * the resource — but both are stated optional so the result assigns to a host's
439
+ * client config without narrowing the union first. The unused branch is removed
440
+ * from the result so a leftover from the host's base cannot survive the merge:
441
+ * `@sanity/client` prefers `resource` over `projectId`/`dataset` whenever both
442
+ * are present, which would otherwise silently address the wrong environment.
443
+ */
444
+ declare interface WorkflowResourceAddressing {
445
+ projectId?: string;
446
+ dataset?: string;
447
+ resource?: WorkflowResource;
448
+ }
449
+
306
450
  /**
307
451
  * Everything a tool call needs from its host: the engine to operate on.
308
452
  * Identity is the token behind the engine's client (`/users/me`) — a host
@@ -339,6 +483,15 @@ export declare interface WorkflowToolDef {
339
483
  * descriptor for non-MCP consumers.
340
484
  */
341
485
  readonly inputSchema: ZodRawShape;
486
+ /**
487
+ * Whether this tool operates on a workflow environment, and so needs the
488
+ * engine it is handed to address the one the caller means. How a host
489
+ * satisfies that is its own choice: one that names an environment per call
490
+ * adds its own address parameters to this tool's schema, one that binds a
491
+ * single environment when it builds the engine adds nothing. `false` marks
492
+ * an engine-independent tool — there is no environment to name.
493
+ */
494
+ readonly requiresAddress: boolean;
342
495
  readonly annotations: ToolAnnotations;
343
496
  /**
344
497
  * Returns plain projected data (the `Projected*` shapes) — hosts own
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- import { WORKFLOW_TOOLS, registerWorkflowTools, toolInputJsonSchema, workflowAddressFromInput } from "./_chunks-es/index.js";
1
+ import { LIST_WORKFLOW_TAGS_DESCRIPTION, LIST_WORKFLOW_TAGS_TOOL_NAME, WORKFLOW_TAG_DESCRIPTION, WORKFLOW_TOOLS, createWorkflowEngine, deployWorkflowDefinitionTool, diagnoseWorkflowTool, fireActionTool, getWorkflowAuthoringGuideTool, getWorkflowDefinitionTool, getWorkflowStateTool, listWorkflowDefinitionsTool, listWorkflowInstancesTool, registerWorkflowTools, startWorkflowTool, toolInputJsonSchema, validateWorkflowDefinitionTool, workflowAddressFromInput, workflowClientConfig, workflowErrorText } from "./_chunks-es/index.js";
2
2
 
3
- export { WORKFLOW_TOOLS, registerWorkflowTools, toolInputJsonSchema, workflowAddressFromInput };
3
+ export { LIST_WORKFLOW_TAGS_DESCRIPTION, LIST_WORKFLOW_TAGS_TOOL_NAME, WORKFLOW_TAG_DESCRIPTION, WORKFLOW_TOOLS, createWorkflowEngine, deployWorkflowDefinitionTool, diagnoseWorkflowTool, fireActionTool, getWorkflowAuthoringGuideTool, getWorkflowDefinitionTool, getWorkflowStateTool, listWorkflowDefinitionsTool, listWorkflowInstancesTool, registerWorkflowTools, startWorkflowTool, toolInputJsonSchema, validateWorkflowDefinitionTool, workflowAddressFromInput, workflowClientConfig, workflowErrorText };
package/dist/stdio.js CHANGED
@@ -2,58 +2,55 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
 
3
3
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
4
 
5
- import { ENGINE_API_VERSION, clientConfigFromResource, resourceGdr, createEngine, datasetResourceParts, EXECUTION_KINDS } from "@sanity/workflow-engine";
5
+ import { deployedTagsGroq, parseResourceGdr, datasetResourceParts, EXECUTION_KINDS } from "@sanity/workflow-engine";
6
6
 
7
- import { registerWorkflowTools, workflowAddressFromInput, createMcpTelemetry } from "./_chunks-es/index.js";
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
- import { createClient } from "@sanity/client";
10
-
11
- var version = "0.24.0", packageJson = {
9
+ var version = "0.26.0", packageJson = {
12
10
  version: version
13
11
  };
14
12
 
15
- function clientForResource(args) {
16
- const {resource: resource, token: token, apiHost: apiHost} = args;
17
- return createClient({
18
- token: token,
19
- apiHost: apiHost,
20
- apiVersion: ENGINE_API_VERSION,
21
- useCdn: !1,
22
- requestTagPrefix: "sanity.workflows-mcp",
23
- ...clientConfigFromResource(resource)
24
- });
25
- }
26
-
27
- function createEngineCache({token: token, apiHost: apiHost, executionContext: executionContext, telemetry: telemetry}) {
28
- const engines = /* @__PURE__ */ new Map;
29
- return ({workflowResource: workflowResource, tag: tag}) => {
30
- const key = `${resourceGdr(workflowResource)} ${tag}`, existing = engines.get(key);
31
- if (existing !== void 0) return existing;
32
- const engine = createEngine({
33
- client: clientForResource({
34
- resource: workflowResource,
35
- token: token,
36
- apiHost: apiHost
37
- }),
38
- workflowResource: workflowResource,
39
- tag: tag,
40
- ...executionContext !== void 0 ? {
41
- executionContext: executionContext
42
- } : {},
43
- ...telemetry !== void 0 ? {
44
- telemetry: telemetry
45
- } : {}
46
- });
47
- return engines.set(key, engine), engine;
48
- };
49
- }
50
-
51
13
  function requireEnv(env, name) {
52
14
  const value = env[name];
53
15
  if (typeof value != "string" || value === "") throw new Error(`Missing required environment variable: ${name}`);
54
16
  return value;
55
17
  }
56
18
 
19
+ const readDeployedTags = ({resource: resource, token: token, apiHost: apiHost}) => clientForResource({
20
+ resource: resource,
21
+ token: token,
22
+ apiHost: apiHost
23
+ }).fetch(deployedTagsGroq(), {}, {
24
+ tag: "definition.tags"
25
+ });
26
+
27
+ function registerListWorkflowTagsTool(server, {token: token, apiHost: apiHost, readTags: readTags = readDeployedTags, telemetry: telemetry, onResource: onResource}) {
28
+ server.registerTool(LIST_WORKFLOW_TAGS_TOOL_NAME, {
29
+ description: LIST_WORKFLOW_TAGS_DESCRIPTION,
30
+ inputSchema: {
31
+ workflow_resource: workflowAddressFields.workflow_resource
32
+ },
33
+ annotations: {
34
+ readOnlyHint: !0
35
+ }
36
+ }, args => withToolTelemetry({
37
+ tool: LIST_WORKFLOW_TAGS_TOOL_NAME,
38
+ input: args,
39
+ ...telemetry !== void 0 ? {
40
+ telemetry: telemetry
41
+ } : {}
42
+ }, async () => {
43
+ const resource = parseResourceGdr(args.workflow_resource);
44
+ return onResource?.(resource), {
45
+ tags: await readTags({
46
+ resource: resource,
47
+ token: token,
48
+ apiHost: apiHost
49
+ })
50
+ };
51
+ }));
52
+ }
53
+
57
54
  async function runStdioServer() {
58
55
  const token = requireEnv(process.env, "SANITY_AUTH_TOKEN"), apiHost = process.env.SANITY_API_HOST ?? "https://api.sanity.io";
59
56
  process.stderr.write(`workflow-mcp MCP starting against ${apiHost} (org-authed; workflow environments are addressed per tool call)\n`);
@@ -66,12 +63,12 @@ async function runStdioServer() {
66
63
  if (telemetry === void 0) throw new Error("workflow-mcp: telemetry trace before any environment was addressed");
67
64
  return telemetry.logger.trace(event, context);
68
65
  }
69
- }, initTelemetry = address => {
70
- if (telemetry !== void 0 || address.workflowResource.type !== "dataset") return;
71
- const {projectId: projectId, dataset: dataset} = datasetResourceParts(address.workflowResource.id);
66
+ }, initTelemetry = resource => {
67
+ if (telemetry !== void 0 || resource.type !== "dataset") return;
68
+ const {projectId: projectId, dataset: dataset} = datasetResourceParts(resource.id);
72
69
  telemetry = createMcpTelemetry({
73
70
  client: clientForResource({
74
- resource: address.workflowResource,
71
+ resource: resource,
75
72
  token: token,
76
73
  apiHost: apiHost
77
74
  }),
@@ -94,11 +91,16 @@ async function runStdioServer() {
94
91
  });
95
92
  registerWorkflowTools(server, (_extra, input) => {
96
93
  const address = workflowAddressFromInput(input);
97
- return initTelemetry(address), {
94
+ return initTelemetry(address.workflowResource), {
98
95
  engine: engineFor(address)
99
96
  };
100
97
  }, {
101
98
  telemetry: logger
99
+ }), registerListWorkflowTagsTool(server, {
100
+ token: token,
101
+ apiHost: apiHost,
102
+ telemetry: logger,
103
+ onResource: initTelemetry
102
104
  });
103
105
  const FLUSH_DEADLINE_MS = 3e3;
104
106
  let shuttingDown = !1;