Skip to content

Development

Rod Christiansen edited this page Oct 8, 2026 · 2 revisions

Development

The repo is small: five source files, one test file, two workflows. It uses uv for dependency management, ruff for lint, and pytest for tests. Python 3.10 or newer.

Clone and sync

git clone https://github.com/reportmate/reportmate-mcp
cd reportmate-mcp
uv sync --group dev

Lint and test

The same two commands CI runs:

uv run ruff check .
uv run pytest -q

The tests never touch the network. They monkeypatch the environment to exercise Config.from_env(), assert the exact set of eight registered tool names and the ten entries in MODULES, substitute a fake client to check that module_report normalizes its argument into the right path, and check that __version__ is a zero-padded calendar stamp. pytest.ini sets asyncio_mode = auto, so async test functions need no decorator.

Run it locally

With the two environment variables set, the console script starts a stdio server:

uv run reportmate-mcp

It will sit waiting for MCP protocol frames on stdin, which is correct — it is meant to be launched by a client. To drive it by hand, use the MCP Inspector or point a client at it as described in Client Setup.

Layout

Path Contents
src/reportmate_mcp/__init__.py __version__, the calendar version literal
src/reportmate_mcp/__main__.py main(), the reportmate-mcp console script
src/reportmate_mcp/config.py Config dataclass, env resolution, auth header
src/reportmate_mcp/client.py ReportMateClient, an httpx AsyncClient wrapper
src/reportmate_mcp/server.py The FastMCP instance, MODULES, all eight tools
tests/test_mcp.py Config, tool-registration, module-list, path-shaping and version tests

Adding a tool

Tools are plain async functions decorated with @mcp.tool in server.py. The docstring becomes the tool description the agent sees, so write it as instructions to an agent, not as an implementation note. Type annotations become the parameter schema. Add the new name to the assertion in test_expected_tools_registered or CI fails.

Keep new tools read-only. The set is intent-shaped rather than one-tool-per-endpoint so the agent's toolset stays legible; if a question can be answered by an existing tool, do not add another.

CI and releases

.github/workflows/ci.yml runs sync, ruff, and pytest on pushes and pull requests to main, with in-progress runs cancelled per ref.

.github/workflows/build.yml builds the linux/amd64 image from the Dockerfile and pushes it to ghcr.io/reportmate/reportmate-mcp. It runs on pushes to main, on v* tags, and on pull requests — but a pull-request run builds without pushing and does not log in to the registry. Tags applied are the branch name, the tag name, the long commit SHA, and latest on the default branch.

Contributions go through pull requests against main.

License

AGPL-3.0-or-later. A commercial license is available for organizations that cannot meet the AGPL's terms; see COMMERCIAL-LICENSE.md.

Clone this wiki locally