Skip to content

Commit 06dcc33

Browse files
committed
url optional and description update
1 parent 862d013 commit 06dcc33

File tree

3 files changed

+101
-43
lines changed

3 files changed

+101
-43
lines changed

cmd/godoc-mcp-server/packageInfo.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,34 @@ import (
1212

1313
func getPackageInfoTool() (tool mcp.Tool, handler server.ToolHandlerFunc) {
1414
return mcp.NewTool("getPackageInfo",
15-
mcp.WithDescription("provide a golang package name,get package consts,types,functions,variables, subpackages from pkg.go.dev"),
15+
mcp.WithDescription("provide a golang package name,get package consts,types,functions,variables,"+
16+
"subpackages and how to use it"),
1617
mcp.WithString("packageName",
1718
mcp.Required(),
18-
mcp.Description("package name for search")),
19+
mcp.Description("package name for search. if use searchPackages before, and user want to get the "+
20+
"subpackage info. you should plus them for example, when user query mcp, and it return packageName: "+
21+
"github.com/mark3labs/mcp-go/mcp and subpackage client, then if user want to get the client package info, "+
22+
"you should set the packageName to github.com/mark3labs/mcp-go/mcp/client rather than client"),
23+
),
24+
mcp.WithBoolean("needURL",
25+
mcp.Description("default is false. if it`s true, will return the url of the definition of the "+
26+
"package`s consts,types,functions,variables,subpackages. only when user need it, set it"),
27+
),
1928
),
2029
func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
2130
pkgName, err := requiredParam[string](request, "packageName")
2231
if err != nil {
2332
return mcp.NewToolResultError(err.Error()), nil
2433
}
25-
pkgDoc, err := godoc.GetPackageDocument(pkgName)
34+
35+
needURL, _, err := OptionalParamOK[bool](request, "needURL")
36+
if err != nil {
37+
return mcp.NewToolResultError(err.Error()), nil
38+
}
39+
pkgDoc, err := godoc.GetPackageDocument(godoc.GetPackageRequest{
40+
PackageName: pkgName,
41+
NeedURL: needURL,
42+
})
2643
if err != nil {
2744
return nil, errors.WithMessage(err, "get pkg info failed")
2845
}

cmd/godoc-mcp-server/server.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,27 @@ func requiredParam[T comparable](r mcp.CallToolRequest, p string) (T, error) {
3131

3232
return r.Params.Arguments[p].(T), nil
3333
}
34+
35+
// OptionalParamOK is a helper function that can be used to fetch a requested parameter from the request.
36+
// It returns the value, a boolean indicating if the parameter was present, and an error if the type is wrong.
37+
func OptionalParamOK[T any](r mcp.CallToolRequest, p string) (value T, ok bool, err error) {
38+
// Check if the parameter is present in the request
39+
val, exists := r.Params.Arguments[p]
40+
if !exists {
41+
// Not present, return zero value, false, no error
42+
return
43+
}
44+
45+
// Check if the parameter is of the expected type
46+
value, ok = val.(T)
47+
if !ok {
48+
// Present but wrong type
49+
err = fmt.Errorf("parameter %s is not of type %T, is %T", p, value, val)
50+
ok = true // Set ok to true because the parameter *was* present, even if wrong type
51+
return
52+
}
53+
54+
// Present and correct type
55+
ok = true
56+
return
57+
}

pkg/godoc/package.go

Lines changed: 57 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -56,46 +56,51 @@ type SubPackage struct {
5656
Comment string
5757
}
5858

59-
func GetPackageDocument(pkgName string) (*PackageDocument, error) {
59+
type GetPackageRequest struct {
60+
PackageName string
61+
NeedURL bool
62+
}
63+
64+
func GetPackageDocument(req GetPackageRequest) (*PackageDocument, error) {
6065
resp, err := client().
6166
R().
62-
Get(baseURL() + "/" + pkgName)
67+
Get(baseURL() + "/" + req.PackageName)
6368
if err != nil {
6469
return nil, errors.WithStack(err)
6570
}
66-
result, err := extractDocResult(resp.String())
71+
result, err := extractDocResult(resp.String(), req)
6772
if err != nil {
6873
return nil, err
6974
}
7075
return result, nil
7176
}
7277

73-
func extractDocResult(html string) (*PackageDocument, error) {
78+
func extractDocResult(html string, req GetPackageRequest) (*PackageDocument, error) {
7479
doc, err := getDoc(html)
7580
if err != nil {
7681
return nil, err
7782
}
78-
overview, err := extractDocOverview(doc)
83+
overview, err := extractDocOverview(doc, req)
7984
if err != nil {
8085
return nil, err
8186
}
82-
consts, err := extractDocConsts(doc)
87+
consts, err := extractDocConsts(doc, req)
8388
if err != nil {
8489
return nil, err
8590
}
86-
variables, err := extractDocVariables(doc)
91+
variables, err := extractDocVariables(doc, req)
8792
if err != nil {
8893
return nil, err
8994
}
90-
fns, err := extractDocFunctions(doc)
95+
fns, err := extractDocFunctions(doc, req)
9196
if err != nil {
9297
return nil, err
9398
}
94-
types, err := extractDocTypes(doc)
99+
types, err := extractDocTypes(doc, req)
95100
if err != nil {
96101
return nil, err
97102
}
98-
subPackages, err := extractSubPackages(doc)
103+
subPackages, err := extractSubPackages(doc, req)
99104
if err != nil {
100105
return nil, err
101106
}
@@ -110,14 +115,14 @@ func extractDocResult(html string) (*PackageDocument, error) {
110115
}, nil
111116
}
112117

113-
func extractDocOverview(doc *goquery.Document) (string, error) {
118+
func extractDocOverview(doc *goquery.Document, req GetPackageRequest) (string, error) {
114119
var overview string
115120

116121
overview = doc.Find("section.Documentation-overview p").Text()
117122
return overview, nil
118123
}
119124

120-
func extractDocConsts(doc *goquery.Document) ([]ConstBlock, error) {
125+
func extractDocConsts(doc *goquery.Document, req GetPackageRequest) ([]ConstBlock, error) {
121126
var consts []ConstBlock
122127
doc.
123128
Find("section.Documentation-constants").
@@ -126,9 +131,12 @@ func extractDocConsts(doc *goquery.Document) ([]ConstBlock, error) {
126131
// 如果现在是 div 标签,则是常量定义
127132
if s.Is("div") {
128133
cb := ConstBlock{}
129-
// 常量定义里有超链接和定义
130-
url, _ := s.Find("a.Documentation-source").Attr("href")
131-
cb.SourceURL = url
134+
if req.NeedURL {
135+
// 常量定义里有超链接和定义
136+
url, _ := s.Find("a.Documentation-source").Attr("href")
137+
cb.SourceURL = url
138+
}
139+
132140
// 找到 pre 标签,里面是定义
133141
var lines []string
134142
s.Find("pre").Each(func(i int, s *goquery.Selection) {
@@ -149,18 +157,20 @@ func extractDocConsts(doc *goquery.Document) ([]ConstBlock, error) {
149157
return consts, nil
150158
}
151159

152-
func extractDocVariables(doc *goquery.Document) ([]VariableBlock, error) {
160+
func extractDocVariables(doc *goquery.Document, req GetPackageRequest) ([]VariableBlock, error) {
153161
var vars []VariableBlock
154162
doc.
155163
Find("section.Documentation-variables").
156164
Children().
157165
Each(func(i int, s *goquery.Selection) {
158-
// 如果现在是 div 标签,则是常量定义
159166
if s.Is("div") && s.AttrOr("class", "") == "Documentation-declaration" {
160167
vb := VariableBlock{}
161-
// 常量定义里有超链接和定义
162-
url, _ := s.Find("a.Documentation-source").Attr("href")
163-
vb.SourceURL = url
168+
if req.NeedURL {
169+
// 定义里有超链接和定义
170+
url, _ := s.Find("a.Documentation-source").Attr("href")
171+
vb.SourceURL = url
172+
}
173+
164174
// 找到 pre 标签,里面是定义
165175
var lines []string
166176
s.Find("pre").Each(func(i int, s *goquery.Selection) {
@@ -181,7 +191,7 @@ func extractDocVariables(doc *goquery.Document) ([]VariableBlock, error) {
181191
return vars, nil
182192
}
183193

184-
func extractDocFunctions(doc *goquery.Document) ([]FunctionBlock, error) {
194+
func extractDocFunctions(doc *goquery.Document, req GetPackageRequest) ([]FunctionBlock, error) {
185195
var fns []FunctionBlock
186196
doc.
187197
Find("section.Documentation-functions").
@@ -190,7 +200,9 @@ func extractDocFunctions(doc *goquery.Document) ([]FunctionBlock, error) {
190200
Each(func(i int, s *goquery.Selection) {
191201
fnb := FunctionBlock{}
192202
// Documentation-source 超链接到定义
193-
fnb.SourceURL = s.Find("a.Documentation-source").AttrOr("href", "")
203+
if req.NeedURL {
204+
fnb.SourceURL = s.Find("a.Documentation-source").AttrOr("href", "")
205+
}
194206

195207
//Documentation-declaration 是函数定义
196208
s.Find("div.Documentation-declaration").
@@ -210,7 +222,7 @@ func extractDocFunctions(doc *goquery.Document) ([]FunctionBlock, error) {
210222
return fns, nil
211223
}
212224

213-
func extractDocTypes(doc *goquery.Document) ([]TypeBlock, error) {
225+
func extractDocTypes(doc *goquery.Document, req GetPackageRequest) ([]TypeBlock, error) {
214226
var types []TypeBlock
215227
var err error
216228
doc.
@@ -219,13 +231,15 @@ func extractDocTypes(doc *goquery.Document) ([]TypeBlock, error) {
219231
Find("div.Documentation-type").
220232
Each(func(i int, s *goquery.Selection) {
221233
tpb := TypeBlock{}
222-
// 找到 h4 标签 Documentation-typeHeader
223-
// 找到 a 标签 Documentation-source
224-
// 这是类型的链接
225-
tpb.SourceURL = s.
226-
Find("h4.Documentation-typeHeader").
227-
Find("a.Documentation-source").
228-
AttrOr("href", "")
234+
if req.NeedURL {
235+
// 找到 h4 标签 Documentation-typeHeader
236+
// 找到 a 标签 Documentation-source
237+
// 这是类型的链接
238+
tpb.SourceURL = s.
239+
Find("h4.Documentation-typeHeader").
240+
Find("a.Documentation-source").
241+
AttrOr("href", "")
242+
}
229243

230244
// 找到 div.Documentation-declaration 是定义
231245
s.Find("div.Documentation-declaration").
@@ -239,7 +253,7 @@ func extractDocTypes(doc *goquery.Document) ([]TypeBlock, error) {
239253
})
240254
// 找到p标签 是注释
241255
tpb.Comment = s.Find("p").Text()
242-
tpMethods, _err := extractDocTypeMethods(s)
256+
tpMethods, _err := extractDocTypeMethods(s, req)
243257
if _err != nil {
244258
err = multierr.Append(err, _err)
245259
return
@@ -254,17 +268,20 @@ func extractDocTypes(doc *goquery.Document) ([]TypeBlock, error) {
254268
}
255269

256270
// 需要传入 extractDocTypes 中的 Documentation-type 节点
257-
func extractDocTypeMethods(s *goquery.Selection) ([]TypeMethod, error) {
271+
func extractDocTypeMethods(s *goquery.Selection, req GetPackageRequest) ([]TypeMethod, error) {
258272
var methods []TypeMethod
259273
s.
260274
Find("div.Documentation-typeMethod").
261275
Each(func(i int, s *goquery.Selection) {
262276
method := TypeMethod{}
263-
// url
264-
method.SourceURL = s.
265-
Find("h4.Documentation-typeMethodHeader").
266-
Find("a.Documentation-source").
267-
AttrOr("href", "")
277+
if req.NeedURL {
278+
// url
279+
method.SourceURL = s.
280+
Find("h4.Documentation-typeMethodHeader").
281+
Find("a.Documentation-source").
282+
AttrOr("href", "")
283+
}
284+
268285
// 定义
269286
s.Find("div.Documentation-declaration").
270287
Each(func(i int, s *goquery.Selection) {
@@ -282,7 +299,7 @@ func extractDocTypeMethods(s *goquery.Selection) ([]TypeMethod, error) {
282299
return methods, nil
283300
}
284301

285-
func extractSubPackages(doc *goquery.Document) ([]*SubPackage, error) {
302+
func extractSubPackages(doc *goquery.Document, req GetPackageRequest) ([]*SubPackage, error) {
286303
var subPackages []*SubPackage
287304
var err error
288305

@@ -296,7 +313,7 @@ func extractSubPackages(doc *goquery.Document) ([]*SubPackage, error) {
296313

297314
if hasSubPackage {
298315
// 目录要处理自己和子包
299-
dir, _err := extractSubPackageAsDir(s)
316+
dir, _err := extractSubPackageAsDir(s, req)
300317
if _err != nil {
301318
err = multierr.Append(err, _err)
302319
return
@@ -350,7 +367,7 @@ func extractSubPackage(s *goquery.Selection) (*SubPackage, error) {
350367
}, nil
351368
}
352369

353-
func extractSubPackageAsDir(s *goquery.Selection) (*SubPackage, error) {
370+
func extractSubPackageAsDir(s *goquery.Selection, req GetPackageRequest) (*SubPackage, error) {
354371

355372
// pathCell name
356373
name := s.Find("div.UnitDirectories-pathCell").Find("span").Text()

0 commit comments

Comments
 (0)