Commit 0bff639

mo khan <mo@mokhan.ca>
2025-06-22 05:49:49
refactor: reorganize servers into pkg/ packages for better modularity
- Move server implementations from cmd/ to pkg/ for reusability - Create dedicated packages for each server: - pkg/gitserver/: Git operations server - pkg/fsserver/: Filesystem operations server - pkg/fetchserver/: Web content fetching server - pkg/memoryserver/: Knowledge graph memory server - pkg/thinkingserver/: Sequential thinking server - pkg/timeserver/: Time and timezone server - Simplify cmd/ directories to contain only thin main.go wrappers - Update all imports and function calls for new package structure - Rename constructors to New() following Go conventions - Fix Makefile build rules for new structure - Update README with improved architecture documentation Benefits: - Better separation of concerns between CLI and business logic - Easier to test and reuse server implementations - Follows Go project layout standards - Maintains all functionality while improving maintainability ๐Ÿค– Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent ff17334
cmd/fetch/main.go
@@ -4,11 +4,12 @@ import (
 	"context"
 	"log"
 
+	"github.com/xlgmokha/mcp/pkg/fetchserver"
 	"github.com/xlgmokha/mcp/pkg/mcp"
 )
 
 func main() {
-	server := NewFetchServer()
+	server := fetchserver.New()
 	
 	// Set up basic initialization
 	server.SetInitializeHandler(func(req mcp.InitializeRequest) (mcp.InitializeResult, error) {
cmd/filesystem/main.go
@@ -5,6 +5,7 @@ import (
 	"log"
 	"os"
 
+	"github.com/xlgmokha/mcp/pkg/fsserver"
 	"github.com/xlgmokha/mcp/pkg/mcp"
 )
 
@@ -15,7 +16,7 @@ func main() {
 	}
 
 	allowedDirs := os.Args[1:]
-	server := NewFilesystemServer(allowedDirs)
+	server := fsserver.New(allowedDirs)
 	
 	// Set up basic initialization
 	server.SetInitializeHandler(func(req mcp.InitializeRequest) (mcp.InitializeResult, error) {
cmd/git/main.go
@@ -4,11 +4,12 @@ import (
 	"context"
 	"log"
 
+	"github.com/xlgmokha/mcp/pkg/gitserver"
 	"github.com/xlgmokha/mcp/pkg/mcp"
 )
 
 func main() {
-	server := NewGitServer()
+	server := gitserver.New()
 	
 	// Set up basic initialization
 	server.SetInitializeHandler(func(req mcp.InitializeRequest) (mcp.InitializeResult, error) {
cmd/memory/main.go
@@ -7,6 +7,7 @@ import (
 	"path/filepath"
 
 	"github.com/xlgmokha/mcp/pkg/mcp"
+	"github.com/xlgmokha/mcp/pkg/memoryserver"
 )
 
 func main() {
@@ -20,7 +21,7 @@ func main() {
 		memoryFile = filepath.Join(homeDir, ".mcp_memory.json")
 	}
 
-	server := NewMemoryServer(memoryFile)
+	server := memoryserver.New(memoryFile)
 	
 	// Set up basic initialization
 	server.SetInitializeHandler(func(req mcp.InitializeRequest) (mcp.InitializeResult, error) {
cmd/sequential-thinking/main.go
@@ -5,10 +5,11 @@ import (
 	"log"
 
 	"github.com/xlgmokha/mcp/pkg/mcp"
+	"github.com/xlgmokha/mcp/pkg/thinkingserver"
 )
 
 func main() {
-	server := NewSequentialThinkingServer()
+	server := thinkingserver.New()
 	
 	// Set up basic initialization
 	server.SetInitializeHandler(func(req mcp.InitializeRequest) (mcp.InitializeResult, error) {
cmd/time/main.go
@@ -5,10 +5,11 @@ import (
 	"log"
 
 	"github.com/xlgmokha/mcp/pkg/mcp"
+	"github.com/xlgmokha/mcp/pkg/timeserver"
 )
 
 func main() {
-	server := NewTimeServer()
+	server := timeserver.New()
 	
 	// Set up basic initialization
 	server.SetInitializeHandler(func(req mcp.InitializeRequest) (mcp.InitializeResult, error) {
cmd/fetch/server.go โ†’ pkg/fetchserver/server.go
@@ -1,4 +1,4 @@
-package main
+package fetchserver
 
 import (
 	"encoding/json"
@@ -14,8 +14,8 @@ import (
 	"golang.org/x/net/html"
 )
 
-// FetchServer implements the Fetch MCP server
-type FetchServer struct {
+// Server implements the Fetch MCP server
+type Server struct {
 	*mcp.Server
 	httpClient *http.Client
 	userAgent  string
@@ -31,11 +31,11 @@ type FetchResult struct {
 	NextIndex   int    `json:"next_index,omitempty"`
 }
 
-// NewFetchServer creates a new Fetch MCP server
-func NewFetchServer() *FetchServer {
+// New creates a new Fetch MCP server
+func New() *Server {
 	server := mcp.NewServer("mcp-fetch", "1.0.0")
 
-	fetchServer := &FetchServer{
+	fetchServer := &Server{
 		Server: server,
 		httpClient: &http.Client{
 			Timeout: 30 * time.Second,
@@ -50,12 +50,12 @@ func NewFetchServer() *FetchServer {
 }
 
 // registerTools registers all Fetch tools with the server
-func (fs *FetchServer) registerTools() {
+func (fs *Server) registerTools() {
 	fs.RegisterTool("fetch", fs.HandleFetch)
 }
 
 // ListTools returns all available Fetch tools
-func (fs *FetchServer) ListTools() []mcp.Tool {
+func (fs *Server) ListTools() []mcp.Tool {
 	return []mcp.Tool{
 		{
 			Name:        "fetch",
@@ -95,7 +95,7 @@ func (fs *FetchServer) ListTools() []mcp.Tool {
 
 // Tool handlers
 
-func (fs *FetchServer) HandleFetch(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (fs *Server) HandleFetch(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	urlStr, ok := req.Arguments["url"].(string)
 	if !ok {
 		return mcp.NewToolError("url is required"), nil
@@ -162,7 +162,7 @@ func (fs *FetchServer) HandleFetch(req mcp.CallToolRequest) (mcp.CallToolResult,
 
 // Helper methods
 
-func (fs *FetchServer) fetchContent(urlStr string, maxLength, startIndex int, raw bool) (*FetchResult, error) {
+func (fs *Server) fetchContent(urlStr string, maxLength, startIndex int, raw bool) (*FetchResult, error) {
 	// Create HTTP request
 	req, err := http.NewRequest("GET", urlStr, nil)
 	if err != nil {
@@ -250,7 +250,7 @@ func isHTMLContent(content, contentType string) bool {
 	return strings.Contains(strings.ToLower(prefix), "<html")
 }
 
-func (fs *FetchServer) htmlToMarkdown(htmlContent string) string {
+func (fs *Server) htmlToMarkdown(htmlContent string) string {
 	// Parse HTML
 	doc, err := html.Parse(strings.NewReader(htmlContent))
 	if err != nil {
@@ -269,7 +269,7 @@ func (fs *FetchServer) htmlToMarkdown(htmlContent string) string {
 	return content
 }
 
-func (fs *FetchServer) extractMarkdown(node *html.Node, result *strings.Builder, depth int) {
+func (fs *Server) extractMarkdown(node *html.Node, result *strings.Builder, depth int) {
 	if node.Type == html.TextNode {
 		text := strings.TrimSpace(node.Data)
 		if text != "" {
@@ -354,7 +354,7 @@ func (fs *FetchServer) extractMarkdown(node *html.Node, result *strings.Builder,
 	}
 }
 
-func (fs *FetchServer) stripHTMLTags(content string) string {
+func (fs *Server) stripHTMLTags(content string) string {
 	// Remove HTML tags using regex
 	re := regexp.MustCompile(`<[^>]*>`)
 	text := re.ReplaceAllString(content, " ")
@@ -366,7 +366,7 @@ func (fs *FetchServer) stripHTMLTags(content string) string {
 	return strings.TrimSpace(text)
 }
 
-func (fs *FetchServer) cleanMarkdown(content string) string {
+func (fs *Server) cleanMarkdown(content string) string {
 	// Remove excessive newlines
 	re := regexp.MustCompile(`\n{3,}`)
 	content = re.ReplaceAllString(content, "\n\n")
cmd/fetch/server_test.go โ†’ pkg/fetchserver/server_test.go
@@ -1,4 +1,4 @@
-package main
+package fetchserver
 
 import (
 	"net/http"
@@ -9,7 +9,7 @@ import (
 	"github.com/xlgmokha/mcp/pkg/mcp"
 )
 
-func TestFetchServer_FetchTool(t *testing.T) {
+func TestServer_FetchTool(t *testing.T) {
 	// Create test server with HTML content
 	testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		w.Header().Set("Content-Type", "text/html")
@@ -27,7 +27,7 @@ func TestFetchServer_FetchTool(t *testing.T) {
 	}))
 	defer testServer.Close()
 
-	server := NewFetchServer()
+	server := New()
 
 	req := mcp.CallToolRequest{
 		Name: "fetch",
@@ -65,7 +65,7 @@ func TestFetchServer_FetchTool(t *testing.T) {
 	}
 }
 
-func TestFetchServer_FetchRawContent(t *testing.T) {
+func TestServer_FetchRawContent(t *testing.T) {
 	// Create test server with HTML content
 	testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		w.Header().Set("Content-Type", "text/html")
@@ -74,7 +74,7 @@ func TestFetchServer_FetchRawContent(t *testing.T) {
 	}))
 	defer testServer.Close()
 
-	server := NewFetchServer()
+	server := New()
 
 	req := mcp.CallToolRequest{
 		Name: "fetch",
@@ -109,7 +109,7 @@ func TestFetchServer_FetchRawContent(t *testing.T) {
 	}
 }
 
-func TestFetchServer_FetchWithMaxLength(t *testing.T) {
+func TestServer_FetchWithMaxLength(t *testing.T) {
 	// Create test server with long plain text content to avoid HTML conversion complexity
 	longContent := strings.Repeat("x", 200) // 200 characters
 	testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -119,7 +119,7 @@ func TestFetchServer_FetchWithMaxLength(t *testing.T) {
 	}))
 	defer testServer.Close()
 
-	server := NewFetchServer()
+	server := New()
 
 	req := mcp.CallToolRequest{
 		Name: "fetch",
@@ -154,7 +154,7 @@ func TestFetchServer_FetchWithMaxLength(t *testing.T) {
 	}
 }
 
-func TestFetchServer_FetchWithStartIndex(t *testing.T) {
+func TestServer_FetchWithStartIndex(t *testing.T) {
 	// Create test server with content
 	testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		w.Header().Set("Content-Type", "text/html")
@@ -163,7 +163,7 @@ func TestFetchServer_FetchWithStartIndex(t *testing.T) {
 	}))
 	defer testServer.Close()
 
-	server := NewFetchServer()
+	server := New()
 
 	req := mcp.CallToolRequest{
 		Name: "fetch",
@@ -196,8 +196,8 @@ func TestFetchServer_FetchWithStartIndex(t *testing.T) {
 	}
 }
 
-func TestFetchServer_FetchInvalidURL(t *testing.T) {
-	server := NewFetchServer()
+func TestServer_FetchInvalidURL(t *testing.T) {
+	server := New()
 
 	req := mcp.CallToolRequest{
 		Name: "fetch",
@@ -225,7 +225,7 @@ func TestFetchServer_FetchInvalidURL(t *testing.T) {
 	}
 }
 
-func TestFetchServer_FetchHTTPError(t *testing.T) {
+func TestServer_FetchHTTPError(t *testing.T) {
 	// Create test server that returns 404
 	testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		w.WriteHeader(http.StatusNotFound)
@@ -233,7 +233,7 @@ func TestFetchServer_FetchHTTPError(t *testing.T) {
 	}))
 	defer testServer.Close()
 
-	server := NewFetchServer()
+	server := New()
 
 	req := mcp.CallToolRequest{
 		Name: "fetch",
@@ -261,7 +261,7 @@ func TestFetchServer_FetchHTTPError(t *testing.T) {
 	}
 }
 
-func TestFetchServer_FetchPlainText(t *testing.T) {
+func TestServer_FetchPlainText(t *testing.T) {
 	// Create test server with plain text content
 	testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		w.Header().Set("Content-Type", "text/plain")
@@ -270,7 +270,7 @@ func TestFetchServer_FetchPlainText(t *testing.T) {
 	}))
 	defer testServer.Close()
 
-	server := NewFetchServer()
+	server := New()
 
 	req := mcp.CallToolRequest{
 		Name: "fetch",
@@ -300,8 +300,8 @@ func TestFetchServer_FetchPlainText(t *testing.T) {
 	}
 }
 
-func TestFetchServer_ListTools(t *testing.T) {
-	server := NewFetchServer()
+func TestServer_ListTools(t *testing.T) {
+	server := New()
 	tools := server.ListTools()
 
 	expectedTools := []string{
cmd/filesystem/server.go โ†’ pkg/fsserver/server.go
@@ -1,4 +1,4 @@
-package main
+package fsserver
 
 import (
 	"fmt"
@@ -11,14 +11,14 @@ import (
 	"github.com/xlgmokha/mcp/pkg/mcp"
 )
 
-// FilesystemServer implements the Filesystem MCP server
-type FilesystemServer struct {
+// Server implements the Filesystem MCP server
+type Server struct {
 	*mcp.Server
 	allowedDirectories []string
 }
 
-// NewFilesystemServer creates a new Filesystem MCP server
-func NewFilesystemServer(allowedDirs []string) *FilesystemServer {
+// New creates a new Filesystem MCP server
+func New(allowedDirs []string) *Server {
 	server := mcp.NewServer("secure-filesystem-server", "0.2.0")
 	
 	// Normalize and validate allowed directories
@@ -31,7 +31,7 @@ func NewFilesystemServer(allowedDirs []string) *FilesystemServer {
 		normalizedDirs[i] = filepath.Clean(absPath)
 	}
 	
-	fsServer := &FilesystemServer{
+	fsServer := &Server{
 		Server:             server,
 		allowedDirectories: normalizedDirs,
 	}
@@ -43,7 +43,7 @@ func NewFilesystemServer(allowedDirs []string) *FilesystemServer {
 }
 
 // registerTools registers all Filesystem tools with the server
-func (fs *FilesystemServer) registerTools() {
+func (fs *Server) registerTools() {
 	fs.RegisterTool("read_file", fs.HandleReadFile)
 	fs.RegisterTool("read_multiple_files", fs.HandleReadMultipleFiles)
 	fs.RegisterTool("write_file", fs.HandleWriteFile)
@@ -59,7 +59,7 @@ func (fs *FilesystemServer) registerTools() {
 }
 
 // ListTools returns all available Filesystem tools
-func (fs *FilesystemServer) ListTools() []mcp.Tool {
+func (fs *Server) ListTools() []mcp.Tool {
 	return []mcp.Tool{
 		{
 			Name:        "read_file",
@@ -287,7 +287,7 @@ func (fs *FilesystemServer) ListTools() []mcp.Tool {
 
 // Tool handlers
 
-func (fs *FilesystemServer) HandleReadFile(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (fs *Server) HandleReadFile(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	pathStr, ok := req.Arguments["path"].(string)
 	if !ok {
 		return mcp.NewToolError("path is required"), nil
@@ -330,7 +330,7 @@ func (fs *FilesystemServer) HandleReadFile(req mcp.CallToolRequest) (mcp.CallToo
 	return mcp.NewToolResult(mcp.NewTextContent(string(content))), nil
 }
 
-func (fs *FilesystemServer) HandleReadMultipleFiles(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (fs *Server) HandleReadMultipleFiles(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	pathsInterface, ok := req.Arguments["paths"]
 	if !ok {
 		return mcp.NewToolError("paths is required"), nil
@@ -361,7 +361,7 @@ func (fs *FilesystemServer) HandleReadMultipleFiles(req mcp.CallToolRequest) (mc
 	return mcp.NewToolResult(mcp.NewTextContent(strings.Join(results, "\n---\n"))), nil
 }
 
-func (fs *FilesystemServer) HandleWriteFile(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (fs *Server) HandleWriteFile(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	pathStr, ok := req.Arguments["path"].(string)
 	if !ok {
 		return mcp.NewToolError("path is required"), nil
@@ -385,7 +385,7 @@ func (fs *FilesystemServer) HandleWriteFile(req mcp.CallToolRequest) (mcp.CallTo
 	return mcp.NewToolResult(mcp.NewTextContent(fmt.Sprintf("Successfully wrote to %s", pathStr))), nil
 }
 
-func (fs *FilesystemServer) HandleEditFile(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (fs *Server) HandleEditFile(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	pathStr, ok := req.Arguments["path"].(string)
 	if !ok {
 		return mcp.NewToolError("path is required"), nil
@@ -422,7 +422,7 @@ func (fs *FilesystemServer) HandleEditFile(req mcp.CallToolRequest) (mcp.CallToo
 	return mcp.NewToolResult(mcp.NewTextContent(diff)), nil
 }
 
-func (fs *FilesystemServer) HandleCreateDirectory(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (fs *Server) HandleCreateDirectory(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	pathStr, ok := req.Arguments["path"].(string)
 	if !ok {
 		return mcp.NewToolError("path is required"), nil
@@ -441,7 +441,7 @@ func (fs *FilesystemServer) HandleCreateDirectory(req mcp.CallToolRequest) (mcp.
 	return mcp.NewToolResult(mcp.NewTextContent(fmt.Sprintf("Successfully created directory %s", pathStr))), nil
 }
 
-func (fs *FilesystemServer) HandleListDirectory(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (fs *Server) HandleListDirectory(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	pathStr, ok := req.Arguments["path"].(string)
 	if !ok {
 		return mcp.NewToolError("path is required"), nil
@@ -469,7 +469,7 @@ func (fs *FilesystemServer) HandleListDirectory(req mcp.CallToolRequest) (mcp.Ca
 	return mcp.NewToolResult(mcp.NewTextContent(strings.Join(formatted, "\n"))), nil
 }
 
-func (fs *FilesystemServer) HandleListDirectoryWithSizes(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (fs *Server) HandleListDirectoryWithSizes(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	pathStr, ok := req.Arguments["path"].(string)
 	if !ok {
 		return mcp.NewToolError("path is required"), nil
@@ -551,7 +551,7 @@ func (fs *FilesystemServer) HandleListDirectoryWithSizes(req mcp.CallToolRequest
 	return mcp.NewToolResult(mcp.NewTextContent(strings.Join(formatted, "\n"))), nil
 }
 
-func (fs *FilesystemServer) HandleDirectoryTree(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (fs *Server) HandleDirectoryTree(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	pathStr, ok := req.Arguments["path"].(string)
 	if !ok {
 		return mcp.NewToolError("path is required"), nil
@@ -570,7 +570,7 @@ func (fs *FilesystemServer) HandleDirectoryTree(req mcp.CallToolRequest) (mcp.Ca
 	return mcp.NewToolResult(mcp.NewTextContent(tree)), nil
 }
 
-func (fs *FilesystemServer) HandleMoveFile(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (fs *Server) HandleMoveFile(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	sourcePath, ok := req.Arguments["source"].(string)
 	if !ok {
 		return mcp.NewToolError("source is required"), nil
@@ -599,7 +599,7 @@ func (fs *FilesystemServer) HandleMoveFile(req mcp.CallToolRequest) (mcp.CallToo
 	return mcp.NewToolResult(mcp.NewTextContent(fmt.Sprintf("Successfully moved %s to %s", sourcePath, destPath))), nil
 }
 
-func (fs *FilesystemServer) HandleSearchFiles(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (fs *Server) HandleSearchFiles(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	pathStr, ok := req.Arguments["path"].(string)
 	if !ok {
 		return mcp.NewToolError("path is required"), nil
@@ -634,7 +634,7 @@ func (fs *FilesystemServer) HandleSearchFiles(req mcp.CallToolRequest) (mcp.Call
 	return mcp.NewToolResult(mcp.NewTextContent(strings.Join(results, "\n"))), nil
 }
 
-func (fs *FilesystemServer) HandleGetFileInfo(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (fs *Server) HandleGetFileInfo(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	pathStr, ok := req.Arguments["path"].(string)
 	if !ok {
 		return mcp.NewToolError("path is required"), nil
@@ -661,7 +661,7 @@ func (fs *FilesystemServer) HandleGetFileInfo(req mcp.CallToolRequest) (mcp.Call
 	return mcp.NewToolResult(mcp.NewTextContent(strings.Join(result, "\n"))), nil
 }
 
-func (fs *FilesystemServer) HandleListAllowedDirectories(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (fs *Server) HandleListAllowedDirectories(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	dirs := []string{"Allowed directories:"}
 	dirs = append(dirs, fs.allowedDirectories...)
 	return mcp.NewToolResult(mcp.NewTextContent(strings.Join(dirs, "\n"))), nil
@@ -669,7 +669,7 @@ func (fs *FilesystemServer) HandleListAllowedDirectories(req mcp.CallToolRequest
 
 // Helper methods
 
-func (fs *FilesystemServer) validatePath(requestedPath string) (string, error) {
+func (fs *Server) validatePath(requestedPath string) (string, error) {
 	expandedPath := expandHome(requestedPath)
 	var absolute string
 	
@@ -729,7 +729,7 @@ func expandHome(filePath string) string {
 	return filePath
 }
 
-func (fs *FilesystemServer) convertToStringSlice(input interface{}) ([]string, error) {
+func (fs *Server) convertToStringSlice(input interface{}) ([]string, error) {
 	switch v := input.(type) {
 	case []interface{}:
 		result := make([]string, len(v))
@@ -748,7 +748,7 @@ func (fs *FilesystemServer) convertToStringSlice(input interface{}) ([]string, e
 	}
 }
 
-func (fs *FilesystemServer) tailFile(filePath string, numLines int) (string, error) {
+func (fs *Server) tailFile(filePath string, numLines int) (string, error) {
 	// Simple implementation - read file and return last N lines
 	content, err := os.ReadFile(filePath)
 	if err != nil {
@@ -763,7 +763,7 @@ func (fs *FilesystemServer) tailFile(filePath string, numLines int) (string, err
 	return strings.Join(lines[len(lines)-numLines:], "\n"), nil
 }
 
-func (fs *FilesystemServer) headFile(filePath string, numLines int) (string, error) {
+func (fs *Server) headFile(filePath string, numLines int) (string, error) {
 	// Simple implementation - read file and return first N lines
 	content, err := os.ReadFile(filePath)
 	if err != nil {
@@ -778,7 +778,7 @@ func (fs *FilesystemServer) headFile(filePath string, numLines int) (string, err
 	return strings.Join(lines[:numLines], "\n"), nil
 }
 
-func (fs *FilesystemServer) parseEdits(editsInterface interface{}) ([]Edit, error) {
+func (fs *Server) parseEdits(editsInterface interface{}) ([]Edit, error) {
 	editsSlice, ok := editsInterface.([]interface{})
 	if !ok {
 		return nil, fmt.Errorf("edits must be an array")
@@ -812,7 +812,7 @@ type Edit struct {
 	NewText string
 }
 
-func (fs *FilesystemServer) applyFileEdits(filePath string, edits []Edit, dryRun bool) (string, error) {
+func (fs *Server) applyFileEdits(filePath string, edits []Edit, dryRun bool) (string, error) {
 	content, err := os.ReadFile(filePath)
 	if err != nil {
 		return "", err
@@ -842,7 +842,7 @@ func (fs *FilesystemServer) applyFileEdits(filePath string, edits []Edit, dryRun
 	return diff, nil
 }
 
-func (fs *FilesystemServer) createUnifiedDiff(original, modified, filePath string) string {
+func (fs *Server) createUnifiedDiff(original, modified, filePath string) string {
 	// Simple diff implementation
 	if original == modified {
 		return "No changes made"
@@ -856,7 +856,7 @@ func (fs *FilesystemServer) createUnifiedDiff(original, modified, filePath strin
 		strings.ReplaceAll(modified, "\n", "\n+"))
 }
 
-func (fs *FilesystemServer) formatSize(bytes int64) string {
+func (fs *Server) formatSize(bytes int64) string {
 	const unit = 1024
 	if bytes < unit {
 		return fmt.Sprintf("%d B", bytes)
@@ -869,7 +869,7 @@ func (fs *FilesystemServer) formatSize(bytes int64) string {
 	return fmt.Sprintf("%.2f %cB", float64(bytes)/float64(div), "KMGTPE"[exp])
 }
 
-func (fs *FilesystemServer) buildDirectoryTree(rootPath string) (string, error) {
+func (fs *Server) buildDirectoryTree(rootPath string) (string, error) {
 	type TreeEntry struct {
 		Name     string      `json:"name"`
 		Type     string      `json:"type"`
@@ -922,7 +922,7 @@ func (fs *FilesystemServer) buildDirectoryTree(rootPath string) (string, error)
 	return fmt.Sprintf("%+v", tree), nil
 }
 
-func (fs *FilesystemServer) searchFiles(rootPath, pattern string, excludePatterns []string) ([]string, error) {
+func (fs *Server) searchFiles(rootPath, pattern string, excludePatterns []string) ([]string, error) {
 	var results []string
 	pattern = strings.ToLower(pattern)
 
cmd/filesystem/server_test.go โ†’ pkg/fsserver/server_test.go
@@ -1,4 +1,4 @@
-package main
+package fsserver
 
 import (
 	"os"
@@ -23,7 +23,7 @@ func TestFilesystemServer_ReadFile(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	server := NewFilesystemServer([]string{tempDir})
+	server := New([]string{tempDir})
 
 	req := mcp.CallToolRequest{
 		Name: "read_file",
@@ -59,7 +59,7 @@ func TestFilesystemServer_WriteFile(t *testing.T) {
 	}
 	defer os.RemoveAll(tempDir)
 
-	server := NewFilesystemServer([]string{tempDir})
+	server := New([]string{tempDir})
 	testFile := filepath.Join(tempDir, "new_file.txt")
 	testContent := "New content"
 
@@ -99,7 +99,7 @@ func TestFilesystemServer_SecurityValidation(t *testing.T) {
 	}
 	defer os.RemoveAll(tempDir)
 
-	server := NewFilesystemServer([]string{tempDir})
+	server := New([]string{tempDir})
 
 	// Try to access file outside allowed directory
 	req := mcp.CallToolRequest{
@@ -147,7 +147,7 @@ func TestFilesystemServer_ListDirectory(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	server := NewFilesystemServer([]string{tempDir})
+	server := New([]string{tempDir})
 
 	req := mcp.CallToolRequest{
 		Name: "list_directory",
@@ -188,7 +188,7 @@ func TestFilesystemServer_CreateDirectory(t *testing.T) {
 	}
 	defer os.RemoveAll(tempDir)
 
-	server := NewFilesystemServer([]string{tempDir})
+	server := New([]string{tempDir})
 	newDir := filepath.Join(tempDir, "new", "nested", "directory")
 
 	req := mcp.CallToolRequest{
@@ -214,7 +214,7 @@ func TestFilesystemServer_CreateDirectory(t *testing.T) {
 }
 
 func TestFilesystemServer_ListTools(t *testing.T) {
-	server := NewFilesystemServer([]string{"/tmp"})
+	server := New([]string{"/tmp"})
 	tools := server.ListTools()
 
 	expectedTools := []string{
@@ -255,7 +255,7 @@ func TestFilesystemServer_EditFile(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	server := NewFilesystemServer([]string{tempDir})
+	server := New([]string{tempDir})
 
 	req := mcp.CallToolRequest{
 		Name: "edit_file",
cmd/git/server.go โ†’ pkg/gitserver/server.go
@@ -1,4 +1,4 @@
-package main
+package gitserver
 
 import (
 	"fmt"
@@ -11,16 +11,16 @@ import (
 	"github.com/xlgmokha/mcp/pkg/mcp"
 )
 
-// GitServer implements the Git MCP server
-type GitServer struct {
+// Server implements the Git MCP server
+type Server struct {
 	*mcp.Server
 }
 
-// NewGitServer creates a new Git MCP server
-func NewGitServer() *GitServer {
+// New creates a new Git MCP server
+func New() *Server {
 	server := mcp.NewServer("mcp-git", "1.0.0")
 	
-	gitServer := &GitServer{
+	gitServer := &Server{
 		Server: server,
 	}
 	
@@ -31,7 +31,7 @@ func NewGitServer() *GitServer {
 }
 
 // registerTools registers all Git tools with the server
-func (gs *GitServer) registerTools() {
+func (gs *Server) registerTools() {
 	gs.RegisterTool("git_status", gs.HandleGitStatus)
 	gs.RegisterTool("git_diff_unstaged", gs.HandleGitDiffUnstaged)
 	gs.RegisterTool("git_diff_staged", gs.HandleGitDiffStaged)
@@ -47,7 +47,7 @@ func (gs *GitServer) registerTools() {
 }
 
 // ListTools returns all available Git tools
-func (gs *GitServer) ListTools() []mcp.Tool {
+func (gs *Server) ListTools() []mcp.Tool {
 	return []mcp.Tool{
 		{
 			Name:        "git_status",
@@ -258,7 +258,7 @@ func (gs *GitServer) ListTools() []mcp.Tool {
 
 // Tool handlers
 
-func (gs *GitServer) HandleGitStatus(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (gs *Server) HandleGitStatus(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	repoPath, ok := req.Arguments["repo_path"].(string)
 	if !ok {
 		return mcp.NewToolError("repo_path is required"), nil
@@ -272,7 +272,7 @@ func (gs *GitServer) HandleGitStatus(req mcp.CallToolRequest) (mcp.CallToolResul
 	return mcp.NewToolResult(mcp.NewTextContent(fmt.Sprintf("Repository status:\n%s", output))), nil
 }
 
-func (gs *GitServer) HandleGitDiffUnstaged(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (gs *Server) HandleGitDiffUnstaged(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	repoPath, ok := req.Arguments["repo_path"].(string)
 	if !ok {
 		return mcp.NewToolError("repo_path is required"), nil
@@ -286,7 +286,7 @@ func (gs *GitServer) HandleGitDiffUnstaged(req mcp.CallToolRequest) (mcp.CallToo
 	return mcp.NewToolResult(mcp.NewTextContent(fmt.Sprintf("Unstaged changes:\n%s", output))), nil
 }
 
-func (gs *GitServer) HandleGitDiffStaged(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (gs *Server) HandleGitDiffStaged(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	repoPath, ok := req.Arguments["repo_path"].(string)
 	if !ok {
 		return mcp.NewToolError("repo_path is required"), nil
@@ -300,7 +300,7 @@ func (gs *GitServer) HandleGitDiffStaged(req mcp.CallToolRequest) (mcp.CallToolR
 	return mcp.NewToolResult(mcp.NewTextContent(fmt.Sprintf("Staged changes:\n%s", output))), nil
 }
 
-func (gs *GitServer) HandleGitDiff(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (gs *Server) HandleGitDiff(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	repoPath, ok := req.Arguments["repo_path"].(string)
 	if !ok {
 		return mcp.NewToolError("repo_path is required"), nil
@@ -319,7 +319,7 @@ func (gs *GitServer) HandleGitDiff(req mcp.CallToolRequest) (mcp.CallToolResult,
 	return mcp.NewToolResult(mcp.NewTextContent(fmt.Sprintf("Diff with %s:\n%s", target, output))), nil
 }
 
-func (gs *GitServer) HandleGitCommit(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (gs *Server) HandleGitCommit(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	repoPath, ok := req.Arguments["repo_path"].(string)
 	if !ok {
 		return mcp.NewToolError("repo_path is required"), nil
@@ -338,7 +338,7 @@ func (gs *GitServer) HandleGitCommit(req mcp.CallToolRequest) (mcp.CallToolResul
 	return mcp.NewToolResult(mcp.NewTextContent(fmt.Sprintf("Changes committed successfully:\n%s", output))), nil
 }
 
-func (gs *GitServer) HandleGitAdd(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (gs *Server) HandleGitAdd(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	repoPath, ok := req.Arguments["repo_path"].(string)
 	if !ok {
 		return mcp.NewToolError("repo_path is required"), nil
@@ -363,7 +363,7 @@ func (gs *GitServer) HandleGitAdd(req mcp.CallToolRequest) (mcp.CallToolResult,
 	return mcp.NewToolResult(mcp.NewTextContent("Files staged successfully")), nil
 }
 
-func (gs *GitServer) HandleGitReset(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (gs *Server) HandleGitReset(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	repoPath, ok := req.Arguments["repo_path"].(string)
 	if !ok {
 		return mcp.NewToolError("repo_path is required"), nil
@@ -377,7 +377,7 @@ func (gs *GitServer) HandleGitReset(req mcp.CallToolRequest) (mcp.CallToolResult
 	return mcp.NewToolResult(mcp.NewTextContent("All staged changes reset")), nil
 }
 
-func (gs *GitServer) HandleGitLog(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (gs *Server) HandleGitLog(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	repoPath, ok := req.Arguments["repo_path"].(string)
 	if !ok {
 		return mcp.NewToolError("repo_path is required"), nil
@@ -398,7 +398,7 @@ func (gs *GitServer) HandleGitLog(req mcp.CallToolRequest) (mcp.CallToolResult,
 	return mcp.NewToolResult(mcp.NewTextContent(fmt.Sprintf("Commit history:\n%s", output))), nil
 }
 
-func (gs *GitServer) HandleGitCreateBranch(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (gs *Server) HandleGitCreateBranch(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	repoPath, ok := req.Arguments["repo_path"].(string)
 	if !ok {
 		return mcp.NewToolError("repo_path is required"), nil
@@ -426,7 +426,7 @@ func (gs *GitServer) HandleGitCreateBranch(req mcp.CallToolRequest) (mcp.CallToo
 	return mcp.NewToolResult(mcp.NewTextContent(fmt.Sprintf("Created branch '%s'", branchName))), nil
 }
 
-func (gs *GitServer) HandleGitCheckout(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (gs *Server) HandleGitCheckout(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	repoPath, ok := req.Arguments["repo_path"].(string)
 	if !ok {
 		return mcp.NewToolError("repo_path is required"), nil
@@ -445,7 +445,7 @@ func (gs *GitServer) HandleGitCheckout(req mcp.CallToolRequest) (mcp.CallToolRes
 	return mcp.NewToolResult(mcp.NewTextContent(fmt.Sprintf("Switched to branch '%s'", branchName))), nil
 }
 
-func (gs *GitServer) HandleGitShow(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (gs *Server) HandleGitShow(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	repoPath, ok := req.Arguments["repo_path"].(string)
 	if !ok {
 		return mcp.NewToolError("repo_path is required"), nil
@@ -464,7 +464,7 @@ func (gs *GitServer) HandleGitShow(req mcp.CallToolRequest) (mcp.CallToolResult,
 	return mcp.NewToolResult(mcp.NewTextContent(output)), nil
 }
 
-func (gs *GitServer) HandleGitInit(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (gs *Server) HandleGitInit(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	repoPath, ok := req.Arguments["repo_path"].(string)
 	if !ok {
 		return mcp.NewToolError("repo_path is required"), nil
@@ -485,7 +485,7 @@ func (gs *GitServer) HandleGitInit(req mcp.CallToolRequest) (mcp.CallToolResult,
 
 // Helper methods
 
-func (gs *GitServer) runGitCommand(repoPath string, args ...string) (string, error) {
+func (gs *Server) runGitCommand(repoPath string, args ...string) (string, error) {
 	// Check if path exists
 	if _, err := os.Stat(repoPath); os.IsNotExist(err) {
 		return "", fmt.Errorf("repository path does not exist: %s", repoPath)
@@ -510,7 +510,7 @@ func (gs *GitServer) runGitCommand(repoPath string, args ...string) (string, err
 	return strings.TrimSpace(string(output)), nil
 }
 
-func (gs *GitServer) convertToStringSlice(input interface{}) ([]string, error) {
+func (gs *Server) convertToStringSlice(input interface{}) ([]string, error) {
 	switch v := input.(type) {
 	case []interface{}:
 		result := make([]string, len(v))
cmd/git/server_test.go โ†’ pkg/gitserver/server_test.go
@@ -1,4 +1,4 @@
-package main
+package gitserver
 
 import (
 	"fmt"
@@ -22,7 +22,7 @@ func TestGitServer_GitStatus(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	server := NewGitServer()
+	server := New()
 	
 	// Test git status
 	req := mcp.CallToolRequest{
@@ -64,7 +64,7 @@ func TestGitServer_GitInit(t *testing.T) {
 	}
 	defer os.RemoveAll(tempDir)
 
-	server := NewGitServer()
+	server := New()
 	
 	// Test git init
 	req := mcp.CallToolRequest{
@@ -119,7 +119,7 @@ func TestGitServer_GitAdd(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	server := NewGitServer()
+	server := New()
 	
 	// Test git add
 	req := mcp.CallToolRequest{
@@ -151,7 +151,7 @@ func TestGitServer_GitAdd(t *testing.T) {
 }
 
 func TestGitServer_ListTools(t *testing.T) {
-	server := NewGitServer()
+	server := New()
 	tools := server.ListTools()
 
 	expectedTools := []string{
@@ -179,7 +179,7 @@ func TestGitServer_ListTools(t *testing.T) {
 // Helper functions
 func initGitRepo(dir string) error {
 	// Use actual git init command for testing
-	server := NewGitServer()
+	server := New()
 	req := mcp.CallToolRequest{
 		Name: "git_init",
 		Arguments: map[string]interface{}{
cmd/memory/server.go โ†’ pkg/memoryserver/server.go
@@ -1,4 +1,4 @@
-package main
+package memoryserver
 
 import (
 	"encoding/json"
@@ -10,8 +10,8 @@ import (
 	"github.com/xlgmokha/mcp/pkg/mcp"
 )
 
-// MemoryServer implements the Memory MCP server with knowledge graph functionality
-type MemoryServer struct {
+// Server implements the Memory MCP server with knowledge graph functionality
+type Server struct {
 	*mcp.Server
 	memoryFile string
 	graph      *KnowledgeGraph
@@ -38,11 +38,11 @@ type Relation struct {
 	RelationType string `json:"relationType"`
 }
 
-// NewMemoryServer creates a new Memory MCP server
-func NewMemoryServer(memoryFile string) *MemoryServer {
+// New creates a new Memory MCP server
+func New(memoryFile string) *Server {
 	server := mcp.NewServer("mcp-memory", "1.0.0")
 
-	memoryServer := &MemoryServer{
+	memoryServer := &Server{
 		Server:     server,
 		memoryFile: memoryFile,
 		graph: &KnowledgeGraph{
@@ -61,7 +61,7 @@ func NewMemoryServer(memoryFile string) *MemoryServer {
 }
 
 // registerTools registers all Memory tools with the server
-func (ms *MemoryServer) registerTools() {
+func (ms *Server) registerTools() {
 	ms.RegisterTool("create_entities", ms.HandleCreateEntities)
 	ms.RegisterTool("create_relations", ms.HandleCreateRelations)
 	ms.RegisterTool("add_observations", ms.HandleAddObservations)
@@ -74,7 +74,7 @@ func (ms *MemoryServer) registerTools() {
 }
 
 // ListTools returns all available Memory tools
-func (ms *MemoryServer) ListTools() []mcp.Tool {
+func (ms *Server) ListTools() []mcp.Tool {
 	return []mcp.Tool{
 		{
 			Name:        "create_entities",
@@ -293,7 +293,7 @@ func (ms *MemoryServer) ListTools() []mcp.Tool {
 
 // Tool handlers
 
-func (ms *MemoryServer) HandleCreateEntities(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (ms *Server) HandleCreateEntities(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	ms.mu.Lock()
 	defer ms.mu.Unlock()
 
@@ -364,7 +364,7 @@ func (ms *MemoryServer) HandleCreateEntities(req mcp.CallToolRequest) (mcp.CallT
 	return mcp.NewToolResult(mcp.NewTextContent(result)), nil
 }
 
-func (ms *MemoryServer) HandleCreateRelations(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (ms *Server) HandleCreateRelations(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	ms.mu.Lock()
 	defer ms.mu.Unlock()
 
@@ -433,7 +433,7 @@ func (ms *MemoryServer) HandleCreateRelations(req mcp.CallToolRequest) (mcp.Call
 	return mcp.NewToolResult(mcp.NewTextContent(result)), nil
 }
 
-func (ms *MemoryServer) HandleAddObservations(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (ms *Server) HandleAddObservations(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	ms.mu.Lock()
 	defer ms.mu.Unlock()
 
@@ -498,7 +498,7 @@ func (ms *MemoryServer) HandleAddObservations(req mcp.CallToolRequest) (mcp.Call
 	return mcp.NewToolResult(mcp.NewTextContent(result)), nil
 }
 
-func (ms *MemoryServer) HandleDeleteEntities(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (ms *Server) HandleDeleteEntities(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	ms.mu.Lock()
 	defer ms.mu.Unlock()
 
@@ -543,7 +543,7 @@ func (ms *MemoryServer) HandleDeleteEntities(req mcp.CallToolRequest) (mcp.CallT
 	return mcp.NewToolResult(mcp.NewTextContent(result)), nil
 }
 
-func (ms *MemoryServer) HandleDeleteObservations(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (ms *Server) HandleDeleteObservations(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	ms.mu.Lock()
 	defer ms.mu.Unlock()
 
@@ -615,7 +615,7 @@ func (ms *MemoryServer) HandleDeleteObservations(req mcp.CallToolRequest) (mcp.C
 	return mcp.NewToolResult(mcp.NewTextContent(result)), nil
 }
 
-func (ms *MemoryServer) HandleDeleteRelations(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (ms *Server) HandleDeleteRelations(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	ms.mu.Lock()
 	defer ms.mu.Unlock()
 
@@ -671,7 +671,7 @@ func (ms *MemoryServer) HandleDeleteRelations(req mcp.CallToolRequest) (mcp.Call
 	return mcp.NewToolResult(mcp.NewTextContent(result)), nil
 }
 
-func (ms *MemoryServer) HandleReadGraph(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (ms *Server) HandleReadGraph(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	ms.mu.RLock()
 	defer ms.mu.RUnlock()
 
@@ -684,7 +684,7 @@ func (ms *MemoryServer) HandleReadGraph(req mcp.CallToolRequest) (mcp.CallToolRe
 	return mcp.NewToolResult(mcp.NewTextContent(string(graphJSON))), nil
 }
 
-func (ms *MemoryServer) HandleSearchNodes(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (ms *Server) HandleSearchNodes(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	ms.mu.RLock()
 	defer ms.mu.RUnlock()
 
@@ -733,7 +733,7 @@ func (ms *MemoryServer) HandleSearchNodes(req mcp.CallToolRequest) (mcp.CallTool
 	return mcp.NewToolResult(mcp.NewTextContent(string(resultJSON))), nil
 }
 
-func (ms *MemoryServer) HandleOpenNodes(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (ms *Server) HandleOpenNodes(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	ms.mu.RLock()
 	defer ms.mu.RUnlock()
 
@@ -775,7 +775,7 @@ func (ms *MemoryServer) HandleOpenNodes(req mcp.CallToolRequest) (mcp.CallToolRe
 
 // Helper methods
 
-func (ms *MemoryServer) loadGraph() error {
+func (ms *Server) loadGraph() error {
 	if _, err := os.Stat(ms.memoryFile); os.IsNotExist(err) {
 		// File doesn't exist, start with empty graph
 		return nil
@@ -794,7 +794,7 @@ func (ms *MemoryServer) loadGraph() error {
 	return json.Unmarshal(data, ms.graph)
 }
 
-func (ms *MemoryServer) saveGraph() error {
+func (ms *Server) saveGraph() error {
 	data, err := json.MarshalIndent(ms.graph, "", "  ")
 	if err != nil {
 		return err
cmd/memory/server_test.go โ†’ pkg/memoryserver/server_test.go
@@ -1,4 +1,4 @@
-package main
+package memoryserver
 
 import (
 	"path/filepath"
@@ -13,7 +13,7 @@ func TestMemoryServer_CreateEntities(t *testing.T) {
 	tempDir := t.TempDir()
 	memoryFile := filepath.Join(tempDir, "test_memory.json")
 
-	server := NewMemoryServer(memoryFile)
+	server := New(memoryFile)
 
 	req := mcp.CallToolRequest{
 		Name: "create_entities",
@@ -62,7 +62,7 @@ func TestMemoryServer_CreateRelations(t *testing.T) {
 	tempDir := t.TempDir()
 	memoryFile := filepath.Join(tempDir, "test_memory.json")
 
-	server := NewMemoryServer(memoryFile)
+	server := New(memoryFile)
 
 	// First create entities
 	createReq := mcp.CallToolRequest{
@@ -123,7 +123,7 @@ func TestMemoryServer_AddObservations(t *testing.T) {
 	tempDir := t.TempDir()
 	memoryFile := filepath.Join(tempDir, "test_memory.json")
 
-	server := NewMemoryServer(memoryFile)
+	server := New(memoryFile)
 
 	// First create entity
 	createReq := mcp.CallToolRequest{
@@ -178,7 +178,7 @@ func TestMemoryServer_ReadGraph(t *testing.T) {
 	tempDir := t.TempDir()
 	memoryFile := filepath.Join(tempDir, "test_memory.json")
 
-	server := NewMemoryServer(memoryFile)
+	server := New(memoryFile)
 
 	// Create some test data
 	createReq := mcp.CallToolRequest{
@@ -234,7 +234,7 @@ func TestMemoryServer_SearchNodes(t *testing.T) {
 	tempDir := t.TempDir()
 	memoryFile := filepath.Join(tempDir, "test_memory.json")
 
-	server := NewMemoryServer(memoryFile)
+	server := New(memoryFile)
 
 	// Create test entities
 	createReq := mcp.CallToolRequest{
@@ -294,7 +294,7 @@ func TestMemoryServer_OpenNodes(t *testing.T) {
 	tempDir := t.TempDir()
 	memoryFile := filepath.Join(tempDir, "test_memory.json")
 
-	server := NewMemoryServer(memoryFile)
+	server := New(memoryFile)
 
 	// Create test entities
 	createReq := mcp.CallToolRequest{
@@ -354,7 +354,7 @@ func TestMemoryServer_DeleteEntities(t *testing.T) {
 	tempDir := t.TempDir()
 	memoryFile := filepath.Join(tempDir, "test_memory.json")
 
-	server := NewMemoryServer(memoryFile)
+	server := New(memoryFile)
 
 	// Create test entity
 	createReq := mcp.CallToolRequest{
@@ -407,7 +407,7 @@ func TestMemoryServer_DeleteObservations(t *testing.T) {
 	tempDir := t.TempDir()
 	memoryFile := filepath.Join(tempDir, "test_memory.json")
 
-	server := NewMemoryServer(memoryFile)
+	server := New(memoryFile)
 
 	// Create entity with observations
 	createReq := mcp.CallToolRequest{
@@ -469,7 +469,7 @@ func TestMemoryServer_ListTools(t *testing.T) {
 	tempDir := t.TempDir()
 	memoryFile := filepath.Join(tempDir, "test_memory.json")
 
-	server := NewMemoryServer(memoryFile)
+	server := New(memoryFile)
 	tools := server.ListTools()
 
 	expectedTools := []string{
@@ -505,7 +505,7 @@ func TestMemoryServer_Persistence(t *testing.T) {
 	memoryFile := filepath.Join(tempDir, "test_memory.json")
 
 	// Create first server instance and add data
-	server1 := NewMemoryServer(memoryFile)
+	server1 := New(memoryFile)
 
 	createReq := mcp.CallToolRequest{
 		Name: "create_entities",
@@ -522,7 +522,7 @@ func TestMemoryServer_Persistence(t *testing.T) {
 	server1.HandleCreateEntities(createReq)
 
 	// Create second server instance (should load from file)
-	server2 := NewMemoryServer(memoryFile)
+	server2 := New(memoryFile)
 
 	readReq := mcp.CallToolRequest{
 		Name:      "read_graph",
cmd/sequential-thinking/server.go โ†’ pkg/thinkingserver/server.go
@@ -1,4 +1,4 @@
-package main
+package thinkingserver
 
 import (
 	"encoding/json"
@@ -9,8 +9,8 @@ import (
 	"github.com/xlgmokha/mcp/pkg/mcp"
 )
 
-// SequentialThinkingServer implements the Sequential Thinking MCP server
-type SequentialThinkingServer struct {
+// Server implements the Sequential Thinking MCP server
+type Server struct {
 	*mcp.Server
 }
 
@@ -43,11 +43,11 @@ type ThinkingResponse struct {
 	Solution          string `json:"solution,omitempty"`
 }
 
-// NewSequentialThinkingServer creates a new Sequential Thinking MCP server
-func NewSequentialThinkingServer() *SequentialThinkingServer {
+// New creates a new Sequential Thinking MCP server
+func New() *Server {
 	server := mcp.NewServer("mcp-sequential-thinking", "1.0.0")
 
-	thinkingServer := &SequentialThinkingServer{
+	thinkingServer := &Server{
 		Server: server,
 	}
 
@@ -58,12 +58,12 @@ func NewSequentialThinkingServer() *SequentialThinkingServer {
 }
 
 // registerTools registers all Sequential Thinking tools with the server
-func (sts *SequentialThinkingServer) registerTools() {
+func (sts *Server) registerTools() {
 	sts.RegisterTool("sequentialthinking", sts.HandleSequentialThinking)
 }
 
 // ListTools returns all available Sequential Thinking tools
-func (sts *SequentialThinkingServer) ListTools() []mcp.Tool {
+func (sts *Server) ListTools() []mcp.Tool {
 	return []mcp.Tool{
 		{
 			Name:        "sequentialthinking",
@@ -122,7 +122,7 @@ func (sts *SequentialThinkingServer) ListTools() []mcp.Tool {
 
 // Tool handlers
 
-func (sts *SequentialThinkingServer) HandleSequentialThinking(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (sts *Server) HandleSequentialThinking(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	// Parse input parameters
 	thought, ok := req.Arguments["thought"].(string)
 	if !ok {
@@ -265,7 +265,7 @@ func (sts *SequentialThinkingServer) HandleSequentialThinking(req mcp.CallToolRe
 
 // Helper methods
 
-func (sts *SequentialThinkingServer) extractSolution(finalThought string) string {
+func (sts *Server) extractSolution(finalThought string) string {
 	// Simple heuristic to extract a solution from the final thought
 	content := strings.ToLower(finalThought)
 	
@@ -318,7 +318,7 @@ func (sts *SequentialThinkingServer) extractSolution(finalThought string) string
 	return "Solution extracted from final thought"
 }
 
-func (sts *SequentialThinkingServer) formatThinkingResult(response ThinkingResponse, thought Thought, contextInfo []string) string {
+func (sts *Server) formatThinkingResult(response ThinkingResponse, thought Thought, contextInfo []string) string {
 	var result strings.Builder
 	
 	// Header
@@ -368,7 +368,7 @@ func (sts *SequentialThinkingServer) formatThinkingResult(response ThinkingRespo
 	return result.String()
 }
 
-func (sts *SequentialThinkingServer) createProgressBar(current, total int) string {
+func (sts *Server) createProgressBar(current, total int) string {
 	if total <= 0 {
 		return "[โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ] 100%"
 	}
cmd/sequential-thinking/server_test.go โ†’ pkg/thinkingserver/server_test.go
@@ -1,4 +1,4 @@
-package main
+package thinkingserver
 
 import (
 	"strings"
@@ -7,8 +7,8 @@ import (
 	"github.com/xlgmokha/mcp/pkg/mcp"
 )
 
-func TestSequentialThinkingServer_BasicThinking(t *testing.T) {
-	server := NewSequentialThinkingServer()
+func TestServer_BasicThinking(t *testing.T) {
+	server := New()
 
 	req := mcp.CallToolRequest{
 		Name: "sequentialthinking",
@@ -51,8 +51,8 @@ func TestSequentialThinkingServer_BasicThinking(t *testing.T) {
 	}
 }
 
-func TestSequentialThinkingServer_CompletedThinking(t *testing.T) {
-	server := NewSequentialThinkingServer()
+func TestServer_CompletedThinking(t *testing.T) {
+	server := New()
 
 	req := mcp.CallToolRequest{
 		Name: "sequentialthinking",
@@ -95,8 +95,8 @@ func TestSequentialThinkingServer_CompletedThinking(t *testing.T) {
 	}
 }
 
-func TestSequentialThinkingServer_RevisionThinking(t *testing.T) {
-	server := NewSequentialThinkingServer()
+func TestServer_RevisionThinking(t *testing.T) {
+	server := New()
 
 	req := mcp.CallToolRequest{
 		Name: "sequentialthinking",
@@ -136,8 +136,8 @@ func TestSequentialThinkingServer_RevisionThinking(t *testing.T) {
 	}
 }
 
-func TestSequentialThinkingServer_BranchThinking(t *testing.T) {
-	server := NewSequentialThinkingServer()
+func TestServer_BranchThinking(t *testing.T) {
+	server := New()
 
 	req := mcp.CallToolRequest{
 		Name: "sequentialthinking",
@@ -176,8 +176,8 @@ func TestSequentialThinkingServer_BranchThinking(t *testing.T) {
 	}
 }
 
-func TestSequentialThinkingServer_NeedsMoreThoughts(t *testing.T) {
-	server := NewSequentialThinkingServer()
+func TestServer_NeedsMoreThoughts(t *testing.T) {
+	server := New()
 
 	req := mcp.CallToolRequest{
 		Name: "sequentialthinking",
@@ -216,8 +216,8 @@ func TestSequentialThinkingServer_NeedsMoreThoughts(t *testing.T) {
 	}
 }
 
-func TestSequentialThinkingServer_MissingRequiredParams(t *testing.T) {
-	server := NewSequentialThinkingServer()
+func TestServer_MissingRequiredParams(t *testing.T) {
+	server := New()
 
 	req := mcp.CallToolRequest{
 		Name: "sequentialthinking",
@@ -246,8 +246,8 @@ func TestSequentialThinkingServer_MissingRequiredParams(t *testing.T) {
 	}
 }
 
-func TestSequentialThinkingServer_InvalidParams(t *testing.T) {
-	server := NewSequentialThinkingServer()
+func TestServer_InvalidParams(t *testing.T) {
+	server := New()
 
 	req := mcp.CallToolRequest{
 		Name: "sequentialthinking",
@@ -278,8 +278,8 @@ func TestSequentialThinkingServer_InvalidParams(t *testing.T) {
 	}
 }
 
-func TestSequentialThinkingServer_SolutionExtraction(t *testing.T) {
-	server := NewSequentialThinkingServer()
+func TestServer_SolutionExtraction(t *testing.T) {
+	server := New()
 
 	// Test with explicit solution keyword
 	req := mcp.CallToolRequest{
@@ -308,8 +308,8 @@ func TestSequentialThinkingServer_SolutionExtraction(t *testing.T) {
 	}
 }
 
-func TestSequentialThinkingServer_ListTools(t *testing.T) {
-	server := NewSequentialThinkingServer()
+func TestServer_ListTools(t *testing.T) {
+	server := New()
 	tools := server.ListTools()
 
 	expectedTools := []string{
@@ -346,8 +346,8 @@ func TestSequentialThinkingServer_ListTools(t *testing.T) {
 	}
 }
 
-func TestSequentialThinkingServer_ProgressBar(t *testing.T) {
-	server := NewSequentialThinkingServer()
+func TestServer_ProgressBar(t *testing.T) {
+	server := New()
 
 	// Test progress bar creation
 	progressBar := server.createProgressBar(3, 10)
cmd/time/server.go โ†’ pkg/timeserver/server.go
@@ -1,4 +1,4 @@
-package main
+package timeserver
 
 import (
 	"encoding/json"
@@ -10,8 +10,8 @@ import (
 	"github.com/xlgmokha/mcp/pkg/mcp"
 )
 
-// TimeServer implements the Time MCP server
-type TimeServer struct {
+// Server implements the Time MCP server
+type Server struct {
 	*mcp.Server
 	localTimezone string
 }
@@ -30,14 +30,14 @@ type TimeConversionResult struct {
 	TimeDifference string     `json:"time_difference"`
 }
 
-// NewTimeServer creates a new Time MCP server
-func NewTimeServer() *TimeServer {
+// New creates a new Time MCP server
+func New() *Server {
 	server := mcp.NewServer("mcp-time", "1.0.0")
 	
 	// Get local timezone
 	localTZ := getLocalTimezone()
 	
-	timeServer := &TimeServer{
+	timeServer := &Server{
 		Server:        server,
 		localTimezone: localTZ,
 	}
@@ -49,13 +49,13 @@ func NewTimeServer() *TimeServer {
 }
 
 // registerTools registers all Time tools with the server
-func (ts *TimeServer) registerTools() {
+func (ts *Server) registerTools() {
 	ts.RegisterTool("get_current_time", ts.HandleGetCurrentTime)
 	ts.RegisterTool("convert_time", ts.HandleConvertTime)
 }
 
 // ListTools returns all available Time tools
-func (ts *TimeServer) ListTools() []mcp.Tool {
+func (ts *Server) ListTools() []mcp.Tool {
 	return []mcp.Tool{
 		{
 			Name:        "get_current_time",
@@ -98,7 +98,7 @@ func (ts *TimeServer) ListTools() []mcp.Tool {
 
 // Tool handlers
 
-func (ts *TimeServer) HandleGetCurrentTime(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (ts *Server) HandleGetCurrentTime(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	timezone, ok := req.Arguments["timezone"].(string)
 	if !ok {
 		return mcp.NewToolError("timezone is required"), nil
@@ -117,7 +117,7 @@ func (ts *TimeServer) HandleGetCurrentTime(req mcp.CallToolRequest) (mcp.CallToo
 	return mcp.NewToolResult(mcp.NewTextContent(string(jsonResult))), nil
 }
 
-func (ts *TimeServer) HandleConvertTime(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
+func (ts *Server) HandleConvertTime(req mcp.CallToolRequest) (mcp.CallToolResult, error) {
 	sourceTimezone, ok := req.Arguments["source_timezone"].(string)
 	if !ok {
 		return mcp.NewToolError("source_timezone is required"), nil
@@ -148,7 +148,7 @@ func (ts *TimeServer) HandleConvertTime(req mcp.CallToolRequest) (mcp.CallToolRe
 
 // Helper methods
 
-func (ts *TimeServer) getCurrentTime(timezone string) (*TimeResult, error) {
+func (ts *Server) getCurrentTime(timezone string) (*TimeResult, error) {
 	loc, err := time.LoadLocation(timezone)
 	if err != nil {
 		return nil, fmt.Errorf("Invalid timezone: %v", err)
@@ -163,7 +163,7 @@ func (ts *TimeServer) getCurrentTime(timezone string) (*TimeResult, error) {
 	}, nil
 }
 
-func (ts *TimeServer) convertTime(sourceTimezone, timeStr, targetTimezone string) (*TimeConversionResult, error) {
+func (ts *Server) convertTime(sourceTimezone, timeStr, targetTimezone string) (*TimeConversionResult, error) {
 	sourceLoc, err := time.LoadLocation(sourceTimezone)
 	if err != nil {
 		return nil, fmt.Errorf("Invalid source timezone: %v", err)
cmd/time/server_test.go โ†’ pkg/timeserver/server_test.go
@@ -1,4 +1,4 @@
-package main
+package timeserver
 
 import (
 	"strings"
@@ -7,8 +7,8 @@ import (
 	"github.com/xlgmokha/mcp/pkg/mcp"
 )
 
-func TestTimeServer_GetCurrentTime(t *testing.T) {
-	server := NewTimeServer()
+func TestServer_GetCurrentTime(t *testing.T) {
+	server := New()
 
 	req := mcp.CallToolRequest{
 		Name: "get_current_time",
@@ -41,8 +41,8 @@ func TestTimeServer_GetCurrentTime(t *testing.T) {
 	}
 }
 
-func TestTimeServer_ConvertTime(t *testing.T) {
-	server := NewTimeServer()
+func TestServer_ConvertTime(t *testing.T) {
+	server := New()
 
 	req := mcp.CallToolRequest{
 		Name: "convert_time",
@@ -81,8 +81,8 @@ func TestTimeServer_ConvertTime(t *testing.T) {
 	}
 }
 
-func TestTimeServer_InvalidTimezone(t *testing.T) {
-	server := NewTimeServer()
+func TestServer_InvalidTimezone(t *testing.T) {
+	server := New()
 
 	req := mcp.CallToolRequest{
 		Name: "get_current_time",
@@ -110,8 +110,8 @@ func TestTimeServer_InvalidTimezone(t *testing.T) {
 	}
 }
 
-func TestTimeServer_InvalidTimeFormat(t *testing.T) {
-	server := NewTimeServer()
+func TestServer_InvalidTimeFormat(t *testing.T) {
+	server := New()
 
 	req := mcp.CallToolRequest{
 		Name: "convert_time",
@@ -141,8 +141,8 @@ func TestTimeServer_InvalidTimeFormat(t *testing.T) {
 	}
 }
 
-func TestTimeServer_ListTools(t *testing.T) {
-	server := NewTimeServer()
+func TestServer_ListTools(t *testing.T) {
+	server := New()
 	tools := server.ListTools()
 
 	expectedTools := []string{
@@ -166,8 +166,8 @@ func TestTimeServer_ListTools(t *testing.T) {
 	}
 }
 
-func TestTimeServer_ConvertTimeWithDST(t *testing.T) {
-	server := NewTimeServer()
+func TestServer_ConvertTimeWithDST(t *testing.T) {
+	server := New()
 
 	// Test during daylight saving time period
 	req := mcp.CallToolRequest{
Makefile
@@ -23,7 +23,7 @@ all: build ## Build all servers
 
 build: $(BINARIES) ## Build all MCP servers
 
-$(BINDIR)/mcp-%: cmd/%/main.go cmd/%/server.go
+$(BINDIR)/mcp-%: cmd/%/main.go
 	@mkdir -p $(BINDIR)
 	$(GOBUILD) $(BUILD_FLAGS) -o $@ ./cmd/$*
 
README.md
@@ -7,11 +7,11 @@ A pure Go implementation of Model Context Protocol (MCP) servers, providing drop
 
 ## Features
 
-- =๏ฟฝ **Zero Dependencies**: Statically linked binaries with no runtime dependencies
+- =๏ฟฝ **Zero Dependencies**: Statically linked binaries with no runtime dependencies
 - =' **Drop-in Replacement**: Compatible with existing Python MCP server configurations
-- >๏ฟฝ **Test-Driven Development**: Comprehensive test coverage for all servers
+- >๏ฟฝ **Test-Driven Development**: Comprehensive test coverage for all servers
 - = **Security First**: Built-in access controls and validation
-- ๏ฟฝ **High Performance**: Native Go performance and concurrency
+- ๏ฟฝ **High Performance**: Native Go performance and concurrency
 
 ## Available Servers
 
@@ -231,14 +231,21 @@ go test ./cmd/git/...
 
 ## Architecture
 
-The project follows a clean architecture with:
-
-- **`pkg/mcp/`**: Core MCP protocol implementation
-- **`cmd/*/`**: Individual MCP server implementations
+The project follows a clean, modular architecture with:
+
+- **`pkg/mcp/`**: Core MCP protocol implementation and shared utilities
+- **`pkg/*/`**: Individual MCP server implementations (reusable packages)
+  - `pkg/gitserver/`: Git operations server
+  - `pkg/fsserver/`: Filesystem operations server  
+  - `pkg/fetchserver/`: Web content fetching server
+  - `pkg/memoryserver/`: Knowledge graph memory server
+  - `pkg/thinkingserver/`: Sequential thinking server
+  - `pkg/timeserver/`: Time and timezone server
+- **`cmd/*/`**: Minimal CLI entry points (thin wrappers around packages)
 - **Standard Go project layout** with clear separation of concerns
 - **Test-driven development** ensuring reliability
 
-Each server is a standalone binary that communicates via JSON-RPC over stdin/stdout, following the MCP specification.
+Each server is a standalone binary that communicates via JSON-RPC over stdin/stdout, following the MCP specification. The modular package structure allows for easy reuse and testing of server implementations.
 
 ## Performance