Find accounts in an Octopus Deploy space
find_accountsRetrieve an account by ID or list all accounts in a space, with optional filtering by name, type, and pagination.
Instructions
Find accounts in a space - can retrieve a single account by ID or list all accounts
This unified tool can either:
Get detailed information about a specific account when accountId is provided
List all accounts in a space when accountId is omitted
You can optionally filter by various parameters like name, account type, etc. when listing.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| spaceName | Yes | ||
| accountId | No | The ID of a specific account to retrieve. If omitted, lists all accounts. | |
| skip | No | Number of accounts to skip for pagination (only used when listing) | |
| take | No | Number of accounts to take for pagination (only used when listing) | |
| ids | No | Filter by specific account IDs (only used when listing) | |
| partialName | No | Filter by partial name match (only used when listing) | |
| accountType | No | Filter by account type (only used when listing) |
Implementation Reference
- src/tools/findAccounts.ts:37-112 (handler)The async handler function that executes the find_accounts tool logic. It connects to the Octopus API, retrieves either a single account by ID or lists all accounts with optional filters, and returns the mapped results.
async ({ spaceName, accountId, skip, take, ids, partialName, accountType, }) => { const configuration = getClientConfigurationFromEnvironment(); const client = await Client.create(configuration); const spaceId = await resolveSpaceId(client, spaceName); // If accountId is provided, get a single account if (accountId) { validateEntityId(accountId, 'account', ENTITY_PREFIXES.account); try { const response = await client.get<AccountResource>( "~/api/{spaceId}/accounts/{id}", { spaceId, id: accountId, } ); const account = mapAccountResource(response); return { content: [ { type: "text", text: JSON.stringify(account), }, ], }; } catch (error) { handleOctopusApiError(error, { entityType: 'account', entityId: accountId, spaceName }); } } // Otherwise, list all accounts const response = await client.get<ResourceCollection<AccountResource>>( "~/api/{spaceId}/accounts{?skip,take,ids,partialName,accountType}", { spaceId, skip, take, ids, partialName, accountType, } ); const accounts = response.Items.map((account: AccountResource) => mapAccountResource(account)); return { content: [ { type: "text", text: JSON.stringify({ totalResults: response.TotalResults, itemsPerPage: response.ItemsPerPage, numberOfPages: response.NumberOfPages, lastPageNumber: response.LastPageNumber, items: accounts, }), }, ], }; } ); - src/tools/findAccounts.ts:17-36 (schema)Input schema definition for the find_accounts tool using Zod. Defines parameters: spaceName (required), accountId, skip, take, ids, partialName, and accountType (optional enum).
{ title: "Find accounts in an Octopus Deploy space", description: `Find accounts in a space - can retrieve a single account by ID or list all accounts This unified tool can either: - Get detailed information about a specific account when accountId is provided - List all accounts in a space when accountId is omitted You can optionally filter by various parameters like name, account type, etc. when listing.`, inputSchema: { spaceName: z.string(), accountId: z.string().optional().describe("The ID of a specific account to retrieve. If omitted, lists all accounts."), skip: z.number().optional().describe("Number of accounts to skip for pagination (only used when listing)"), take: z.number().optional().describe("Number of accounts to take for pagination (only used when listing)"), ids: z.array(z.string()).optional().describe("Filter by specific account IDs (only used when listing)"), partialName: z.string().optional().describe("Filter by partial name match (only used when listing)"), accountType: z.nativeEnum(AccountType).optional().describe("Filter by account type (only used when listing)"), }, annotations: READ_ONLY_TOOL_ANNOTATIONS, }, - src/types/accountTypes.ts:5-223 (schema)AccountType enum and AccountResource interfaces used by the handler to map API responses. The mapAccountResource function converts raw account data into a structured format with type-specific properties.
export enum AccountType { None = "None", UsernamePassword = "UsernamePassword", Token = "Token", SshKeyPair = "SshKeyPair", AzureSubscription = "AzureSubscription", AzureServicePrincipal = "AzureServicePrincipal", AzureManagementCertificate = "AzureManagementCertificate", AzureOidc = "AzureOidc", AmazonWebServicesAccount = "AmazonWebServicesAccount", AmazonWebServicesOidcAccount = "AmazonWebServicesOidcAccount", GoogleCloudAccount = "GoogleCloudAccount", GenericOidcAccount = "GenericOidcAccount", } interface AccountResourceLinks { Self: string; Usages: string; } export interface BaseAccountResource extends ResourceWithSlug { Id: string; Name: string; Description: string; AccountType: AccountType; } export interface AccountResource extends BaseAccountResource, NamedResource<AccountResourceLinks>, SpaceScopedResource { EnvironmentIds: string[]; TenantIds: string[]; TenantTags: string[]; TenantedDeploymentParticipation: TenantedDeploymentMode; } export interface AzureServicePrincipalAccountResource extends AccountResource { SubscriptionNumber: string; ClientId: string; TenantId: string; AzureEnvironment: string; ResourceManagementEndpointBaseUri: string; ActiveDirectoryEndpointBaseUri: string; } export interface AzureOidcAccountResource extends AccountResource { SubscriptionNumber: string; ClientId: string; TenantId: string; AzureEnvironment: string; TenantedSubjectGeneration: boolean; ResourceManagementEndpointBaseUri: string; ActiveDirectoryEndpointBaseUri: string; DeploymentSubjectKeys: string[]; HealthCheckSubjectKeys: string[]; AccountTestSubjectKeys: string[]; Audience: string; CustomClaims: Record<string, string>; } export interface AzureSubscriptionAccountResource extends AccountResource { SubscriptionNumber: string; CertificateThumbprint: string; AzureEnvironment: string; ServiceManagementEndpointBaseUri: string; ServiceManagementEndpointSuffix: string; } export interface GenericOidcAccountResource extends AccountResource { TenantedSubjectGeneration: boolean; DeploymentSubjectKeys: string[]; HealthCheckSubjectKeys: string[]; AccountTestSubjectKeys: string[]; Audience: string; CustomClaims: Record<string, string>; } export interface SshKeyPairAccountResource extends AccountResource { Username: string; } export interface UsernamePasswordAccountResource extends AccountResource { Username: string; } export interface TokenAccountResource extends AccountResource { } export interface AmazonWebServicesAccessKeyAccountResource extends AccountResource { AccessKey: string; } export interface AmazonWebServicesOidcAccountResource extends AccountResource { RoleArn: string; SessionDuration: string; DeploymentSubjectKeys: string[]; HealthCheckSubjectKeys: string[]; AccountTestSubjectKeys: string[]; CustomClaims: Record<string, string>; } export interface GoogleCloudAccountResource extends AccountResource { } export function mapAccountResource(account: AccountResource) { const baseAccount = { spaceId: account.SpaceId, id: account.Id, name: account.Name, description: account.Description, slug: account.Slug, accountType: account.AccountType, environmentIds: account.EnvironmentIds, tenantIds: account.TenantIds, tenantTags: account.TenantTags, tenantedDeploymentParticipation: account.TenantedDeploymentParticipation, }; // Add type-specific properties based on AccountType switch (account.AccountType) { case AccountType.AzureSubscription: { const azureAccount = account as AzureSubscriptionAccountResource; return { ...baseAccount, subscriptionNumber: azureAccount.SubscriptionNumber, certificateThumbprint: azureAccount.CertificateThumbprint, azureEnvironment: azureAccount.AzureEnvironment, serviceManagementEndpointBaseUri: azureAccount.ServiceManagementEndpointBaseUri, serviceManagementEndpointSuffix: azureAccount.ServiceManagementEndpointSuffix, }; } case AccountType.AzureServicePrincipal: { const azureAccount = account as AzureServicePrincipalAccountResource; return { ...baseAccount, subscriptionNumber: azureAccount.SubscriptionNumber, clientId: azureAccount.ClientId, tenantId: azureAccount.TenantId, azureEnvironment: azureAccount.AzureEnvironment, resourceManagementEndpointBaseUri: azureAccount.ResourceManagementEndpointBaseUri, activeDirectoryEndpointBaseUri: azureAccount.ActiveDirectoryEndpointBaseUri, }; } case AccountType.AzureOidc: { const azureAccount = account as AzureOidcAccountResource; return { ...baseAccount, subscriptionNumber: azureAccount.SubscriptionNumber, clientId: azureAccount.ClientId, tenantId: azureAccount.TenantId, azureEnvironment: azureAccount.AzureEnvironment, tenantedSubjectGeneration: azureAccount.TenantedSubjectGeneration, resourceManagementEndpointBaseUri: azureAccount.ResourceManagementEndpointBaseUri, activeDirectoryEndpointBaseUri: azureAccount.ActiveDirectoryEndpointBaseUri, deploymentSubjectKeys: azureAccount.DeploymentSubjectKeys, healthCheckSubjectKeys: azureAccount.HealthCheckSubjectKeys, accountTestSubjectKeys: azureAccount.AccountTestSubjectKeys, audience: azureAccount.Audience, customClaims: azureAccount.CustomClaims, }; } case AccountType.SshKeyPair: { const sshAccount = account as SshKeyPairAccountResource; return { ...baseAccount, username: sshAccount.Username, }; } case AccountType.UsernamePassword: { const userPassAccount = account as UsernamePasswordAccountResource; return { ...baseAccount, username: userPassAccount.Username, }; } case AccountType.AmazonWebServicesAccount: { const awsAccount = account as AmazonWebServicesAccessKeyAccountResource; return { ...baseAccount, accessKey: awsAccount.AccessKey, }; } case AccountType.AmazonWebServicesOidcAccount: { const awsOidcAccount = account as AmazonWebServicesOidcAccountResource; return { ...baseAccount, roleArn: awsOidcAccount.RoleArn, sessionDuration: awsOidcAccount.SessionDuration, deploymentSubjectKeys: awsOidcAccount.DeploymentSubjectKeys, healthCheckSubjectKeys: awsOidcAccount.HealthCheckSubjectKeys, accountTestSubjectKeys: awsOidcAccount.AccountTestSubjectKeys, customClaims: awsOidcAccount.CustomClaims, }; } case AccountType.GenericOidcAccount: { const genericOidcAccount = account as GenericOidcAccountResource; return { ...baseAccount, tenantedSubjectGeneration: genericOidcAccount.TenantedSubjectGeneration, deploymentSubjectKeys: genericOidcAccount.DeploymentSubjectKeys, healthCheckSubjectKeys: genericOidcAccount.HealthCheckSubjectKeys, accountTestSubjectKeys: genericOidcAccount.AccountTestSubjectKeys, audience: genericOidcAccount.Audience, customClaims: genericOidcAccount.CustomClaims, }; } case AccountType.Token: case AccountType.GoogleCloudAccount: case AccountType.None: default: return baseAccount; } } - src/tools/findAccounts.ts:14-113 (registration)The registerFindAccountsTool function that registers the tool on the MCP server. Also self-registers via registerToolDefinition at line 115-119 with the 'accounts' toolset.
export function registerFindAccountsTool(server: McpServer) { server.registerTool( "find_accounts", { title: "Find accounts in an Octopus Deploy space", description: `Find accounts in a space - can retrieve a single account by ID or list all accounts This unified tool can either: - Get detailed information about a specific account when accountId is provided - List all accounts in a space when accountId is omitted You can optionally filter by various parameters like name, account type, etc. when listing.`, inputSchema: { spaceName: z.string(), accountId: z.string().optional().describe("The ID of a specific account to retrieve. If omitted, lists all accounts."), skip: z.number().optional().describe("Number of accounts to skip for pagination (only used when listing)"), take: z.number().optional().describe("Number of accounts to take for pagination (only used when listing)"), ids: z.array(z.string()).optional().describe("Filter by specific account IDs (only used when listing)"), partialName: z.string().optional().describe("Filter by partial name match (only used when listing)"), accountType: z.nativeEnum(AccountType).optional().describe("Filter by account type (only used when listing)"), }, annotations: READ_ONLY_TOOL_ANNOTATIONS, }, async ({ spaceName, accountId, skip, take, ids, partialName, accountType, }) => { const configuration = getClientConfigurationFromEnvironment(); const client = await Client.create(configuration); const spaceId = await resolveSpaceId(client, spaceName); // If accountId is provided, get a single account if (accountId) { validateEntityId(accountId, 'account', ENTITY_PREFIXES.account); try { const response = await client.get<AccountResource>( "~/api/{spaceId}/accounts/{id}", { spaceId, id: accountId, } ); const account = mapAccountResource(response); return { content: [ { type: "text", text: JSON.stringify(account), }, ], }; } catch (error) { handleOctopusApiError(error, { entityType: 'account', entityId: accountId, spaceName }); } } // Otherwise, list all accounts const response = await client.get<ResourceCollection<AccountResource>>( "~/api/{spaceId}/accounts{?skip,take,ids,partialName,accountType}", { spaceId, skip, take, ids, partialName, accountType, } ); const accounts = response.Items.map((account: AccountResource) => mapAccountResource(account)); return { content: [ { type: "text", text: JSON.stringify({ totalResults: response.TotalResults, itemsPerPage: response.ItemsPerPage, numberOfPages: response.NumberOfPages, lastPageNumber: response.LastPageNumber, items: accounts, }), }, ], }; } ); } - src/tools/index.ts:30-30 (registration)Import of the findAccounts module in the tools index, which triggers self-registration of the tool via the side-effect import.
import "./findAccounts.js";