Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Comment thread
data-douser marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"toolName": "codeql_query_compile",
"arguments": {
Comment thread
data-douser marked this conversation as resolved.
"query": "server/ql/javascript/examples/src/ExampleQuery1/ExampleQuery1.ql"
Comment thread
data-douser marked this conversation as resolved.
}
}
Comment thread
data-douser marked this conversation as resolved.
15 changes: 15 additions & 0 deletions server/dist/codeql-development-mcp-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -193859,6 +193859,19 @@ function registerCLITool(server, definition) {
break;
}
case "codeql_query_compile":
if (query) {
positionalArgs = [...positionalArgs, query];
}
if (options["dump-dil"] === void 0) {
const pending = Array.isArray(options.additionalArgs) ? options.additionalArgs : [];
const hasDilOverride = pending.some(
(arg) => arg === "--no-dump-dil" || arg === "--dump-dil"
);
if (!hasDilOverride) {
options["dump-dil"] = true;
}
}
break;
case "codeql_resolve_metadata":
if (query) {
positionalArgs = [...positionalArgs, query];
Expand Down Expand Up @@ -196066,6 +196079,7 @@ var codeqlQueryCompileTool = {
inputSchema: {
query: external_exports.string().describe("Path to the CodeQL query file (.ql)"),
database: external_exports.string().optional().describe("Path to the CodeQL database"),
"dump-dil": external_exports.boolean().optional().describe("Print the optimized DIL intermediate representation to standard output while compiling. Enabled by default; pass false or --no-dump-dil to disable."),
library: external_exports.string().optional().describe("Path to query library"),
output: external_exports.string().optional().describe("Output file path"),
warnings: external_exports.enum(["hide", "show", "error"]).optional().describe("How to handle compilation warnings"),
Expand All @@ -196074,6 +196088,7 @@ var codeqlQueryCompileTool = {
},
examples: [
"codeql query compile --database=/path/to/db MyQuery.ql",
"codeql query compile --dump-dil --database=/path/to/db MyQuery.ql",
"codeql query compile --library=/path/to/lib --output=compiled.qlo MyQuery.ql"
]
};
Expand Down
4 changes: 2 additions & 2 deletions server/dist/codeql-development-mcp-server.js.map

Large diffs are not rendered by default.

22 changes: 21 additions & 1 deletion server/src/lib/cli-tool-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -459,8 +459,28 @@ export function registerCLITool(server: McpServer, definition: CLIToolDefinition
}

case 'codeql_query_compile':
// Handle query parameter as positional argument
if (query) {
positionalArgs = [...positionalArgs, query as string];
}
// Enable --dump-dil by default unless the user explicitly set
// dump-dil to false or passed --no-dump-dil / --dump-dil in
// additionalArgs (which takes precedence).
if (options['dump-dil'] === undefined) {
const pending = Array.isArray(options.additionalArgs)
? options.additionalArgs as string[]
: [];
const hasDilOverride = pending.some(
arg => arg === '--no-dump-dil' || arg === '--dump-dil'
);
if (!hasDilOverride) {
options['dump-dil'] = true;
}
}
break;

case 'codeql_resolve_metadata':
// Handle query parameter as positional argument for query compilation and metadata tools
// Handle query parameter as positional argument for metadata tools
if (query) {
positionalArgs = [...positionalArgs, query as string];
}
Expand Down
3 changes: 3 additions & 0 deletions server/src/tools/codeql/query-compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ export const codeqlQueryCompileTool: CLIToolDefinition = {
inputSchema: {
query: z.string().describe('Path to the CodeQL query file (.ql)'),
database: z.string().optional().describe('Path to the CodeQL database'),
'dump-dil': z.boolean().optional()
.describe('Print the optimized DIL intermediate representation to standard output while compiling. Enabled by default; pass false or --no-dump-dil to disable.'),
library: z.string().optional().describe('Path to query library'),
output: z.string().optional().describe('Output file path'),
warnings: z.enum(['hide', 'show', 'error']).optional()
Expand All @@ -22,6 +24,7 @@ export const codeqlQueryCompileTool: CLIToolDefinition = {
},
examples: [
'codeql query compile --database=/path/to/db MyQuery.ql',
'codeql query compile --dump-dil --database=/path/to/db MyQuery.ql',
'codeql query compile --library=/path/to/lib --output=compiled.qlo MyQuery.ql'
]
};
135 changes: 135 additions & 0 deletions server/test/src/lib/cli-tool-registry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,141 @@ describe('registerCLITool handler behavior', () => {
);
});

it('should enable --dump-dil by default for codeql_query_compile', async () => {
const definition: CLIToolDefinition = {
name: 'codeql_query_compile',
description: 'Compile query',
command: 'codeql',
subcommand: 'query compile',
inputSchema: {
query: z.string(),
'dump-dil': z.boolean().optional(),
additionalArgs: z.array(z.string()).optional()
}
};

registerCLITool(mockServer, definition);

const handler = (mockServer.registerTool as ReturnType<typeof vi.fn>).mock.calls[0][2];

executeCodeQLCommand.mockResolvedValueOnce({
stdout: 'Compilation successful',
stderr: '',
success: true
});

await handler({ query: '/path/to/query.ql' });

const call = executeCodeQLCommand.mock.calls[0];
const options = call[1] as Record<string, unknown>;

// --dump-dil should be enabled by default
expect(options['dump-dil']).toBe(true);
});

it('should respect dump-dil: false for codeql_query_compile', async () => {
const definition: CLIToolDefinition = {
name: 'codeql_query_compile',
description: 'Compile query',
command: 'codeql',
subcommand: 'query compile',
inputSchema: {
query: z.string(),
'dump-dil': z.boolean().optional(),
additionalArgs: z.array(z.string()).optional()
}
};

registerCLITool(mockServer, definition);

const handler = (mockServer.registerTool as ReturnType<typeof vi.fn>).mock.calls[0][2];

executeCodeQLCommand.mockResolvedValueOnce({
stdout: 'Compilation successful',
stderr: '',
success: true
});

await handler({ query: '/path/to/query.ql', 'dump-dil': false });

const call = executeCodeQLCommand.mock.calls[0];
const options = call[1] as Record<string, unknown>;

// --dump-dil should not be injected when explicitly disabled;
// buildCodeQLArgs skips false booleans so --dump-dil won't appear on CLI
expect(options['dump-dil']).toBe(false);
});

it('should not inject --dump-dil when --no-dump-dil is in additionalArgs for codeql_query_compile', async () => {
const definition: CLIToolDefinition = {
name: 'codeql_query_compile',
description: 'Compile query',
command: 'codeql',
subcommand: 'query compile',
inputSchema: {
query: z.string(),
'dump-dil': z.boolean().optional(),
additionalArgs: z.array(z.string()).optional()
}
};

registerCLITool(mockServer, definition);

const handler = (mockServer.registerTool as ReturnType<typeof vi.fn>).mock.calls[0][2];

executeCodeQLCommand.mockResolvedValueOnce({
stdout: 'Compilation successful',
stderr: '',
success: true
});

await handler({ query: '/path/to/query.ql', additionalArgs: ['--no-dump-dil'] });

const call = executeCodeQLCommand.mock.calls[0];
const options = call[1] as Record<string, unknown>;
const positionalArgs = call[2] as string[];

// --dump-dil should not be in options when --no-dump-dil is in additionalArgs
expect(options['dump-dil']).toBeUndefined();
// --no-dump-dil should be passed through in the positional/additional args
expect(positionalArgs).toContain('--no-dump-dil');
});

it('should not inject --dump-dil when --dump-dil is already in additionalArgs for codeql_query_compile', async () => {
const definition: CLIToolDefinition = {
name: 'codeql_query_compile',
description: 'Compile query',
command: 'codeql',
subcommand: 'query compile',
inputSchema: {
query: z.string(),
'dump-dil': z.boolean().optional(),
additionalArgs: z.array(z.string()).optional()
}
};

registerCLITool(mockServer, definition);

const handler = (mockServer.registerTool as ReturnType<typeof vi.fn>).mock.calls[0][2];

executeCodeQLCommand.mockResolvedValueOnce({
stdout: 'Compilation successful',
stderr: '',
success: true
});

await handler({ query: '/path/to/query.ql', additionalArgs: ['--dump-dil'] });

const call = executeCodeQLCommand.mock.calls[0];
const options = call[1] as Record<string, unknown>;
const positionalArgs = call[2] as string[];

// --dump-dil should not be duplicated in options when already in additionalArgs
expect(options['dump-dil']).toBeUndefined();
// The explicit --dump-dil from additionalArgs should be passed through
expect(positionalArgs).toContain('--dump-dil');
});

it('should pass format to CLI for codeql_bqrs_interpret', async () => {
const definition: CLIToolDefinition = {
name: 'codeql_bqrs_interpret',
Expand Down
43 changes: 43 additions & 0 deletions server/test/src/tools/codeql/query-compile.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* Tests for query-compile tool
*/

import { describe, it, expect } from 'vitest';
import { codeqlQueryCompileTool } from '../../../../src/tools/codeql/query-compile';

describe('Query Compile Tool', () => {
describe('Tool Definition', () => {
it('should have correct name', () => {
expect(codeqlQueryCompileTool.name).toBe('codeql_query_compile');
});

it('should have correct command and subcommand', () => {
expect(codeqlQueryCompileTool.command).toBe('codeql');
expect(codeqlQueryCompileTool.subcommand).toBe('query compile');
});

it('should have input schema with expected fields', () => {
const schema = codeqlQueryCompileTool.inputSchema;

expect(schema).toHaveProperty('query');
expect(schema).toHaveProperty('database');
expect(schema).toHaveProperty('dump-dil');
expect(schema).toHaveProperty('library');
expect(schema).toHaveProperty('output');
expect(schema).toHaveProperty('warnings');
expect(schema).toHaveProperty('verbose');
expect(schema).toHaveProperty('additionalArgs');
});

it('should have dump-dil as optional boolean parameter', () => {
const dumpDil = codeqlQueryCompileTool.inputSchema['dump-dil'];
expect(dumpDil).toBeDefined();
expect(dumpDil.isOptional()).toBe(true);
});

it('should have examples', () => {
expect(codeqlQueryCompileTool.examples).toBeDefined();
expect(codeqlQueryCompileTool.examples!.length).toBeGreaterThan(0);
});
});
});