Skip to main content
Glama

update_manual_test_case

Modify existing manual test cases: update details, steps, status, priority, add comments, and link Jira issues by ticket keys.

Instructions

Update an existing manual test case. Use this to modify test case details, steps, status, priority, or any other fields. Provide only the fields you want to update in the updates object. To add comments, pass updates.comments as an array of strings — each becomes a new comment (PAT owner is author). To link Jira issues, pass updates.issues as an array of ticket keys (e.g. ['PROJ-123']); the server looks each up in the project's connected Jira and saves with title+url, or as a plain text stub when Jira isn't connected or the ticket isn't found (same fallback as the UI).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
projectIdYesProject ID (Required). The TestDino project identifier.
caseIdYesTest case ID (Required). Can be internal _id or human-readable ID like 'TC-123'.
updatesYesObject containing the fields to update. Can include: name, description, steps, status, priority, severity, type, layer, behavior, preconditions, postconditions, automationStatus, tags, flags, attachments, customFields, etc.

Implementation Reference

  • The main handler function 'handleUpdateManualTestCase' that executes the update logic: validates required args (projectId, caseId, updates), processes attachments in steps and top-level attachments, sends a PATCH request to the API endpoint, and returns the response.
    export async function handleUpdateManualTestCase(
      args?: UpdateManualTestCaseArgs
    ) {
      // Read PAT from environment variable (set in mcp.json) or from args
      const token = getApiKey(args);
    
      if (!token) {
        throw new Error(
          "Missing TESTDINO_PAT environment variable. " +
            "Please configure it in your .cursor/mcp.json file under the 'env' section."
        );
      }
    
      // Validate required parameters
      if (!args?.projectId) {
        throw new Error("projectId is required");
      }
      if (!args?.caseId) {
        throw new Error("caseId is required");
      }
      if (!args?.updates) {
        throw new Error("updates object is required");
      }
    
      try {
        // Process attachments if present: convert local file paths to file data objects (same format as UI)
        const processedUpdates = { ...args.updates };
        if (processedUpdates.steps && Array.isArray(processedUpdates.steps)) {
          processedUpdates.steps = processStepAttachments(processedUpdates.steps);
        }
        if (processedUpdates.attachments?.add) {
          processedUpdates.attachments.add = processAttachments(
            processedUpdates.attachments.add
          );
        }
    
        const body = { updates: processedUpdates };
    
        const updateManualTestCaseUrl = endpoints.updateManualTestCase(
          String(args.projectId),
          String(args.caseId)
        );
    
        const response = await apiRequestJson<unknown>(updateManualTestCaseUrl, {
          method: "PATCH",
          headers: {
            Authorization: `Bearer ${token}`,
          },
          body,
        });
    
        return {
          content: [
            {
              type: "text",
              text: JSON.stringify(response, null, 2),
            },
          ],
        };
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        throw new Error(`Failed to update manual test case: ${errorMessage}`);
      }
    }
  • The tool definition 'updateManualTestCaseTool' including the inputSchema (JSON Schema) and TypeScript interfaces (ManualTestCaseUpdates, UpdateManualTestCaseArgs) defining all updatable fields: name, description, status, steps, priority, severity, type, layer, behavior, automationStatus, tags, flags, attachments, customFields, comments, issues.
    export const updateManualTestCaseTool = {
      name: "update_manual_test_case",
      description:
        "Update an existing manual test case. Use this to modify test case details, steps, status, priority, or any other fields. Provide only the fields you want to update in the updates object. " +
        "To add comments, pass `updates.comments` as an array of strings — each becomes a new comment (PAT owner is author). " +
        "To link Jira issues, pass `updates.issues` as an array of ticket keys (e.g. ['PROJ-123']); the server looks each up in the project's connected Jira and saves with title+url, or as a plain text stub when Jira isn't connected or the ticket isn't found (same fallback as the UI).",
      inputSchema: {
        type: "object",
        properties: {
          projectId: {
            type: "string",
            description: "Project ID (Required). The TestDino project identifier.",
          },
          caseId: {
            type: "string",
            description:
              "Test case ID (Required). Can be internal _id or human-readable ID like 'TC-123'.",
          },
          updates: {
            type: "object",
            description:
              "Object containing the fields to update. Can include: name, description, steps, status, priority, severity, type, layer, behavior, preconditions, postconditions, automationStatus, tags, flags, attachments, customFields, etc.",
            properties: {
              name: {
                type: "string",
                description: "Updated test case name/title.",
              },
              description: {
                type: "string",
                description: "Updated description.",
              },
              status: {
                type: "string",
                description: "Updated status.",
                enum: ["Active", "Draft", "Deprecated"],
              },
              testStepsDeclarationType: {
                type: "string",
                description: "Updated test steps declaration type.",
                enum: ["Classic", "Gherkin"],
              },
              preconditions: {
                type: "string",
                description: "Updated preconditions.",
              },
              postconditions: {
                type: "string",
                description: "Updated postconditions.",
              },
              steps: {
                type: "array",
                description:
                  "Updated test steps array. For Classic format: action, expectedResult, and optional data. For Gherkin format: event and stepDescription. Each top-level step can include attachments as URLs or local file paths.",
                items: {
                  type: "object",
                  oneOf: [
                    {
                      properties: {
                        action: {
                          type: "string",
                          description:
                            "The action to perform in this step (Classic format).",
                        },
                        expectedResult: {
                          type: "string",
                          description:
                            "The expected outcome of this action (Classic format).",
                        },
                        data: {
                          type: "string",
                          description:
                            "Optional test data for this step (Classic format).",
                        },
                        attachments: {
                          type: "array",
                          description:
                            "Optional top-level step attachments as URLs or local file paths.",
                          items: { type: "string" },
                        },
                      },
                      required: ["action", "expectedResult"],
                    },
                    {
                      properties: {
                        event: {
                          type: "string",
                          enum: ["Given", "When", "And", "Then", "But"],
                        },
                        stepDescription: { type: "string" },
                        attachments: {
                          type: "array",
                          description:
                            "Optional top-level step attachments as URLs or local file paths.",
                          items: { type: "string" },
                        },
                      },
                      required: ["event", "stepDescription"],
                    },
                  ],
                },
              },
              priority: {
                type: "string",
                description: "Updated priority.",
                enum: ["high", "medium", "low", "Not set"],
              },
              severity: {
                type: "string",
                description: "Updated severity.",
                enum: [
                  "Blocker",
                  "critical",
                  "major",
                  "Normal",
                  "minor",
                  "trivial",
                  "Not set",
                ],
              },
              type: {
                type: "string",
                description: "Updated type.",
                enum: [
                  "functional",
                  "smoke",
                  "regression",
                  "security",
                  "performance",
                  "e2e",
                  "Integration",
                  "API",
                  "Unit",
                  "Accessability",
                  "Compatibility",
                  "Acceptance",
                  "Exploratory",
                  "Usability",
                  "Other",
                ],
              },
              layer: {
                type: "string",
                description: "Updated layer.",
                enum: ["e2e", "api", "unit", "not set"],
              },
              behavior: {
                type: "string",
                description: "Updated behavior.",
                enum: ["positive", "negative", "destructive", "Not set"],
              },
              automationStatus: {
                type: "string",
                description: "Updated automation status.",
                enum: ["Manual", "Automated", "To be automated"],
              },
              tags: {
                type: "string",
                description: "Updated tags.",
              },
              flags: {
                type: "array",
                description: "Updated automation flags/checklist options.",
                items: {
                  type: "string",
                  enum: ["To be Automated", "Is flaky", "Muted"],
                },
              },
              attachments: {
                type: "object",
                description: "Add or remove attachments (up to 10MB each).",
                properties: {
                  add: {
                    type: "array",
                    description: "Array of attachment URLs or file paths to add.",
                    items: { type: "string" },
                  },
                  remove: {
                    type: "array",
                    description: "Array of attachment IDs or URLs to remove.",
                    items: { type: "string" },
                  },
                },
              },
              customFields: {
                type: "object",
                description:
                  "Updated custom fields as key-value pairs. Only available if custom fields are configured in test case management settings.",
                additionalProperties: {
                  type: "string",
                },
              },
              comments: {
                type: "array",
                description:
                  "Array of comment bodies to append to the test case. Each string becomes a new comment with the PAT owner as the author. The server enforces a cap of 20 comments per case; entries past the cap are rejected.",
                items: { type: "string" },
              },
              issues: {
                type: "array",
                description:
                  "Array of Jira ticket keys to link to the test case (e.g. ['PROJ-123', 'ENG-45']). The server resolves each key against the project's connected Jira: tickets that are found are saved with title and URL; tickets that aren't found (or if no Jira is connected) are saved as plain text stubs — same fallback as the UI's add-issue flow. Duplicate links for the same ticket are silently skipped.",
                items: { type: "string" },
              },
            },
          },
        },
        required: ["projectId", "caseId", "updates"],
      },
    };
  • src/index.ts:100-130 (registration)
    The tool object 'updateManualTestCaseTool' is included in the tools array (line 110) passed to the MCP server for tool listing.
      healthTool,
      listTestRunsTool,
      getRunDetailsTool,
      listTestCasesTool,
      getTestCaseDetailsTool,
      debugTestCaseTool,
      testAuditTool,
      listManualTestCasesTool,
      getManualTestCaseTool,
      createManualTestCaseTool,
      updateManualTestCaseTool,
      listManualTestSuitesTool,
      createManualTestSuiteTool,
      // Releases
      listReleasesTool,
      getReleaseTool,
      createReleaseTool,
      updateReleaseTool,
      // Manual runs
      listManualRunsTool,
      getManualRunTool,
      createManualRunTool,
      updateManualRunTool,
      listRunTestCasesTool,
      updateRunTestCaseTool,
      // Sessions
      listSessionsTool,
      getSessionTool,
      createSessionTool,
      updateSessionTool,
    ];
  • src/index.ts:255-259 (registration)
    Routing in CallToolRequestSchema handler: when name === 'update_manual_test_case', calls handleUpdateManualTestCase with the args.
    if (name === "update_manual_test_case") {
      return await handleUpdateManualTestCase(
        args as Parameters<typeof handleUpdateManualTestCase>[0]
      );
    }
  • Endpoint helper function 'updateManualTestCase' that builds the URL for the PATCH /api/mcp/manual-tests/:projectId/test-cases/:caseId API call.
    /**
     * Update manual test case
     * PATCH /api/mcp/manual-tests/:projectId/test-cases/:caseId
     */
    updateManualTestCase: (projectId: string, caseId: string): string => {
      const baseUrl = getBaseUrl();
      return `${baseUrl}/api/mcp/manual-tests/${projectId}/test-cases/${caseId}`;
    },
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full responsibility. It discloses behavioral traits: comments are appended, PAT owner is author, Jira linking has fallback behavior, and duplicate issues are skipped. It does not explicitly state whether non-updated fields remain unchanged, but this is implied.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single paragraph but front-loads the purpose. It is concise enough, though slightly longer than necessary. Could benefit from bullet points for readability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of the tool (nested updates object) and absence of output schema, the description covers the main input behaviors well. It does not mention error handling or permissions, but for a typical update operation this is sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description adds significant meaning beyond the schema for the 'comments' and 'issues' parameters, explaining their behavior in detail. This goes beyond a baseline of 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Update an existing manual test case' and lists the types of fields that can be modified. It distinguishes from sibling tools like 'create_manual_test_case' by focusing on modification rather than creation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear instructions: 'Provide only the fields you want to update in the updates object' and explains how to add comments and link Jira issues. However, it does not explicitly state when not to use this tool or compare it with other update tools like 'update_manual_run'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/testdino-hq/testdino-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server