From 3b9236695c7a6659d4b3395898b9d91b76c7cb7b Mon Sep 17 00:00:00 2001 From: silverwind Date: Wed, 25 Feb 2026 19:00:17 +0000 Subject: [PATCH] fix: add missing required attributes to search tool schemas (#135) ## Summary - Add `mcp.Required()` to `keyword` in `search_repos` and `search_users` tool schemas - Add `mcp.Required()` to `org` and `query` in `search_org_teams` tool schema - Add test verifying required fields are set on all search tool schemas - Fixes MCP clients failing with `keyword is required` because the schema didn't declare the field as required Closes #115 --- *This PR was authored by Claude.* Reviewed-on: https://gitea.com/gitea/gitea-mcp/pulls/135 Reviewed-by: Lunny Xiao Co-authored-by: silverwind Co-committed-by: silverwind --- operation/search/search.go | 8 +++---- operation/search/search_test.go | 42 +++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 operation/search/search_test.go diff --git a/operation/search/search.go b/operation/search/search.go index 3dee452..83a5d14 100644 --- a/operation/search/search.go +++ b/operation/search/search.go @@ -27,7 +27,7 @@ var ( SearchUsersTool = mcp.NewTool( SearchUsersToolName, mcp.WithDescription("search users"), - mcp.WithString("keyword", mcp.Description("Keyword")), + mcp.WithString("keyword", mcp.Required(), mcp.Description("Keyword")), mcp.WithNumber("page", mcp.Description("Page"), mcp.DefaultNumber(1)), mcp.WithNumber("pageSize", mcp.Description("PageSize"), mcp.DefaultNumber(100)), ) @@ -35,8 +35,8 @@ var ( SearOrgTeamsTool = mcp.NewTool( SearchOrgTeamsToolName, mcp.WithDescription("search organization teams"), - mcp.WithString("org", mcp.Description("organization name")), - mcp.WithString("query", mcp.Description("search organization teams")), + mcp.WithString("org", mcp.Required(), mcp.Description("organization name")), + mcp.WithString("query", mcp.Required(), mcp.Description("search organization teams")), mcp.WithBoolean("includeDescription", mcp.Description("include description?")), mcp.WithNumber("page", mcp.Description("Page"), mcp.DefaultNumber(1)), mcp.WithNumber("pageSize", mcp.Description("PageSize"), mcp.DefaultNumber(100)), @@ -45,7 +45,7 @@ var ( SearchReposTool = mcp.NewTool( SearchReposToolName, mcp.WithDescription("search repos"), - mcp.WithString("keyword", mcp.Description("Keyword")), + mcp.WithString("keyword", mcp.Required(), mcp.Description("Keyword")), mcp.WithBoolean("keywordIsTopic", mcp.Description("KeywordIsTopic")), mcp.WithBoolean("keywordInDescription", mcp.Description("KeywordInDescription")), mcp.WithNumber("ownerID", mcp.Description("OwnerID")), diff --git a/operation/search/search_test.go b/operation/search/search_test.go new file mode 100644 index 0000000..81e37e3 --- /dev/null +++ b/operation/search/search_test.go @@ -0,0 +1,42 @@ +package search + +import ( + "slices" + "testing" + + "github.com/mark3labs/mcp-go/mcp" +) + +func TestSearchToolsRequiredFields(t *testing.T) { + tests := []struct { + name string + tool mcp.Tool + required []string + }{ + { + name: "search_users", + tool: SearchUsersTool, + required: []string{"keyword"}, + }, + { + name: "search_org_teams", + tool: SearOrgTeamsTool, + required: []string{"org", "query"}, + }, + { + name: "search_repos", + tool: SearchReposTool, + required: []string{"keyword"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + for _, field := range tt.required { + if !slices.Contains(tt.tool.InputSchema.Required, field) { + t.Errorf("tool %s: expected %q to be required, got required=%v", tt.name, field, tt.tool.InputSchema.Required) + } + } + }) + } +}