diff --git a/cli/exp_mcp.go b/cli/exp_mcp.go index 8b8c96ab41863..35032a43d68fc 100644 --- a/cli/exp_mcp.go +++ b/cli/exp_mcp.go @@ -402,7 +402,9 @@ func mcpServerHandler(inv *serpent.Invocation, client *codersdk.Client, instruct // Create a new context for the tools with all relevant information. clientCtx := toolsdk.WithClient(ctx, client) // Get the workspace agent token from the environment. + var hasAgentClient bool if agentToken, err := getAgentToken(fs); err == nil && agentToken != "" { + hasAgentClient = true agentClient := agentsdk.New(client.URL) agentClient.SetSessionToken(agentToken) clientCtx = toolsdk.WithAgentClient(clientCtx, agentClient) @@ -417,6 +419,11 @@ func mcpServerHandler(inv *serpent.Invocation, client *codersdk.Client, instruct // Register tools based on the allowlist (if specified) for _, tool := range toolsdk.All { + // Skip adding the coder_report_task tool if there is no agent client + if !hasAgentClient && tool.Tool.Name == "coder_report_task" { + cliui.Warnf(inv.Stderr, "Task reporting not available") + continue + } if len(allowedTools) == 0 || slices.ContainsFunc(allowedTools, func(t string) bool { return t == tool.Tool.Name }) { @@ -689,6 +696,11 @@ func getAgentToken(fs afero.Fs) (string, error) { // mcpFromSDK adapts a toolsdk.Tool to go-mcp's server.ServerTool. // It assumes that the tool responds with a valid JSON object. func mcpFromSDK(sdkTool toolsdk.Tool[any]) server.ServerTool { + // NOTE: some clients will silently refuse to use tools if there is an issue + // with the tool's schema or configuration. + if sdkTool.Schema.Properties == nil { + panic("developer error: schema properties cannot be nil") + } return server.ServerTool{ Tool: mcp.Tool{ Name: sdkTool.Tool.Name, diff --git a/codersdk/toolsdk/toolsdk.go b/codersdk/toolsdk/toolsdk.go index 835c37a65180e..134c30c4f1474 100644 --- a/codersdk/toolsdk/toolsdk.go +++ b/codersdk/toolsdk/toolsdk.go @@ -259,6 +259,10 @@ is provisioned correctly and the agent can connect to the control plane. Tool: aisdk.Tool{ Name: "coder_list_templates", Description: "Lists templates for the authenticated user.", + Schema: aisdk.Schema{ + Properties: map[string]any{}, + Required: []string{}, + }, }, Handler: func(ctx context.Context, _ map[string]any) ([]MinimalTemplate, error) { client, err := clientFromContext(ctx) @@ -318,6 +322,10 @@ is provisioned correctly and the agent can connect to the control plane. Tool: aisdk.Tool{ Name: "coder_get_authenticated_user", Description: "Get the currently authenticated user, similar to the `whoami` command.", + Schema: aisdk.Schema{ + Properties: map[string]any{}, + Required: []string{}, + }, }, Handler: func(ctx context.Context, _ map[string]any) (codersdk.User, error) { client, err := clientFromContext(ctx)
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: