checkmarx_dscan is a modular Python package for five related workflows:
- Run a Checkmarx One upload scan against a local directory, file, or zip archive.
- Retrieve a Checkmarx JSON report that was already archived by a Jenkins pipeline build.
- Retrieve SonarQube coverage data through an MCP server with project, branch, file, and best-effort line-level detail.
- Run local pytest-based coverage analysis through the same MCP server to predict whether the current workspace is likely to clear a coverage threshold before push.
- Expose the same capabilities through an MCP server so any MCP-capable agent can call them.
Both flows return JSON shaped for downstream automation and agent processing.
By default, the tool-facing adapters in this workspace now use bundled mock reports so demos can run without live Checkmarx, Jenkins, or Sonar access. Switch back to live systems by setting CHECKMARX_DSCAN_DATA_SOURCE=live in .env or the process environment.
You can also mix live and mock per tool with these overrides (any value of mock or live):
CHECKMARX_DSCAN_DATA_SOURCE_CHECKMARXCHECKMARX_DSCAN_DATA_SOURCE_JENKINSCHECKMARX_DSCAN_DATA_SOURCE_SONAR
Each override falls back to CHECKMARX_DSCAN_DATA_SOURCE, so you can keep Checkmarx pointed at a real tenant while demoing Jenkins and SonarQube from the bundled fixtures (no JENKINS_JOB_URL or SONAR_BASE_URL required).
If you attach this project as an MCP server to an agent client such as Cody, the client should treat the tool response itself as the primary output. output_json only writes a local copy for audit or later inspection; agents do not need to read files from disk unless they explicitly want persisted artifacts.
Recommended tool selection order:
checkmarx_scanUse this for all direct Checkmarx workflows. By default it resolves the requested project against accessible Checkmarx projects and fetches the latest existing scan for that project and optional branch. Setscan_mode=projectswhen you need to enumerate accessible projects and find the best match for a user-supplied project name. Usescan_mode=uploadonly when you explicitly want to upload local source to Checkmarx and start a new scan. UseCHECKMARX_DSCAN_DATA_SOURCE=livewhen you want real API traffic instead of the bundled mock report.jenkins_artifactUse this when you want the report attached to a Jenkins pipeline build or when Jenkins build selection matters. You can pointjob_urlat a direct Jenkins job or at a PR change-requests view; when used with a change-requests view, passpr_numberto target one PR or omit it to use the latest available PR job. UseCHECKMARX_DSCAN_DATA_SOURCE=livewhen you want to call Jenkins and optional Checkmarx enrichment live.sonarUse this single tool for all Sonar and local coverage flows. Setoperation=access_probeto validate Sonar access,operation=projectsto discover project keys,operation=remote_reportfor the latest Sonar coverage report,operation=file_detailfor one file,operation=local_reportto run local pytest coverage and predict whether the current branch is likely to clear the requested threshold before push, oroperation=local_quality_gatefor the same local analysis with an explicit quality-gate pass/fail view. Liveremote_reportresponses now includeanalysis_context,quality_gate, anddecision_summaryso agents get a direct pass/fail or unknown answer inline, including pull-request scope when SonarQube exposes PR analysis metadata. In live mode, local Sonar operations runcoverage.pyin the workspace, then use SonarQube APIs to resolve the matching project and inspect the current remote quality gate definition and status. All Sonar operations, includinglocal_reportandlocal_quality_gate, followCHECKMARX_DSCAN_DATA_SOURCE: mock mode returns bundled mock data, and live mode runs the real Sonar or local coverage workflow.
Recommended response fields for agents:
agent_report.vulnerability_summaryHigh-level scan outcome, severity counts, engine counts, and terminal status.agent_report.engine_coverageWhich engines were enabled, which produced findings, and which returned zero findings.agent_report.top_actionable_issuesThe highest-priority grouped issues to review first.agent_report.top_fix_targetsThe best concise remediation targets for packages, images, or locations.agent_report.code_issues,dependency_issues,infrastructure_issues,container_issuesCategory-specific views when the agent needs to focus on one type of issue.findingsoragent_report.vulnerabilitiesLong-form normalized vulnerabilities when the summary is not enough.raw.final_scanandraw.resultsNative Checkmarx payloads when the normalized structures are still insufficient. Request these by settinginclude_raw=true.
Report profiles:
compactDefault for CLI and MCP exports. Keeps the fullagent_report.vulnerabilitieslist and the top remediation summaries, but removes duplicated derived arrays such as repeated top-level findings copies, per-category issue lists, and full actionable/fix target mirrors.fullPreserves every derived section for auditing or debugging. Use this only when you explicitly need every redundant view in one JSON payload.
Recommended agent workflow:
- Read
agent_report.vulnerability_summaryandagent_report.engine_coverage. - Inspect
agent_report.top_actionable_issuesoragent_report.top_fix_targets. - If more context is needed, inspect
findingsoragent_report.vulnerabilities. - If the project name is ambiguous, call
checkmarx_scanwithscan_mode=projectsand inspectmatchesorproject_resolution.best_match. - If native Checkmarx response details are required, call the tool again with
include_raw=true.
The package now follows a layered structure so the codebase is easier to extend without coupling CrewAI integration, CLI entrypoints, transport clients, and reporting logic together.
application/Use-case orchestration, request resolution, reporting composition, and service entrypoints.domain/Shared domain-facing models, constants, and error types used across the package.infrastructure/HTTP clients, archive creation, and JSON persistence helpers.interfaces/CLI adapters and CrewAI-facing tool bindings.
The MCP adapter is additive. The CLI entrypoints, CrewAI tools, application services, and domain models still remain the source of truth, and the MCP server only wraps the same underlying execution functions.
The original top-level modules are still kept as compatibility facades so existing imports, scripts, and tests continue to work while new development can target the layered packages.
For a direct Checkmarx scan, the package returns a bundle with:
- Normalized findings with severity, title, description, location, package metadata, remediation hints, and extracted attributes.
- Scan summary counts by severity and engine.
- Request, archive, project, and scan metadata.
- Raw Checkmarx payloads for the project, scan creation response, final scan response, and all results.
For Jenkins artifact retrieval, the package returns a bundle with:
- Jenkins job metadata.
- Selected build metadata.
- The archived artifact path and download URL.
- The downloaded Checkmarx report JSON.
- An
agent_report.vulnerabilitiesarray with per-vulnerability type, severity, title, description, location, package coordinates, recommended upgrade version, fix guidance, references, and raw detail fields when Checkmarx API enrichment is available. - Optional raw Jenkins API payloads.
- Python 3.11 or newer.
- Network access to Checkmarx One for direct scans.
- Network access to Jenkins for archived report retrieval.
- Valid credentials for whichever flow you want to use.
Use this sequence on a new machine when you want the MCP server and the validation suite to work immediately.
Windows PowerShell:
py -3.13 -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -e ".[mcp,dev]"
Copy-Item .env.example .env
python -m unittest tests.test_agent_adapters tests.test_config tests.test_project_catalog_service tests.test_project_scan_service tests.test_checkmarx_scan_service tests.test_jenkins_service tests.test_sonar_service
checkmarx-mcp-servermacOS or Linux:
python3.13 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e '.[mcp,dev]'
cp .env.example .env
python -m unittest tests.test_agent_adapters tests.test_config tests.test_project_catalog_service tests.test_project_scan_service tests.test_checkmarx_scan_service tests.test_jenkins_service tests.test_sonar_service
checkmarx-mcp-serverIf you do not need the MCP server, install with pip install -e .[dev] instead. If you only need the runtime CLI entrypoints, pip install -e . is sufficient.
For the most portable demo setup, keep .env in mock mode first, verify the tests pass, and only then switch the machine to live credentials.
Editable install:
pip install -e .Editable install with CrewAI support:
pip install -e .[crewai]Editable install with MCP server support:
pip install -e .[mcp]Python 3.13 is supported and is the primary validated runtime for this workspace.
This project can work with two separate systems. You only need the credentials for the flow you are actually using.
For SonarQube coverage, prefer a dedicated service account with a user token and only the minimum browse permissions needed for the target projects.
Required for checkmarx-dscan or python -m checkmarx_dscan.
CHECKMARX_API_TOKENorCX_APIKEYThis is the Checkmarx One API token used to obtain an access token.CHECKMARX_BASE_URLorCX_BASE_URIExample:https://us.ast.checkmarx.net
Optional:
CHECKMARX_AUTH_URL,CHECKMARX_BASE_AUTH_URL, orCX_BASE_AUTH_URICHECKMARX_TENANTorCX_TENANTCHECKMARX_BRANCHorCX_BRANCHCHECKMARX_SCAN_TYPESCHECKMARX_TIMEOUTCHECKMARX_POLL_INTERVALCHECKMARX_POLL_TIMEOUTCHECKMARX_RESULTS_PAGE_SIZE
Required for checkmarx-jenkins-artifact or python -m checkmarx_dscan.interfaces.cli.jenkins.
JENKINS_USERNAMEorJENKINS_USERYour Jenkins user id.JENKINS_API_TOKENYour Jenkins API token.JENKINS_JOB_URLFull Jenkins job URL or pass--job-urlon the command line.
Optional:
JENKINS_BASE_URLorJENKINS_URLOnly needed if you prefer to pass relative job paths instead of a full job URL.JENKINS_TIMEOUTJENKINS_POLL_INTERVALJENKINS_POLL_TIMEOUTJENKINS_ARTIFACT_NAMEDefaults tocheckmarx-ast-results.json.
Required for Sonar MCP coverage tools that talk to a SonarQube server.
SONAR_BASE_URLorSONAR_HOST_URLExample:http://sonar.multiplan.com
Optional but recommended:
SONAR_TOKENorSONAR_API_TOKENPrefer a user token from a dedicated service account.SONAR_TIMEOUT
Recommended minimum Sonar permissions for the token's backing account:
Browseon the target projects for project, branch, and measure access.See Source Codeon the target projects if you want source excerpts and best-effort line-level detail.
If no token is configured, the Sonar tool will attempt anonymous access and clearly report that mode in the tool output. For operation=local_report and operation=local_quality_gate, no Sonar base URL is required.
For operation=remote_report, local_report, and local_quality_gate, the MCP server runs real Sonar or local coverage analysis only when CHECKMARX_DSCAN_DATA_SOURCE=live. In that live path it uses SonarQube APIs such as project discovery, branch lookup, measures, file/component lookup, source lookup, and api/qualitygates/project_status to connect the current workspace to the remote Sonar project and quality gate. When a pull_request is provided, the server also attempts to resolve PR-specific analysis metadata if the SonarQube instance exposes that capability. In mock mode it returns the bundled Sonar payloads, consistent with the rest of the mock-only demo flow.
The package reads .env before resolving environment variables. Use only KEY=VALUE lines.
Do not put PowerShell commands, shell commands, or comments containing secrets into .env.
Generated JSON artifacts should be written under the top-level output/ directory. Relative --output-json paths are resolved under output/, and paths that already start with output/ are preserved as-is, which keeps the repository root clean without creating nested output/output/ directories.
Example .env for both flows:
CHECKMARX_BASE_URL=https://us.ast.checkmarx.net
CHECKMARX_API_TOKEN=your_checkmarx_api_token
JENKINS_USERNAME=your.jenkins.user
JENKINS_API_TOKEN=your_jenkins_api_token
JENKINS_JOB_URL=http://jenkins.example.com/job/folder/job/project/job/release_1/
SONAR_BASE_URL=http://sonar.multiplan.com
SONAR_TOKEN=your_sonar_user_token
# Optional: switch the tool adapters between bundled demo data and live APIs.
# This is the single source of truth for mode selection.
# Default is mock in this workspace.
CHECKMARX_DSCAN_DATA_SOURCE=mockMinimal .env for mock-only MCP usage:
CHECKMARX_DSCAN_DATA_SOURCE=mockThat single variable is the only .env entry you need to force bundled mock payloads on any machine.
The repository now includes a resettable demo target at demo/mock_providerportal_web.
The mock Checkmarx findings intentionally point to these real files:
demo/mock_providerportal_web/package.jsondemo/mock_providerportal_web/package-lock.jsondemo/mock_providerportal_web/Dockerfiledemo/mock_providerportal_web/src/server.js
Recommended demo flow:
- Keep
CHECKMARX_DSCAN_DATA_SOURCE=mockin.env. - Run the MCP server.
- Ask Copilot to inspect the mock findings and apply the recommended fixes in
demo/mock_providerportal_web. - After the demo, restore the vulnerable baseline with
python tools/mock_demo_project.py reset.
You can check the current demo-project state with python tools/mock_demo_project.py status.
What is mandatory for mock mode:
CHECKMARX_DSCAN_DATA_SOURCE=mockRecommended even though the code defaults tomock, because it removes ambiguity on fresh machines and in MCP clients.
What is not mandatory for mock mode:
CHECKMARX_BASE_URLCHECKMARX_API_TOKENJENKINS_USERNAMEJENKINS_API_TOKENSONAR_BASE_URLSONAR_TOKEN
Optional convenience values for mock mode:
JENKINS_JOB_URLOnly useful if you want to calljenkins_artifactwithout passingjob_urlin the CLI or MCP tool call.CHECKMARX_DSCAN_ENV_FILEUseful when your MCP client launches the server outside the workspace root and you want it to load a specific env file.
To switch the same machine to live services later, change CHECKMARX_DSCAN_DATA_SOURCE=live and then add only the credentials required by the workflow you intend to call.
The validation command used in this workspace for a mock-safe check is:
python -m unittest tests.test_agent_adapters tests.test_config tests.test_project_catalog_service tests.test_project_scan_service tests.test_checkmarx_scan_service tests.test_jenkins_service tests.test_sonar_serviceWhen you want to force mock mode regardless of what is already in the shell environment, set CHECKMARX_DSCAN_DATA_SOURCE=mock before running the command.
This README follows the current Jenkins documentation for scripted clients and pipeline credentials.
According to the Jenkins documentation:
- Scripted clients should use HTTP basic authentication with
username:apiToken. - API tokens are preferred over passwords.
- Credentials should be passed from the first request.
- In pipelines, credentials should be injected with Jenkins credentials bindings rather than hardcoded.
Typical steps:
- Open your Jenkins user security or configure page.
- Create a new API token for this integration.
- Copy the raw token value immediately when Jenkins shows it.
- Store it in a secure secret store, local
.env, or Jenkins credential. - If a token is ever pasted into chat, logs, or source control, rotate it.
If your Jenkins controller offers HTTPS, use HTTPS instead of HTTP.
PowerShell example:
$pair = "your.username:YOUR_JENKINS_API_TOKEN"
$basic = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes($pair))
Invoke-RestMethod -Uri "http://jenkins.example.com/user/your.username/api/json" -Headers @{ Authorization = "Basic $basic" }If this returns a 401 or 403, the most common causes are:
- Wrong username.
- Wrong token.
- Token copied incorrectly.
- Token created on a different Jenkins controller than the one you are calling.
- Jenkins policy preventing that API access for your user.
Module form:
python -m checkmarx_dscan my-project --source ./repo --output-json checkmarx-scanInstalled script form:
checkmarx-dscan my-project --source ./repo --output-json checkmarx-scanExample with explicit scan settings:
checkmarx-dscan my-project \
--source ./repo \
--branch main \
--scan-types sast,sca,iac-security \
--results-limit 20 \
--output-json checkmarx-scanLatest existing project scan through the same command:
checkmarx-dscan my-project \
--scan-mode latest_project \
--branch release_1 \
--output-json checkmarx-scanModule form:
python -m checkmarx_dscan.interfaces.cli.jenkins \
--job-url http://jenkins.example.com/job/folder/job/project/job/release_1/ \
--output-json jenkins-checkmarxInstalled script form:
checkmarx-jenkins-artifact \
--job-url http://jenkins.example.com/job/folder/job/project/job/release_1/ \
--output-json jenkins-checkmarxSpecific build example:
checkmarx-jenkins-artifact \
--job-url http://jenkins.example.com/job/folder/job/project/job/release_1/ \
--build-number 139 \
--output-json jenkins-build-139Latest completed build only:
checkmarx-jenkins-artifact \
--job-url http://jenkins.example.com/job/folder/job/project/job/release_1/ \
--latest-completed-only \
--output-json jenkins-checkmarxBehavior when no build number is provided:
- Prefer the current running build.
- Otherwise fall back to the latest completed build.
- Search archived artifacts by exact file name.
- Download the file named
checkmarx-ast-results.jsonunless overridden.
If you want a Jenkins pipeline to archive the Checkmarx JSON report so this project can retrieve it later, store credentials in Jenkins and archive the JSON artifact explicitly.
For calling Checkmarx One from a Jenkins pipeline:
- Store the Checkmarx API token as a Jenkins secret text credential.
For this project's Jenkins artifact retrieval flow:
- Store the Jenkins username and Jenkins API token as either:
- a Username with password credential where the password is the Jenkins API token, or
- separate credentials if your organization prefers that pattern.
This example follows Jenkins guidance to use credentials bindings and to avoid Groovy string interpolation for secrets.
pipeline {
agent any
environment {
CHECKMARX_BASE_URL = 'https://us.ast.checkmarx.net'
CHECKMARX_API_TOKEN = credentials('checkmarx-api-token')
}
stages {
stage('Run Checkmarx Tool') {
steps {
bat 'checkmarx-dscan cis-providerportal-web --source . --output-json checkmarx-scan'
}
}
}
post {
always {
archiveArtifacts artifacts: 'checkmarx-ast-results.json', fingerprint: true, onlyIfSuccessful: false
}
}
}If a later pipeline or job needs to pull the archived report from another job, bind Jenkins credentials and call the retrieval command.
pipeline {
agent any
stages {
stage('Pull Checkmarx Artifact') {
steps {
withCredentials([usernamePassword(credentialsId: 'jenkins-api-user-token', usernameVariable: 'JENKINS_USERNAME', passwordVariable: 'JENKINS_API_TOKEN')]) {
bat 'checkmarx-jenkins-artifact --job-url "http://jenkins.example.com/job/folder/job/project/job/release_1/" --output-json jenkins-checkmarx'
}
}
}
}
post {
always {
archiveArtifacts artifacts: 'jenkins-checkmarx-report.json', fingerprint: true, onlyIfSuccessful: false
}
}
}- Do not hardcode tokens in
Jenkinsfile. - Do not echo tokens to logs.
- Do not use Groovy double-quoted interpolation for secrets in
sh,bat,powershell, orpwshsteps. - Prefer credentials bindings such as
credentials(...)orwithCredentials(...). - Rotate tokens if they appear in chat, source control, or logs.
Install the optional CrewAI dependencies first:
pip install -e .[crewai]Then register the tools with your agent:
from crewai import Agent
from checkmarx_dscan.interfaces.agents.crewai import CheckmarxScanTool, JenkinsArtifactTool
scan_tool = CheckmarxScanTool()
jenkins_tool = JenkinsArtifactTool()
security_agent = Agent(
role="Application Security Analyst",
goal="Run Checkmarx scans and reason over the resulting JSON payloads.",
backstory="Specializes in translating scan output into remediation guidance.",
tools=[scan_tool, jenkins_tool],
)The tools return JSON strings so a CrewAI agent can pass them directly to later tasks or parse them into structured analysis.
The package also exposes the same scan and Jenkins retrieval capabilities through a stdio MCP server for any MCP-capable client, including GitHub Copilot, custom agents, and other orchestration frameworks.
Install the MCP extra if needed:
pip install -e .[mcp]Run the MCP server over stdio:
checkmarx-mcp-serverOr via module form:
python -m checkmarx_dscan.interfaces.agents.mcpIf you want the MCP server to stay fully offline and use bundled demo data, make sure .env contains CHECKMARX_DSCAN_DATA_SOURCE=mock before starting it.
The MCP server exposes three tools:
checkmarx_scanRuns a live Checkmarx upload scan and returns structured JSON.jenkins_artifactPulls an archived Checkmarx report from Jenkins and returns structured JSON.sonarUnified Sonar and local coverage tool. Useoperation=access_probe,projects,remote_report,file_detail, orlocal_reportdepending on the workflow.
Unlike the CrewAI adapter, the MCP server returns structured tool output directly instead of JSON strings, which is better for generic MCP clients.
Example GitHub Copilot MCP configuration using stdio:
{
"servers": {
"checkmarx-dscan": {
"type": "stdio",
"command": "checkmarx-mcp-server",
"env": {
"CHECKMARX_BASE_URL": "https://us.ast.checkmarx.net",
"CHECKMARX_API_TOKEN": "${input:checkmarxApiToken}",
"SONAR_BASE_URL": "http://sonar.multiplan.com",
"SONAR_TOKEN": "${input:sonarToken}"
}
}
}
}If your client prefers a full Python invocation instead of a script entrypoint:
{
"servers": {
"checkmarx-dscan": {
"type": "stdio",
"command": "python",
"args": ["-m", "checkmarx_dscan.interfaces.agents.mcp"],
"env": {
"CHECKMARX_BASE_URL": "https://us.ast.checkmarx.net",
"CHECKMARX_API_TOKEN": "${input:checkmarxApiToken}",
"SONAR_BASE_URL": "http://sonar.multiplan.com",
"SONAR_TOKEN": "${input:sonarToken}"
}
}
}
}If your MCP client launches the server from a directory other than the repository root, a relative env_file such as .env may not be found where you expect. This server now searches parent directories for relative env files, but the most reliable options are still either:
- pass
env_fileas an absolute path in the tool call, or - inject
CHECKMARX_BASE_URL,CHECKMARX_API_TOKEN,SONAR_BASE_URL, andSONAR_TOKENdirectly into the MCP server process environment.
For local workspace use, the server also supports CHECKMARX_DSCAN_ENV_FILE or CHECKMARX_ENV_FILE in the MCP server process environment. Point that variable at your workspace .env file when you want the server to load credentials from the repo without duplicating them in the client config.
Because the MCP server uses the same application services as the CLI and CrewAI tools, any improvements to scan normalization, Jenkins enrichment, or reporting automatically flow to MCP clients as well.
Check these first:
JENKINS_USERNAMEis the actual Jenkins user id.JENKINS_API_TOKENis the raw token value shown when created.- The token was generated on the same Jenkins controller you are calling.
- The token was not copied with extra whitespace.
- You are testing the same controller path as the target job.
Check these next:
- The pipeline archives
checkmarx-ast-results.jsonwitharchiveArtifacts. - The file exists before the
postblock completes. - The artifact name matches exactly, or override it with
--artifact-name. - The build reached the stage where artifact archiving happens.
That is expected if Checkmarx credentials are valid but Jenkins credentials are not. The two flows are independent.
That error is typically from the MCP client layer, not from this Python server. The usual causes are:
- The Copilot MCP client has stale tool metadata after a schema change. Restart the MCP server or reload the VS Code window.
- The MCP server is not connected or failed during startup, so the client has no live
checkmarx_scantool instance to invoke. - The MCP server was launched without the environment it needs.
Recommended setup for Copilot MCP:
- Prefer injecting
CHECKMARX_BASE_URLandCHECKMARX_API_TOKENin the MCP serverenvblock. - If you want to keep secrets only in the workspace, set
CHECKMARX_DSCAN_ENV_FILEto the absolute path of the workspace.envin the MCP serverenvblock. - Only rely on implicit
.envdiscovery when the server is running from the same repo layout and you are comfortable with that coupling.
pytest