Skip to main content
Glama

build-toolset

Create and customize a personalized toolset by selecting specific tools for your workflow. Define names and include tools by their identifiers to streamline tasks and improve efficiency on the hypertool-mcp server.

Instructions

Build and save a custom toolset by selecting specific tools. Like assembling tools from a workshop - pick the exact tools you need for a specific task or workflow. You must specify which tools to include. Each tool must specify either namespacedName or refId for identification. Example: {name: 'dev-essentials', tools: [{namespacedName: 'git.status'}, {namespacedName: 'docker.ps'}], autoEquip: true} creates and immediately equips a development toolset.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
autoEquipNoAutomatically equip this toolset after creation (default: false)
descriptionNoOptional description of what this toolset is for (e.g., 'Essential tools for web development')
nameYesName for the new toolset. Use lowercase with hyphens (e.g., 'dev-essentials', 'git-workflow', 'debug-kit')
toolsYesArray of tools to include in the toolset. Each tool must specify either namespacedName or refId for identification. Use list-available-tools to see available options.

Implementation Reference

  • The main handler function for the 'build-toolset' MCP tool. It receives input arguments, calls toolsetManager.buildToolset to perform the actual creation, handles auto-equip, and returns the result.
    handler: async (args: any) => {
      if (deps.discoveryEngine) {
        const result = await deps.toolsetManager.buildToolset(
          args?.name || "",
          args?.tools || [],
          {
            description: args?.description,
            autoEquip: args?.autoEquip,
          }
        );
    
        // Auto-exit to normal mode if autoEquip succeeded
        if (args?.autoEquip && result.meta?.success && onModeChangeRequest) {
          onModeChangeRequest();
        }
    
        return {
          content: [
            {
              type: "text",
              text: JSON.stringify(result),
            },
          ],
          structuredContent: result,
        };
      } else {
        return {
          content: [
            {
              type: "text",
              text: "❌ **Tool discovery not available**\n\nDiscovery engine is not initialized. Server may not be fully started.",
            },
          ],
        };
      }
  • Tool definition including input schema for validation and output schema reference. Defines the structure expected for input parameters like name, tools array, description, and autoEquip.
    export const buildToolsetDefinition: Tool = {
      name: "build-toolset",
      description:
        "Build and save a custom toolset by selecting specific tools. Like assembling tools from a workshop - pick the exact tools you need for a specific task or workflow. You must specify which tools to include. Each tool must specify either namespacedName or refId for identification. Example: {name: 'dev-essentials', tools: [{namespacedName: 'git.status'}, {namespacedName: 'docker.ps'}], autoEquip: true} creates and immediately equips a development toolset.",
      inputSchema: {
        type: "object" as const,
        properties: {
          name: {
            type: "string",
            description:
              "Name for the new toolset. Use lowercase with hyphens (e.g., 'dev-essentials', 'git-workflow', 'debug-kit')",
            pattern: "^[a-z0-9-]+$",
            minLength: 2,
            maxLength: 50,
          },
          tools: {
            type: "array",
            description:
              "Array of tools to include in the toolset. Each tool must specify either namespacedName or refId for identification. Use list-available-tools to see available options.",
            minItems: 1,
            maxItems: 100,
            items: {
              type: "object",
              properties: {
                namespacedName: {
                  type: "string",
                  description:
                    "Tool reference by namespaced name (e.g., 'git.status', 'docker.ps')",
                },
                refId: {
                  type: "string",
                  description:
                    "Tool reference by unique hash identifier (e.g., 'abc123def456...')",
                },
              },
              oneOf: [{ required: ["namespacedName"] }, { required: ["refId"] }],
              additionalProperties: false,
            },
          },
          description: {
            type: "string",
            description:
              "Optional description of what this toolset is for (e.g., 'Essential tools for web development')",
            maxLength: 200,
          },
          autoEquip: {
            type: "boolean",
            description:
              "Automatically equip this toolset after creation (default: false)",
          },
        },
        required: ["name", "tools"],
        additionalProperties: false,
      },
      outputSchema: buildToolsetResponseSchema as any,
    };
  • Zod schema and JSON schema for the build-toolset response, defining the output structure including meta (success, error) and toolset info.
    export const buildToolsetResponseZodSchema = z.object({
      meta: z
        .object({
          success: z
            .boolean()
            .describe("Whether the toolset was successfully created"),
          toolsetName: z
            .string()
            .optional()
            .describe("Name of the created toolset"),
          autoEquipped: z
            .boolean()
            .optional()
            .describe(
              "Whether the toolset was automatically equipped after creation"
            ),
          error: z
            .string()
            .optional()
            .describe("Error message if the operation failed"),
        })
        .describe("Operation metadata"),
      toolset: toolsetInfoZodSchema
        .optional()
        .describe("Toolset information (only present if successful)"),
    });
    
    /**
     * Zod schema for equip toolset response
     */
    export const equipToolsetResponseZodSchema = z.object({
      success: z
        .boolean()
        .describe("Whether the toolset was successfully equipped"),
      error: z
        .string()
        .optional()
        .describe("Error message if the operation failed"),
      toolset: toolsetInfoZodSchema
        .optional()
        .describe("Equipped toolset information (only present if successful)"),
    });
    
    /**
     * Zod schema for get active toolset response
     */
    export const getActiveToolsetResponseZodSchema = z.object({
      equipped: z.boolean().describe("Whether a toolset is currently equipped"),
      toolset: toolsetInfoZodSchema
        .optional()
        .describe("Toolset information (only present if equipped)"),
      serverStatus: z
        .object({
          totalConfigured: z
            .number()
            .describe("Total number of configured servers"),
          enabled: z.number().describe("Number of enabled servers"),
          available: z.number().describe("Number of available servers"),
          unavailable: z.number().describe("Number of unavailable servers"),
          disabled: z.number().describe("Number of disabled servers"),
        })
        .optional()
        .describe("Server status summary"),
      toolSummary: z
        .object({
          currentlyExposed: z
            .number()
            .describe("Number of tools currently exposed"),
          totalDiscovered: z.number().describe("Total number of discovered tools"),
          filteredOut: z.number().describe("Number of tools filtered out"),
        })
        .optional()
        .describe("Tool summary information"),
      exposedTools: z
        .record(z.array(toolInfoResponseZodSchema))
        .describe("Tools grouped by server with full details"),
      unavailableServers: z
        .array(z.string())
        .describe("List of unavailable server names"),
      warnings: z.array(z.string()).describe("List of warnings"),
      context: contextInfoZodSchema
        .optional()
        .describe("Context usage information for the exposed tools"),
    });
    
    /**
     * TypeScript types inferred from Zod schemas
     */
    export type ContextInfo = z.infer<typeof contextInfoZodSchema>;
    export type ToolInfoResponse = z.infer<typeof toolInfoResponseZodSchema>;
    export type ListSavedToolsetsResponse = z.infer<
      typeof listSavedToolsetsResponseZodSchema
    >;
    export type BuildToolsetResponse = z.infer<
      typeof buildToolsetResponseZodSchema
    >;
    export type EquipToolsetResponse = z.infer<
      typeof equipToolsetResponseZodSchema
    >;
    export type GetActiveToolsetResponse = z.infer<
      typeof getActiveToolsetResponseZodSchema
    >;
    
    /**
     * JSON Schemas generated from Zod schemas using zod-to-json-schema
     * Note: Using $refStrategy: 'none' to avoid $ref definitions for MCP compatibility
     */
    export const serverConfigSchema = zodToJsonSchema(serverConfigZodSchema, {
      $refStrategy: "none",
    });
    
    export const toolsetInfoSchema = zodToJsonSchema(toolsetInfoZodSchema, {
      $refStrategy: "none",
    });
    
    export const listSavedToolsetsResponseSchema = zodToJsonSchema(
      listSavedToolsetsResponseZodSchema,
      {
        $refStrategy: "none",
      }
    );
    
    export const buildToolsetResponseSchema = zodToJsonSchema(
      buildToolsetResponseZodSchema,
      {
        $refStrategy: "none",
      }
    );
  • Registration of the build-toolset tool factory in the configuration tools factories array.
    export const CONFIG_TOOL_FACTORIES: ToolModuleFactory[] = [
      createListAvailableToolsModule,
      createBuildToolsetModule,
      createListSavedToolsetsModule,
      createEquipToolsetModule,
      createDeleteToolsetModule,
      createUnequipToolsetModule,
      createGetActiveToolsetModule,
      createAddToolAnnotationModule,
      createListPersonasModule, // Persona management tool
      createExitConfigurationModeModule,
    ];
  • Core helper method in ToolsetManager that implements the toolset building logic: validates inputs, resolves tools, saves to user preferences, generates detailed info, and handles auto-equip.
    async buildToolset(
      name: string,
      tools: DynamicToolReference[],
      options: {
        description?: string;
        autoEquip?: boolean;
      } = {}
    ): Promise<BuildToolsetResponse> {
      try {
        // Validate toolset name format
        const namePattern = /^[a-z0-9-]+$/;
        if (!namePattern.test(name)) {
          return {
            meta: {
              success: false,
              error:
                "Invalid toolset name format. Use only lowercase letters, numbers, and hyphens (a-z, 0-9, -)",
            },
          };
        }
    
        if (name.length < 2 || name.length > 50) {
          return {
            meta: {
              success: false,
              error: "Toolset name must be between 2 and 50 characters",
            },
          };
        }
    
        if (!tools || tools.length === 0) {
          return {
            meta: {
              success: false,
              error: "Toolset must include at least one tool",
            },
          };
        }
    
        // Validate tool references if discovery engine is available
        if (this.discoveryEngine) {
          const validationResult = this.validateToolReferences(tools);
          if (!validationResult.valid) {
            return {
              meta: {
                success: false,
                error: `Invalid tool references: ${validationResult.invalidReferences.join(", ")}`,
              },
            };
          }
        }
    
        // Check if toolset already exists
        const preferences = await import("../../../config/preferenceStore.js");
        const loadToolsetsFromPreferences = preferences.loadStoredToolsets;
        const saveToolsetsToPreferences = preferences.saveStoredToolsets;
        const stored = await loadToolsetsFromPreferences();
    
        if (stored[name]) {
          return {
            meta: {
              success: false,
              error: `Toolset "${name}" already exists. Use a different name or delete the existing toolset first.`,
            },
          };
        }
    
        // Create toolset configuration
        const config: ToolsetConfig = {
          name,
          description: options.description,
          version: "1.0.0",
          createdAt: new Date(),
          tools,
        };
    
        // Validate configuration
        const validation = validateToolsetConfig(config);
        if (!validation.valid) {
          return {
            meta: {
              success: false,
              error: `Invalid toolset configuration: ${validation.errors.join(", ")}`,
            },
          };
        }
    
        // Save toolset
        stored[name] = config;
        await saveToolsetsToPreferences(stored);
    
        // Generate detailed toolset information
        const toolsetInfo = await this.generateToolsetInfo(config);
    
        const result = {
          meta: {
            success: true,
            toolsetName: name,
            autoEquipped: false,
          },
          toolset: toolsetInfo,
        };
    
        // Auto-equip if requested
        if (options.autoEquip) {
          const equipResult = await this.equipToolset(name);
          if (equipResult.success) {
            result.meta.autoEquipped = true;
            result.toolset.active = true;
          }
        }
    
        return result;
      } catch (error) {
        return {
          meta: {
            success: false,
            error: `Failed to create toolset: ${error instanceof Error ? error.message : String(error)}`,
          },
        };
      }
    }
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