Commit 5d2408c
Changed files (16)
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