mirror of
https://github.com/hanzoai/python-sdk.git
synced 2026-10-27 04:20:09 +00:00
- Fix import sorting (I001) in all packages - Fix bare except (E722) in lsp_tool.py - Fix duplicate set item (B033) in refactor_tool.py
321 lines
11 KiB
Python
321 lines
11 KiB
Python
"""Tool for managing development modes with programmer personalities."""
|
|
|
|
from typing import Optional, override
|
|
|
|
from mcp.server import FastMCP
|
|
from mcp.server.fastmcp import Context as MCPContext
|
|
from hanzo_mcp.tools.common.mode import ModeRegistry, register_default_modes
|
|
|
|
from hanzo_tools.core import BaseTool, auto_timeout
|
|
|
|
|
|
class ModeTool(BaseTool):
|
|
"""Tool for managing development modes."""
|
|
|
|
name = "mode"
|
|
|
|
def __init__(self):
|
|
"""Initialize the mode tool."""
|
|
super().__init__()
|
|
# Register default modes on initialization
|
|
register_default_modes()
|
|
|
|
@property
|
|
@override
|
|
def description(self) -> str:
|
|
"""Get the tool description."""
|
|
return """Manage development modes (programmer personalities). Actions: list (default), activate, show, current.
|
|
|
|
Usage:
|
|
mode
|
|
mode --action list
|
|
mode --action activate guido
|
|
mode --action show linus
|
|
mode --action current"""
|
|
|
|
@override
|
|
async def run(
|
|
self,
|
|
ctx: MCPContext,
|
|
action: str = "list",
|
|
name: Optional[str] = None,
|
|
) -> str:
|
|
"""Manage development modes.
|
|
|
|
Args:
|
|
ctx: MCP context
|
|
action: Action to perform (list, activate, show, current)
|
|
name: Mode name (for activate/show actions)
|
|
|
|
Returns:
|
|
Action result
|
|
"""
|
|
if action == "list":
|
|
modes = ModeRegistry.list()
|
|
if not modes:
|
|
return "No modes registered"
|
|
|
|
output = ["Available development modes (100 programmer personalities):"]
|
|
active = ModeRegistry.get_active()
|
|
|
|
# Group modes by category
|
|
categories = {
|
|
"Language Creators": [
|
|
"guido",
|
|
"matz",
|
|
"brendan",
|
|
"dennis",
|
|
"bjarne",
|
|
"james",
|
|
"anders",
|
|
"larry",
|
|
"rasmus",
|
|
"rich",
|
|
],
|
|
"Systems & Infrastructure": [
|
|
"linus",
|
|
"rob",
|
|
"ken",
|
|
"bill",
|
|
"richard",
|
|
"brian",
|
|
"donald",
|
|
"graydon",
|
|
"ryan",
|
|
"mitchell",
|
|
],
|
|
"Web & Frontend": [
|
|
"tim",
|
|
"douglas",
|
|
"john",
|
|
"evan",
|
|
"jordan",
|
|
"jeremy",
|
|
"david",
|
|
"taylor",
|
|
"adrian",
|
|
"matt",
|
|
],
|
|
"Database & Data": [
|
|
"michael_s",
|
|
"michael_w",
|
|
"salvatore",
|
|
"dwight",
|
|
"edgar",
|
|
"jim_gray",
|
|
"jeff_dean",
|
|
"sanjay",
|
|
"mike",
|
|
"matei",
|
|
],
|
|
"AI & Machine Learning": [
|
|
"yann",
|
|
"geoffrey",
|
|
"yoshua",
|
|
"andrew",
|
|
"demis",
|
|
"ilya",
|
|
"andrej",
|
|
"chris",
|
|
"francois",
|
|
"jeremy_howard",
|
|
],
|
|
"Security & Cryptography": [
|
|
"bruce",
|
|
"phil",
|
|
"whitfield",
|
|
"ralph",
|
|
"daniel_b",
|
|
"moxie",
|
|
"theo",
|
|
"dan_kaminsky",
|
|
"katie",
|
|
"matt_blaze",
|
|
],
|
|
"Gaming & Graphics": [
|
|
"john_carmack",
|
|
"sid",
|
|
"shigeru",
|
|
"gabe",
|
|
"markus",
|
|
"jonathan",
|
|
"casey",
|
|
"tim_sweeney",
|
|
"hideo",
|
|
"will",
|
|
],
|
|
"Open Source Leaders": [
|
|
"miguel",
|
|
"nat",
|
|
"patrick",
|
|
"ian",
|
|
"mark_shuttleworth",
|
|
"lennart",
|
|
"bram",
|
|
"daniel_r",
|
|
"judd",
|
|
"fabrice",
|
|
],
|
|
"Modern Innovators": [
|
|
"vitalik",
|
|
"satoshi",
|
|
"chris_lattner",
|
|
"joe",
|
|
"jose",
|
|
"sebastian",
|
|
"palmer",
|
|
"dylan",
|
|
"guillermo",
|
|
"tom",
|
|
],
|
|
"Special Configurations": [
|
|
"fullstack",
|
|
"minimal",
|
|
"data_scientist",
|
|
"devops",
|
|
"security",
|
|
"academic",
|
|
"startup",
|
|
"enterprise",
|
|
"creative",
|
|
"hanzo",
|
|
],
|
|
}
|
|
|
|
for category, mode_names in categories.items():
|
|
output.append(f"\n{category}:")
|
|
for mode_name in mode_names:
|
|
mode = next((m for m in modes if m.name == mode_name), None)
|
|
if mode:
|
|
marker = " (active)" if active and active.name == mode.name else ""
|
|
output.append(f" {mode.name}{marker}: {mode.programmer} - {mode.description}")
|
|
|
|
output.append("\nUse 'mode --action activate <name>' to activate a mode")
|
|
|
|
return "\n".join(output)
|
|
|
|
elif action == "activate":
|
|
if not name:
|
|
return "Error: Mode name required for activate action"
|
|
|
|
try:
|
|
ModeRegistry.set_active(name)
|
|
mode = ModeRegistry.get(name)
|
|
|
|
output = [f"Activated mode: {mode.name}"]
|
|
output.append(f"Programmer: {mode.programmer}")
|
|
output.append(f"Description: {mode.description}")
|
|
if mode.philosophy:
|
|
output.append(f"Philosophy: {mode.philosophy}")
|
|
output.append(f"\nEnabled tools ({len(mode.tools)}):")
|
|
|
|
# Group tools by category
|
|
core_tools = []
|
|
package_tools = []
|
|
ai_tools = []
|
|
search_tools = []
|
|
other_tools = []
|
|
|
|
for tool in sorted(mode.tools):
|
|
if tool in [
|
|
"read",
|
|
"write",
|
|
"edit",
|
|
"multi_edit",
|
|
"bash",
|
|
"tree",
|
|
"grep",
|
|
]:
|
|
core_tools.append(tool)
|
|
elif tool in ["npx", "uvx", "pip", "cargo", "gem"]:
|
|
package_tools.append(tool)
|
|
elif tool in ["agent", "consensus", "critic", "think"]:
|
|
ai_tools.append(tool)
|
|
elif tool in ["search", "symbols", "git_search"]:
|
|
search_tools.append(tool)
|
|
else:
|
|
other_tools.append(tool)
|
|
|
|
if core_tools:
|
|
output.append(f" Core: {', '.join(core_tools)}")
|
|
if package_tools:
|
|
output.append(f" Package managers: {', '.join(package_tools)}")
|
|
if ai_tools:
|
|
output.append(f" AI tools: {', '.join(ai_tools)}")
|
|
if search_tools:
|
|
output.append(f" Search: {', '.join(search_tools)}")
|
|
if other_tools:
|
|
output.append(f" Specialized: {', '.join(other_tools)}")
|
|
|
|
if mode.environment:
|
|
output.append("\nEnvironment variables:")
|
|
for key, value in mode.environment.items():
|
|
output.append(f" {key}={value}")
|
|
|
|
output.append("\nNote: Restart MCP session for changes to take full effect")
|
|
|
|
return "\n".join(output)
|
|
|
|
except ValueError as e:
|
|
return str(e)
|
|
|
|
elif action == "show":
|
|
if not name:
|
|
return "Error: Mode name required for show action"
|
|
|
|
mode = ModeRegistry.get(name)
|
|
if not mode:
|
|
return f"Mode '{name}' not found"
|
|
|
|
output = [f"Mode: {mode.name}"]
|
|
output.append(f"Programmer: {mode.programmer}")
|
|
output.append(f"Description: {mode.description}")
|
|
if mode.philosophy:
|
|
output.append(f"Philosophy: {mode.philosophy}")
|
|
output.append(f"\nTools ({len(mode.tools)}):")
|
|
|
|
for tool in sorted(mode.tools):
|
|
output.append(f" - {tool}")
|
|
|
|
if mode.environment:
|
|
output.append("\nEnvironment:")
|
|
for key, value in mode.environment.items():
|
|
output.append(f" {key}={value}")
|
|
|
|
return "\n".join(output)
|
|
|
|
elif action == "current":
|
|
active = ModeRegistry.get_active()
|
|
if not active:
|
|
return "No mode currently active\nUse 'mode --action activate <name>' to activate one"
|
|
|
|
output = [f"Current mode: {active.name}"]
|
|
output.append(f"Programmer: {active.programmer}")
|
|
output.append(f"Description: {active.description}")
|
|
if active.philosophy:
|
|
output.append(f"Philosophy: {active.philosophy}")
|
|
output.append(f"Enabled tools: {len(active.tools)}")
|
|
|
|
return "\n".join(output)
|
|
|
|
else:
|
|
return f"Unknown action: {action}. Use 'list', 'activate', 'show', or 'current'"
|
|
|
|
def register(self, server: FastMCP) -> None:
|
|
"""Register the tool with the MCP server."""
|
|
tool_self = self
|
|
|
|
@server.tool(name=self.name, description=self.description)
|
|
async def mode_handler(ctx: MCPContext, action: str = "list", name: Optional[str] = None) -> str:
|
|
"""Handle mode tool calls."""
|
|
return await tool_self.run(ctx, action=action, name=name)
|
|
|
|
@auto_timeout("mode")
|
|
async def call(self, ctx: MCPContext, **params) -> str:
|
|
"""Call the tool with arguments."""
|
|
return await self.run(ctx, action=params.get("action", "list"), name=params.get("name"))
|
|
|
|
|
|
# Create tool instance
|
|
mode_tool = ModeTool()
|