Skip to main content
Glama
OctopusDeploy

Octopus Deploy MCP Server

Official

list_deployment_targets

Read-only

Retrieve deployment targets (machines) within a specified Octopus Deploy space. Filter results by name, roles, health status, or other parameters to identify available infrastructure for deployments.

Instructions

List deployment targets (machines) in a space

This tool lists all deployment targets in a given space. The space name is required. You can optionally filter by various parameters like name, roles, health status, etc.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
spaceNameYes
skipNo
takeNo
nameNo
idsNo
partialNameNo
rolesNoA list of roles / target tags to filter by.
isDisabledNo
healthStatusesNoPossible values: Healthy, Unhealthy, Unavailable, Unknown, HasWarnings
commStylesNo
tenantIdsNo
tenantTagsNo
environmentIdsNo
thumbprintNo
deploymentIdNo
shellNamesNo
deploymentTargetTypesNo

Implementation Reference

  • The handler function that fetches deployment targets from the Octopus Deploy API using the provided filters, maps the response, and returns a JSON-formatted text content.
    async ({
      spaceName,
      skip,
      take,
      name,
      ids,
      partialName,
      roles,
      isDisabled,
      healthStatuses,
      commStyles,
      tenantIds,
      tenantTags,
      environmentIds,
      thumbprint,
      deploymentId,
      shellNames,
      deploymentTargetTypes,
    }) => {
      const configuration = getClientConfigurationFromEnvironment();
      const client = await Client.create(configuration);
      const spaceId = await resolveSpaceId(client, spaceName);
    
      const response = await client.get<ResourceCollection<DeploymentTargetResource>>(
        "~/api/{spaceId}/machines{?skip,take,name,ids,partialName,roles,isDisabled,healthStatuses,commStyles,tenantIds,tenantTags,environmentIds,thumbprint,deploymentId,shellNames,deploymentTargetTypes}",
        {
          spaceId,
          skip,
          take,
          name,
          ids,
          partialName,
          roles,
          isDisabled,
          healthStatuses,
          commStyles,
          tenantIds,
          tenantTags,
          environmentIds,
          thumbprint,
          deploymentId,
          shellNames,
          deploymentTargetTypes,
        }
      );
      const deploymentTargets = response.Items.map((target: DeploymentTargetResource) => ({
        spaceId: target.SpaceId,
        id: target.Id,
        name: target.Name,
        slug: target.Slug,
        isDisabled: target.IsDisabled,
        healthStatus: target.HealthStatus,
        statusSummary: target.StatusSummary,
        environmentIds: target.EnvironmentIds,
        roles: target.Roles,
        tenantedDeploymentParticipation: target.TenantedDeploymentParticipation,
        tenantIds: target.TenantIds,
        tenantTags: target.TenantTags,
        endpoint: {
          communicationStyle: target.Endpoint.CommunicationStyle,
          uri: target.Endpoint.Uri,
          fingerprint: target.Endpoint.Fingerprint,
        },
        shellName: target.ShellName,
        machinePolicyId: target.MachinePolicyId,
        hasLatestCalamari: target.HasLatestCalamari,
        isInProcess: target.IsInProcess,
      }));
    
      return {
        content: [
          {
            type: "text",
            text: JSON.stringify({
              totalResults: response.TotalResults,
              itemsPerPage: response.ItemsPerPage,
              numberOfPages: response.NumberOfPages,
              lastPageNumber: response.LastPageNumber,
              items: deploymentTargets,
            }),
          },
        ],
      };
    }
  • Zod schema defining the input parameters for filtering and paginating the list of deployment targets.
      spaceName: z.string(),
      skip: z.number().optional(),
      take: z.number().optional(),
      name: z.string().optional(),
      ids: z.array(z.string()).optional(),
      partialName: z.string().optional(),
      roles: z.array(z.string()).optional().describe("A list of roles / target tags to filter by."),
      isDisabled: z.boolean().optional(),
      healthStatuses: z.array(z.string()).optional().describe("Possible values: Healthy, Unhealthy, Unavailable, Unknown, HasWarnings"),
      commStyles: z.array(z.string()).optional(),
      tenantIds: z.array(z.string()).optional(),
      tenantTags: z.array(z.string()).optional(),
      environmentIds: z.array(z.string()).optional(),
      thumbprint: z.string().optional(),
      deploymentId: z.string().optional(),
      shellNames: z.array(z.string()).optional(),
      deploymentTargetTypes: z.array(z.string()).optional(),
    },
  • The registration function that registers the 'list_deployment_targets' tool on the MCP server, including name, description, schema, and handler.
    export function registerListDeploymentTargetsTool(server: McpServer) {
      server.tool(
        "list_deployment_targets",
        `List deployment targets (machines) in a space
    
    This tool lists all deployment targets in a given space. The space name is required. You can optionally filter by various parameters like name, roles, health status, etc.`,
        {
          spaceName: z.string(),
          skip: z.number().optional(),
          take: z.number().optional(),
          name: z.string().optional(),
          ids: z.array(z.string()).optional(),
          partialName: z.string().optional(),
          roles: z.array(z.string()).optional().describe("A list of roles / target tags to filter by."),
          isDisabled: z.boolean().optional(),
          healthStatuses: z.array(z.string()).optional().describe("Possible values: Healthy, Unhealthy, Unavailable, Unknown, HasWarnings"),
          commStyles: z.array(z.string()).optional(),
          tenantIds: z.array(z.string()).optional(),
          tenantTags: z.array(z.string()).optional(),
          environmentIds: z.array(z.string()).optional(),
          thumbprint: z.string().optional(),
          deploymentId: z.string().optional(),
          shellNames: z.array(z.string()).optional(),
          deploymentTargetTypes: z.array(z.string()).optional(),
        },
        {
          title: "List all deployment targets in an Octopus Deploy space",
          readOnlyHint: true,
        },
        async ({
          spaceName,
          skip,
          take,
          name,
          ids,
          partialName,
          roles,
          isDisabled,
          healthStatuses,
          commStyles,
          tenantIds,
          tenantTags,
          environmentIds,
          thumbprint,
          deploymentId,
          shellNames,
          deploymentTargetTypes,
        }) => {
          const configuration = getClientConfigurationFromEnvironment();
          const client = await Client.create(configuration);
          const spaceId = await resolveSpaceId(client, spaceName);
    
          const response = await client.get<ResourceCollection<DeploymentTargetResource>>(
            "~/api/{spaceId}/machines{?skip,take,name,ids,partialName,roles,isDisabled,healthStatuses,commStyles,tenantIds,tenantTags,environmentIds,thumbprint,deploymentId,shellNames,deploymentTargetTypes}",
            {
              spaceId,
              skip,
              take,
              name,
              ids,
              partialName,
              roles,
              isDisabled,
              healthStatuses,
              commStyles,
              tenantIds,
              tenantTags,
              environmentIds,
              thumbprint,
              deploymentId,
              shellNames,
              deploymentTargetTypes,
            }
          );
          const deploymentTargets = response.Items.map((target: DeploymentTargetResource) => ({
            spaceId: target.SpaceId,
            id: target.Id,
            name: target.Name,
            slug: target.Slug,
            isDisabled: target.IsDisabled,
            healthStatus: target.HealthStatus,
            statusSummary: target.StatusSummary,
            environmentIds: target.EnvironmentIds,
            roles: target.Roles,
            tenantedDeploymentParticipation: target.TenantedDeploymentParticipation,
            tenantIds: target.TenantIds,
            tenantTags: target.TenantTags,
            endpoint: {
              communicationStyle: target.Endpoint.CommunicationStyle,
              uri: target.Endpoint.Uri,
              fingerprint: target.Endpoint.Fingerprint,
            },
            shellName: target.ShellName,
            machinePolicyId: target.MachinePolicyId,
            hasLatestCalamari: target.HasLatestCalamari,
            isInProcess: target.IsInProcess,
          }));
    
          return {
            content: [
              {
                type: "text",
                text: JSON.stringify({
                  totalResults: response.TotalResults,
                  itemsPerPage: response.ItemsPerPage,
                  numberOfPages: response.NumberOfPages,
                  lastPageNumber: response.LastPageNumber,
                  items: deploymentTargets,
                }),
              },
            ],
          };
        }
      );
    }
  • Self-registration of the tool into the global TOOL_REGISTRY for conditional enabling.
    registerToolDefinition({
      toolName: "list_deployment_targets",
      config: { toolset: "machines", readOnly: true },
      registerFn: registerListDeploymentTargetsTool,
    });
  • Import that triggers the self-registration of the listDeploymentTargets tool.
    import "./listDeploymentTargets.js";
Behavior3/5

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

Annotations provide readOnlyHint=true, indicating a safe read operation. The description adds behavioral context by specifying that it 'lists all deployment targets' with optional filtering, which clarifies scope beyond annotations. However, it doesn't disclose other traits like pagination behavior (implied by skip/take parameters but not explained), rate limits, or authentication needs. No contradiction with annotations exists.

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 appropriately sized with two sentences: the first states the purpose, and the second adds details about required and optional parameters. It's front-loaded with the core functionality and avoids unnecessary elaboration. Every sentence contributes directly to understanding the tool's use.

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

Completeness3/5

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

Given the complexity (17 parameters, low schema coverage, no output schema), the description is adequate but has gaps. It covers the basic purpose and hints at filtering, but doesn't explain output format, pagination, or error handling. With annotations providing safety context, it meets minimum viability but lacks depth for a tool with many parameters and no output schema.

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 description coverage is low (12%), with only 'roles' and 'healthStatuses' having descriptions. The description adds value by mentioning 'space name is required' and listing filterable parameters like 'name, roles, health status, etc.,' but doesn't provide detailed semantics for most of the 17 parameters. It compensates somewhat for the low coverage but doesn't fully explain parameter usage or relationships.

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

Purpose4/5

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

The description clearly states the tool's purpose: 'List deployment targets (machines) in a space' and 'lists all deployment targets in a given space.' It specifies the verb ('list'), resource ('deployment targets'), and scope ('in a space'), but doesn't explicitly differentiate from sibling tools like 'get_deployment_target' (singular) or other list tools. The title annotation adds 'Octopus Deploy space' context, but the description itself doesn't mention siblings.

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 implies usage context by stating 'The space name is required' and mentioning optional filtering, but doesn't provide explicit guidance on when to use this tool versus alternatives. For example, it doesn't contrast with 'get_deployment_target' (singular retrieval) or other list tools like 'list_environments.' Usage is implied through the description of functionality rather than stated as explicit guidelines.

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