104 lines
3.0 KiB
Go
104 lines
3.0 KiB
Go
|
|
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
|
||
|
|
})
|
||
|
|
}
|