Content-Length: 45862 | pFad | http://github.com/github/github-mcp-server/pull/90.patch
thub.com
From 79a9380fae3a0b2208f7878a63df8a4bb8461d76 Mon Sep 17 00:00:00 2001
From: William Martin
Date: Thu, 3 Apr 2025 13:30:28 +0200
Subject: [PATCH 1/2] Make JSONRPC easier in conformance tests
---
conformance/conformance_test.go | 58 +++++++++++++--------------------
1 file changed, 23 insertions(+), 35 deletions(-)
diff --git a/conformance/conformance_test.go b/conformance/conformance_test.go
index 899ce38e2..282551c13 100644
--- a/conformance/conformance_test.go
+++ b/conformance/conformance_test.go
@@ -130,8 +130,11 @@ func TestCapabilities(t *testing.T) {
anthropicServer := start(t, anthropic)
githubServer := start(t, github)
- req := newInitializeRequest(
- initializeRequestParams{
+ req := initializeRequest{
+ JSONRPC: "2.0",
+ ID: 1,
+ Method: "initialize",
+ Params: initializeParams{
ProtocolVersion: "2025-03-26",
Capabilities: clientCapabilities{},
ClientInfo: clientInfo{
@@ -139,7 +142,7 @@ func TestCapabilities(t *testing.T) {
Version: "0.0.1",
},
},
- )
+ }
require.NoError(t, anthropicServer.send(req))
@@ -274,6 +277,14 @@ func (s server) receive(res response) error {
return res.unmarshal(line)
}
+type request interface {
+ marshal() ([]byte, error)
+}
+
+type response interface {
+ unmarshal([]byte) error
+}
+
type jsonRPRCRequest[params any] struct {
JSONRPC string `json:"jsonrpc"`
ID int `json:"id"`
@@ -281,6 +292,10 @@ type jsonRPRCRequest[params any] struct {
Params params `json:"params"`
}
+func (r jsonRPRCRequest[any]) marshal() ([]byte, error) {
+ return json.Marshal(r)
+}
+
type jsonRPRCResponse[result any] struct {
JSONRPC string `json:"jsonrpc"`
ID int `json:"id"`
@@ -288,34 +303,13 @@ type jsonRPRCResponse[result any] struct {
Result result `json:"result"`
}
-type request interface {
- marshal() ([]byte, error)
-}
-
-type response interface {
- unmarshal([]byte) error
-}
-
-func newInitializeRequest(params initializeRequestParams) initializeRequest {
- return initializeRequest{
- jsonRPRCRequest: jsonRPRCRequest[initializeRequestParams]{
- JSONRPC: "2.0",
- ID: 1,
- Method: "initialize",
- Params: params,
- },
- }
-}
-
-type initializeRequest struct {
- jsonRPRCRequest[initializeRequestParams]
+func (r *jsonRPRCResponse[any]) unmarshal(b []byte) error {
+ return json.Unmarshal(b, r)
}
-func (r initializeRequest) marshal() ([]byte, error) {
- return json.Marshal(r)
-}
+type initializeRequest = jsonRPRCRequest[initializeParams]
-type initializeRequestParams struct {
+type initializeParams struct {
ProtocolVersion string `json:"protocolVersion"`
Capabilities clientCapabilities `json:"capabilities"`
ClientInfo clientInfo `json:"clientInfo"`
@@ -328,13 +322,7 @@ type clientInfo struct {
Version string `json:"version"`
}
-type initializeResponse struct {
- jsonRPRCResponse[initializeResult]
-}
-
-func (r *initializeResponse) unmarshal(b []byte) error {
- return json.Unmarshal(b, r)
-}
+type initializeResponse = jsonRPRCResponse[initializeResult]
type initializeResult struct {
ProtocolVersion string `json:"protocolVersion"`
From e3dc62a820878fc87c77a28180b278293069056a Mon Sep 17 00:00:00 2001
From: William Martin
Date: Thu, 3 Apr 2025 22:23:10 +0200
Subject: [PATCH 2/2] Conform list tools
---
README.md | 40 +++---
cmd/mcpcurl/README.md | 2 +-
conformance/conformance_test.go | 85 ++++++++++++
go.mod | 1 +
pkg/github/code_scanning.go | 4 +-
pkg/github/code_scanning_test.go | 16 +--
pkg/github/pullrequests.go | 40 +++---
pkg/github/pullrequests_test.go | 182 ++++++++++++-------------
pkg/github/repositories.go | 6 +-
pkg/github/repositories_test.go | 6 +-
pkg/github/repository_resource.go | 4 +-
pkg/github/repository_resource_test.go | 2 +-
pkg/github/search.go | 2 +-
pkg/github/search_test.go | 2 +-
14 files changed, 239 insertions(+), 153 deletions(-)
diff --git a/README.md b/README.md
index 5b9084c4b..6c14ca756 100644
--- a/README.md
+++ b/README.md
@@ -150,7 +150,7 @@ export GITHUB_MCP_TOOL_ADD_ISSUE_COMMENT_DESCRIPTION="an alternative description
- `direction`: Sort direction ('asc', 'desc') (string, optional)
- `since`: Filter by date (ISO 8601 timestamp) (string, optional)
- `page`: Page number (number, optional)
- - `per_page`: Results per page (number, optional)
+ - `perPage`: Results per page (number, optional)
- **update_issue** - Update an existing issue in a GitHub repository
@@ -177,7 +177,7 @@ export GITHUB_MCP_TOOL_ADD_ISSUE_COMMENT_DESCRIPTION="an alternative description
- `owner`: Repository owner (string, required)
- `repo`: Repository name (string, required)
- - `pull_number`: Pull request number (number, required)
+ - `pullNumber`: Pull request number (number, required)
- **list_pull_requests** - List and filter repository pull requests
@@ -186,14 +186,14 @@ export GITHUB_MCP_TOOL_ADD_ISSUE_COMMENT_DESCRIPTION="an alternative description
- `state`: PR state (string, optional)
- `sort`: Sort field (string, optional)
- `direction`: Sort direction (string, optional)
- - `per_page`: Results per page (number, optional)
+ - `perPage`: Results per page (number, optional)
- `page`: Page number (number, optional)
- **merge_pull_request** - Merge a pull request
- `owner`: Repository owner (string, required)
- `repo`: Repository name (string, required)
- - `pull_number`: Pull request number (number, required)
+ - `pullNumber`: Pull request number (number, required)
- `commit_title`: Title for the merge commit (string, optional)
- `commit_message`: Message for the merge commit (string, optional)
- `merge_method`: Merge method (string, optional)
@@ -202,41 +202,41 @@ export GITHUB_MCP_TOOL_ADD_ISSUE_COMMENT_DESCRIPTION="an alternative description
- `owner`: Repository owner (string, required)
- `repo`: Repository name (string, required)
- - `pull_number`: Pull request number (number, required)
+ - `pullNumber`: Pull request number (number, required)
- **get_pull_request_status** - Get the combined status of all status checks for a pull request
- `owner`: Repository owner (string, required)
- `repo`: Repository name (string, required)
- - `pull_number`: Pull request number (number, required)
+ - `pullNumber`: Pull request number (number, required)
- **update_pull_request_branch** - Update a pull request branch with the latest changes from the base branch
- `owner`: Repository owner (string, required)
- `repo`: Repository name (string, required)
- - `pull_number`: Pull request number (number, required)
- - `expected_head_sha`: The expected SHA of the pull request's HEAD ref (string, optional)
+ - `pullNumber`: Pull request number (number, required)
+ - `expectedHeadSha`: The expected SHA of the pull request's HEAD ref (string, optional)
- **get_pull_request_comments** - Get the review comments on a pull request
- `owner`: Repository owner (string, required)
- `repo`: Repository name (string, required)
- - `pull_number`: Pull request number (number, required)
+ - `pullNumber`: Pull request number (number, required)
- **get_pull_request_reviews** - Get the reviews on a pull request
- `owner`: Repository owner (string, required)
- `repo`: Repository name (string, required)
- - `pull_number`: Pull request number (number, required)
+ - `pullNumber`: Pull request number (number, required)
- **create_pull_request_review** - Create a review on a pull request review
- `owner`: Repository owner (string, required)
- `repo`: Repository name (string, required)
- - `pull_number`: Pull request number (number, required)
+ - `pullNumber`: Pull request number (number, required)
- `body`: Review comment text (string, optional)
- `event`: Review action ('APPROVE', 'REQUEST_CHANGES', 'COMMENT') (string, required)
- - `commit_id`: SHA of commit to review (string, optional)
+ - `commitId`: SHA of commit to review (string, optional)
- `comments`: Line-specific comments array of objects, each object with path (string), position (number), and body (string) (array, optional)
- **create_pull_request** - Create a new pull request
@@ -276,14 +276,14 @@ export GITHUB_MCP_TOOL_ADD_ISSUE_COMMENT_DESCRIPTION="an alternative description
- `sort`: Sort field (string, optional)
- `order`: Sort order (string, optional)
- `page`: Page number (number, optional)
- - `per_page`: Results per page (number, optional)
+ - `perPage`: Results per page (number, optional)
- **create_repository** - Create a new GitHub repository
- `name`: Repository name (string, required)
- `description`: Repository description (string, optional)
- `private`: Whether the repository is private (boolean, optional)
- - `auto_init`: Auto-initialize with README (boolean, optional)
+ - `autoInit`: Auto-initialize with README (boolean, optional)
- **get_file_contents** - Get contents of a file or directory
@@ -311,7 +311,7 @@ export GITHUB_MCP_TOOL_ADD_ISSUE_COMMENT_DESCRIPTION="an alternative description
- `sha`: Branch name, tag, or commit SHA (string, optional)
- `path`: Only commits containing this file path (string, optional)
- `page`: Page number (number, optional)
- - `per_page`: Results per page (number, optional)
+ - `perPage`: Results per page (number, optional)
### Search
@@ -321,14 +321,14 @@ export GITHUB_MCP_TOOL_ADD_ISSUE_COMMENT_DESCRIPTION="an alternative description
- `sort`: Sort field (string, optional)
- `order`: Sort order (string, optional)
- `page`: Page number (number, optional)
- - `per_page`: Results per page (number, optional)
+ - `perPage`: Results per page (number, optional)
- **search_users** - Search for GitHub users
- `query`: Search query (string, required)
- `sort`: Sort field (string, optional)
- `order`: Sort order (string, optional)
- `page`: Page number (number, optional)
- - `per_page`: Results per page (number, optional)
+ - `perPage`: Results per page (number, optional)
### Code Scanning
@@ -336,7 +336,7 @@ export GITHUB_MCP_TOOL_ADD_ISSUE_COMMENT_DESCRIPTION="an alternative description
- `owner`: Repository owner (string, required)
- `repo`: Repository name (string, required)
- - `alert_number`: Alert number (number, required)
+ - `alertNumber`: Alert number (number, required)
- **list_code_scanning_alerts** - List code scanning alerts for a repository
- `owner`: Repository owner (string, required)
@@ -391,11 +391,11 @@ export GITHUB_MCP_TOOL_ADD_ISSUE_COMMENT_DESCRIPTION="an alternative description
- **Get Repository Content for a Specific Pull Request**
Retrieves the content of a repository at a specific path for a given pull request.
- - **Template**: `repo://{owner}/{repo}/refs/pull/{pr_number}/head/contents{/path*}`
+ - **Template**: `repo://{owner}/{repo}/refs/pull/{prNumber}/head/contents{/path*}`
- **Parameters**:
- `owner`: Repository owner (string, required)
- `repo`: Repository name (string, required)
- - `pr_number`: Pull request number (string, required)
+ - `prNumber`: Pull request number (string, required)
- `path`: File or directory path (string, optional)
## License
diff --git a/cmd/mcpcurl/README.md b/cmd/mcpcurl/README.md
index f7b7ea2bf..06ce26ee0 100644
--- a/cmd/mcpcurl/README.md
+++ b/cmd/mcpcurl/README.md
@@ -72,7 +72,7 @@ Use "mcpcurl tools [command] --help" for more information about a command.
Get help for a specific tool:
```bash
- % ./mcpcurl --stdio-server-cmd "docker run -i --rm -e GITHUB_PERSONAL_ACCESS_TOKEN mcp/github" tools get_issue --help
+ % ./mcpcurl --stdio-server-cmd "docker run -i --rm -e GITHUB_PERSONAL_ACCESS_TOKEN mcp/github" tools get_issue --help
Get details of a specific issue in a GitHub repository.
Usage:
diff --git a/conformance/conformance_test.go b/conformance/conformance_test.go
index 282551c13..cd69e013a 100644
--- a/conformance/conformance_test.go
+++ b/conformance/conformance_test.go
@@ -6,6 +6,7 @@ import (
"bufio"
"context"
"encoding/json"
+ "errors"
"fmt"
"io"
"os"
@@ -17,6 +18,8 @@ import (
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/client"
"github.com/docker/docker/pkg/stdcopy"
+ "github.com/google/go-cmp/cmp"
+ "github.com/google/go-cmp/cmp/cmpopts"
"github.com/stretchr/testify/require"
)
@@ -230,6 +233,69 @@ func diffNonNilFields(a, b interface{}, path string) string {
return sb.String()
}
+func TestListTools(t *testing.T) {
+ anthropicServer := start(t, anthropic)
+ githubServer := start(t, github)
+
+ req := listToolsRequest{
+ JSONRPC: "2.0",
+ ID: 1,
+ Method: "tools/list",
+ }
+
+ require.NoError(t, anthropicServer.send(req))
+
+ var anthropicListToolsResponse listToolsResponse
+ require.NoError(t, anthropicServer.receive(&anthropicListToolsResponse))
+
+ require.NoError(t, githubServer.send(req))
+
+ var ghListToolsResponse listToolsResponse
+ require.NoError(t, githubServer.receive(&ghListToolsResponse))
+
+ require.NoError(t, isToolListSubset(anthropicListToolsResponse.Result, ghListToolsResponse.Result), "expected the github list tools response to be a subset of the anthropic list tools response")
+}
+
+func isToolListSubset(subset, superset listToolsResult) error {
+ // Build a map from tool name to Tool from the superset
+ supersetMap := make(map[string]tool)
+ for _, tool := range superset.Tools {
+ supersetMap[tool.Name] = tool
+ }
+
+ var err error
+ for _, tool := range subset.Tools {
+ sup, ok := supersetMap[tool.Name]
+ if !ok {
+ return fmt.Errorf("tool %q not found in superset", tool.Name)
+ }
+
+ // Intentionally ignore the description fields because there are lots of slight differences.
+ // if tool.Description != sup.Description {
+ // return fmt.Errorf("description mismatch for tool %q, got %q expected %q", tool.Name, tool.Description, sup.Description)
+ // }
+
+ // Ignore any description fields within the input schema properties for the same reason
+ ignoreDescOpt := cmp.FilterPath(func(p cmp.Path) bool {
+ // Look for a field named "Properties" somewhere in the path
+ for _, ps := range p {
+ if sf, ok := ps.(cmp.StructField); ok && sf.Name() == "Properties" {
+ return true
+ }
+ }
+ return false
+ }, cmpopts.IgnoreMapEntries(func(k string, _ any) bool {
+ return k == "description"
+ }))
+
+ if diff := cmp.Diff(tool.InputSchema, sup.InputSchema, ignoreDescOpt); diff != "" {
+ err = errors.Join(err, fmt.Errorf("inputSchema mismatch for tool %q:\n%s", tool.Name, diff))
+ }
+ }
+
+ return err
+}
+
type serverStartResult struct {
server server
err error
@@ -348,3 +414,22 @@ type serverInfo struct {
Name string `json:"name"`
Version string `json:"version"`
}
+
+type listToolsRequest = jsonRPRCRequest[struct{}]
+
+type listToolsResponse = jsonRPRCResponse[listToolsResult]
+
+type listToolsResult struct {
+ Tools []tool `json:"tools"`
+}
+type tool struct {
+ Name string `json:"name"`
+ Description string `json:"description,omitempty"`
+ InputSchema inputSchema `json:"inputSchema"`
+}
+
+type inputSchema struct {
+ Type string `json:"type"`
+ Properties map[string]any `json:"properties,omitempty"`
+ Required []string `json:"required,omitempty"`
+}
diff --git a/go.mod b/go.mod
index 324ebccd8..cf96ca5de 100644
--- a/go.mod
+++ b/go.mod
@@ -5,6 +5,7 @@ go 1.23.7
require (
github.com/aws/smithy-go v1.22.3
github.com/docker/docker v28.0.4+incompatible
+ github.com/google/go-cmp v0.7.0
github.com/google/go-github/v69 v69.2.0
github.com/mark3labs/mcp-go v0.18.0
github.com/migueleliasweb/go-github-mock v1.1.0
diff --git a/pkg/github/code_scanning.go b/pkg/github/code_scanning.go
index 380dc02cf..81ee2c314 100644
--- a/pkg/github/code_scanning.go
+++ b/pkg/github/code_scanning.go
@@ -24,7 +24,7 @@ func getCodeScanningAlert(client *github.Client, t translations.TranslationHelpe
mcp.Required(),
mcp.Description("The name of the repository."),
),
- mcp.WithNumber("alert_number",
+ mcp.WithNumber("alertNumber",
mcp.Required(),
mcp.Description("The number of the alert."),
),
@@ -38,7 +38,7 @@ func getCodeScanningAlert(client *github.Client, t translations.TranslationHelpe
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
- alertNumber, err := requiredInt(request, "alert_number")
+ alertNumber, err := requiredInt(request, "alertNumber")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
diff --git a/pkg/github/code_scanning_test.go b/pkg/github/code_scanning_test.go
index 9dd301374..ec4d671ef 100644
--- a/pkg/github/code_scanning_test.go
+++ b/pkg/github/code_scanning_test.go
@@ -22,8 +22,8 @@ func Test_GetCodeScanningAlert(t *testing.T) {
assert.NotEmpty(t, tool.Description)
assert.Contains(t, tool.InputSchema.Properties, "owner")
assert.Contains(t, tool.InputSchema.Properties, "repo")
- assert.Contains(t, tool.InputSchema.Properties, "alert_number")
- assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner", "repo", "alert_number"})
+ assert.Contains(t, tool.InputSchema.Properties, "alertNumber")
+ assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner", "repo", "alertNumber"})
// Setup mock alert for success case
mockAlert := &github.Alert{
@@ -50,9 +50,9 @@ func Test_GetCodeScanningAlert(t *testing.T) {
),
),
requestArgs: map[string]interface{}{
- "owner": "owner",
- "repo": "repo",
- "alert_number": float64(42),
+ "owner": "owner",
+ "repo": "repo",
+ "alertNumber": float64(42),
},
expectError: false,
expectedAlert: mockAlert,
@@ -69,9 +69,9 @@ func Test_GetCodeScanningAlert(t *testing.T) {
),
),
requestArgs: map[string]interface{}{
- "owner": "owner",
- "repo": "repo",
- "alert_number": float64(9999),
+ "owner": "owner",
+ "repo": "repo",
+ "alertNumber": float64(9999),
},
expectError: true,
expectedErrMsg: "failed to get alert",
diff --git a/pkg/github/pullrequests.go b/pkg/github/pullrequests.go
index ddec1e6ef..c02336ca0 100644
--- a/pkg/github/pullrequests.go
+++ b/pkg/github/pullrequests.go
@@ -25,7 +25,7 @@ func getPullRequest(client *github.Client, t translations.TranslationHelperFunc)
mcp.Required(),
mcp.Description("Repository name"),
),
- mcp.WithNumber("pull_number",
+ mcp.WithNumber("pullNumber",
mcp.Required(),
mcp.Description("Pull request number"),
),
@@ -39,7 +39,7 @@ func getPullRequest(client *github.Client, t translations.TranslationHelperFunc)
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
- pullNumber, err := requiredInt(request, "pull_number")
+ pullNumber, err := requiredInt(request, "pullNumber")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
@@ -186,7 +186,7 @@ func mergePullRequest(client *github.Client, t translations.TranslationHelperFun
mcp.Required(),
mcp.Description("Repository name"),
),
- mcp.WithNumber("pull_number",
+ mcp.WithNumber("pullNumber",
mcp.Required(),
mcp.Description("Pull request number"),
),
@@ -209,7 +209,7 @@ func mergePullRequest(client *github.Client, t translations.TranslationHelperFun
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
- pullNumber, err := requiredInt(request, "pull_number")
+ pullNumber, err := requiredInt(request, "pullNumber")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
@@ -266,7 +266,7 @@ func getPullRequestFiles(client *github.Client, t translations.TranslationHelper
mcp.Required(),
mcp.Description("Repository name"),
),
- mcp.WithNumber("pull_number",
+ mcp.WithNumber("pullNumber",
mcp.Required(),
mcp.Description("Pull request number"),
),
@@ -280,7 +280,7 @@ func getPullRequestFiles(client *github.Client, t translations.TranslationHelper
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
- pullNumber, err := requiredInt(request, "pull_number")
+ pullNumber, err := requiredInt(request, "pullNumber")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
@@ -321,7 +321,7 @@ func getPullRequestStatus(client *github.Client, t translations.TranslationHelpe
mcp.Required(),
mcp.Description("Repository name"),
),
- mcp.WithNumber("pull_number",
+ mcp.WithNumber("pullNumber",
mcp.Required(),
mcp.Description("Pull request number"),
),
@@ -335,7 +335,7 @@ func getPullRequestStatus(client *github.Client, t translations.TranslationHelpe
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
- pullNumber, err := requiredInt(request, "pull_number")
+ pullNumber, err := requiredInt(request, "pullNumber")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
@@ -390,11 +390,11 @@ func updatePullRequestBranch(client *github.Client, t translations.TranslationHe
mcp.Required(),
mcp.Description("Repository name"),
),
- mcp.WithNumber("pull_number",
+ mcp.WithNumber("pullNumber",
mcp.Required(),
mcp.Description("Pull request number"),
),
- mcp.WithString("expected_head_sha",
+ mcp.WithString("expectedHeadSha",
mcp.Description("The expected SHA of the pull request's HEAD ref"),
),
),
@@ -407,11 +407,11 @@ func updatePullRequestBranch(client *github.Client, t translations.TranslationHe
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
- pullNumber, err := requiredInt(request, "pull_number")
+ pullNumber, err := requiredInt(request, "pullNumber")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
- expectedHeadSHA, err := optionalParam[string](request, "expected_head_sha")
+ expectedHeadSHA, err := optionalParam[string](request, "expectedHeadSha")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
@@ -460,7 +460,7 @@ func getPullRequestComments(client *github.Client, t translations.TranslationHel
mcp.Required(),
mcp.Description("Repository name"),
),
- mcp.WithNumber("pull_number",
+ mcp.WithNumber("pullNumber",
mcp.Required(),
mcp.Description("Pull request number"),
),
@@ -474,7 +474,7 @@ func getPullRequestComments(client *github.Client, t translations.TranslationHel
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
- pullNumber, err := requiredInt(request, "pull_number")
+ pullNumber, err := requiredInt(request, "pullNumber")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
@@ -520,7 +520,7 @@ func getPullRequestReviews(client *github.Client, t translations.TranslationHelp
mcp.Required(),
mcp.Description("Repository name"),
),
- mcp.WithNumber("pull_number",
+ mcp.WithNumber("pullNumber",
mcp.Required(),
mcp.Description("Pull request number"),
),
@@ -534,7 +534,7 @@ func getPullRequestReviews(client *github.Client, t translations.TranslationHelp
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
- pullNumber, err := requiredInt(request, "pull_number")
+ pullNumber, err := requiredInt(request, "pullNumber")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
@@ -574,7 +574,7 @@ func createPullRequestReview(client *github.Client, t translations.TranslationHe
mcp.Required(),
mcp.Description("Repository name"),
),
- mcp.WithNumber("pull_number",
+ mcp.WithNumber("pullNumber",
mcp.Required(),
mcp.Description("Pull request number"),
),
@@ -585,7 +585,7 @@ func createPullRequestReview(client *github.Client, t translations.TranslationHe
mcp.Required(),
mcp.Description("Review action ('APPROVE', 'REQUEST_CHANGES', 'COMMENT')"),
),
- mcp.WithString("commit_id",
+ mcp.WithString("commitId",
mcp.Description("SHA of commit to review"),
),
mcp.WithArray("comments",
@@ -622,7 +622,7 @@ func createPullRequestReview(client *github.Client, t translations.TranslationHe
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
- pullNumber, err := requiredInt(request, "pull_number")
+ pullNumber, err := requiredInt(request, "pullNumber")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
@@ -646,7 +646,7 @@ func createPullRequestReview(client *github.Client, t translations.TranslationHe
}
// Add commit ID if provided
- commitID, err := optionalParam[string](request, "commit_id")
+ commitID, err := optionalParam[string](request, "commitId")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
diff --git a/pkg/github/pullrequests_test.go b/pkg/github/pullrequests_test.go
index 761de5010..b666e8a8b 100644
--- a/pkg/github/pullrequests_test.go
+++ b/pkg/github/pullrequests_test.go
@@ -23,8 +23,8 @@ func Test_GetPullRequest(t *testing.T) {
assert.NotEmpty(t, tool.Description)
assert.Contains(t, tool.InputSchema.Properties, "owner")
assert.Contains(t, tool.InputSchema.Properties, "repo")
- assert.Contains(t, tool.InputSchema.Properties, "pull_number")
- assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner", "repo", "pull_number"})
+ assert.Contains(t, tool.InputSchema.Properties, "pullNumber")
+ assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner", "repo", "pullNumber"})
// Setup mock PR for success case
mockPR := &github.PullRequest{
@@ -62,9 +62,9 @@ func Test_GetPullRequest(t *testing.T) {
),
),
requestArgs: map[string]interface{}{
- "owner": "owner",
- "repo": "repo",
- "pull_number": float64(42),
+ "owner": "owner",
+ "repo": "repo",
+ "pullNumber": float64(42),
},
expectError: false,
expectedPR: mockPR,
@@ -81,9 +81,9 @@ func Test_GetPullRequest(t *testing.T) {
),
),
requestArgs: map[string]interface{}{
- "owner": "owner",
- "repo": "repo",
- "pull_number": float64(999),
+ "owner": "owner",
+ "repo": "repo",
+ "pullNumber": float64(999),
},
expectError: true,
expectedErrMsg: "failed to get pull request",
@@ -265,11 +265,11 @@ func Test_MergePullRequest(t *testing.T) {
assert.NotEmpty(t, tool.Description)
assert.Contains(t, tool.InputSchema.Properties, "owner")
assert.Contains(t, tool.InputSchema.Properties, "repo")
- assert.Contains(t, tool.InputSchema.Properties, "pull_number")
+ assert.Contains(t, tool.InputSchema.Properties, "pullNumber")
assert.Contains(t, tool.InputSchema.Properties, "commit_title")
assert.Contains(t, tool.InputSchema.Properties, "commit_message")
assert.Contains(t, tool.InputSchema.Properties, "merge_method")
- assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner", "repo", "pull_number"})
+ assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner", "repo", "pullNumber"})
// Setup mock merge result for success case
mockMergeResult := &github.PullRequestMergeResult{
@@ -303,7 +303,7 @@ func Test_MergePullRequest(t *testing.T) {
requestArgs: map[string]interface{}{
"owner": "owner",
"repo": "repo",
- "pull_number": float64(42),
+ "pullNumber": float64(42),
"commit_title": "Merge PR #42",
"commit_message": "Merging awesome feature",
"merge_method": "squash",
@@ -323,9 +323,9 @@ func Test_MergePullRequest(t *testing.T) {
),
),
requestArgs: map[string]interface{}{
- "owner": "owner",
- "repo": "repo",
- "pull_number": float64(42),
+ "owner": "owner",
+ "repo": "repo",
+ "pullNumber": float64(42),
},
expectError: true,
expectedErrMsg: "failed to merge pull request",
@@ -376,8 +376,8 @@ func Test_GetPullRequestFiles(t *testing.T) {
assert.NotEmpty(t, tool.Description)
assert.Contains(t, tool.InputSchema.Properties, "owner")
assert.Contains(t, tool.InputSchema.Properties, "repo")
- assert.Contains(t, tool.InputSchema.Properties, "pull_number")
- assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner", "repo", "pull_number"})
+ assert.Contains(t, tool.InputSchema.Properties, "pullNumber")
+ assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner", "repo", "pullNumber"})
// Setup mock PR files for success case
mockFiles := []*github.CommitFile{
@@ -416,9 +416,9 @@ func Test_GetPullRequestFiles(t *testing.T) {
),
),
requestArgs: map[string]interface{}{
- "owner": "owner",
- "repo": "repo",
- "pull_number": float64(42),
+ "owner": "owner",
+ "repo": "repo",
+ "pullNumber": float64(42),
},
expectError: false,
expectedFiles: mockFiles,
@@ -435,9 +435,9 @@ func Test_GetPullRequestFiles(t *testing.T) {
),
),
requestArgs: map[string]interface{}{
- "owner": "owner",
- "repo": "repo",
- "pull_number": float64(999),
+ "owner": "owner",
+ "repo": "repo",
+ "pullNumber": float64(999),
},
expectError: true,
expectedErrMsg: "failed to get pull request files",
@@ -492,8 +492,8 @@ func Test_GetPullRequestStatus(t *testing.T) {
assert.NotEmpty(t, tool.Description)
assert.Contains(t, tool.InputSchema.Properties, "owner")
assert.Contains(t, tool.InputSchema.Properties, "repo")
- assert.Contains(t, tool.InputSchema.Properties, "pull_number")
- assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner", "repo", "pull_number"})
+ assert.Contains(t, tool.InputSchema.Properties, "pullNumber")
+ assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner", "repo", "pullNumber"})
// Setup mock PR for successful PR fetch
mockPR := &github.PullRequest{
@@ -553,9 +553,9 @@ func Test_GetPullRequestStatus(t *testing.T) {
),
),
requestArgs: map[string]interface{}{
- "owner": "owner",
- "repo": "repo",
- "pull_number": float64(42),
+ "owner": "owner",
+ "repo": "repo",
+ "pullNumber": float64(42),
},
expectError: false,
expectedStatus: mockStatus,
@@ -572,9 +572,9 @@ func Test_GetPullRequestStatus(t *testing.T) {
),
),
requestArgs: map[string]interface{}{
- "owner": "owner",
- "repo": "repo",
- "pull_number": float64(999),
+ "owner": "owner",
+ "repo": "repo",
+ "pullNumber": float64(999),
},
expectError: true,
expectedErrMsg: "failed to get pull request",
@@ -595,9 +595,9 @@ func Test_GetPullRequestStatus(t *testing.T) {
),
),
requestArgs: map[string]interface{}{
- "owner": "owner",
- "repo": "repo",
- "pull_number": float64(42),
+ "owner": "owner",
+ "repo": "repo",
+ "pullNumber": float64(42),
},
expectError: true,
expectedErrMsg: "failed to get combined status",
@@ -653,9 +653,9 @@ func Test_UpdatePullRequestBranch(t *testing.T) {
assert.NotEmpty(t, tool.Description)
assert.Contains(t, tool.InputSchema.Properties, "owner")
assert.Contains(t, tool.InputSchema.Properties, "repo")
- assert.Contains(t, tool.InputSchema.Properties, "pull_number")
- assert.Contains(t, tool.InputSchema.Properties, "expected_head_sha")
- assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner", "repo", "pull_number"})
+ assert.Contains(t, tool.InputSchema.Properties, "pullNumber")
+ assert.Contains(t, tool.InputSchema.Properties, "expectedHeadSha")
+ assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner", "repo", "pullNumber"})
// Setup mock update result for success case
mockUpdateResult := &github.PullRequestBranchUpdateResponse{
@@ -684,10 +684,10 @@ func Test_UpdatePullRequestBranch(t *testing.T) {
),
),
requestArgs: map[string]interface{}{
- "owner": "owner",
- "repo": "repo",
- "pull_number": float64(42),
- "expected_head_sha": "abcd1234",
+ "owner": "owner",
+ "repo": "repo",
+ "pullNumber": float64(42),
+ "expectedHeadSha": "abcd1234",
},
expectError: false,
expectedUpdateResult: mockUpdateResult,
@@ -703,9 +703,9 @@ func Test_UpdatePullRequestBranch(t *testing.T) {
),
),
requestArgs: map[string]interface{}{
- "owner": "owner",
- "repo": "repo",
- "pull_number": float64(42),
+ "owner": "owner",
+ "repo": "repo",
+ "pullNumber": float64(42),
},
expectError: false,
expectedUpdateResult: mockUpdateResult,
@@ -722,9 +722,9 @@ func Test_UpdatePullRequestBranch(t *testing.T) {
),
),
requestArgs: map[string]interface{}{
- "owner": "owner",
- "repo": "repo",
- "pull_number": float64(42),
+ "owner": "owner",
+ "repo": "repo",
+ "pullNumber": float64(42),
},
expectError: true,
expectedErrMsg: "failed to update pull request branch",
@@ -769,8 +769,8 @@ func Test_GetPullRequestComments(t *testing.T) {
assert.NotEmpty(t, tool.Description)
assert.Contains(t, tool.InputSchema.Properties, "owner")
assert.Contains(t, tool.InputSchema.Properties, "repo")
- assert.Contains(t, tool.InputSchema.Properties, "pull_number")
- assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner", "repo", "pull_number"})
+ assert.Contains(t, tool.InputSchema.Properties, "pullNumber")
+ assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner", "repo", "pullNumber"})
// Setup mock PR comments for success case
mockComments := []*github.PullRequestComment{
@@ -819,9 +819,9 @@ func Test_GetPullRequestComments(t *testing.T) {
),
),
requestArgs: map[string]interface{}{
- "owner": "owner",
- "repo": "repo",
- "pull_number": float64(42),
+ "owner": "owner",
+ "repo": "repo",
+ "pullNumber": float64(42),
},
expectError: false,
expectedComments: mockComments,
@@ -838,9 +838,9 @@ func Test_GetPullRequestComments(t *testing.T) {
),
),
requestArgs: map[string]interface{}{
- "owner": "owner",
- "repo": "repo",
- "pull_number": float64(999),
+ "owner": "owner",
+ "repo": "repo",
+ "pullNumber": float64(999),
},
expectError: true,
expectedErrMsg: "failed to get pull request comments",
@@ -896,8 +896,8 @@ func Test_GetPullRequestReviews(t *testing.T) {
assert.NotEmpty(t, tool.Description)
assert.Contains(t, tool.InputSchema.Properties, "owner")
assert.Contains(t, tool.InputSchema.Properties, "repo")
- assert.Contains(t, tool.InputSchema.Properties, "pull_number")
- assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner", "repo", "pull_number"})
+ assert.Contains(t, tool.InputSchema.Properties, "pullNumber")
+ assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner", "repo", "pullNumber"})
// Setup mock PR reviews for success case
mockReviews := []*github.PullRequestReview{
@@ -942,9 +942,9 @@ func Test_GetPullRequestReviews(t *testing.T) {
),
),
requestArgs: map[string]interface{}{
- "owner": "owner",
- "repo": "repo",
- "pull_number": float64(42),
+ "owner": "owner",
+ "repo": "repo",
+ "pullNumber": float64(42),
},
expectError: false,
expectedReviews: mockReviews,
@@ -961,9 +961,9 @@ func Test_GetPullRequestReviews(t *testing.T) {
),
),
requestArgs: map[string]interface{}{
- "owner": "owner",
- "repo": "repo",
- "pull_number": float64(999),
+ "owner": "owner",
+ "repo": "repo",
+ "pullNumber": float64(999),
},
expectError: true,
expectedErrMsg: "failed to get pull request reviews",
@@ -1019,12 +1019,12 @@ func Test_CreatePullRequestReview(t *testing.T) {
assert.NotEmpty(t, tool.Description)
assert.Contains(t, tool.InputSchema.Properties, "owner")
assert.Contains(t, tool.InputSchema.Properties, "repo")
- assert.Contains(t, tool.InputSchema.Properties, "pull_number")
+ assert.Contains(t, tool.InputSchema.Properties, "pullNumber")
assert.Contains(t, tool.InputSchema.Properties, "body")
assert.Contains(t, tool.InputSchema.Properties, "event")
- assert.Contains(t, tool.InputSchema.Properties, "commit_id")
+ assert.Contains(t, tool.InputSchema.Properties, "commitId")
assert.Contains(t, tool.InputSchema.Properties, "comments")
- assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner", "repo", "pull_number", "event"})
+ assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner", "repo", "pullNumber", "event"})
// Setup mock review for success case
mockReview := &github.PullRequestReview{
@@ -1061,17 +1061,17 @@ func Test_CreatePullRequestReview(t *testing.T) {
),
),
requestArgs: map[string]interface{}{
- "owner": "owner",
- "repo": "repo",
- "pull_number": float64(42),
- "body": "Looks good!",
- "event": "APPROVE",
+ "owner": "owner",
+ "repo": "repo",
+ "pullNumber": float64(42),
+ "body": "Looks good!",
+ "event": "APPROVE",
},
expectError: false,
expectedReview: mockReview,
},
{
- name: "successful review creation with commit_id",
+ name: "successful review creation with commitId",
mockedClient: mock.NewMockedHTTPClient(
mock.WithRequestMatchHandler(
mock.PostReposPullsReviewsByOwnerByRepoByPullNumber,
@@ -1085,12 +1085,12 @@ func Test_CreatePullRequestReview(t *testing.T) {
),
),
requestArgs: map[string]interface{}{
- "owner": "owner",
- "repo": "repo",
- "pull_number": float64(42),
- "body": "Looks good!",
- "event": "APPROVE",
- "commit_id": "abcdef123456",
+ "owner": "owner",
+ "repo": "repo",
+ "pullNumber": float64(42),
+ "body": "Looks good!",
+ "event": "APPROVE",
+ "commitId": "abcdef123456",
},
expectError: false,
expectedReview: mockReview,
@@ -1121,11 +1121,11 @@ func Test_CreatePullRequestReview(t *testing.T) {
),
),
requestArgs: map[string]interface{}{
- "owner": "owner",
- "repo": "repo",
- "pull_number": float64(42),
- "body": "Some issues to fix",
- "event": "REQUEST_CHANGES",
+ "owner": "owner",
+ "repo": "repo",
+ "pullNumber": float64(42),
+ "body": "Some issues to fix",
+ "event": "REQUEST_CHANGES",
"comments": []interface{}{
map[string]interface{}{
"path": "file1.go",
@@ -1154,10 +1154,10 @@ func Test_CreatePullRequestReview(t *testing.T) {
),
),
requestArgs: map[string]interface{}{
- "owner": "owner",
- "repo": "repo",
- "pull_number": float64(42),
- "event": "REQUEST_CHANGES",
+ "owner": "owner",
+ "repo": "repo",
+ "pullNumber": float64(42),
+ "event": "REQUEST_CHANGES",
"comments": []interface{}{
map[string]interface{}{
"path": "file1.go",
@@ -1181,11 +1181,11 @@ func Test_CreatePullRequestReview(t *testing.T) {
),
),
requestArgs: map[string]interface{}{
- "owner": "owner",
- "repo": "repo",
- "pull_number": float64(42),
- "body": "Looks good!",
- "event": "APPROVE",
+ "owner": "owner",
+ "repo": "repo",
+ "pullNumber": float64(42),
+ "body": "Looks good!",
+ "event": "APPROVE",
},
expectError: true,
expectedErrMsg: "failed to create pull request review",
diff --git a/pkg/github/repositories.go b/pkg/github/repositories.go
index e4302b889..112eb3740 100644
--- a/pkg/github/repositories.go
+++ b/pkg/github/repositories.go
@@ -32,7 +32,7 @@ func listCommits(client *github.Client, t translations.TranslationHelperFunc) (t
mcp.WithNumber("page",
mcp.Description("Page number"),
),
- mcp.WithNumber("per_page",
+ mcp.WithNumber("perPage",
mcp.Description("Number of records per page"),
),
),
@@ -204,7 +204,7 @@ func createRepository(client *github.Client, t translations.TranslationHelperFun
mcp.WithBoolean("private",
mcp.Description("Whether repo should be private"),
),
- mcp.WithBoolean("auto_init",
+ mcp.WithBoolean("autoInit",
mcp.Description("Initialize with README"),
),
),
@@ -221,7 +221,7 @@ func createRepository(client *github.Client, t translations.TranslationHelperFun
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
- autoInit, err := optionalParam[bool](request, "auto_init")
+ autoInit, err := optionalParam[bool](request, "autoInit")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
diff --git a/pkg/github/repositories_test.go b/pkg/github/repositories_test.go
index 4ae450831..bb6579f85 100644
--- a/pkg/github/repositories_test.go
+++ b/pkg/github/repositories_test.go
@@ -486,7 +486,7 @@ func Test_ListCommits(t *testing.T) {
assert.Contains(t, tool.InputSchema.Properties, "repo")
assert.Contains(t, tool.InputSchema.Properties, "sha")
assert.Contains(t, tool.InputSchema.Properties, "page")
- assert.Contains(t, tool.InputSchema.Properties, "per_page")
+ assert.Contains(t, tool.InputSchema.Properties, "perPage")
assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner", "repo"})
// Setup mock commits for success case
@@ -822,7 +822,7 @@ func Test_CreateRepository(t *testing.T) {
assert.Contains(t, tool.InputSchema.Properties, "name")
assert.Contains(t, tool.InputSchema.Properties, "description")
assert.Contains(t, tool.InputSchema.Properties, "private")
- assert.Contains(t, tool.InputSchema.Properties, "auto_init")
+ assert.Contains(t, tool.InputSchema.Properties, "autoInit")
assert.ElementsMatch(t, tool.InputSchema.Required, []string{"name"})
// Setup mock repository response
@@ -868,7 +868,7 @@ func Test_CreateRepository(t *testing.T) {
"name": "test-repo",
"description": "Test repository",
"private": true,
- "auto_init": true,
+ "autoInit": true,
},
expectError: false,
expectedRepo: mockRepo,
diff --git a/pkg/github/repository_resource.go b/pkg/github/repository_resource.go
index 9fa74c3c6..8efb67e6a 100644
--- a/pkg/github/repository_resource.go
+++ b/pkg/github/repository_resource.go
@@ -56,7 +56,7 @@ func getRepositoryResourceTagContent(client *github.Client, t translations.Trans
// getRepositoryResourcePrContent defines the resource template and handler for getting repository content for a pull request.
func getRepositoryResourcePrContent(client *github.Client, t translations.TranslationHelperFunc) (mcp.ResourceTemplate, server.ResourceTemplateHandlerFunc) {
return mcp.NewResourceTemplate(
- "repo://{owner}/{repo}/refs/pull/{pr_number}/head/contents{/path*}", // Resource template
+ "repo://{owner}/{repo}/refs/pull/{prNumber}/head/contents{/path*}", // Resource template
t("RESOURCE_REPOSITORY_CONTENT_PR_DESCRIPTION", "Repository Content for specific pull request"),
),
repositoryResourceContentsHandler(client)
@@ -101,7 +101,7 @@ func repositoryResourceContentsHandler(client *github.Client) func(ctx context.C
if ok && len(tag) > 0 {
opts.Ref = "refs/tags/" + tag[0]
}
- prNumber, ok := request.Params.Arguments["pr_number"].([]string)
+ prNumber, ok := request.Params.Arguments["prNumber"].([]string)
if ok && len(prNumber) > 0 {
opts.Ref = "refs/pull/" + prNumber[0] + "/head"
}
diff --git a/pkg/github/repository_resource_test.go b/pkg/github/repository_resource_test.go
index 0a5b0b0f0..adad8744d 100644
--- a/pkg/github/repository_resource_test.go
+++ b/pkg/github/repository_resource_test.go
@@ -279,5 +279,5 @@ func Test_getRepositoryResourceTagContent(t *testing.T) {
func Test_getRepositoryResourcePrContent(t *testing.T) {
tmpl, _ := getRepositoryResourcePrContent(nil, translations.NullTranslationHelper)
- require.Equal(t, "repo://{owner}/{repo}/refs/pull/{pr_number}/head/contents{/path*}", tmpl.URITemplate.Raw())
+ require.Equal(t, "repo://{owner}/{repo}/refs/pull/{prNumber}/head/contents{/path*}", tmpl.URITemplate.Raw())
}
diff --git a/pkg/github/search.go b/pkg/github/search.go
index e02c3d0c0..f9a20be14 100644
--- a/pkg/github/search.go
+++ b/pkg/github/search.go
@@ -23,7 +23,7 @@ func searchRepositories(client *github.Client, t translations.TranslationHelperF
mcp.WithNumber("page",
mcp.Description("Page number for pagination"),
),
- mcp.WithNumber("per_page",
+ mcp.WithNumber("perPage",
mcp.Description("Results per page (max 100)"),
),
),
diff --git a/pkg/github/search_test.go b/pkg/github/search_test.go
index 44513b1f5..2485c4c26 100644
--- a/pkg/github/search_test.go
+++ b/pkg/github/search_test.go
@@ -22,7 +22,7 @@ func Test_SearchRepositories(t *testing.T) {
assert.NotEmpty(t, tool.Description)
assert.Contains(t, tool.InputSchema.Properties, "query")
assert.Contains(t, tool.InputSchema.Properties, "page")
- assert.Contains(t, tool.InputSchema.Properties, "per_page")
+ assert.Contains(t, tool.InputSchema.Properties, "perPage")
assert.ElementsMatch(t, tool.InputSchema.Required, []string{"query"})
// Setup mock search results
--- a PPN by Garber Painting Akron. With Image Size Reduction included!Fetched URL: http://github.com/github/github-mcp-server/pull/90.patch
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy