- version
-
2.3.02.3.1
espn changelog
io.github.christianclaudio/espn
16 changes recorded. MCP Harbor re-reads this listing from the official registry every six hours and asks the live server what it exposes, and keeps what changed between one look and the next.
-
server.json 1 field changed
-
server.json 1 field changed
- version
-
2.2.02.3.0
-
AGENTS.md +3 −2
https://raw.githubusercontent.com/christianclaudio/mcp-server-espn/HEAD/AGENTS.md
− - `.github/workflows/` — `ci.yml` (lint, py3.10–3.14 tests, contract/drift/protocol/conformance, build, CodeQL), `release.yml` (on a `v*` tag, five jobs: `build` (contents: read) builds with full history, checks the wheel version matches the tag, builds the release notes, checks the packages and the SBOM; `publish` (id-token and contents: write) uploads to PyPI and creates the GitHub Release from `scripts/release_notes.py` with the wheel, sdist and SBOM; `docker` (packages: write) pushes the GHC− CI is defined in `.github/workflows/ci.yml` (jobs: lint and types, tests on Python 3.10–3.14 at 100% coverage, tool contract + OpenAPI drift + protocol + conformance, build + `scripts/check_version.py` + `twine check`, `docker-build` (checks that the builder stage fails at its `ca-certificates` floor check, before any pip step, when the floor is above the installed version), CodeQL). Jobs that install or build the package, and `drift-monitor.yml`, check out with `fetch-depth: 0`, because a shall+ - `.github/workflows/` — `ci.yml` (lint, py3.11–3.14 tests, contract/drift/protocol/conformance, build, `docker-build`, `drift-check` (scheduled and manual runs only)), `release.yml` (on a `v*` tag, five jobs: `build` (contents: read) builds with full history, checks the wheel version matches the tag, builds the release notes, checks the packages and the SBOM; `publish` (id-token and contents: write) uploads to PyPI and creates the GitHub Release from `scripts/release_notes.py` with the wheel, s+ - Runtime dependencies install from `uv.lock`, so the image runs the versions CI tests: the builder installs uv from `docker/uv-bootstrap.txt` (hash-pinned, `--require-hashes`, into `/tmp/uv` outside the venv, so the runtime image has no uv), runs `uv export --locked --no-dev --no-emit-project --format requirements.txt` (base dependencies only, a hash for every package, and the build fails if `uv.lock` is stale), installs that file with pip in hash-checking mode, then installs the project bui+ CI is defined in `.github/workflows/ci.yml` (jobs: lint and types, tests on Python 3.11–3.14 at 100% coverage, tool contract + OpenAPI drift + protocol + conformance, build + `scripts/check_version.py` + `twine check`, `docker-build` (builds the full image without pushing it and checks that the runtime image has the project and none of the build-only packages (runtime dependencies such as `packaging` stay), checks that the image answers `initialize` and `tools/list` over stdio with no network, t
-
server.json 1 field changed
- version
-
2.1.12.2.0
-
AGENTS.md +6 −2
https://raw.githubusercontent.com/christianclaudio/mcp-server-espn/HEAD/AGENTS.md
− - `.github/workflows/` — `ci.yml` (lint, py3.10–3.13 tests, contract/drift/protocol/conformance, build, CodeQL), `release.yml` (on a `v*` tag, five jobs: `build` (contents: read) builds with full history, checks the wheel version matches the tag, builds the release notes, checks the packages and the SBOM; `publish` (id-token and contents: write) uploads to PyPI and creates the GitHub Release from `scripts/release_notes.py` with the wheel, sdist and SBOM; `docker` (packages: write) pushes the GHC− CI is defined in `.github/workflows/ci.yml` (jobs: lint and types, tests on Python 3.10–3.13 at 100% coverage, tool contract + OpenAPI drift + protocol + conformance, build + `scripts/check_version.py` + `twine check`, CodeQL). Jobs that install or build the package, and `drift-monitor.yml`, check out with `fetch-depth: 0`, because a shallow checkout has no reachable tag and reports `0.0.1.devN`. The Docker image is built only in `release.yml`, with `UV_DYNAMIC_VERSIONING_BYPASS` set to the tag + - `.github/workflows/` — `ci.yml` (lint, py3.10–3.14 tests, contract/drift/protocol/conformance, build, CodeQL), `release.yml` (on a `v*` tag, five jobs: `build` (contents: read) builds with full history, checks the wheel version matches the tag, builds the release notes, checks the packages and the SBOM; `publish` (id-token and contents: write) uploads to PyPI and creates the GitHub Release from `scripts/release_notes.py` with the wheel, sdist and SBOM; `docker` (packages: write) pushes the GHC+ - Trust stores follow FastMCP's [certificate authority incident notice (October 2026)](https://github.com/PrefectHQ/fastmcp/blob/main/SECURITY.md#certificate-authority-incident-october-2026): both stages upgrade the OS `ca-certificates` package and fail the build below the patched Debian version ([DSA-6572-1](https://security-tracker.debian.org/tracker/DSA-6572-1); `ARG CA_CERTIFICATES_FLOOR`, declared once), the builder does so before any pip runs because pip trusts the OS store as well as i+ - The pip bootstrap is hash-pinned in `docker/pip-bootstrap.txt` and installed with `--require-hashes`, so it does not depend on the TLS trust of the base image's older pip and certifi; whoever raises the pip floor updates that pin and its sha256 from PyPI (`https://pypi.org/pypi/pip/<version>/json`, the `py3-none-any` wheel's `digests.sha256`), because Dependabot does not track the file.+ - Lowering `CA_CERTIFICATES_FLOOR` with `--build-arg` is unsupported; the build-arg exists only so CI can raise it for the negative floor check, and CI and the release workflow never pass it otherwise.+ uv 0.13.4 or later is required (`[tool.uv] required-version` in `pyproject.toml`, from FastMCP's certificate authority incident notice); older uv refuses to run, and CI's `setup-uv` installs from that setting.+ CI is defined in `.github/workflows/ci.yml` (jobs: lint and types, tests on Python 3.10–3.14 at 100% coverage, tool contract + OpenAPI drift + protocol + conformance, build + `scripts/check_version.py` + `twine check`, `docker-build` (checks that the builder stage fails at its `ca-certificates` floor check, before any pip step, when the floor is above the installed version), CodeQL). Jobs that install or build the package, and `drift-monitor.yml`, check out with `fetch-depth: 0`, because a shall
-
server.json 1 field changed
- version
-
2.1.02.1.1
-
server.json 1 field changed
- version
-
2.0.02.1.0
-
server.json 2 fields changed
- env_vars
-
ESPN_BASE_URL, ESPN_TIMEOUT_SECONDS, ESPN_MAX_RETRIES, ESPN_MCP_READONLY, ESPN_MCP_PROFILE, ESPN_MCP_ENABLE_TOOL_SEARCHESPN_BASE_URL, ESPN_TIMEOUT_SECONDS, ESPN_MAX_RETRIES, ESPN_MCP_READONLY, ESPN_MCP_PROFILE, ESPN_MCP_ENABLE_TOOL_SEARCH, ESPN_MCP_TOOL_SEARCH_BACKEND - version
-
1.3.52.0.0
-
server.json 1 field changed
- version
-
1.3.41.3.5
-
AGENTS.md +4 −4
https://raw.githubusercontent.com/christianclaudio/mcp-server-espn/HEAD/AGENTS.md
− - `src/espn_mcp/client.py` — async `ESPNClient` (pooling, retries, path encoding, league aliases). `errors.py` — typed errors and redaction. `middleware.py` — parent and child middleware. `config.py` — Pydantic settings (cache TTLs, profile, ports).− - `.github/workflows/` — `ci.yml` (lint, py3.10–3.13 tests, contract/drift/protocol/conformance, build, CodeQL), `release.yml` (on a `v*` tag: build with full history, check the wheel version matches the tag, build the release notes, then SBOM, build provenance, PyPI, the GitHub Release from `scripts/release_notes.py` with the wheel, sdist and SBOM, the GHCR Docker image, and MCP Registry publish last (the tag version is stamped into `server.json`); only the provenance step is `continue-on-error− - All errors and logs pass through regex redaction (`_redact_secrets`).− CI is defined in `.github/workflows/ci.yml` (jobs: lint and types, tests on Python 3.10–3.13 at 100% coverage, tool contract + OpenAPI drift + protocol + conformance, build + `scripts/check_version.py` + `twine check`, CodeQL). Jobs that install or build the package, and `drift-monitor.yml`, check out with `fetch-depth: 0`, because a shallow checkout has no reachable tag and reports `0.0.1.devN`. The Docker image is built only in `release.yml`, with `UV_DYNAMIC_VERSIONING_BYPASS` set to the tag + - `src/espn_mcp/client.py` — async `ESPNClient` (pooling, retries, path encoding, league aliases). `auth.py` — `ESPN_MCP_AUTH_TOKEN` bearer verifier and the tokenless non-localhost HTTP bind refusal. `errors.py` — typed errors and redaction. `middleware.py` — parent and child middleware. `config.py` — Pydantic settings (cache TTLs, profile, ports).+ - `.github/workflows/` — `ci.yml` (lint, py3.10–3.13 tests, contract/drift/protocol/conformance, build, CodeQL), `release.yml` (on a `v*` tag, five jobs: `build` (contents: read) builds with full history, checks the wheel version matches the tag, builds the release notes, checks the packages and the SBOM; `publish` (id-token and contents: write) uploads to PyPI and creates the GitHub Release from `scripts/release_notes.py` with the wheel, sdist and SBOM; `docker` (packages: write) pushes the GHC+ - All errors and logs pass through regex redaction (`_redact_secrets`). PEM blocks run from `-----BEGIN <label>-----` to the `-----END <label>-----` with the same label (any case; an END with another label does not end it), and a `-----BEGIN` with no matching END is masked to the end of the text. A `{...}`/`[...]`/`(...)` value after a credential key or a token key, quoted or not (a Python `repr` such as `{'api_key': ['x']}` or `{'api_key': ('a', 'x')}`), is masked to its balanced bracket, wi+ CI is defined in `.github/workflows/ci.yml` (jobs: lint and types, tests on Python 3.10–3.13 at 100% coverage, tool contract + OpenAPI drift + protocol + conformance, build + `scripts/check_version.py` + `twine check`, CodeQL). Jobs that install or build the package, and `drift-monitor.yml`, check out with `fetch-depth: 0`, because a shallow checkout has no reachable tag and reports `0.0.1.devN`. The Docker image is built only in `release.yml`, with `UV_DYNAMIC_VERSIONING_BYPASS` set to the tag
-
server.json 1 field changed
- version
-
1.3.31.3.4
-
server.json 1 field changed
- version
-
1.3.21.3.3
-
server.json 1 field changed
- version
-
1.3.11.3.2
-
server.json 1 field changed
- version
-
1.3.01.3.1
-
AGENTS.md +36 −46
https://raw.githubusercontent.com/christianclaudio/mcp-server-espn/HEAD/AGENTS.md
− This is `mcp-server-espn` — an enterprise Model Context Protocol (MCP) server exposing 33 tools providing real-time scores, play-by-play data, rosters, player statistics, betting odds, and prediction market resolution data from ESPN's public APIs. Built on FastMCP 4 Server Composition, it supports stdio and modern Streamable HTTP transports.− ## 🏗️ Repository Layout & Architecture− ```text− mcp-server-espn/− ├── src/espn_mcp/− │ ├── __init__.py # Package entrypoint and version metadata− │ ├── client.py # Async HTTP client with connection pooling, retries, path encoding− │ ├── config.py # Pydantic v2 Settings (SEP-2549 cache TTLs, profile, ports)− │ ├── errors.py # Typed ESPN error hierarchy and regex credential redaction− │ ├── middleware.py # Hierarchical parent & child middleware− │ ├── server.py # Root FastMCP server, composition mounting, resources, prompts− │ └── tools/ # Modular domain sub-servers− │ ├── __init__.py # Re-exports domain sub-servers and tool functions− │ ├── games.py # espn-games sub-server (scores, summaries, schedules, standings, rankings, odds, plays, situation, predictor, calendar, futures, FPI)− │ ├── teams.py # espn-teams sub-server (rosters, depth charts, player stats, athlete info, bio, stats, gamelog, splits, search, team details)− │ └── news.py # espn-news sub-server (league news, reference resources)− ├── scripts/− │ ├── check_tool_contract.py # Contract verification asserting 33 tools and annotations− │ ├── check_openapi_drift.py # AST visitor validating client methods against OpenAPI spec− │ ├── check_conformance.sh # Official @modelcontextprotocol/conformance runner− │ └── determine_bump.py # Conventional commit SemVer bump calculation script− ├── tests/− │ ├── conftest.py # Mock HTTP transport fixtures− │ ├── test_client.py # Client route and CDN error handling tests− │ ├── test_server.py # Tool registration, arguments, and execution tests− │ ├── test_layered.py # FastMCP 4 composition, profiles, middleware, domain guard tests− │ ├── test_errors.py # Structured exception and redaction tests− │ ├── test_drift.py # AST drift verification tests− │ ├── test_protocol.py # FastMCP Client in-memory, stdio & stateless HTTP verification− │ ├── test_determine_bump.py # SemVer calculation tests− │ └── test_e2e_live.py # On-demand live trial verification (-m e2e)− ├── .github/workflows/− │ ├── ci.yml # CI matrix: lint, py3.10-3.13 tests, conformance, CodeQL, docker− │ └── release.yml # Automated release on v* tags: wheels, sdist, CycloneDX SBOM, GHCR− ├── Dockerfile # Multi-stage container running as non-root USER mcp− ├── conformance-baseline.yml # Expected failures baseline for protocol conformance suite− ├── fastmcp.json # FastMCP 4 server configuration manifest− ├── server.json # MCP Registry catalog metadata (runtimeHint: uvx, stdio transport)− ├── pyproject.toml # Packaging metadata, entrypoint CLI (espn-mcp), fastmcp>=4.0.10− └── README.md # User documentation and setup guide+ This is `mcp-server-espn` — an enterprise Model Context Protocol (MCP) server providing real-time scores, play-by-play data, rosters, player statistics, betting odds, and prediction market resolution data from ESPN's public APIs. Built on FastMCP 4 Server Composition, it supports stdio and modern Streamable HTTP transports. The expected tool set lives in `scripts/check_tool_contract.py`.+ ## 🏗️ Key Paths+ - `src/espn_mcp/server.py` — root FastMCP server: mounts the `games`, `teams`, and `news` sub-servers with matching namespaces; resources, prompts.+ - `src/espn_mcp/tools/{games,teams,news}.py` — domain sub-servers holding every tool; re-exported from `tools/__init__.py`.+ - `src/espn_mcp/client.py` — async `ESPNClient` (pooling, retries, path encoding, league aliases). `errors.py` — typed errors and redaction. `middleware.py` — parent and child middleware. `config.py` — Pydantic settings (cache TTLs, profile, ports).+ - `scripts/check_tool_contract.py` — source of truth for the expected tool set and annotations. Do not hard-code tool counts elsewhere.+ - `scripts/check_openapi_drift.py`, `scripts/check_conformance.sh` + `conformance-baseline.yml`.+ - `scripts/release_notes.py` — release body from squash commits since the previous `v*` tag. `scripts/check_version.py` — runs after `uv build` and reads the version from the single wheel in `dist/` (the file that ships, as release.yml's tag check does); fails on `0.0.0` (no git metadata) or `0.0.1.devN` (no reachable tag, a shallow checkout).+ - `tests/` — offline unit, layered-composition, and protocol tests; `test_e2e_live.py` is opt-in (`uv run pytest -m e2e --no-cov`).+ - `.github/workflows/` — `ci.yml` (lint, py3.10–3.13 tests, contract/drift/protocol/conformance, build, CodeQL), `release.yml` (on a `v*` tag: build with full history, check the wheel version matches the tag, build the release notes, then SBOM, build provenance, PyPI, the GitHub Release from `scripts/release_notes.py` with the wheel, sdist and SBOM, the GHCR Docker image, and MCP Registry publish last (the tag version is stamped into `server.json`); only the provenance step is `continue-on-error+ - `server.json` (MCP Registry metadata), `Dockerfile`, `fastmcp.json`, `pyproject.toml` (console scripts `mcp-server-espn`, which must equal the `server.json` identifier, and `espn-mcp`, which the README configs and Dockerfile run).+ 2. **Tool Handler (`src/espn_mcp/tools/{games,teams,news}.py`)**:+ - Register on the domain sub-server with `@<domain>_server.tool(...)` and `@espn_tool`. `server.py` mounts each sub-server with its namespace.+ 5. **Git Safety & Releases**:+ - **The git tag is the version.** `uv-dynamic-versioning` reads the `vX.Y.Z` tag at build time; `pyproject.toml` declares `dynamic = ["version"]`, `__version__` comes from `importlib.metadata`, and `server.json` commits `0.0.0` (the release workflow stamps the tag version into it). PRs never edit a version: no bump in `pyproject.toml`, `src/espn_mcp/__init__.py`, `server.json`, `uv.lock`, or `CHANGELOG.md`. Untagged builds report `X.Y.(Z+1).devN+<sha>`; a build with no git metadata reports th+ - **Breaking changes:** every `feat!` / `fix!` PR (any `type!:` title) carries a `BREAKING CHANGE:` footer as the final paragraph of the PR body, and the footer text must include the migration steps. `BREAKING CHANGE:` (or its synonym `BREAKING-CHANGE:`) is the only footer token; do not add a separate migration token. `scripts/release_notes.py` stops at the CodeRabbit marker line (outside a code fence) `<!-- This is an auto-generated comment: release notes by coderabbit.ai -->` and ignores ev+ - **Squash merges use the PR body as the commit message** (repo settings: PR title as squash title, PR body as squash message). Keep the PR body accurate up to the merge, because `scripts/release_notes.py` reads it from the squash commit.+ - **`CHANGELOG.md` is frozen** as of 1.2.9. GitHub Releases are the changelog: `scripts/release_notes.py` builds each release body from the squash commits since the previous tag (every `BREAKING CHANGE:` footer verbatim, then the commit subjects). Do not add CHANGELOG entries.+ - `skills/espn-mcp/SKILL.md` carries no version: the [Agent Skills specification](https://agentskills.io/specification) has no top-level `version` field. Do not add one. Update the skill only when its operator guidance changes.+ - **README is outside the release version ceremony.** Do not add or chase `README.md` `==X.Y.Z` install pins. Update `README.md` only when project behavior, install method, config, or commands actually change. Prefer unpinned install examples (`uvx --from mcp-server-espn espn-mcp`) or point readers to GitHub Releases.+ uv sync --locked --extra dev+ # Build version guard (reads the single wheel in dist/; rejects 0.0.0 and the untagged 0.0.1.devN)+ rm -rf dist && uv build && uv run python scripts/check_version.py+ ---+ ## 🔄 CI & Releases+ CI is defined in `.github/workflows/ci.yml` (jobs: lint and types, tests on Python 3.10–3.13 at 100% coverage, tool contract + OpenAPI drift + protocol + conformance, build + `scripts/check_version.py` + `twine check`, CodeQL). Jobs that install or build the package, and `drift-monitor.yml`, check out with `fetch-depth: 0`, because a shallow checkout has no reachable tag and reports `0.0.1.devN`. The Docker image is built only in `release.yml`, with `UV_DYNAMIC_VERSIONING_BYPASS` set to the tag + Do not create tags or releases unless the maintainer asks. There is no release PR: merged commits accumulate on `main`, and releases go out on any weekday on the maintainer's go; no fixed release day. Before the tag:+ - The release owner previews the release body on an up-to-date `main` with full history and tags (`git fetch --tags && python3 scripts/release_notes.py`) and posts it with the release Ask.+ - The reviewer checks the proposed version against the commit types since the last tag (`!` / `BREAKING CHANGE:` → major, `feat` → minor, otherwise patch), that every breaking commit carries its footer with migration steps, and that the version is unused in all three places it could already exist:+ ```bash+ git ls-remote --tags origin vX.Y.Z # prints nothing+ curl -s -o /dev/null -w '%{http_code}\n' https://pypi.org/pypi/mcp-server-espn/X.Y.Z/json # prints 404+ curl -s -o /dev/null -w '%{http_code}\n' https://registry.modelcontextprotocol.io/v0.1/servers/io.github.christianclaudio%2Fespn/versions/X.Y.Z # prints 404+ ```+ In a throwaway clone, the reviewer tags the release commit locally, runs `rm -rf dist && uv build`, and confirms the wheel is `mcp_server_espn-X.Y.Z-py3-none-any.whl` and `scripts/check_version.py` passes; then discards the clone without pushing.+ - Only the maintainer's go creates the tag. PyPI never accepts the same version twice: if a release fails after the PyPI upload, do not re-run it; merge a fix and tag the next patch.
Showing the first 40 of each.
-
server.json 1 field changed
- version
-
1.2.91.3.0