# Understanding Dynamic Toolsets and On-Demand Tool Discovery in the GitHub MCP Server

> Discover dynamic toolsets and on-demand tool discovery in the GitHub MCP Server. Learn how it reduces token usage and boosts performance by loading tools at runtime.

- Repository: [GitHub/github-mcp-server](https://github.com/github/github-mcp-server)
- Tags: deep-dive
- Published: 2026-02-16

---

**Dynamic toolsets allow the GitHub MCP Server to start with a minimal set of management tools and load additional capabilities at runtime through on-demand discovery, reducing token usage and improving performance.**

The GitHub MCP Server implements a flexible architecture for managing GitHub operations through the Model Context Protocol (MCP). By leveraging dynamic toolsets and on-demand tool discovery, the server can defer loading expensive tool definitions until they are actually needed, optimizing both client resources and server startup time.

## What Are Dynamic Toolsets?

A **dynamic toolset** is a special toolset with the ID `dynamic` that contains three management tools for runtime toolset administration. Unlike static toolsets that load all tools at startup, the dynamic toolset enables clients to discover and enable other toolsets on demand.

The three dynamic management tools are defined in [`pkg/github/dynamic_tools.go`](https://github.com/github/github-mcp-server/blob/main/pkg/github/dynamic_tools.go):

- **`list_available_toolsets`**: Returns every toolset the server knows about, including whether each is currently enabled. Implemented in the `ListAvailableToolsets` function (lines 15-31).
- **`get_toolset_tools`**: Returns the list of tools belonging to a specific toolset without enabling it. Implemented in the `GetToolsetsTools` function (lines 58-78).
- **`enable_toolset`**: Marks a toolset as enabled and registers all its tools with the running server. Implemented in the `EnableToolset` function (lines 80-82).

The dynamic toolset itself is registered in [`pkg/github/tools.go`](https://github.com/github/github-mcp-server/blob/main/pkg/github/tools.go) as `ToolsetMetadataDynamic` (lines 26-31), which identifies it as a regular `ToolsetMetadata` entry with the unique ID `dynamic`.

## How On-Demand Tool Discovery Works

On-demand tool discovery follows a five-step workflow that begins with minimal server startup and progresses to full capability registration.

### 1. Enable Dynamic Mode

Dynamic tool discovery requires explicit activation through either the `--dynamic-toolsets` CLI flag or the `GITHUB_DYNAMIC_TOOLSETS` environment variable. This configuration is documented in [`docs/server-configuration.md`](https://github.com/github/github-mcp-server/blob/main/docs/server-configuration.md) (lines 12-14). Without this flag, the server loads all toolsets statically at startup.

### 2. Start with Minimal Tools

When dynamic mode is active, the server initializes with only the three dynamic management tools enabled. This minimal startup reduces initial token consumption and memory footprint.

### 3. List Available Toolsets

The client calls `list_available_toolsets`, which invokes `Inventory.ToolsetIDs()` and `Inventory.ToolsetDescriptions()` from [`pkg/inventory/registry.go`](https://github.com/github/github-mcp-server/blob/main/pkg/inventory/registry.go). The server returns a JSON payload containing every toolset ID, description, and its current enabled status.

### 4. Inspect Specific Toolsets

Before enabling a toolset, the client can inspect its contents using `get_toolset_tools`. This calls `Inventory.ToolsForToolset` from [`pkg/inventory/filters.go`](https://github.com/github/github-mcp-server/blob/main/pkg/inventory/filters.go) (lines 18-33), which bypasses the enabled-toolset filter to return tool definitions without activating them.

### 5. Enable Toolsets at Runtime

When the client decides to load a toolset, it calls `enable_toolset`. The handler in [`pkg/github/dynamic_tools.go`](https://github.com/github/github-mcp-server/blob/main/pkg/github/dynamic_tools.go) performs three operations:
- Verifies the toolset exists via `Inventory.HasToolset`
- Calls `Inventory.EnableToolset` from [`pkg/inventory/filters.go`](https://github.com/github/github-mcp-server/blob/main/pkg/inventory/filters.go) (lines 47-55) to mark it as enabled
- Retrieves all tools via `Inventory.ToolsForToolset` and registers each with the MCP server using `ServerTool.RegisterFunc`

After registration, these tools become immediately available for normal MCP tool calls.

## Benefits of Dynamic Toolsets

Dynamic toolsets provide three primary advantages for MCP clients and servers.

**Reduced Surface Area**  
Clients start with minimal tool definitions, reducing token usage in system prompts and improving performance. Additional capabilities load only when specific tasks require them.

**Context-Aware Discovery**  
By inspecting toolset contents before enabling them, clients can make informed decisions about whether loading additional tools will help complete a task, avoiding unnecessary resource consumption.

**Security Isolation**  
When operating in read-only or lockdown modes, write-capable tools remain hidden even after a toolset is enabled. The `Inventory.EnableToolset` method respects read-only filters when exposing tools, ensuring security policies persist across dynamic loading operations.

## Practical Implementation Examples

### Enabling Dynamic Mode

Configure your MCP client to launch the server with dynamic toolsets enabled:

```json
{
  "type": "stdio",
  "command": "go",
  "args": [
    "run",
    "./cmd/github-mcp-server",
    "stdio",
    "--dynamic-toolsets"
  ],
  "env": {
    "GITHUB_PERSONAL_ACCESS_TOKEN": "${input:github_token}"
  }
}

```

Alternatively, set the `GITHUB_DYNAMIC_TOOLSETS` environment variable to `true`.

### Listing Available Toolsets

Request the current toolset inventory:

```json
{
  "method": "tools/call",
  "tool": "list_available_toolsets",
  "arguments": {}
}

```

**Response excerpt:**

```json
[
  {"name":"repos","description":"GitHub Repository related tools","can_enable":"true","currently_enabled":"false"},
  {"name":"issues","description":"GitHub Issues related tools","can_enable":"true","currently_enabled":"true"}
]

```

This calls `ListAvailableToolsets` in [`pkg/github/dynamic_tools.go`](https://github.com/github/github-mcp-server/blob/main/pkg/github/dynamic_tools.go), which returns JSON via `utils.NewToolResultText`.

### Inspecting Toolset Contents

Preview tools before enabling them:

```json
{
  "method": "tools/call",
  "tool": "get_toolset_tools",
  "arguments": {"toolset":"repos"}
}

```

**Response excerpt:**

```json
[
  {"name":"search_repositories","description":"Search repositories","can_enable":"true","toolset":"repos"},
  {"name":"get_file_contents","description":"Read a file from a repo","can_enable":"true","toolset":"repos"}
]

```

This invokes `GetToolsetsTools`, which uses `Inventory.ToolsForToolset` from [`pkg/inventory/filters.go`](https://github.com/github/github-mcp-server/blob/main/pkg/inventory/filters.go) to bypass the enabled filter.

### Enabling a Toolset at Runtime

Activate the repositories toolset:

```json
{
  "method": "tools/call",
  "tool": "enable_toolset",
  "arguments": {"toolset":"repos"}
}

```

**Response:**

```json
"Toolset repos enabled with 14 tools"

```

The `EnableToolset` handler in [`pkg/github/dynamic_tools.go`](https://github.com/github/github-mcp-server/blob/main/pkg/github/dynamic_tools.go) calls `Inventory.EnableToolset` from [`pkg/inventory/filters.go`](https://github.com/github/github-mcp-server/blob/main/pkg/inventory/filters.go) and registers each tool via `ServerTool.RegisterFunc`.

### Using Newly Enabled Tools

After enabling the `repos` toolset, immediately call its tools:

```json
{
  "method": "tools/call",
  "tool": "search_repositories",
  "arguments": {"query":"language:go"}
}

```

## Summary

- **Dynamic toolsets** provide a runtime tool management system centered around the `dynamic` toolset ID, which contains three management tools: `list_available_toolsets`, `get_toolset_tools`, and `enable_toolset`.
- **On-demand discovery** requires activating dynamic mode via `--dynamic-toolsets` or `GITHUB_DYNAMIC_TOOLSETS`, then following a workflow: list available toolsets, inspect contents, enable as needed, and register tools via `Inventory.EnableToolset` and `ServerTool.RegisterFunc`.
- **Key source files** include [`pkg/github/dynamic_tools.go`](https://github.com/github/github-mcp-server/blob/main/pkg/github/dynamic_tools.go) (tool handlers), [`pkg/inventory/filters.go`](https://github.com/github/github-mcp-server/blob/main/pkg/inventory/filters.go) (enablement logic), and [`pkg/inventory/registry.go`](https://github.com/github/github-mcp-server/blob/main/pkg/inventory/registry.go) (inventory management).
- **Benefits** include reduced token usage through minimal startup, context-aware capability loading, and maintained security isolation in read-only modes.

## Frequently Asked Questions

### How do I enable dynamic toolsets in the GitHub MCP Server?

You can enable dynamic toolsets by starting the server with the `--dynamic-toolsets` CLI flag or by setting the `GITHUB_DYNAMIC_TOOLSETS` environment variable to `true`. When enabled, the server starts with only the three dynamic management tools (`list_available_toolsets`, `get_toolset_tools`, and `enable_toolset`) rather than loading all available tools immediately.

### What is the difference between the dynamic toolset and other toolsets?

The dynamic toolset (ID: `dynamic`) is a special meta-toolset defined in [`pkg/github/tools.go`](https://github.com/github/github-mcp-server/blob/main/pkg/github/tools.go) that contains only runtime management tools for discovering and enabling other toolsets. Regular toolsets like `repos` or `issues` contain actual GitHub API operations. The dynamic toolset enables on-demand loading of these regular toolsets through the `enable_toolset` tool, while other toolsets provide the actual functionality for interacting with GitHub repositories, issues, pull requests, and other resources.

### Can I disable a toolset after enabling it?

The current implementation in [`pkg/inventory/filters.go`](https://github.com/github/github-mcp-server/blob/main/pkg/inventory/filters.go) provides `EnableToolset` functionality but does not expose a corresponding `disable_toolset` tool in the dynamic toolset. Once a toolset is enabled via the `enable_toolset` tool, its tools remain registered with the server for the duration of the session. To remove capabilities, you would need to restart the server without dynamic mode or with specific toolset exclusions configured at startup.

### How does dynamic tool discovery affect performance?

Dynamic tool discovery significantly improves performance by reducing initial token consumption and memory footprint. When running in dynamic mode, the server only registers three management tools at startup rather than dozens of GitHub API tools. This minimal initialization reduces the size of system prompts sent to language models, lowering token costs and improving response times. Tools are loaded only when explicitly enabled via `enable_toolset`, allowing clients to maintain a lean tool inventory tailored to specific tasks rather than carrying the overhead of unused capabilities.