Skip to content

Conversation

@sashalevin
Copy link

This PR adds a lazy loading mode to semcode-mcp that reduces initial context window consumption by approximately 96%. When enabled via the --lazy flag, the server exposes only three meta-tools (list_categories, get_tools, call_tool) instead of the full set of 16 tools. Claude can then discover available capabilities on-demand by querying categories and retrieving tool schemas only when needed.

The 16 existing tools are organized into five logical categories: code_lookup, code_search, git_history, lore_email, and status. This approach preserves full functionality while dramatically reducing the token overhead for tool discovery, following the patterns described in https://www.anthropic.com/engineering/advanced-tool-use.

Sasha Levin added 8 commits January 17, 2026 15:31
Add foundational support for MCP lazy tool loading:
- Add --lazy CLI flag to Args struct
- Add lazy_mode field to McpServer struct
- Define ToolCategory struct and TOOL_CATEGORIES constant
  with 5 categories: code_lookup, code_search, git_history,
  lore_email, and status
- Update McpServer::new() to accept and store lazy_mode parameter
- Log lazy loading status on server startup

Signed-off-by: Sasha Levin <sashal@kernel.org>
Refactor tool schema definitions to enable lazy loading:
- Add get_tool_schema(name) function returning JSON schema for each
  tool by name via match statement
- Add get_all_tool_schemas() helper returning all 16 tool schemas
- Simplify handle_list_tools() to use get_all_tool_schemas()

This separates tool schema definitions from the MCP handler, enabling
reuse in both the original tools/list response and the upcoming
get_tools meta-tool for lazy loading.

Signed-off-by: Sasha Levin <sashal@kernel.org>
Add the first lazy loading meta-tool for browsing tool categories:
- Add handle_list_categories() method returning formatted list of
  all 5 categories with their descriptions and tool names
- Add "list_categories" case to handle_tool_call() dispatch
- Remove dead_code annotations from ToolCategory and TOOL_CATEGORIES
  now that they are being used

Categories:
1. code_lookup - function/type definition lookup (5 tools)
2. code_search - pattern and semantic search (3 tools)
3. git_history - commit analysis and branches (4 tools)
4. lore_email - kernel mailing list search (3 tools)
5. status - system status (1 tool)

Signed-off-by: Sasha Levin <sashal@kernel.org>
Add the second lazy loading meta-tool for retrieving tool schemas:
- Add handle_get_tools() method that looks up a category by name
  and returns full JSON schemas for all tools in that category
- Add "get_tools" case to handle_tool_call() dispatch
- Return helpful error message with available categories if
  an invalid category name is provided

This allows Claude to progressively discover tool schemas only for
the categories it needs, reducing initial context window usage.

Signed-off-by: Sasha Levin <sashal@kernel.org>
Add the third lazy loading meta-tool for executing tools by name:
- Add handle_call_tool() method that dispatches to underlying tool
  handlers based on tool_name argument
- Add "call_tool" case to handle_tool_call() dispatch
- Dispatch directly to handlers to avoid async recursion issues
- Prevent calling meta-tools via call_tool (returns error message)
- Return helpful error message for unknown tool names

This allows Claude to execute any semcode tool by name after
discovering it through list_categories and get_tools.

Signed-off-by: Sasha Levin <sashal@kernel.org>
Complete the lazy loading feature by modifying handle_list_tools:
- Check self.lazy_mode to determine which tools to return
- In lazy mode: return only 3 meta-tools (list_categories, get_tools,
  call_tool) with their schemas (~230 tokens vs ~6,400 tokens)
- In normal mode: return all 16 tool schemas (existing behavior)
- Remove dead_code annotation from lazy_mode field

The --lazy CLI flag now fully enables lazy tool loading, providing
approximately 96% reduction in initial context window usage.

Signed-off-by: Sasha Levin <sashal@kernel.org>
Add comprehensive test coverage for the lazy loading feature:

Schema tests:
- test_get_tool_schema_returns_valid_schemas: Verify all 16 tools
  have valid schemas with name and inputSchema
- test_get_tool_schema_returns_none_for_unknown: Verify unknown
  tools return None
- test_get_all_tool_schemas_returns_16_tools: Verify correct count
- test_tool_categories_cover_all_tools: Verify categories match
  all available tools

Meta-tool handler tests:
- test_handle_list_categories_returns_all_categories: Verify all 5
  categories are listed
- test_handle_get_tools_returns_schemas_for_category: Verify
  correct tools returned for code_lookup category
- test_handle_get_tools_invalid_category: Verify error handling
- test_handle_call_tool_unknown_tool: Verify error handling
- test_handle_call_tool_prevents_meta_tool_recursion: Verify
  meta-tools cannot be called via call_tool

Mode switching tests:
- test_lazy_mode_returns_meta_tools_only: Verify lazy mode returns
  exactly 3 meta-tools
- test_non_lazy_mode_returns_all_tools: Verify non-lazy mode
  returns all 16 tools

Signed-off-by: Sasha Levin <sashal@kernel.org>
Added comprehensive documentation for the new lazy loading mode in the MCP server,
including:
- The --lazy command line flag
- Context reduction benefits (~96%)
- The three meta-tools: list_categories, get_tools, call_tool
- The expected workflow for clients

Signed-off-by: Sasha Levin <sashal@kernel.org>
@meta-cla meta-cla bot added the CLA Signed This label is managed by the Meta Open Source bot. label Jan 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant