diff --git a/operation/wiki/wiki.go b/operation/wiki/wiki.go index 1e4373b..b019724 100644 --- a/operation/wiki/wiki.go +++ b/operation/wiki/wiki.go @@ -2,6 +2,7 @@ package wiki import ( "context" + "encoding/base64" "fmt" "net/url" @@ -40,7 +41,7 @@ var ( mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")), mcp.WithString("pageName", mcp.Description("wiki page name (required for 'update', 'delete')")), mcp.WithString("title", mcp.Description("wiki page title (required for 'create', optional for 'update')")), - mcp.WithString("content_base64", mcp.Description("page content, base64 encoded (required for 'create', 'update')")), + mcp.WithString("content", mcp.Description("page content (required for 'create', 'update')")), mcp.WithString("message", mcp.Description("commit message")), ) ) @@ -176,7 +177,7 @@ func createWikiPageFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallTo if err != nil { return to.ErrorResult(err) } - contentBase64, err := params.GetString(args, "content_base64") + content, err := params.GetString(args, "content") if err != nil { return to.ErrorResult(err) } @@ -188,7 +189,7 @@ func createWikiPageFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallTo requestBody := map[string]string{ "title": title, - "content_base64": contentBase64, + "content_base64": base64.StdEncoding.EncodeToString([]byte(content)), "message": message, } @@ -216,13 +217,13 @@ func updateWikiPageFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallTo if err != nil { return to.ErrorResult(err) } - contentBase64, err := params.GetString(args, "content_base64") + content, err := params.GetString(args, "content") if err != nil { return to.ErrorResult(err) } requestBody := map[string]string{ - "content_base64": contentBase64, + "content_base64": base64.StdEncoding.EncodeToString([]byte(content)), } // If title is given, use it. Otherwise, keep current page name diff --git a/operation/wiki/wiki_test.go b/operation/wiki/wiki_test.go new file mode 100644 index 0000000..e72137d --- /dev/null +++ b/operation/wiki/wiki_test.go @@ -0,0 +1,75 @@ +package wiki + +import ( + "context" + "encoding/base64" + "encoding/json" + "io" + "net/http" + "net/http/httptest" + "testing" + + mcpContext "gitea.com/gitea/gitea-mcp/pkg/context" + "gitea.com/gitea/gitea-mcp/pkg/flag" + + "github.com/mark3labs/mcp-go/mcp" +) + +func TestWikiWriteBase64Encoding(t *testing.T) { + tests := []struct { + name string + method string + content string + }{ + {"create ascii", "create", "Hello, World!"}, + {"create unicode", "create", "日本語テスト 🎉"}, + {"create multiline", "create", "line1\nline2\nline3"}, + {"update ascii", "update", "Updated content"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var gotBody map[string]string + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + body, _ := io.ReadAll(r.Body) + json.Unmarshal(body, &gotBody) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write([]byte(`{"title":"test"}`)) + })) + defer srv.Close() + + origHost := flag.Host + flag.Host = srv.URL + defer func() { flag.Host = origHost }() + + ctx := context.WithValue(context.Background(), mcpContext.TokenContextKey, "test-token") + + args := map[string]any{ + "method": tt.method, + "owner": "org", + "repo": "repo", + "content": tt.content, + "pageName": "TestPage", + "title": "TestPage", + } + + req := mcp.CallToolRequest{} + req.Params.Arguments = args + + result, err := wikiWriteFn(ctx, req) + if err != nil { + t.Fatalf("wikiWriteFn() error: %v", err) + } + if result.IsError { + t.Fatalf("wikiWriteFn() returned error result") + } + + got := gotBody["content_base64"] + want := base64.StdEncoding.EncodeToString([]byte(tt.content)) + if got != want { + t.Errorf("content_base64 = %q, want %q", got, want) + } + }) + } +}