Commit 817bb38

mo khan <mo@mokhan.ca>
2025-08-18 20:08:04
refactor: re-organized the mcp package
1 parent 1635915
pkg/mcp/content.go
@@ -0,0 +1,31 @@
+package mcp
+
+type Content interface {
+  GetType() string
+}
+
+type TextContent struct {
+  Type string `json:"type"`
+  Text string `json:"text"`
+}
+
+func (t TextContent) GetType() string {
+  return t.Type
+}
+
+type ImageContent struct {
+  Type     string `json:"type"`
+  Data     string `json:"data"`
+  MimeType string `json:"mimeType"`
+}
+
+func (i ImageContent) GetType() string {
+  return i.Type
+}
+
+func NewTextContent(text string) TextContent {
+  return TextContent{
+    Type: "text",
+    Text: text,
+  }
+}
\ No newline at end of file
pkg/mcp/initialize.go
@@ -0,0 +1,44 @@
+package mcp
+
+type InitializeRequest struct {
+  ProtocolVersion string       `json:"protocolVersion"`
+  Capabilities    Capabilities `json:"capabilities"`
+  ClientInfo      ClientInfo   `json:"clientInfo"`
+}
+
+type Capabilities struct {
+  Roots        *RootsCapability       `json:"roots,omitempty"`
+  Sampling     *SamplingCapability    `json:"sampling,omitempty"`
+  Experimental map[string]interface{} `json:"experimental,omitempty"`
+}
+
+type RootsCapability struct {
+  ListChanged bool `json:"listChanged,omitempty"`
+}
+
+type SamplingCapability struct{}
+
+type ClientInfo struct {
+  Name    string `json:"name"`
+  Version string `json:"version"`
+}
+
+type InitializeResult struct {
+  ProtocolVersion string             `json:"protocolVersion"`
+  Capabilities    ServerCapabilities `json:"capabilities"`
+  ServerInfo      ServerInfo         `json:"serverInfo"`
+  Instructions    string             `json:"instructions,omitempty"`
+}
+
+type ServerCapabilities struct {
+  Logging   *LoggingCapability   `json:"logging,omitempty"`
+  Prompts   *PromptsCapability   `json:"prompts,omitempty"`
+  Resources *ResourcesCapability `json:"resources,omitempty"`
+  Roots     *RootsCapability     `json:"roots,omitempty"`
+  Tools     *ToolsCapability     `json:"tools,omitempty"`
+}
+
+type ServerInfo struct {
+  Name    string `json:"name"`
+  Version string `json:"version"`
+}
\ No newline at end of file
pkg/mcp/jsonrpc.go
@@ -0,0 +1,25 @@
+package mcp
+
+import (
+  "encoding/json"
+)
+
+type JSONRPCRequest struct {
+  JSONRPC string          `json:"jsonrpc"`
+  ID      *int            `json:"id,omitempty"`
+  Method  string          `json:"method"`
+  Params  json.RawMessage `json:"params,omitempty"`
+}
+
+type JSONRPCResponse struct {
+  JSONRPC string           `json:"jsonrpc"`
+  ID      *int             `json:"id,omitempty"`
+  Result  *json.RawMessage `json:"result,omitempty"`
+  Error   *JSONRPCError    `json:"error,omitempty"`
+}
+
+type JSONRPCError struct {
+  Code    int         `json:"code"`
+  Message string      `json:"message"`
+  Data    interface{} `json:"data,omitempty"`
+}
\ No newline at end of file
pkg/mcp/logging.go
@@ -0,0 +1,32 @@
+package mcp
+
+type LoggingLevel string
+
+const (
+  LoggingLevelDebug   LoggingLevel = "debug"
+  LoggingLevelInfo    LoggingLevel = "info"
+  LoggingLevelNotice  LoggingLevel = "notice"
+  LoggingLevelWarning LoggingLevel = "warning"
+  LoggingLevelError   LoggingLevel = "error"
+  LoggingLevelCrit    LoggingLevel = "crit"
+  LoggingLevelAlert   LoggingLevel = "alert"
+  LoggingLevelEmerg   LoggingLevel = "emerg"
+)
+
+type LoggingCapability struct{}
+
+type SetLoggingLevelRequest struct {
+  Level LoggingLevel `json:"level"`
+}
+
+type LoggingMessageNotification struct {
+  Level  LoggingLevel `json:"level"`
+  Data   interface{}  `json:"data"`
+  Logger string       `json:"logger,omitempty"`
+}
+
+type ProgressNotification struct {
+  ProgressToken string  `json:"progressToken"`
+  Progress      float64 `json:"progress"`
+  Total         float64 `json:"total,omitempty"`
+}
\ No newline at end of file
pkg/mcp/mcp.go
@@ -0,0 +1,9 @@
+package mcp
+
+const (
+  ParseError     = -32700
+  InvalidRequest = -32600
+  MethodNotFound = -32601
+  InvalidParams  = -32602
+  InternalError  = -32603
+)
\ No newline at end of file
pkg/mcp/prompt.go
@@ -0,0 +1,48 @@
+package mcp
+
+type PromptHandler func(GetPromptRequest) (GetPromptResult, error)
+
+type Prompt struct {
+  Name        string           `json:"name"`
+  Description string           `json:"description"`
+  Arguments   []PromptArgument `json:"arguments,omitempty"`
+  Handler     PromptHandler    `json:"-"`
+}
+
+type PromptArgument struct {
+  Name        string `json:"name"`
+  Description string `json:"description"`
+  Required    bool   `json:"required,omitempty"`
+}
+
+type PromptsCapability struct {
+  ListChanged bool `json:"listChanged,omitempty"`
+}
+
+type ListPromptsResult struct {
+  Prompts []Prompt `json:"prompts"`
+}
+
+type GetPromptRequest struct {
+  Name      string                 `json:"name"`
+  Arguments map[string]interface{} `json:"arguments,omitempty"`
+}
+
+type PromptMessage struct {
+  Role    string  `json:"role"`
+  Content Content `json:"content"`
+}
+
+type GetPromptResult struct {
+  Description string          `json:"description,omitempty"`
+  Messages    []PromptMessage `json:"messages"`
+}
+
+func NewPrompt(name, description string, arguments []PromptArgument, handler PromptHandler) Prompt {
+  return Prompt{
+    Name:        name,
+    Description: description,
+    Arguments:   arguments,
+    Handler:     handler,
+  }
+}
\ No newline at end of file
pkg/mcp/resource.go
@@ -0,0 +1,37 @@
+package mcp
+
+type ResourceHandler func(ReadResourceRequest) (ReadResourceResult, error)
+
+type Resource struct {
+  URI         string          `json:"uri"`
+  Name        string          `json:"name"`
+  Description string          `json:"description,omitempty"`
+  MimeType    string          `json:"mimeType,omitempty"`
+  Handler     ResourceHandler `json:"-"`
+}
+
+type ResourcesCapability struct {
+  Subscribe   bool `json:"subscribe,omitempty"`
+  ListChanged bool `json:"listChanged,omitempty"`
+}
+
+type ListResourcesResult struct {
+  Resources []Resource `json:"resources"`
+}
+
+type ReadResourceRequest struct {
+  URI string `json:"uri"`
+}
+
+type ReadResourceResult struct {
+  Contents []Content `json:"contents"`
+}
+
+func NewResource(uri, name, mimeType string, handler ResourceHandler) Resource {
+  return Resource{
+    URI:      uri,
+    Name:     name,
+    MimeType: mimeType,
+    Handler:  handler,
+  }
+}
\ No newline at end of file
pkg/mcp/root.go
@@ -0,0 +1,17 @@
+package mcp
+
+type Root struct {
+  URI  string `json:"uri"`
+  Name string `json:"name"`
+}
+
+type ListRootsResult struct {
+  Roots []Root `json:"roots"`
+}
+
+func NewRoot(uri, name string) Root {
+  return Root{
+    URI:  uri,
+    Name: name,
+  }
+}
\ No newline at end of file
pkg/mcp/roots.go
@@ -1,20 +0,0 @@
-package mcp
-
-// ListRootsRequest represents a request to list available roots
-type ListRootsRequest struct {
-	// No parameters for list_roots
-}
-
-// RootHandler defines the interface for handling root-related operations
-type RootHandler interface {
-	// ListRoots returns all available roots for this server
-	ListRoots() []Root
-}
-
-// NewRoot creates a new Root with the given URI and name
-func NewRoot(uri, name string) Root {
-	return Root{
-		URI:  uri,
-		Name: name,
-	}
-}
pkg/mcp/server.go
@@ -1,340 +1,258 @@
 package mcp
 
 import (
-	"bufio"
-	"context"
-	"encoding/json"
-	"fmt"
-	"log"
-	"os"
-	"strings"
+  "bufio"
+  "context"
+  "encoding/json"
+  "fmt"
+  "log"
+  "os"
+  "strings"
 )
 
 type Server struct {
-	name         string
-	version      string
-	capabilities ServerCapabilities
+  name         string
+  version      string
+  capabilities ServerCapabilities
 
-	tools               map[string]Tool
-	prompts             map[string]Prompt
-	resourceDefinitions map[string]Resource
-	rootDefinitions     map[string]Root
+  tools               map[string]Tool
+  prompts             map[string]Prompt
+  resourceDefinitions map[string]Resource
+  rootDefinitions     map[string]Root
 
-	initializeHandler func(InitializeRequest) (InitializeResult, error)
-	shutdownHandler   func() error
+  initializeHandler func(InitializeRequest) (InitializeResult, error)
+  shutdownHandler   func() error
 }
 
-type ResourceHandler func(ReadResourceRequest) (ReadResourceResult, error)
 
-func (s *Server) ListTools() []Tool {
-	tools := make([]Tool, 0, len(s.tools))
-	for _, tool := range s.tools {
-		tools = append(tools, tool)
-	}
-	return tools
-}
-
-// ListPrompts returns all registered prompts
-func (s *Server) ListPrompts() []Prompt {
-	prompts := make([]Prompt, 0, len(s.prompts))
-	for _, prompt := range s.prompts {
-		prompts = append(prompts, prompt)
-	}
-	return prompts
-}
-
-// ListResources returns all registered resources
-func (s *Server) ListResources() []Resource {
-	resources := make([]Resource, 0, len(s.resourceDefinitions))
-	for _, resource := range s.resourceDefinitions {
-		resources = append(resources, resource)
-	}
-	return resources
-}
-
-// ListRoots returns all registered roots
-func (s *Server) ListRoots() []Root {
-	roots := make([]Root, 0, len(s.rootDefinitions))
-	for _, root := range s.rootDefinitions {
-		roots = append(roots, root)
-	}
-	return roots
-}
-
-// Run starts the server and handles JSON-RPC over stdio
 func (s *Server) Run(ctx context.Context) error {
-	scanner := bufio.NewScanner(os.Stdin)
-	encoder := json.NewEncoder(os.Stdout)
-
-	for scanner.Scan() {
-		line := scanner.Bytes()
-
-		var req JSONRPCRequest
-		if err := json.Unmarshal(line, &req); err != nil {
-			s.sendError(encoder, nil, ParseError, "Parse error")
-			continue
-		}
-
-		response := s.handleRequest(req)
-		if err := encoder.Encode(response); err != nil {
-			log.Printf("Error encoding response: %v", err)
-		}
-
-		// Check for shutdown
-		if req.Method == "shutdown" {
-			break
-		}
-	}
-
-	if err := scanner.Err(); err != nil {
-		return fmt.Errorf("scanner error: %w", err)
-	}
-
-	return nil
-}
-
-// handleRequest processes a JSON-RPC request
-func (s *Server) handleRequest(req JSONRPCRequest) JSONRPCResponse {
-	switch req.Method {
-	case "initialize":
-		return s.handleInitialize(req)
-	case "initialized":
-		return s.handleInitialized(req)
-	case "shutdown":
-		return s.handleShutdown(req)
-	case "tools/list":
-		return s.handleListTools(req)
-	case "tools/call":
-		return s.handleCallTool(req)
-	case "prompts/list":
-		return s.handleListPrompts(req)
-	case "prompts/get":
-		return s.handleGetPrompt(req)
-	case "resources/list":
-		return s.handleListResources(req)
-	case "resources/read":
-		return s.handleReadResource(req)
-	case "roots/list":
-		return s.handleListRoots(req)
-	default:
-		return s.createErrorResponse(req.ID, MethodNotFound, "Method not found")
-	}
-}
-
-func (s *Server) handleInitialize(req JSONRPCRequest) JSONRPCResponse {
-	var initReq InitializeRequest
-	if err := json.Unmarshal(req.Params, &initReq); err != nil {
-		return s.createErrorResponse(req.ID, InvalidParams, "Invalid params")
-	}
-
-	result := InitializeResult{
-		ProtocolVersion: "2025-06-18",
-		Capabilities:    s.capabilities,
-		ServerInfo: ServerInfo{
-			Name:    s.name,
-			Version: s.version,
-		},
-	}
-
-	if s.initializeHandler != nil {
-		if customResult, err := s.initializeHandler(initReq); err == nil {
-			result = customResult
-		}
-	}
-
-	return s.createSuccessResponse(req.ID, result)
-}
-
-func (s *Server) handleInitialized(req JSONRPCRequest) JSONRPCResponse {
-	// Initialized notification - no response needed
-	return JSONRPCResponse{
-		JSONRPC: "2.0",
-		ID:      req.ID,
-	}
-}
-
-func (s *Server) handleShutdown(req JSONRPCRequest) JSONRPCResponse {
-	if s.shutdownHandler != nil {
-		s.shutdownHandler()
-	}
-
-	return s.createSuccessResponse(req.ID, nil)
-}
-
-func (s *Server) handleListTools(req JSONRPCRequest) JSONRPCResponse {
-	tools := s.ListTools()
-	result := ListToolsResult{Tools: tools}
-	return s.createSuccessResponse(req.ID, result)
-}
+  scanner := bufio.NewScanner(os.Stdin)
+  encoder := json.NewEncoder(os.Stdout)
 
-func (s *Server) handleCallTool(req JSONRPCRequest) JSONRPCResponse {
-	var callReq CallToolRequest
-	if err := json.Unmarshal(req.Params, &callReq); err != nil {
-		return s.createErrorResponse(req.ID, InvalidParams, "Invalid params")
-	}
+  for scanner.Scan() {
+    line := scanner.Bytes()
 
-	tool, exists := s.tools[callReq.Name]
-	if !exists {
-		return s.createErrorResponse(req.ID, MethodNotFound, "Tool not found")
-	}
+    var req JSONRPCRequest
+    if err := json.Unmarshal(line, &req); err != nil {
+      s.sendError(encoder, nil, ParseError, "Parse error")
+      continue
+    }
 
-	result, err := tool.Handler(callReq)
-	if err != nil {
-		return s.createErrorResponse(req.ID, InternalError, err.Error())
-	}
+    response := s.handleRequest(req)
+    if err := encoder.Encode(response); err != nil {
+      log.Printf("Error encoding response: %v", err)
+    }
 
-	return s.createSuccessResponse(req.ID, result)
-}
-
-func (s *Server) handleListPrompts(req JSONRPCRequest) JSONRPCResponse {
-	prompts := s.ListPrompts()
-	result := ListPromptsResult{Prompts: prompts}
-	return s.createSuccessResponse(req.ID, result)
-}
+    if req.Method == "shutdown" {
+      break
+    }
+  }
 
-func (s *Server) handleGetPrompt(req JSONRPCRequest) JSONRPCResponse {
-	var promptReq GetPromptRequest
-	if err := json.Unmarshal(req.Params, &promptReq); err != nil {
-		return s.createErrorResponse(req.ID, InvalidParams, "Invalid params")
-	}
+  if err := scanner.Err(); err != nil {
+    return fmt.Errorf("scanner error: %w", err)
+  }
 
-	prompt, exists := s.prompts[promptReq.Name]
-	if !exists {
-		return s.createErrorResponse(req.ID, MethodNotFound, "Prompt not found")
-	}
-
-	result, err := prompt.Handler(promptReq)
-	if err != nil {
-		return s.createErrorResponse(req.ID, InternalError, err.Error())
-	}
-
-	return s.createSuccessResponse(req.ID, result)
+  return nil
 }
 
-func (s *Server) handleListResources(req JSONRPCRequest) JSONRPCResponse {
-	resources := s.ListResources()
-	result := ListResourcesResult{Resources: resources}
-	return s.createSuccessResponse(req.ID, result)
-}
-
-func (s *Server) handleListRoots(req JSONRPCRequest) JSONRPCResponse {
-	roots := s.ListRoots()
-	result := ListRootsResult{Roots: roots}
-	return s.createSuccessResponse(req.ID, result)
+func (s *Server) handleRequest(req JSONRPCRequest) JSONRPCResponse {
+  handleInitialize := func() JSONRPCResponse {
+    var initReq InitializeRequest
+    if err := json.Unmarshal(req.Params, &initReq); err != nil {
+      return s.createErrorResponse(req.ID, InvalidParams, "Invalid params")
+    }
+
+    result := InitializeResult{
+      ProtocolVersion: "2025-06-18",
+      Capabilities:    s.capabilities,
+      ServerInfo: ServerInfo{
+        Name:    s.name,
+        Version: s.version,
+      },
+    }
+
+    if s.initializeHandler != nil {
+      if customResult, err := s.initializeHandler(initReq); err == nil {
+        result = customResult
+      }
+    }
+
+    return s.createSuccessResponse(req.ID, result)
+  }
+
+  handleInitialized := func() JSONRPCResponse {
+    return JSONRPCResponse{
+      JSONRPC: "2.0",
+      ID:      req.ID,
+    }
+  }
+
+  handleShutdown := func() JSONRPCResponse {
+    if s.shutdownHandler != nil {
+      s.shutdownHandler()
+    }
+    return s.createSuccessResponse(req.ID, nil)
+  }
+
+  handleListTools := func() JSONRPCResponse {
+    tools := make([]Tool, 0, len(s.tools))
+    for _, tool := range s.tools {
+      tools = append(tools, tool)
+    }
+    result := ListToolsResult{Tools: tools}
+    return s.createSuccessResponse(req.ID, result)
+  }
+
+  handleCallTool := func() JSONRPCResponse {
+    var callReq CallToolRequest
+    if err := json.Unmarshal(req.Params, &callReq); err != nil {
+      return s.createErrorResponse(req.ID, InvalidParams, "Invalid params")
+    }
+
+    tool, exists := s.tools[callReq.Name]
+    if !exists {
+      return s.createErrorResponse(req.ID, MethodNotFound, "Tool not found")
+    }
+
+    result, err := tool.Handler(callReq)
+    if err != nil {
+      return s.createErrorResponse(req.ID, InternalError, err.Error())
+    }
+
+    return s.createSuccessResponse(req.ID, result)
+  }
+
+  handleListPrompts := func() JSONRPCResponse {
+    prompts := make([]Prompt, 0, len(s.prompts))
+    for _, prompt := range s.prompts {
+      prompts = append(prompts, prompt)
+    }
+    result := ListPromptsResult{Prompts: prompts}
+    return s.createSuccessResponse(req.ID, result)
+  }
+
+  handleGetPrompt := func() JSONRPCResponse {
+    var promptReq GetPromptRequest
+    if err := json.Unmarshal(req.Params, &promptReq); err != nil {
+      return s.createErrorResponse(req.ID, InvalidParams, "Invalid params")
+    }
+
+    prompt, exists := s.prompts[promptReq.Name]
+    if !exists {
+      return s.createErrorResponse(req.ID, MethodNotFound, "Prompt not found")
+    }
+
+    result, err := prompt.Handler(promptReq)
+    if err != nil {
+      return s.createErrorResponse(req.ID, InternalError, err.Error())
+    }
+
+    return s.createSuccessResponse(req.ID, result)
+  }
+
+  handleListResources := func() JSONRPCResponse {
+    resources := make([]Resource, 0, len(s.resourceDefinitions))
+    for _, resource := range s.resourceDefinitions {
+      resources = append(resources, resource)
+    }
+    result := ListResourcesResult{Resources: resources}
+    return s.createSuccessResponse(req.ID, result)
+  }
+
+  handleListRoots := func() JSONRPCResponse {
+    roots := make([]Root, 0, len(s.rootDefinitions))
+    for _, root := range s.rootDefinitions {
+      roots = append(roots, root)
+    }
+    result := ListRootsResult{Roots: roots}
+    return s.createSuccessResponse(req.ID, result)
+  }
+
+  handleReadResource := func() JSONRPCResponse {
+    var readReq ReadResourceRequest
+    if err := json.Unmarshal(req.Params, &readReq); err != nil {
+      return s.createErrorResponse(req.ID, InvalidParams, "Invalid params")
+    }
+
+    resource, exists := s.resourceDefinitions[readReq.URI]
+    if !exists {
+      for pattern, r := range s.resourceDefinitions {
+        if pattern != "" && readReq.URI != pattern &&
+          ((pattern == "file://" && strings.HasPrefix(readReq.URI, "file://")) ||
+            (strings.HasSuffix(pattern, "*") && strings.HasPrefix(readReq.URI, strings.TrimSuffix(pattern, "*")))) {
+          resource = r
+          exists = true
+          break
+        }
+      }
+    }
+
+    if !exists {
+      return s.createErrorResponse(req.ID, MethodNotFound, "Resource not found")
+    }
+
+    result, err := resource.Handler(readReq)
+    if err != nil {
+      return s.createErrorResponse(req.ID, InternalError, err.Error())
+    }
+
+    return s.createSuccessResponse(req.ID, result)
+  }
+
+  switch req.Method {
+  case "initialize":
+    return handleInitialize()
+  case "initialized":
+    return handleInitialized()
+  case "shutdown":
+    return handleShutdown()
+  case "tools/list":
+    return handleListTools()
+  case "tools/call":
+    return handleCallTool()
+  case "prompts/list":
+    return handleListPrompts()
+  case "prompts/get":
+    return handleGetPrompt()
+  case "resources/list":
+    return handleListResources()
+  case "resources/read":
+    return handleReadResource()
+  case "roots/list":
+    return handleListRoots()
+  default:
+    return s.createErrorResponse(req.ID, MethodNotFound, "Method not found")
+  }
 }
 
-func (s *Server) handleReadResource(req JSONRPCRequest) JSONRPCResponse {
-	var readReq ReadResourceRequest
-	if err := json.Unmarshal(req.Params, &readReq); err != nil {
-		return s.createErrorResponse(req.ID, InvalidParams, "Invalid params")
-	}
-
-	resource, exists := s.resourceDefinitions[readReq.URI]
-	if !exists {
-		// Try to find a pattern-based handler (e.g., for "file://" prefix)
-		for pattern, r := range s.resourceDefinitions {
-			if pattern != "" && readReq.URI != pattern &&
-				((pattern == "file://" && strings.HasPrefix(readReq.URI, "file://")) ||
-					(strings.HasSuffix(pattern, "*") && strings.HasPrefix(readReq.URI, strings.TrimSuffix(pattern, "*")))) {
-				resource = r
-				exists = true
-				break
-			}
-		}
-	}
-
-	if !exists {
-		return s.createErrorResponse(req.ID, MethodNotFound, "Resource not found")
-	}
-
-	result, err := resource.Handler(readReq)
-	if err != nil {
-		return s.createErrorResponse(req.ID, InternalError, err.Error())
-	}
-
-	return s.createSuccessResponse(req.ID, result)
-}
 
 func (s *Server) createSuccessResponse(id *int, result interface{}) JSONRPCResponse {
-	var resultBytes *json.RawMessage
-	if result != nil {
-		bytes, _ := json.Marshal(result)
-		rawMsg := json.RawMessage(bytes)
-		resultBytes = &rawMsg
-	}
-
-	return JSONRPCResponse{
-		JSONRPC: "2.0",
-		ID:      id,
-		Result:  resultBytes,
-	}
+  var resultBytes *json.RawMessage
+  if result != nil {
+    bytes, _ := json.Marshal(result)
+    rawMsg := json.RawMessage(bytes)
+    resultBytes = &rawMsg
+  }
+
+  return JSONRPCResponse{
+    JSONRPC: "2.0",
+    ID:      id,
+    Result:  resultBytes,
+  }
 }
 
 func (s *Server) createErrorResponse(id *int, code int, message string) JSONRPCResponse {
-	return JSONRPCResponse{
-		JSONRPC: "2.0",
-		ID:      id,
-		Error: &JSONRPCError{
-			Code:    code,
-			Message: message,
-		},
-	}
+  return JSONRPCResponse{
+    JSONRPC: "2.0",
+    ID:      id,
+    Error: &JSONRPCError{
+      Code:    code,
+      Message: message,
+    },
+  }
 }
 
 func (s *Server) sendError(encoder *json.Encoder, id *int, code int, message string) {
-	response := s.createErrorResponse(id, code, message)
-	encoder.Encode(response)
-}
-
-// Helper function to create text content
-func NewTextContent(text string) TextContent {
-	return TextContent{
-		Type: "text",
-		Text: text,
-	}
-}
-
-// Helper function to create tool result
-func NewToolResult(content ...Content) CallToolResult {
-	return CallToolResult{
-		Content: content,
-	}
-}
-
-// Helper function to create tool error result
-func NewToolError(message string) CallToolResult {
-	return CallToolResult{
-		Content: []Content{NewTextContent("Error: " + message)},
-		IsError: true,
-	}
-}
-
-// Helper function to create a new tool with all fields
-func NewTool(name, description string, inputSchema interface{}, handler ToolHandler) Tool {
-	return Tool{
-		Name:        name,
-		Description: description,
-		InputSchema: inputSchema,
-		Handler:     handler,
-	}
-}
-
-// Helper function to create a new resource with all fields
-func NewResource(uri, name, mimeType string, handler ResourceHandler) Resource {
-	return Resource{
-		URI:      uri,
-		Name:     name,
-		MimeType: mimeType,
-		Handler:  handler,
-	}
-}
-
-// Helper function to create a new prompt with all fields
-func NewPrompt(name, description string, arguments []PromptArgument, handler PromptHandler) Prompt {
-	return Prompt{
-		Name:        name,
-		Description: description,
-		Arguments:   arguments,
-		Handler:     handler,
-	}
+  response := s.createErrorResponse(id, code, message)
+  encoder.Encode(response)
 }
pkg/mcp/tool.go
@@ -0,0 +1,50 @@
+package mcp
+
+type ToolHandler func(CallToolRequest) (CallToolResult, error)
+
+type Tool struct {
+  Name        string      `json:"name"`
+  Description string      `json:"description"`
+  InputSchema interface{} `json:"inputSchema"`
+  Handler     ToolHandler `json:"-"`
+}
+
+type ToolsCapability struct {
+  ListChanged bool `json:"listChanged,omitempty"`
+}
+
+type ListToolsResult struct {
+  Tools []Tool `json:"tools"`
+}
+
+type CallToolRequest struct {
+  Name      string                 `json:"name"`
+  Arguments map[string]interface{} `json:"arguments,omitempty"`
+}
+
+type CallToolResult struct {
+  Content []Content `json:"content"`
+  IsError bool      `json:"isError,omitempty"`
+}
+
+func NewTool(name, description string, inputSchema interface{}, handler ToolHandler) Tool {
+  return Tool{
+    Name:        name,
+    Description: description,
+    InputSchema: inputSchema,
+    Handler:     handler,
+  }
+}
+
+func NewToolResult(content ...Content) CallToolResult {
+  return CallToolResult{
+    Content: content,
+  }
+}
+
+func NewToolError(message string) CallToolResult {
+  return CallToolResult{
+    Content: []Content{NewTextContent("Error: " + message)},
+    IsError: true,
+  }
+}
\ No newline at end of file
pkg/mcp/types.go
@@ -1,237 +0,0 @@
-package mcp
-
-import (
-	"encoding/json"
-)
-
-// JSON-RPC 2.0 types
-type JSONRPCRequest struct {
-	JSONRPC string          `json:"jsonrpc"`
-	ID      *int            `json:"id,omitempty"`
-	Method  string          `json:"method"`
-	Params  json.RawMessage `json:"params,omitempty"`
-}
-
-type JSONRPCResponse struct {
-	JSONRPC string           `json:"jsonrpc"`
-	ID      *int             `json:"id,omitempty"`
-	Result  *json.RawMessage `json:"result,omitempty"`
-	Error   *JSONRPCError    `json:"error,omitempty"`
-}
-
-type JSONRPCError struct {
-	Code    int         `json:"code"`
-	Message string      `json:"message"`
-	Data    interface{} `json:"data,omitempty"`
-}
-
-// JSON-RPC error codes
-const (
-	ParseError     = -32700
-	InvalidRequest = -32600
-	MethodNotFound = -32601
-	InvalidParams  = -32602
-	InternalError  = -32603
-)
-
-// MCP Protocol types
-type InitializeRequest struct {
-	ProtocolVersion string       `json:"protocolVersion"`
-	Capabilities    Capabilities `json:"capabilities"`
-	ClientInfo      ClientInfo   `json:"clientInfo"`
-}
-
-type Capabilities struct {
-	Roots        *RootsCapability       `json:"roots,omitempty"`
-	Sampling     *SamplingCapability    `json:"sampling,omitempty"`
-	Experimental map[string]interface{} `json:"experimental,omitempty"`
-}
-
-type RootsCapability struct {
-	ListChanged bool `json:"listChanged,omitempty"`
-}
-
-type SamplingCapability struct{}
-
-type ClientInfo struct {
-	Name    string `json:"name"`
-	Version string `json:"version"`
-}
-
-type InitializeResult struct {
-	ProtocolVersion string             `json:"protocolVersion"`
-	Capabilities    ServerCapabilities `json:"capabilities"`
-	ServerInfo      ServerInfo         `json:"serverInfo"`
-	Instructions    string             `json:"instructions,omitempty"`
-}
-
-type ServerCapabilities struct {
-	Logging   *LoggingCapability   `json:"logging,omitempty"`
-	Prompts   *PromptsCapability   `json:"prompts,omitempty"`
-	Resources *ResourcesCapability `json:"resources,omitempty"`
-	Roots     *RootsCapability     `json:"roots,omitempty"`
-	Tools     *ToolsCapability     `json:"tools,omitempty"`
-}
-
-type LoggingCapability struct{}
-type PromptsCapability struct {
-	ListChanged bool `json:"listChanged,omitempty"`
-}
-type ResourcesCapability struct {
-	Subscribe   bool `json:"subscribe,omitempty"`
-	ListChanged bool `json:"listChanged,omitempty"`
-}
-type ToolsCapability struct {
-	ListChanged bool `json:"listChanged,omitempty"`
-}
-
-type ServerInfo struct {
-	Name    string `json:"name"`
-	Version string `json:"version"`
-}
-
-// Tool types
-type ToolHandler func(CallToolRequest) (CallToolResult, error)
-
-type Tool struct {
-	Name        string      `json:"name"`
-	Description string      `json:"description"`
-	InputSchema interface{} `json:"inputSchema"`
-	Handler     ToolHandler `json:"-"`
-}
-
-type ListToolsResult struct {
-	Tools []Tool `json:"tools"`
-}
-
-type CallToolRequest struct {
-	Name      string                 `json:"name"`
-	Arguments map[string]interface{} `json:"arguments,omitempty"`
-}
-
-type CallToolResult struct {
-	Content []Content `json:"content"`
-	IsError bool      `json:"isError,omitempty"`
-}
-
-// Content types
-type Content interface {
-	GetType() string
-}
-
-type TextContent struct {
-	Type string `json:"type"`
-	Text string `json:"text"`
-}
-
-func (t TextContent) GetType() string {
-	return t.Type
-}
-
-type ImageContent struct {
-	Type     string `json:"type"`
-	Data     string `json:"data"`
-	MimeType string `json:"mimeType"`
-}
-
-func (i ImageContent) GetType() string {
-	return i.Type
-}
-
-// Handler types
-type PromptHandler func(GetPromptRequest) (GetPromptResult, error)
-
-// Prompt types
-type Prompt struct {
-	Name        string           `json:"name"`
-	Description string           `json:"description"`
-	Arguments   []PromptArgument `json:"arguments,omitempty"`
-	Handler     PromptHandler    `json:"-"`
-}
-
-type PromptArgument struct {
-	Name        string `json:"name"`
-	Description string `json:"description"`
-	Required    bool   `json:"required,omitempty"`
-}
-
-type ListPromptsResult struct {
-	Prompts []Prompt `json:"prompts"`
-}
-
-type GetPromptRequest struct {
-	Name      string                 `json:"name"`
-	Arguments map[string]interface{} `json:"arguments,omitempty"`
-}
-
-type PromptMessage struct {
-	Role    string  `json:"role"`
-	Content Content `json:"content"`
-}
-
-type GetPromptResult struct {
-	Description string          `json:"description,omitempty"`
-	Messages    []PromptMessage `json:"messages"`
-}
-
-// Resource types
-type Resource struct {
-	URI         string          `json:"uri"`
-	Name        string          `json:"name"`
-	Description string          `json:"description,omitempty"`
-	MimeType    string          `json:"mimeType,omitempty"`
-	Handler     ResourceHandler `json:"-"`
-}
-
-type ListResourcesResult struct {
-	Resources []Resource `json:"resources"`
-}
-
-type ReadResourceRequest struct {
-	URI string `json:"uri"`
-}
-
-type ReadResourceResult struct {
-	Contents []Content `json:"contents"`
-}
-
-// Root types
-type Root struct {
-	URI  string `json:"uri"`
-	Name string `json:"name"`
-}
-
-type ListRootsResult struct {
-	Roots []Root `json:"roots"`
-}
-
-// Logging types
-type LoggingLevel string
-
-const (
-	LoggingLevelDebug   LoggingLevel = "debug"
-	LoggingLevelInfo    LoggingLevel = "info"
-	LoggingLevelNotice  LoggingLevel = "notice"
-	LoggingLevelWarning LoggingLevel = "warning"
-	LoggingLevelError   LoggingLevel = "error"
-	LoggingLevelCrit    LoggingLevel = "crit"
-	LoggingLevelAlert   LoggingLevel = "alert"
-	LoggingLevelEmerg   LoggingLevel = "emerg"
-)
-
-type SetLoggingLevelRequest struct {
-	Level LoggingLevel `json:"level"`
-}
-
-// Notification types
-type LoggingMessageNotification struct {
-	Level  LoggingLevel `json:"level"`
-	Data   interface{}  `json:"data"`
-	Logger string       `json:"logger,omitempty"`
-}
-
-type ProgressNotification struct {
-	ProgressToken string  `json:"progressToken"`
-	Progress      float64 `json:"progress"`
-	Total         float64 `json:"total,omitempty"`
-}