Skip to content

Commit 7b0422b

Browse files
authored
fix(codersdk/toolsdk): fix tool schemata (#17365)
Fixes two issues with the MCP server: - Ensures we have a non-null schema, as the following schema was making claude-code unhappy: ``` "inputSchema": { "type": "object", "properties": null }, ``` - Skip adding the coder_report_task tool if an agent client is not available. Otherwise the agent may try to report tasks and get confused.
1 parent 6330b0d commit 7b0422b

File tree

2 files changed

+20
-0
lines changed

2 files changed

+20
-0
lines changed

cli/exp_mcp.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,9 @@ func mcpServerHandler(inv *serpent.Invocation, client *codersdk.Client, instruct
402402
// Create a new context for the tools with all relevant information.
403403
clientCtx := toolsdk.WithClient(ctx, client)
404404
// Get the workspace agent token from the environment.
405+
var hasAgentClient bool
405406
if agentToken, err := getAgentToken(fs); err == nil && agentToken != "" {
407+
hasAgentClient = true
406408
agentClient := agentsdk.New(client.URL)
407409
agentClient.SetSessionToken(agentToken)
408410
clientCtx = toolsdk.WithAgentClient(clientCtx, agentClient)
@@ -417,6 +419,11 @@ func mcpServerHandler(inv *serpent.Invocation, client *codersdk.Client, instruct
417419

418420
// Register tools based on the allowlist (if specified)
419421
for _, tool := range toolsdk.All {
422+
// Skip adding the coder_report_task tool if there is no agent client
423+
if !hasAgentClient && tool.Tool.Name == "coder_report_task" {
424+
cliui.Warnf(inv.Stderr, "Task reporting not available")
425+
continue
426+
}
420427
if len(allowedTools) == 0 || slices.ContainsFunc(allowedTools, func(t string) bool {
421428
return t == tool.Tool.Name
422429
}) {
@@ -689,6 +696,11 @@ func getAgentToken(fs afero.Fs) (string, error) {
689696
// mcpFromSDK adapts a toolsdk.Tool to go-mcp's server.ServerTool.
690697
// It assumes that the tool responds with a valid JSON object.
691698
func mcpFromSDK(sdkTool toolsdk.Tool[any]) server.ServerTool {
699+
// NOTE: some clients will silently refuse to use tools if there is an issue
700+
// with the tool's schema or configuration.
701+
if sdkTool.Schema.Properties == nil {
702+
panic("developer error: schema properties cannot be nil")
703+
}
692704
return server.ServerTool{
693705
Tool: mcp.Tool{
694706
Name: sdkTool.Tool.Name,

codersdk/toolsdk/toolsdk.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,10 @@ is provisioned correctly and the agent can connect to the control plane.
259259
Tool: aisdk.Tool{
260260
Name: "coder_list_templates",
261261
Description: "Lists templates for the authenticated user.",
262+
Schema: aisdk.Schema{
263+
Properties: map[string]any{},
264+
Required: []string{},
265+
},
262266
},
263267
Handler: func(ctx context.Context, _ map[string]any) ([]MinimalTemplate, error) {
264268
client, err := clientFromContext(ctx)
@@ -318,6 +322,10 @@ is provisioned correctly and the agent can connect to the control plane.
318322
Tool: aisdk.Tool{
319323
Name: "coder_get_authenticated_user",
320324
Description: "Get the currently authenticated user, similar to the `whoami` command.",
325+
Schema: aisdk.Schema{
326+
Properties: map[string]any{},
327+
Required: []string{},
328+
},
321329
},
322330
Handler: func(ctx context.Context, _ map[string]any) (codersdk.User, error) {
323331
client, err := clientFromContext(ctx)

0 commit comments

Comments
 (0)