mirror of
https://github.com/headroomlabs-ai/headroom.git
synced 2026-08-27 14:17:10 -04:00
## 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.
86 lines
2.7 KiB
Python
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
|