Skip to main content
Glama
soil-dev

capsulemcp

remove_additional_party

Removes the link between an opportunity or project and an additional party without deleting the party. Requires confirmation and is reversible by re-adding the link.

Instructions

Remove an additional-party link between an opportunity/project and a party. The party itself is NOT deleted. Requires confirm=true. Reversible by re-adding via add_additional_party. Idempotent on retry: response is {removed: true, alreadyRemoved: false, entity, entityId, partyId} on a fresh remove or {removed: true, alreadyRemoved: true, ...} if the link was already gone (Capsule's 404 is caught and converted).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
entityYesWhich entity has the additional-party links. Use 'kases' for projects.
entityIdYes
partyIdYes
confirmYesMust be set to true. Removes the link between the entity and the additional party. The party itself is not deleted. Reversible by re-adding the link.

Implementation Reference

  • The handler function that executes the tool logic. Validates confirm=true, then uses the idempotent helper to DELETE /<entity>/{entityId}/parties/{partyId}. Returns {removed, alreadyRemoved, entity, entityId, partyId} on success, or {removed, alreadyRemoved: true} if the link was already gone (404 caught by idempotent).
    export async function removeAdditionalParty(input: z.infer<typeof removeAdditionalPartySchema>) {
      if (input.confirm !== true) {
        throw new Error("remove_additional_party requires confirm: true");
      }
      // Capsule's 404 here covers both "party doesn't exist" and "party
      // isn't linked to this entity" — both are observationally "the link
      // doesn't exist", treat both as already-removed.
      return idempotent(
        () => capsuleDelete(`/${input.entity}/${input.entityId}/parties/${input.partyId}`),
        () => ({
          removed: true,
          alreadyRemoved: false,
          entity: input.entity,
          entityId: input.entityId,
          partyId: input.partyId,
        }),
        () => ({
          removed: true,
          alreadyRemoved: true,
          entity: input.entity,
          entityId: input.entityId,
          partyId: input.partyId,
        }),
      );
    }
  • Zod schema defining the input: entity (opportunities|kases), entityId (positive int), partyId (positive int), confirm (literal true, using shared confirmFlag helper).
    export const removeAdditionalPartySchema = z.object({
      entity: RelationshipEntity,
      entityId: z.number().int().positive(),
      partyId: z.number().int().positive(),
      confirm: confirmFlag().describe(
        "Must be set to true. Removes the link between the entity and the additional party. The party itself is not deleted. Reversible by re-adding the link.",
      ),
    });
  • src/server.ts:560-566 (registration)
    Registration of the MCP tool 'remove_additional_party' with its description, schema, and handler via the registerTool helper.
    registerTool(
      server,
      "remove_additional_party",
      "Remove an additional-party link between an opportunity/project and a party. The party itself is NOT deleted. Requires confirm=true. Reversible by re-adding via add_additional_party. Idempotent on retry: response is `{removed: true, alreadyRemoved: false, entity, entityId, partyId}` on a fresh remove or `{removed: true, alreadyRemoved: true, ...}` if the link was already gone (Capsule's 404 is caught and converted).",
      removeAdditionalPartySchema,
      removeAdditionalParty,
    );
  • Idempotency helper used by the handler. Tries the DELETE op; if it throws a 404 (using default isCapsule404 predicate), returns the alreadyRemoved shape instead of propagating the error.
    export async function idempotent<T>(
      op: () => Promise<unknown>,
      success: () => T,
      alreadyDone: () => T,
      isAlreadyDoneError: (err: unknown) => boolean = isCapsule404,
    ): Promise<T> {
      try {
        await op();
        return success();
      } catch (err) {
        if (isAlreadyDoneError(err)) return alreadyDone();
        throw err;
      }
    }
  • Shared confirmFlag helper that produces a z.literal(true) schema with a custom error message, used by the schema's confirm field.
    const CONFIRM_REQUIRED_MESSAGE =
      "confirm: true is required to perform this destructive operation (set the parameter explicitly to acknowledge the destructive intent)";
    
    export function confirmFlag(): z.ZodLiteral<true> {
      return z.literal(true, { error: () => CONFIRM_REQUIRED_MESSAGE });
    }
Behavior5/5

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

With no annotations, the description fully discloses key behaviors: party not deleted, confirm requirement, reversibility, idempotency, and response format including error handling (Capsule's 404 caught). This goes well beyond the schema.

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 relatively concise (5 sentences) and front-loads the main purpose. Some redundancy (e.g., confirm explanation appears in both schema and description) but overall efficient.

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 purpose, effect, safety (confirm), reversibility, idempotency, and response format. Missing prerequisites and other error cases, but sufficient for most agent use cases given 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 coverage is 50%; description adds meaning for 'confirm' (explains purpose) but does not describe 'entityId' or 'partyId' beyond the schema. The description partially compensates but leaves those parameters unexplained.

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 action ('Remove an additional-party link') and the resource ('between an opportunity/project and a party'). It distinguishes itself from sibling tools by noting that the party is not deleted (different from remove_party) and is reversible by add_additional_party.

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?

The description implies when to use (to remove a link without deleting the party) and mentions the alternative add_additional_party for re-adding. However, it lacks explicit 'when not to use' statements or comparison with other remove tools.

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/soil-dev/capsulemcp'

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