Understanding Dynamic Toolsets and On-Demand Tool Discovery in the GitHub MCP Server
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:
list_available_toolsets: Returns every toolset the server knows about, including whether each is currently enabled. Implemented in theListAvailableToolsetsfunction (lines 15-31).get_toolset_tools: Returns the list of tools belonging to a specific toolset without enabling it. Implemented in theGetToolsetsToolsfunction (lines 58-78).enable_toolset: Marks a toolset as enabled and registers all its tools with the running server. Implemented in theEnableToolsetfunction (lines 80-82).
The dynamic toolset itself is registered in 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 (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. 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 (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 performs three operations:
- Verifies the toolset exists via
Inventory.HasToolset - Calls
Inventory.EnableToolsetfrompkg/inventory/filters.go(lines 47-55) to mark it as enabled - Retrieves all tools via
Inventory.ToolsForToolsetand registers each with the MCP server usingServerTool.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:
{
"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:
{
"method": "tools/call",
"tool": "list_available_toolsets",
"arguments": {}
}
Response excerpt:
[
{"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, which returns JSON via utils.NewToolResultText.
Inspecting Toolset Contents
Preview tools before enabling them:
{
"method": "tools/call",
"tool": "get_toolset_tools",
"arguments": {"toolset":"repos"}
}
Response excerpt:
[
{"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 to bypass the enabled filter.
Enabling a Toolset at Runtime
Activate the repositories toolset:
{
"method": "tools/call",
"tool": "enable_toolset",
"arguments": {"toolset":"repos"}
}
Response:
"Toolset repos enabled with 14 tools"
The EnableToolset handler in pkg/github/dynamic_tools.go calls Inventory.EnableToolset from pkg/inventory/filters.go and registers each tool via ServerTool.RegisterFunc.
Using Newly Enabled Tools
After enabling the repos toolset, immediately call its tools:
{
"method": "tools/call",
"tool": "search_repositories",
"arguments": {"query":"language:go"}
}
Summary
- Dynamic toolsets provide a runtime tool management system centered around the
dynamictoolset ID, which contains three management tools:list_available_toolsets,get_toolset_tools, andenable_toolset. - On-demand discovery requires activating dynamic mode via
--dynamic-toolsetsorGITHUB_DYNAMIC_TOOLSETS, then following a workflow: list available toolsets, inspect contents, enable as needed, and register tools viaInventory.EnableToolsetandServerTool.RegisterFunc. - Key source files include
pkg/github/dynamic_tools.go(tool handlers),pkg/inventory/filters.go(enablement logic), andpkg/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 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 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →