Skip to content

Commit c47757a

Browse files
committed
Address latest PR review feedback
1 parent a02b3da commit c47757a

File tree

11 files changed

+994
-18
lines changed

11 files changed

+994
-18
lines changed

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

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -183829,12 +183829,13 @@ var SqliteStore = class _SqliteStore {
183829183829
truncated
183830183830
};
183831183831
} catch {
183832-
const fallback = this.getCacheContentSubset(cacheKey2, { maxLines: options.maxResults ?? 100 });
183832+
const FALLBACK_MAX_LINES = 500;
183833+
const fallback = this.getCacheContentSubset(cacheKey2, { maxLines: FALLBACK_MAX_LINES });
183833183834
if (!fallback) return null;
183834183835
return {
183835183836
content: fallback.content,
183836-
totalResults: fallback.totalLines,
183837-
returnedResults: fallback.returnedLines,
183837+
totalResults: 0,
183838+
returnedResults: 0,
183838183839
truncated: fallback.truncated
183839183840
};
183840183841
}
@@ -193434,7 +193435,7 @@ function registerAnnotationGetTool(server) {
193434193435
"annotation_get",
193435193436
"Retrieve a single annotation by its numeric ID.",
193436193437
{
193437-
id: external_exports.number().describe("The annotation ID.")
193438+
id: external_exports.number().int().positive().describe("The annotation ID (positive integer primary key).")
193438193439
},
193439193440
async ({ id }) => {
193440193441
const store = sessionDataManager.getStore();
@@ -193475,7 +193476,7 @@ function registerAnnotationUpdateTool(server) {
193475193476
"annotation_update",
193476193477
"Update the content, label, or metadata of an existing annotation.",
193477193478
{
193478-
id: external_exports.number().describe("The annotation ID to update."),
193479+
id: external_exports.number().int().positive().describe("The annotation ID to update (positive integer primary key)."),
193479193480
content: external_exports.string().optional().describe("New content (replaces existing)."),
193480193481
label: external_exports.string().optional().describe("New label (replaces existing)."),
193481193482
metadata: external_exports.string().optional().describe("New JSON-encoded metadata (replaces existing).")
@@ -193560,7 +193561,7 @@ function registerAuditStoreFindingsTool(server) {
193560193561
repo: external_exports.string().describe("Repository name."),
193561193562
findings: external_exports.array(external_exports.object({
193562193563
sourceLocation: external_exports.string().describe("File path of the finding."),
193563-
line: external_exports.number().describe("Line number of the finding."),
193564+
line: external_exports.number().int().min(1).describe("Line number of the finding (integer >= 1)."),
193564193565
sourceType: external_exports.string().describe('Type of the source (e.g. "RemoteFlowSource").'),
193565193566
description: external_exports.string().optional().describe("Human-readable description.")
193566193567
})).describe("Array of findings to store.")
@@ -193640,7 +193641,7 @@ function registerAuditAddNotesTool(server) {
193640193641
owner: external_exports.string().describe("Repository owner."),
193641193642
repo: external_exports.string().describe("Repository name."),
193642193643
sourceLocation: external_exports.string().describe("File path of the finding."),
193643-
line: external_exports.number().describe("Line number of the finding."),
193644+
line: external_exports.number().int().min(1).describe("Line number of the finding (integer >= 1)."),
193644193645
notes: external_exports.string().describe("Notes to append.")
193645193646
},
193646193647
async ({ owner, repo, sourceLocation, line, notes }) => {
@@ -193781,7 +193782,7 @@ function registerQueryResultsCacheRetrieveTool(server) {
193781193782
totalResults: subset2.totalResults,
193782193783
returnedResults: subset2.returnedResults,
193783193784
truncated: subset2.truncated,
193784-
results: parsedResults
193785+
sarifSubset: parsedResults
193785193786
}, null, 2)
193786193787
}]
193787193788
};

server/src/lib/query-results-evaluator.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,9 @@ export type BuiltInEvaluator = keyof typeof BUILT_IN_EVALUATORS;
3636
/**
3737
* In-memory cache for extracted query metadata, keyed by file path.
3838
* Stores the file modification time to invalidate when the file changes.
39-
* Bounded to {@link METADATA_CACHE_MAX} entries; oldest entries are evicted
40-
* when the limit is reached (Map iteration order = insertion order).
39+
* Bounded to {@link METADATA_CACHE_MAX} entries; least-recently-used entries
40+
* (by access) are evicted when the limit is reached. Entries are refreshed
41+
* on cache hits via delete+set, so Map iteration order reflects LRU state.
4142
*/
4243
const METADATA_CACHE_MAX = 256;
4344
const metadataCache = new Map<string, { mtime: number; metadata: QueryMetadata }>();

server/src/lib/sqlite-store.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -772,12 +772,15 @@ export class SqliteStore {
772772
truncated,
773773
};
774774
} catch {
775-
const fallback = this.getCacheContentSubset(cacheKey, { maxLines: options.maxResults ?? 100 });
775+
// Cached content is not valid SARIF JSON; fall back to line-oriented
776+
// retrieval with a dedicated line limit.
777+
const FALLBACK_MAX_LINES = 500;
778+
const fallback = this.getCacheContentSubset(cacheKey, { maxLines: FALLBACK_MAX_LINES });
776779
if (!fallback) return null;
777780
return {
778781
content: fallback.content,
779-
totalResults: fallback.totalLines,
780-
returnedResults: fallback.returnedLines,
782+
totalResults: 0,
783+
returnedResults: 0,
781784
truncated: fallback.truncated,
782785
};
783786
}

server/src/tools/annotation-tools.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ function registerAnnotationGetTool(server: McpServer): void {
6767
'annotation_get',
6868
'Retrieve a single annotation by its numeric ID.',
6969
{
70-
id: z.number().describe('The annotation ID.'),
70+
id: z.number().int().positive().describe('The annotation ID (positive integer primary key).'),
7171
},
7272
async ({ id }) => {
7373
const store = sessionDataManager.getStore();
@@ -118,7 +118,7 @@ function registerAnnotationUpdateTool(server: McpServer): void {
118118
'annotation_update',
119119
'Update the content, label, or metadata of an existing annotation.',
120120
{
121-
id: z.number().describe('The annotation ID to update.'),
121+
id: z.number().int().positive().describe('The annotation ID to update (positive integer primary key).'),
122122
content: z.string().optional().describe('New content (replaces existing).'),
123123
label: z.string().optional().describe('New label (replaces existing).'),
124124
metadata: z.string().optional().describe('New JSON-encoded metadata (replaces existing).'),

server/src/tools/audit-tools.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ function registerAuditStoreFindingsTool(server: McpServer): void {
5757
repo: z.string().describe('Repository name.'),
5858
findings: z.array(z.object({
5959
sourceLocation: z.string().describe('File path of the finding.'),
60-
line: z.number().describe('Line number of the finding.'),
60+
line: z.number().int().min(1).describe('Line number of the finding (integer >= 1).'),
6161
sourceType: z.string().describe('Type of the source (e.g. "RemoteFlowSource").'),
6262
description: z.string().optional().describe('Human-readable description.'),
6363
})).describe('Array of findings to store.'),
@@ -152,7 +152,7 @@ function registerAuditAddNotesTool(server: McpServer): void {
152152
owner: z.string().describe('Repository owner.'),
153153
repo: z.string().describe('Repository name.'),
154154
sourceLocation: z.string().describe('File path of the finding.'),
155-
line: z.number().describe('Line number of the finding.'),
155+
line: z.number().int().min(1).describe('Line number of the finding (integer >= 1).'),
156156
notes: z.string().describe('Notes to append.'),
157157
},
158158
async ({ owner, repo, sourceLocation, line, notes }) => {

server/src/tools/cache-tools.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ function registerQueryResultsCacheRetrieveTool(server: McpServer): void {
136136
totalResults: subset.totalResults,
137137
returnedResults: subset.returnedResults,
138138
truncated: subset.truncated,
139-
results: parsedResults,
139+
sarifSubset: parsedResults,
140140
}, null, 2),
141141
}],
142142
};

server/test/src/lib/sqlite-store.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,5 +445,27 @@ describe('SqliteStore', () => {
445445
expect(cleared).toBe(2);
446446
expect(store.listCacheEntries()).toHaveLength(0);
447447
});
448+
449+
it('should fall back to line-based retrieval for non-JSON SARIF content', () => {
450+
const nonJsonContent = 'This is not valid JSON\nLine 2\nLine 3\nLine 4\nLine 5';
451+
store.putCacheEntry({
452+
cacheKey: 'bad-sarif',
453+
queryName: 'Q',
454+
queryPath: '/q.ql',
455+
databasePath: '/db',
456+
language: 'javascript',
457+
codeqlVersion: '2.25.0',
458+
outputFormat: 'sarif-latest',
459+
resultContent: nonJsonContent,
460+
});
461+
462+
const subset = store.getCacheSarifSubset('bad-sarif', {});
463+
expect(subset).not.toBeNull();
464+
// Fallback should report 0 for result counts since it's not valid SARIF
465+
expect(subset!.totalResults).toBe(0);
466+
expect(subset!.returnedResults).toBe(0);
467+
// Content should still be returned (line-based fallback)
468+
expect(subset!.content).toContain('This is not valid JSON');
469+
});
448470
});
449471
});

0 commit comments

Comments
 (0)