Development¶
uv sync --all-extras
uv run ruff check .
uv run pytest
uv run python -m mypy src tests
uv run mkdocs build --strict
uv build
MCP SDK Compatibility¶
The bridge supports the official MCP Python SDK >=2.0,<3. Production code uses
only the SDK's public API, and every direct mcp import is confined to
src/listmonk_mcp/mcp_adapter.py. Keep bridge policy and tool implementations
independent of SDK model names so a future major-version migration remains
localized to that adapter.
CI checks both MCP 2.0.0 and the newest available v2 release. The protocol suite exercises negotiated modern mode and explicit legacy mode, cancellation, server lifespan cleanup, and the installed wheel with Python warnings treated as errors. When changing the SDK boundary, update the lockfile and keep all of these checks passing before release.
Automated Dependency Maintenance¶
The existing Published Package Canary runs daily at 05:17 UTC. Alongside its
published-package smoke tests, it audits every version in uv.lock, including
development, documentation, and platform-specific dependencies. CI runs the same
audit on pull requests and master. To run it locally:
python scripts/audit_dependencies.py --report /tmp/listmonk-dependency-audit.json
When an audit finds vulnerable packages, the canary attempts targeted lockfile
upgrades and audits the result again. A failed published-package smoke test or
failed Dependabot Python CI run also triggers a refresh of direct runtime
dependencies. Repairs use trusted master code and stay within the dependency
bounds in pyproject.toml. They create or update one
automation/python-security PR. Missing audit data, unresolved vulnerabilities,
and incompatible updates fail visibly and require review.
The maintenance job uses the existing GH_TOKEN_FOR_UPDATES secret to create
PRs that trigger CI. It must have repository contents and pull request write
access. The ordinary GITHUB_TOKEN cannot trigger those PR workflows.
Auto-merge Dependency Updates waits for all PR checks, including the dependency audit, MCP matrix, container, docs, and CodeQL. It rejects drafts, forks, and stale workflow results, and merges only the exact checked commit. Code changes, wider dependency bounds, and GitHub service errors still need manual attention.
The documentation header reads the version from pyproject.toml during every
MkDocs build. Package runtime version reporting uses installed distribution
metadata, so neither requires a separate release edit.
MCP Inspector Validation¶
Use MCP Inspector before release or when changing tool registration:
- Start the server with defaults:
LISTMONK_MCP_MODE=agenticandLISTMONK_MCP_READ_ONLY=true. - Open MCP Inspector against the stdio command used by your client.
- Verify that only agentic tools are visible.
- Verify safe resources are visible, including
listmonk://health,listmonk://capabilities,listmonk://lists,listmonk://campaigns/summaryandlistmonk://templates/summary. - Verify prompts are visible:
inspect_listmonk_audience,create_campaign_safely,send_campaign_safely,import_subscribers_safely,review_campaign_performanceanddebug_listmonk_connection. - Call
check_listmonk_health,listmonk_diagnosticsandlistmonk_capability_report. - Attempt dry-run safe create/update/import/send workflows.
- Attempt a real write while read-only is enabled and verify it is blocked before an upstream HTTP request.
- Restart with
LISTMONK_MCP_MODE=fulland verify the low-level Listmonk API wrappers are visible.
Versioning And Deprecation¶
The project follows semantic versioning. Tool names and input schemas are public
API. Breaking tool schema changes require a major version bump. Deprecated tools
remain available for at least one minor release and should return
deprecated=true with a clear deprecationMessage where practical.
Release notes are maintained in CHANGELOG.md. Documentation is versioned in
docs/ and published to GitHub Pages through the docs workflow.
Listmonk API Compatibility¶
Run the local, network-free contract gate before publishing changes:
python scripts/listmonk_api_compat.py validate
The scheduled Listmonk API Watch workflow polls stable upstream releases. It
derives a contract from Listmonk's Go router and OpenAPI document, opens a draft
PR for changed metadata, and fails closed when routes are new, removed, or no
longer match the bridge. Update compatibility/listmonk-api-policy.json only
after implementing a route or documenting why it remains omitted.
Changes to routes, schemas, permissions, or relevant upstream handler source also change the contract fingerprint. After reviewing and resolving the generated diff, acknowledge that exact contract before rerunning validation:
python scripts/listmonk_api_compat.py acknowledge --write
Repository variable LISTMONK_API_ASSIGN_COPILOT=true optionally assigns a
review-required tracking issue to Copilot. The agent targets the automation
branch; the main compatibility PR still requires normal CI and review.
Transport Strategy¶
The supported production transport is stdio. Docker usage should still expose the MCP server through stdio. Do not expose a public HTTP transport unless TLS, authentication, rate limits and request size limits are implemented.
Docker Build¶
docker build -t listmonk-mcp-bridge:local .
Staging Smoke Tests¶
Staging smoke tests are opt-in and should only run against a disposable or staging Listmonk instance. They exercise settings update, import and email send paths.
Documentation¶
Documentation is versioned in docs/ and published to GitHub Pages through the docs workflow.
Acknowledgements¶
Earlier project history referenced rhnvrm/listmonk-mcp. The current implementation was rewritten around the public Listmonk API surface and this project's own safety and operational requirements.