Skip to main content
Glama
OctopusDeploy

Octopus Deploy MCP Server

Official

Create a new release in Octopus Deploy

create_release

Create a new release for a project in Octopus Deploy. Requires space name and project name; optional parameters allow customizing version, channel, packages, and release notes.

Instructions

Create a new release for an Octopus Deploy project

This tool creates a new release for a project. The space name and project name are required. All other parameters are optional and will use Octopus defaults if not specified.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
spaceNameYesThe space name
projectNameYesThe project name
releaseVersionNoThe version for the release (e.g., '1.0.0'). If not specified, Octopus will auto-generate based on project settings.
channelNameNoThe channel name (uses default channel if not specified)
packageVersionNoDefault package version to use for all packages
packagesNoArray of package specifications (format depends on Octopus configuration)
gitCommitNoGit commit hash
gitRefNoGit reference (branch or tag)
releaseNotesNoRelease notes for this release
ignoreIfAlreadyExistsNoIf true, skip creation if release already exists (returns existing release)
ignoreChannelRulesNoIf true, ignore channel version rules
packagePrereleaseNoPackage prerelease tag
customFieldsNoCustom field values as key-value pairs
confirmNoRequired only when the MCP client does not support elicitation. Set to true to confirm release creation; otherwise the tool aborts.

Implementation Reference

  • The main handler function for the create_release tool. Registers the tool with the MCP server, defines the input schema (spaceName, projectName, releaseVersion, channelName, packageVersion, packages, gitCommit, gitRef, releaseNotes, ignoreIfAlreadyExists, ignoreChannelRules, packagePrerelease, customFields, confirm), builds the command payload, requests user confirmation, creates the release via ReleaseRepository.create(), fetches the persisted release to return resolved SelectedPackages and VersionControlReference, and returns the result.
    export function registerCreateReleaseTool(server: McpServer) {
      server.registerTool(
        "create_release",
        {
          title: "Create a new release in Octopus Deploy",
          description: `Create a new release for an Octopus Deploy project
    
    This tool creates a new release for a project. The space name and project name are required. All other parameters are optional and will use Octopus defaults if not specified.`,
          inputSchema: {
            spaceName: z.string().describe("The space name"),
            projectName: z.string().describe("The project name"),
            releaseVersion: z
              .string()
              .optional()
              .describe(
                "The version for the release (e.g., '1.0.0'). If not specified, Octopus will auto-generate based on project settings.",
              ),
            channelName: z
              .string()
              .optional()
              .describe("The channel name (uses default channel if not specified)"),
            packageVersion: z
              .string()
              .optional()
              .describe("Default package version to use for all packages"),
            packages: z
              .array(z.string())
              .optional()
              .describe(
                "Array of package specifications (format depends on Octopus configuration)",
              ),
            gitCommit: z.string().optional().describe("Git commit hash"),
            gitRef: z.string().optional().describe("Git reference (branch or tag)"),
            releaseNotes: z
              .string()
              .optional()
              .describe("Release notes for this release"),
            ignoreIfAlreadyExists: z
              .boolean()
              .optional()
              .describe(
                "If true, skip creation if release already exists (returns existing release)",
              ),
            ignoreChannelRules: z
              .boolean()
              .optional()
              .describe("If true, ignore channel version rules"),
            packagePrerelease: z
              .string()
              .optional()
              .describe("Package prerelease tag"),
            customFields: z
              .record(z.string())
              .optional()
              .describe("Custom field values as key-value pairs"),
            confirm: z
              .boolean()
              .optional()
              .describe(
                "Required only when the MCP client does not support elicitation. Set to true to confirm release creation; otherwise the tool aborts.",
              ),
          },
          annotations: ADDITIVE_WRITE_TOOL_ANNOTATIONS,
        },
        async ({
          spaceName,
          projectName,
          releaseVersion,
          channelName,
          packageVersion,
          packages,
          gitCommit,
          gitRef,
          releaseNotes,
          ignoreIfAlreadyExists,
          ignoreChannelRules,
          packagePrerelease,
          customFields,
          confirm,
        }) => {
          try {
            const summary = [
              `Create release for project ${projectName}`,
              releaseVersion ? `version ${releaseVersion}` : null,
              channelName ? `on channel ${channelName}` : null,
              gitRef ? `from ${gitRef}` : null,
              `in space ${spaceName}`,
            ]
              .filter(Boolean)
              .join(" ");
    
            const command = {
              spaceName: spaceName,
              ProjectName: projectName,
              ...(releaseVersion && { ReleaseVersion: releaseVersion }),
              ...(channelName && { ChannelName: channelName }),
              ...(packageVersion && { PackageVersion: packageVersion }),
              ...(packages && { Packages: packages }),
              ...(gitCommit && { GitCommit: gitCommit }),
              ...(gitRef && { GitRef: gitRef }),
              ...(releaseNotes && { ReleaseNotes: releaseNotes }),
              ...(ignoreIfAlreadyExists !== undefined && {
                IgnoreIfAlreadyExists: ignoreIfAlreadyExists,
              }),
              ...(ignoreChannelRules !== undefined && {
                IgnoreChannelRules: ignoreChannelRules,
              }),
              ...(packagePrerelease && { PackagePrerelease: packagePrerelease }),
              ...(customFields && { CustomFields: customFields }),
            };
    
            const confirmation = await requireConfirmation(server, {
              message: `${summary}?`,
              fallbackConfirm: confirm,
              change: { source: {}, target: command },
            });
            if (!confirmation.confirmed) {
              return unconfirmedResponse(confirmation, {
                action: "release creation",
              });
            }
    
            const configuration = getClientConfigurationFromEnvironment();
            const client = await Client.create(configuration);
            const releaseRepository = new ReleaseRepository(client, spaceName);
    
            const response = await releaseRepository.create(command);
    
            // Fetch the persisted Release so we can echo VersionControlReference and
            // the resolved SelectedPackages. The create response only carries the
            // ReleaseId/ReleaseVersion; SelectedPackages comes from the resolved
            // release body and is the single most useful field for the caller to
            // confirm version-template / channel-rule resolution without a second
            // round trip.
            let versionControlReference:
              | { GitRef?: string; GitCommit?: string }
              | undefined;
            let selectedPackages: SelectedPackage[] | undefined;
            try {
              const release = await releaseRepository.get(response.ReleaseId);
              versionControlReference = release.VersionControlReference;
              selectedPackages = release.SelectedPackages;
            } catch {
              versionControlReference = undefined;
              selectedPackages = undefined;
            }
    
            const encodedSpace = encodeURIComponent(spaceName);
            const encodedId = encodeURIComponent(response.ReleaseId);
            const resourceUri = `octopus://spaces/${encodedSpace}/releases/${encodedId}`;
    
            return {
              content: [
                {
                  type: "text",
                  text: JSON.stringify(
                    {
                      success: true,
                      releaseId: response.ReleaseId,
                      releaseVersion: response.ReleaseVersion,
                      versionControlReference,
                      selectedPackages,
                      resourceUri,
                      message: `Release ${response.ReleaseVersion} created successfully`,
                      helpText:
                        "selectedPackages shows the resolved package versions bound to this release. Read resourceUri for the full release body (includes releaseNotes). Use deploy_release to deploy this release to environments.",
                    },
                    null,
                    2,
                  ),
                },
              ],
            };
          } catch (error) {
            handleOctopusApiError(error, {
              entityType: "release",
              spaceName,
              helpText:
                "Use list_projects to find valid project names. Ensure you have permissions to create releases and that the project exists.",
            });
          }
        },
      );
    }
  • Zod input schema defining all parameters for the create_release tool: spaceName and projectName are required; releaseVersion, channelName, packageVersion, packages, gitCommit, gitRef, releaseNotes, ignoreIfAlreadyExists, ignoreChannelRules, packagePrerelease, customFields, and confirm are optional.
    inputSchema: {
      spaceName: z.string().describe("The space name"),
      projectName: z.string().describe("The project name"),
      releaseVersion: z
        .string()
        .optional()
        .describe(
          "The version for the release (e.g., '1.0.0'). If not specified, Octopus will auto-generate based on project settings.",
        ),
      channelName: z
        .string()
        .optional()
        .describe("The channel name (uses default channel if not specified)"),
      packageVersion: z
        .string()
        .optional()
        .describe("Default package version to use for all packages"),
      packages: z
        .array(z.string())
        .optional()
        .describe(
          "Array of package specifications (format depends on Octopus configuration)",
        ),
      gitCommit: z.string().optional().describe("Git commit hash"),
      gitRef: z.string().optional().describe("Git reference (branch or tag)"),
      releaseNotes: z
        .string()
        .optional()
        .describe("Release notes for this release"),
      ignoreIfAlreadyExists: z
        .boolean()
        .optional()
        .describe(
          "If true, skip creation if release already exists (returns existing release)",
        ),
      ignoreChannelRules: z
        .boolean()
        .optional()
        .describe("If true, ignore channel version rules"),
      packagePrerelease: z
        .string()
        .optional()
        .describe("Package prerelease tag"),
      customFields: z
        .record(z.string())
        .optional()
        .describe("Custom field values as key-value pairs"),
      confirm: z
        .boolean()
        .optional()
        .describe(
          "Required only when the MCP client does not support elicitation. Set to true to confirm release creation; otherwise the tool aborts.",
        ),
    },
  • Self-registration of the create_release tool via registerToolDefinition. Classified under the 'releases' toolset, marked as readOnly: false (write operation), and requires Octopus server version 2022.3.5512 or later.
    registerToolDefinition({
      toolName: "create_release",
      config: { toolset: "releases", readOnly: false },
      registerFn: registerCreateReleaseTool,
      // ReleaseRepository.create uses the Executions API (~/api/{space}/releases/create/v1)
      // which the api-client refuses to call against servers older than 2022.3.5512.
      minimumOctopusVersion: "2022.3.5512",
    });
  • Import of the createRelease module in the tools index, which triggers its self-registration when loaded.
    import "./createRelease.js";
  • Helper that builds the Octopus API client configuration from environment variables (OCTOPUS_SERVER_URL, OCTOPUS_API_KEY, OCTOPUS_ACCESS_TOKEN), used by the create_release handler to create the API client.
    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"],
      });
    }
Behavior3/5

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

Annotations indicate the tool is not read-only and not destructive, which is consistent with creating a release. The description adds that optional parameters use defaults. However, it omits key behavioral traits like the confirm parameter that controls creation behavior and potential failure modes (e.g., duplicate releases).

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?

The description is two concise sentences that front-load the purpose and then provide essential guidance on required/optional parameters. Every sentence is necessary and no information is wasted.

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

Completeness2/5

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

Given the tool has 14 parameters and no output schema, the description is too brief. It fails to mention critical aspects like the confirm parameter's role in preventing accidental creation, potential error scenarios, or what the tool returns (e.g., a release object). This leaves the agent without enough behavioral context.

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%, so each parameter is well-described in the schema. The description adds value by explicitly grouping required vs optional parameters and noting default behavior, which helps agents parse param importance.

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 tool creates a release for a specific project, using strong verb+resource phrasing. It distinguishes itself from sibling tools like deploy_release (deploy vs create) and find_releases (find vs create).

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

Usage Guidelines3/5

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

The description notes that spaceName and projectName are required and other parameters are optional with defaults, but it does not provide explicit guidance on when to use this tool versus alternatives (e.g., deploy_release) or when not to use it. More specific context would improve agent decision-making.

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