@aksorn/sonarqube-mcp
v0.2.0
Published
MCP server that exposes SonarQube scan and code-quality tools to Cursor
Maintainers
Readme
SonarQube MCP Server
An MCP (Model Context Protocol) server that lets Cursor's AI agent check code quality and security using SonarQube across many apps.
Target workflow: a non-technical user says "check my code" in Cursor, the agent resolves the correct SonarQube project, reads issues, fixes code, runs another scan, and confirms the updated result.
Tool descriptions embed an explicit resolve project → fetch → explain → fix → rescan → verify workflow. For consistent agent behavior across projects, distribute the skill folder at distribution-skill/sonarqube-mcp-workflow so the agent has an explicit SonarQube workflow skill.
For app-team setup instructions, see USER_SETUP.md.
What it does
Two groups of tools are exposed to the AI:
SonarQube tools (always available)
| Tool | What the AI uses it for |
|------|------------------------|
| find_projects | Search SonarQube projects by app name or project key |
| ensure_project | Resolve or create the SonarQube project for a new app |
| run_scan | Run a SonarQube scan directly from the MCP server and wait for completion |
| check_code | Get quality gate status + all issues in one call — the main "check my code" tool |
| get_issues | Drill into specific files, rules, or severity levels |
| get_quality_gate | See which quality gate conditions are failing and why |
| get_rule_details | Understand a specific rule and how to fix it |
Content Gate tools (enabled when CONTENT_GATE_URL is set)
| Tool | What the AI uses it for |
|------|------------------------|
| submit_scan | ZIP a directory, upload it, and enqueue a governance scan |
| get_scan_status | Poll job status until completion |
| get_scan_result | Get the final pass/fail verdict and all findings |
| list_recent_scans | See recent scan history for a project |
Two deployment modes
| Mode | Best for | Setup effort | |------|----------|-------------| | Shared HTTP server | Teams — one instance, everyone connects | Admin sets it up once on an internal server | | Local stdio | Individual developers or offline use | Each person installs and configures locally |
Docker / Dokploy
For Dokploy (or any container host), use the included Dockerfile. The image runs node dist/http.js and listens on 3333 by default.
Step-by-step: see DOKPLOY.md.
Prerequisites
- Node.js 18+
- Access to the internal SonarQube instance (
https://idg-sonarqube.aksorn.com) — requires company VPN/network - A SonarQube user token (see setup below)
Shared HTTP server setup (recommended for teams)
Run once on any machine on your internal network. Teammates just add a URL to Cursor — no installation required on their end.
1. Run the server (admin only)
# On the shared machine:
cd sonarqube-mcp-server
npm install && npm run build
# Set env vars and start
SONAR_HOST_URL=https://idg-sonarqube.aksorn.com \
SONAR_TOKEN=<service-account-token> \
SONAR_PROJECT_KEY_PREFIX=vibe \
SONAR_AUTO_CREATE_PROJECTS=true \
MCP_HTTP_PORT=3333 \
npm run start:httpOptional settings:
MCP_HTTP_PORT=3333 # port to listen on (default: 3333)
MCP_HTTP_HOST=0.0.0.0 # bind address (default: 0.0.0.0)
MCP_API_KEY=secret123 # optional — require this key from all clients
SONAR_PROJECT_KEY_FIXED=vibe:some-existing-app # fallback for single-app setups
SONAR_PROJECT_KEY_PREFIX=vibe # prefix for derived keys like vibe:my-app
SONAR_AUTO_CREATE_PROJECTS=true # allow onboarding of new apps
SONAR_SCANNER_CLI_PATH=sonar-scanner # scanner binary for run_scan
CONTENT_GATE_URL=http://localhost:3000 # enables Content Gate toolsUse a SonarQube service account token, not a personal token — so it doesn't expire when someone leaves. The Docker image includes SonarScanner CLI for the built-in
run_scantool. The server auto-loads a local.envfile from its working directory too, so Docker deployments can use--env-file .envor mount/app/.env.
2. Keep it running (use PM2 or systemd)
npm install -g pm2
pm2 start npm --name sonarqube-mcp -- run start:http
pm2 save && pm2 startup3. What teammates add to Cursor
Each teammate adds one URL to their .cursor/mcp.json — nothing to install:
{
"mcpServers": {
"sonarqube": {
"url": "http://YOUR_SERVER_IP:3333/mcp"
}
}
}If MCP_API_KEY is set on the server:
{
"mcpServers": {
"sonarqube": {
"url": "http://YOUR_SERVER_IP:3333/mcp",
"headers": {
"Authorization": "Bearer secret123"
}
}
}
}Then Cmd+Shift+P → MCP: Restart All Servers — done.
Local stdio setup (individual / offline)
# From the sonarqube-mcp-local-server repo root:
cd sonarqube-mcp-server
npm install
npm run build2. Get a SonarQube token
- Open
https://idg-sonarqube.aksorn.com(must be on company network/VPN) - Click your avatar → My Account → Security
- Under Generate Tokens, enter a name (e.g.
cursor-mcp) and click Generate - Copy the token — you won't see it again
3. Configure Cursor
Create or edit .cursor/mcp.json in your project root:
{
"mcpServers": {
"sonarqube-local": {
"command": "node",
"args": ["/absolute/path/to/sonarqube-mcp-server/dist/index.js"],
"env": {
"SONAR_HOST_URL": "https://idg-sonarqube.aksorn.com",
"SONAR_TOKEN": "YOUR_TOKEN_HERE",
"SONAR_PROJECT_KEY_PREFIX": "vibe",
"SONAR_AUTO_CREATE_PROJECTS": "true",
"SONAR_MAX_ISSUES": "50"
}
}
}
}Replace
/absolute/path/to/sonarqube-mcp-serverwith the real path on your machine. On macOS this is typically/Users/YOUR_NAME/Documents/GitHub/sonarqube-mcp-local-server/sonarqube-mcp-server
4. Activate in Cursor
Cmd+Shift+P → MCP: Restart All Servers
You should see sonarqube-local with SonarQube project, scan, and issue tools in Cursor Settings → MCP.
run_scanrequires SonarScanner CLI in local stdio mode. Ifsonar-scanneris not installed, the tool falls back to Docker when Docker is available. The read-only SonarQube tools still work without either scanner.
Usage
Check code quality
Just say it naturally in Cursor chat:
"Check my code" "Are there any security issues?" "What's failing the quality gate?"
For multi-app use, the AI should:
- call
find_projectsif the correct project is not obvious - call
ensure_projectif the app has no SonarQube project yet - call
run_scanto upload a fresh analysis - call
check_codeto get the current issues - fix issues in the repo
- call
run_scanagain - call
check_codeagain to confirm the result
The AI should prioritize BLOCKER and CRITICAL issues first, then MAJOR, then MINOR.
Submit for governance review
"Submit my code for content gate review" "Run the content gate scan on the src/ directory"
The AI will ZIP your code, submit it, wait for the scan, and report the verdict.
Optional: Content Gate adapter
To enable the governance tools, add to your mcp.json env:
"CONTENT_GATE_URL": "http://localhost:3000",
"CONTENT_GATE_TOKEN": "your-content-gate-token"This requires a reachable Content Gate service.
Testing without VPN (mock mode)
To test the full AI → MCP → fix workflow without needing VPN access, add to your mcp.json env:
"SONAR_MOCK": "true"This returns realistic fake issues so you can validate the Cursor integration works before connecting to the real SonarQube instance. Remove this line when on the company network.
Environment variables reference
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| SONAR_HOST_URL | yes | — | SonarQube URL. Fallback: SONARQUBE_URL |
| SONAR_TOKEN | yes | — | SonarQube user token. Fallback: SONARQUBE_TOKEN |
| SONAR_PROJECT_KEY_FIXED | no | derived from repo name or prefix | Fallback project key for single-app setups |
| SONAR_PROJECT_KEY_PREFIX | no | vibe | Prefix used when deriving per-app project keys |
| SONAR_AUTO_CREATE_PROJECTS | no | false | If true, ensure_project and check_code may create missing SonarQube projects |
| SONAR_QUALITY_GATE_NAME | no | SonarQube default gate | If set, projects created by this MCP are automatically assigned to this quality gate |
| SONAR_ORGANIZATION | no | — | SonarCloud org slug (not needed for self-hosted) |
| SONAR_MAX_ISSUES | no | 50 | Max issues returned per tool call |
| SONAR_SCANNER_CLI_PATH | no | sonar-scanner | Scanner binary used by run_scan |
| SONAR_SCANNER_DOCKER_IMAGE | no | sonarsource/sonar-scanner-cli | Legacy Docker fallback image if sonar-scanner is not installed |
| SONAR_SCANNER_WAIT_TIMEOUT_MS | no | 180000 | Max time run_scan waits for SonarQube compute task completion |
| SONAR_SCANNER_POLL_INTERVAL_MS | no | 3000 | Poll interval while waiting for SonarQube compute task completion |
| SONAR_MOCK | no | — | Set to true to return fake issues (for testing) |
| CONTENT_GATE_URL | no | — | Enables Content Gate tools when set (e.g. http://localhost:3000) |
| CONTENT_GATE_TOKEN | no | — | Auth token for the Content Gate service |
| MCP_HTTP_PORT | no | 3333 | Port for HTTP server mode (npm run start:http) |
| MCP_HTTP_HOST | no | 0.0.0.0 | Bind address for HTTP server mode |
| MCP_API_KEY | no | — | If set, all HTTP clients must pass this as a Bearer token |
Development
# Run without building (uses tsx)
npm run dev
# Type-check only
npm run typecheck
# Build to dist/
npm run buildTroubleshooting
"sonarqube-local" doesn't appear in Cursor
- Check the
argspath inmcp.jsonis absolute and correct - Run
npm run buildand confirmdist/index.jsexists
Tools return "Cannot reach SonarQube"
- You must be on company VPN or internal network
- Verify with:
curl -u "YOUR_TOKEN:" https://idg-sonarqube.aksorn.com/api/system/status
run_scan fails
- Ensure SonarScanner CLI is installed on the MCP host:
sonar-scanner --version - If you rely on the Docker fallback locally, ensure Docker is installed and running
- Check that the SonarQube project exists or use
ensure_projectfirst
check my code uses the wrong app
- Search first with
find_projects - Pass the returned
projectKeyintocheck_code - For new apps, call
ensure_projectbefore the first scan
Tools return "AUTH_FAILED"
- Your token has expired or was deleted — generate a new one (step 2 above)
submit_scan fails with "DIRECTORY_NOT_FOUND"
- Pass an absolute path to
directory, or ensurecwdis your project root
Content Gate tools not appearing
CONTENT_GATE_URLmust be set inmcp.jsonfor these tools to register- the Content Gate service must be running at that URL
