Commit 5d2408c

mo khan <mo@mokhan.ca>
2025-08-14 23:30:20
fix: tools/list for all servers
1 parent d305088
pkg/bash/handlers.go
@@ -390,4 +390,4 @@ func toJSONString(data interface{}) string {
 		return fmt.Sprintf("Error serializing data: %v", err)
 	}
 	return string(jsonData)
-}
\ No newline at end of file
+}
pkg/bash/server.go
@@ -150,23 +150,38 @@ func ConfigFromEnv() *Config {
 
 // registerTools registers all bash tools with the server
 func (bs *BashServer) registerTools() {
-	// Core execution tools
-	bs.RegisterTool("bash_exec", bs.HandleBashExec)
-	bs.RegisterTool("bash_exec_stream", bs.HandleBashExecStream)
+	// Get all tool definitions from ListTools method
+	tools := bs.ListTools()
 	
-	// Documentation tools
-	bs.RegisterTool("man_page", bs.HandleManPage)
-	bs.RegisterTool("which_command", bs.HandleWhichCommand)
-	bs.RegisterTool("command_help", bs.HandleCommandHelp)
-	
-	// Environment management tools
-	bs.RegisterTool("get_env", bs.HandleGetEnv)
-	bs.RegisterTool("get_working_dir", bs.HandleGetWorkingDir)
-	bs.RegisterTool("set_working_dir", bs.HandleSetWorkingDir)
-	
-	// System information tools
-	bs.RegisterTool("system_info", bs.HandleSystemInfo)
-	bs.RegisterTool("process_info", bs.HandleProcessInfo)
+	// Register each tool with its proper definition
+	for _, tool := range tools {
+		var handler mcp.ToolHandler
+		switch tool.Name {
+		case "bash_exec":
+			handler = bs.HandleBashExec
+		case "bash_exec_stream":
+			handler = bs.HandleBashExecStream
+		case "man_page":
+			handler = bs.HandleManPage
+		case "which_command":
+			handler = bs.HandleWhichCommand
+		case "command_help":
+			handler = bs.HandleCommandHelp
+		case "get_env":
+			handler = bs.HandleGetEnv
+		case "get_working_dir":
+			handler = bs.HandleGetWorkingDir
+		case "set_working_dir":
+			handler = bs.HandleSetWorkingDir
+		case "system_info":
+			handler = bs.HandleSystemInfo
+		case "process_info":
+			handler = bs.HandleProcessInfo
+		default:
+			continue
+		}
+		bs.RegisterToolWithDefinition(tool, handler)
+	}
 }
 
 // registerResources registers MCP resources
pkg/fetch/server.go
@@ -53,7 +53,20 @@ func New() *Server {
 
 // registerTools registers all Fetch tools with the server
 func (fs *Server) registerTools() {
-	fs.RegisterTool("fetch", fs.HandleFetch)
+	// Get all tool definitions from ListTools method
+	tools := fs.ListTools()
+	
+	// Register each tool with its proper definition
+	for _, tool := range tools {
+		var handler mcp.ToolHandler
+		switch tool.Name {
+		case "fetch":
+			handler = fs.HandleFetch
+		default:
+			continue
+		}
+		fs.RegisterToolWithDefinition(tool, handler)
+	}
 }
 
 // registerPrompts registers all Fetch prompts with the server
pkg/filesystem/server.go
@@ -47,18 +47,42 @@ func New(allowedDirs []string) *Server {
 
 // registerTools registers all Filesystem tools with the server
 func (fs *Server) registerTools() {
-	fs.RegisterTool("read_file", fs.HandleReadFile)
-	fs.RegisterTool("read_multiple_files", fs.HandleReadMultipleFiles)
-	fs.RegisterTool("write_file", fs.HandleWriteFile)
-	fs.RegisterTool("edit_file", fs.HandleEditFile)
-	fs.RegisterTool("create_directory", fs.HandleCreateDirectory)
-	fs.RegisterTool("list_directory", fs.HandleListDirectory)
-	fs.RegisterTool("list_directory_with_sizes", fs.HandleListDirectoryWithSizes)
-	fs.RegisterTool("directory_tree", fs.HandleDirectoryTree)
-	fs.RegisterTool("move_file", fs.HandleMoveFile)
-	fs.RegisterTool("search_files", fs.HandleSearchFiles)
-	fs.RegisterTool("get_file_info", fs.HandleGetFileInfo)
-	fs.RegisterTool("list_allowed_directories", fs.HandleListAllowedDirectories)
+	// Get all tool definitions from ListTools method
+	tools := fs.ListTools()
+	
+	// Register each tool with its proper definition
+	for _, tool := range tools {
+		var handler mcp.ToolHandler
+		switch tool.Name {
+		case "read_file":
+			handler = fs.HandleReadFile
+		case "read_multiple_files":
+			handler = fs.HandleReadMultipleFiles
+		case "write_file":
+			handler = fs.HandleWriteFile
+		case "edit_file":
+			handler = fs.HandleEditFile
+		case "create_directory":
+			handler = fs.HandleCreateDirectory
+		case "list_directory":
+			handler = fs.HandleListDirectory
+		case "list_directory_with_sizes":
+			handler = fs.HandleListDirectoryWithSizes
+		case "directory_tree":
+			handler = fs.HandleDirectoryTree
+		case "move_file":
+			handler = fs.HandleMoveFile
+		case "search_files":
+			handler = fs.HandleSearchFiles
+		case "get_file_info":
+			handler = fs.HandleGetFileInfo
+		case "list_allowed_directories":
+			handler = fs.HandleListAllowedDirectories
+		default:
+			continue
+		}
+		fs.RegisterToolWithDefinition(tool, handler)
+	}
 }
 
 // registerPrompts registers all Filesystem prompts with the server
pkg/git/server.go
@@ -144,18 +144,42 @@ func (gs *Server) ListResources() []mcp.Resource {
 
 // registerTools registers all Git tools with the server
 func (gs *Server) registerTools() {
-	gs.RegisterTool("git_status", gs.HandleGitStatus)
-	gs.RegisterTool("git_diff_unstaged", gs.HandleGitDiffUnstaged)
-	gs.RegisterTool("git_diff_staged", gs.HandleGitDiffStaged)
-	gs.RegisterTool("git_diff", gs.HandleGitDiff)
-	gs.RegisterTool("git_commit", gs.HandleGitCommit)
-	gs.RegisterTool("git_add", gs.HandleGitAdd)
-	gs.RegisterTool("git_reset", gs.HandleGitReset)
-	gs.RegisterTool("git_log", gs.HandleGitLog)
-	gs.RegisterTool("git_create_branch", gs.HandleGitCreateBranch)
-	gs.RegisterTool("git_checkout", gs.HandleGitCheckout)
-	gs.RegisterTool("git_show", gs.HandleGitShow)
-	gs.RegisterTool("git_init", gs.HandleGitInit)
+	// Get all tool definitions from ListTools method
+	tools := gs.ListTools()
+	
+	// Register each tool with its proper definition
+	for _, tool := range tools {
+		var handler mcp.ToolHandler
+		switch tool.Name {
+		case "git_status":
+			handler = gs.HandleGitStatus
+		case "git_diff_unstaged":
+			handler = gs.HandleGitDiffUnstaged
+		case "git_diff_staged":
+			handler = gs.HandleGitDiffStaged
+		case "git_diff":
+			handler = gs.HandleGitDiff
+		case "git_commit":
+			handler = gs.HandleGitCommit
+		case "git_add":
+			handler = gs.HandleGitAdd
+		case "git_reset":
+			handler = gs.HandleGitReset
+		case "git_log":
+			handler = gs.HandleGitLog
+		case "git_create_branch":
+			handler = gs.HandleGitCreateBranch
+		case "git_checkout":
+			handler = gs.HandleGitCheckout
+		case "git_show":
+			handler = gs.HandleGitShow
+		case "git_init":
+			handler = gs.HandleGitInit
+		default:
+			continue
+		}
+		gs.RegisterToolWithDefinition(tool, handler)
+	}
 }
 
 // registerPrompts registers all Git prompts with the server
pkg/gitlab/server.go
@@ -120,21 +120,203 @@ func NewServer(gitlabURL, token string) (*Server, error) {
 		cache: cache,
 	}
 
-	// Register tools for GitLab employee workflow
-	server.RegisterTool("gitlab_list_my_projects", server.handleListMyProjects)
-	server.RegisterTool("gitlab_list_my_issues", server.handleListMyIssues)
-	server.RegisterTool("gitlab_get_issue_conversations", server.handleGetIssueConversations)
-	server.RegisterTool("gitlab_find_similar_issues", server.handleFindSimilarIssues)
-	server.RegisterTool("gitlab_get_my_activity", server.handleGetMyActivity)
-	
-	// Register cache management tools
-	server.RegisterTool("gitlab_cache_stats", server.handleCacheStats)
-	server.RegisterTool("gitlab_cache_clear", server.handleCacheClear)
-	server.RegisterTool("gitlab_offline_query", server.handleOfflineQuery)
+	// Register tools
+	server.registerTools()
 
 	return server, nil
 }
 
+// ListTools returns all available GitLab tools
+func (s *Server) ListTools() []mcp.Tool {
+	return []mcp.Tool{
+		{
+			Name:        "gitlab_list_my_projects",
+			Description: "List projects where you are a member, with activity and access level info",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"limit": map[string]interface{}{
+						"type":        "integer",
+						"description": "Maximum number of projects to return",
+						"minimum":     1,
+						"default":     20,
+					},
+					"archived": map[string]interface{}{
+						"type":        "boolean",
+						"description": "Include archived projects",
+						"default":     false,
+					},
+				},
+			},
+		},
+		{
+			Name:        "gitlab_list_my_issues",
+			Description: "List issues assigned to you, created by you, or where you're mentioned",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"scope": map[string]interface{}{
+						"type":        "string",
+						"description": "Filter scope: assigned_to_me, authored, mentioned, all",
+						"default":     "assigned_to_me",
+						"enum":        []string{"assigned_to_me", "authored", "mentioned", "all"},
+					},
+					"state": map[string]interface{}{
+						"type":        "string",
+						"description": "Issue state filter: opened, closed, all",
+						"default":     "opened",
+						"enum":        []string{"opened", "closed", "all"},
+					},
+					"limit": map[string]interface{}{
+						"type":        "integer",
+						"description": "Maximum number of issues to return",
+						"minimum":     1,
+						"default":     50,
+					},
+				},
+			},
+		},
+		{
+			Name:        "gitlab_get_issue_conversations",
+			Description: "Get full conversation history for a specific issue including notes and system events",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"project_id": map[string]interface{}{
+						"type":        "integer",
+						"description": "GitLab project ID",
+						"minimum":     1,
+					},
+					"issue_iid": map[string]interface{}{
+						"type":        "integer",
+						"description": "Issue internal ID within the project",
+						"minimum":     1,
+					},
+				},
+				"required": []string{"project_id", "issue_iid"},
+			},
+		},
+		{
+			Name:        "gitlab_find_similar_issues",
+			Description: "Find issues similar to a search query across your accessible projects",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"query": map[string]interface{}{
+						"type":        "string",
+						"description": "Search query for finding similar issues",
+					},
+					"limit": map[string]interface{}{
+						"type":        "integer",
+						"description": "Maximum number of results",
+						"minimum":     1,
+						"default":     20,
+					},
+				},
+				"required": []string{"query"},
+			},
+		},
+		{
+			Name:        "gitlab_get_my_activity",
+			Description: "Get recent activity summary including commits, issues, merge requests",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"limit": map[string]interface{}{
+						"type":        "integer",
+						"description": "Maximum number of activity events",
+						"minimum":     1,
+						"default":     50,
+					},
+				},
+			},
+		},
+		{
+			Name:        "gitlab_cache_stats",
+			Description: "Get cache performance statistics and storage information",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+			},
+		},
+		{
+			Name:        "gitlab_cache_clear",
+			Description: "Clear cached data for specific types or all cached data",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"cache_type": map[string]interface{}{
+						"type":        "string",
+						"description": "Type of cache to clear: issues, projects, users, notes, events, search, or empty for all",
+						"enum":        []string{"issues", "projects", "users", "notes", "events", "search"},
+					},
+					"confirm": map[string]interface{}{
+						"type":        "string",
+						"description": "Confirmation string 'true' to proceed with cache clearing",
+					},
+				},
+				"required": []string{"confirm"},
+			},
+		},
+		{
+			Name:        "gitlab_offline_query",
+			Description: "Query cached GitLab data when network connectivity is unavailable",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"query_type": map[string]interface{}{
+						"type":        "string",
+						"description": "Type of cached data to query: issues, projects, users, notes, events",
+						"enum":        []string{"issues", "projects", "users", "notes", "events"},
+					},
+					"search": map[string]interface{}{
+						"type":        "string",
+						"description": "Optional search term to filter cached results",
+					},
+					"limit": map[string]interface{}{
+						"type":        "integer",
+						"description": "Maximum number of results to return",
+						"minimum":     1,
+						"default":     50,
+					},
+				},
+				"required": []string{"query_type"},
+			},
+		},
+	}
+}
+
+// registerTools registers all GitLab tools with the server
+func (s *Server) registerTools() {
+	// Get all tool definitions from ListTools method
+	tools := s.ListTools()
+	
+	// Register each tool with its proper definition
+	for _, tool := range tools {
+		var handler mcp.ToolHandler
+		switch tool.Name {
+		case "gitlab_list_my_projects":
+			handler = s.handleListMyProjects
+		case "gitlab_list_my_issues":
+			handler = s.handleListMyIssues
+		case "gitlab_get_issue_conversations":
+			handler = s.handleGetIssueConversations
+		case "gitlab_find_similar_issues":
+			handler = s.handleFindSimilarIssues
+		case "gitlab_get_my_activity":
+			handler = s.handleGetMyActivity
+		case "gitlab_cache_stats":
+			handler = s.handleCacheStats
+		case "gitlab_cache_clear":
+			handler = s.handleCacheClear
+		case "gitlab_offline_query":
+			handler = s.handleOfflineQuery
+		default:
+			continue
+		}
+		s.RegisterToolWithDefinition(tool, handler)
+	}
+}
+
 func (s *Server) makeRequest(method, endpoint string, params map[string]string) ([]byte, error) {
 	return s.makeRequestWithCache(method, endpoint, params, "")
 }
pkg/imap/server.go
@@ -1001,4 +1001,4 @@ func (s *Server) Close() error {
 	}
 	s.connected = false
 	return nil
-}
\ No newline at end of file
+}
pkg/maildir/server.go
@@ -94,15 +94,159 @@ func New(allowedPaths []string) *Server {
 }
 
 
+// ListTools returns all available Maildir tools
+func (ms *Server) ListTools() []mcp.Tool {
+	return []mcp.Tool{
+		{
+			Name:        "maildir_scan_folders",
+			Description: "Scan and list all folders in the Maildir structure",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+			},
+		},
+		{
+			Name:        "maildir_list_messages",
+			Description: "List messages in a specific folder with optional pagination and filtering",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"folder": map[string]interface{}{
+						"type":        "string",
+						"description": "The folder name to list messages from",
+					},
+					"limit": map[string]interface{}{
+						"type":        "integer",
+						"description": "Maximum number of messages to return",
+						"minimum":     1,
+						"default":     50,
+					},
+					"offset": map[string]interface{}{
+						"type":        "integer",
+						"description": "Number of messages to skip",
+						"minimum":     0,
+						"default":     0,
+					},
+					"unread_only": map[string]interface{}{
+						"type":        "boolean",
+						"description": "Only return unread messages",
+						"default":     false,
+					},
+				},
+				"required": []string{"folder"},
+			},
+		},
+		{
+			Name:        "maildir_read_message",
+			Description: "Read the full content of a specific message",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"message_id": map[string]interface{}{
+						"type":        "string",
+						"description": "The unique message ID",
+					},
+				},
+				"required": []string{"message_id"},
+			},
+		},
+		{
+			Name:        "maildir_search_messages",
+			Description: "Search for messages across all folders using various criteria",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"query": map[string]interface{}{
+						"type":        "string",
+						"description": "Search query string",
+					},
+					"sender": map[string]interface{}{
+						"type":        "string",
+						"description": "Filter by sender email or name",
+					},
+					"subject": map[string]interface{}{
+						"type":        "string",
+						"description": "Filter by subject line",
+					},
+					"folder": map[string]interface{}{
+						"type":        "string",
+						"description": "Limit search to specific folder",
+					},
+					"limit": map[string]interface{}{
+						"type":        "integer",
+						"description": "Maximum number of results",
+						"minimum":     1,
+						"default":     50,
+					},
+				},
+			},
+		},
+		{
+			Name:        "maildir_get_thread",
+			Description: "Get all messages in a conversation thread",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"message_id": map[string]interface{}{
+						"type":        "string",
+						"description": "Message ID to find thread for",
+					},
+				},
+				"required": []string{"message_id"},
+			},
+		},
+		{
+			Name:        "maildir_analyze_contacts",
+			Description: "Analyze contact frequency and relationship data from email history",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"limit": map[string]interface{}{
+						"type":        "integer",
+						"description": "Maximum number of contacts to analyze",
+						"minimum":     1,
+						"default":     100,
+					},
+				},
+			},
+		},
+		{
+			Name:        "maildir_get_statistics",
+			Description: "Get comprehensive statistics about the maildir including message counts, storage usage, and activity patterns",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+			},
+		},
+	}
+}
+
 // registerTools registers all Maildir tools with the server
 func (ms *Server) registerTools() {
-	ms.RegisterTool("maildir_scan_folders", ms.HandleScanFolders)
-	ms.RegisterTool("maildir_list_messages", ms.HandleListMessages)
-	ms.RegisterTool("maildir_read_message", ms.HandleReadMessage)
-	ms.RegisterTool("maildir_search_messages", ms.HandleSearchMessages)
-	ms.RegisterTool("maildir_get_thread", ms.HandleGetThread)
-	ms.RegisterTool("maildir_analyze_contacts", ms.HandleAnalyzeContacts)
-	ms.RegisterTool("maildir_get_statistics", ms.HandleGetStatistics)
+	// Get all tool definitions from ListTools method
+	tools := ms.ListTools()
+	
+	// Register each tool with its proper definition
+	for _, tool := range tools {
+		var handler mcp.ToolHandler
+		switch tool.Name {
+		case "maildir_scan_folders":
+			handler = ms.HandleScanFolders
+		case "maildir_list_messages":
+			handler = ms.HandleListMessages
+		case "maildir_read_message":
+			handler = ms.HandleReadMessage
+		case "maildir_search_messages":
+			handler = ms.HandleSearchMessages
+		case "maildir_get_thread":
+			handler = ms.HandleGetThread
+		case "maildir_analyze_contacts":
+			handler = ms.HandleAnalyzeContacts
+		case "maildir_get_statistics":
+			handler = ms.HandleGetStatistics
+		default:
+			continue
+		}
+		ms.RegisterToolWithDefinition(tool, handler)
+	}
 }
 
 // registerPrompts registers all Maildir prompts with the server
pkg/mcp/server.go
@@ -19,6 +19,7 @@ type Server struct {
 
 	// Handler functions
 	toolHandlers        map[string]ToolHandler
+	toolDefinitions     map[string]Tool
 	promptHandlers      map[string]PromptHandler
 	promptDefinitions   map[string]Prompt
 	resourceHandlers    map[string]ResourceHandler
@@ -46,6 +47,7 @@ func NewServer(name, version string) *Server {
 		name:                  name,
 		version:               version,
 		toolHandlers:          make(map[string]ToolHandler),
+		toolDefinitions:       make(map[string]Tool),
 		promptHandlers:        make(map[string]PromptHandler),
 		promptDefinitions:     make(map[string]Prompt),
 		resourceHandlers:      make(map[string]ResourceHandler),
@@ -62,11 +64,13 @@ func NewServer(name, version string) *Server {
 	}
 }
 
-// RegisterTool registers a tool handler
-func (s *Server) RegisterTool(name string, handler ToolHandler) {
+
+// RegisterToolWithDefinition registers a tool with its full definition and handler
+func (s *Server) RegisterToolWithDefinition(tool Tool, handler ToolHandler) {
 	s.mu.Lock()
 	defer s.mu.Unlock()
-	s.toolHandlers[name] = handler
+	s.toolHandlers[tool.Name] = handler
+	s.toolDefinitions[tool.Name] = tool
 }
 
 // RegisterPrompt registers a prompt with its definition and handler
@@ -125,18 +129,9 @@ func (s *Server) ListTools() []Tool {
 	s.mu.RLock()
 	defer s.mu.RUnlock()
 
-	tools := make([]Tool, 0, len(s.toolHandlers))
-	for name := range s.toolHandlers {
-		// Tools will be defined by individual servers
-		// This is a placeholder - real implementation would store tool definitions
-		tools = append(tools, Tool{
-			Name:        name,
-			Description: "Tool: " + name,
-			InputSchema: map[string]interface{}{
-				"type":       "object",
-				"properties": map[string]interface{}{},
-			},
-		})
+	tools := make([]Tool, 0, len(s.toolDefinitions))
+	for _, tool := range s.toolDefinitions {
+		tools = append(tools, tool)
 	}
 
 	return tools
pkg/memory/server.go
@@ -80,15 +80,36 @@ func (ms *Server) ensureGraphLoaded() error {
 
 // registerTools registers all Memory tools with the server
 func (ms *Server) registerTools() {
-	ms.RegisterTool("create_entities", ms.HandleCreateEntities)
-	ms.RegisterTool("create_relations", ms.HandleCreateRelations)
-	ms.RegisterTool("add_observations", ms.HandleAddObservations)
-	ms.RegisterTool("delete_entities", ms.HandleDeleteEntities)
-	ms.RegisterTool("delete_observations", ms.HandleDeleteObservations)
-	ms.RegisterTool("delete_relations", ms.HandleDeleteRelations)
-	ms.RegisterTool("read_graph", ms.HandleReadGraph)
-	ms.RegisterTool("search_nodes", ms.HandleSearchNodes)
-	ms.RegisterTool("open_nodes", ms.HandleOpenNodes)
+	// Get all tool definitions from ListTools method
+	tools := ms.ListTools()
+	
+	// Register each tool with its proper definition
+	for _, tool := range tools {
+		var handler mcp.ToolHandler
+		switch tool.Name {
+		case "create_entities":
+			handler = ms.HandleCreateEntities
+		case "create_relations":
+			handler = ms.HandleCreateRelations
+		case "add_observations":
+			handler = ms.HandleAddObservations
+		case "delete_entities":
+			handler = ms.HandleDeleteEntities
+		case "delete_observations":
+			handler = ms.HandleDeleteObservations
+		case "delete_relations":
+			handler = ms.HandleDeleteRelations
+		case "read_graph":
+			handler = ms.HandleReadGraph
+		case "search_nodes":
+			handler = ms.HandleSearchNodes
+		case "open_nodes":
+			handler = ms.HandleOpenNodes
+		default:
+			continue
+		}
+		ms.RegisterToolWithDefinition(tool, handler)
+	}
 }
 
 // registerPrompts registers all Memory prompts with the server
pkg/packages/server.go
@@ -26,32 +26,356 @@ func NewServer() *Server {
 		Server: baseServer,
 	}
 
-	// Register Cargo tools
-	server.RegisterTool("cargo_build", server.handleCargoBuild)
-	server.RegisterTool("cargo_run", server.handleCargoRun)
-	server.RegisterTool("cargo_test", server.handleCargoTest)
-	server.RegisterTool("cargo_add", server.handleCargoAdd)
-	server.RegisterTool("cargo_update", server.handleCargoUpdate)
-	server.RegisterTool("cargo_check", server.handleCargoCheck)
-	server.RegisterTool("cargo_clippy", server.handleCargoClippy)
-
-	// Register Homebrew tools
-	server.RegisterTool("brew_install", server.handleBrewInstall)
-	server.RegisterTool("brew_uninstall", server.handleBrewUninstall)
-	server.RegisterTool("brew_search", server.handleBrewSearch)
-	server.RegisterTool("brew_update", server.handleBrewUpdate)
-	server.RegisterTool("brew_upgrade", server.handleBrewUpgrade)
-	server.RegisterTool("brew_doctor", server.handleBrewDoctor)
-	server.RegisterTool("brew_list", server.handleBrewList)
-
-	// Register cross-platform tools
-	server.RegisterTool("check_vulnerabilities", server.handleCheckVulnerabilities)
-	server.RegisterTool("outdated_packages", server.handleOutdatedPackages)
-	server.RegisterTool("package_info", server.handlePackageInfo)
+	server.registerTools()
 
 	return server
 }
 
+// ListTools returns all available package management tools
+func (s *Server) ListTools() []mcp.Tool {
+	return []mcp.Tool{
+		// Cargo tools
+		{
+			Name:        "cargo_build",
+			Description: "Build a Rust project using Cargo",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"directory": map[string]interface{}{
+						"type":        "string",
+						"description": "Project directory (optional, defaults to current directory)",
+					},
+					"release": map[string]interface{}{
+						"type":        "boolean",
+						"description": "Build in release mode (default: false)",
+					},
+					"target": map[string]interface{}{
+						"type":        "string",
+						"description": "Target triple to build for (optional)",
+					},
+					"features": map[string]interface{}{
+						"type":        "string",
+						"description": "Space-separated list of features to activate",
+					},
+				},
+			},
+		},
+		{
+			Name:        "cargo_run",
+			Description: "Run a Rust project using Cargo",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"directory": map[string]interface{}{
+						"type":        "string",
+						"description": "Project directory (optional, defaults to current directory)",
+					},
+					"release": map[string]interface{}{
+						"type":        "boolean",
+						"description": "Run in release mode (default: false)",
+					},
+					"args": map[string]interface{}{
+						"type":        "string",
+						"description": "Arguments to pass to the program",
+					},
+				},
+			},
+		},
+		{
+			Name:        "cargo_test",
+			Description: "Run tests for a Rust project using Cargo",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"directory": map[string]interface{}{
+						"type":        "string",
+						"description": "Project directory (optional, defaults to current directory)",
+					},
+					"test_name": map[string]interface{}{
+						"type":        "string",
+						"description": "Name of specific test to run (optional)",
+					},
+					"release": map[string]interface{}{
+						"type":        "boolean",
+						"description": "Run tests in release mode (default: false)",
+					},
+				},
+			},
+		},
+		{
+			Name:        "cargo_add",
+			Description: "Add a dependency to a Rust project",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"directory": map[string]interface{}{
+						"type":        "string",
+						"description": "Project directory (optional, defaults to current directory)",
+					},
+					"package": map[string]interface{}{
+						"type":        "string",
+						"description": "Package name to add",
+					},
+					"version": map[string]interface{}{
+						"type":        "string",
+						"description": "Version requirement (optional)",
+					},
+					"dev": map[string]interface{}{
+						"type":        "boolean",
+						"description": "Add as dev dependency (default: false)",
+					},
+				},
+				"required": []string{"package"},
+			},
+		},
+		{
+			Name:        "cargo_update",
+			Description: "Update dependencies in a Rust project",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"directory": map[string]interface{}{
+						"type":        "string",
+						"description": "Project directory (optional, defaults to current directory)",
+					},
+					"package": map[string]interface{}{
+						"type":        "string",
+						"description": "Specific package to update (optional, updates all if not specified)",
+					},
+				},
+			},
+		},
+		{
+			Name:        "cargo_check",
+			Description: "Check a Rust project for errors without building",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"directory": map[string]interface{}{
+						"type":        "string",
+						"description": "Project directory (optional, defaults to current directory)",
+					},
+				},
+			},
+		},
+		{
+			Name:        "cargo_clippy",
+			Description: "Run Clippy linter on a Rust project",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"directory": map[string]interface{}{
+						"type":        "string",
+						"description": "Project directory (optional, defaults to current directory)",
+					},
+					"fix": map[string]interface{}{
+						"type":        "boolean",
+						"description": "Automatically apply fixes (default: false)",
+					},
+				},
+			},
+		},
+		// Homebrew tools
+		{
+			Name:        "brew_install",
+			Description: "Install a package using Homebrew",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"package": map[string]interface{}{
+						"type":        "string",
+						"description": "Package name to install",
+					},
+					"cask": map[string]interface{}{
+						"type":        "boolean",
+						"description": "Install as cask (GUI application) (default: false)",
+					},
+				},
+				"required": []string{"package"},
+			},
+		},
+		{
+			Name:        "brew_uninstall",
+			Description: "Uninstall a package using Homebrew",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"package": map[string]interface{}{
+						"type":        "string",
+						"description": "Package name to uninstall",
+					},
+					"cask": map[string]interface{}{
+						"type":        "boolean",
+						"description": "Uninstall as cask (GUI application) (default: false)",
+					},
+				},
+				"required": []string{"package"},
+			},
+		},
+		{
+			Name:        "brew_search",
+			Description: "Search for packages in Homebrew",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"query": map[string]interface{}{
+						"type":        "string",
+						"description": "Search query",
+					},
+					"cask": map[string]interface{}{
+						"type":        "boolean",
+						"description": "Search in casks (GUI applications) (default: false)",
+					},
+				},
+				"required": []string{"query"},
+			},
+		},
+		{
+			Name:        "brew_update",
+			Description: "Update Homebrew and formulae",
+			InputSchema: map[string]interface{}{
+				"type":       "object",
+				"properties": map[string]interface{}{},
+			},
+		},
+		{
+			Name:        "brew_upgrade",
+			Description: "Upgrade installed packages using Homebrew",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"package": map[string]interface{}{
+						"type":        "string",
+						"description": "Specific package to upgrade (optional, upgrades all if not specified)",
+					},
+				},
+			},
+		},
+		{
+			Name:        "brew_doctor",
+			Description: "Check Homebrew for potential problems",
+			InputSchema: map[string]interface{}{
+				"type":       "object",
+				"properties": map[string]interface{}{},
+			},
+		},
+		{
+			Name:        "brew_list",
+			Description: "List installed packages in Homebrew",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"cask": map[string]interface{}{
+						"type":        "boolean",
+						"description": "List casks (GUI applications) (default: false)",
+					},
+				},
+			},
+		},
+		// Cross-platform tools
+		{
+			Name:        "check_vulnerabilities",
+			Description: "Check for known vulnerabilities in dependencies",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"directory": map[string]interface{}{
+						"type":        "string",
+						"description": "Project directory (optional, defaults to current directory)",
+					},
+					"format": map[string]interface{}{
+						"type":        "string",
+						"description": "Output format (json, table) (default: table)",
+						"enum":        []string{"json", "table"},
+					},
+				},
+			},
+		},
+		{
+			Name:        "outdated_packages",
+			Description: "Check for outdated packages in the project",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"directory": map[string]interface{}{
+						"type":        "string",
+						"description": "Project directory (optional, defaults to current directory)",
+					},
+				},
+			},
+		},
+		{
+			Name:        "package_info",
+			Description: "Get detailed information about a package",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"package": map[string]interface{}{
+						"type":        "string",
+						"description": "Package name to get information about",
+					},
+					"manager": map[string]interface{}{
+						"type":        "string",
+						"description": "Package manager (cargo, brew, npm, pip) (optional, auto-detected)",
+						"enum":        []string{"cargo", "brew", "npm", "pip"},
+					},
+				},
+				"required": []string{"package"},
+			},
+		},
+	}
+}
+
+// registerTools registers all package management tools with the server
+func (s *Server) registerTools() {
+	// Get all tool definitions from ListTools method
+	tools := s.ListTools()
+	
+	// Register each tool with its proper definition
+	for _, tool := range tools {
+		var handler mcp.ToolHandler
+		switch tool.Name {
+		case "cargo_build":
+			handler = s.handleCargoBuild
+		case "cargo_run":
+			handler = s.handleCargoRun
+		case "cargo_test":
+			handler = s.handleCargoTest
+		case "cargo_add":
+			handler = s.handleCargoAdd
+		case "cargo_update":
+			handler = s.handleCargoUpdate
+		case "cargo_check":
+			handler = s.handleCargoCheck
+		case "cargo_clippy":
+			handler = s.handleCargoClippy
+		case "brew_install":
+			handler = s.handleBrewInstall
+		case "brew_uninstall":
+			handler = s.handleBrewUninstall
+		case "brew_search":
+			handler = s.handleBrewSearch
+		case "brew_update":
+			handler = s.handleBrewUpdate
+		case "brew_upgrade":
+			handler = s.handleBrewUpgrade
+		case "brew_doctor":
+			handler = s.handleBrewDoctor
+		case "brew_list":
+			handler = s.handleBrewList
+		case "check_vulnerabilities":
+			handler = s.handleCheckVulnerabilities
+		case "outdated_packages":
+			handler = s.handleOutdatedPackages
+		case "package_info":
+			handler = s.handlePackageInfo
+		default:
+			continue
+		}
+		s.RegisterToolWithDefinition(tool, handler)
+	}
+}
+
 // Cargo tool handlers
 
 func (s *Server) handleCargoBuild(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
pkg/semantic/server.go
@@ -32,19 +32,239 @@ func NewServer() *Server {
 		projectManager: projectManager,
 	}
 
-	// Phase 1: Core symbol discovery tools
-	server.RegisterTool("semantic_find_symbol", server.handleFindSymbol)
-	server.RegisterTool("semantic_get_overview", server.handleGetOverview)
-	server.RegisterTool("semantic_get_definition", server.handleGetDefinition)
-
-	// Phase 2: Analysis & relationship tools
-	server.RegisterTool("semantic_get_references", server.handleGetReferences)
-	server.RegisterTool("semantic_get_call_hierarchy", server.handleGetCallHierarchy)
-	server.RegisterTool("semantic_analyze_dependencies", server.handleAnalyzeDependencies)
+	server.registerTools()
 
 	return server
 }
 
+// ListTools returns all available semantic analysis tools
+func (s *Server) ListTools() []mcp.Tool {
+	return []mcp.Tool{
+		// Core symbol discovery tools
+		{
+			Name:        "semantic_find_symbol",
+			Description: "Find symbols by name, type, or pattern across the project",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"query": map[string]interface{}{
+						"type":        "string",
+						"description": "Symbol name or pattern to search for",
+					},
+					"symbol_type": map[string]interface{}{
+						"type":        "string",
+						"description": "Type of symbol to search for (function, class, variable, etc.)",
+						"enum":        []string{"function", "class", "variable", "interface", "type", "constant", "module"},
+					},
+					"language": map[string]interface{}{
+						"type":        "string",
+						"description": "Programming language to filter by (optional)",
+						"enum":        []string{"go", "rust", "typescript", "javascript", "python", "java", "cpp"},
+					},
+					"case_sensitive": map[string]interface{}{
+						"type":        "boolean",
+						"description": "Whether the search should be case sensitive (default: false)",
+					},
+					"exact_match": map[string]interface{}{
+						"type":        "boolean",
+						"description": "Whether to match the exact symbol name (default: false, allows partial matches)",
+					},
+				},
+				"required": []string{"query"},
+			},
+		},
+		{
+			Name:        "semantic_get_overview",
+			Description: "Get a high-level overview of symbols and structure in a file or directory",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"path": map[string]interface{}{
+						"type":        "string",
+						"description": "File or directory path to analyze",
+					},
+					"depth": map[string]interface{}{
+						"type":        "integer",
+						"description": "Depth of analysis (1=top-level only, 2=include immediate children, etc.) (default: 2)",
+						"minimum":     1,
+						"maximum":     5,
+					},
+					"include_private": map[string]interface{}{
+						"type":        "boolean",
+						"description": "Include private/internal symbols (default: false)",
+					},
+					"group_by": map[string]interface{}{
+						"type":        "string",
+						"description": "How to group the results (type, file, module) (default: type)",
+						"enum":        []string{"type", "file", "module"},
+					},
+				},
+				"required": []string{"path"},
+			},
+		},
+		{
+			Name:        "semantic_get_definition",
+			Description: "Get the definition location and details for a specific symbol",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"symbol": map[string]interface{}{
+						"type":        "string",
+						"description": "Symbol name to find definition for",
+					},
+					"file": map[string]interface{}{
+						"type":        "string",
+						"description": "File path where the symbol is referenced (helps with context)",
+					},
+					"line": map[string]interface{}{
+						"type":        "integer",
+						"description": "Line number where the symbol is referenced (optional, for better precision)",
+						"minimum":     1,
+					},
+					"column": map[string]interface{}{
+						"type":        "integer",
+						"description": "Column number where the symbol is referenced (optional, for better precision)",
+						"minimum":     1,
+					},
+					"include_signature": map[string]interface{}{
+						"type":        "boolean",
+						"description": "Include full function/method signature (default: true)",
+					},
+				},
+				"required": []string{"symbol"},
+			},
+		},
+		{
+			Name:        "semantic_get_references",
+			Description: "Find all references to a specific symbol across the project",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"symbol": map[string]interface{}{
+						"type":        "string",
+						"description": "Symbol name to find references for",
+					},
+					"file": map[string]interface{}{
+						"type":        "string",
+						"description": "File path where the symbol is defined (helps with context)",
+					},
+					"line": map[string]interface{}{
+						"type":        "integer",
+						"description": "Line number where the symbol is defined (optional, for better precision)",
+						"minimum":     1,
+					},
+					"include_declaration": map[string]interface{}{
+						"type":        "boolean",
+						"description": "Include the symbol declaration in results (default: true)",
+					},
+					"scope": map[string]interface{}{
+						"type":        "string",
+						"description": "Scope of search (file, directory, project) (default: project)",
+						"enum":        []string{"file", "directory", "project"},
+					},
+				},
+				"required": []string{"symbol"},
+			},
+		},
+		{
+			Name:        "semantic_get_call_hierarchy",
+			Description: "Get the call hierarchy (callers and callees) for a function or method",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"symbol": map[string]interface{}{
+						"type":        "string",
+						"description": "Function or method name to analyze",
+					},
+					"file": map[string]interface{}{
+						"type":        "string",
+						"description": "File path where the function is defined",
+					},
+					"line": map[string]interface{}{
+						"type":        "integer",
+						"description": "Line number where the function is defined (optional)",
+						"minimum":     1,
+					},
+					"direction": map[string]interface{}{
+						"type":        "string",
+						"description": "Direction of call hierarchy (incoming=who calls this, outgoing=what this calls, both) (default: both)",
+						"enum":        []string{"incoming", "outgoing", "both"},
+					},
+					"depth": map[string]interface{}{
+						"type":        "integer",
+						"description": "Depth of call hierarchy to retrieve (default: 3)",
+						"minimum":     1,
+						"maximum":     10,
+					},
+				},
+				"required": []string{"symbol", "file"},
+			},
+		},
+		{
+			Name:        "semantic_analyze_dependencies",
+			Description: "Analyze dependencies and relationships between modules, files, or symbols",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"path": map[string]interface{}{
+						"type":        "string",
+						"description": "Path to analyze (file, directory, or project root)",
+					},
+					"analysis_type": map[string]interface{}{
+						"type":        "string",
+						"description": "Type of dependency analysis to perform (default: imports)",
+						"enum":        []string{"imports", "exports", "modules", "symbols", "circular"},
+					},
+					"include_external": map[string]interface{}{
+						"type":        "boolean",
+						"description": "Include external/third-party dependencies (default: false)",
+					},
+					"format": map[string]interface{}{
+						"type":        "string",
+						"description": "Output format (tree, graph, list) (default: tree)",
+						"enum":        []string{"tree", "graph", "list"},
+					},
+					"max_depth": map[string]interface{}{
+						"type":        "integer",
+						"description": "Maximum depth of dependency analysis (default: 5)",
+						"minimum":     1,
+						"maximum":     20,
+					},
+				},
+				"required": []string{"path"},
+			},
+		},
+	}
+}
+
+// registerTools registers all semantic analysis tools with the server
+func (s *Server) registerTools() {
+	// Get all tool definitions from ListTools method
+	tools := s.ListTools()
+	
+	// Register each tool with its proper definition
+	for _, tool := range tools {
+		var handler mcp.ToolHandler
+		switch tool.Name {
+		case "semantic_find_symbol":
+			handler = s.handleFindSymbol
+		case "semantic_get_overview":
+			handler = s.handleGetOverview
+		case "semantic_get_definition":
+			handler = s.handleGetDefinition
+		case "semantic_get_references":
+			handler = s.handleGetReferences
+		case "semantic_get_call_hierarchy":
+			handler = s.handleGetCallHierarchy
+		case "semantic_analyze_dependencies":
+			handler = s.handleAnalyzeDependencies
+		default:
+			continue
+		}
+		s.RegisterToolWithDefinition(tool, handler)
+	}
+}
+
 // handleFindSymbol finds symbols by name, type, or pattern across the project
 func (s *Server) handleFindSymbol(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	s.mu.RLock()
pkg/signal/server.go
@@ -82,13 +82,7 @@ func NewServer(signalPath string) (*Server, error) {
 	}
 
 	// Register tools
-	server.RegisterTool("signal_list_conversations", server.handleListConversations)
-	server.RegisterTool("signal_search_messages", server.handleSearchMessages)
-	server.RegisterTool("signal_get_conversation", server.handleGetConversation)
-	server.RegisterTool("signal_get_contact", server.handleGetContact)
-	server.RegisterTool("signal_get_message", server.handleGetMessage)
-	server.RegisterTool("signal_list_attachments", server.handleListAttachments)
-	server.RegisterTool("signal_get_stats", server.handleGetStats)
+	server.registerTools()
 
 	// Register prompts
 	conversationPrompt := mcp.Prompt{
@@ -105,6 +99,159 @@ func NewServer(signalPath string) (*Server, error) {
 	return server, nil
 }
 
+// ListTools returns all available Signal tools
+func (s *Server) ListTools() []mcp.Tool {
+	return []mcp.Tool{
+		{
+			Name:        "signal_list_conversations",
+			Description: "List recent Signal conversations with timestamps and participants",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"limit": map[string]interface{}{
+						"type":        "integer",
+						"description": "Maximum number of conversations to return",
+						"minimum":     1,
+						"default":     20,
+					},
+				},
+			},
+		},
+		{
+			Name:        "signal_search_messages",
+			Description: "Search Signal messages by content with filtering options",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"query": map[string]interface{}{
+						"type":        "string",
+						"description": "Search query string",
+					},
+					"conversation_id": map[string]interface{}{
+						"type":        "string",
+						"description": "Optional conversation ID to limit search scope",
+					},
+					"limit": map[string]interface{}{
+						"type":        "integer",
+						"description": "Maximum number of results",
+						"minimum":     1,
+						"default":     50,
+					},
+				},
+				"required": []string{"query"},
+			},
+		},
+		{
+			Name:        "signal_get_conversation",
+			Description: "Get detailed conversation history including all messages and metadata",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"conversation_id": map[string]interface{}{
+						"type":        "string",
+						"description": "The conversation ID to retrieve",
+					},
+					"limit": map[string]interface{}{
+						"type":        "integer",
+						"description": "Maximum number of messages to return",
+						"minimum":     1,
+						"default":     100,
+					},
+				},
+				"required": []string{"conversation_id"},
+			},
+		},
+		{
+			Name:        "signal_get_contact",
+			Description: "Get detailed contact information by ID, phone number, or name",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"contact_id": map[string]interface{}{
+						"type":        "string",
+						"description": "Contact ID, phone number, or display name",
+					},
+				},
+				"required": []string{"contact_id"},
+			},
+		},
+		{
+			Name:        "signal_get_message",
+			Description: "Get detailed information about a specific message including attachments and reactions",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"message_id": map[string]interface{}{
+						"type":        "string",
+						"description": "The message ID to retrieve",
+					},
+				},
+				"required": []string{"message_id"},
+			},
+		},
+		{
+			Name:        "signal_list_attachments",
+			Description: "List message attachments with metadata and filtering options",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"conversation_id": map[string]interface{}{
+						"type":        "string",
+						"description": "Optional conversation ID to filter attachments",
+					},
+					"media_type": map[string]interface{}{
+						"type":        "string",
+						"description": "Filter by media type (image, video, audio, file)",
+					},
+					"limit": map[string]interface{}{
+						"type":        "integer",
+						"description": "Maximum number of attachments to return",
+						"minimum":     1,
+						"default":     50,
+					},
+				},
+			},
+		},
+		{
+			Name:        "signal_get_stats",
+			Description: "Get Signal database statistics and connection information",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+			},
+		},
+	}
+}
+
+// registerTools registers all Signal tools with the server
+func (s *Server) registerTools() {
+	// Get all tool definitions from ListTools method
+	tools := s.ListTools()
+	
+	// Register each tool with its proper definition
+	for _, tool := range tools {
+		var handler mcp.ToolHandler
+		switch tool.Name {
+		case "signal_list_conversations":
+			handler = s.handleListConversations
+		case "signal_search_messages":
+			handler = s.handleSearchMessages
+		case "signal_get_conversation":
+			handler = s.handleGetConversation
+		case "signal_get_contact":
+			handler = s.handleGetContact
+		case "signal_get_message":
+			handler = s.handleGetMessage
+		case "signal_list_attachments":
+			handler = s.handleListAttachments
+		case "signal_get_stats":
+			handler = s.handleGetStats
+		default:
+			continue
+		}
+		s.RegisterToolWithDefinition(tool, handler)
+	}
+}
+
 func findSignalPaths() (dbPath, configPath string, err error) {
 	var basePath string
 	
pkg/speech/server.go
@@ -56,15 +56,139 @@ func NewServer() *Server {
 	}
 
 	// Register speech tools
-	server.RegisterTool("say", server.handleSay)
-	server.RegisterTool("list_voices", server.handleListVoices)
-	server.RegisterTool("speak_file", server.handleSpeakFile)
-	server.RegisterTool("stop_speech", server.handleStopSpeech)
-	server.RegisterTool("speech_settings", server.handleSpeechSettings)
+	server.registerTools()
 
 	return server
 }
 
+// registerTools registers all Speech tools with the server
+func (s *Server) registerTools() {
+	// Get all tool definitions from ListTools method
+	tools := s.ListTools()
+	
+	// Register each tool with its proper definition
+	for _, tool := range tools {
+		var handler mcp.ToolHandler
+		switch tool.Name {
+		case "say":
+			handler = s.handleSay
+		case "list_voices":
+			handler = s.handleListVoices
+		case "speak_file":
+			handler = s.handleSpeakFile
+		case "stop_speech":
+			handler = s.handleStopSpeech
+		case "speech_settings":
+			handler = s.handleSpeechSettings
+		default:
+			continue
+		}
+		s.RegisterToolWithDefinition(tool, handler)
+	}
+}
+
+// ListTools returns all available Speech tools
+func (s *Server) ListTools() []mcp.Tool {
+	return []mcp.Tool{
+		{
+			Name:        "say",
+			Description: "Convert text to speech using system TTS. Supports voice selection, speech rate, volume, and audio file output",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"text": map[string]interface{}{
+						"type":        "string",
+						"description": "The text to speak",
+					},
+					"voice": map[string]interface{}{
+						"type":        "string",
+						"description": "Voice to use (platform-specific). Use list_voices to see available options",
+					},
+					"rate": map[string]interface{}{
+						"type":        "integer",
+						"description": "Speech rate in words per minute (80-500). macOS: 80-500, Linux: 80-450",
+						"minimum":     80,
+						"maximum":     500,
+					},
+					"volume": map[string]interface{}{
+						"type":        "number",
+						"description": "Volume level (0.0-1.0). macOS only - Linux ignores this parameter",
+						"minimum":     0.0,
+						"maximum":     1.0,
+					},
+					"output": map[string]interface{}{
+						"type":        "string",
+						"description": "Output audio file path. macOS: .aiff, .wav, .m4a. Linux: .wav only",
+					},
+				},
+				"required": []string{"text"},
+			},
+		},
+		{
+			Name:        "list_voices",
+			Description: "List available TTS voices on the system, optionally filtered by language",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"language": map[string]interface{}{
+						"type":        "string",
+						"description": "Filter voices by language code (e.g., 'en', 'fr', 'de')",
+					},
+				},
+			},
+		},
+		{
+			Name:        "speak_file",
+			Description: "Read and speak the contents of a text file with optional line limiting",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+				"properties": map[string]interface{}{
+					"filepath": map[string]interface{}{
+						"type":        "string",
+						"description": "Path to the text file to read and speak",
+					},
+					"voice": map[string]interface{}{
+						"type":        "string",
+						"description": "Voice to use (platform-specific)",
+					},
+					"rate": map[string]interface{}{
+						"type":        "integer",
+						"description": "Speech rate in words per minute (80-500)",
+						"minimum":     80,
+						"maximum":     500,
+					},
+					"volume": map[string]interface{}{
+						"type":        "number",
+						"description": "Volume level (0.0-1.0). macOS only",
+						"minimum":     0.0,
+						"maximum":     1.0,
+					},
+					"max_lines": map[string]interface{}{
+						"type":        "integer",
+						"description": "Maximum number of lines to read from the file",
+						"minimum":     1,
+					},
+				},
+				"required": []string{"filepath"},
+			},
+		},
+		{
+			Name:        "stop_speech",
+			Description: "Stop any currently playing speech synthesis",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+			},
+		},
+		{
+			Name:        "speech_settings",
+			Description: "Get information about the speech system including platform, backend, and usage help",
+			InputSchema: map[string]interface{}{
+				"type": "object",
+			},
+		},
+	}
+}
+
 // handleSay speaks the provided text using the system TTS
 func (s *Server) handleSay(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	s.mu.RLock()
pkg/thinking/server.go
@@ -97,11 +97,28 @@ func NewWithPersistence(persistFile string) *Server {
 
 // registerTools registers all Sequential Thinking tools with the server
 func (sts *Server) registerTools() {
-	sts.RegisterTool("sequentialthinking", sts.HandleSequentialThinking)
-	sts.RegisterTool("get_session_history", sts.HandleGetSessionHistory)
-	sts.RegisterTool("list_sessions", sts.HandleListSessions)
-	sts.RegisterTool("get_branch_history", sts.HandleGetBranchHistory)
-	sts.RegisterTool("clear_session", sts.HandleClearSession)
+	// Get all tool definitions from ListTools method
+	tools := sts.ListTools()
+	
+	// Register each tool with its proper definition
+	for _, tool := range tools {
+		var handler mcp.ToolHandler
+		switch tool.Name {
+		case "sequentialthinking":
+			handler = sts.HandleSequentialThinking
+		case "get_session_history":
+			handler = sts.HandleGetSessionHistory
+		case "list_sessions":
+			handler = sts.HandleListSessions
+		case "get_branch_history":
+			handler = sts.HandleGetBranchHistory
+		case "clear_session":
+			handler = sts.HandleClearSession
+		default:
+			continue
+		}
+		sts.RegisterToolWithDefinition(tool, handler)
+	}
 }
 
 // ListTools returns all available Sequential Thinking tools
pkg/time/server.go
@@ -50,8 +50,22 @@ func New() *Server {
 
 // registerTools registers all Time tools with the server
 func (ts *Server) registerTools() {
-	ts.RegisterTool("get_current_time", ts.HandleGetCurrentTime)
-	ts.RegisterTool("convert_time", ts.HandleConvertTime)
+	// Get all tool definitions from ListTools method
+	tools := ts.ListTools()
+	
+	// Register each tool with its proper definition
+	for _, tool := range tools {
+		var handler mcp.ToolHandler
+		switch tool.Name {
+		case "get_current_time":
+			handler = ts.HandleGetCurrentTime
+		case "convert_time":
+			handler = ts.HandleConvertTime
+		default:
+			continue
+		}
+		ts.RegisterToolWithDefinition(tool, handler)
+	}
 }
 
 // ListTools returns all available Time tools