feat(mcp): add credential and all-runs tools; replace deprecated z.string().uuid()
- add list_scenario_credentials, add_scenario_credential, remove_scenario_credential tools - add list_all_runs tool (global across all scenarios) - replace all deprecated z.string().uuid() with z.uuid() throughout mcp.service
This commit is contained in:
+156
-25
@@ -86,7 +86,7 @@ export class McpService {
|
||||
{
|
||||
description: "Delete a session by numeric ID (closes it first if open)",
|
||||
inputSchema: {
|
||||
id: z.string().uuid().describe("Session ID to delete"),
|
||||
id: z.uuid().describe("Session ID to delete"),
|
||||
},
|
||||
},
|
||||
async ({ id }) => {
|
||||
@@ -151,7 +151,7 @@ export class McpService {
|
||||
{
|
||||
description: "Get an environment record by ID",
|
||||
inputSchema: {
|
||||
id: z.string().uuid().describe("Environment ID"),
|
||||
id: z.uuid().describe("Environment ID"),
|
||||
},
|
||||
},
|
||||
async ({ id }) => {
|
||||
@@ -207,7 +207,7 @@ export class McpService {
|
||||
{
|
||||
description: "Update an existing environment (name and/or data)",
|
||||
inputSchema: {
|
||||
id: z.string().uuid().describe("Environment ID to update"),
|
||||
id: z.uuid().describe("Environment ID to update"),
|
||||
name: z.string().optional().describe("New name"),
|
||||
data: z
|
||||
.record(z.string(), z.string())
|
||||
@@ -238,7 +238,7 @@ export class McpService {
|
||||
{
|
||||
description: "Delete an environment by ID",
|
||||
inputSchema: {
|
||||
id: z.string().uuid().describe("Environment ID to delete"),
|
||||
id: z.uuid().describe("Environment ID to delete"),
|
||||
},
|
||||
},
|
||||
async ({ id }) => {
|
||||
@@ -392,7 +392,7 @@ export class McpService {
|
||||
{
|
||||
description: "Get a scenario with its steps by ID",
|
||||
inputSchema: {
|
||||
id: z.string().uuid().describe("Scenario ID"),
|
||||
id: z.uuid().describe("Scenario ID"),
|
||||
},
|
||||
},
|
||||
async ({ id }) => {
|
||||
@@ -442,7 +442,7 @@ export class McpService {
|
||||
{
|
||||
description: "Update a scenario name",
|
||||
inputSchema: {
|
||||
id: z.string().uuid().describe("Scenario ID"),
|
||||
id: z.uuid().describe("Scenario ID"),
|
||||
name: z.string().optional().describe("New name"),
|
||||
},
|
||||
},
|
||||
@@ -468,7 +468,7 @@ export class McpService {
|
||||
{
|
||||
description: "Delete a scenario by ID",
|
||||
inputSchema: {
|
||||
id: z.string().uuid().describe("Scenario ID"),
|
||||
id: z.uuid().describe("Scenario ID"),
|
||||
},
|
||||
},
|
||||
async ({ id }) => {
|
||||
@@ -493,7 +493,7 @@ export class McpService {
|
||||
{
|
||||
description: "Add a step to a scenario",
|
||||
inputSchema: {
|
||||
scenarioId: z.string().uuid().describe("Parent scenario ID"),
|
||||
scenarioId: z.uuid().describe("Parent scenario ID"),
|
||||
order: z
|
||||
.number()
|
||||
.int()
|
||||
@@ -527,8 +527,8 @@ export class McpService {
|
||||
{
|
||||
description: "Get a single step of a scenario",
|
||||
inputSchema: {
|
||||
scenarioId: z.string().uuid().describe("Scenario ID"),
|
||||
stepId: z.string().uuid().describe("Step ID"),
|
||||
scenarioId: z.uuid().describe("Scenario ID"),
|
||||
stepId: z.uuid().describe("Step ID"),
|
||||
},
|
||||
},
|
||||
async ({ scenarioId, stepId }) => {
|
||||
@@ -551,8 +551,8 @@ export class McpService {
|
||||
{
|
||||
description: "Update a step within a scenario",
|
||||
inputSchema: {
|
||||
scenarioId: z.string().uuid().describe("Scenario ID"),
|
||||
stepId: z.string().uuid().describe("Step ID"),
|
||||
scenarioId: z.uuid().describe("Scenario ID"),
|
||||
stepId: z.uuid().describe("Step ID"),
|
||||
order: z
|
||||
.number()
|
||||
.int()
|
||||
@@ -591,8 +591,8 @@ export class McpService {
|
||||
{
|
||||
description: "Delete a step from a scenario",
|
||||
inputSchema: {
|
||||
scenarioId: z.string().uuid().describe("Scenario ID"),
|
||||
stepId: z.string().uuid().describe("Step ID"),
|
||||
scenarioId: z.uuid().describe("Scenario ID"),
|
||||
stepId: z.uuid().describe("Step ID"),
|
||||
},
|
||||
},
|
||||
async ({ scenarioId, stepId }) => {
|
||||
@@ -621,7 +621,7 @@ export class McpService {
|
||||
description:
|
||||
"List runs for a scenario (paginated, optionally filtered by status)",
|
||||
inputSchema: {
|
||||
scenarioId: z.string().uuid().describe("Scenario ID"),
|
||||
scenarioId: z.uuid().describe("Scenario ID"),
|
||||
status: z
|
||||
.enum(["pending", "in_progress", "pass", "fail"])
|
||||
.optional()
|
||||
@@ -664,11 +664,8 @@ export class McpService {
|
||||
{
|
||||
description: "Trigger an immediate run of a scenario by ID",
|
||||
inputSchema: {
|
||||
id: z.string().uuid().describe("Scenario ID to run"),
|
||||
environmentId: z
|
||||
.string()
|
||||
.uuid()
|
||||
.describe("Environment ID to run the scenario in"),
|
||||
id: z.uuid().describe("Scenario ID to run"),
|
||||
environmentId: z.uuid().describe("Environment ID to run the scenario in"),
|
||||
},
|
||||
},
|
||||
async ({ id, environmentId }) => {
|
||||
@@ -692,8 +689,8 @@ export class McpService {
|
||||
description:
|
||||
"Get a specific scenario run with all step runs and their outputs",
|
||||
inputSchema: {
|
||||
scenarioId: z.string().uuid().describe("Scenario ID"),
|
||||
runId: z.string().uuid().describe("Run ID"),
|
||||
scenarioId: z.uuid().describe("Scenario ID"),
|
||||
runId: z.uuid().describe("Run ID"),
|
||||
},
|
||||
},
|
||||
async ({ scenarioId, runId }) => {
|
||||
@@ -717,8 +714,8 @@ export class McpService {
|
||||
description:
|
||||
"Block until a scenario run reaches pass or fail (max 5 min), then return the full run with step outputs",
|
||||
inputSchema: {
|
||||
scenarioId: z.string().uuid().describe("Scenario ID"),
|
||||
runId: z.string().uuid().describe("Run ID"),
|
||||
scenarioId: z.uuid().describe("Scenario ID"),
|
||||
runId: z.uuid().describe("Run ID"),
|
||||
},
|
||||
},
|
||||
async ({ scenarioId, runId }) => {
|
||||
@@ -736,13 +733,147 @@ export class McpService {
|
||||
},
|
||||
);
|
||||
|
||||
server.registerTool(
|
||||
"list_scenario_credentials",
|
||||
{
|
||||
description: "List credentials assigned to a scenario",
|
||||
inputSchema: {
|
||||
scenarioId: z.uuid().describe("Scenario ID"),
|
||||
},
|
||||
},
|
||||
async ({ scenarioId }) => {
|
||||
try {
|
||||
const creds =
|
||||
await this.scenarioService.findScenarioCredentials(scenarioId);
|
||||
return {
|
||||
content: [{ type: "text" as const, text: JSON.stringify(creds) }],
|
||||
};
|
||||
} catch (err) {
|
||||
return {
|
||||
isError: true,
|
||||
content: [{ type: "text" as const, text: (err as Error).message }],
|
||||
};
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
server.registerTool(
|
||||
"add_scenario_credential",
|
||||
{
|
||||
description:
|
||||
"Add a credential to a scenario with an alias (used in snippets)",
|
||||
inputSchema: {
|
||||
scenarioId: z.uuid().describe("Scenario ID"),
|
||||
credentialId: z.uuid().describe("Credential ID to associate"),
|
||||
alias: z
|
||||
.string()
|
||||
.describe(
|
||||
"Alias used to reference this credential in step code, e.g. pkcs_key",
|
||||
),
|
||||
},
|
||||
},
|
||||
async ({ scenarioId, credentialId, alias }) => {
|
||||
try {
|
||||
const result = await this.scenarioService.addScenarioCredential(
|
||||
scenarioId,
|
||||
{ credentialId, alias },
|
||||
);
|
||||
return {
|
||||
content: [
|
||||
{ type: "text" as const, text: JSON.stringify(result) },
|
||||
],
|
||||
};
|
||||
} catch (err) {
|
||||
return {
|
||||
isError: true,
|
||||
content: [{ type: "text" as const, text: (err as Error).message }],
|
||||
};
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
server.registerTool(
|
||||
"remove_scenario_credential",
|
||||
{
|
||||
description: "Remove a credential assignment from a scenario",
|
||||
inputSchema: {
|
||||
scenarioId: z.uuid().describe("Scenario ID"),
|
||||
scenarioCredentialId: z.uuid().describe("Scenario-credential assignment ID (not the credential ID)"),
|
||||
},
|
||||
},
|
||||
async ({ scenarioId, scenarioCredentialId }) => {
|
||||
try {
|
||||
await this.scenarioService.removeScenarioCredential(
|
||||
scenarioId,
|
||||
scenarioCredentialId,
|
||||
);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text" as const,
|
||||
text: `Credential assignment ${scenarioCredentialId} removed from scenario ${scenarioId}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
} catch (err) {
|
||||
return {
|
||||
isError: true,
|
||||
content: [{ type: "text" as const, text: (err as Error).message }],
|
||||
};
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
server.registerTool(
|
||||
"list_all_runs",
|
||||
{
|
||||
description:
|
||||
"List runs across all scenarios (paginated, filterable by status)",
|
||||
inputSchema: {
|
||||
status: z
|
||||
.enum(["pending", "in_progress", "pass", "fail"])
|
||||
.optional()
|
||||
.describe("Filter by run status"),
|
||||
page: z
|
||||
.number()
|
||||
.int()
|
||||
.min(1)
|
||||
.optional()
|
||||
.describe("Page number (default 1)"),
|
||||
limit: z
|
||||
.number()
|
||||
.int()
|
||||
.min(1)
|
||||
.optional()
|
||||
.describe("Items per page (default 20)"),
|
||||
},
|
||||
},
|
||||
async ({ status, page, limit }) => {
|
||||
try {
|
||||
const result = await this.scenarioService.findAllRuns({
|
||||
status,
|
||||
page,
|
||||
limit,
|
||||
});
|
||||
return {
|
||||
content: [{ type: "text" as const, text: JSON.stringify(result) }],
|
||||
};
|
||||
} catch (err) {
|
||||
return {
|
||||
isError: true,
|
||||
content: [{ type: "text" as const, text: (err as Error).message }],
|
||||
};
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
server.registerTool(
|
||||
"export_scenario",
|
||||
{
|
||||
description:
|
||||
"Export a scenario as a portable JSON payload (name + steps)",
|
||||
inputSchema: {
|
||||
id: z.string().uuid().describe("Scenario ID to export"),
|
||||
id: z.uuid().describe("Scenario ID to export"),
|
||||
},
|
||||
},
|
||||
async ({ id }) => {
|
||||
|
||||
Reference in New Issue
Block a user