Developer Guide
April 28, 2026 ยท View on GitHub
Setup
Prerequisites
- Python 3.10 or later
- Git
Environment
git clone https://github.com/your-org/opensips-mcp-server.git
cd opensips-mcp-server
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
This installs the package in editable mode along with development dependencies: pytest, ruff, mypy, respx, and factory-boy.
Project Structure
opensips-mcp-server/
src/opensips_mcp/
__init__.py
__main__.py # CLI entry point (Click)
server.py # FastMCP instance, lifespan, and module registration
settings.py # Pydantic settings (env vars)
mi/
__init__.py
client.py # Async MI JSON-RPC client
commands.py # MI command helpers
exceptions.py # MI error hierarchy
db/
__init__.py
engine.py # SQLAlchemy base and engine factory
models/ # ORM models (one file per table)
crud/ # Async CRUD functions (one file per domain)
cfg/
__init__.py
builder.py # ConfigBuilder (Jinja2 rendering)
parser.py # Config parser (extracts structure)
validator.py # Config validator (opensips -C -f)
templates/
scenarios/ # 8 complete scenario templates
partials/ # 13 reusable template fragments
tools/ # MCP tool modules (one file per domain)
resources/ # MCP resource modules
prompts/ # MCP prompt modules
security/
__init__.py
rbac.py # Role-based access control
validators.py # Input validation functions
audit.py # Audit logging
version/
__init__.py
base.py # Base version strategy
v3_4.py # OpenSIPS 3.4 specifics
v3_6.py # OpenSIPS 3.6 specifics
v4_0.py # OpenSIPS 4.0 specifics
registry.py # Version strategy registry
tests/
conftest.py # Shared fixtures
test_server.py # Server-level tests
unit/ # Unit tests (no external deps)
integration/ # Integration tests (needs running OpenSIPS)
e2e/ # End-to-end tests
docker/
Dockerfile # Multi-stage production build
docker-compose.yml # Full stack (OpenSIPS + MySQL + MCP)
docker-compose.dev.yml # Development stack
scenarios/ # 7 deployment scenario Docker setups
ecosystem/ # Monitoring, testing stacks
scripts/
seed_test_data.py # Database seeder
validate_all_templates.py # Template validator
docs/ # Documentation
Adding New Tools
1. Create or edit a tool module
Tool modules live in src/opensips_mcp/tools/. Each file groups related tools by domain.
# src/opensips_mcp/tools/my_tools.py
"""My new tools."""
from __future__ import annotations
from typing import Any
from mcp.server.fastmcp import Context
from opensips_mcp.security.rbac import require_permission
from opensips_mcp.server import mcp
@mcp.tool()
@require_permission("mi.read")
async def my_new_tool(ctx: Context, param1: str, param2: int = 10) -> dict[str, Any]:
"""One-line description of what this tool does.
Parameters
----------
param1:
Description of param1.
param2:
Description of param2.
"""
app = ctx.request_context.lifespan_context
result = await app.mi_client.execute("some_command", {"key": param1})
return result
2. Register the module
Add an import in src/opensips_mcp/server.py:
from opensips_mcp.tools import my_tools as _my_tools # noqa: E402, F401
3. Apply security
- Use
@require_permission("scope")with the appropriate scope from the RBAC model. - For write operations, consider adding
@audited("operation_name"). - Validate all user-provided inputs using functions from
security/validators.py.
4. Write tests
Create tests/unit/test_my_tools.py:
import pytest
from unittest.mock import AsyncMock, MagicMock
@pytest.mark.asyncio
async def test_my_new_tool(mock_ctx):
from opensips_mcp.tools.my_tools import my_new_tool
# mock_ctx is a fixture from conftest.py
result = await my_new_tool(mock_ctx, param1="test")
assert "result" in result
Adding New Templates
Scenario Template
- Create
src/opensips_mcp/cfg/templates/scenarios/my_scenario.cfg.j2. - Register it in
src/opensips_mcp/cfg/builder.py:
SCENARIOS = {
# ... existing scenarios ...
"my_scenario": {
"description": "My new scenario",
"required_params": ["db_url"],
"optional_params": ["listen_ip", "listen_port"],
},
}
- Add default params in
scripts/validate_all_templates.pyunderDEFAULT_SCENARIO_PARAMS. - Validate:
python scripts/validate_all_templates.py
Partial Template
- Create
src/opensips_mcp/cfg/templates/partials/my_feature.cfg.j2. - Include it in scenario templates with:
{% include "partials/my_feature.cfg.j2" %}
- Add default params in the validation script and run it.
Testing Guide
Run all tests
make test
Run unit tests only
make test-unit
Unit tests must not require any external services (no OpenSIPS, no database server).
Run integration tests
make test-int
Integration tests are marked with @pytest.mark.integration and require a running OpenSIPS instance and database.
Test fixtures
The tests/conftest.py file provides shared fixtures:
mock_ctx-- A mock MCP context with a fakeAppContext.db_session-- An in-memory SQLite session for database tests.mi_client-- A mock MI client usingrespx.
Coverage
python -m pytest tests/ -v --cov=opensips_mcp --cov-report=term-missing
Code Style
Tools
- Ruff: Linting and formatting. Run
make lintandmake format. - mypy: Type checking in strict mode. Run
make type-check.
Conventions
- All function signatures must include type hints.
- All public functions, classes, and modules must have docstrings.
- Use
from __future__ import annotationsat the top of every module. - Line length: 100 characters.
- Import order: standard library, third-party, local (enforced by ruff).
- Use
async/awaitfor all I/O operations. - Use
dict[str, Any](lowercase) instead ofDict[str, Any](Python 3.10+ syntax).
Pre-commit Checklist
Before submitting a PR:
make lint # Fix any linting issues
make format # Auto-format code
make type-check # Fix type errors
make test # All tests pass