Skip to content

Commit 263a769

Browse files
committed
gopls/internal/mcp: use official go mcp sdk
The gopls MCP server currently uses an internal version of the Go MCP sdk. This CL updates it to use the official version at https://github.com/modelcontextprotocol/go-sdk Change-Id: I35bccd47b6fbb85aaf03f2d00283e07def9ce0f9 Reviewed-on: https://go-review.googlesource.com/c/tools/+/700901 Reviewed-by: Robert Findley <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent e548c70 commit 263a769

File tree

14 files changed

+315
-309
lines changed

14 files changed

+315
-309
lines changed

gopls/go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ require (
77
github.com/fsnotify/fsnotify v1.9.0
88
github.com/google/go-cmp v0.7.0
99
github.com/jba/templatecheck v0.7.1
10+
github.com/modelcontextprotocol/go-sdk v0.4.0
1011
golang.org/x/mod v0.27.0
1112
golang.org/x/sync v0.16.0
1213
golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488
@@ -23,7 +24,9 @@ require (
2324
github.com/BurntSushi/toml v1.5.0 // indirect
2425
github.com/fatih/camelcase v1.0.0 // indirect
2526
github.com/fatih/structtag v1.2.0 // indirect
27+
github.com/google/jsonschema-go v0.2.1-0.20250825175020-748c325cec76 // indirect
2628
github.com/google/safehtml v0.1.0 // indirect
29+
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
2730
golang.org/x/exp/typeparams v0.0.0-20250718183923-645b1fa84792 // indirect
2831
golang.org/x/sys v0.35.0 // indirect
2932
golang.org/x/tools/go/expect v0.1.1-deprecated // indirect

gopls/go.sum

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZs
1313
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
1414
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
1515
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
16+
github.com/google/jsonschema-go v0.2.1-0.20250825175020-748c325cec76 h1:mBlBwtDebdDYr+zdop8N62a44g+Nbv7o2KjWyS1deR4=
17+
github.com/google/jsonschema-go v0.2.1-0.20250825175020-748c325cec76/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE=
1618
github.com/google/safehtml v0.1.0 h1:EwLKo8qawTKfsi0orxcQAZzu07cICaBeFMegAU9eaT8=
1719
github.com/google/safehtml v0.1.0/go.mod h1:L4KWwDsUJdECRAEpZoBn3O64bQaywRscowZjJAzjHnU=
1820
github.com/jba/templatecheck v0.7.1 h1:yOEIFazBEwzdTPYHZF3Pm81NF1ksxx1+vJncSEwvjKc=
@@ -21,8 +23,12 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
2123
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
2224
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
2325
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
26+
github.com/modelcontextprotocol/go-sdk v0.4.0 h1:RJ6kFlneHqzTKPzlQqiunrz9nbudSZcYLmLHLsokfoU=
27+
github.com/modelcontextprotocol/go-sdk v0.4.0/go.mod h1:whv0wHnsTphwq7CTiKYHkLtwLC06WMoY2KpO+RB9yXQ=
2428
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
2529
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
30+
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
31+
github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
2632
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
2733
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
2834
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=

gopls/internal/licenses/licenses.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,82 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
204204
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
205205
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
206206
207+
-- github.com/google/jsonschema-go LICENSE --
208+
209+
MIT License
210+
211+
Copyright (c) 2025 JSON Schema Go Project Authors
212+
213+
Permission is hereby granted, free of charge, to any person obtaining a copy
214+
of this software and associated documentation files (the "Software"), to deal
215+
in the Software without restriction, including without limitation the rights
216+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
217+
copies of the Software, and to permit persons to whom the Software is
218+
furnished to do so, subject to the following conditions:
219+
220+
The above copyright notice and this permission notice shall be included in all
221+
copies or substantial portions of the Software.
222+
223+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
224+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
225+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
226+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
227+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
228+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
229+
SOFTWARE.
230+
231+
-- github.com/modelcontextprotocol/go-sdk LICENSE --
232+
233+
MIT License
234+
235+
Copyright (c) 2025 Go MCP SDK Authors
236+
237+
Permission is hereby granted, free of charge, to any person obtaining a copy
238+
of this software and associated documentation files (the "Software"), to deal
239+
in the Software without restriction, including without limitation the rights
240+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
241+
copies of the Software, and to permit persons to whom the Software is
242+
furnished to do so, subject to the following conditions:
243+
244+
The above copyright notice and this permission notice shall be included in all
245+
copies or substantial portions of the Software.
246+
247+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
248+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
249+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
250+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
251+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
252+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
253+
SOFTWARE.
254+
255+
-- github.com/yosida95/uritemplate/v3 LICENSE --
256+
257+
Copyright (C) 2016, Kohei YOSHIDA <https://yosida95.com/>. All rights reserved.
258+
259+
Redistribution and use in source and binary forms, with or without
260+
modification, are permitted provided that the following conditions are met:
261+
262+
* Redistributions of source code must retain the above copyright
263+
notice, this list of conditions and the following disclaimer.
264+
* Redistributions in binary form must reproduce the above copyright
265+
notice, this list of conditions and the following disclaimer in the
266+
documentation and/or other materials provided with the distribution.
267+
* Neither the name of the copyright holder nor the names of its
268+
contributors may be used to endorse or promote products derived from
269+
this software without specific prior written permission.
270+
271+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
272+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
273+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
274+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
275+
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
276+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
277+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
278+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
279+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
280+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
281+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
282+
207283
-- honnef.co/go/tools LICENSE --
208284
209285
Copyright (c) 2016 Dominik Honnef

gopls/internal/mcp/context.go

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"slices"
1717
"strings"
1818

19+
"github.com/modelcontextprotocol/go-sdk/mcp"
1920
"golang.org/x/tools/gopls/internal/cache"
2021
"golang.org/x/tools/gopls/internal/cache/metadata"
2122
"golang.org/x/tools/gopls/internal/cache/parsego"
@@ -24,39 +25,27 @@ import (
2425
"golang.org/x/tools/gopls/internal/protocol"
2526
"golang.org/x/tools/internal/analysisinternal"
2627
"golang.org/x/tools/internal/astutil"
27-
"golang.org/x/tools/internal/mcp"
2828
)
2929

3030
type ContextParams struct {
31-
File string `json:"file"`
31+
File string `json:"file" jsonschema:"the absolute path to the file"`
3232
}
3333

34-
func (h *handler) contextTool() *mcp.ServerTool {
35-
return mcp.NewServerTool(
36-
"go_context",
37-
"Provide context for a region within a Go file",
38-
h.contextHandler,
39-
mcp.Input(
40-
mcp.Property("file", mcp.Description("the absolute path to the file")),
41-
),
42-
)
43-
}
44-
45-
func (h *handler) contextHandler(ctx context.Context, _ *mcp.ServerSession, params *mcp.CallToolParamsFor[ContextParams]) (*mcp.CallToolResultFor[any], error) {
46-
fh, snapshot, release, err := h.fileOf(ctx, params.Arguments.File)
34+
func (h *handler) contextHandler(ctx context.Context, req *mcp.CallToolRequest, params ContextParams) (*mcp.CallToolResult, any, error) {
35+
fh, snapshot, release, err := h.fileOf(ctx, params.File)
4736
if err != nil {
48-
return nil, err
37+
return nil, nil, err
4938
}
5039
defer release()
5140

5241
// TODO(hxjiang): support context for GoMod.
5342
if snapshot.FileKind(fh) != file.Go {
54-
return nil, fmt.Errorf("can't provide context for non-Go file")
43+
return nil, nil, fmt.Errorf("can't provide context for non-Go file")
5544
}
5645

5746
pkg, pgf, err := golang.NarrowestPackageForFile(ctx, snapshot, fh.URI())
5847
if err != nil {
59-
return nil, err
48+
return nil, nil, err
6049
}
6150

6251
var result strings.Builder
@@ -67,7 +56,7 @@ func (h *handler) contextHandler(ctx context.Context, _ *mcp.ServerSession, para
6756
fmt.Fprintf(&result, "%s (current file):\n", pgf.URI.Base())
6857
result.WriteString("```go\n")
6958
if err := writeFileSummary(ctx, snapshot, pgf.URI, &result, false, nil); err != nil {
70-
return nil, err
59+
return nil, nil, err
7160
}
7261
result.WriteString("```\n\n")
7362
}
@@ -82,7 +71,7 @@ func (h *handler) contextHandler(ctx context.Context, _ *mcp.ServerSession, para
8271
fmt.Fprintf(&result, "%s:\n", file.URI.Base())
8372
result.WriteString("```go\n")
8473
if err := writeFileSummary(ctx, snapshot, file.URI, &result, false, nil); err != nil {
85-
return nil, err
74+
return nil, nil, err
8675
}
8776
result.WriteString("```\n\n")
8877
}
@@ -104,7 +93,7 @@ func (h *handler) contextHandler(ctx context.Context, _ *mcp.ServerSession, para
10493

10594
text, err := pgf.NodeText(genDecl)
10695
if err != nil {
107-
return nil, err
96+
return nil, nil, err
10897
}
10998

11099
result.Write(text)
@@ -144,7 +133,7 @@ func (h *handler) contextHandler(ctx context.Context, _ *mcp.ServerSession, para
144133
}
145134
}
146135

147-
return textResult(result.String()), nil
136+
return textResult(result.String()), nil, nil
148137
}
149138

150139
func summarizePackage(ctx context.Context, snapshot *cache.Snapshot, md *metadata.Package) string {

gopls/internal/mcp/file_context.go

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,41 +11,30 @@ import (
1111
"go/types"
1212
"strings"
1313

14+
"github.com/modelcontextprotocol/go-sdk/mcp"
1415
"golang.org/x/tools/gopls/internal/golang"
1516
"golang.org/x/tools/gopls/internal/protocol"
16-
"golang.org/x/tools/internal/mcp"
1717
)
1818

1919
type fileContextParams struct {
20-
File string `json:"file"`
20+
File string `json:"file" jsonschema:"the absolute path to the file"`
2121
}
2222

23-
func (h *handler) fileContextTool() *mcp.ServerTool {
24-
return mcp.NewServerTool(
25-
"go_file_context",
26-
"Summarizes a file's cross-file dependencies",
27-
h.fileContextHandler,
28-
mcp.Input(
29-
mcp.Property("file", mcp.Description("the absolute path to the file")),
30-
),
31-
)
32-
}
33-
34-
func (h *handler) fileContextHandler(ctx context.Context, _ *mcp.ServerSession, params *mcp.CallToolParamsFor[fileContextParams]) (*mcp.CallToolResultFor[any], error) {
35-
fh, snapshot, release, err := h.fileOf(ctx, params.Arguments.File)
23+
func (h *handler) fileContextHandler(ctx context.Context, req *mcp.CallToolRequest, params fileContextParams) (*mcp.CallToolResult, any, error) {
24+
fh, snapshot, release, err := h.fileOf(ctx, params.File)
3625
if err != nil {
37-
return nil, err
26+
return nil, nil, err
3827
}
3928
defer release()
4029

4130
pkg, pgf, err := golang.NarrowestPackageForFile(ctx, snapshot, fh.URI())
4231
if err != nil {
43-
return nil, err
32+
return nil, nil, err
4433
}
4534

4635
info := pkg.TypesInfo()
4736
if info == nil {
48-
return nil, fmt.Errorf("no types info for package %q", pkg.Metadata().PkgPath)
37+
return nil, nil, fmt.Errorf("no types info for package %q", pkg.Metadata().PkgPath)
4938
}
5039

5140
// Group objects defined in other files by file URI.
@@ -79,26 +68,26 @@ func (h *handler) fileContextHandler(ctx context.Context, _ *mcp.ServerSession,
7968
}
8069

8170
var result strings.Builder
82-
fmt.Fprintf(&result, "File `%s` is in package %q.\n", params.Arguments.File, pkg.Metadata().PkgPath)
71+
fmt.Fprintf(&result, "File `%s` is in package %q.\n", params.File, pkg.Metadata().PkgPath)
8372
fmt.Fprintf(&result, "Below is a summary of the APIs it uses from other files.\n")
8473
fmt.Fprintf(&result, "To read the full API of any package, use go_package_api.\n")
8574
for uri, decls := range otherFiles {
8675
pkgPath := "UNKNOWN"
8776
md, err := snapshot.NarrowestMetadataForFile(ctx, uri)
8877
if err != nil {
8978
if ctx.Err() != nil {
90-
return nil, ctx.Err()
79+
return nil, nil, ctx.Err()
9180
}
9281
} else {
9382
pkgPath = string(md.PkgPath)
9483
}
9584
fmt.Fprintf(&result, "Referenced declarations from %s (package %q):\n", uri.Path(), pkgPath)
9685
result.WriteString("```go\n")
9786
if err := writeFileSummary(ctx, snapshot, uri, &result, false, decls); err != nil {
98-
return nil, err
87+
return nil, nil, err
9988
}
10089
result.WriteString("```\n\n")
10190
}
10291

103-
return textResult(result.String()), nil
92+
return textResult(result.String()), nil, nil
10493
}

gopls/internal/mcp/file_diagnostics.go

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,46 +20,36 @@ import (
2020
"golang.org/x/tools/gopls/internal/golang"
2121
"golang.org/x/tools/gopls/internal/protocol"
2222
"golang.org/x/tools/internal/diff"
23-
"golang.org/x/tools/internal/mcp"
23+
24+
"github.com/modelcontextprotocol/go-sdk/mcp"
2425
)
2526

2627
type diagnosticsParams struct {
27-
File string `json:"file"`
28-
}
29-
30-
func (h *handler) fileDiagnosticsTool() *mcp.ServerTool {
31-
return mcp.NewServerTool(
32-
"go_file_diagnostics",
33-
"Provides diagnostics for a Go file",
34-
h.fileDiagnosticsHandler,
35-
mcp.Input(
36-
mcp.Property("file", mcp.Description("the absolute path to the file to diagnose")),
37-
),
38-
)
28+
File string `json:"file" jsonschema:"the absolute path to the file to diagnose"`
3929
}
4030

41-
func (h *handler) fileDiagnosticsHandler(ctx context.Context, _ *mcp.ServerSession, params *mcp.CallToolParamsFor[diagnosticsParams]) (*mcp.CallToolResultFor[any], error) {
42-
fh, snapshot, release, err := h.fileOf(ctx, params.Arguments.File)
31+
func (h *handler) fileDiagnosticsHandler(ctx context.Context, req *mcp.CallToolRequest, params diagnosticsParams) (*mcp.CallToolResult, any, error) {
32+
fh, snapshot, release, err := h.fileOf(ctx, params.File)
4333
if err != nil {
44-
return nil, err
34+
return nil, nil, err
4535
}
4636
defer release()
4737

4838
diagnostics, fixes, err := h.diagnoseFile(ctx, snapshot, fh.URI())
4939
if err != nil {
50-
return nil, err
40+
return nil, nil, err
5141
}
5242

5343
var builder strings.Builder
5444
if len(diagnostics) == 0 {
55-
return textResult("No diagnostics"), nil
45+
return textResult("No diagnostics"), nil, nil
5646
}
5747

5848
if err := summarizeDiagnostics(ctx, snapshot, &builder, diagnostics, fixes); err != nil {
59-
return nil, err
49+
return nil, nil, err
6050
}
6151

62-
return textResult(builder.String()), nil
52+
return textResult(builder.String()), nil, nil
6353
}
6454

6555
// diagnoseFile diagnoses a single file, including go/analysis and quick fixes.

0 commit comments

Comments
 (0)