blob: d67f39ec34e485ce397bb3b77d0b78cc587c93ca [file] [log] [blame] [edit]
// Copyright 2025 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package mcp
import (
"context"
"fmt"
"strconv"
"github.com/modelcontextprotocol/go-sdk/mcp"
"golang.org/x/tools/gopls/internal/cache/metadata"
)
type outlineParams struct {
PackagePaths []string `json:"packagePaths" jsonschema:"the go package paths to describe"`
}
func (h *handler) outlineHandler(ctx context.Context, req *mcp.CallToolRequest, params outlineParams) (*mcp.CallToolResult, any, error) {
countGoPackageAPIMCP.Inc()
snapshot, release, err := h.snapshot()
if err != nil {
return nil, nil, err
}
defer release()
// Await initialization to ensure we've at least got an initial package graph
md, err := snapshot.LoadMetadataGraph(ctx)
if err != nil {
return nil, nil, err
}
var toSummarize []*metadata.Package
for _, imp := range params.PackagePaths {
pkgPath := metadata.PackagePath(imp)
if len(imp) > 0 && imp[0] == '"' {
unquoted, err := strconv.Unquote(imp)
if err != nil {
return nil, nil, fmt.Errorf("failed to unquote %s: %v", imp, err)
}
pkgPath = metadata.PackagePath(unquoted)
}
if mps := md.ForPackagePath[pkgPath]; len(mps) > 0 {
toSummarize = append(toSummarize, mps[0]) // first is best
}
}
var content []mcp.Content
for _, mp := range toSummarize {
if md == nil {
continue // ignore error
}
if summary := summarizePackage(ctx, snapshot, mp); summary != "" {
content = append(content, &mcp.TextContent{Text: summary})
}
}
return &mcp.CallToolResult{
Content: content,
}, nil, nil
}