Skip to main content
Glama
soil-dev

capsulemcp

add_tag

Attach a tag to a party, opportunity, or project by name. Capsule resolves to an existing tag or creates a new one, with case-insensitive matching and idempotent operation.

Instructions

Attach a tag to a party, opportunity, or project (kase) by NAME. Capsule resolves to an existing tag in the tenant or creates a fresh one with this name. Matching is case-insensitive — 'VIP' and 'vip' attach the same tag, preserving the canonical casing from whichever variant was created first. To avoid creating a genuinely-distinct near-duplicate (e.g. 'VIP' vs 'V.I.P.'), call list_tags first and reuse the exact name. Idempotent — re-attaching an already-attached tag is harmless. To DETACH a tag, use remove_tag_by_id with the tag's id (read via get_party/get_opportunity/get_project with embed='tags').

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
entityYesWhich entity type. Use 'kases' for projects (Capsule's legacy path name).
entityIdYesThe party/opportunity/kase id.
tagNameYesName of the tag to attach. Capsule resolves by name: if a tag with this name already exists in the tenant it is attached to the entity; if not, Capsule creates the tag and attaches it. Names are tenant-global. Capsule matches case-INSENSITIVELY when resolving (so 'VIP' and 'vip' attach the same tag), preserving the canonical casing from whichever variant was created first. To ensure consistent casing in your tag list, call list_tags first and reuse the exact name from there. Idempotent — re-attaching an already-attached tag is harmless.

Implementation Reference

  • The registerTool helper function that wraps the handler result in MCP text content response and calls server.registerTool.
    export function registerTool<Schema extends z.ZodObject<ZodRawShape>>(
      server: McpServer,
      name: string,
      description: string,
      schema: Schema,
      handler: (input: z.infer<Schema>) => Promise<unknown>,
    ): void {
      // Use the SDK config-form registerTool with the full Zod schema. The
      // deprecated shape overload rebuilds z.object(schema.shape), which drops
      // object-level refinements such as superRefine.
      const registerWithSchema = server.registerTool.bind(server) as (
        toolName: string,
        config: { description: string; inputSchema: Schema },
        callback: (input: z.infer<Schema>) => Promise<CallToolResult>,
      ) => void;
    
      registerWithSchema(name, { description, inputSchema: schema }, async (input) => {
        const result = await handler(input);
        return wrapAsText(result);
      });
    }
Behavior5/5

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

Despite no annotations, the description fully discloses key behaviors: case-insensitive matching, tag creation if missing, idempotency, and canonical casing preservation. It also warns about near-duplicates, adding significant transparency.

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 concise (6 sentences) and front-loaded with the core purpose. Every sentence provides unique value without redundancy, making it efficient for an AI agent to parse.

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

Completeness5/5

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

Given the tool has 3 parameters, no output schema, and no annotations, the description is remarkably complete. It covers behavior, side effects, prerequisites (calling list_tags), and relation to other tools, leaving no ambiguity.

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?

The input schema has 100% coverage with good descriptions; the description adds meaningful context beyond the schema, such as idempotency and case-insensitivity details for tagName, which enhances understanding.

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 defines the action: 'Attach a tag to a party, opportunity, or project (kase) by NAME.' It specifies the resource (tag) and target entities, and distinguishes from the sibling tool 'remove_tag_by_id' by mentioning the detachment case.

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

Usage Guidelines5/5

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

Provides explicit when-to-use and when-not-to-use guidance: 'To avoid creating a genuinely-distinct near-duplicate... call list_tags first' and 'To DETACH a tag, use remove_tag_by_id.' It also explains idempotency, making the tool's behavior predictable.

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