Commit 1635915

mo khan <mo@mokhan.ca>
2025-08-18 19:55:02
refactor: rename fields
1 parent 3ab02d5
pkg/mcp/roots.go
@@ -17,4 +17,4 @@ func NewRoot(uri, name string) Root {
 		URI:  uri,
 		Name: name,
 	}
-}
\ No newline at end of file
+}
pkg/mcp/server.go
@@ -10,156 +10,25 @@ import (
 	"strings"
 )
 
-// ServerBuilder helps build immutable MCP servers with a fluent API
-type ServerBuilder struct {
-	name    string
-	version string
-	tools   []Tool
-	prompts []Prompt
-	resources []Resource
-	roots   []Root
-	
-	// Optional handlers
-	initializeHandler func(InitializeRequest) (InitializeResult, error)
-	shutdownHandler   func() error
-}
-
-// Server represents an immutable MCP server
 type Server struct {
 	name         string
 	version      string
 	capabilities ServerCapabilities
 
-	// Immutable component definitions (handlers embedded in structs)
-	toolDefinitions     map[string]Tool
-	promptDefinitions   map[string]Prompt
+	tools               map[string]Tool
+	prompts             map[string]Prompt
 	resourceDefinitions map[string]Resource
 	rootDefinitions     map[string]Root
 
-	// Lifecycle handlers
 	initializeHandler func(InitializeRequest) (InitializeResult, error)
 	shutdownHandler   func() error
 }
 
-// Handler types
 type ResourceHandler func(ReadResourceRequest) (ReadResourceResult, error)
 
-// NewServerBuilder creates a new server builder
-func NewServerBuilder(name, version string) *ServerBuilder {
-	return &ServerBuilder{
-		name:    name,
-		version: version,
-		tools:   []Tool{},
-		prompts: []Prompt{},
-		resources: []Resource{},
-		roots:   []Root{},
-	}
-}
-
-// AddTool adds a tool to the server
-func (b *ServerBuilder) AddTool(tool Tool) *ServerBuilder {
-	b.tools = append(b.tools, tool)
-	return b
-}
-
-// AddPrompt adds a prompt to the server
-func (b *ServerBuilder) AddPrompt(prompt Prompt) *ServerBuilder {
-	b.prompts = append(b.prompts, prompt)
-	return b
-}
-
-// AddResource adds a resource to the server
-func (b *ServerBuilder) AddResource(resource Resource) *ServerBuilder {
-	b.resources = append(b.resources, resource)
-	return b
-}
-
-// AddRoot adds a root to the server
-func (b *ServerBuilder) AddRoot(root Root) *ServerBuilder {
-	b.roots = append(b.roots, root)
-	return b
-}
-
-// SetInitializeHandler sets the initialize handler
-func (b *ServerBuilder) SetInitializeHandler(handler func(InitializeRequest) (InitializeResult, error)) *ServerBuilder {
-	b.initializeHandler = handler
-	return b
-}
-
-// SetShutdownHandler sets the shutdown handler
-func (b *ServerBuilder) SetShutdownHandler(handler func() error) *ServerBuilder {
-	b.shutdownHandler = handler
-	return b
-}
-
-// Build creates an immutable server with dynamic capabilities
-func (b *ServerBuilder) Build() *Server {
-	// Build dynamic capabilities based on what components are present
-	capabilities := ServerCapabilities{
-		Logging: &LoggingCapability{}, // Always present
-	}
-	
-	if len(b.tools) > 0 {
-		capabilities.Tools = &ToolsCapability{}
-	}
-	if len(b.prompts) > 0 {
-		capabilities.Prompts = &PromptsCapability{}
-	}
-	if len(b.resources) > 0 {
-		capabilities.Resources = &ResourcesCapability{}
-	}
-	if len(b.roots) > 0 {
-		capabilities.Roots = &RootsCapability{}
-	}
-	
-	server := &Server{
-		name:         b.name,
-		version:      b.version,
-		capabilities: capabilities,
-		toolDefinitions:     make(map[string]Tool),
-		promptDefinitions:   make(map[string]Prompt),
-		resourceDefinitions: make(map[string]Resource),
-		rootDefinitions:     make(map[string]Root),
-		initializeHandler:   b.initializeHandler,
-		shutdownHandler:     b.shutdownHandler,
-	}
-
-	// Register all components
-	for _, tool := range b.tools {
-		server.toolDefinitions[tool.Name] = tool
-	}
-	for _, prompt := range b.prompts {
-		server.promptDefinitions[prompt.Name] = prompt
-	}
-	for _, resource := range b.resources {
-		server.resourceDefinitions[resource.URI] = resource
-	}
-	for _, root := range b.roots {
-		server.rootDefinitions[root.URI] = root
-	}
-
-	return server
-}
-
-
-
-
-
-// SetInitializeHandler sets the initialize handler
-func (s *Server) SetInitializeHandler(handler func(InitializeRequest) (InitializeResult, error)) {
-	s.initializeHandler = handler
-}
-
-// SetShutdownHandler sets the shutdown handler
-func (s *Server) SetShutdownHandler(handler func() error) {
-	s.shutdownHandler = handler
-}
-
-
-// ListTools returns all registered tools
 func (s *Server) ListTools() []Tool {
-	tools := make([]Tool, 0, len(s.toolDefinitions))
-	for _, tool := range s.toolDefinitions {
+	tools := make([]Tool, 0, len(s.tools))
+	for _, tool := range s.tools {
 		tools = append(tools, tool)
 	}
 	return tools
@@ -167,8 +36,8 @@ func (s *Server) ListTools() []Tool {
 
 // ListPrompts returns all registered prompts
 func (s *Server) ListPrompts() []Prompt {
-	prompts := make([]Prompt, 0, len(s.promptDefinitions))
-	for _, prompt := range s.promptDefinitions {
+	prompts := make([]Prompt, 0, len(s.prompts))
+	for _, prompt := range s.prompts {
 		prompts = append(prompts, prompt)
 	}
 	return prompts
@@ -304,7 +173,7 @@ func (s *Server) handleCallTool(req JSONRPCRequest) JSONRPCResponse {
 		return s.createErrorResponse(req.ID, InvalidParams, "Invalid params")
 	}
 
-	tool, exists := s.toolDefinitions[callReq.Name]
+	tool, exists := s.tools[callReq.Name]
 	if !exists {
 		return s.createErrorResponse(req.ID, MethodNotFound, "Tool not found")
 	}
@@ -329,7 +198,7 @@ func (s *Server) handleGetPrompt(req JSONRPCRequest) JSONRPCResponse {
 		return s.createErrorResponse(req.ID, InvalidParams, "Invalid params")
 	}
 
-	prompt, exists := s.promptDefinitions[promptReq.Name]
+	prompt, exists := s.prompts[promptReq.Name]
 	if !exists {
 		return s.createErrorResponse(req.ID, MethodNotFound, "Prompt not found")
 	}
@@ -469,4 +338,3 @@ func NewPrompt(name, description string, arguments []PromptArgument, handler Pro
 		Handler:     handler,
 	}
 }
-
pkg/mcp/server_builder.go
@@ -0,0 +1,110 @@
+package mcp
+
+type ServerBuilder struct {
+	name      string
+	version   string
+	tools     []Tool
+	prompts   []Prompt
+	resources []Resource
+	roots     []Root
+
+	initializeHandler func(InitializeRequest) (InitializeResult, error)
+	shutdownHandler   func() error
+}
+
+// NewServerBuilder creates a new server builder
+func NewServerBuilder(name, version string) *ServerBuilder {
+	return &ServerBuilder{
+		name:      name,
+		version:   version,
+		tools:     []Tool{},
+		prompts:   []Prompt{},
+		resources: []Resource{},
+		roots:     []Root{},
+	}
+}
+
+// AddTool adds a tool to the server
+func (b *ServerBuilder) AddTool(tool Tool) *ServerBuilder {
+	b.tools = append(b.tools, tool)
+	return b
+}
+
+// AddPrompt adds a prompt to the server
+func (b *ServerBuilder) AddPrompt(prompt Prompt) *ServerBuilder {
+	b.prompts = append(b.prompts, prompt)
+	return b
+}
+
+// AddResource adds a resource to the server
+func (b *ServerBuilder) AddResource(resource Resource) *ServerBuilder {
+	b.resources = append(b.resources, resource)
+	return b
+}
+
+// AddRoot adds a root to the server
+func (b *ServerBuilder) AddRoot(root Root) *ServerBuilder {
+	b.roots = append(b.roots, root)
+	return b
+}
+
+// SetInitializeHandler sets the initialize handler
+func (b *ServerBuilder) SetInitializeHandler(handler func(InitializeRequest) (InitializeResult, error)) *ServerBuilder {
+	b.initializeHandler = handler
+	return b
+}
+
+// SetShutdownHandler sets the shutdown handler
+func (b *ServerBuilder) SetShutdownHandler(handler func() error) *ServerBuilder {
+	b.shutdownHandler = handler
+	return b
+}
+
+// Build creates an immutable server with dynamic capabilities
+func (b *ServerBuilder) Build() *Server {
+	// Build dynamic capabilities based on what components are present
+	capabilities := ServerCapabilities{
+		Logging: &LoggingCapability{}, // Always present
+	}
+
+	if len(b.tools) > 0 {
+		capabilities.Tools = &ToolsCapability{}
+	}
+	if len(b.prompts) > 0 {
+		capabilities.Prompts = &PromptsCapability{}
+	}
+	if len(b.resources) > 0 {
+		capabilities.Resources = &ResourcesCapability{}
+	}
+	if len(b.roots) > 0 {
+		capabilities.Roots = &RootsCapability{}
+	}
+
+	server := &Server{
+		name:                b.name,
+		version:             b.version,
+		capabilities:        capabilities,
+		tools:               make(map[string]Tool),
+		prompts:             make(map[string]Prompt),
+		resourceDefinitions: make(map[string]Resource),
+		rootDefinitions:     make(map[string]Root),
+		initializeHandler:   b.initializeHandler,
+		shutdownHandler:     b.shutdownHandler,
+	}
+
+	// Register all components
+	for _, tool := range b.tools {
+		server.tools[tool.Name] = tool
+	}
+	for _, prompt := range b.prompts {
+		server.prompts[prompt.Name] = prompt
+	}
+	for _, resource := range b.resources {
+		server.resourceDefinitions[resource.URI] = resource
+	}
+	for _, root := range b.roots {
+		server.rootDefinitions[root.URI] = root
+	}
+
+	return server
+}
Makefile
@@ -33,6 +33,12 @@ $(BINDIR)/mcp-%: cmd/%/main.go
 test: ## Run all tests
 	$(GOTEST) -v ./...
 
+test-smoke: clean build
+	echo '{"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {}}' | ./bin/mcp-filesystem --allowed-directory . | jq '.'
+	echo '{"jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {}}' | ./bin/mcp-filesystem --allowed-directory . | jq '.'
+	echo '{"jsonrpc": "2.0", "id": 1, "method": "resources/list", "params": {}}' | ./bin/mcp-filesystem --allowed-directory . | jq '.'
+	echo '{"jsonrpc": "2.0", "id": 1, "method": "prompts/list", "params": {}}' | ./bin/mcp-filesystem --allowed-directory . | jq '.'
+
 test-coverage: ## Run tests with coverage
 	$(GOTEST) -cover ./...