Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
10 changes: 9 additions & 1 deletion mcp-server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { enableActionTool } from "./tools/actions/enable-action.js";
import { disableActionTool } from "./tools/actions/disable-action.js";
import { listAffectedTestsTool } from "./tools/actions/list-affected-tests.js";
import { getAffectedTestExecutionsTool } from "./tools/actions/get-affected-test-executions.js";
import { getAffectedTestExecutionsByActionTool } from "./tools/actions/get-affected-test-executions-by-action.js";
// Projects tools
import { getProjectsTool } from "./tools/projects/get-projects.js";
import { getProjectTool } from "./tools/projects/get-project.js";
Expand Down Expand Up @@ -109,11 +110,18 @@ server.tool(

server.tool(
"currents-get-affected-test-executions",
"Get execution details for a specific test affected by actions within a date range. Returns individual test execution records with action info. Requires projectId, signature, date_start, and date_end. (Preview endpoint: fields and path may change.)",
"Get execution details for a specific affected test (by signature) within a date range. Returns individual test execution records with action info. Uses cursor-based pagination. Requires projectId, signature, date_start, and date_end.",
getAffectedTestExecutionsTool.schema,
getAffectedTestExecutionsTool.handler
);

server.tool(
"currents-get-affected-test-executions-by-action",
"List test executions where a specific action/rule was applied, within a date range. Uses cursor-based pagination. Requires actionId, date_start, and date_end.",
getAffectedTestExecutionsByActionTool.schema,
getAffectedTestExecutionsByActionTool.handler
);

// Projects API tools
server.tool(
"currents-get-projects",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { z } from "zod";
import { fetchApi } from "../../lib/request.js";
import { logger } from "../../lib/logger.js";

const zodSchema = z.object({
actionId: z
.string()
.describe("The action ID to fetch affected test executions for."),
date_start: z
.string()
.describe("Start date in ISO 8601 format (required)."),
date_end: z
.string()
.describe("End date in ISO 8601 format (required)."),
limit: z
.number()
.int()
.min(1)
.max(50)
.optional()
.describe("Maximum number of executions (1-50). Defaults to 25."),
starting_after: z
.string()
.optional()
.describe("Cursor for pagination. Returns items after this cursor value."),
ending_before: z
.string()
.optional()
.describe("Cursor for pagination. Returns items before this cursor value."),
search: z
.string()
.max(100)
.optional()
.describe("Search by action name (case-insensitive)."),
});

const handler = async ({
actionId,
date_start,
date_end,
limit = 25,
starting_after,
ending_before,
search,
}: z.infer<typeof zodSchema>) => {
const queryParams = new URLSearchParams();
queryParams.append("date_start", date_start);
queryParams.append("date_end", date_end);
queryParams.append("limit", limit.toString());

if (starting_after) {
queryParams.append("starting_after", starting_after);
}

if (ending_before) {
queryParams.append("ending_before", ending_before);
}

if (search) {
queryParams.append("search", search);
}

logger.info(
`Fetching affected test executions for action ${actionId} with query params: ${queryParams.toString()}`
);

const data = await fetchApi(
`/actions/${actionId}/tests?${queryParams.toString()}`
);

if (!data) {
return {
content: [
{
type: "text" as const,
text: "Failed to retrieve affected test executions for action",
},
],
};
}

return {
content: [
{
type: "text" as const,
text: JSON.stringify(data, null, 2),
},
],
};
};

export const getAffectedTestExecutionsByActionTool = {
schema: zodSchema.shape,
handler,
};
42 changes: 16 additions & 26 deletions mcp-server/src/tools/actions/get-affected-test-executions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const zodSchema = z.object({
.describe("The project ID."),
signature: z
.string()
.describe("The test signature to fetch affected executions for."),
.describe("The test signature hash to fetch affected executions for."),
date_start: z
.string()
.describe("Start date in ISO 8601 format (required)."),
Expand All @@ -21,26 +21,20 @@ const zodSchema = z.object({
.min(1)
.max(50)
.optional()
.describe("Maximum number of results (1-50). Defaults to 25."),
dir: z
.enum(["asc", "desc"])
.optional()
.describe("Sort direction. Defaults to 'desc'."),
actionTypes: z
.array(z.enum(["quarantine", "skip", "tag"]))
.describe("Maximum number of executions (1-50). Defaults to 25."),
starting_after: z
.string()
.optional()
.describe(
"Filter by action types (can be specified multiple times)."
),
actionId: z
.describe("Cursor for pagination. Returns items after this cursor value."),
ending_before: z
.string()
.optional()
.describe("Filter by a specific action ID."),
.describe("Cursor for pagination. Returns items before this cursor value."),
search: z
.string()
.max(100)
.optional()
.describe("Search executions by name."),
.describe("Search by action name (case-insensitive)."),
});

const handler = async ({
Expand All @@ -49,26 +43,22 @@ const handler = async ({
date_start,
date_end,
limit = 25,
dir,
actionTypes,
actionId,
starting_after,
ending_before,
search,
}: z.infer<typeof zodSchema>) => {
const queryParams = new URLSearchParams();
queryParams.append("projectId", projectId);
queryParams.append("date_start", date_start);
queryParams.append("date_end", date_end);
queryParams.append("limit", limit.toString());

if (dir) {
queryParams.append("dir", dir);
}

if (actionTypes && actionTypes.length > 0) {
actionTypes.forEach((t) => queryParams.append("actionTypes", t));
if (starting_after) {
queryParams.append("starting_after", starting_after);
}

if (actionId) {
queryParams.append("actionId", actionId);
if (ending_before) {
queryParams.append("ending_before", ending_before);
}

if (search) {
Expand All @@ -80,7 +70,7 @@ const handler = async ({
);

const data = await fetchApi(
`/actions/tests/${projectId}/${signature}?${queryParams.toString()}`
`/actions/tests/${signature}?${queryParams.toString()}`
);

if (!data) {
Expand Down
23 changes: 12 additions & 11 deletions mcp-server/src/tools/actions/list-affected-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,21 @@ const zodSchema = z.object({
.string()
.max(100)
.optional()
.describe("Search affected tests by name."),
actionTypes: z
.describe("Search by spec file path, test title, or action name (case-insensitive)."),
action_type: z
.array(z.enum(["quarantine", "skip", "tag"]))
.optional()
.describe(
"Filter by action types (can be specified multiple times)."
),
actionId: z
action_id: z
.string()
.optional()
.describe("Filter by a specific action ID."),
dir: z
.enum(["asc", "desc"])
.optional()
.describe("Sort direction. Defaults to 'desc'."),
.describe("Sort direction for lastSeen. Defaults to 'desc'."),
status: z
.array(z.enum(["active", "disabled", "expired", "archived"]))
.optional()
Expand All @@ -57,12 +57,13 @@ const handler = async ({
page = 0,
limit = 25,
search,
actionTypes,
actionId,
action_type,
action_id,
dir,
status,
}: z.infer<typeof zodSchema>) => {
const queryParams = new URLSearchParams();
queryParams.append("projectId", projectId);
queryParams.append("date_start", date_start);
queryParams.append("date_end", date_end);
queryParams.append("page", page.toString());
Expand All @@ -72,12 +73,12 @@ const handler = async ({
queryParams.append("search", search);
}

if (actionTypes && actionTypes.length > 0) {
actionTypes.forEach((t) => queryParams.append("actionTypes", t));
if (action_type && action_type.length > 0) {
action_type.forEach((t) => queryParams.append("action_type", t));
}

if (actionId) {
queryParams.append("actionId", actionId);
if (action_id) {
queryParams.append("action_id", action_id);
}

if (dir) {
Expand All @@ -93,7 +94,7 @@ const handler = async ({
);

const data = await fetchApi(
`/actions/tests/${projectId}?${queryParams.toString()}`
`/actions/tests?${queryParams.toString()}`
);

if (!data) {
Expand Down
Loading