headroom/tests/test_mcp_registry/test_server_json.py
Rod Boev e9e9cd55b7
feat(mcp): publish canonical server.json (#1510)
## Description

Headroom can launch its MCP server, but did not publish a canonical
`server.json` that registries and MCP hosts can consume directly. This
PR adds a shared descriptor builder, commits a root `server.json`,
parity-tests that artifact against the builder and existing runtime
spec, and updates docs so registry authors do not need to reconstruct
`headroom mcp serve` from prose.

Closes #929.

## Type of Change

- [ ] Bug fix (non-breaking change that fixes an issue)
- [x] New feature (non-breaking change that adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [x] Documentation update
- [ ] Performance improvement
- [ ] Code refactoring (no functional changes)

## Changes Made

- Added a shared `server_json.py` descriptor builder for Headroom MCP
publication metadata.
- Published a canonical root `server.json` and parity-tested it against
the builder.
- Encoded the publishable uvx contract as `headroom-ai[mcp]` plus
`headroom mcp serve`.
- Updated README and MCP docs to point registry authors at the canonical
descriptor.
- Added the README ownership marker used by MCP Registry verification.
- Kept existing registrars and `headroom mcp install` behavior
unchanged.

## Testing

- [x] Unit tests pass
- [x] Linting passes
- [x] Type checking passes
- [x] New tests added for new functionality when applicable
- [x] Manual testing performed

### Test Output

```text
Focused registry/server-json tests and reviewer approval were completed on this PR before the governance body cleanup. The current body update is documentation-only metadata for PR governance.
```

## Real Behavior Proof

- Environment: Headroom development checkout with MCP test dependencies.
- Exact command / steps: Inspected the generated `server.json` contract
and parity coverage against the descriptor builder and runtime MCP spec.
- Observed result: The committed descriptor matches the builder/runtime
contract and advertises the intended `headroom-ai[mcp]` / `headroom mcp
serve` launch path.
- Not tested: live publication to third-party registries

## Review Readiness

- [x] I have performed a self-review
- [x] This PR is ready for human review

## Additional Notes

This body was normalized by a maintainer after approval so the
governance parser reflects the already-reviewed PR state.
2026-07-14 13:25:29 -04:00

86 lines
2.7 KiB
Python

"""Tests for the canonical MCP server.json descriptor."""
from __future__ import annotations
import json
from pathlib import Path
from headroom.mcp_registry import build_server_json, render_server_json
from headroom.mcp_registry.install import build_headroom_spec
from headroom.mcp_registry.server_json import (
PYPI_OWNERSHIP_MARKER,
REPOSITORY_ID,
REPOSITORY_URL,
SCHEMA_URL,
SERVER_DESCRIPTION,
SERVER_NAME,
WEBSITE_URL,
_build_mcp_package_spec,
load_project_metadata,
)
PROJECT_ROOT = Path(__file__).resolve().parents[2]
def test_build_server_json_uses_project_metadata() -> None:
metadata = load_project_metadata()
descriptor = build_server_json(metadata)
assert descriptor["$schema"] == SCHEMA_URL
assert descriptor["name"] == SERVER_NAME
assert descriptor["description"] == SERVER_DESCRIPTION
assert descriptor["version"] == metadata.version
assert descriptor["websiteUrl"] == WEBSITE_URL
assert descriptor["repository"] == {
"url": REPOSITORY_URL,
"source": "github",
"id": REPOSITORY_ID,
}
package = descriptor["packages"][0]
assert package["registryType"] == "pypi"
assert package["registryBaseUrl"] == "https://pypi.org"
assert package["identifier"] == metadata.package_name
assert package["version"] == metadata.version
assert package["runtimeArguments"] == [
{
"type": "named",
"name": "--from",
"value": _build_mcp_package_spec(metadata),
}
]
def test_build_server_json_matches_runtime_contract() -> None:
descriptor = build_server_json()
runtime = build_headroom_spec()
package = descriptor["packages"][0]
assert package["runtimeHint"] == "uvx"
assert package["runtimeArguments"] == [
{
"type": "named",
"name": "--from",
"value": _build_mcp_package_spec(load_project_metadata()),
}
]
assert [arg["value"] for arg in package["packageArguments"]] == [
runtime.name,
*runtime.args[-2:],
]
assert package["transport"] == {"type": "stdio"}
def test_root_server_json_matches_builder() -> None:
artifact = PROJECT_ROOT / "server.json"
assert artifact.read_text(encoding="utf-8") == render_server_json()
assert json.loads(artifact.read_text(encoding="utf-8")) == build_server_json()
def test_docs_point_to_canonical_server_json() -> None:
readme = (PROJECT_ROOT / "README.md").read_text(encoding="utf-8")
mcp_docs = (PROJECT_ROOT / "docs/content/docs/mcp.mdx").read_text(encoding="utf-8")
assert PYPI_OWNERSHIP_MARKER in readme
assert "`server.json`" in readme
assert "https://github.com/headroomlabs-ai/headroom/blob/main/server.json" in mcp_docs