Development
Guide for setting up, contributing to, and deploying ra-mcp.
Setup
git clone https://github.com/AI-Riksarkivet/ra-mcp.git
cd ra-mcp
uv sync
Requires Python 3.13+ and uv.
Running the Server
# MCP server (stdio) — for Claude Desktop integration
uv run ra serve
# MCP server (HTTP) — for web clients, testing, and development
uv run ra serve --port 7860
# With verbose logging
uv run ra serve --port 7860 -v
# Selective modules
uv run ra serve --port 7860 --modules search,browse
Testing with MCP Inspector
npx @modelcontextprotocol/inspector uv run ra serve
Testing
# Run all tests
uv run pytest
# Run specific package tests
uv run pytest packages/common/tests/ -v
uv run pytest packages/search/tests/ -v
uv run pytest packages/browse/tests/ -v
# Run with coverage
uv run pytest --cov=ra_mcp_common --cov=ra_mcp_search --cov=ra_mcp_browse --cov-report=html
Testing Principles
- One test file per source module:
test_formatting.pytestsformatting.py - Flat module-level functions — no test classes
- Parametrize for edge cases (pydantic pattern)
- Mock at the right boundary: inject a mock
HTTPClientvia constructor for domain packages, useClient(mcp)for MCP tools - Test behavior, not instrumentation
Code Quality
# Format code
uv run ruff format .
# Lint and auto-fix
uv run ruff check --fix .
# Type check
uv run ty check
CI Checks
Run the same checks as GitHub Actions locally:
# Full pipeline
dagger call checks && dagger call test
# Or via Makefile
make check
Always run dagger call checks before committing.
Environment Variables
Debugging
| Variable | Default | Description |
|---|---|---|
RA_MCP_LOG_LEVEL |
INFO |
Logging level (DEBUG, INFO, WARNING, ERROR) |
RA_MCP_LOG_API |
(unset) | Enable API logging to ra_mcp_api.log |
RA_MCP_TIMEOUT |
60 |
Override default HTTP timeout in seconds |
HTR
| Variable | Default | Description |
|---|---|---|
HTR_SPACE_URL |
https://riksarkivet-htr-demo.hf.space |
Gradio Space URL |
HTR_TIMEOUT |
300 |
Transcription timeout in seconds |
Adding a New MCP Tool
- Create a tool file in the appropriate MCP package (e.g.,
packages/search-mcp/src/ra_mcp_search_mcp/) - Define a
register_*_tool(mcp)function using@mcp.tool() - Add parameter documentation via
Annotated[type, Field(description=...)] - Call the register function from the package's
tools.py - Add tests using
Client(mcp)for in-process testing
Adding a New Module
- Create domain package:
packages/mymodule/with models, clients, operations - Create MCP package:
packages/mymodule-mcp/with tool registration - Register in
src/ra_mcp_server/server.pyAVAILABLE_MODULES:
AVAILABLE_MODULES = {
"mymodule": {
"server": mymodule_mcp,
"description": "Description for --list-modules",
"default": True,
},
}
- Add dependencies to root
pyproject.toml
Adding a New Skill
- Create
plugins/ra-mcp-tools/skills/{name}/SKILL.md - Add YAML frontmatter with
nameanddescription - The skill is auto-discovered on server restart
Updating Dependencies
# Add to a package
cd packages/common && uv add package-name
# Add dev dependency (root)
uv add --dev package-name
# Sync all
uv sync