Contributing
Thank you for your interest in contributing to the MikroTik MCP server. This MCP (Model Context Protocol) server provides tools for managing MikroTik RouterOS devices. Contributors can extend functionality by adding new scopes (feature areas) and their corresponding tools.
Project structure
The codebase splits into a src/mcp_mikrotik/ package (the server and its
feature scopes) and a tests/ tree (unit + integration suites):
src/mcp_mikrotik/ ├── scope/ # Feature modules — each file registers MCP tools via decorators ├── app.py # MCPServer instance and ToolAnnotation constants ├── config.py # Configuration (pydantic-settings, CLI args, env vars) ├── connector.py # SSH connection handling ├── server.py # Entry point — imports scopes, starts the server └── mikrotik_ssh_client.py # Low-level SSH client tests/ ├── integration/ # Integration tests using testcontainers └── unit/ # Unit tests
Contributing new features
To add a new MikroTik feature/scope to the project, follow these five steps.
1. Create the scope implementation
Navigate to src/mcp_mikrotik/scope/ and create a new Python file for your
feature (e.g. my_feature.py). Your scope file should:
- Import
mcp, the appropriateToolAnnotationsconstant, andannotatefrom..app - Import
execute_mikrotik_commandfrom..connector - Register tools using
@mcp.tool()decorators — always useannotate(BASE, "Title")(never a bare constant) - Follow the existing naming convention:
mikrotik_<action>_<resource> - Use type hints for all parameters (including
Literalfor fixed-value params) - Keep docstrings concise — a single sentence is ideal; avoid re-documenting every parameter
- Handle errors gracefully and return meaningful messages
annotate(BASE, "Title") — passing a bare
annotation constant skips the human-readable title and is considered incorrect.
from typing import Optional from mcp.server.mcpserver import Context from ..connector import execute_mikrotik_command from ..app import mcp, READ, WRITE, annotate @mcp.tool(name="create_my_resource", annotations=annotate(WRITE, "Create My Resource")) async def mikrotik_create_my_resource( ctx: Context, name: str, required_param: str, optional_param: Optional[str] = None, comment: Optional[str] = None ) -> str: """Creates a new resource on the MikroTik device.""" await ctx.info(f"Creating resource: name={name}") cmd = f"/my/feature add name={name} param={required_param}" if optional_param: cmd += f" optional-param={optional_param}" if comment: cmd += f' comment="{comment}"' result = await execute_mikrotik_command(cmd, ctx) if "failure:" in result.lower() or "error" in result.lower(): return f"Failed to create resource: {result}" return f"Resource created successfully:\n\n{result}"
2. Choose the right tool annotation
Import the appropriate annotation constant from app.py and pass it via
@mcp.tool(annotations=...):
| Constant | Use for |
|---|---|
READ | Read-only queries (print, list, get, export) |
WRITE | Non-idempotent writes (add, create) |
WRITE_IDEMPOTENT | Idempotent writes (set, update, enable, disable) |
DESTRUCTIVE | Idempotent destructive operations (remove, flush) |
DANGEROUS | Non-idempotent destructive operations (reset, bulk create) |
3. Register your scope
Update src/mcp_mikrotik/app.py to import your new scope module:
from mcp_mikrotik.scope import ( # noqa: F401 backup, dhcp, dns, firewall_filter, firewall_nat, ip_address, ip_pool, logs, my_feature, routes, users, vlan, wireless, )
The import triggers the @mcp.tool() decorators, which automatically register
your tools with the MCP server. No manual registry is needed.
4. Write tests
Create tests in tests/ for unit tests or tests/integration/ for
integration tests. Integration tests should:
- Use testcontainers to spin up a real MikroTik RouterOS container
- Follow the existing test structure and naming conventions
- Test complete workflows (create, read, update, delete operations)
- Include proper cleanup to ensure tests are isolated
- Use the
@pytest.mark.integrationdecorator
"""Integration tests for MikroTik my feature using testcontainers.""" import pytest from mcp_mikrotik.scope.my_feature import ( mikrotik_create_my_resource, mikrotik_list_my_resources ) @pytest.mark.integration class TestMikroTikMyFeatureIntegration: def test_01_create_resource(self, mikrotik_container): result = mikrotik_create_my_resource( name="test_resource", required_param="test_value" ) assert "failed" not in result.lower() assert "test_resource" in result def test_02_list_resources(self, mikrotik_container): result = mikrotik_list_my_resources() assert "test_resource" in result
5. Test your implementation
Before submitting, ensure your implementation works:
- Run integration tests:
$ pytest tests/integration/test_my_feature_integration.py -v
- Use MCP Inspector: test your tools interactively using the MCP Inspector.
# Install MCP Inspector $ npm install -g @modelcontextprotocol/inspector # Test your MCP server (stdio transport) $ mcp-inspector python -m mcp_mikrotik.server
- Manual testing: test with a real MikroTik device to ensure commands work correctly.
Transport modes
The server supports three transport modes:
- stdio (default) — standard input/output, used by most MCP clients
- sse — Server-Sent Events over HTTP (exposes
/healthendpoint) - streamable-http — HTTP with streaming support (exposes
/healthendpoint)
Configure via CLI (--mcp.transport) or environment variable
(MIKROTIK_MCP__TRANSPORT).
Development guidelines
Code style
- Follow existing code patterns and naming conventions
- Use type hints for all function parameters and return values
- Use
Literaltypes for parameters with a fixed set of valid values - Use
Annotated[..., Field(...)]for numeric constraints (e.g. VLAN IDs) - Handle errors gracefully with meaningful error messages
- Log important operations using
ctx.info()/ctx.error()for client-visible logging
MikroTik command guidelines
- Always validate command syntax against MikroTik documentation
- Use proper escaping for string parameters (wrap in quotes when needed)
- Implement both creation and listing/querying functionality
- Consider implementing filtering options where appropriate
- Test commands on actual RouterOS before implementation
Testing requirements
- Write tests that cover the main functionality
- Ensure tests are isolated and clean up after themselves
- Use descriptive test names that explain what is being tested
- Include edge cases and error conditions in your tests
Commit message format
This project follows the Conventional Commits specification.
Format
<type>[optional scope]: <description> [optional body] [optional footer(s)]
Types
feat: A new featurefix: A bug fixdocs: Documentation only changesstyle: Changes that do not affect the meaning of the coderefactor: A code change that neither fixes a bug nor adds a featuretest: Adding missing tests or correcting existing testschore: Changes to the build process or auxiliary tools
Examples
feat(dhcp): add DHCP server creation and management tools Add comprehensive DHCP server management including: - Create DHCP servers with configurable options - List and filter DHCP servers - Create DHCP networks and pools - Remove DHCP servers Includes integration tests with RouterOS container
fix(firewall): handle special characters in rule comments Escape special characters when creating firewall rules with comments to prevent command parsing errors on RouterOS devices
test(users): expand integration test coverage Add tests for user group management and permission validation
Submitting a pull request
- Fork the repository and create your feature branch from
master - Implement your changes following the guidelines above
- Run all tests to ensure nothing is broken
- Test with MCP Inspector to verify tools work correctly
- Write descriptive commit messages following conventional commits
- Submit a pull request with:
- Clear description of what you've added
- Reference to any related issues
- Screenshots or examples if applicable
- Confirmation that tests pass
Getting help
- Check existing scope implementations for reference
- Review the MikroTik RouterOS documentation for command syntax
- Look at existing tests for testing patterns
- Open an issue if you need clarification on implementation details
Code review process
All contributions go through code review to ensure:
- Code follows project conventions and patterns
- MikroTik commands are correct and safe
- Tests provide adequate coverage
- Documentation is clear and complete
- Integration with existing codebase is smooth
Thank you for contributing to MikroTik MCP. Your additions help make RouterOS management more accessible through the Model Context Protocol.