Skip to content

Commit 0157993

Browse files
Copilotdata-douser
andauthored
fix: address automated review feedback — error message, fingerprint response, dedup perf, changelog links
1. loadSarif error message updated to source-agnostic "No SARIF source provided" 2. sarif_compare_alerts response now includes fingerprintMatch/matchedFingerprints in fingerprint mode 3. sarif_deduplicate_rules precomputes per-rule extracted results before pairwise loop 4. CHANGELOG entries corrected: partialFingerprints → fingerprint, added PR #234 links Agent-Logs-Url: https://github.com/advanced-security/codeql-development-mcp-server/sessions/85233122-a70c-49a6-a247-fb01f4da6946 Co-authored-by: data-douser <70299490+data-douser@users.noreply.github.com>
1 parent a9df508 commit 0157993

File tree

5 files changed

+85
-32
lines changed

5 files changed

+85
-32
lines changed

CHANGELOG.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ _Changes on `main` since the latest tagged release that have not yet been includ
2020

2121
- **Annotation, audit, cache, and SARIF tools are now always enabled** — Removed the `ENABLE_ANNOTATION_TOOLS` opt-in gate; all annotation, audit, query result cache, and SARIF analysis tools are registered by default. The `ENABLE_ANNOTATION_TOOLS` environment variable no longer controls tool availability; when set to `false`, it only disables the related auto-caching behaviour in result processing. ([#223](https://github.com/advanced-security/codeql-development-mcp-server/pull/223))
2222
- **Go-based `ql-mcp-client` rewrite** — Replaced the Node.js `ql-mcp-client.js` integration test runner with a Go CLI (`gh-ql-mcp-client`) built with Cobra and `mcp-go`. Adds `list tools/prompts/resources` commands and assertion-based integration test validation. ([#223](https://github.com/advanced-security/codeql-development-mcp-server/pull/223))
23-
- **Code Scanning lifecycle management** — Added `code-scanning list-analyses`, `list-alerts`, and `download-analysis` subcommands to `gh-ql-mcp-client` with GitHub REST API integration via `go-gh`. Added `sarif` parent subcommand for SARIF delegation workflows. Enhanced SARIF tools with `sarif_store` (session cache ingest), `sarif_deduplicate_rules` (cross-file rule deduplication), and `partialFingerprints` overlap mode with automatic fallback.
23+
- **Code Scanning lifecycle management** — Added `code-scanning list-analyses`, `list-alerts`, and `download-analysis` subcommands to `gh-ql-mcp-client` with GitHub REST API integration via `go-gh`. Added `sarif` parent subcommand for SARIF delegation workflows. Enhanced SARIF tools with `sarif_store` (session cache ingest), `sarif_deduplicate_rules` (cross-file rule deduplication), and `fingerprint` overlap mode with automatic fallback. ([#234](https://github.com/advanced-security/codeql-development-mcp-server/pull/234))
2424
- **Persistent MRVA workflow state and caching** — Introduced a new `SqliteStore` backend plus annotation, audit, and query result cache tools to support the next phase of MCP-assisted CodeQL development and `seclab-taskflow-agent` integration. ([#169](https://github.com/advanced-security/codeql-development-mcp-server/pull/169))
2525
- **Rust language support** — Added first-class Rust support with `PrintAST`, `PrintCFG`, `CallGraphFrom`, `CallGraphTo`, and `CallGraphFromTo` queries, bringing the total supported languages to 10. ([#195](https://github.com/advanced-security/codeql-development-mcp-server/pull/195))
2626
- **Bug fixes and design improvements from recent evaluation sessions** — Fixed 5 bugs across `bqrs_interpret`, `bqrs_info`, `annotation_search`, `audit_add_notes`, and `query_results_cache_compare`; added `database_analyze` auto-caching and per-database mutex serialization; auto-enabled annotation tools in VS Code extension. ([#199](https://github.com/advanced-security/codeql-development-mcp-server/pull/199))
@@ -30,13 +30,13 @@ _Changes on `main` since the latest tagged release that have not yet been includ
3030

3131
#### MCP Server Tools
3232

33-
| Tool | Description |
34-
| ------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
35-
| `annotation_create`, `annotation_get`, `annotation_list`, `annotation_update`, `annotation_delete`, `annotation_search` | General-purpose annotation tools for creating, managing, and searching notes and bookmarks on analysis entities. ([#169](https://github.com/advanced-security/codeql-development-mcp-server/pull/169)) |
36-
| `audit_store_findings`, `audit_list_findings`, `audit_add_notes`, `audit_clear_repo` | Repo-keyed audit tools for MRVA finding management and triage workflows. ([#169](https://github.com/advanced-security/codeql-development-mcp-server/pull/169)) |
37-
| `query_results_cache_lookup`, `query_results_cache_retrieve`, `query_results_cache_clear`, `query_results_cache_compare` | Query result cache tools for lookup, subset retrieval, cache clearing, and cross-database comparison. ([#169](https://github.com/advanced-security/codeql-development-mcp-server/pull/169)) |
38-
| `sarif_list_rules`, `sarif_extract_rule`, `sarif_rule_to_markdown`, `sarif_compare_alerts`, `sarif_diff_runs` | SARIF analysis tools for rule discovery, per-rule extraction, Mermaid dataflow visualization, alert overlap comparison, and cross-run behavioral diffing. ([#204](https://github.com/advanced-security/codeql-development-mcp-server/pull/204)) |
39-
| `sarif_store`, `sarif_deduplicate_rules` | SARIF session cache ingest and cross-file rule deduplication tools. `sarif_compare_alerts` enhanced with `partialFingerprints` overlap mode with automatic fallback to full-path comparison. |
33+
| Tool | Description |
34+
| ------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
35+
| `annotation_create`, `annotation_get`, `annotation_list`, `annotation_update`, `annotation_delete`, `annotation_search` | General-purpose annotation tools for creating, managing, and searching notes and bookmarks on analysis entities. ([#169](https://github.com/advanced-security/codeql-development-mcp-server/pull/169)) |
36+
| `audit_store_findings`, `audit_list_findings`, `audit_add_notes`, `audit_clear_repo` | Repo-keyed audit tools for MRVA finding management and triage workflows. ([#169](https://github.com/advanced-security/codeql-development-mcp-server/pull/169)) |
37+
| `query_results_cache_lookup`, `query_results_cache_retrieve`, `query_results_cache_clear`, `query_results_cache_compare` | Query result cache tools for lookup, subset retrieval, cache clearing, and cross-database comparison. ([#169](https://github.com/advanced-security/codeql-development-mcp-server/pull/169)) |
38+
| `sarif_list_rules`, `sarif_extract_rule`, `sarif_rule_to_markdown`, `sarif_compare_alerts`, `sarif_diff_runs` | SARIF analysis tools for rule discovery, per-rule extraction, Mermaid dataflow visualization, alert overlap comparison, and cross-run behavioral diffing. ([#204](https://github.com/advanced-security/codeql-development-mcp-server/pull/204)) |
39+
| `sarif_store`, `sarif_deduplicate_rules` | SARIF session cache ingest and cross-file rule deduplication tools. `sarif_compare_alerts` enhanced with `fingerprint` overlap mode with automatic fallback to full-path comparison. ([#234](https://github.com/advanced-security/codeql-development-mcp-server/pull/234)) |
4040

4141
#### MCP Server Resources
4242

@@ -60,8 +60,8 @@ _Changes on `main` since the latest tagged release that have not yet been includ
6060

6161
- Added Rust coverage to CI and release workflows, including query unit tests and VSIX bundling. ([#195](https://github.com/advanced-security/codeql-development-mcp-server/pull/195))
6262
- Added client integration tests for the new Rust queries and for the annotation, audit, and cache tool suites, including an MRVA triage workflow end-to-end test. ([#169](https://github.com/advanced-security/codeql-development-mcp-server/pull/169), [#195](https://github.com/advanced-security/codeql-development-mcp-server/pull/195))
63-
- Added `code-scanning` and `sarif` subcommand groups to `gh-ql-mcp-client` with GitHub REST API client integration via `go-gh` for Code Scanning alert lifecycle management.
64-
- Added `gh` extension packaging support with cross-compilation targets for `darwin/amd64`, `darwin/arm64`, `linux/amd64`, `linux/arm64`, `windows/amd64`.
63+
- Added `code-scanning` and `sarif` subcommand groups to `gh-ql-mcp-client` with GitHub REST API client integration via `go-gh` for Code Scanning alert lifecycle management. ([#234](https://github.com/advanced-security/codeql-development-mcp-server/pull/234))
64+
- Added `gh` extension packaging support with cross-compilation targets for `darwin/amd64`, `darwin/arm64`, `linux/amd64`, `linux/arm64`, `windows/amd64`. ([#234](https://github.com/advanced-security/codeql-development-mcp-server/pull/234))
6565

6666
### Changed
6767

server/dist/codeql-development-mcp-server.js

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -200435,7 +200435,7 @@ function registerSarifTools(server) {
200435200435
function loadSarif(opts) {
200436200436
const { cacheKey: cacheKey2, inlineContent, sarifPath } = opts;
200437200437
if (!sarifPath && !cacheKey2 && !inlineContent) {
200438-
return { error: "Either sarifPath or cacheKey is required." };
200438+
return { error: "No SARIF source provided." };
200439200439
}
200440200440
let content;
200441200441
if (inlineContent) {
@@ -200630,6 +200630,12 @@ function registerSarifCompareAlertsTool(server) {
200630200630
if (overlap.pathSimilarity !== void 0) {
200631200631
response.pathSimilarity = overlap.pathSimilarity;
200632200632
}
200633+
if (overlap.fingerprintMatch !== void 0) {
200634+
response.fingerprintMatch = overlap.fingerprintMatch;
200635+
}
200636+
if (overlap.matchedFingerprints !== void 0) {
200637+
response.matchedFingerprints = overlap.matchedFingerprints;
200638+
}
200633200639
return {
200634200640
content: [{
200635200641
type: "text",
@@ -200759,15 +200765,32 @@ function registerSarifDeduplicateRulesTool(server) {
200759200765
const rulesA = listSarifRules(loadedA.sarif);
200760200766
const rulesB = listSarifRules(loadedB.sarif);
200761200767
const duplicateGroups = [];
200768+
const ruleDataA = /* @__PURE__ */ new Map();
200769+
for (const rA of rulesA) {
200770+
if (rA.resultCount === 0) continue;
200771+
const extracted = extractRuleFromSarif(loadedA.sarif, rA.ruleId);
200772+
ruleDataA.set(rA.ruleId, {
200773+
results: extracted.runs[0]?.results ?? [],
200774+
ruleObj: extracted.runs[0]?.tool.driver.rules?.[0] ?? { id: rA.ruleId }
200775+
});
200776+
}
200777+
const ruleDataB = /* @__PURE__ */ new Map();
200778+
for (const rB of rulesB) {
200779+
if (rB.resultCount === 0) continue;
200780+
const extracted = extractRuleFromSarif(loadedB.sarif, rB.ruleId);
200781+
ruleDataB.set(rB.ruleId, {
200782+
results: extracted.runs[0]?.results ?? [],
200783+
ruleObj: extracted.runs[0]?.tool.driver.rules?.[0] ?? { id: rB.ruleId }
200784+
});
200785+
}
200762200786
for (const rA of rulesA) {
200787+
const dataA = ruleDataA.get(rA.ruleId);
200788+
if (!dataA) continue;
200763200789
for (const rB of rulesB) {
200764-
if (rA.resultCount === 0 || rB.resultCount === 0) continue;
200765-
const extractedA = extractRuleFromSarif(loadedA.sarif, rA.ruleId);
200766-
const extractedB = extractRuleFromSarif(loadedB.sarif, rB.ruleId);
200767-
const resultsA = extractedA.runs[0]?.results ?? [];
200768-
const resultsB = extractedB.runs[0]?.results ?? [];
200769-
const ruleObjA = extractedA.runs[0]?.tool.driver.rules?.[0] ?? { id: rA.ruleId };
200770-
const ruleObjB = extractedB.runs[0]?.tool.driver.rules?.[0] ?? { id: rB.ruleId };
200790+
const dataB = ruleDataB.get(rB.ruleId);
200791+
if (!dataB) continue;
200792+
const { results: resultsA, ruleObj: ruleObjA } = dataA;
200793+
const { results: resultsB, ruleObj: ruleObjB } = dataB;
200771200794
const overlaps = findOverlappingAlerts(resultsA, ruleObjA, resultsB, ruleObjB, "full-path");
200772200795
const matchedAIndices = /* @__PURE__ */ new Set();
200773200796
for (let ai = 0; ai < resultsA.length; ai++) {

server/dist/codeql-development-mcp-server.js.map

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

server/src/tools/sarif-tools.ts

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
sarifRuleToMarkdown,
1919
} from '../lib/sarif-utils';
2020
import { sessionDataManager } from '../lib/session-data-manager';
21+
import type { SarifResult, SarifRule } from '../types/sarif';
2122
import type { SarifDocument } from '../types/sarif';
2223
import { logger } from '../utils/logger';
2324

@@ -56,7 +57,7 @@ function loadSarif(
5657
const { cacheKey, inlineContent, sarifPath } = opts;
5758

5859
if (!sarifPath && !cacheKey && !inlineContent) {
59-
return { error: 'Either sarifPath or cacheKey is required.' };
60+
return { error: 'No SARIF source provided.' };
6061
}
6162

6263
let content: string;
@@ -298,6 +299,12 @@ function registerSarifCompareAlertsTool(server: McpServer): void {
298299
if (overlap.pathSimilarity !== undefined) {
299300
response.pathSimilarity = overlap.pathSimilarity;
300301
}
302+
if (overlap.fingerprintMatch !== undefined) {
303+
response.fingerprintMatch = overlap.fingerprintMatch;
304+
}
305+
if (overlap.matchedFingerprints !== undefined) {
306+
response.matchedFingerprints = overlap.matchedFingerprints;
307+
}
301308

302309
return {
303310
content: [{
@@ -468,17 +475,40 @@ function registerSarifDeduplicateRulesTool(server: McpServer): void {
468475
unmatchedB: number;
469476
}> = [];
470477

478+
// Precompute per-rule extracted results to avoid redundant filtering in the pairwise loop
479+
type RuleData = {
480+
results: SarifResult[];
481+
ruleObj: SarifRule | { id: string };
482+
};
483+
const ruleDataA = new Map<string, RuleData>();
484+
for (const rA of rulesA) {
485+
if (rA.resultCount === 0) continue;
486+
const extracted = extractRuleFromSarif(loadedA.sarif!, rA.ruleId);
487+
ruleDataA.set(rA.ruleId, {
488+
results: extracted.runs[0]?.results ?? [],
489+
ruleObj: extracted.runs[0]?.tool.driver.rules?.[0] ?? { id: rA.ruleId },
490+
});
491+
}
492+
const ruleDataB = new Map<string, RuleData>();
493+
for (const rB of rulesB) {
494+
if (rB.resultCount === 0) continue;
495+
const extracted = extractRuleFromSarif(loadedB.sarif!, rB.ruleId);
496+
ruleDataB.set(rB.ruleId, {
497+
results: extracted.runs[0]?.results ?? [],
498+
ruleObj: extracted.runs[0]?.tool.driver.rules?.[0] ?? { id: rB.ruleId },
499+
});
500+
}
501+
471502
// Compare each rule in A against each rule in B
472503
for (const rA of rulesA) {
504+
const dataA = ruleDataA.get(rA.ruleId);
505+
if (!dataA) continue;
473506
for (const rB of rulesB) {
474-
if (rA.resultCount === 0 || rB.resultCount === 0) continue;
475-
476-
const extractedA = extractRuleFromSarif(loadedA.sarif!, rA.ruleId);
477-
const extractedB = extractRuleFromSarif(loadedB.sarif!, rB.ruleId);
478-
const resultsA = extractedA.runs[0]?.results ?? [];
479-
const resultsB = extractedB.runs[0]?.results ?? [];
480-
const ruleObjA = extractedA.runs[0]?.tool.driver.rules?.[0] ?? { id: rA.ruleId };
481-
const ruleObjB = extractedB.runs[0]?.tool.driver.rules?.[0] ?? { id: rB.ruleId };
507+
const dataB = ruleDataB.get(rB.ruleId);
508+
if (!dataB) continue;
509+
510+
const { results: resultsA, ruleObj: ruleObjA } = dataA;
511+
const { results: resultsB, ruleObj: ruleObjB } = dataB;
482512

483513
// Full-path location overlap
484514
const overlaps = findOverlappingAlerts(resultsA, ruleObjA, resultsB, ruleObjB, 'full-path');

server/test/src/tools/sarif-tools.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ describe('SARIF Tools', () => {
189189

190190
it('should return error when no sarifPath or cacheKey provided', async () => {
191191
const result = await handlers.sarif_extract_rule({ ruleId: 'js/sql-injection' });
192-
expect(result.content[0].text).toContain('Either sarifPath or cacheKey is required');
192+
expect(result.content[0].text).toContain('No SARIF source provided');
193193
});
194194

195195
it('should return error for invalid file path', async () => {
@@ -344,7 +344,7 @@ describe('SARIF Tools', () => {
344344
const result = await handlers.sarif_diff_runs({
345345
sarifPathB: testSarifPath,
346346
});
347-
expect(result.content[0].text).toContain('Either sarifPath or cacheKey is required');
347+
expect(result.content[0].text).toContain('No SARIF source provided');
348348
});
349349
});
350350

@@ -500,7 +500,7 @@ describe('SARIF Tools', () => {
500500
const result = await handlers.sarif_deduplicate_rules({
501501
sarifPathB: testSarifPath,
502502
});
503-
expect(result.content[0].text).toContain('Either sarifPath or cacheKey is required');
503+
expect(result.content[0].text).toContain('No SARIF source provided');
504504
});
505505
});
506506
});

0 commit comments

Comments
 (0)