Improved code by updating any interfaces
Change-Id: I9a2e630c37f3c427569f5bbd773978c2705dc08c
diff --git a/auth/oauth_test.go b/auth/oauth_test.go
index 9c6b0cc..65b4e50 100644
--- a/auth/oauth_test.go
+++ b/auth/oauth_test.go
@@ -126,7 +126,7 @@
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/token" {
w.Header().Set("Content-Type", "application/json")
- response := map[string]interface{}{
+ response := map[string]any{
"access_token": "test-access-token",
"token_type": "Bearer",
"expires_in": 3600,
@@ -162,7 +162,7 @@
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/token" {
w.Header().Set("Content-Type", "application/json")
- response := map[string]interface{}{
+ response := map[string]any{
"access_token": "client-credentials-token",
"token_type": "Bearer",
"expires_in": 3600,
@@ -249,7 +249,7 @@
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/token" {
w.Header().Set("Content-Type", "application/json")
- response := map[string]interface{}{
+ response := map[string]any{
"access_token": "refreshed-access-token",
"refresh_token": "new-refresh-token",
"token_type": "Bearer",
diff --git a/cmd/korap-mcp/main.go b/cmd/korap-mcp/main.go
index 2b67475..d908f10 100644
--- a/cmd/korap-mcp/main.go
+++ b/cmd/korap-mcp/main.go
@@ -37,10 +37,10 @@
err = server.AddTool(
"ping",
"Simple ping tool to test server connectivity",
- map[string]interface{}{
+ map[string]any{
"type": "object",
- "properties": map[string]interface{}{
- "message": map[string]interface{}{
+ "properties": map[string]any{
+ "message": map[string]any{
"type": "string",
"description": "Message to echo back",
},
diff --git a/cmd/korap-mcp/main_test.go b/cmd/korap-mcp/main_test.go
index b447a5b..4c45170 100644
--- a/cmd/korap-mcp/main_test.go
+++ b/cmd/korap-mcp/main_test.go
@@ -258,8 +258,8 @@
tests := []struct {
name string
field string
- expected interface{}
- actual interface{}
+ expected any
+ actual any
}{
{
name: "korap base URL",
diff --git a/logger/logger_test.go b/logger/logger_test.go
index 06bc660..84193fd 100644
--- a/logger/logger_test.go
+++ b/logger/logger_test.go
@@ -113,7 +113,7 @@
logger.Info().Str("test", "value").Msg("test message")
// Parse the JSON output
- var logEntry map[string]interface{}
+ var logEntry map[string]any
err := json.Unmarshal(buf.Bytes(), &logEntry)
assert.NoError(t, err)
diff --git a/mcp/server.go b/mcp/server.go
index b6d7b10..b3ea43b 100644
--- a/mcp/server.go
+++ b/mcp/server.go
@@ -31,7 +31,7 @@
}
// AddTool registers a new tool with the server
-func (s *Server) AddTool(name, description string, inputSchema map[string]interface{}, handler func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error)) error {
+func (s *Server) AddTool(name, description string, inputSchema map[string]any, handler func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error)) error {
if name == "" {
return fmt.Errorf("tool name cannot be empty")
}
diff --git a/mcp/server_test.go b/mcp/server_test.go
index a0073c3..c00d315 100644
--- a/mcp/server_test.go
+++ b/mcp/server_test.go
@@ -21,10 +21,10 @@
server := NewServer("test-server", "1.0.0")
// Test adding a valid tool
- err := server.AddTool("test-tool", "A test tool", map[string]interface{}{
+ err := server.AddTool("test-tool", "A test tool", map[string]any{
"type": "object",
- "properties": map[string]interface{}{
- "input": map[string]interface{}{
+ "properties": map[string]any{
+ "input": map[string]any{
"type": "string",
},
},
@@ -35,12 +35,12 @@
assert.NoError(t, err)
// Test adding tool with empty name
- err = server.AddTool("", "description", map[string]interface{}{}, nil)
+ err = server.AddTool("", "description", map[string]any{}, nil)
assert.Error(t, err)
assert.Contains(t, err.Error(), "tool name cannot be empty")
// Test adding tool with empty description
- err = server.AddTool("name", "", map[string]interface{}{}, nil)
+ err = server.AddTool("name", "", map[string]any{}, nil)
assert.Error(t, err)
assert.Contains(t, err.Error(), "tool description cannot be empty")
}
diff --git a/service/client.go b/service/client.go
index bdc9d8b..0ea0b94 100644
--- a/service/client.go
+++ b/service/client.go
@@ -139,7 +139,7 @@
}
// Post performs a POST request to the specified endpoint with JSON body
-func (c *Client) Post(ctx context.Context, endpoint string, body interface{}) (*http.Response, error) {
+func (c *Client) Post(ctx context.Context, endpoint string, body any) (*http.Response, error) {
var bodyReader io.Reader
if body != nil {
jsonBody, err := json.Marshal(body)
@@ -153,7 +153,7 @@
}
// GetJSON performs a GET request and unmarshals the JSON response
-func (c *Client) GetJSON(ctx context.Context, endpoint string, target interface{}) error {
+func (c *Client) GetJSON(ctx context.Context, endpoint string, target any) error {
resp, err := c.Get(ctx, endpoint)
if err != nil {
return err
@@ -172,7 +172,7 @@
}
// PostJSON performs a POST request and unmarshals the JSON response
-func (c *Client) PostJSON(ctx context.Context, endpoint string, body interface{}, target interface{}) error {
+func (c *Client) PostJSON(ctx context.Context, endpoint string, body any, target any) error {
resp, err := c.Post(ctx, endpoint, body)
if err != nil {
return err
diff --git a/service/client_test.go b/service/client_test.go
index 3827b09..0009d71 100644
--- a/service/client_test.go
+++ b/service/client_test.go
@@ -164,7 +164,7 @@
})
t.Run("Error handling", func(t *testing.T) {
- var result map[string]interface{}
+ var result map[string]any
err := client.GetJSON(ctx, "/error", &result)
assert.Error(t, err)
@@ -189,7 +189,7 @@
if r.URL.Path == "/token" {
// Mock token endpoint
w.Header().Set("Content-Type", "application/json")
- json.NewEncoder(w).Encode(map[string]interface{}{
+ json.NewEncoder(w).Encode(map[string]any{
"access_token": "test-access-token",
"token_type": "Bearer",
"expires_in": 3600,
@@ -232,7 +232,7 @@
ctx := context.Background()
t.Run("Unauthenticated request", func(t *testing.T) {
- var result map[string]interface{}
+ var result map[string]any
err := client.GetJSON(ctx, "/", &result)
assert.Error(t, err)
@@ -251,7 +251,7 @@
})
t.Run("Authenticated request", func(t *testing.T) {
- var result map[string]interface{}
+ var result map[string]any
err := client.GetJSON(ctx, "/", &result)
assert.NoError(t, err)
diff --git a/service/types.go b/service/types.go
index a6151b6..cb1aed0 100644
--- a/service/types.go
+++ b/service/types.go
@@ -42,14 +42,14 @@
// SearchMeta contains metadata about the search results
type SearchMeta struct {
- Count int `json:"count"`
- StartIndex int `json:"startIndex"`
- ItemsPerPage int `json:"itemsPerPage"`
- TotalResults int `json:"totalResults"`
- SearchTime float64 `json:"searchTime,omitempty"`
- Benchmark string `json:"benchmark,omitempty"`
- Context string `json:"context,omitempty"`
- CorpusStatistics map[string]interface{} `json:"corpusStatistics,omitempty"`
+ Count int `json:"count"`
+ StartIndex int `json:"startIndex"`
+ ItemsPerPage int `json:"itemsPerPage"`
+ TotalResults int `json:"totalResults"`
+ SearchTime float64 `json:"searchTime,omitempty"`
+ Benchmark string `json:"benchmark,omitempty"`
+ Context string `json:"context,omitempty"`
+ CorpusStatistics map[string]any `json:"corpusStatistics,omitempty"`
}
// SearchQuery contains information about the executed query
@@ -63,19 +63,19 @@
// SearchMatch represents a single search result match
type SearchMatch struct {
- Field string `json:"field"`
- PubPlace string `json:"pubPlace,omitempty"`
- TextSigle string `json:"textSigle"`
- UID int `json:"UID"`
- MatchID string `json:"matchID"`
- Snippet string `json:"snippet"`
- LeftContext []ContextToken `json:"leftContext,omitempty"`
- RightContext []ContextToken `json:"rightContext,omitempty"`
- Position int `json:"position"`
- StartMore bool `json:"startMore,omitempty"`
- EndMore bool `json:"endMore,omitempty"`
- Match []MatchToken `json:"match,omitempty"`
- Fields map[string]interface{} `json:"fields,omitempty"`
+ Field string `json:"field"`
+ PubPlace string `json:"pubPlace,omitempty"`
+ TextSigle string `json:"textSigle"`
+ UID int `json:"UID"`
+ MatchID string `json:"matchID"`
+ Snippet string `json:"snippet"`
+ LeftContext []ContextToken `json:"leftContext,omitempty"`
+ RightContext []ContextToken `json:"rightContext,omitempty"`
+ Position int `json:"position"`
+ StartMore bool `json:"startMore,omitempty"`
+ EndMore bool `json:"endMore,omitempty"`
+ Match []MatchToken `json:"match,omitempty"`
+ Fields map[string]any `json:"fields,omitempty"`
}
// ContextToken represents a token in the context
@@ -98,14 +98,14 @@
// CorpusInfo represents information about a corpus
type CorpusInfo struct {
- ID string `json:"id"`
- Name string `json:"name"`
- Description string `json:"description,omitempty"`
- Documents int `json:"documents,omitempty"`
- Tokens int `json:"tokens,omitempty"`
- Sentences int `json:"sentences,omitempty"`
- Paragraphs int `json:"paragraphs,omitempty"`
- Fields map[string]interface{} `json:"fields,omitempty"`
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Description string `json:"description,omitempty"`
+ Documents int `json:"documents,omitempty"`
+ Tokens int `json:"tokens,omitempty"`
+ Sentences int `json:"sentences,omitempty"`
+ Paragraphs int `json:"paragraphs,omitempty"`
+ Fields map[string]any `json:"fields,omitempty"`
}
// CorpusListResponse represents the response for corpus listing
@@ -115,9 +115,9 @@
// StatisticsResponse represents corpus statistics
type StatisticsResponse struct {
- Documents int `json:"documents"`
- Tokens int `json:"tokens"`
- Sentences int `json:"sentences,omitempty"`
- Paragraphs int `json:"paragraphs,omitempty"`
- Fields map[string]interface{} `json:"fields,omitempty"`
+ Documents int `json:"documents"`
+ Tokens int `json:"tokens"`
+ Sentences int `json:"sentences,omitempty"`
+ Paragraphs int `json:"paragraphs,omitempty"`
+ Fields map[string]any `json:"fields,omitempty"`
}
diff --git a/tools/metadata.go b/tools/metadata.go
index 46eb221..a70bd39 100644
--- a/tools/metadata.go
+++ b/tools/metadata.go
@@ -36,18 +36,18 @@
}
// InputSchema returns the JSON schema for tool parameters
-func (m *MetadataTool) InputSchema() map[string]interface{} {
- return map[string]interface{}{
+func (m *MetadataTool) InputSchema() map[string]any {
+ return map[string]any{
"type": "object",
- "properties": map[string]interface{}{
- "action": map[string]interface{}{
+ "properties": map[string]any{
+ "action": map[string]any{
"type": "string",
"description": "Type of metadata operation to perform. 'list' retrieves all available corpora with their basic information, 'statistics' provides detailed corpus statistics.",
"enum": []string{"list", "statistics"},
"default": "list",
"examples": []string{"list", "statistics"},
},
- "corpus": map[string]interface{}{
+ "corpus": map[string]any{
"type": "string",
"description": "Virtual corpus query to filter results based on metadata fields. For 'list' action, this parameter is ignored. For 'statistics' action, specifies which subset of data to analyze using metadata queries with boolean operations (& | !), comparison operators (= != < > in), and regular expressions (/pattern/). When not provided with 'statistics', returns statistics for all accessible data.",
"pattern": "^[a-zA-Z0-9._\\-\\s&|!=<>()/*\"']+$",
diff --git a/tools/metadata_test.go b/tools/metadata_test.go
index 04a067c..f1194d0 100644
--- a/tools/metadata_test.go
+++ b/tools/metadata_test.go
@@ -38,13 +38,13 @@
assert.Equal(t, false, schema["additionalProperties"])
// Verify properties exist
- properties, ok := schema["properties"].(map[string]interface{})
+ properties, ok := schema["properties"].(map[string]any)
assert.True(t, ok)
assert.Contains(t, properties, "action")
assert.Contains(t, properties, "corpus")
// Verify action property details
- action, ok := properties["action"].(map[string]interface{})
+ action, ok := properties["action"].(map[string]any)
assert.True(t, ok)
assert.Equal(t, "string", action["type"])
assert.Contains(t, action["description"], "Type of metadata operation")
@@ -61,7 +61,7 @@
assert.Contains(t, actionExamples, "statistics")
// Verify corpus property details
- corpus, ok := properties["corpus"].(map[string]interface{})
+ corpus, ok := properties["corpus"].(map[string]any)
assert.True(t, ok)
assert.Equal(t, "string", corpus["type"])
assert.Contains(t, corpus["description"], "Virtual corpus query")
@@ -89,7 +89,7 @@
// Create request without action parameter
request := mcp.CallToolRequest{
Params: mcp.CallToolParams{
- Arguments: map[string]interface{}{},
+ Arguments: map[string]any{},
},
}
@@ -103,7 +103,7 @@
request := mcp.CallToolRequest{
Params: mcp.CallToolParams{
- Arguments: map[string]interface{}{
+ Arguments: map[string]any{
"action": "list",
},
},
@@ -120,7 +120,7 @@
request := mcp.CallToolRequest{
Params: mcp.CallToolParams{
- Arguments: map[string]interface{}{
+ Arguments: map[string]any{
"action": "unknown",
},
},
@@ -138,7 +138,7 @@
request := mcp.CallToolRequest{
Params: mcp.CallToolParams{
- Arguments: map[string]interface{}{
+ Arguments: map[string]any{
"action": "statistics",
},
},
@@ -160,19 +160,19 @@
tests := []struct {
name string
- arguments map[string]interface{}
+ arguments map[string]any
expectErr bool
}{
{
name: "list_action",
- arguments: map[string]interface{}{
+ arguments: map[string]any{
"action": "list",
},
expectErr: true, // Will fail at authentication
},
{
name: "statistics_action",
- arguments: map[string]interface{}{
+ arguments: map[string]any{
"action": "statistics",
"corpus": "test-corpus",
},
@@ -180,7 +180,7 @@
},
{
name: "statistics_with_empty_corpus",
- arguments: map[string]interface{}{
+ arguments: map[string]any{
"action": "statistics",
"corpus": "",
},
@@ -276,7 +276,7 @@
Tokens: 100000,
Sentences: 5000,
Paragraphs: 1000,
- Fields: map[string]interface{}{
+ Fields: map[string]any{
"genre": "literature",
"language": "German",
"year": 2023,
@@ -310,27 +310,27 @@
tests := []struct {
name string
- arguments map[string]interface{}
+ arguments map[string]any
expectValid bool
errorMsg string
}{
{
name: "valid_list_minimal",
- arguments: map[string]interface{}{
+ arguments: map[string]any{
"action": "list",
},
expectValid: true,
},
{
name: "valid_statistics_minimal",
- arguments: map[string]interface{}{
+ arguments: map[string]any{
"action": "statistics",
},
expectValid: true,
},
{
name: "valid_statistics_with_corpus",
- arguments: map[string]interface{}{
+ arguments: map[string]any{
"action": "statistics",
"corpus": "test-corpus",
},
@@ -338,7 +338,7 @@
},
{
name: "valid_list_with_corpus_ignored",
- arguments: map[string]interface{}{
+ arguments: map[string]any{
"action": "list",
"corpus": "test-corpus", // Should be ignored for list action
},
@@ -346,7 +346,7 @@
},
{
name: "missing_required_action",
- arguments: map[string]interface{}{
+ arguments: map[string]any{
"corpus": "test-corpus",
},
expectValid: false,
@@ -354,7 +354,7 @@
},
{
name: "invalid_action",
- arguments: map[string]interface{}{
+ arguments: map[string]any{
"action": "invalid",
},
expectValid: false,
@@ -362,7 +362,7 @@
},
{
name: "empty_action",
- arguments: map[string]interface{}{
+ arguments: map[string]any{
"action": "",
},
expectValid: false,
@@ -370,7 +370,7 @@
},
{
name: "invalid_corpus_format",
- arguments: map[string]interface{}{
+ arguments: map[string]any{
"action": "statistics",
"corpus": "invalid@corpus#format",
},
@@ -379,7 +379,7 @@
},
{
name: "valid_corpus_with_boolean",
- arguments: map[string]interface{}{
+ arguments: map[string]any{
"action": "statistics",
"corpus": "corpus1 & corpus2",
},
@@ -387,7 +387,7 @@
},
{
name: "valid_collection_query",
- arguments: map[string]interface{}{
+ arguments: map[string]any{
"action": "statistics",
"corpus": "textClass = \"politics\" & pubDate in 2020",
},
diff --git a/tools/registry.go b/tools/registry.go
index 9116f08..fc3bb7c 100644
--- a/tools/registry.go
+++ b/tools/registry.go
@@ -18,7 +18,7 @@
Description() string
// InputSchema returns the JSON schema for the tool's input parameters
- InputSchema() map[string]interface{}
+ InputSchema() map[string]any
// Execute runs the tool with the given arguments and returns the result
Execute(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error)
diff --git a/tools/registry_test.go b/tools/registry_test.go
index 4e70978..1c1693d 100644
--- a/tools/registry_test.go
+++ b/tools/registry_test.go
@@ -12,7 +12,7 @@
type mockTool struct {
name string
description string
- schema map[string]interface{}
+ schema map[string]any
}
func (t *mockTool) Name() string {
@@ -23,7 +23,7 @@
return t.description
}
-func (t *mockTool) InputSchema() map[string]interface{} {
+func (t *mockTool) InputSchema() map[string]any {
return t.schema
}
@@ -44,7 +44,7 @@
tool := &mockTool{
name: "test-tool",
description: "A test tool",
- schema: map[string]interface{}{
+ schema: map[string]any{
"type": "object",
},
}
diff --git a/tools/schema_test.go b/tools/schema_test.go
index 4365537..240d0c1 100644
--- a/tools/schema_test.go
+++ b/tools/schema_test.go
@@ -37,14 +37,14 @@
}
// validateBasicSchemaStructure checks that the schema has the required top-level properties
-func validateBasicSchemaStructure(t *testing.T, schema map[string]interface{}, toolName string) {
+func validateBasicSchemaStructure(t *testing.T, schema map[string]any, toolName string) {
// Must be object type
assert.Equal(t, "object", schema["type"], "Tool %s schema must be object type", toolName)
// Must have properties
properties, exists := schema["properties"]
assert.True(t, exists, "Tool %s schema must have properties", toolName)
- assert.IsType(t, map[string]interface{}{}, properties, "Tool %s properties must be an object", toolName)
+ assert.IsType(t, map[string]any{}, properties, "Tool %s properties must be an object", toolName)
// Must have required array
required, exists := schema["required"]
@@ -61,11 +61,11 @@
}
// validateSchemaIsValidJSON ensures the schema can be properly serialized to JSON
-func validateSchemaIsValidJSON(t *testing.T, schema map[string]interface{}, toolName string) {
+func validateSchemaIsValidJSON(t *testing.T, schema map[string]any, toolName string) {
jsonBytes, err := json.Marshal(schema)
require.NoError(t, err, "Tool %s schema must be serializable to JSON", toolName)
- var unmarshalled map[string]interface{}
+ var unmarshalled map[string]any
err = json.Unmarshal(jsonBytes, &unmarshalled)
require.NoError(t, err, "Tool %s schema JSON must be valid", toolName)
@@ -74,12 +74,12 @@
}
// validateSchemaDocumentation checks that all properties have proper documentation
-func validateSchemaDocumentation(t *testing.T, schema map[string]interface{}, toolName string) {
- properties, ok := schema["properties"].(map[string]interface{})
+func validateSchemaDocumentation(t *testing.T, schema map[string]any, toolName string) {
+ properties, ok := schema["properties"].(map[string]any)
require.True(t, ok, "Tool %s properties must be accessible", toolName)
for propName, propSchema := range properties {
- propMap, ok := propSchema.(map[string]interface{})
+ propMap, ok := propSchema.(map[string]any)
require.True(t, ok, "Tool %s property %s must be an object", toolName, propName)
// Must have type
@@ -133,10 +133,10 @@
tool := NewSearchTool(client)
schema := tool.InputSchema()
- properties := schema["properties"].(map[string]interface{})
+ properties := schema["properties"].(map[string]any)
// Test query examples
- queryProp := properties["query"].(map[string]interface{})
+ queryProp := properties["query"].(map[string]any)
examples := queryProp["examples"].([]string)
for _, example := range examples {
@@ -145,7 +145,7 @@
}
// Test corpus examples
- corpusProp := properties["corpus"].(map[string]interface{})
+ corpusProp := properties["corpus"].(map[string]any)
corpusExamples := corpusProp["examples"].([]string)
for _, example := range corpusExamples {
@@ -160,10 +160,10 @@
tool := NewMetadataTool(client)
schema := tool.InputSchema()
- properties := schema["properties"].(map[string]interface{})
+ properties := schema["properties"].(map[string]any)
// Test action examples
- actionProp := properties["action"].(map[string]interface{})
+ actionProp := properties["action"].(map[string]any)
examples := actionProp["examples"].([]string)
enumValues := actionProp["enum"].([]string)
@@ -180,10 +180,10 @@
t.Run("SearchTool", func(t *testing.T) {
tool := NewSearchTool(client)
schema := tool.InputSchema()
- properties := schema["properties"].(map[string]interface{})
+ properties := schema["properties"].(map[string]any)
// Test query constraints
- queryProp := properties["query"].(map[string]interface{})
+ queryProp := properties["query"].(map[string]any)
minLength := queryProp["minLength"].(int)
maxLength := queryProp["maxLength"].(int)
@@ -192,7 +192,7 @@
assert.LessOrEqual(t, maxLength, 10000, "Query maximum length should be reasonable")
// Test count constraints
- countProp := properties["count"].(map[string]interface{})
+ countProp := properties["count"].(map[string]any)
minimum := countProp["minimum"].(int)
maximum := countProp["maximum"].(int)
defaultValue := countProp["default"].(int)
@@ -228,14 +228,14 @@
// Tool-specific stability checks
switch tool.Name() {
case "korap_search":
- properties := schema["properties"].(map[string]interface{})
+ properties := schema["properties"].(map[string]any)
assert.Contains(t, properties, "query", "Search tool must always have query parameter")
required := schema["required"].([]string)
assert.Contains(t, required, "query", "Search tool must always require query parameter")
case "korap_metadata":
- properties := schema["properties"].(map[string]interface{})
+ properties := schema["properties"].(map[string]any)
assert.Contains(t, properties, "action", "Metadata tool must always have action parameter")
required := schema["required"].([]string)
@@ -312,14 +312,14 @@
}
// generateHelpText creates human-readable help text from a schema
-func generateHelpText(schema map[string]interface{}, toolName string) string {
+func generateHelpText(schema map[string]any, toolName string) string {
help := fmt.Sprintf("Tool: %s\n", toolName)
if desc, ok := schema["description"].(string); ok {
help += fmt.Sprintf("Description: %s\n\n", desc)
}
- properties, ok := schema["properties"].(map[string]interface{})
+ properties, ok := schema["properties"].(map[string]any)
if !ok {
return help
}
@@ -332,7 +332,7 @@
help += "Parameters:\n"
for paramName, paramSchema := range properties {
- paramMap, ok := paramSchema.(map[string]interface{})
+ paramMap, ok := paramSchema.(map[string]any)
if !ok {
continue
}
diff --git a/tools/search.go b/tools/search.go
index 002dc86..d1a15fe 100644
--- a/tools/search.go
+++ b/tools/search.go
@@ -36,37 +36,37 @@
}
// InputSchema returns the JSON schema for tool parameters
-func (s *SearchTool) InputSchema() map[string]interface{} {
- return map[string]interface{}{
+func (s *SearchTool) InputSchema() map[string]any {
+ return map[string]any{
"type": "object",
- "properties": map[string]interface{}{
- "query": map[string]interface{}{
+ "properties": map[string]any{
+ "query": map[string]any{
"type": "string",
"description": "The search query. Supports different query languages like Poliqarp, CosmasII, or Annis depending on the selected query_language parameter.",
"minLength": 1,
"maxLength": 1000,
"examples": []string{"Haus", "[pos=NN]", "der /w1:5 Mann"},
},
- "query_language": map[string]interface{}{
+ "query_language": map[string]any{
"type": "string",
"description": "Query language to use for parsing the search query. Supported languages: 'poliqarp' (default; extended Poliqarp QL), 'cosmas2' (corpus query syntax of COSMAS II), 'annis' (multi-layer annotation queries), 'cql' (corpus query language), 'cqp' (Corpus Query Processor syntax), 'fcsql' (Federated Content Search queries).",
"enum": []string{"poliqarp", "cosmas2", "annis", "cql", "cqp", "fcsql"},
"default": "poliqarp",
"examples": []string{"poliqarp", "cosmas2", "annis", "cql", "cqp", "fcsql"},
},
- "corpus": map[string]interface{}{
+ "corpus": map[string]any{
"type": "string",
"description": "Virtual corpus query to filter search results based on metadata fields. Supports boolean operations (& | !), comparison operators (= != < > in), and regular expressions (/pattern/). Use metadata fields like corpusSigle, textClass, pubDate, textType, availability, etc. When not provided, searches all available data accessible to the user.",
"pattern": "^[a-zA-Z0-9._\\-\\s&|!=<>()/*\"']+$",
"examples": []string{"corpusSigle = \"GOE\"", "textClass = \"politics\" & pubDate in 2020", "textType = \"news\" | textType = \"blog\"", "availability = /CC.*/ & textClass != \"fiction\""},
},
- "count": map[string]interface{}{
+ "count": map[string]any{
"type": "integer",
"description": "Maximum number of search results to return. Higher values may increase response time. Use smaller values for faster responses when doing exploratory searches.",
"minimum": 0,
"maximum": 10000,
"default": 25,
- "examples": []interface{}{10, 25, 50, 100},
+ "examples": []any{10, 25, 50, 100},
},
},
"required": []string{"query"},
diff --git a/tools/search_test.go b/tools/search_test.go
index b80915a..6be267d 100644
--- a/tools/search_test.go
+++ b/tools/search_test.go
@@ -37,7 +37,7 @@
assert.Equal(t, false, schema["additionalProperties"])
// Verify properties exist
- properties, ok := schema["properties"].(map[string]interface{})
+ properties, ok := schema["properties"].(map[string]any)
assert.True(t, ok)
assert.Contains(t, properties, "query")
assert.Contains(t, properties, "query_language")
@@ -45,7 +45,7 @@
assert.Contains(t, properties, "count")
// Verify query property details
- query, ok := properties["query"].(map[string]interface{})
+ query, ok := properties["query"].(map[string]any)
assert.True(t, ok)
assert.Equal(t, "string", query["type"])
assert.Contains(t, query["description"], "search query")
@@ -56,7 +56,7 @@
assert.Contains(t, examples, "Haus")
// Verify query_language property details
- queryLang, ok := properties["query_language"].(map[string]interface{})
+ queryLang, ok := properties["query_language"].(map[string]any)
assert.True(t, ok)
assert.Equal(t, "string", queryLang["type"])
assert.Contains(t, queryLang["description"], "Query language to use for parsing")
@@ -71,7 +71,7 @@
assert.Equal(t, "poliqarp", queryLang["default"])
// Verify corpus property details
- corpus, ok := properties["corpus"].(map[string]interface{})
+ corpus, ok := properties["corpus"].(map[string]any)
assert.True(t, ok)
assert.Equal(t, "string", corpus["type"])
assert.Contains(t, corpus["description"], "Virtual corpus query")
@@ -81,14 +81,14 @@
assert.Contains(t, corpusExamples, "corpusSigle = \"GOE\"")
// Verify count property details
- count, ok := properties["count"].(map[string]interface{})
+ count, ok := properties["count"].(map[string]any)
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{})
+ countExamples, ok := count["examples"].([]any)
assert.True(t, ok)
assert.Contains(t, countExamples, 25)
@@ -106,20 +106,20 @@
tests := []struct {
name string
- arguments map[string]interface{}
+ arguments map[string]any
expectValid bool
errorMsg string
}{
{
name: "valid_minimal",
- arguments: map[string]interface{}{
+ arguments: map[string]any{
"query": "test",
},
expectValid: true,
},
{
name: "valid_full",
- arguments: map[string]interface{}{
+ arguments: map[string]any{
"query": "word",
"query_language": "cosmas2",
"corpus": "test-corpus",
@@ -129,7 +129,7 @@
},
{
name: "missing_required_query",
- arguments: map[string]interface{}{
+ arguments: map[string]any{
"query_language": "poliqarp",
},
expectValid: false,
@@ -137,7 +137,7 @@
},
{
name: "invalid_query_language",
- arguments: map[string]interface{}{
+ arguments: map[string]any{
"query": "test",
"query_language": "invalid",
},
@@ -146,7 +146,7 @@
},
{
name: "invalid_count_negative",
- arguments: map[string]interface{}{
+ arguments: map[string]any{
"query": "test",
"count": -1,
},
@@ -155,7 +155,7 @@
},
{
name: "invalid_count_too_large",
- arguments: map[string]interface{}{
+ arguments: map[string]any{
"query": "test",
"count": 20000,
},
@@ -164,7 +164,7 @@
},
{
name: "empty_query",
- arguments: map[string]interface{}{
+ arguments: map[string]any{
"query": "",
},
expectValid: false,
@@ -172,7 +172,7 @@
},
{
name: "count_zero_valid",
- arguments: map[string]interface{}{
+ arguments: map[string]any{
"query": "test",
"count": 0,
},
@@ -222,7 +222,7 @@
// Create request without query parameter
request := mcp.CallToolRequest{
Params: mcp.CallToolParams{
- Arguments: map[string]interface{}{},
+ Arguments: map[string]any{},
},
}
@@ -236,7 +236,7 @@
request := mcp.CallToolRequest{
Params: mcp.CallToolParams{
- Arguments: map[string]interface{}{
+ Arguments: map[string]any{
"query": "test",
},
},
@@ -257,19 +257,19 @@
tests := []struct {
name string
- arguments map[string]interface{}
+ arguments map[string]any
expectErr bool
}{
{
name: "minimal_query",
- arguments: map[string]interface{}{
+ arguments: map[string]any{
"query": "test",
},
expectErr: true, // Will fail at authentication
},
{
name: "full_parameters",
- arguments: map[string]interface{}{
+ arguments: map[string]any{
"query": "word",
"query_language": "cosmas2",
"corpus": "test-corpus",
@@ -279,7 +279,7 @@
},
{
name: "invalid_count_type",
- arguments: map[string]interface{}{
+ arguments: map[string]any{
"query": "test",
"count": "invalid", // Should use default
},
diff --git a/validation/validator.go b/validation/validator.go
index 343e820..22fcc70 100644
--- a/validation/validator.go
+++ b/validation/validator.go
@@ -6,6 +6,8 @@
"regexp"
"strings"
+ "slices"
+
"github.com/korap/korap-mcp/service"
"github.com/rs/zerolog"
)
@@ -101,7 +103,7 @@
}
// Validate query language if provided
- if req.QueryLanguage != "" && !contains(validQueryLanguages, req.QueryLanguage) {
+ if req.QueryLanguage != "" && !slices.Contains(validQueryLanguages, req.QueryLanguage) {
errors = append(errors, ValidationError{
Field: "query_language",
Value: req.QueryLanguage,
@@ -452,13 +454,3 @@
return sanitized
}
-
-// contains checks if a string slice contains a specific value
-func contains(slice []string, item string) bool {
- for _, s := range slice {
- if s == item {
- return true
- }
- }
- return false
-}