MCPcopy Index your code
hub / github.com/github/github-mcp-server / ScanReadOnlyHint

Function ScanReadOnlyHint

pkg/toolvalidation/readonlyhint.go:59–95  ·  view source on GitHub ↗

ScanReadOnlyHint parses every non-test .go file in dir (a single package directory) and returns a violation for each mcp.Tool composite literal that does not explicitly set Annotations.ReadOnlyHint. The Go runtime cannot distinguish an unset bool field from one explicitly set to false, so this AST-

(dir string)

Source from the content-addressed store, hash-verified

57// dir, _ := os.Getwd()
58// violations, err := toolvalidation.ScanReadOnlyHint(dir)
59func ScanReadOnlyHint(dir string) ([]ReadOnlyHintViolation, error) {
60 fset := token.NewFileSet()
61 pkgs, err := parser.ParseDir(fset, dir, func(info os.FileInfo) bool {
62 // Skip test files: they are allowed to construct mcp.Tool literals
63 // for fixtures or mocks where ReadOnlyHint is not meaningful.
64 return !strings.HasSuffix(info.Name(), "_test.go")
65 }, parser.ParseComments)
66 if err != nil {
67 return nil, fmt.Errorf("parse package directory %q: %w", dir, err)
68 }
69
70 var violations []ReadOnlyHintViolation
71 for _, pkg := range pkgs {
72 for filename, file := range pkg.Files {
73 aliases := mcpAliasesFor(file)
74 if len(aliases) == 0 {
75 continue
76 }
77 rel, relErr := filepath.Rel(dir, filename)
78 if relErr != nil || rel == "" {
79 rel = filepath.Base(filename)
80 }
81 ast.Inspect(file, func(n ast.Node) bool {
82 cl, ok := n.(*ast.CompositeLit)
83 if !ok {
84 return true
85 }
86 if !isQualifiedType(cl.Type, aliases, "Tool") {
87 return true
88 }
89 violations = append(violations, checkToolLiteral(cl, aliases, rel, fset.Position(cl.Pos()).Line)...)
90 return true
91 })
92 }
93 }
94 return violations, nil
95}
96
97// FormatReadOnlyHintViolations renders a single multi-line error message
98// suitable for passing to t.Fatal. Returns "" when violations is empty.

Calls 4

mcpAliasesForFunction · 0.85
isQualifiedTypeFunction · 0.85
checkToolLiteralFunction · 0.85
NameMethod · 0.80