Improved parameter validation

Change-Id: If2e7ec1b063a6e114a6c5582463af784b75c37b8
diff --git a/tools/search_test.go b/tools/search_test.go
index 5966877..b80915a 100644
--- a/tools/search_test.go
+++ b/tools/search_test.go
@@ -32,6 +32,9 @@
 
 	// Verify it's an object type
 	assert.Equal(t, "object", schema["type"])
+	assert.Equal(t, "KorAP Search Parameters", schema["title"])
+	assert.Contains(t, schema["description"], "Parameters for searching text corpora")
+	assert.Equal(t, false, schema["additionalProperties"])
 
 	// Verify properties exist
 	properties, ok := schema["properties"].(map[string]interface{})
@@ -40,12 +43,168 @@
 	assert.Contains(t, properties, "query_language")
 	assert.Contains(t, properties, "corpus")
 	assert.Contains(t, properties, "count")
-	// Note: offset and context will be added in future iterations
+
+	// Verify query property details
+	query, ok := properties["query"].(map[string]interface{})
+	assert.True(t, ok)
+	assert.Equal(t, "string", query["type"])
+	assert.Contains(t, query["description"], "search query")
+	assert.Equal(t, 1, query["minLength"])
+	assert.Equal(t, 1000, query["maxLength"])
+	examples, ok := query["examples"].([]string)
+	assert.True(t, ok)
+	assert.Contains(t, examples, "Haus")
+
+	// Verify query_language property details
+	queryLang, ok := properties["query_language"].(map[string]interface{})
+	assert.True(t, ok)
+	assert.Equal(t, "string", queryLang["type"])
+	assert.Contains(t, queryLang["description"], "Query language to use for parsing")
+	enum, ok := queryLang["enum"].([]string)
+	assert.True(t, ok)
+	assert.Contains(t, enum, "poliqarp")
+	assert.Contains(t, enum, "cosmas2")
+	assert.Contains(t, enum, "annis")
+	assert.Contains(t, enum, "cql")
+	assert.Contains(t, enum, "cqp")
+	assert.Contains(t, enum, "fcsql")
+	assert.Equal(t, "poliqarp", queryLang["default"])
+
+	// Verify corpus property details
+	corpus, ok := properties["corpus"].(map[string]interface{})
+	assert.True(t, ok)
+	assert.Equal(t, "string", corpus["type"])
+	assert.Contains(t, corpus["description"], "Virtual corpus query")
+	assert.NotEmpty(t, corpus["pattern"])
+	corpusExamples, ok := corpus["examples"].([]string)
+	assert.True(t, ok)
+	assert.Contains(t, corpusExamples, "corpusSigle = \"GOE\"")
+
+	// Verify count property details
+	count, ok := properties["count"].(map[string]interface{})
+	assert.True(t, ok)
+	assert.Equal(t, "integer", count["type"])
+	assert.Contains(t, count["description"], "Maximum number")
+	assert.Equal(t, 0, count["minimum"])
+	assert.Equal(t, 10000, count["maximum"])
+	assert.Equal(t, 25, count["default"])
+	countExamples, ok := count["examples"].([]interface{})
+	assert.True(t, ok)
+	assert.Contains(t, countExamples, 25)
 
 	// Verify required fields
 	required, ok := schema["required"].([]string)
 	assert.True(t, ok)
 	assert.Contains(t, required, "query")
+	assert.Len(t, required, 1) // Only query should be required
+}
+
+func TestSearchTool_SchemaCompliance(t *testing.T) {
+	// Test various parameter combinations against the schema
+	client := &service.Client{}
+	tool := NewSearchTool(client)
+
+	tests := []struct {
+		name        string
+		arguments   map[string]interface{}
+		expectValid bool
+		errorMsg    string
+	}{
+		{
+			name: "valid_minimal",
+			arguments: map[string]interface{}{
+				"query": "test",
+			},
+			expectValid: true,
+		},
+		{
+			name: "valid_full",
+			arguments: map[string]interface{}{
+				"query":          "word",
+				"query_language": "cosmas2",
+				"corpus":         "test-corpus",
+				"count":          10,
+			},
+			expectValid: true,
+		},
+		{
+			name: "missing_required_query",
+			arguments: map[string]interface{}{
+				"query_language": "poliqarp",
+			},
+			expectValid: false,
+			errorMsg:    "query parameter is required",
+		},
+		{
+			name: "invalid_query_language",
+			arguments: map[string]interface{}{
+				"query":          "test",
+				"query_language": "invalid",
+			},
+			expectValid: false,
+			errorMsg:    "invalid query language",
+		},
+		{
+			name: "invalid_count_negative",
+			arguments: map[string]interface{}{
+				"query": "test",
+				"count": -1,
+			},
+			expectValid: false,
+			errorMsg:    "count must be",
+		},
+		{
+			name: "invalid_count_too_large",
+			arguments: map[string]interface{}{
+				"query": "test",
+				"count": 20000,
+			},
+			expectValid: false,
+			errorMsg:    "count must be",
+		},
+		{
+			name: "empty_query",
+			arguments: map[string]interface{}{
+				"query": "",
+			},
+			expectValid: false,
+			errorMsg:    "query is required and cannot be empty",
+		},
+		{
+			name: "count_zero_valid",
+			arguments: map[string]interface{}{
+				"query": "test",
+				"count": 0,
+			},
+			expectValid: true, // Zero count should be valid (uses default behavior)
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			request := mcp.CallToolRequest{
+				Params: mcp.CallToolParams{
+					Arguments: tt.arguments,
+				},
+			}
+
+			_, err := tool.Execute(context.Background(), request)
+
+			if tt.expectValid {
+				// For valid requests, we expect authentication/client errors, not validation errors
+				if err != nil {
+					assert.NotContains(t, err.Error(), "validation")
+					assert.Contains(t, err.Error(), "authentication")
+				}
+			} else {
+				// For invalid requests, we expect validation errors
+				assert.Error(t, err)
+				if tt.errorMsg != "" {
+					assert.Contains(t, err.Error(), tt.errorMsg)
+				}
+			}
+		})
+	}
 }
 
 func TestNewSearchTool(t *testing.T) {