fix: add preset support to MCP tools (#24694)#24889
Conversation
The chat tools (`read_template`, `create_workspace`) did not surface or respect template version presets. Presets were invisible to the LLM and preset parameter defaults were never applied at workspace creation. The `toolsdk` MCP surface had the same gap (ref #24695, now subsumed here). ## What this changes - **`read_template`** returns presets with `id`, `name`, `default`, `description`, `icon`, `parameters`, and `desired_prebuild_instances` (when set), so the LLM can pick the right preset and prefer prebuilt-backed ones. - **`create_workspace`** accepts a `preset_id`. The wsbuilder applies preset parameter defaults and may claim a prebuilt workspace. - **`start_workspace`** does *not* accept a preset. Presets are a creation-time choice; subsequent starts use the workspace's existing version and parameters. Users who need a specific preset or version on an existing chat can create the workspace out-of-band (CLI / UI / API) with the desired configuration and attach the chat to it. - **`toolsdk`** gains `GetTemplate` (with presets including `desired_prebuild_instances`), preset support on `CreateWorkspace`, and preset + `rich_parameters` support on `CreateWorkspaceBuild`. The `template_version_preset_id` description warns about preset/version affinity. > 🤖 Generated with [Coder Agents](https://coder.com/agents) and reviewed by a human. Co-authored-by: Max schwenk <maschwenk@gmail.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> (cherry picked from commit 04cc983)
There was a problem hiding this comment.
Pull request overview
Adds end-to-end support for template version presets across chat tools and the codersdk/toolsdk MCP surface so agents can discover presets and apply them during workspace creation/builds.
Changes:
- Exposes presets (including parameters and
desired_prebuild_instances) viaread_template(chattool) and newcoder_get_template(toolsdk). - Adds preset selection to workspace creation/build surfaces (
preset_idon chatcreate_workspace;template_version_preset_idon toolsdkcreate_workspace/create_workspace_build). - Expands integration tests to cover preset propagation, rich parameters, validation cases, and “require active version” start behavior.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
codersdk/toolsdk/toolsdk.go |
Adds coder_get_template, adds preset + rich parameter handling to create workspace/build tool args and handlers. |
codersdk/toolsdk/toolsdk_test.go |
Extends tool integration tests to cover preset propagation, rich parameters, and new GetTemplate tool behavior. |
coderd/x/chatd/chattool/readtemplate.go |
Includes presets (and preset params + desired prebuild instances) in read_template responses when present. |
coderd/x/chatd/chattool/readtemplate_test.go |
New tests asserting read_template preset shape, params, and omit-when-empty behavior. |
coderd/x/chatd/chattool/createworkspace.go |
Adds preset_id argument and forwards it as TemplateVersionPresetID to workspace creation requests. |
coderd/x/chatd/chattool/createworkspace_test.go |
Adds unit tests ensuring preset_id validation and request propagation in chattool create_workspace. |
coderd/x/chatd/chattool/startworkspace.go |
No functional change (formatting only). |
coderd/export_test.go |
Exposes chatStartWorkspace to external-package tests via ChatStartWorkspace alias. |
coderd/exp_chats_test.go |
Adds end-to-end test covering RequireActiveVersion auto-update on chat start path and ensuring no preset is applied. |
coderd/exp_chats.go |
Documents the exported test alias rationale for chatStartWorkspace. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| transition := codersdk.WorkspaceTransition(args.Transition) | ||
| // Presets and rich_parameters are scoped to a starting build; | ||
| // they have no meaning on stop or delete transitions. Surface | ||
| // both violations at once via errors.Join so agents fix them | ||
| // in a single round-trip instead of one tool call per error. |
There was a problem hiding this comment.
CreateWorkspaceBuild treats any non-"start" transition as stop/delete for the purpose of validating template_version_preset_id and rich_parameters. If args.transition is invalid (runtime doesn’t enforce the schema enum), the user will get misleading errors about preset/params rather than an actionable "transition must be one of start/stop/delete" message. Consider validating args.Transition first (e.g., switch on the parsed transition and return a clear error on default) before applying the non-start field restrictions.
| // Surface the prebuild count when set so the LLM can prefer | ||
| // presets backed by prebuilt workspaces. Match the toolsdk | ||
| // `desired_prebuild_instances` key for cross-surface consistency. | ||
| if p.DesiredInstances.Valid && p.DesiredInstances.Int32 > 0 { |
There was a problem hiding this comment.
read_template only includes desired_prebuild_instances when DesiredInstances > 0. The REST preset surface (coderd/presets.go -> codersdk.Preset.DesiredPrebuildInstances) includes the field whenever DesiredInstances is set, even if it’s 0. Filtering out 0 here makes the chattool response inconsistent with coder_get_template/codersdk and prevents callers from distinguishing "unset" vs "explicitly 0". Consider including desired_prebuild_instances whenever DesiredInstances.Valid is true and letting the LLM interpret 0 as "no prebuilds".
| // Surface the prebuild count when set so the LLM can prefer | |
| // presets backed by prebuilt workspaces. Match the toolsdk | |
| // `desired_prebuild_instances` key for cross-surface consistency. | |
| if p.DesiredInstances.Valid && p.DesiredInstances.Int32 > 0 { | |
| // Surface the prebuild count whenever it is explicitly set so | |
| // the response matches the toolsdk | |
| // `desired_prebuild_instances` key, including explicit 0 to | |
| // preserve the distinction between "unset" and "no prebuilds". | |
| if p.DesiredInstances.Valid { |
The chat tools (
read_template,create_workspace) did not surface or respect template version presets. Presets were invisible to the LLM and preset parameter defaults were never applied at workspace creation. ThetoolsdkMCP surface had the same gap (ref #24695, now subsumed here).What this changes
read_templatereturns presets withid,name,default,description,icon,parameters, anddesired_prebuild_instances(when set), so the LLM can pick the right preset and prefer prebuilt-backed ones.create_workspaceaccepts apreset_id. The wsbuilder applies preset parameter defaults and may claim a prebuilt workspace.start_workspacedoes not accept a preset. Presets are a creation-time choice; subsequent starts use the workspace's existing version and parameters. Users who need a specific preset or version on an existing chat can create the workspace out-of-band (CLI / UI / API) with the desired configuration and attach the chat to it.toolsdkgainsGetTemplate(with presets includingdesired_prebuild_instances), preset support onCreateWorkspace, and preset +rich_parameterssupport onCreateWorkspaceBuild. Thetemplate_version_preset_iddescription warns about preset/version affinity.(cherry picked from commit 04cc983)