Skip to main content
Glama
elad12390
by elad12390

get_changelog

Retrieve changelog and release notes for software packages to track updates and changes across different package registries.

Instructions

Get changelog and release notes for a package.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
packageYes
reasoningYes
registryNoauto
max_releasesNo

Implementation Reference

  • Core handler function in ChangelogFetcher class that implements the get_changelog logic: finds repo, fetches releases from GitHub, parses for breaking changes, returns structured data.
    async def get_changelog(self, package: str, registry: str, max_releases: int = 5) -> dict: """Get changelog for a package.""" # Find repository repo_url = await self._find_repository(package, registry) if not repo_url: return {"error": "Could not find repository", "package": package} # Extract owner/repo owner, repo = self._parse_repo_url(repo_url) if not owner or not repo: return {"error": "Invalid repository URL", "package": package} # Fetch releases try: releases_data = await self.github.get_releases(owner, repo, max_releases) releases = [self.parser.parse_release(r) for r in releases_data] breaking_count = sum(len(r.breaking_changes) for r in releases) return { "package": package, "registry": registry, "repository": repo_url, "releases": [ { "version": r.version, "date": r.date, "notes": r.notes, "breaking_changes": r.breaking_changes, } for r in releases ], "summary": { "total_releases": len(releases), "breaking_changes_count": breaking_count, "recommendation": "Safe to upgrade" if breaking_count == 0 else f"{breaking_count} breaking change(s) - review carefully", }, } except Exception as e: return {"error": f"Failed to fetch releases: {e}", "package": package}
  • MCP tool registration (@mcp.tool()) for get_changelog, including schema via Annotated params, calls ChangelogFetcher.get_changelog, handles JSON output, tracking, and errors.
    @mcp.tool() async def get_changelog( package: Annotated[str, "Package name (e.g., react, fastapi)"], reasoning: Annotated[str, "Why you're checking the changelog"], registry: Annotated[Literal["npm", "pypi", "auto"], "Package registry"] = "auto", max_releases: Annotated[int, "Maximum releases to fetch"] = 5, ) -> str: """Get changelog and release notes for a package.""" import json start_time = time.time() success = False error_msg = None result = "" detected_registry = registry try: # Auto-detect registry if registry == "auto": detected_registry = "npm" # Default to npm # Fetch changelog changelog = await changelog_fetcher.get_changelog(package, detected_registry, max_releases) result = json.dumps(changelog, indent=2, ensure_ascii=False) result = clamp_text(result, MAX_RESPONSE_CHARS) success = "error" not in changelog if not success: error_msg = changelog.get("error") except Exception as exc: error_msg = str(exc) result = f"Changelog fetch failed for {package}: {exc}" finally: response_time = (time.time() - start_time) * 1000 tracker.track_usage( tool_name="get_changelog", reasoning=reasoning, parameters={ "package": package, "registry": detected_registry, "max_releases": max_releases, }, response_time_ms=response_time, success=success, error_message=error_msg, response_size=len(result.encode("utf-8")), ) return result
  • Instantiation of ChangelogFetcher instance used by the get_changelog tool.
    changelog_fetcher = ChangelogFetcher(github_client, registry_client)
  • Dataclass schema for Release information parsed from changelogs.
    @dataclass class Release: """Information about a package release.""" version: str date: str | None = None notes: str | None = None breaking_changes: list[str] = field(default_factory=list)
  • ChangelogParser helper class for parsing release notes and detecting breaking changes.
    class ChangelogParser: """Parse and analyze package changelogs.""" BREAKING_KEYWORDS = [ "breaking", "removed", "deprecated", "incompatible", "migration", "⚠", "🚨", ] def parse_release(self, release_data: dict) -> Release: """Parse GitHub release data.""" body = release_data.get("body", "") release = Release( version=release_data.get("tag_name", "unknown"), date=release_data.get("published_at"), notes=body[:500] if body else None, ) # Extract breaking changes lines = body.split("\n") if body else [] for line in lines: if any(kw in line.lower() for kw in self.BREAKING_KEYWORDS): clean = re.sub(r"^[-*•]\s*", "", line).strip() if clean: release.breaking_changes.append(clean[:200]) return release

Latest Blog Posts

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/elad12390/web-research-assistant'

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