Skip to main content
Glama

add-tool-annotation

Add contextual annotations to tools within hypertool-mcp to enhance LLM usage. Provide user-specific guidance, best practices, and usage notes directly within tool descriptions for improved clarity and efficiency.

Instructions

Add contextual annotations to a tool in the current toolset to guide LLM usage. Annotations provide user-specific guidance, best practices, and usage notes that will be displayed with the tool's description. Example: {toolRef: {namespacedName: 'linear.create_issue'}, notes: [{name: 'team-selection', note: 'Always confirm team with user first'}]}

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
notesYesArray of annotations to add to the tool. Each annotation has a name (identifier) and note (content).
toolRefYesReference to the tool (use namespacedName or refId). Use list-available-tools to find the correct reference.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
toolYesTool that was annotated
errorsNoError messages for failed annotations
toolsetYesName of the toolset that was updated
addedNotesYesNotes that were successfully added
errorCountYesNumber of annotations that failed to be added
successCountYesNumber of annotations successfully added

Implementation Reference

  • The tool module factory and handler function implementing the core logic of 'add-tool-annotation': validates input, resolves tool refs, manages toolset notes, persists changes, and formats response.
    export const createAddToolAnnotationModule: ToolModuleFactory = (
      deps
    ): ToolModule => {
      return {
        toolName: "add-tool-annotation",
        definition: addToolAnnotationDefinition,
        handler: async (args: any) => {
          // Check if a toolset is equipped
          if (!deps.toolsetManager.hasActiveToolset()) {
            // Get list of available toolsets
            const availableToolsets = await deps.toolsetManager.listSavedToolsets();
            const toolsetNames = availableToolsets.success
              ? availableToolsets.toolsets.map((t) => t.name)
              : [];
    
            const response: AddToolAnnotationResponse = {
              toolset: "",
              tool: {
                namespacedName: "",
                refId: "",
                server: "",
              },
              addedNotes: [],
              successCount: 0,
              errorCount: 1,
              errors: [
                "No toolset is currently equipped. Use equip-toolset to load a toolset first.",
                ...(toolsetNames.length > 0
                  ? [`Available toolsets: ${toolsetNames.join(", ")}`]
                  : ["No saved toolsets found. Use build-toolset to create one."]),
              ],
            };
    
            return {
              content: [
                {
                  type: "text",
                  text: JSON.stringify(response),
                },
              ],
            };
          }
    
          // Check if discovery engine is available
          if (!deps.discoveryEngine) {
            const response: AddToolAnnotationResponse = {
              toolset: deps.toolsetManager.getCurrentToolset()?.name || "",
              tool: {
                namespacedName: "",
                refId: "",
                server: "",
              },
              addedNotes: [],
              successCount: 0,
              errorCount: 1,
              errors: [
                "Tool discovery not available. Server may not be fully started.",
              ],
            };
    
            return {
              content: [
                {
                  type: "text",
                  text: JSON.stringify(response),
                },
              ],
            };
          }
    
          try {
            const toolRef = args?.toolRef as DynamicToolReference;
            const notes = args?.notes as ToolsetToolNote[];
    
            // Validate tool reference
            if (!toolRef || (!toolRef.namespacedName && !toolRef.refId)) {
              const response: AddToolAnnotationResponse = {
                toolset: deps.toolsetManager.getCurrentToolset()?.name || "",
                tool: {
                  namespacedName: "",
                  refId: "",
                  server: "",
                },
                addedNotes: [],
                successCount: 0,
                errorCount: 1,
                errors: [
                  "Invalid tool reference. Must provide either namespacedName or refId.",
                ],
              };
    
              return {
                content: [
                  {
                    type: "text",
                    text: JSON.stringify(response),
                  },
                ],
              };
            }
    
            // Resolve the tool reference
            const resolution = deps.discoveryEngine.resolveToolReference(toolRef, {
              allowStaleRefs: false,
            });
    
            if (!resolution?.exists || !resolution.tool) {
              const response: AddToolAnnotationResponse = {
                toolset: deps.toolsetManager.getCurrentToolset()?.name || "",
                tool: {
                  namespacedName: "",
                  refId: "",
                  server: "",
                },
                addedNotes: [],
                successCount: 0,
                errorCount: 1,
                errors: [
                  `Tool not found: ${toolRef.namespacedName || toolRef.refId}. Use list-available-tools to see available tools.`,
                ],
              };
    
              return {
                content: [
                  {
                    type: "text",
                    text: JSON.stringify(response),
                  },
                ],
              };
            }
    
            // Check if the tool is in the current toolset
            const currentToolset = deps.toolsetManager.getCurrentToolset();
            if (!currentToolset) {
              const response: AddToolAnnotationResponse = {
                toolset: "",
                tool: {
                  namespacedName: resolution.tool.namespacedName,
                  refId: resolution.tool.toolHash,
                  server: resolution.tool.serverName,
                },
                addedNotes: [],
                successCount: 0,
                errorCount: 1,
                errors: ["No toolset configuration loaded."],
              };
    
              return {
                content: [
                  {
                    type: "text",
                    text: JSON.stringify(response),
                  },
                ],
              };
            }
    
            // Verify the tool is part of the current toolset
            const toolInToolset = currentToolset.tools.some((t) => {
              if (
                t.namespacedName &&
                t.namespacedName === resolution.tool!.namespacedName
              ) {
                return true;
              }
              if (t.refId && t.refId === resolution.tool!.toolHash) {
                return true;
              }
              return false;
            });
    
            if (!toolInToolset) {
              const response: AddToolAnnotationResponse = {
                toolset: currentToolset.name,
                tool: {
                  namespacedName: resolution.tool.namespacedName,
                  refId: resolution.tool.toolHash,
                  server: resolution.tool.serverName,
                },
                addedNotes: [],
                successCount: 0,
                errorCount: 1,
                errors: [
                  `Tool "${resolution.tool.namespacedName}" is not in the current toolset "${currentToolset.name}".`,
                ],
              };
    
              return {
                content: [
                  {
                    type: "text",
                    text: JSON.stringify(response),
                  },
                ],
              };
            }
    
            // Initialize toolNotes array if it doesn't exist
            if (!currentToolset.toolNotes) {
              currentToolset.toolNotes = [];
            }
    
            // Find existing notes for this tool
            let toolNotesEntry = currentToolset.toolNotes.find((entry) => {
              if (
                entry.toolRef.namespacedName &&
                entry.toolRef.namespacedName === resolution.tool!.namespacedName
              ) {
                return true;
              }
              if (
                entry.toolRef.refId &&
                entry.toolRef.refId === resolution.tool!.toolHash
              ) {
                return true;
              }
              return false;
            });
    
            // Create new entry if none exists
            if (!toolNotesEntry) {
              toolNotesEntry = {
                toolRef: {
                  namespacedName: resolution.tool.namespacedName,
                  refId: resolution.tool.toolHash,
                },
                notes: [],
              };
              currentToolset.toolNotes.push(toolNotesEntry);
            }
    
            // Add new notes (skip duplicates)
            const addedNotes: ToolsetToolNote[] = [];
            const skippedNotes: string[] = [];
    
            for (const note of notes) {
              const existingNote = toolNotesEntry.notes.find(
                (n) => n.name === note.name
              );
              if (existingNote) {
                skippedNotes.push(note.name);
              } else {
                toolNotesEntry.notes.push(note);
                addedNotes.push(note);
              }
            }
    
            // Update the last modified timestamp
            currentToolset.lastModified = new Date();
    
            // Save the updated toolset to preferences
            try {
              const preferences = await import(
                "../../../../config/preferenceStore.js"
              );
              const loadToolsetsFromPreferences = preferences.loadStoredToolsets;
              const saveToolsetsToPreferences = preferences.saveStoredToolsets;
    
              const stored = await loadToolsetsFromPreferences();
              stored[currentToolset.name] = currentToolset;
              await saveToolsetsToPreferences(stored);
            } catch (error) {
              const response: AddToolAnnotationResponse = {
                toolset: currentToolset.name,
                tool: {
                  namespacedName: resolution.tool.namespacedName,
                  refId: resolution.tool.toolHash,
                  server: resolution.tool.serverName,
                },
                addedNotes: [],
                successCount: 0,
                errorCount: 1,
                errors: [
                  `Failed to save annotations: ${error instanceof Error ? error.message : String(error)}`,
                ],
              };
    
              return {
                content: [
                  {
                    type: "text",
                    text: JSON.stringify(response),
                  },
                ],
              };
            }
    
            // Emit toolset change event to refresh tools
            deps.toolsetManager.setCurrentToolset(currentToolset);
    
            // Prepare response
            const response: AddToolAnnotationResponse = {
              toolset: currentToolset.name,
              tool: {
                namespacedName: resolution.tool.namespacedName,
                refId: resolution.tool.toolHash,
                server: resolution.tool.serverName,
              },
              addedNotes,
              successCount: addedNotes.length,
              errorCount: skippedNotes.length,
              errors:
                skippedNotes.length > 0
                  ? skippedNotes.map(
                      (name) => `Annotation "${name}" already exists`
                    )
                  : undefined,
            };
    
            return {
              content: [
                {
                  type: "text",
                  text: JSON.stringify(response),
                },
              ],
              structuredContent: response,
            };
          } catch (error) {
            const response: AddToolAnnotationResponse = {
              toolset: deps.toolsetManager.getCurrentToolset()?.name || "",
              tool: {
                namespacedName: "",
                refId: "",
                server: "",
              },
              addedNotes: [],
              successCount: 0,
              errorCount: 1,
              errors: [
                `Failed to add annotations: ${
                  error instanceof Error ? error.message : String(error)
                }`,
              ],
            };
    
            return {
              content: [
                {
                  type: "text",
                  text: JSON.stringify(response),
                },
              ],
            };
          }
        },
      };
    };
  • Tool definition object with name, description, detailed inputSchema (JSON Schema for parameters), and reference to output schema.
    export const addToolAnnotationDefinition: Tool = {
      name: "add-tool-annotation",
      description:
        "Add contextual annotations to a tool in the current toolset to guide LLM usage. Annotations provide user-specific guidance, best practices, and usage notes that will be displayed with the tool's description. Example: {toolRef: {namespacedName: 'linear.create_issue'}, notes: [{name: 'team-selection', note: 'Always confirm team with user first'}]}",
      inputSchema: {
        type: "object" as const,
        properties: {
          toolRef: {
            type: "object",
            description:
              "Reference to the tool (use namespacedName or refId). Use list-available-tools to find the correct reference.",
            properties: {
              namespacedName: {
                type: "string",
                description:
                  "Tool reference by namespaced name (e.g., 'linear.create_issue', 'git.status')",
              },
              refId: {
                type: "string",
                description:
                  "Tool reference by unique hash identifier (shown in list-available-tools output)",
              },
            },
            oneOf: [{ required: ["namespacedName"] }, { required: ["refId"] }],
            additionalProperties: false,
          },
          notes: {
            type: "array",
            description:
              "Array of annotations to add to the tool. Each annotation has a name (identifier) and note (content).",
            minItems: 1,
            maxItems: 20,
            items: {
              type: "object",
              properties: {
                name: {
                  type: "string",
                  description:
                    "Identifier for this annotation (e.g., 'usage-tips', 'team-conventions', 'common-pitfalls')",
                  pattern: "^[a-z0-9-]+$",
                  minLength: 2,
                  maxLength: 50,
                },
                note: {
                  type: "string",
                  description:
                    "The annotation content to help guide LLM usage. Be clear and specific.",
                  minLength: 1,
                  maxLength: 500,
                },
              },
              required: ["name", "note"],
              additionalProperties: false,
            },
          },
        },
        required: ["toolRef", "notes"],
        additionalProperties: false,
      },
      outputSchema: addToolAnnotationResponseSchema as any,
    };
  • Registers the createAddToolAnnotationModule factory in the central CONFIG_TOOL_FACTORIES array used for configuration tools.
    export const CONFIG_TOOL_FACTORIES: ToolModuleFactory[] = [
      createListAvailableToolsModule,
      createBuildToolsetModule,
      createListSavedToolsetsModule,
      createEquipToolsetModule,
      createDeleteToolsetModule,
      createUnequipToolsetModule,
      createGetActiveToolsetModule,
      createAddToolAnnotationModule,
      createListPersonasModule, // Persona management tool
      createExitConfigurationModeModule,
    ];
  • Zod schema and JSON schema conversion for the tool's output response structure (AddToolAnnotationResponse).
    export const addToolAnnotationResponseSchema = zodToJsonSchema(
Behavior3/5

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

With no annotations provided, the description carries the full burden. It explains the tool's purpose and provides an example, but doesn't disclose important behavioral traits like whether annotations are persistent across sessions, if they override existing ones, what permissions are required, or how they integrate with the toolset system. The example helps but leaves operational details unclear.

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 perfectly front-loaded with the core purpose in the first sentence, followed by supporting details about what annotations provide, and concludes with a practical example. Every sentence earns its place with no redundant information, making it efficient and well-structured.

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 with nested objects), 100% schema coverage, and presence of an output schema, the description is reasonably complete. It explains the purpose and provides an example, though it could benefit from mentioning how these annotations affect tool usage in practice or referencing the output schema's role.

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?

With 100% schema description coverage, the baseline is 3. The description adds value by providing a concrete example that illustrates how both parameters (toolRef and notes) work together in practice, showing the structure of annotations with specific field examples. This enhances understanding beyond the schema's technical definitions.

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 contextual annotations'), target resource ('to a tool in the current toolset'), and purpose ('to guide LLM usage'). It distinguishes this from sibling tools like 'list-available-tools' or 'build-toolset' by focusing on annotation management rather than tool discovery or set construction.

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 about when to use this tool ('to guide LLM usage') and includes an example annotation structure. However, it doesn't explicitly state when NOT to use it or mention alternatives like modifying existing annotations versus adding new ones, which prevents a perfect score.

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

Related 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/toolprint/hypertool-mcp'

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