Skip to main content
Glama
OctopusDeploy

Octopus Deploy MCP Server

Official

Find releases

find_releases
Read-onlyIdempotent

Find releases in Octopus Deploy by release ID, project ID, or across the space. Each summary includes a resource URI for full release details.

Instructions

Find releases in an Octopus Deploy space.

Three modes, picked by which arguments are supplied:

  • releaseId → fetch the summary for that release.

  • projectId → list releases for that project (optionally filtered by searchByVersion).

  • neither → list releases across the space.

Each summary includes a resourceUri for fetching the full release body (release notes, packages, build information, custom fields).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
spaceNameYesSpace name.
releaseIdNoFetch a single release by ID. Mutually exclusive with projectId and searchByVersion.
projectIdNoRestrict listing to a single project. Mutually exclusive with releaseId.
searchByVersionNoFilter by version string. Requires projectId.
skipNoPagination offset.
takeNoPagination page size.

Implementation Reference

  • Main handler function that registers and implements the 'find_releases' tool. Supports three modes: fetch by releaseId, list by projectId (optionally filtered by searchByVersion), or list all releases in a space. Returns slim release summaries with a resourceUri for fetching full release details.
    export function registerFindReleasesTool(server: McpServer) {
      server.registerTool(
        "find_releases",
        {
          title: "Find releases",
          description: `Find releases in an Octopus Deploy space.
    
      Three modes, picked by which arguments are supplied:
      - releaseId  → fetch the summary for that release.
      - projectId  → list releases for that project (optionally filtered by searchByVersion).
      - neither    → list releases across the space.
    
      Each summary includes a resourceUri for fetching the full release body
      (release notes, packages, build information, custom fields).`,
          inputSchema: findReleasesInputSchema,
          annotations: READ_ONLY_TOOL_ANNOTATIONS,
        },
        async (args) => {
          const parsed = findReleasesValidationSchema.safeParse(args);
          if (!parsed.success) return zodErrorResponse(parsed.error);
          const { spaceName, releaseId, projectId, searchByVersion, skip, take } =
            parsed.data;
          const client = await Client.create(getClientConfigurationFromEnvironment());
          const releaseRepository = new ReleaseRepository(client, spaceName);
    
          if (releaseId) {
            validateEntityId(releaseId, "release", ENTITY_PREFIXES.release);
    
            try {
              const release = await releaseRepository.get(releaseId);
              return {
                content: [
                  {
                    type: "text",
                    text: JSON.stringify(releaseSummary(release, spaceName)),
                  },
                ],
              };
            } catch (error) {
              handleOctopusApiError(error, {
                entityType: "release",
                entityId: releaseId,
                spaceName,
                helpText: "Call find_releases without releaseId to list valid IDs.",
              });
            }
          }
    
          const releasesResponse = projectId
            ? await releaseRepository.listForProject(projectId, {
                skip,
                take,
                searchByVersion,
              })
            : await releaseRepository.list({ skip, take });
    
          return {
            content: [
              {
                type: "text",
                text: JSON.stringify({
                  totalResults: releasesResponse.TotalResults,
                  itemsPerPage: releasesResponse.ItemsPerPage,
                  numberOfPages: releasesResponse.NumberOfPages,
                  lastPageNumber: releasesResponse.LastPageNumber,
                  items: releasesResponse.Items.map((release) =>
                    releaseSummary(release, spaceName),
                  ),
                }),
              },
            ],
          };
        },
      );
    }
  • Input schema definition for find_releases tool. Defines five optional/mandatory fields: spaceName (required), releaseId, projectId, searchByVersion, skip, take.
    const findReleasesRawShape = {
      spaceName: z.string().describe("Space name."),
      releaseId: z
        .string()
        .optional()
        .describe(
          "Fetch a single release by ID. Mutually exclusive with projectId and searchByVersion.",
        ),
      projectId: z
        .string()
        .optional()
        .describe("Restrict listing to a single project. Mutually exclusive with releaseId."),
      searchByVersion: z
        .string()
        .optional()
        .describe("Filter by version string. Requires projectId."),
      skip: z.number().optional().describe("Pagination offset."),
      take: z.number().optional().describe("Pagination page size."),
    };
  • Validation schema with superRefine logic: enforces mutual exclusivity of releaseId and projectId, requires projectId when searchByVersion is used, and prevents combining releaseId with searchByVersion.
    export const findReleasesValidationSchema = findReleasesInputSchema.superRefine(
      (args, ctx) => {
        if (args.releaseId && args.projectId) {
          ctx.addIssue({
            code: z.ZodIssueCode.custom,
            message:
              "Provide either releaseId or projectId, not both. Use releaseId to fetch a single release; use projectId to list releases for a project.",
            path: ["projectId"],
          });
        }
        if (args.searchByVersion && !args.projectId) {
          ctx.addIssue({
            code: z.ZodIssueCode.custom,
            message: "searchByVersion requires projectId.",
            path: ["searchByVersion"],
          });
        }
        if (args.releaseId && args.searchByVersion) {
          ctx.addIssue({
            code: z.ZodIssueCode.custom,
            message:
              "searchByVersion is only valid when listing releases for a project; it cannot be combined with releaseId.",
            path: ["searchByVersion"],
          });
        }
      },
    );
  • Tool registration directing find_releases into the 'releases' toolset as a read-only tool.
    registerToolDefinition({
      toolName: "find_releases",
      config: { toolset: "releases", readOnly: true },
      registerFn: registerFindReleasesTool,
    });
  • Helper function that creates a slim release summary, omitting heavy fields like releaseNotes, selectedPackages, etc. Includes a resourceUri for fetching the full release body.
    function releaseSummary(release: Release, spaceName: string) {
      const encodedSpace = encodeURIComponent(spaceName);
      const encodedId = encodeURIComponent(release.Id);
    
      return {
        id: release.Id,
        version: release.Version,
        channelId: release.ChannelId,
        projectId: release.ProjectId,
        assembled: release.Assembled,
        ignoreChannelRules: release.IgnoreChannelRules,
        versionControlReference: release.VersionControlReference,
        resourceUri: `octopus://spaces/${encodedSpace}/releases/${encodedId}`,
      };
    }
Behavior4/5

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

Annotations already mark as read-only and idempotent. Description adds context about returning summaries with a resourceUri for full body, and explains mode selection logic. No contradiction with annotations.

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?

Concise, front-loaded with main purpose, uses bullet points for modes. No wasted words. Each sentence adds value.

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?

Covers modes, summary vs full body, and pagination parameters are in schema. Minor gaps: no mention of ordering or empty results, but sufficient for a read tool with good annotations.

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?

Input schema has 100% description coverage, so baseline is 3. Description provides overall context for modes but does not add significant new semantic detail beyond the schema descriptions (e.g., mutual exclusivity is already in 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?

Clearly states it finds releases in an Octopus Deploy space. Explains three modes (by releaseId, projectId, or neither) which distinguishes it from sibling tools like create_release and deploy_release.

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?

Describes when to use each mode: specific release, project releases, or all releases. Implicitly discourages use for full release body by mentioning resourceUri for that purpose. Could explicitly mention read_resource as an alternative for full details, but still clear.

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