Repository navigation
feat(mcp): add Docker deployment and harden MCP tools - #111
Merged
Merged
Conversation
Add a stdio and Streamable HTTP MCP server for CrowdSec with bouncer, watcher and mTLS authentication, read-only-by-default tools, server-side filtering and Markdown output. Tools cover status, decisions (list/ban/unban), alerts (list/get/delete) and allowlists (list/get/check). HTTP always requires a bearer token. Includes unit, HTTP contract, stdio end-to-end and opt-in Docker integration tests. Alert deletion is documented as local-only because of the CrowdSec LAPI restriction.
- add Dockerfile, compose sidecar and GHCR workflow - reject invalid durations/scope values before the LAPI call - honor limit/all and report exact hidden counts in list tools - trim allowlist names and clarify CIDR matches - refresh licenses, package metadata, docs and QA TODO
- pin external actions to commit SHAs and harden release caches - upgrade crowdsec-client to axios 1.21.0 / follow-redirects 1.16.2 - escape backslashes in Markdown table cells - pin zizmor and snyk-agent-scan versions
- run uvx tools with --no-build and pin their versions - use explicit permissions in the Scorecard workflow - simplify the duration regex and a few lint findings
- bump body-parser to 2.4.0, qs to 6.16.1 and fast-uri to 3.1.9 - addresses Snyk findings in the MCP dependency tree
|
You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool. What Enabling Code Scanning Means:
For more information about GitHub Code Scanning, check out the documentation. |
- make the CodeQL job depend on the Snyk security job so code scanning sees its SARIF configurations - keep the standalone CodeQL workflow for the weekly scheduled scan only
- split complex handlers into focused helpers - remove async-without-await and awaited loops - simplify duration parsing, ternaries and string handling - inline the Node LTS tsconfig and set the Sonar Python version
- remove the now-unnecessary await on the synchronous passthrough factory - split the remaining complex helpers - make cell stringification and JSON body parsing explicit
- add model-facing resources, instructions and triage/investigation prompts - require scope+value for delete_alerts - add Dockerized HTTP passthrough E2E and CI workflow - document deployment, E2E, security notes and release status
- address SNYK-JS-QS-21755395 in the MCP dependency tree
- use bash [[ tests in the E2E script - remove an async function without await - replace push calls with arrays in the investigation prompt
- add shared duration helpers to crowdsec-client (days, Go wire format) - interpret numeric ban durations as seconds - stop sending undocumented alert filters and filter kind locally - delete decisions by id/scope directly, keep search for CIDR containment - harden HTTP transport (timeouts, 413 vs 500, safe cleanup, shutdown) - move the HTTP E2E script to .github/scripts and run the live integration test in CI - remove unused workflow patch scripts
- pass contains=false for alert searches so CIDR ranges match contained decisions - keep contains for watcher decisions and internal range unbans - extract list_decisions validation to lower cognitive complexity (Sonar S3776)
- config: default to watcher for TLS-only auth - unban_ip: require confirm for type/scenario-only deletes - alerts: keep since/until as Go durations on DELETE - allowlist: cover the year-1 never-expiration sentinel - docs/status: hide delete_alerts in read-only, clarify write capability - http: catch unhandled request failures - client: export GoDuration/SearchAlertsQuery/DeleteAlertsQuery overrides - build: use esbuild.js and generated pkg.ts for crowdsec-mcp
- normalize scope/value before sending list filters to the LAPI - keep CrowdSec casing (Ip/CAPI) in bouncer decision output - preserve real network/TLS errors during passthrough auth - handle aborted HTTP request bodies without leaking handlers - use the bulk allowlist endpoint for single checks too - fix Sonar issues: node: imports, regex escapes, nested ternary, async handler without await - keep GoDuration as a documented branded alias instead of a plain string
Gate the destructive delete_alerts tool on the HTTP transport itself: without a service token it stays hidden unless CROWDSEC_MCP_ALLOW_ALERT_DELETE_WITHOUT_TOKEN is explicitly set. This covers passthrough and any future tokenless HTTP setup.
Replace em/en dashes, arrows, ellipsis, comparison and multiplication symbols in docs, comments, MCP output placeholders and tests. Keep the micro sign (µ) and the 2³² superscripts, which are meaningful units/values.
…nt HTTP security delete_alerts without a narrow target (id, ip, range or scope+value) now requires confirm=true, like unban_ip type/scenario-only filters. Update the tool description, server instructions and README, and add tests for each broad filter. Also expand the README security section with the transport threat model, recommended deployments and security-relevant variables.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Summary
Adds the CrowdSec MCP server (stdio + streamable HTTP), its Docker/Compose deployment, and hardens the MCP tools after a targeted QA pass. It also extracts shared duration helpers into
crowdsec-clientand refreshes repo metadata, docs, CI and security workflows.Highlights
crowdsec-mcppackage: decisions, alerts, allowlists and a status tool, plus MCP resources (crowdsec://docs/*) and prompts. Supports bouncer and watcher modes, read-only by default."300"); numeric durations are interpreted as seconds (300→5m). Validate and normalizeCountry/ASscope values before calling the LAPI.list_decisionsandlist_alertshonorlimit/all, report exact hidden counts whenlimitis explicit, and no longer caplist_alertsat 25 rows. Default calls stay cheap and show a “more results may be available” hint.delete_alerts, and a GHCR publishing workflow with SBOM/provenance.docs/agent-setup-guide.md,llms.txt, SECURITY/CONTRIBUTING/CODE_OF_CONDUCT/SUPPORT, issue and PR templates, package licenses and metadata.Validation
pnpm --filter crowdsec-mcp buildpnpm --filter crowdsec-mcp test -- --run→ 219 passed, 11 skippedpnpm --filter crowdsec-client test -- --run→ 200 passed, 2 skippedpnpm --filter crowdsec-mcp lintgit diff --cached --checklimit=40→ 0 hidden,limit=26→ 14 hidden,limit=25→ 15 hidden,limit=1000→ 0 hidden,all=true→ 40delete_alerts,unban_ipby IP/IDNotes
delete_alertsremains local-only on the LAPI; use the sidecar deployment or run the MCP on the LAPI host.limitfetches all matching rows to compute an exact hidden count. This keeps the count accurate at the cost of a larger query; withoutlimitthe request stays small and only hints that more rows may exist.crowdsec-clientnow usesaxios@1.21.0withfollow-redirects@1.16.2; the previous Snykfollow-redirectsfinding is resolved.body-parser@2.4.0,qs@6.17.0,fast-uri@3.1.9.crowdsec-client@1.3.0andcrowdsec-mcpremains a separate release step.