charmbracelet/crush · error
error parsing parameters: %s
Error message
error parsing parameters: %s
What it means
RunTool is the entry point for invoking an MCP tool; it expects `input` to be a JSON object that unmarshals into map[string]any. If json.Unmarshal fails (malformed JSON, or valid JSON that is not an object such as an array or string), the parse error is returned as `error parsing parameters: ...` and the tool is never called.
Source
Thrown at internal/agent/tools/mcp/tools.go:39
type ToolResult struct {
Type string
Content string
Data []byte
MediaType string
}
var allTools = csync.NewMap[string, []*Tool]()
// Tools returns all available MCP tools.
func Tools() iter.Seq2[string, []*Tool] {
return allTools.Seq2()
}
// RunTool runs an MCP tool with the given input parameters.
func RunTool(ctx context.Context, cfg *config.ConfigStore, name, toolName string, input string) (ToolResult, error) {
var args map[string]any
if err := json.Unmarshal([]byte(input), &args); err != nil {
return ToolResult{}, fmt.Errorf("error parsing parameters: %s", err)
}
c, err := getOrRenewClient(ctx, cfg, name)
if err != nil {
return ToolResult{}, err
}
result, err := c.CallTool(ctx, &mcp.CallToolParams{
Name: toolName,
Arguments: args,
})
if err != nil {
return ToolResult{}, err
}
if len(result.Content) == 0 {
return ToolResult{Type: "text", Content: ""}, nil
}
View on GitHub (pinned to 7944b8e522)
Solutions
- Marshal arguments with json.Marshal from a map[string]any/struct instead of hand-building the JSON string
- Validate the input parses as a JSON object before calling RunTool (json.Valid or an Unmarshal into map[string]any)
- Strip markdown fences or prose the model may have wrapped around the JSON
- Check for trailing commas/comments — Go's encoding/json rejects them; emit strict JSON
Example fix
// before
input := fmt.Sprintf(`{"path": %q}`, path) // breaks on quotes
// after
args, _ := json.Marshal(map[string]any{"path": path})
result, err := mcp.RunTool(ctx, cfg, name, toolName, string(args)) Defensive patterns
Strategy: validation
Validate before calling
var probe map[string]any
if err := json.Unmarshal([]byte(input), &probe); err != nil {
return fmt.Errorf("tool input is not a JSON object: %w", err)
}
result, err := mcp.RunTool(ctx, cfg, name, toolName, input) Type guard
func isJSONObject(s string) bool {
var m map[string]any
return json.Unmarshal([]byte(s), &m) == nil && m != nil
} Try / catch
result, err := mcp.RunTool(ctx, cfg, name, toolName, input)
var synthErr *json.SyntaxError
if errors.As(err, &synthErr) || strings.HasPrefix(err.Error(), "error parsing parameters") {
// re-marshal arguments from a typed struct instead of retrying raw
input = mustMarshalJSON(argsStruct)
result, err = mcp.RunTool(ctx, cfg, name, toolName, input)
} Prevention
- Always build tool arguments with json.Marshal, never string concatenation
- Strip markdown code fences from model output before parsing
- Reject trailing commas/comments — emit strict RFC 8259 JSON
When it happens
Trigger: Calling mcp.RunTool (or the agent invoking an MCP tool) with input that is not a JSON object: raw text, truncated JSON, single quotes instead of double quotes, a JSON array or bare string, or unescaped newlines/control characters inside strings.
Common situations: LLM emits pseudo-JSON with trailing commas or comments; tool arguments built by string concatenation instead of marshalling; upstream caller passes the raw model output without validating it is an object first.
Related errors
- failed to unmarshal response: %w
- failed to decode MCP prompt response: %w
- failed to decode MCP states: %w
- failed to decode MCP pending auth: %w
- failed to decode MCP auth URL: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/67135563edb49359.
Report an issue: GitHub.