A Spring Boot MCP server that exposes CodeQL static analysis as a tool, allowing LLMs to run security and quality analysis on source code repositories and receive SARIF reports.
The fastest way to get started is to run:
./setup-run.sh- Pulls the latest pre-built image
davidparry/codeql-query-serverfrom Docker Hub - Creates a
./reposdirectory to hold source code that will be analyzed - Writes
CODEQL_IMAGEinto.envso docker compose uses the remote image - Clones the example repo
data-access(branchsecurity-problem) into./repos/— this is a sample Java project with intentional security issues for demo purposes - Starts three services via
docker compose up -d:codeql-query-server— the MCP server on port 8182prometheus— metrics scraper on port 9090grafana— dashboard on port 3000 (login:admin/admin)
Once it completes you'll see a prompt with the exact Claude prompt to use.
curl http://localhost:8182/actuator/healthYou should see {"status":"UP"}. Optionally, verify the Grafana dashboard is running at http://localhost:3000 (login: admin / admin).
The repo ships with a .mcp.json file. If you open this project folder in Claude Code, the MCP server is auto-discovered.
For Claude Desktop or other clients, add this to your MCP config:
{
"mcpServers": {
"codeql": {
"type": "http",
"url": "http://localhost:8182/mcp",
"timeout": 600000
}
}
}Ask Claude (with the MCP server connected):
use the analyze tool to inspect the repo: data-access pass this into the tool
and read the output and suggest fixes from the report if the tool fails in any
way just report the failure nothing more dont do or change code
Claude will invoke the analyze tool, run CodeQL against the cloned data-access repo, read the SARIF output, and suggest security fixes.
The data-access repo ships with one intentional vulnerability:
| Severity | Rule | File | Line | Issue |
|---|---|---|---|---|
| error | java/concatenated-sql-query |
src/main/java/ai/qodo/dao/OrderDao.java |
34 | SQL query built by string concatenation with untrusted input |
The problem — building a SQL query by concatenating user-controlled values directly into the string:
// VULNERABLE
String sql = "SELECT * FROM orders WHERE id = " + orderId;The fix — use a PreparedStatement with bind parameters so user input is treated as data, not executable SQL:
// SAFE
String sql = "SELECT * FROM orders WHERE id = ?";
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setInt(1, orderId);
ResultSet rs = stmt.executeQuery();This is a SQL injection vulnerability (OWASP A03). Parameterized queries completely prevent it by separating code from data.
Put any repository into the ./repos directory, then ask Claude to analyze it by name:
use the analyze tool to inspect the repo: my-project
For non-Java languages, specify the language (CodeQL pack is downloaded automatically):
use the analyze tool to inspect the repo: my-project with language: javascript
- Grafana dashboard: http://localhost:3000 — login
admin/admin - Prometheus: http://localhost:9090
./inspector/run.shLaunches the MCP Inspector pre-connected to the server at http://localhost:8182/mcp.
Runs CodeQL analysis on a repository and returns a SARIF report.
| Parameter | Required | Description |
|---|---|---|
repo |
Yes | Name of the repository directory under /workspace/repo/ |
language |
No | Language to analyze (default: java). Supported: java, javascript, python, cpp, csharp, go, ruby, swift, rust |
The java query pack is pre-installed in the Docker image. All other language packs are downloaded on first use.
| Host | Container | Service |
|---|---|---|
| 8182 | 8080 | MCP HTTP endpoint (/mcp, /sse) |
| 9090 | 9090 | Prometheus |
| 3000 | 3000 | Grafana |
Want to modify the server or contribute? Here's what you need and the level of effort involved.
| Tool | Version | Notes |
|---|---|---|
| JDK | 21 | Eclipse Temurin recommended — matches the Docker build |
| Maven | 3.9+ | Or use the included ./mvnw wrapper (no install needed) |
| Docker | Any recent | For building and running the container |
| Layer | Technology |
|---|---|
| Framework | Spring Boot 3.4.3 |
| MCP | Spring AI 1.1.2 (spring-ai-starter-mcp-server-webmvc) |
| Metrics | Micrometer + Prometheus |
| CodeQL CLI | v2.24.3 (baked into the Docker image) |
| Java | 21 |
src/main/java/com/davidparry/codeql/codeqlserver/
├── CodeqlQueryServerApplication.java # Spring Boot entry point, CORS + tool wiring
└── AnalyzeService.java # @Tool method — shells out to analyze.sh
analyze.sh # Wrapper: codeql database create + analyze
Dockerfile # Two-stage: Maven build → Ubuntu 22.04 runtime
docker-compose.yml # codeql-server + prometheus + grafana
setup-run.sh # Pull image, clone demo repo, start compose
The core logic is small — just two Java files. AnalyzeService registers an MCP tool via @Tool, invokes analyze.sh as a subprocess, streams progress notifications back to the client, and returns the raw SARIF JSON.
# Build the JAR (skip tests)
./mvnw package -DskipTests
# Build the Docker image locally
docker build -t codeql-query-server .
# Start everything (uses the locally built image)
./compose-run.shcompose-run.sh builds the image, starts the stack, and drops you into a shell inside the container.
To use a custom repos path:
REPOS_PATH=/path/to/your/repos ./compose-run.sh| Task | Effort |
|---|---|
| Understanding the codebase | ~15 min — two Java files, one shell script |
| Adding a new language pack | Low — add a case to analyze.sh or AnalyzeService.java |
| Adding a new MCP tool | Low — annotate a new method with @Tool in any @Service |
| Modifying analysis query suites | Low — edit the .qls path in analyze.sh |
| Changing Spring Boot config | Low — src/main/resources/application.properties |
| Adding unit tests | Medium — requires mocking the ProcessBuilder shell-out |
| Supporting multi-repo batch analysis | Medium |
| Building the Docker image | ~5–10 min first time (downloads CodeQL + Java pack) |
docker compose downTo also remove volumes (clears Prometheus/Grafana data):
docker compose down -v