Skip to content

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.py tests formatting.py
  • Flat module-level functions — no test classes
  • Parametrize for edge cases (pydantic pattern)
  • Mock at the right boundary: inject a mock HTTPClient via constructor for domain packages, use Client(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

  1. Create a tool file in the appropriate MCP package (e.g., packages/search-mcp/src/ra_mcp_search_mcp/)
  2. Define a register_*_tool(mcp) function using @mcp.tool()
  3. Add parameter documentation via Annotated[type, Field(description=...)]
  4. Call the register function from the package's tools.py
  5. Add tests using Client(mcp) for in-process testing

Adding a New Module

  1. Create domain package: packages/mymodule/ with models, clients, operations
  2. Create MCP package: packages/mymodule-mcp/ with tool registration
  3. Register in src/ra_mcp_server/server.py AVAILABLE_MODULES:
AVAILABLE_MODULES = {
    "mymodule": {
        "server": mymodule_mcp,
        "description": "Description for --list-modules",
        "default": True,
    },
}
  1. Add dependencies to root pyproject.toml

Adding a New Skill

  1. Create plugins/ra-mcp-tools/skills/{name}/SKILL.md
  2. Add YAML frontmatter with name and description
  3. 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