Skip to main content
Glama

https://github.com/sammcj/mcp-package-version

by sammcj
java.go7.84 kB
package handlers import ( "context" "encoding/json" "fmt" "sort" "strings" "sync" "github.com/mark3labs/mcp-go/mcp" "github.com/sirupsen/logrus" ) const ( // MavenCentralURL is the base URL for the Maven Central API MavenCentralURL = "https://search.maven.org/solrsearch/select" ) // JavaHandler handles Java package version checking type JavaHandler struct { client HTTPClient cache *sync.Map logger *logrus.Logger } // NewJavaHandler creates a new Java handler func NewJavaHandler(logger *logrus.Logger, cache *sync.Map) *JavaHandler { if cache == nil { cache = &sync.Map{} } return &JavaHandler{ client: DefaultHTTPClient, cache: cache, logger: logger, } } // MavenSearchResponse represents a response from the Maven Central API type MavenSearchResponse struct { Response struct { NumFound int `json:"numFound"` Docs []struct { ID string `json:"id"` GroupID string `json:"g"` ArtifactID string `json:"a"` Version string `json:"v"` Versions []string `json:"versions,omitempty"` } `json:"docs"` } `json:"response"` } // getLatestVersion gets the latest version of a Maven artifact func (h *JavaHandler) getLatestVersion(groupID, artifactID string) (string, error) { // Check cache first cacheKey := fmt.Sprintf("maven:%s:%s", groupID, artifactID) if cachedVersion, ok := h.cache.Load(cacheKey); ok { h.logger.WithFields(logrus.Fields{ "groupId": groupID, "artifactId": artifactID, }).Debug("Using cached Maven artifact version") return cachedVersion.(string), nil } // Construct URL queryURL := fmt.Sprintf("%s?q=g:%s+AND+a:%s&core=gav&rows=1&wt=json", MavenCentralURL, groupID, artifactID) h.logger.WithFields(logrus.Fields{ "groupId": groupID, "artifactId": artifactID, "url": queryURL, }).Debug("Fetching Maven artifact info") // Make request body, err := MakeRequestWithLogger(h.client, h.logger, "GET", queryURL, nil) if err != nil { return "", fmt.Errorf("failed to fetch Maven artifact info: %w", err) } // Parse response var response MavenSearchResponse if err := json.Unmarshal(body, &response); err != nil { return "", fmt.Errorf("failed to parse Maven artifact info: %w", err) } // Check if artifact was found if response.Response.NumFound == 0 || len(response.Response.Docs) == 0 { return "", fmt.Errorf("artifact not found: %s:%s", groupID, artifactID) } // Get latest version latestVersion := response.Response.Docs[0].Version // Cache result h.cache.Store(cacheKey, latestVersion) return latestVersion, nil } // GetLatestVersionFromMaven gets the latest version of Java packages from Maven func (h *JavaHandler) GetLatestVersionFromMaven(ctx context.Context, args map[string]interface{}) (*mcp.CallToolResult, error) { h.logger.Debug("Getting latest Maven package versions") // Parse dependencies depsRaw, ok := args["dependencies"] if !ok { return nil, fmt.Errorf("missing required parameter: dependencies") } // Convert to []MavenDependency var deps []MavenDependency if depsArr, ok := depsRaw.([]interface{}); ok { for _, depRaw := range depsArr { if depMap, ok := depRaw.(map[string]interface{}); ok { var dep MavenDependency if groupID, ok := depMap["groupId"].(string); ok { dep.GroupID = groupID } else { continue } if artifactID, ok := depMap["artifactId"].(string); ok { dep.ArtifactID = artifactID } else { continue } if version, ok := depMap["version"].(string); ok { dep.Version = version } if scope, ok := depMap["scope"].(string); ok { dep.Scope = scope } deps = append(deps, dep) } } } else { return nil, fmt.Errorf("invalid dependencies format: expected array") } // Process each dependency results := make([]PackageVersion, 0, len(deps)) for _, dep := range deps { h.logger.WithFields(logrus.Fields{ "groupId": dep.GroupID, "artifactId": dep.ArtifactID, "version": dep.Version, }).Debug("Processing Maven dependency") // Get latest version latestVersion, err := h.getLatestVersion(dep.GroupID, dep.ArtifactID) if err != nil { h.logger.WithFields(logrus.Fields{ "groupId": dep.GroupID, "artifactId": dep.ArtifactID, "error": err.Error(), }).Error("Failed to get Maven artifact info") results = append(results, PackageVersion{ Name: fmt.Sprintf("%s:%s", dep.GroupID, dep.ArtifactID), CurrentVersion: StringPtr(dep.Version), LatestVersion: "unknown", Registry: "maven", Skipped: true, SkipReason: fmt.Sprintf("Failed to fetch artifact info: %v", err), }) continue } // Add result name := fmt.Sprintf("%s:%s", dep.GroupID, dep.ArtifactID) if dep.Scope != "" { name = fmt.Sprintf("%s (%s)", name, dep.Scope) } results = append(results, PackageVersion{ Name: name, CurrentVersion: StringPtr(dep.Version), LatestVersion: latestVersion, Registry: "maven", }) } // Sort results by name sort.Slice(results, func(i, j int) bool { return strings.ToLower(results[i].Name) < strings.ToLower(results[j].Name) }) return NewToolResultJSON(results) } // GetLatestVersionFromGradle gets the latest version of Java packages from Gradle func (h *JavaHandler) GetLatestVersionFromGradle(ctx context.Context, args map[string]interface{}) (*mcp.CallToolResult, error) { h.logger.Debug("Getting latest Gradle package versions") // Parse dependencies depsRaw, ok := args["dependencies"] if !ok { return nil, fmt.Errorf("missing required parameter: dependencies") } // Convert to []GradleDependency var deps []GradleDependency if depsArr, ok := depsRaw.([]interface{}); ok { for _, depRaw := range depsArr { if depMap, ok := depRaw.(map[string]interface{}); ok { var dep GradleDependency if config, ok := depMap["configuration"].(string); ok { dep.Configuration = config } else { continue } if group, ok := depMap["group"].(string); ok { dep.Group = group } else { continue } if name, ok := depMap["name"].(string); ok { dep.Name = name } else { continue } if version, ok := depMap["version"].(string); ok { dep.Version = version } deps = append(deps, dep) } } } else { return nil, fmt.Errorf("invalid dependencies format: expected array") } // Process each dependency results := make([]PackageVersion, 0, len(deps)) for _, dep := range deps { h.logger.WithFields(logrus.Fields{ "group": dep.Group, "name": dep.Name, "version": dep.Version, "configuration": dep.Configuration, }).Debug("Processing Gradle dependency") // Get latest version latestVersion, err := h.getLatestVersion(dep.Group, dep.Name) if err != nil { h.logger.WithFields(logrus.Fields{ "group": dep.Group, "name": dep.Name, "error": err.Error(), }).Error("Failed to get Maven artifact info") results = append(results, PackageVersion{ Name: fmt.Sprintf("%s:%s", dep.Group, dep.Name), CurrentVersion: StringPtr(dep.Version), LatestVersion: "unknown", Registry: "gradle", Skipped: true, SkipReason: fmt.Sprintf("Failed to fetch artifact info: %v", err), }) continue } // Add result name := fmt.Sprintf("%s:%s", dep.Group, dep.Name) if dep.Configuration != "" { name = fmt.Sprintf("%s (%s)", name, dep.Configuration) } results = append(results, PackageVersion{ Name: name, CurrentVersion: StringPtr(dep.Version), LatestVersion: latestVersion, Registry: "gradle", }) } // Sort results by name sort.Slice(results, func(i, j int) bool { return strings.ToLower(results[i].Name) < strings.ToLower(results[j].Name) }) return NewToolResultJSON(results) }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sammcj/mcp-package-version'

If you have feedback or need assistance with the MCP directory API, please join our Discord server