package tools import ( "context" "code.nochebuena.dev/einherjar/mcp/internal/index" "github.com/modelcontextprotocol/go-sdk/mcp" ) type getModuleInput struct { Name string `json:"name" jsonschema:"the module name, e.g. core, web, auth-jwt"` IncludeReadme bool `json:"includeReadme,omitempty" jsonschema:"when true, embed the full README markdown in the response"` } type getModuleOutput struct { Name string `json:"name"` ImportPath string `json:"importPath"` Purpose string `json:"purpose"` Doc string `json:"doc"` GoVersion string `json:"goVersion"` DependsOn []string `json:"dependsOn"` SubPackages []index.SubPackage `json:"subPackages"` KeySymbols []symbolHeader `json:"keySymbols"` ADRs []adrHeader `json:"adrs"` Compliance complianceSummary `json:"compliance"` Readme string `json:"readme,omitempty"` } type complianceSummary struct { InterfaceAssertCount int `json:"interfaceAssertCount"` TestCount int `json:"testCount"` } type symbolHeader struct { Kind string `json:"kind"` Name string `json:"name"` SubPackage string `json:"subPackage"` Signature string `json:"signature"` } type adrHeader struct { ID string `json:"id"` Title string `json:"title"` } func registerGetModule(s *mcp.Server, idx *index.Index) { mcp.AddTool(s, &mcp.Tool{ Name: "get_module", Description: "Describe one Einherjar module: sub-packages, key exported symbols (types/interfaces/funcs), and ADRs. Set includeReadme=true to also receive the README markdown.", }, func(ctx context.Context, req *mcp.CallToolRequest, args getModuleInput) (*mcp.CallToolResult, getModuleOutput, error) { m := idx.FindModule(args.Name) if m == nil { return errorResult("module not found: " + args.Name), getModuleOutput{}, nil } key := make([]symbolHeader, 0, len(m.Symbols)) for _, sym := range m.Symbols { if sym.Kind == "type" || sym.Kind == "interface" || sym.Kind == "func" { key = append(key, symbolHeader{ Kind: sym.Kind, Name: sym.Name, SubPackage: sym.SubPackage, Signature: sym.Signature, }) } } adrs := make([]adrHeader, 0, len(m.ADRs)) for _, a := range m.ADRs { adrs = append(adrs, adrHeader{ID: a.ID, Title: a.Title}) } subs := make([]index.SubPackage, 0, len(m.SubPackages)) for _, sp := range m.SubPackages { if sp.Name == "" { continue } subs = append(subs, sp) } deps := m.DependsOn if deps == nil { deps = []string{} } out := getModuleOutput{ Name: m.Name, ImportPath: m.ImportPath, Purpose: m.Purpose, Doc: m.Doc, GoVersion: m.GoVersion, DependsOn: deps, SubPackages: subs, KeySymbols: key, ADRs: adrs, Compliance: complianceSummary{ InterfaceAssertCount: len(m.Compliance.InterfaceAsserts), TestCount: len(m.Compliance.Tests), }, } if args.IncludeReadme { out.Readme = m.Readme } return jsonText(out), out, nil }) }