Summary
During a thorough evaluation of the ql-mcp server primitives against 3 CodeQL databases, 4 query packs (UI5, CAP, XSJS, standard JS), generating 11 SARIF files with 1,101 total findings, several bugs and design improvement opportunities were identified. This issue tracks resolution of all items for the v2.25.1-next.2 release.
Evaluation context: JavaScript language, advanced-security/codeql-sap-js custom queries, CodeQL CLI v2.25.1, macOS.
Bugs
Bug 1: bqrs_interpret is unusable through the MCP interface (Critical)
The codeql_bqrs_interpret tool has multiple schema/parameter issues that make it effectively non-functional:
file parameter type mismatch: When passed as a string, the tool rejects with "must be array". When passed as an array ["/path/to/file.bqrs"], the literal bracket characters are included in the file path, causing: No results file present at /Users/.../["/path/to/file.bqrs"]
-t parameter undocumented format: The underlying CLI requires KEY=VALUE format (e.g. -t id=js/query-id) but the tool schema provides no guidance on this. Passing just a string like "problem" fails with: Value for option '-t' should be in KEY=VALUE format but was problem
- Missing required
database parameter: The tool needs a database path for source archive context during SARIF interpretation, but this isn't exposed as a required parameter in the schema.
Impact: bqrs_interpret is the only BQRS-to-SARIF primitive available standalone (outside of database_analyze/query_run). Its broken state forces workarounds.
Suggested fix: Fix the file parameter to accept a single string path. Document the -t parameter format. Add database as an optional parameter for source archive resolution.
Bug 2: query_results_cache_compare reports incorrect totalResultCount
Reproduction:
- Run
query_run for UI5Clickjacking.ql on a database → cached with a key
query_results_cache_retrieve with that cache key → returns totalResults: 82 ✅
query_results_cache_compare with queryName: "UI5Clickjacking" → reports totalResultCount: 0 for both databases ❌
The compare tool is not properly reading the result count from the cached SARIF data.
Suggested fix: Ensure cache_compare reads totalResults from the stored SARIF subset the same way cache_retrieve does.
Bug 3: annotation_search does not search by category field
Reproduction:
- Create annotation with
category: "performance", entityKey: "UI5Xss.ql", content about performance data
annotation_search with search: "performance" → returns [] (empty) ❌
annotation_search with search: "UI5Xss" → returns the annotation ✅
The search only matches against content and entityKey text, not the category field.
Suggested fix: Include the category field in the full-text search, or add a separate category filter parameter.
Bug 4: audit_add_notes ignores findingId parameter
Reproduction:
- Store a finding via
audit_store_findings → returns finding with id: 10
- Call
audit_add_notes with findingId: 10 + notes → rejected as "must have required property 'sourceLocation'"
- Must provide
sourceLocation + line + owner + repo instead of just findingId
The findingId parameter is accepted by the schema but effectively ignored — the tool identifies findings by sourceLocation + line composite key.
Suggested fix: Either make findingId the primary lookup mechanism (simpler API), or document clearly that sourceLocation + line is required.
Bug 5: bqrs_info files parameter schema mismatch
The files parameter is typed as an array, but codeql bqrs info only accepts a single file argument. Passing multiple files in the array causes: Unmatched arguments from index 1: '/path/to/second.bqrs'
Suggested fix: Change files to a single file string parameter, or loop internally over the array calling bqrs info once per file.
Design Improvements
Design 1: database_analyze should populate query_results_cache
Currently, only query_run auto-caches results into the query_results_cache. Running database_analyze (the primary bulk analysis tool) does not populate the cache. This means:
- Users cannot use
cache_compare or cache_retrieve after a database_analyze run
- To get cached results, users must re-run each query individually via
query_run
Suggested approach: After database_analyze completes, iterate over the per-query BQRS results and cache them the same way query_run does.
Design 2: Guard against parallel database_analyze on the same database
When the MCP framework dispatches two database_analyze calls in parallel targeting the same database, the second fails with:
the cache directory is already locked by another running process
The CodeQL CLI uses exclusive file locks on the database cache directory and cannot handle concurrent access.
Suggested approach: Implement a per-database mutex/queue in the MCP server so that concurrent requests to the same database are serialized rather than failing. Alternatively, return a user-friendly error indicating the database is in use.
Design 3: query_results_cache_lookup should support lookup by cache key or query name
Currently query_results_cache_lookup only accepts language as a parameter. It cannot look up whether a specific cache key exists or whether results for a specific query name are cached. The only way to check is to call cache_retrieve and see if it returns data.
Suggested approach: Add optional cacheKey and/or queryName parameters to cache_lookup so users can check cache status without retrieving the full result set.
Design 4: MCP prompts for persisting profile_codeql_query_from_logs results
The profile_codeql_query_from_logs tool returns raw JSON with profiling data (slowest predicates, durations, result sizes, cache hit ratios). There is currently no streamlined way to persist these results as annotations or audit findings.
Suggested approach: Provide MCP prompt templates (e.g. store_profiling_results or annotate_query_performance) that:
- Accept profiling output from
profile_codeql_query_from_logs
- Automatically extract key metrics (top N predicates, total duration, predicate counts, cache hit ratio)
- Create structured annotations or audit findings linked to the query file
- Enable iterative profile → annotate → optimize → re-profile → compare workflows
Design 5: Auto-enable annotation, audit, and cache tools by default in the VSIX extension
Currently, to use the annotation, audit, and query results caching tools, users must manually configure two environment variables in VS Code settings:
ENABLE_ANNOTATION_TOOLS = true
MONITORING_STORAGE_LOCATION = .codeql/ql-mcp
This is a poor out-of-box experience and means most users never discover these capabilities.
Suggested approach for v2.25.1-next.2:
- Set
ENABLE_ANNOTATION_TOOLS=true by default in the extension's server startup logic, so annotation/audit/cache tools are registered automatically when the MCP server starts.
- Default
MONITORING_STORAGE_LOCATION to a sensible workspace-relative path (e.g. .codeql/ql-mcp) when not explicitly configured. This aligns with the existing convention of storing ql-mcp artifacts under .codeql/.
- Add a VS Code extension setting (e.g.
codeql-mcp.enableAnnotationTools with default true) that allows users to disable these tools at server startup if desired. When set to false, the extension should omit ENABLE_ANNOTATION_TOOLS from the env or set it to false, preventing registration of the annotation/audit/cache tools.
- Remove the need for manual
Additional Env configuration — the two env vars should be managed internally by the extension based on the setting above, not require users to hand-add them in the Codeql-mcp: Additional Env table.
This ensures:
- New installs get the full tool suite immediately
- Existing users who already have the env vars configured are unaffected
- Users who experience issues can disable via a single toggle in settings
- The
Additional Env mechanism remains available as an override for advanced configuration
Checklist for v2.25.1-next.2
Testing Notes
All bugs were discovered during a single evaluation session using:
- Databases: 3 JavaScript databases of varying sizes (5.8 MB and 11.5 MB stringpools)
- Query packs:
advanced-security/javascript-sap-ui5-queries, advanced-security/javascript-sap-cap-queries, advanced-security/javascript-sap-xsjs-queries, codeql/javascript-queries
- Tools exercised:
register_database, resolve_database, database_analyze, query_run, bqrs_info, bqrs_decode, bqrs_interpret, query_results_cache_lookup/retrieve/compare, annotation_create/get/search/update/list, audit_store_findings/list_findings/add_notes, profile_codeql_query_from_logs
- 11 SARIF files generated with 1,101 total findings across all query packs
- 15 annotations and 5 audit findings persisted in the ql-mcp annotation/audit stores
Summary
During a thorough evaluation of the
ql-mcpserver primitives against 3 CodeQL databases, 4 query packs (UI5, CAP, XSJS, standard JS), generating 11 SARIF files with 1,101 total findings, several bugs and design improvement opportunities were identified. This issue tracks resolution of all items for thev2.25.1-next.2release.Evaluation context: JavaScript language,
advanced-security/codeql-sap-jscustom queries, CodeQL CLI v2.25.1, macOS.Bugs
Bug 1:
bqrs_interpretis unusable through the MCP interface (Critical)The
codeql_bqrs_interprettool has multiple schema/parameter issues that make it effectively non-functional:fileparameter type mismatch: When passed as a string, the tool rejects with"must be array". When passed as an array["/path/to/file.bqrs"], the literal bracket characters are included in the file path, causing:No results file present at /Users/.../["/path/to/file.bqrs"]-tparameter undocumented format: The underlying CLI requires KEY=VALUE format (e.g.-t id=js/query-id) but the tool schema provides no guidance on this. Passing just a string like"problem"fails with:Value for option '-t' should be in KEY=VALUE format but was problemdatabaseparameter: The tool needs a database path for source archive context during SARIF interpretation, but this isn't exposed as a required parameter in the schema.Impact:
bqrs_interpretis the only BQRS-to-SARIF primitive available standalone (outside ofdatabase_analyze/query_run). Its broken state forces workarounds.Suggested fix: Fix the
fileparameter to accept a single string path. Document the-tparameter format. Adddatabaseas an optional parameter for source archive resolution.Bug 2:
query_results_cache_comparereports incorrecttotalResultCountReproduction:
query_runforUI5Clickjacking.qlon a database → cached with a keyquery_results_cache_retrievewith that cache key → returnstotalResults: 82✅query_results_cache_comparewithqueryName: "UI5Clickjacking"→ reportstotalResultCount: 0for both databases ❌The compare tool is not properly reading the result count from the cached SARIF data.
Suggested fix: Ensure
cache_comparereadstotalResultsfrom the stored SARIF subset the same waycache_retrievedoes.Bug 3:
annotation_searchdoes not search bycategoryfieldReproduction:
category: "performance",entityKey: "UI5Xss.ql", content about performance dataannotation_searchwithsearch: "performance"→ returns[](empty) ❌annotation_searchwithsearch: "UI5Xss"→ returns the annotation ✅The search only matches against
contentandentityKeytext, not thecategoryfield.Suggested fix: Include the
categoryfield in the full-text search, or add a separatecategoryfilter parameter.Bug 4:
audit_add_notesignoresfindingIdparameterReproduction:
audit_store_findings→ returns finding withid: 10audit_add_noteswithfindingId: 10+ notes → rejected as"must have required property 'sourceLocation'"sourceLocation+line+owner+repoinstead of justfindingIdThe
findingIdparameter is accepted by the schema but effectively ignored — the tool identifies findings bysourceLocation+linecomposite key.Suggested fix: Either make
findingIdthe primary lookup mechanism (simpler API), or document clearly thatsourceLocation+lineis required.Bug 5:
bqrs_infofilesparameter schema mismatchThe
filesparameter is typed as an array, butcodeql bqrs infoonly accepts a single file argument. Passing multiple files in the array causes:Unmatched arguments from index 1: '/path/to/second.bqrs'Suggested fix: Change
filesto a singlefilestring parameter, or loop internally over the array callingbqrs infoonce per file.Design Improvements
Design 1:
database_analyzeshould populatequery_results_cacheCurrently, only
query_runauto-caches results into thequery_results_cache. Runningdatabase_analyze(the primary bulk analysis tool) does not populate the cache. This means:cache_compareorcache_retrieveafter adatabase_analyzerunquery_runSuggested approach: After
database_analyzecompletes, iterate over the per-query BQRS results and cache them the same wayquery_rundoes.Design 2: Guard against parallel
database_analyzeon the same databaseWhen the MCP framework dispatches two
database_analyzecalls in parallel targeting the same database, the second fails with:The CodeQL CLI uses exclusive file locks on the database cache directory and cannot handle concurrent access.
Suggested approach: Implement a per-database mutex/queue in the MCP server so that concurrent requests to the same database are serialized rather than failing. Alternatively, return a user-friendly error indicating the database is in use.
Design 3:
query_results_cache_lookupshould support lookup by cache key or query nameCurrently
query_results_cache_lookuponly acceptslanguageas a parameter. It cannot look up whether a specific cache key exists or whether results for a specific query name are cached. The only way to check is to callcache_retrieveand see if it returns data.Suggested approach: Add optional
cacheKeyand/orqueryNameparameters tocache_lookupso users can check cache status without retrieving the full result set.Design 4: MCP prompts for persisting
profile_codeql_query_from_logsresultsThe
profile_codeql_query_from_logstool returns raw JSON with profiling data (slowest predicates, durations, result sizes, cache hit ratios). There is currently no streamlined way to persist these results as annotations or audit findings.Suggested approach: Provide MCP prompt templates (e.g.
store_profiling_resultsorannotate_query_performance) that:profile_codeql_query_from_logsDesign 5: Auto-enable annotation, audit, and cache tools by default in the VSIX extension
Currently, to use the annotation, audit, and query results caching tools, users must manually configure two environment variables in VS Code settings:
ENABLE_ANNOTATION_TOOLS=trueMONITORING_STORAGE_LOCATION=.codeql/ql-mcpThis is a poor out-of-box experience and means most users never discover these capabilities.
Suggested approach for
v2.25.1-next.2:ENABLE_ANNOTATION_TOOLS=trueby default in the extension's server startup logic, so annotation/audit/cache tools are registered automatically when the MCP server starts.MONITORING_STORAGE_LOCATIONto a sensible workspace-relative path (e.g..codeql/ql-mcp) when not explicitly configured. This aligns with the existing convention of storing ql-mcp artifacts under.codeql/.codeql-mcp.enableAnnotationToolswith defaulttrue) that allows users to disable these tools at server startup if desired. When set tofalse, the extension should omitENABLE_ANNOTATION_TOOLSfrom the env or set it tofalse, preventing registration of the annotation/audit/cache tools.Additional Envconfiguration — the two env vars should be managed internally by the extension based on the setting above, not require users to hand-add them in theCodeql-mcp: Additional Envtable.This ensures:
Additional Envmechanism remains available as an override for advanced configurationChecklist for v2.25.1-next.2
bqrs_interpretparameter handling (filetype,-tformat docs,databaseparam)query_results_cache_compareresult countingcategoryinannotation_searchmatchingaudit_add_notesto usefindingIdas primary lookupbqrs_infofilesparameter to handle single file correctlyquery_results_cachefromdatabase_analyzeresultsdatabase_analyzecalls to the same databasecacheKey/queryNameparams toquery_results_cache_lookupcodeql-mcp.enableAnnotationToolssettingmaintain-changelogagent skill to guide an update of theCHANGLOG.mdin order to replace the section forv2.25.1-next.1release with an entry appropriate for thev2.25.1->v2.25.1-next.2deltaTesting Notes
All bugs were discovered during a single evaluation session using:
advanced-security/javascript-sap-ui5-queries,advanced-security/javascript-sap-cap-queries,advanced-security/javascript-sap-xsjs-queries,codeql/javascript-queriesregister_database,resolve_database,database_analyze,query_run,bqrs_info,bqrs_decode,bqrs_interpret,query_results_cache_lookup/retrieve/compare,annotation_create/get/search/update/list,audit_store_findings/list_findings/add_notes,profile_codeql_query_from_logs