Skip to content

Commit 2b1a3c9

Browse files
committed
fix: promote key prompt parameters from optional to required
Make databasePath, language, queryPath, and sarifPath required where the prompt depends on them. VS Code now correctly marks these fields as required in the slash-command input dialog.
1 parent 12d66d0 commit 2b1a3c9

File tree

5 files changed

+247
-311
lines changed

5 files changed

+247
-311
lines changed

extensions/vscode/test/suite/mcp-prompt-e2e.integration.test.ts

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ suite('MCP Prompt Error Handling Integration Tests', () => {
126126
const result = await client.getPrompt({
127127
name: 'explain_codeql_query',
128128
arguments: {
129+
databasePath: 'nonexistent/database',
129130
queryPath: 'nonexistent/path/to/query.ql',
130131
language: 'javascript',
131132
},
@@ -153,6 +154,7 @@ suite('MCP Prompt Error Handling Integration Tests', () => {
153154
const result = await client.getPrompt({
154155
name: 'explain_codeql_query',
155156
arguments: {
157+
databasePath: existingFile,
156158
queryPath: existingFile,
157159
language: 'javascript',
158160
},
@@ -183,6 +185,7 @@ suite('MCP Prompt Error Handling Integration Tests', () => {
183185
const result = await client.getPrompt({
184186
name: 'explain_codeql_query',
185187
arguments: {
188+
databasePath: '/some/db',
186189
queryPath: '/some/query.ql',
187190
language: 'rust',
188191
},
@@ -322,22 +325,25 @@ suite('MCP Prompt Error Handling Integration Tests', () => {
322325
console.log('[mcp-prompt-e2e] sarif_rank_false_positives correctly warned for nonexistent path');
323326
});
324327

325-
test('sarif_rank_false_positives with no arguments should return content without warning', async function () {
328+
test('sarif_rank_false_positives with no arguments should reject missing sarifPath', async function () {
326329
this.timeout(15_000);
327330

328-
const result = await client.getPrompt({
329-
name: 'sarif_rank_false_positives',
330-
arguments: {},
331-
});
332-
333-
const text = getFirstMessageText(result);
334-
// With no file paths provided, there should be no file-not-found warning.
335-
assert.ok(
336-
!text.includes('does not exist'),
337-
`Response should not contain path warnings when no paths given. Got:\n${text.slice(0, 500)}`,
338-
);
331+
// sarifPath is required; SDK should reject with a clear error.
332+
try {
333+
await client.getPrompt({
334+
name: 'sarif_rank_false_positives',
335+
arguments: {},
336+
});
337+
assert.fail('Should have thrown for missing required sarifPath');
338+
} catch (error: unknown) {
339+
const msg = error instanceof Error ? error.message : String(error);
340+
assert.ok(
341+
msg.includes('sarifPath') || msg.includes('Required'),
342+
`Error should mention the missing field. Got: ${msg.slice(0, 500)}`,
343+
);
344+
}
339345

340-
console.log('[mcp-prompt-e2e] sarif_rank_false_positives returned clean response with no args');
346+
console.log('[mcp-prompt-e2e] sarif_rank_false_positives correctly rejected missing sarifPath');
341347
});
342348

343349
// ─────────────────────────────────────────────────────────────────────
@@ -389,25 +395,28 @@ suite('MCP Prompt Error Handling Integration Tests', () => {
389395
});
390396

391397
// ─────────────────────────────────────────────────────────────────────
392-
// All prompts with all-optional params should handle empty args gracefully
398+
// Prompts with required fields should return validation error on empty args
393399
// ─────────────────────────────────────────────────────────────────────
394400

395-
test('ql_tdd_basic with empty arguments should return content without errors', async function () {
401+
test('ql_tdd_basic with empty arguments should reject missing language', async function () {
396402
this.timeout(15_000);
397403

398-
const result = await client.getPrompt({
399-
name: 'ql_tdd_basic',
400-
arguments: {},
401-
});
402-
403-
const text = getFirstMessageText(result);
404-
assert.ok(text.length > 0, 'Should return non-empty content');
405-
assert.ok(
406-
!text.includes('does not exist'),
407-
'Should not contain path warnings with no args',
408-
);
404+
// language is required; SDK should reject with a clear error.
405+
try {
406+
await client.getPrompt({
407+
name: 'ql_tdd_basic',
408+
arguments: {},
409+
});
410+
assert.fail('Should have thrown for missing required language');
411+
} catch (error: unknown) {
412+
const msg = error instanceof Error ? error.message : String(error);
413+
assert.ok(
414+
msg.includes('language') || msg.includes('Required'),
415+
`Error should mention the missing field. Got: ${msg.slice(0, 500)}`,
416+
);
417+
}
409418

410-
console.log('[mcp-prompt-e2e] ql_tdd_basic returned clean response with empty args');
419+
console.log('[mcp-prompt-e2e] ql_tdd_basic correctly rejected missing language');
411420
});
412421

413422
test('run_query_and_summarize_false_positives with nonexistent queryPath should return warning', async function () {

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

Lines changed: 38 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -64387,23 +64387,23 @@ var workshopCreationWorkflowSchema = external_exports.object({
6438764387
numStages: external_exports.coerce.number().optional().describe("Number of incremental stages (default: 4-8)")
6438864388
});
6438964389
var qlTddBasicSchema = external_exports.object({
64390-
language: external_exports.enum(SUPPORTED_LANGUAGES).optional().describe("Programming language for the query (optional)"),
64390+
language: external_exports.enum(SUPPORTED_LANGUAGES).describe("Programming language for the query"),
6439164391
queryName: external_exports.string().optional().describe("Name of the query to develop")
6439264392
});
6439364393
var qlTddAdvancedSchema = external_exports.object({
6439464394
database: external_exports.string().optional().describe("Path to the CodeQL database for analysis"),
64395-
language: external_exports.enum(SUPPORTED_LANGUAGES).optional().describe("Programming language for the query (optional)"),
64395+
language: external_exports.enum(SUPPORTED_LANGUAGES).describe("Programming language for the query"),
6439664396
queryName: external_exports.string().optional().describe("Name of the query to develop")
6439764397
});
6439864398
var sarifRankSchema = external_exports.object({
6439964399
queryId: external_exports.string().optional().describe("CodeQL query/rule identifier"),
64400-
sarifPath: external_exports.string().optional().describe("Path to the SARIF file to analyze")
64400+
sarifPath: external_exports.string().describe("Path to the SARIF file to analyze")
6440164401
});
6440264402
var describeFalsePositivesSchema = external_exports.object({
64403-
queryPath: external_exports.string().optional().describe("Path to the CodeQL query file")
64403+
queryPath: external_exports.string().describe("Path to the CodeQL query file")
6440464404
});
6440564405
var explainCodeqlQuerySchema = external_exports.object({
64406-
databasePath: external_exports.string().optional().describe("Optional path to a real CodeQL database for profiling"),
64406+
databasePath: external_exports.string().describe("Path to a CodeQL database for profiling"),
6440764407
language: external_exports.enum(SUPPORTED_LANGUAGES).describe("Programming language of the query"),
6440864408
queryPath: external_exports.string().describe("Path to the CodeQL query file (.ql or .qlref)")
6440964409
});
@@ -64412,8 +64412,8 @@ var documentCodeqlQuerySchema = external_exports.object({
6441264412
queryPath: external_exports.string().describe("Path to the CodeQL query file (.ql or .qlref)")
6441364413
});
6441464414
var qlLspIterativeDevelopmentSchema = external_exports.object({
64415-
language: external_exports.enum(SUPPORTED_LANGUAGES).optional().describe("Programming language for the query"),
64416-
queryPath: external_exports.string().optional().describe("Path to the query file being developed"),
64415+
language: external_exports.enum(SUPPORTED_LANGUAGES).describe("Programming language for the query"),
64416+
queryPath: external_exports.string().describe("Path to the query file being developed"),
6441764417
workspaceUri: external_exports.string().optional().describe("Workspace URI for LSP dependency resolution")
6441864418
});
6441964419
function toPermissiveShape(shape) {
@@ -64627,17 +64627,13 @@ ${content}`
6462764627
async ({ language, queryName }) => {
6462864628
const template = loadPromptTemplate("ql-tdd-basic.prompt.md");
6462964629
let contextSection = "## Your Development Context\n\n";
64630-
if (language) {
64631-
contextSection += `- **Language**: ${language}
64630+
contextSection += `- **Language**: ${language}
6463264631
`;
64633-
}
6463464632
if (queryName) {
6463564633
contextSection += `- **Query Name**: ${queryName}
6463664634
`;
6463764635
}
64638-
if (language || queryName) {
64639-
contextSection += "\n";
64640-
}
64636+
contextSection += "\n";
6464164637
return {
6464264638
messages: [
6464364639
{
@@ -64669,10 +64665,8 @@ ${content}`
6466964665
if (dbResult.warning) warnings.push(dbResult.warning);
6467064666
}
6467164667
let contextSection = "## Your Development Context\n\n";
64672-
if (language) {
64673-
contextSection += `- **Language**: ${language}
64668+
contextSection += `- **Language**: ${language}
6467464669
`;
64675-
}
6467664670
if (queryName) {
6467764671
contextSection += `- **Query Name**: ${queryName}
6467864672
`;
@@ -64681,9 +64675,7 @@ ${content}`
6468164675
contextSection += `- **Database**: ${resolvedDatabase}
6468264676
`;
6468364677
}
64684-
if (language || queryName || resolvedDatabase) {
64685-
contextSection += "\n";
64686-
}
64678+
contextSection += "\n";
6468764679
const warningSection = warnings.length > 0 ? warnings.join("\n") + "\n\n" : "";
6468864680
return {
6468964681
messages: [
@@ -64709,24 +64701,17 @@ ${content}`
6470964701
async ({ queryId, sarifPath }) => {
6471064702
const template = loadPromptTemplate("sarif-rank-false-positives.prompt.md");
6471164703
const warnings = [];
64712-
let resolvedSarifPath = sarifPath;
64713-
if (sarifPath) {
64714-
const spResult = resolvePromptFilePath(sarifPath);
64715-
resolvedSarifPath = spResult.resolvedPath;
64716-
if (spResult.warning) warnings.push(spResult.warning);
64717-
}
64704+
const spResult = resolvePromptFilePath(sarifPath);
64705+
const resolvedSarifPath = spResult.resolvedPath;
64706+
if (spResult.warning) warnings.push(spResult.warning);
6471864707
let contextSection = "## Analysis Context\n\n";
6471964708
if (queryId) {
6472064709
contextSection += `- **Query ID**: ${queryId}
6472164710
`;
6472264711
}
64723-
if (resolvedSarifPath) {
64724-
contextSection += `- **SARIF File**: ${resolvedSarifPath}
64712+
contextSection += `- **SARIF File**: ${resolvedSarifPath}
6472564713
`;
64726-
}
64727-
if (queryId || resolvedSarifPath) {
64728-
contextSection += "\n";
64729-
}
64714+
contextSection += "\n";
6473064715
const warningSection = warnings.length > 0 ? warnings.join("\n") + "\n\n" : "";
6473164716
return {
6473264717
messages: [
@@ -64752,24 +64737,17 @@ ${content}`
6475264737
async ({ queryId, sarifPath }) => {
6475364738
const template = loadPromptTemplate("sarif-rank-true-positives.prompt.md");
6475464739
const warnings = [];
64755-
let resolvedSarifPath = sarifPath;
64756-
if (sarifPath) {
64757-
const spResult = resolvePromptFilePath(sarifPath);
64758-
resolvedSarifPath = spResult.resolvedPath;
64759-
if (spResult.warning) warnings.push(spResult.warning);
64760-
}
64740+
const spResult = resolvePromptFilePath(sarifPath);
64741+
const resolvedSarifPath = spResult.resolvedPath;
64742+
if (spResult.warning) warnings.push(spResult.warning);
6476164743
let contextSection = "## Analysis Context\n\n";
6476264744
if (queryId) {
6476364745
contextSection += `- **Query ID**: ${queryId}
6476464746
`;
6476564747
}
64766-
if (resolvedSarifPath) {
64767-
contextSection += `- **SARIF File**: ${resolvedSarifPath}
64748+
contextSection += `- **SARIF File**: ${resolvedSarifPath}
6476864749
`;
64769-
}
64770-
if (queryId || resolvedSarifPath) {
64771-
contextSection += "\n";
64772-
}
64750+
contextSection += "\n";
6477364751
const warningSection = warnings.length > 0 ? warnings.join("\n") + "\n\n" : "";
6477464752
return {
6477564753
messages: [
@@ -64795,18 +64773,14 @@ ${content}`
6479564773
async ({ queryPath }) => {
6479664774
const template = loadPromptTemplate("run-query-and-summarize-false-positives.prompt.md");
6479764775
const warnings = [];
64798-
let resolvedQueryPath = queryPath;
64799-
if (queryPath) {
64800-
const qpResult = resolvePromptFilePath(queryPath);
64801-
resolvedQueryPath = qpResult.resolvedPath;
64802-
if (qpResult.warning) warnings.push(qpResult.warning);
64803-
}
64804-
let contextSection = "## Analysis Context\n\n";
64805-
if (resolvedQueryPath) {
64806-
contextSection += `- **Query Path**: ${resolvedQueryPath}
64776+
const qpResult = resolvePromptFilePath(queryPath);
64777+
const resolvedQueryPath = qpResult.resolvedPath;
64778+
if (qpResult.warning) warnings.push(qpResult.warning);
64779+
const contextSection = `## Analysis Context
64780+
64781+
- **Query Path**: ${resolvedQueryPath}
64782+
6480764783
`;
64808-
}
64809-
contextSection += "\n";
6481064784
const warningSection = warnings.length > 0 ? warnings.join("\n") + "\n\n" : "";
6481164785
return {
6481264786
messages: [
@@ -64835,21 +64809,16 @@ ${content}`
6483564809
const qpResult = resolvePromptFilePath(queryPath);
6483664810
const resolvedQueryPath = qpResult.resolvedPath;
6483764811
if (qpResult.warning) warnings.push(qpResult.warning);
64838-
let resolvedDatabasePath = databasePath;
64839-
if (databasePath) {
64840-
const dbResult = resolvePromptFilePath(databasePath);
64841-
resolvedDatabasePath = dbResult.resolvedPath;
64842-
if (dbResult.warning) warnings.push(dbResult.warning);
64843-
}
64812+
const dbResult = resolvePromptFilePath(databasePath);
64813+
const resolvedDatabasePath = dbResult.resolvedPath;
64814+
if (dbResult.warning) warnings.push(dbResult.warning);
6484464815
let contextSection = "## Query to Explain\n\n";
6484564816
contextSection += `- **Query Path**: ${resolvedQueryPath}
6484664817
`;
6484764818
contextSection += `- **Language**: ${language}
6484864819
`;
64849-
if (resolvedDatabasePath) {
64850-
contextSection += `- **Database Path**: ${resolvedDatabasePath}
64820+
contextSection += `- **Database Path**: ${resolvedDatabasePath}
6485164821
`;
64852-
}
6485364822
contextSection += "\n";
6485464823
const warningSection = warnings.length > 0 ? warnings.join("\n") + "\n\n" : "";
6485564824
return {
@@ -64910,34 +64879,25 @@ ${content}`
6491064879
async ({ language, queryPath, workspaceUri }) => {
6491164880
const template = loadPromptTemplate("ql-lsp-iterative-development.prompt.md");
6491264881
const warnings = [];
64913-
let resolvedQueryPath = queryPath;
64914-
if (queryPath) {
64915-
const qpResult = resolvePromptFilePath(queryPath);
64916-
resolvedQueryPath = qpResult.resolvedPath;
64917-
if (qpResult.warning) warnings.push(qpResult.warning);
64918-
}
64882+
const qpResult = resolvePromptFilePath(queryPath);
64883+
const resolvedQueryPath = qpResult.resolvedPath;
64884+
if (qpResult.warning) warnings.push(qpResult.warning);
6491964885
let resolvedWorkspaceUri = workspaceUri;
6492064886
if (workspaceUri) {
6492164887
const wsResult = resolvePromptFilePath(workspaceUri);
6492264888
resolvedWorkspaceUri = wsResult.resolvedPath;
6492364889
if (wsResult.warning) warnings.push(wsResult.warning);
6492464890
}
6492564891
let contextSection = "## Your Development Context\n\n";
64926-
if (language) {
64927-
contextSection += `- **Language**: ${language}
64892+
contextSection += `- **Language**: ${language}
6492864893
`;
64929-
}
64930-
if (resolvedQueryPath) {
64931-
contextSection += `- **Query Path**: ${resolvedQueryPath}
64894+
contextSection += `- **Query Path**: ${resolvedQueryPath}
6493264895
`;
64933-
}
6493464896
if (resolvedWorkspaceUri) {
6493564897
contextSection += `- **Workspace URI**: ${resolvedWorkspaceUri}
6493664898
`;
6493764899
}
64938-
if (language || resolvedQueryPath || resolvedWorkspaceUri) {
64939-
contextSection += "\n";
64940-
}
64900+
contextSection += "\n";
6494164901
const warningSection = warnings.length > 0 ? warnings.join("\n") + "\n\n" : "";
6494264902
return {
6494364903
messages: [

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.

0 commit comments

Comments
 (0)