Files
mcp/internal/tools/validate_snippet.go
T

83 lines
2.1 KiB
Go
Raw Normal View History

package tools
import (
"context"
"code.nochebuena.dev/einherjar/mcp/internal/index"
"code.nochebuena.dev/einherjar/mcp/internal/rules"
"github.com/modelcontextprotocol/go-sdk/mcp"
)
type validateSnippetInput struct {
Code string `json:"code" jsonschema:"Go source code to validate against Einherjar conventions. A full file is preferred; a partial body will be wrapped automatically."`
}
type validateSnippetOutput struct {
Findings []rules.Finding `json:"findings"`
Summary string `json:"summary"`
}
func registerValidateSnippet(s *mcp.Server, _ *index.Index) {
mcp.AddTool(s, &mcp.Tool{
Name: "validate_snippet",
Description: "Validate a Go snippet against Einherjar wiring conventions: lifecycle setup, logger configuration, env-var handling, server registration. Findings are advisory, not a substitute for go vet or the project's tests.",
}, func(ctx context.Context, req *mcp.CallToolRequest, args validateSnippetInput) (*mcp.CallToolResult, validateSnippetOutput, error) {
findings := rules.Run(args.Code)
if findings == nil {
findings = []rules.Finding{}
}
summary := summarise(findings)
out := validateSnippetOutput{Findings: findings, Summary: summary}
return jsonText(out), out, nil
})
}
func summarise(fs []rules.Finding) string {
if len(fs) == 0 {
return "No issues found — snippet follows Einherjar conventions."
}
var errs, warns, infos int
for _, f := range fs {
switch f.Severity {
case rules.SeverityError:
errs++
case rules.SeverityWarning:
warns++
case rules.SeverityInfo:
infos++
}
}
return pluralise(errs, "error", "errors") + ", " +
pluralise(warns, "warning", "warnings") + ", " +
pluralise(infos, "note", "notes")
}
func pluralise(n int, singular, plural string) string {
if n == 1 {
return "1 " + singular
}
return itoa(n) + " " + plural
}
func itoa(n int) string {
if n == 0 {
return "0"
}
neg := n < 0
if neg {
n = -n
}
var buf [20]byte
i := len(buf)
for n > 0 {
i--
buf[i] = byte('0' + n%10)
n /= 10
}
if neg {
i--
buf[i] = '-'
}
return string(buf[i:])
}