Skip to content

Commit dfb9717

Browse files
committed
Add list runs tool
1 parent ea337f2 commit dfb9717

File tree

2 files changed

+151
-0
lines changed

2 files changed

+151
-0
lines changed

packages/cli-v3/src/commands/mcp.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
registerTriggerTaskTool,
1717
registerGetRunDetailsTool,
1818
registerDeployTool,
19+
registerListRunsTool,
1920
} from "../mcp/tools.js";
2021
import { logger } from "../utilities/logger.js";
2122
import { intro, outro } from "@clack/prompts";
@@ -104,6 +105,7 @@ export async function mcpCommand(options: McpCommandOptions) {
104105
registerGetTasksTool(context);
105106
registerTriggerTaskTool(context);
106107
registerGetRunDetailsTool(context);
108+
registerListRunsTool(context);
107109
registerListProjectsTool(context);
108110
registerListOrgsTool(context);
109111
registerCreateProjectTool(context);

packages/cli-v3/src/mcp/tools.ts

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
GetOrgsResponseBody,
33
GetProjectsResponseBody,
44
MachinePresetName,
5+
RunStatus,
56
} from "@trigger.dev/core/v3/schemas";
67
import path, { dirname, join } from "path";
78
import { x } from "tinyexec";
@@ -592,6 +593,154 @@ export function registerGetRunDetailsTool(context: McpContext) {
592593
);
593594
}
594595

596+
export function registerListRunsTool(context: McpContext) {
597+
context.server.registerTool(
598+
"list_runs",
599+
{
600+
description: "List all runs for a project",
601+
inputSchema: {
602+
projectRef: ProjectRefSchema,
603+
configPath: z
604+
.string()
605+
.describe(
606+
"The path to the trigger.config.ts file. Only used when the trigger.config.ts file is not at the root dir (like in a monorepo setup). If not provided, we will try to find the config file in the current working directory"
607+
)
608+
.optional(),
609+
environment: z
610+
.enum(["dev", "staging", "prod", "preview"])
611+
.describe("The environment to trigger the task in")
612+
.default("dev"),
613+
branch: z
614+
.string()
615+
.describe("The branch to trigger the task in, only used for preview environments")
616+
.optional(),
617+
cursor: z
618+
.string()
619+
.describe("The cursor to use for pagination, starts with run_")
620+
.optional(),
621+
limit: z
622+
.number()
623+
.int()
624+
.describe("The number of runs to list in a single page. Up to 100")
625+
.optional(),
626+
status: RunStatus.describe("Filter for runs with this run status").optional(),
627+
taskIdentifier: z
628+
.string()
629+
.describe("Filter for runs that match this task identifier")
630+
.optional(),
631+
version: z
632+
.string()
633+
.describe("Filter for runs that match this version, e.g. 20250808.3")
634+
.optional(),
635+
tag: z.string().describe("Filter for runs that include this tag").optional(),
636+
from: z
637+
.string()
638+
.describe("Filter for runs created after this ISO 8601 timestamp")
639+
.optional(),
640+
to: z
641+
.string()
642+
.describe("Filter for runs created before this ISO 8601 timestamp")
643+
.optional(),
644+
period: z
645+
.string()
646+
.describe("Filter for runs created in the last N time period. e.g. 7d, 30d, 365d")
647+
.optional(),
648+
machine: MachinePresetName.describe(
649+
"Filter for runs that match this machine preset"
650+
).optional(),
651+
},
652+
},
653+
async ({
654+
projectRef,
655+
configPath,
656+
environment,
657+
branch,
658+
cursor,
659+
limit,
660+
status,
661+
taskIdentifier,
662+
version,
663+
tag,
664+
from,
665+
to,
666+
period,
667+
machine,
668+
}) => {
669+
context.logger?.log("calling list_runs", {
670+
projectRef,
671+
configPath,
672+
environment,
673+
branch,
674+
cursor,
675+
limit,
676+
status,
677+
taskIdentifier,
678+
version,
679+
tag,
680+
from,
681+
to,
682+
period,
683+
machine,
684+
});
685+
686+
if (context.options.devOnly && environment !== "dev") {
687+
return respondWithError(
688+
`This MCP server is only available for the dev environment. You tried to access the ${environment} environment. Remove the --dev-only flag to access other environments.`
689+
);
690+
}
691+
692+
const projectRefResult = await resolveExistingProjectRef(context, projectRef, configPath);
693+
694+
if (projectRefResult.status === "error") {
695+
return respondWithError(projectRefResult.error);
696+
}
697+
698+
const $projectRef = projectRefResult.projectRef;
699+
700+
context.logger?.log("list_runs projectRefResult", { projectRefResult });
701+
702+
const auth = await mcpAuth({
703+
server: context.server,
704+
defaultApiUrl: context.options.apiUrl,
705+
profile: context.options.profile,
706+
context,
707+
});
708+
709+
if (!auth.ok) {
710+
return respondWithError(auth.error);
711+
}
712+
713+
const apiClient = await createApiClientWithPublicJWT(auth, $projectRef, environment, [
714+
"read:runs",
715+
]);
716+
717+
if (!apiClient) {
718+
return respondWithError("Failed to create API client with public JWT");
719+
}
720+
721+
const $from = typeof from === "string" ? new Date(from) : undefined;
722+
const $to = typeof to === "string" ? new Date(to) : undefined;
723+
724+
const result = await apiClient.listRuns({
725+
after: cursor,
726+
limit,
727+
status,
728+
taskIdentifier,
729+
version,
730+
tag,
731+
from: $from,
732+
to: $to,
733+
period,
734+
machine,
735+
});
736+
737+
return {
738+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
739+
};
740+
}
741+
);
742+
}
743+
595744
export function registerDeployTool(context: McpContext) {
596745
context.server.registerTool(
597746
"deploy",

0 commit comments

Comments
 (0)