From c0b3f64f839f312806823b8c069d0ab1e029273e Mon Sep 17 00:00:00 2001 From: Kevin Gil Date: Sat, 9 May 2026 19:56:30 -0700 Subject: [PATCH] Make workspace selection discoverable to MCP clients When a tool returned ErrNoWorkspace, the message told the model to "prompt the user" but never named list_workspaces / select_workspace, so models that hit the error often concluded no such tool existed and stalled. Two changes: 1. Rewrite ErrNoWorkspace to spell out the recovery path (list_workspaces -> ask user -> select_workspace -> retry) and explain why the model must not auto-select. 2. Pass server.WithInstructions on the MCP server so the workspace flow is in the host's system context from session start, before any workspace-gated tool is attempted. --- cmd/server.go | 15 +++++++++++++++ pkg/config/config.go | 7 ++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/cmd/server.go b/cmd/server.go index 4e7136e..9503806 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -22,11 +22,26 @@ import ( "github.com/render-oss/render-mcp-server/pkg/session" ) +const serverInstructions = `This server manages resources on Render (https://render.com). + +Workspace selection is required before most actions. Tools that operate on services, ` + + "deploys, postgres databases, key-value stores, logs, or metrics need a workspace to be " + + "selected for the current session.\n\n" + + `Workspace flow: + 1. If unsure whether a workspace is selected, call ` + "`get_selected_workspace`" + `. + 2. If none is selected (or a tool returns a "no workspace selected" error), call ` + + "`list_workspaces`" + ` to see available workspaces. + 3. Ask the user which workspace to use. NEVER pick one yourself — selecting the wrong ` + + `workspace can cause destructive actions on unintended resources. + 4. Once the user confirms, call ` + "`select_workspace`" + ` with the matching ownerID, then ` + + `retry the original tool call.` + func Serve(transport string) *server.MCPServer { // Create MCP server s := server.NewMCPServer( "render-mcp-server", cfg.Version, + server.WithInstructions(serverInstructions), ) c, err := client.NewDefaultClient() diff --git a/pkg/config/config.go b/pkg/config/config.go index 6c55a98..e6ab846 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -18,7 +18,12 @@ var defaultConfigPath string const configPathEnvKey = "RENDER_CONFIG_PATH" const workspaceEnvKey = "RENDER_WORKSPACE" -var ErrNoWorkspace = errors.New("no workspace set. Prompt the user to select a workspace. Do NOT try to select a workspace for them, as it may be destructive") +var ErrNoWorkspace = errors.New("no workspace selected. To resolve: " + + "(1) call the `list_workspaces` tool to see the workspaces this account has access to, " + + "(2) ask the user which workspace to use — do NOT pick one yourself, since acting on the " + + "wrong workspace can cause destructive changes to unintended resources, " + + "(3) once the user confirms, call the `select_workspace` tool with the matching `ownerID`, " + + "then retry the original tool call") var ErrLogin = errors.New("not authenticated; either set RENDER_API_KEY or ask your MCP host to authenticate") type Config struct {