Skip to main content
Glama
aaronsb

Confluence MCP Server

add_confluence_label

Add organizational labels to Confluence pages to categorize content and improve searchability through the Confluence MCP Server.

Instructions

Add a label to a page. Labels help organize content and make it easier to find related pages through search_confluence_pages.

Label Format:

  • Must contain only letters, numbers, hyphens, and underscores

  • No spaces or special characters allowed

Error Handling:

  • Returns 400 for invalid label format

  • Returns 403 for insufficient permissions

  • Returns 404 if page not found

  • Returns 409 if label already exists on the page

Response includes:

  • Success status

  • Label details (id, name, prefix, creation date)

  • Operation message

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
pageIdYesID of the page to add the label to
labelYesLabel to add (letters, numbers, hyphens, and underscores only)

Implementation Reference

  • Main handler function for the 'add_confluence_label' tool. Validates inputs, checks page existence, calls the Confluence client to add the label, handles various errors, and returns a formatted JSON response.
    export async function handleAddConfluenceLabel(
      client: ConfluenceClient,
      args: { pageId: string; label: string }
    ): Promise<{
      content: Array<{ type: "text"; text: string }>;
    }> {
      try {
        if (!args.pageId || !args.label) {
          throw new McpError(
            ErrorCode.InvalidParams,
            "pageId and label are required"
          );
        }
    
        // Validate label format
        if (!/^[a-zA-Z0-9-_]+$/.test(args.label)) {
          throw new McpError(
            ErrorCode.InvalidParams,
            "Label must contain only letters, numbers, hyphens, and underscores"
          );
        }
    
        // First check if the page exists and is accessible
        try {
          await client.getConfluencePage(args.pageId);
        } catch (error: unknown) {
          if (error instanceof ConfluenceError) {
            switch (error.code) {
              case 'PAGE_NOT_FOUND':
                throw new McpError(ErrorCode.InvalidParams, "Page not found");
              case 'INSUFFICIENT_PERMISSIONS':
                throw new McpError(ErrorCode.InvalidRequest, "Insufficient permissions to access page");
              default:
                throw new McpError(ErrorCode.InternalError, error.message);
            }
          }
          throw error;
        }
    
        const label = await client.addConfluenceLabel(args.pageId, args.label);
        const simplified = {
          success: true,
          label: {
            id: label.id,
            name: label.name,
            prefix: label.prefix || null,
            createdDate: label.createdDate || null
          },
          message: `Successfully added label '${args.label}' to page ${args.pageId}`
        };
        return {
          content: [
            {
              type: "text",
              text: JSON.stringify(simplified),
            },
          ],
        };
      } catch (error: unknown) {
        console.error("Error adding label:", error instanceof Error ? error.message : String(error));
        
        if (error instanceof McpError) {
          throw error;
        }
    
        // Handle specific HTTP errors from the Confluence API
        if (error instanceof ConfluenceError) {
          switch (error.code) {
            case 'LABEL_EXISTS':
              throw new McpError(ErrorCode.InvalidRequest, `Label '${args.label}' already exists on this page`);
            case 'INVALID_LABEL':
              throw new McpError(ErrorCode.InvalidParams, "Invalid label format");
            case 'PERMISSION_DENIED':
              throw new McpError(ErrorCode.InvalidRequest, "You don't have permission to add labels to this page");
            default:
              throw new McpError(ErrorCode.InternalError, `Failed to add label: ${error.message}`);
          }
        }
    
        throw new McpError(
          ErrorCode.InternalError,
          `Failed to add label: ${error instanceof Error ? error.message : String(error)}`
        );
      }
  • Schema definition for the 'add_confluence_label' tool, including description, input properties (pageId, label), and required fields.
    add_confluence_label: {
      description: "Add a label to a page. Labels help organize content and make it easier to find related pages through search_confluence_pages.\n\nLabel Format:\n- Must contain only letters, numbers, hyphens, and underscores\n- No spaces or special characters allowed\n\nError Handling:\n- Returns 400 for invalid label format\n- Returns 403 for insufficient permissions\n- Returns 404 if page not found\n- Returns 409 if label already exists on the page\n\nResponse includes:\n- Success status\n- Label details (id, name, prefix, creation date)\n- Operation message",
      inputSchema: {
        type: "object",
        properties: {
          pageId: {
            type: "string",
            description: "ID of the page to add the label to",
          },
          label: {
            type: "string",
            description: "Label to add (letters, numbers, hyphens, and underscores only)",
          },
        },
        required: ["pageId", "label"],
      },
    },
  • src/index.ts:266-270 (registration)
    Tool registration in the main switch statement within the CallToolRequestSchema handler. Dispatches to the handleAddConfluenceLabel function.
    case "add_confluence_label": {
      const { pageId, label } = (args || {}) as { pageId: string; label: string };
      if (!pageId || !label) throw new McpError(ErrorCode.InvalidParams, "pageId and label are required");
      return await handleAddConfluenceLabel(this.confluenceClient, { pageId, label });
    }
  • Helper method in ConfluenceClient that performs the actual API POST request to add a label to a page and handles API-specific errors.
    async addConfluenceLabel(pageId: string, label: string): Promise<Label> {
      try {
        const response = await this.v2Client.post(`/pages/${pageId}/labels`, {
          name: label
        });
        return response.data;
      } catch (error) {
        if (axios.isAxiosError(error)) {
          switch (error.response?.status) {
            case 400:
              throw new ConfluenceError(
                'Invalid label format or label already exists',
                'INVALID_LABEL'
              );
            case 403:
              throw new ConfluenceError(
                'Insufficient permissions to add labels',
                'PERMISSION_DENIED'
              );
            case 404:
              throw new ConfluenceError(
                'Page not found',
                'PAGE_NOT_FOUND'
              );
            case 409:
              throw new ConfluenceError(
                'Label already exists on this page',
                'LABEL_EXISTS'
              );
            default:
              console.error('Error adding label:', error.response?.data);
              throw new ConfluenceError(
                `Failed to add label: ${error.message}`,
                'UNKNOWN'
              );
          }
        }
        throw error;
      }
Behavior4/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively adds context beyond the input schema by detailing error handling (400, 403, 404, 409 status codes) and response content (success status, label details, operation message). This covers key behavioral traits like validation rules, permission requirements, and output structure, though it doesn't mention rate limits or side effects like label uniqueness constraints beyond the 409 error.

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 well-structured and front-loaded with the core purpose, followed by organized sections on label format, error handling, and response details. Each sentence earns its place by providing essential information without redundancy, such as the error codes that clarify behavioral expectations. It is appropriately sized for a tool with two parameters and no annotations.

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?

Given the tool's moderate complexity (2 parameters, no annotations, no output schema), the description is largely complete. It covers purpose, usage context, behavioral traits (error handling, response), and parameter constraints. However, it lacks details on prerequisites (e.g., page must exist, user permissions) and does not fully explain the response structure (e.g., format of 'label details'). With no output schema, more explicit return value documentation would enhance completeness.

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?

The schema description coverage is 100%, with both parameters ('pageId' and 'label') fully documented in the schema. The description adds minimal value beyond the schema: it reiterates the label format rules (letters, numbers, hyphens, underscores only) which are already in the schema's description for 'label', and does not provide additional syntax or usage details. Baseline 3 is appropriate as the schema does the heavy lifting.

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 specific action ('Add a label to a page') and resource ('page'), distinguishing it from sibling tools like 'remove_confluence_label' (which removes labels) and 'get_confluence_labels' (which retrieves labels). It explicitly mentions the purpose of labels ('organize content and make it easier to find related pages through search_confluence_pages'), providing context beyond the basic action.

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 provides clear context for when to use this tool ('Labels help organize content and make it easier to find related pages through search_confluence_pages'), but does not explicitly state when not to use it or mention alternatives. For example, it doesn't contrast with 'remove_confluence_label' or specify if labels should be added only after page creation. The guidance is helpful but lacks explicit exclusions or comparisons to sibling 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/aaronsb/confluence-cloud-mcp'

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