Files
registry_mcp/tool_doctor.go
2026-05-09 13:29:32 +02:00

52 lines
1.5 KiB
Go

package main
import (
"context"
"encoding/json"
"os/exec"
"github.com/mark3labs/mcp-go/mcp"
)
type doctorArgs struct {
Subcommand string `json:"subcommand,omitempty"`
}
func doctorTool() mcp.Tool {
return mcp.NewTool("fn_doctor",
mcp.WithDescription("Run `fn doctor [subcommand] --json` and return the parsed report. Subcommands: artefacts, services, sync, uses-functions, unused. Empty = all checks. Read-only."),
mcp.WithString("subcommand",
mcp.Description("Subcommand. Empty runs all."),
mcp.Enum("", "artefacts", "services", "sync", "uses-functions", "unused"),
),
)
}
func (d *deps) handleDoctor(ctx context.Context, _ mcp.CallToolRequest, args doctorArgs) (*mcp.CallToolResult, error) {
bin := d.fnBin()
cmdArgs := []string{"doctor"}
if args.Subcommand != "" {
cmdArgs = append(cmdArgs, args.Subcommand)
}
cmdArgs = append(cmdArgs, "--json")
cmd := exec.CommandContext(ctx, bin, cmdArgs...)
cmd.Dir = d.root
out, err := cmd.Output()
if err != nil {
stderr := ""
if ee, ok := err.(*exec.ExitError); ok {
stderr = string(ee.Stderr)
}
return mcp.NewToolResultError("fn doctor: " + err.Error() + "\n" + stderr), nil
}
// Try to parse JSON; if it fails, return the raw output.
var report any
if jsonErr := json.Unmarshal(out, &report); jsonErr != nil {
return mcp.NewToolResultText(string(out)), nil
}
b, _ := json.MarshalIndent(map[string]any{"subcommand": args.Subcommand, "report": report}, "", " ")
return mcp.NewToolResultText(string(b)), nil
}