fix(tools): type blueprint/scheduling schemas and document state traps in tool contracts (WM-4172) - #73
Conversation
…s in tool contracts Level 1 contract fixes for the highest-failing MCP tools (Datadog APM, 14d ending 2026-07-17 — see PR body for per-signature volumes): - scenarios_create/update: full JSON Schemas for blueprint (required name/flow/metadata, module-id format guidance) and scheduling (type enum, additionalProperties: false); maxLength 240 on description; wholesale-replace warning + tool-scenario exclusion on update; examples converted from JSON strings to objects - scenarios_run: activation requirement, executions_get-detail before retry, concurrent-run trap, data/interface and responsive semantics - scenarios_activate/deactivate: already-in-state errors documented as success (do not retry) - executions_get vs executions_get-detail: differentiated (metadata vs per-module I/O); executionId format documented with pattern - teams_list/folders_list: Access-denied recovery via users_me - credential-requests_extend-connection/delete: scopes-already-present semantics, exact-scope-string source, requestId provenance Descriptions/schemas only — no execute() behavior changed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR improves the SDK’s tool contract metadata (schemas + descriptions) for MCP/CLI consumers, focusing on reducing common agent authoring failures around scenarios (blueprint/scheduling), executions, teams/folders access scoping, and credential-request behaviors.
Changes:
- Add structured JSON Schemas for
scenarios_create/scenarios_updateblueprintandscheduling, plus stronger “state trap” documentation for scenario lifecycle tools. - Differentiate
executions_getvsexecutions_get-detailbehavior in tool descriptions and documentexecutionIdformat for scenario executions. - Document access-denied recovery guidance for
teams_list/folders_listand clarify credential-request ID/scope semantics.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/endpoints/scenarios.tools.ts | Adds reusable blueprint/scheduling JSON Schemas and expands lifecycle/tool-contract descriptions (activate/deactivate/run/update). |
| src/endpoints/executions.tools.ts | Clarifies get vs get-detail and adds an executionId pattern/description (with one DLQ-specific mismatch noted in review). |
| src/endpoints/teams.tools.ts | Improves teams_list description with org-scoping and access-denied recovery guidance. |
| src/endpoints/folders.tools.ts | Improves folders_list description with access-denied recovery guidance. |
| src/endpoints/credential-requests.tools.ts | Clarifies requestId provenance and “scopes already present” handling guidance. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…om DLQ executionId - The extracted scheduling/blueprint schema consts lost contextual typing, widening 'object' to string — annotate both as JSONSchema and add the missing additionalProperties field to the type (CI ts-jest/typedoc caught this; local pipe masked the exit code) - executions_get-for-incomp-exec: DLQ execution IDs are UUID-shaped with dashes (test/mocks/incomplete-executions/get.json), so the 32-hex pattern would reject valid IDs — removed, format documented instead (Copilot review) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Review — validated locally against the real host validation pipelineHow this was validated: every claim below was reproduced with local runs using only real components — the built The one piece of context everything hinges on: mcp.make.com doesn't just show these schemas to agents — it validates every tool call against them before executing. For each static tool the host runs ( Today 🔴 Finding 1 (blocker):
|
….type guidance on the parent description Blueprints carry more properties than the schema declares (e.g. a webhook node's `listener`), and the MCP host's validation pipeline strips undeclared properties from a scenarios_get → edit → scenarios_update round-trip unless the schema explicitly allows them — silently, with the call still succeeding. `additionalProperties: true` on the blueprint object and its flow items keeps those properties intact while declared properties and required keys stay enforced. Requires host support for the boolean form (make-mcp-server-host#338) before this reaches production. The scheduling.type enum values are also spelled out in the parent scheduling description, since the host's schema conversion drops annotations from enum properties. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Bump version to 1.6.5 for release. Changes since v1.6.4: - fix(tools): type blueprint/scheduling schemas and document state traps in tool contracts (#73) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The enum values always reach agents as anyOf consts in the advertised schema, and the type-specific behavioral guidance on the enum property's description survives host conversion once make-mcp-server-host#338 (a hard prerequisite of this release) is deployed — repeating either in the parent description only adds tokens to every tools/list. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…facts
Generic recovery coaching ('instead of retrying with guessed IDs',
spelled-out error-message matching) is behavior the model infers on its
own; the descriptions keep only what it cannot: where the teamId comes
from, and that a team-scoped token cannot list an organization's teams
(teams_get is the alternative).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
jorgecollinet (@jorgecollinet-make) Thanks for the review. The comments are addressed, also added version bump for the SDK. There is a counterpart PR in MCP repo https://github.com/integromat/make-mcp-server-host/pull/338 - once this one is merged - I'll bump the SDK version there and merge it all together. |
Level 1 tool-contract fixes: typed blueprint/scheduling, state-trap docs, tool differentiation (2026-07-17, agent-interfaces-self-improve iteration 5, case SX-006)
Finding
type: doc-gap
surface(s): mcp | sdk (MakeTools metadata consumed by mcp.make.com and the CLI)
The six highest-failing MCP tools all carry "legacy dialect" contracts:
scenarios_create/scenarios_updateacceptblueprintandschedulingwith notypekey at all and one-line descriptions,scenarios_runsays nothing about the activation requirement, andexecutions_getvsexecutions_get-detailare indistinguishable. Production telemetry (Datadog APM spans,service:mcp-server-host operation_name:mcp.tool_call status:error, 14d windows ending 2026-07-17) shows agents paying for every one of these gaps.Evidence
scenarios_run: 10,315 (~28% of all 36.7K run calls) — the natural create→run loop fails because nothing in the contract says runs require activation.scenarios_activate), "Scenario is not running" 2,863 (scenarios_deactivate), "Scenario is already being executed" 2,292 (scenarios_runretry loops).scheduling.type967 (agents inventcron,hour); blueprint missing requiredmetadata540; "Value exceeded maximum length of 240 chars in parameter 'description'" 1,043; a systematic long tail of invented module slugs (builtin:TextAggregator,util:SetVariables2,google-sheets:searchRows@2, …).executions_get/executions_get-detail: "Value doesn't match pattern in parameter 'executionId'" 673 (format undocumented).teams_list: 676 errors of 1,402 calls (~48%) — org-scoping guidance absent.credential-requests_extend-connection96.8% error rate (30d): errors when scopes are already present (error-as-answer);credential-requests_deleterequestId provenance undocumented.Full research:
make-ai-test-harness/mcp-authoring-failure-modes.md(FM-A, FM-B, FM-C, FM-D).Mapping
All in
src/endpoints/*.tools.ts(the MakeTools metadata that powerstools/liston mcp.make.com via sdk.module auto-registration):scenarios.tools.ts— untypedblueprint/schedulingon create (was line 84-85) and update (was 139-140); one-line descriptions on create/update/run/activate/deactivate.executions.tools.ts— identical descriptions for get vs get-detail (was lines 37/64); untyped executionId.teams.tools.ts:8,folders.tools.ts:8— no Access-denied recovery.credential-requests.tools.ts(extend-connection was line 430, delete was line 99).Fix
Description/schema-only changes; no
executebehavior touched:blueprintandschedulingget full JSON Schemas mirroring the SDK's ownBlueprint/SchedulingTS types (shared consts):scheduling.typeenum,intervalminimum,additionalProperties: falseon scheduling; blueprint requiresname/flow/metadata, flow items requireid/module/version, module-id format guidance ("verify via app-modules_list — never invent"). The blueprint object and its flow items carryadditionalProperties: true— load-bearing, see Host dependency below.blueprint/schedulingas JSON strings; withtype: 'object'declared, the host's validation now rejects the string form before it reaches the API (the API's ownnormalizePayloadstill accepts strings, but MCP tool calls never get that far). The rejection error ("Expected object") is clear enough to self-correct in one turn, and objects are the contract we want agents on. Examples are converted to objects accordingly.scenarios_update: wholesale-replace warning (fetch withscenarios_getfirst), tool-scenario exclusion,maxLength: 240ondescription.scenarios_run: activation requirement, executionId →executions_get-detailbefore retrying, concurrent-run trap,data-keys-must-match-interface,responsivesemantics.scenarios_activate/deactivate: already-in-state errors documented as success — do not retry.executions_getvsexecutions_get-detail: differentiated (metadata-only vs per-module I/O + "ALWAYS call after a failed run"); executionId documented withpattern: ^[0-9a-f]{32}$.teams_list/folders_list: Access-denied recovery via users_me. (MakingorganizationIdoptional requires backend support in imt-web-api — out of scope here, tracked as a Level-3 item.)credential-requests_extend-connection: "all scopes already present" error documented as satisfied-requirement; exact scope strings viacredential-requests_list-app-modules-with-creds.credential-requests_delete: requestId provenance (string ID from create/list, NOT a connectionId).scheduling.type's behavioral guidance lives on the enum property's owndescription. The host's schema conversion used to drop annotations from enum properties; make-mcp-server-host#338 fixes that, and since #338 is a hard prerequisite of this release anyway (see below), no duplication into the parent description is needed. The enum values always survived conversion (asanyOfconsts), so they aren't repeated in prose either.Host dependency & release ordering (from review)
The host validates every tool call against these schemas via
FromSchema→Value.Clean→Value.Check.Value.Cleanstrips undeclared object properties, and real blueprints carry more properties than any schema will ever declare (e.g. a webhook node'slistener) — withoutadditionalProperties: truethe recommendedscenarios_get→ edit →scenarios_updateloop would silently corrupt blueprints. TypeBox only honors the boolean form after make-mcp-server-host#338 (mapsadditionalProperties: true→Type.Unknown(); also preserves enum-property descriptions).Ordering: #338 must be deployed on the host before or together with the
@makehq/sdkbump that picks up this PR. #338 is a no-op until then, so it can merge anytime; plan is to land #338 now and do the SDK bump in the same release once the npm package is published.Delivery chain: this PR carries the version bump to 1.6.5 — npm release on merge → make-mcp-server-host bumps
@makehq/sdk(with #338 already in) → host deploy. Quick prod mitigation meanwhile: GrowthBookmcp-tool-description_{toolName}overrides.Companion PR (host-only tools, same finding class): make-mcp-server-host #337. Each PR is independently useful; this one only reaches production through the SDK release + host bump.
Validation
npm run lint(tsc + eslint) green;npm test(full jest unit suite, 261 tests) green on the final state of the branch.dist/tools.cjs+ #338'sFromSchema+TypeBoxValidationUtil): webhook-blueprint round-trip preserveslistenerand undeclared top-level keys; invalidscheduling.type, missing blueprintmetadata, over-longdescription, and malformedexecutionIdare all still rejected with actionable errors;scheduling.typedescription survives onto the converted schema.service:mcp-server-host operation_name:mcp.tool_call status:errorspans (re-runnable queries in mcp-authoring-failure-modes.md).🤖 Generated with Claude Code
Jira: WM-4172