Enhance KorAP search
diff --git a/tools/search.go b/tools/search.go
index c11caa9..7a0422d 100644
--- a/tools/search.go
+++ b/tools/search.go
@@ -3,6 +3,7 @@
 import (
 	"context"
 	"fmt"
+	"strings"
 
 	"github.com/korap/korap-mcp/service"
 	"github.com/mark3labs/mcp-go/mcp"
@@ -68,26 +69,125 @@
 		Str("tool", s.Name()).
 		Msg("Executing search tool")
 
-	// Extract required query parameter using the same pattern as main.go
+	// Extract required query parameter
 	query, err := request.RequireString("query")
 	if err != nil {
 		return nil, fmt.Errorf("query parameter is required: %w", err)
 	}
 
+	// Extract optional parameters with defaults
+	queryLang := request.GetString("query_language", "poliqarp")
+	corpus := request.GetString("corpus", "")
+	count := request.GetInt("count", 25)
+
 	log.Debug().
 		Str("query", query).
+		Str("query_language", queryLang).
+		Str("corpus", corpus).
+		Int("count", count).
 		Msg("Parsed search parameters")
 
-	// For now, return a simple response to verify the tool works
-	// TODO: Implement actual KorAP search functionality
-	result := "KorAP Search Results\n"
-	result += "====================\n\n"
-	result += fmt.Sprintf("Query: %s\n", query)
-	result += "Status: Tool is working, KorAP integration to be implemented\n"
+	// Check if client is available and authenticated
+	if s.client == nil {
+		return nil, fmt.Errorf("KorAP client not configured")
+	}
+
+	if !s.client.IsAuthenticated() {
+		log.Warn().Msg("Client not authenticated, attempting authentication")
+		if err := s.client.AuthenticateWithClientCredentials(ctx); err != nil {
+			return nil, fmt.Errorf("authentication failed: %w", err)
+		}
+	}
+
+	// Prepare search request
+	searchReq := service.SearchRequest{
+		Query:      query,
+		QueryLang:  queryLang,
+		Collection: corpus,
+		Count:      count,
+	}
+
+	// Perform the search
+	var searchResp service.SearchResponse
+	err = s.client.PostJSON(ctx, "search", searchReq, &searchResp)
+	if err != nil {
+		log.Error().
+			Err(err).
+			Str("query", query).
+			Msg("Search request failed")
+		return nil, fmt.Errorf("search failed: %w", err)
+	}
 
 	log.Info().
 		Str("query", query).
-		Msg("Search tool executed successfully")
+		Int("total_results", searchResp.Meta.TotalResults).
+		Int("returned_matches", len(searchResp.Matches)).
+		Float64("search_time", searchResp.Meta.SearchTime).
+		Msg("Search completed successfully")
+
+	// Format the response
+	result := s.formatSearchResults(&searchResp)
 
 	return mcp.NewToolResultText(result), nil
 }
+
+// formatSearchResults formats the search response into a readable text format
+func (s *SearchTool) formatSearchResults(response *service.SearchResponse) string {
+	var result strings.Builder
+
+	result.WriteString("KorAP Search Results\n")
+	result.WriteString("====================\n\n")
+
+	// Query information
+	result.WriteString(fmt.Sprintf("Query: %s\n", response.Query.Query))
+	if response.Query.QueryLang != "" {
+		result.WriteString(fmt.Sprintf("Query Language: %s\n", response.Query.QueryLang))
+	}
+	if response.Query.Collection != "" {
+		result.WriteString(fmt.Sprintf("Corpus: %s\n", response.Query.Collection))
+	}
+	result.WriteString("\n")
+
+	// Result statistics
+	result.WriteString("Results Summary:\n")
+	result.WriteString(fmt.Sprintf("  Total Results: %d\n", response.Meta.TotalResults))
+	result.WriteString(fmt.Sprintf("  Shown: %d-%d\n",
+		response.Meta.StartIndex+1,
+		response.Meta.StartIndex+len(response.Matches)))
+	if response.Meta.SearchTime > 0 {
+		result.WriteString(fmt.Sprintf("  Search Time: %.3f seconds\n", response.Meta.SearchTime))
+	}
+	result.WriteString("\n")
+
+	// Individual matches
+	if len(response.Matches) > 0 {
+		result.WriteString("Matches:\n")
+		result.WriteString("--------\n")
+
+		for i, match := range response.Matches {
+			result.WriteString(fmt.Sprintf("\n%d. Text: %s\n", i+1, match.TextSigle))
+			if match.Snippet != "" {
+				result.WriteString(fmt.Sprintf("   Snippet: %s\n", match.Snippet))
+			}
+			if match.PubPlace != "" {
+				result.WriteString(fmt.Sprintf("   Publication: %s\n", match.PubPlace))
+			}
+			if match.MatchID != "" {
+				result.WriteString(fmt.Sprintf("   Match ID: %s\n", match.MatchID))
+			}
+			result.WriteString(fmt.Sprintf("   Position: %d\n", match.Position))
+		}
+	} else {
+		result.WriteString("No matches found.\n")
+	}
+
+	// Additional information
+	if response.Query.CutOff {
+		result.WriteString("\nNote: Results were cut off due to limits.\n")
+	}
+	if response.Query.TimeExceeded {
+		result.WriteString("\nNote: Search time limit was exceeded.\n")
+	}
+
+	return result.String()
+}