Skip to main content
Glama
OctopusDeploy

Octopus Deploy MCP Server

Official

Deploy a release to environments in Octopus Deploy

deploy_release
Destructive

Deploy a release to single or multiple environments in Octopus Deploy. Supports both tenanted and untenanted deployments with configurable options.

Instructions

Deploy a release to one or more environments in Octopus Deploy

This tool supports both tenanted and untenanted deployments:

  • Untenanted: Don't provide tenants or tenantTags. Can deploy to multiple environments at once.

  • Tenanted: Provide tenants or tenantTags. Can only deploy to ONE environment, but can target multiple tenants.

The tool automatically determines which deployment type to use based on the parameters provided.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
spaceNameYesThe space name
projectNameYesThe project name
releaseVersionYesThe release version to deploy (e.g., '1.0.0')
environmentNamesYesArray of environment names. For tenanted deployments, must contain exactly one environment.
tenantsNoArray of tenant names for tenanted deployment (optional)
tenantTagsNoArray of tenant tags for tenanted deployment (e.g., ['Region/US-West', 'Tier/Production'])
forcePackageRedeploymentNoForce redeployment of packages
updateVariableSnapshotNoUpdate the variable snapshot
forcePackageDownloadNoForce package download
specificMachineNamesNoDeploy to specific machines only
excludedMachineNamesNoExclude specific machines from deployment
skipStepNamesNoSkip specific deployment steps
useGuidedFailureNoUse guided failure mode
runAtNoSchedule deployment for later (ISO 8601 date string)
noRunAfterNoDon't run deployment after this time (ISO 8601 date string)
variablesNoPrompted variable values as key-value pairs
deploymentFreezeOverrideReasonNoReason for overriding deployment freeze
deploymentFreezeNamesNoNames of deployment freezes to override
confirmNoRequired only when the MCP client does not support elicitation. Set to true to confirm deployment; otherwise the tool aborts.

Implementation Reference

  • The main tool handler function that executes the deploy_release logic. It validates inputs (tenanted vs untenanted), builds the deployment command, requires user confirmation, creates the Octopus API client, and performs the deployment via DeploymentRepository.create() or .createTenanted(). Returns deployment task details including URIs for monitoring.
        async ({
          spaceName,
          projectName,
          releaseVersion,
          environmentNames,
          tenants,
          tenantTags,
          forcePackageRedeployment,
          updateVariableSnapshot,
          forcePackageDownload,
          specificMachineNames,
          excludedMachineNames,
          skipStepNames,
          useGuidedFailure,
          runAt,
          noRunAfter,
          variables,
          deploymentFreezeOverrideReason,
          deploymentFreezeNames,
          confirm,
        }) => {
          try {
            // Validate environment names
            if (!environmentNames || environmentNames.length === 0) {
              throw new Error("At least one environment name must be provided.");
            }
    
            // Determine if this is a tenanted deployment
            const isTenanted =
              (tenants && tenants.length > 0) ||
              (tenantTags && tenantTags.length > 0);
    
            // Validate tenanted deployment constraints
            if (isTenanted && environmentNames.length !== 1) {
              throw new Error(
                `Tenanted deployments can only target one environment at a time. You provided ${environmentNames.length} environments. ` +
                  `For tenanted deployments, specify exactly one environment in environmentNames, then use tenants or tenantTags to target specific tenants.`,
              );
            }
    
            const tenantSummary = isTenanted
              ? ` for tenants [${(tenants ?? []).join(", ")}${
                  tenantTags?.length ? `; tags: ${tenantTags.join(", ")}` : ""
                }]`
              : "";
            const confirmMessage =
              `Deploy release ${releaseVersion} of ${projectName} to ` +
              `[${environmentNames.join(", ")}]${tenantSummary} in space ${spaceName}?`;
    
            // Build common parameters
            const commonParams = {
              spaceName: spaceName,
              ProjectName: projectName,
              ...(forcePackageRedeployment !== undefined && {
                ForcePackageRedeployment: forcePackageRedeployment,
              }),
              ...(updateVariableSnapshot !== undefined && {
                UpdateVariableSnapshot: updateVariableSnapshot,
              }),
              ...(forcePackageDownload !== undefined && {
                ForcePackageDownload: forcePackageDownload,
              }),
              ...(specificMachineNames && {
                SpecificMachineNames: specificMachineNames,
              }),
              ...(excludedMachineNames && {
                ExcludedMachineNames: excludedMachineNames,
              }),
              ...(skipStepNames && { SkipStepNames: skipStepNames }),
              ...(useGuidedFailure !== undefined && {
                UseGuidedFailure: useGuidedFailure,
              }),
              ...(runAt && { RunAt: new Date(runAt) }),
              ...(noRunAfter && { NoRunAfter: new Date(noRunAfter) }),
              ...(variables && { Variables: variables }),
              ...(deploymentFreezeOverrideReason && {
                DeploymentFreezeOverrideReason: deploymentFreezeOverrideReason,
              }),
              ...(deploymentFreezeNames && {
                DeploymentFreezeNames: deploymentFreezeNames,
              }),
            };
    
            const tenantedCommand = {
              ...commonParams,
              ReleaseVersion: releaseVersion,
              EnvironmentName: environmentNames[0],
              Tenants: tenants || [],
              TenantTags: tenantTags || [],
            };
            const untenantedCommand = {
              ...commonParams,
              ReleaseVersion: releaseVersion,
              EnvironmentNames: environmentNames,
            };
    
            const confirmation = await requireConfirmation(server, {
              message: confirmMessage,
              fallbackConfirm: confirm,
              change: {
                source: {},
                target: isTenanted ? tenantedCommand : untenantedCommand,
              },
            });
            if (!confirmation.confirmed) {
              return unconfirmedResponse(confirmation, { action: "deployment" });
            }
    
            const configuration = getClientConfigurationFromEnvironment();
            const client = await Client.create(configuration);
            const deploymentRepository = new DeploymentRepository(
              client,
              spaceName,
            );
    
            const deploymentType = isTenanted ? "tenanted" : "untenanted";
            const response = isTenanted
              ? await deploymentRepository.createTenanted(tenantedCommand)
              : await deploymentRepository.create(untenantedCommand);
    
            // Format the response
            const tasks = response.DeploymentServerTasks || [];
            const encodedSpace = encodeURIComponent(spaceName);
    
            return {
              content: [
                {
                  type: "text",
                  text: JSON.stringify(
                    {
                      success: true,
                      deploymentType,
                      deploymentsCreated: tasks.length,
                      deploymentTasks: tasks.map((task) => ({
                        taskId: task.ServerTaskId,
                        deploymentId: task.DeploymentId,
                        taskResourceUri: `octopus://spaces/${encodedSpace}/tasks/${encodeURIComponent(task.ServerTaskId)}/details`,
                      })),
                      message: `Successfully created ${tasks.length} deployment(s) for release ${releaseVersion}`,
                      helpText: `Feed each deploymentTasks[].taskResourceUri into read_resource (or resources/read) to monitor deployment progress via the structured ActivityLogs tree. For the lighter metadata-only view, swap /details off the URI. To search the raw log for a specific error or step, call grep_task_log with the taskId. Use list_deployments for high-level deployment listings.`,
                    },
                    null,
                    2,
                  ),
                },
              ],
            };
          } catch (error) {
            // Handle validation errors from our code
            if (error instanceof Error && !error.message.includes("octopus")) {
              return {
                content: [
                  {
                    type: "text",
                    text: JSON.stringify(
                      {
                        success: false,
                        error: error.message,
                      },
                      null,
                      2,
                    ),
                  },
                ],
                isError: true,
              };
            }
    
            // Handle Octopus API errors
            handleOctopusApiError(error, {
              entityType: "deployment",
              spaceName,
              helpText:
                "Use list_projects to find valid project names, list_environments for environment names, find_releases to verify the release exists, and find_tenants for tenant information. Ensure you have permissions to create deployments.",
            });
          }
        },
      );
    }
  • Zod input schema defining all deploy_release parameters: spaceName, projectName, releaseVersion, environmentNames, tenants, tenantTags, forcePackageRedeployment, updateVariableSnapshot, forcePackageDownload, specificMachineNames, excludedMachineNames, skipStepNames, useGuidedFailure, runAt, noRunAfter, variables, deploymentFreezeOverrideReason, deploymentFreezeNames, and confirm.
    inputSchema: {
      spaceName: z.string().describe("The space name"),
      projectName: z.string().describe("The project name"),
      releaseVersion: z
        .string()
        .describe("The release version to deploy (e.g., '1.0.0')"),
      environmentNames: z
        .array(z.string())
        .describe(
          "Array of environment names. For tenanted deployments, must contain exactly one environment.",
        ),
      tenants: z
        .array(z.string())
        .optional()
        .describe("Array of tenant names for tenanted deployment (optional)"),
      tenantTags: z
        .array(z.string())
        .optional()
        .describe(
          "Array of tenant tags for tenanted deployment (e.g., ['Region/US-West', 'Tier/Production'])",
        ),
      forcePackageRedeployment: z
        .boolean()
        .optional()
        .describe("Force redeployment of packages"),
      updateVariableSnapshot: z
        .boolean()
        .optional()
        .describe("Update the variable snapshot"),
      forcePackageDownload: z
        .boolean()
        .optional()
        .describe("Force package download"),
      specificMachineNames: z
        .array(z.string())
        .optional()
        .describe("Deploy to specific machines only"),
      excludedMachineNames: z
        .array(z.string())
        .optional()
        .describe("Exclude specific machines from deployment"),
      skipStepNames: z
        .array(z.string())
        .optional()
        .describe("Skip specific deployment steps"),
      useGuidedFailure: z
        .boolean()
        .optional()
        .describe("Use guided failure mode"),
      runAt: z
        .string()
        .optional()
        .describe("Schedule deployment for later (ISO 8601 date string)"),
      noRunAfter: z
        .string()
        .optional()
        .describe(
          "Don't run deployment after this time (ISO 8601 date string)",
        ),
      variables: z
        .record(z.string())
        .optional()
        .describe("Prompted variable values as key-value pairs"),
      deploymentFreezeOverrideReason: z
        .string()
        .optional()
        .describe("Reason for overriding deployment freeze"),
      deploymentFreezeNames: z
        .array(z.string())
        .optional()
        .describe("Names of deployment freezes to override"),
      confirm: z
        .boolean()
        .optional()
        .describe(
          "Required only when the MCP client does not support elicitation. Set to true to confirm deployment; otherwise the tool aborts.",
        ),
    },
  • Registration of the deploy_release tool via registerToolDefinition(), setting toolset to 'deployments', readOnly to false, and minimumOctopusVersion to '2022.3.5512'.
    registerToolDefinition({
      toolName: "deploy_release",
      config: { toolset: "deployments", readOnly: false },
      registerFn: registerDeployReleaseTool,
      // DeploymentRepository.create / .createTenanted use the Executions API
      // (~/api/{space}/deployments/create/v1 and /create/tenanted/v1-alpha) which
      // the api-client refuses to call against servers older than 2022.3.5512.
      minimumOctopusVersion: "2022.3.5512",
    });
  • The registerDeployReleaseTool function that registers the tool with the MCP server, including the full input schema and handler callback.
    export function registerDeployReleaseTool(server: McpServer) {
      server.registerTool(
        "deploy_release",
        {
          title: "Deploy a release to environments in Octopus Deploy",
          description: `Deploy a release to one or more environments in Octopus Deploy
    
    This tool supports both tenanted and untenanted deployments:
    - **Untenanted**: Don't provide tenants or tenantTags. Can deploy to multiple environments at once.
    - **Tenanted**: Provide tenants or tenantTags. Can only deploy to ONE environment, but can target multiple tenants.
    
    The tool automatically determines which deployment type to use based on the parameters provided.`,
          inputSchema: {
            spaceName: z.string().describe("The space name"),
            projectName: z.string().describe("The project name"),
            releaseVersion: z
              .string()
              .describe("The release version to deploy (e.g., '1.0.0')"),
            environmentNames: z
              .array(z.string())
              .describe(
                "Array of environment names. For tenanted deployments, must contain exactly one environment.",
              ),
            tenants: z
              .array(z.string())
              .optional()
              .describe("Array of tenant names for tenanted deployment (optional)"),
            tenantTags: z
              .array(z.string())
              .optional()
              .describe(
                "Array of tenant tags for tenanted deployment (e.g., ['Region/US-West', 'Tier/Production'])",
              ),
            forcePackageRedeployment: z
              .boolean()
              .optional()
              .describe("Force redeployment of packages"),
            updateVariableSnapshot: z
              .boolean()
              .optional()
              .describe("Update the variable snapshot"),
            forcePackageDownload: z
              .boolean()
              .optional()
              .describe("Force package download"),
            specificMachineNames: z
              .array(z.string())
              .optional()
              .describe("Deploy to specific machines only"),
            excludedMachineNames: z
              .array(z.string())
              .optional()
              .describe("Exclude specific machines from deployment"),
            skipStepNames: z
              .array(z.string())
              .optional()
              .describe("Skip specific deployment steps"),
            useGuidedFailure: z
              .boolean()
              .optional()
              .describe("Use guided failure mode"),
            runAt: z
              .string()
              .optional()
              .describe("Schedule deployment for later (ISO 8601 date string)"),
            noRunAfter: z
              .string()
              .optional()
              .describe(
                "Don't run deployment after this time (ISO 8601 date string)",
              ),
            variables: z
              .record(z.string())
              .optional()
              .describe("Prompted variable values as key-value pairs"),
            deploymentFreezeOverrideReason: z
              .string()
              .optional()
              .describe("Reason for overriding deployment freeze"),
            deploymentFreezeNames: z
              .array(z.string())
              .optional()
              .describe("Names of deployment freezes to override"),
            confirm: z
              .boolean()
              .optional()
              .describe(
                "Required only when the MCP client does not support elicitation. Set to true to confirm deployment; otherwise the tool aborts.",
              ),
          },
          annotations: DESTRUCTIVE_WRITE_TOOL_ANNOTATIONS,
        },
        async ({
          spaceName,
          projectName,
          releaseVersion,
          environmentNames,
          tenants,
          tenantTags,
          forcePackageRedeployment,
          updateVariableSnapshot,
          forcePackageDownload,
          specificMachineNames,
          excludedMachineNames,
          skipStepNames,
          useGuidedFailure,
          runAt,
          noRunAfter,
          variables,
          deploymentFreezeOverrideReason,
          deploymentFreezeNames,
          confirm,
        }) => {
          try {
            // Validate environment names
            if (!environmentNames || environmentNames.length === 0) {
              throw new Error("At least one environment name must be provided.");
            }
    
            // Determine if this is a tenanted deployment
            const isTenanted =
              (tenants && tenants.length > 0) ||
              (tenantTags && tenantTags.length > 0);
    
            // Validate tenanted deployment constraints
            if (isTenanted && environmentNames.length !== 1) {
              throw new Error(
                `Tenanted deployments can only target one environment at a time. You provided ${environmentNames.length} environments. ` +
                  `For tenanted deployments, specify exactly one environment in environmentNames, then use tenants or tenantTags to target specific tenants.`,
              );
            }
    
            const tenantSummary = isTenanted
              ? ` for tenants [${(tenants ?? []).join(", ")}${
                  tenantTags?.length ? `; tags: ${tenantTags.join(", ")}` : ""
                }]`
              : "";
            const confirmMessage =
              `Deploy release ${releaseVersion} of ${projectName} to ` +
              `[${environmentNames.join(", ")}]${tenantSummary} in space ${spaceName}?`;
    
            // Build common parameters
            const commonParams = {
              spaceName: spaceName,
              ProjectName: projectName,
              ...(forcePackageRedeployment !== undefined && {
                ForcePackageRedeployment: forcePackageRedeployment,
              }),
              ...(updateVariableSnapshot !== undefined && {
                UpdateVariableSnapshot: updateVariableSnapshot,
              }),
              ...(forcePackageDownload !== undefined && {
                ForcePackageDownload: forcePackageDownload,
              }),
              ...(specificMachineNames && {
                SpecificMachineNames: specificMachineNames,
              }),
              ...(excludedMachineNames && {
                ExcludedMachineNames: excludedMachineNames,
              }),
              ...(skipStepNames && { SkipStepNames: skipStepNames }),
              ...(useGuidedFailure !== undefined && {
                UseGuidedFailure: useGuidedFailure,
              }),
              ...(runAt && { RunAt: new Date(runAt) }),
              ...(noRunAfter && { NoRunAfter: new Date(noRunAfter) }),
              ...(variables && { Variables: variables }),
              ...(deploymentFreezeOverrideReason && {
                DeploymentFreezeOverrideReason: deploymentFreezeOverrideReason,
              }),
              ...(deploymentFreezeNames && {
                DeploymentFreezeNames: deploymentFreezeNames,
              }),
            };
    
            const tenantedCommand = {
              ...commonParams,
              ReleaseVersion: releaseVersion,
              EnvironmentName: environmentNames[0],
              Tenants: tenants || [],
              TenantTags: tenantTags || [],
            };
            const untenantedCommand = {
              ...commonParams,
              ReleaseVersion: releaseVersion,
              EnvironmentNames: environmentNames,
            };
    
            const confirmation = await requireConfirmation(server, {
              message: confirmMessage,
              fallbackConfirm: confirm,
              change: {
                source: {},
                target: isTenanted ? tenantedCommand : untenantedCommand,
              },
            });
            if (!confirmation.confirmed) {
              return unconfirmedResponse(confirmation, { action: "deployment" });
            }
    
            const configuration = getClientConfigurationFromEnvironment();
            const client = await Client.create(configuration);
            const deploymentRepository = new DeploymentRepository(
              client,
              spaceName,
            );
    
            const deploymentType = isTenanted ? "tenanted" : "untenanted";
            const response = isTenanted
              ? await deploymentRepository.createTenanted(tenantedCommand)
              : await deploymentRepository.create(untenantedCommand);
    
            // Format the response
            const tasks = response.DeploymentServerTasks || [];
            const encodedSpace = encodeURIComponent(spaceName);
    
            return {
              content: [
                {
                  type: "text",
                  text: JSON.stringify(
                    {
                      success: true,
                      deploymentType,
                      deploymentsCreated: tasks.length,
                      deploymentTasks: tasks.map((task) => ({
                        taskId: task.ServerTaskId,
                        deploymentId: task.DeploymentId,
                        taskResourceUri: `octopus://spaces/${encodedSpace}/tasks/${encodeURIComponent(task.ServerTaskId)}/details`,
                      })),
                      message: `Successfully created ${tasks.length} deployment(s) for release ${releaseVersion}`,
                      helpText: `Feed each deploymentTasks[].taskResourceUri into read_resource (or resources/read) to monitor deployment progress via the structured ActivityLogs tree. For the lighter metadata-only view, swap /details off the URI. To search the raw log for a specific error or step, call grep_task_log with the taskId. Use list_deployments for high-level deployment listings.`,
                    },
                    null,
                    2,
                  ),
                },
              ],
            };
          } catch (error) {
            // Handle validation errors from our code
            if (error instanceof Error && !error.message.includes("octopus")) {
              return {
                content: [
                  {
                    type: "text",
                    text: JSON.stringify(
                      {
                        success: false,
                        error: error.message,
                      },
                      null,
                      2,
                    ),
                  },
                ],
                isError: true,
              };
            }
    
            // Handle Octopus API errors
            handleOctopusApiError(error, {
              entityType: "deployment",
              spaceName,
              helpText:
                "Use list_projects to find valid project names, list_environments for environment names, find_releases to verify the release exists, and find_tenants for tenant information. Ensure you have permissions to create deployments.",
            });
          }
        },
      );
    }
  • Helper used by the handler to build the Octopus API client configuration from environment variables (OCTOPUS_SERVER_URL, OCTOPUS_API_KEY, OCTOPUS_ACCESS_TOKEN).
    export function getClientConfigurationFromEnvironment(): ClientConfiguration {
      return getClientConfiguration({
        instanceURL: env["CLI_SERVER_URL"] || env["OCTOPUS_SERVER_URL"],
        apiKey: env["OCTOPUS_API_KEY"],
        accessToken: env["OCTOPUS_ACCESS_TOKEN"],
      });
    }
  • Helper used by the handler to gate destructive operations behind user confirmation, supporting both native MCP elicitation and a fallback confirm parameter.
    export async function requireConfirmation(
      server: McpServer,
      opts: RequireConfirmationOptions,
    ): Promise<ConfirmationResult> {
      if (env["OCTOPUS_SKIP_ELICITATION"] === "true") {
        return { confirmed: true, reason: "envSkip" };
      }
    
      const capabilities = server.server.getClientCapabilities();
      if (capabilities?.elicitation) {
        const result = await server.server.elicitInput({
          mode: "form",
          message: buildConfirmationMessage(opts.message, opts.change),
          // Empty properties → most clients render as a plain Accept/Decline prompt.
          requestedSchema: { type: "object", properties: {} },
        });
        switch (result.action) {
          case "accept":
            return { confirmed: true, reason: "accepted" };
          case "decline":
            return { confirmed: false, reason: "declined" };
          case "cancel":
          default:
            return { confirmed: false, reason: "cancelled" };
        }
      }
    
      if (opts.fallbackConfirm === true) {
        return { confirmed: true, reason: "fallbackConfirm" };
      }
      if (opts.fallbackConfirm === false) {
        return { confirmed: false, reason: "declined" };
      }
      return { confirmed: false, reason: "confirmationRequired" };
    }
  • Helper used by the handler to format Octopus API errors with actionable messages for authentication, connection, and 404 issues.
    export function handleOctopusApiError(
      error: unknown,
      context: {
        entityType?: string;
        entityId?: string;
        spaceName?: string;
        helpText?: string;
      },
    ): never {
      const { entityType, entityId, spaceName, helpText } = context;
    
      // Handle 404/not found errors
      if (
        isErrorWithMessage(error, "not found") ||
        isErrorWithMessage(error, "404")
      ) {
        if (entityType && entityId && spaceName) {
          throw new Error(
            `${entityType.charAt(0).toUpperCase() + entityType.slice(1)} '${entityId}' not found in space '${spaceName}'. ` +
              (helpText ||
                `Verify the ${entityType} ID is correct using list_${entityType}s.`),
          );
        }
        if (spaceName) {
          throw new Error(
            `Space '${spaceName}' not found. Use list_spaces to see available spaces. Space names are case-sensitive.`,
          );
        }
      }
    
      // Handle authentication errors
      if (
        isErrorWithMessage(error, "authentication") ||
        isErrorWithMessage(error, "401") ||
        isErrorWithMessage(
          error,
          "You must be logged in to request this resource",
        ) ||
        isErrorWithMessage(error, "provide a valid API key")
      ) {
        throw new Error(
          "Authentication failed. Ensure a valid API key (OCTOPUS_API_KEY) or access token (OCTOPUS_ACCESS_TOKEN) is provided. " +
            "You can generate an API key from your Octopus Deploy user profile.",
        );
      }
    
      // Handle connection errors
      if (
        isErrorWithMessage(error, "connect") ||
        isErrorWithMessage(error, "timeout")
      ) {
        throw new Error(
          "Cannot connect to Octopus Deploy instance. Check that OCTOPUS_SERVER_URL environment variable is set correctly " +
            "(e.g., 'https://your-instance.octopus.app') and that the instance is accessible.",
        );
      }
    
      // Re-throw the original error if no specific handling applies
      throw error;
    }
Behavior3/5

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

Adds behavioral detail on tenanted/untenanted logic beyond annotations, which already indicate destructive hint true. However, it does not describe the result of the operation (e.g., what is returned), nor side effects like creating a deployment task.

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

Conciseness5/5

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

Efficiently structured with front-loaded purpose, followed by clear bullet points. Every sentence adds value without redundancy.

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 (19 parameters, tenanted/untenanted modes) and lack of output schema, the description covers the key decision points well. Missing explanation of return value, but that is partially compensated by the schema descriptions.

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

Parameters3/5

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

Schema coverage is 100% so baseline is 3. The description reinforces the interplay between environmentNames and tenants but adds minimal new meaning beyond the schema.

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 the verb 'deploy' and resource 'release', and distinguishes between tenanted and untenanted deployments. It is specific and contrasts with siblings like create_release and run_runbook.

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?

Provides explicit guidance on when to use tenanted vs untenanted modes with conditions on tenant parameters. However, it does not explicitly differentiate from alternative tools (e.g., when to use deploy_release vs run_runbook), but the context is clear enough.

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/OctopusDeploy/mcp-server'

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