Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit23630b3

Browse files
authored
Add ListProjects tool (#1113)
* Bump go-viper/mapstructure* Update github.com/go-viper/mapstructure/v2 version in licenses* Add tool to list projects* Fix ordering
1 parentd6d60f4 commit23630b3

File tree

6 files changed

+385
-0
lines changed

6 files changed

+385
-0
lines changed

‎README.md‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ The following sets of tools are available (all are on by default):
288288
|`issues`| GitHub Issues related tools|
289289
|`notifications`| GitHub Notifications related tools|
290290
|`orgs`| GitHub Organization related tools|
291+
|`projects`| GitHub Projects related tools|
291292
|`pull_requests`| GitHub Pull Request related tools|
292293
|`repos`| GitHub Repository related tools|
293294
|`secret_protection`| Secret protection related tools, such as GitHub Secret Scanning|
@@ -655,6 +656,20 @@ The following sets of tools are available (all are on by default):
655656

656657
<details>
657658

659+
<summary>Projects</summary>
660+
661+
-**list_projects** - List projects
662+
-`after`: Cursor for items after (forward pagination) (string, optional)
663+
-`before`: Cursor for items before (backwards pagination) (string, optional)
664+
-`owner`: If owner_type == user it is the handle for the GitHub user account. If owner_type == organization it is the name of the organization. The name is not case sensitive. (string, required)
665+
-`owner_type`: Owner type (string, required)
666+
-`per_page`: Number of results per page (max 100, default: 30) (number, optional)
667+
-`query`: Filter projects by a search query (matches title and description) (string, optional)
668+
669+
</details>
670+
671+
<details>
672+
658673
<summary>Pull Requests</summary>
659674

660675
-**add_comment_to_pending_review** - Add review comment to the requester's latest pending pull request review

‎docs/remote-server.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Below is a table of available toolsets for the remote GitHub MCP Server. Each to
2929
| Issues| GitHub Issues related tools|https://api.githubcopilot.com/mcp/x/issues|[Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-issues&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fissues%22%7D)|[read-only](https://api.githubcopilot.com/mcp/x/issues/readonly)|[Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-issues&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fissues%2Freadonly%22%7D)|
3030
| Notifications| GitHub Notifications related tools|https://api.githubcopilot.com/mcp/x/notifications|[Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-notifications&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fnotifications%22%7D)|[read-only](https://api.githubcopilot.com/mcp/x/notifications/readonly)|[Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-notifications&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fnotifications%2Freadonly%22%7D)|
3131
| Organizations| GitHub Organization related tools|https://api.githubcopilot.com/mcp/x/orgs|[Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-orgs&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Forgs%22%7D)|[read-only](https://api.githubcopilot.com/mcp/x/orgs/readonly)|[Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-orgs&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Forgs%2Freadonly%22%7D)|
32+
| Projects| GitHub Projects related tools|https://api.githubcopilot.com/mcp/x/projects|[Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-projects&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fprojects%22%7D)|[read-only](https://api.githubcopilot.com/mcp/x/projects/readonly)|[Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-projects&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fprojects%2Freadonly%22%7D)|
3233
| Pull Requests| GitHub Pull Request related tools|https://api.githubcopilot.com/mcp/x/pull_requests|[Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-pull_requests&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fpull_requests%22%7D)|[read-only](https://api.githubcopilot.com/mcp/x/pull_requests/readonly)|[Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-pull_requests&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fpull_requests%2Freadonly%22%7D)|
3334
| Repositories| GitHub Repository related tools|https://api.githubcopilot.com/mcp/x/repos|[Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-repos&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Frepos%22%7D)|[read-only](https://api.githubcopilot.com/mcp/x/repos/readonly)|[Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-repos&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Frepos%2Freadonly%22%7D)|
3435
| Secret Protection| Secret protection related tools, such as GitHub Secret Scanning|https://api.githubcopilot.com/mcp/x/secret_protection|[Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-secret_protection&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fsecret_protection%22%7D)|[read-only](https://api.githubcopilot.com/mcp/x/secret_protection/readonly)|[Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-secret_protection&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fsecret_protection%2Freadonly%22%7D)|
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"annotations": {
3+
"title":"List projects",
4+
"readOnlyHint":true
5+
},
6+
"description":"List Projects for a user or organization",
7+
"inputSchema": {
8+
"properties": {
9+
"after": {
10+
"description":"Cursor for items after (forward pagination)",
11+
"type":"string"
12+
},
13+
"before": {
14+
"description":"Cursor for items before (backwards pagination)",
15+
"type":"string"
16+
},
17+
"owner": {
18+
"description":"If owner_type == user it is the handle for the GitHub user account. If owner_type == organization it is the name of the organization. The name is not case sensitive.",
19+
"type":"string"
20+
},
21+
"owner_type": {
22+
"description":"Owner type",
23+
"enum": [
24+
"user",
25+
"organization"
26+
],
27+
"type":"string"
28+
},
29+
"per_page": {
30+
"description":"Number of results per page (max 100, default: 30)",
31+
"type":"number"
32+
},
33+
"query": {
34+
"description":"Filter projects by a search query (matches title and description)",
35+
"type":"string"
36+
}
37+
},
38+
"required": [
39+
"owner_type",
40+
"owner"
41+
],
42+
"type":"object"
43+
},
44+
"name":"list_projects"
45+
}

‎pkg/github/projects.go‎

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
package github
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"io"
8+
"net/http"
9+
"net/url"
10+
"reflect"
11+
12+
ghErrors"github.com/github/github-mcp-server/pkg/errors"
13+
"github.com/github/github-mcp-server/pkg/translations"
14+
"github.com/google/go-github/v74/github"
15+
"github.com/google/go-querystring/query"
16+
"github.com/mark3labs/mcp-go/mcp"
17+
"github.com/mark3labs/mcp-go/server"
18+
)
19+
20+
funcListProjects(getClientGetClientFn,t translations.TranslationHelperFunc) (tool mcp.Tool,handler server.ToolHandlerFunc) {
21+
returnmcp.NewTool("list_projects",
22+
mcp.WithDescription(t("TOOL_LIST_PROJECTS_DESCRIPTION","List Projects for a user or organization")),
23+
mcp.WithToolAnnotation(mcp.ToolAnnotation{Title:t("TOOL_LIST_PROJECTS_USER_TITLE","List projects"),ReadOnlyHint:ToBoolPtr(true)}),
24+
mcp.WithString("owner_type",mcp.Required(),mcp.Description("Owner type"),mcp.Enum("user","organization")),
25+
mcp.WithString("owner",mcp.Required(),mcp.Description("If owner_type == user it is the handle for the GitHub user account. If owner_type == organization it is the name of the organization. The name is not case sensitive.")),
26+
mcp.WithString("query",mcp.Description("Filter projects by a search query (matches title and description)")),
27+
mcp.WithString("before",mcp.Description("Cursor for items before (backwards pagination)")),
28+
mcp.WithString("after",mcp.Description("Cursor for items after (forward pagination)")),
29+
mcp.WithNumber("per_page",mcp.Description("Number of results per page (max 100, default: 30)")),
30+
),func(ctx context.Context,req mcp.CallToolRequest) (*mcp.CallToolResult,error) {
31+
owner,err:=RequiredParam[string](req,"owner")
32+
iferr!=nil {
33+
returnmcp.NewToolResultError(err.Error()),nil
34+
}
35+
ownerType,err:=RequiredParam[string](req,"owner_type")
36+
iferr!=nil {
37+
returnmcp.NewToolResultError(err.Error()),nil
38+
}
39+
queryStr,err:=OptionalParam[string](req,"query")
40+
iferr!=nil {
41+
returnmcp.NewToolResultError(err.Error()),nil
42+
}
43+
44+
beforeCursor,err:=OptionalParam[string](req,"before")
45+
iferr!=nil {
46+
returnmcp.NewToolResultError(err.Error()),nil
47+
}
48+
afterCursor,err:=OptionalParam[string](req,"after")
49+
iferr!=nil {
50+
returnmcp.NewToolResultError(err.Error()),nil
51+
}
52+
perPage,err:=OptionalIntParamWithDefault(req,"per_page",30)
53+
iferr!=nil {
54+
returnmcp.NewToolResultError(err.Error()),nil
55+
}
56+
57+
client,err:=getClient(ctx)
58+
iferr!=nil {
59+
returnmcp.NewToolResultError(err.Error()),nil
60+
}
61+
62+
varurlstring
63+
ifownerType=="organization" {
64+
url=fmt.Sprintf("/orgs/%s/projectsV2",owner)
65+
}else {
66+
url=fmt.Sprintf("/users/%s/projectsV2",owner)
67+
}
68+
projects:= []github.ProjectV2{}
69+
70+
opts:=ListProjectsOptions{PerPage:perPage}
71+
ifafterCursor!="" {
72+
opts.After=afterCursor
73+
}
74+
ifbeforeCursor!="" {
75+
opts.Before=beforeCursor
76+
}
77+
ifqueryStr!="" {
78+
opts.Query=queryStr
79+
}
80+
url,err=addOptions(url,opts)
81+
iferr!=nil {
82+
returnnil,fmt.Errorf("failed to add options to request: %w",err)
83+
}
84+
85+
httpRequest,err:=client.NewRequest("GET",url,nil)
86+
iferr!=nil {
87+
returnnil,fmt.Errorf("failed to create request: %w",err)
88+
}
89+
90+
resp,err:=client.Do(ctx,httpRequest,&projects)
91+
iferr!=nil {
92+
returnghErrors.NewGitHubAPIErrorResponse(ctx,
93+
"failed to list projects",
94+
resp,
95+
err,
96+
),nil
97+
}
98+
deferfunc() {_=resp.Body.Close() }()
99+
100+
ifresp.StatusCode!=http.StatusOK {
101+
body,err:=io.ReadAll(resp.Body)
102+
iferr!=nil {
103+
returnnil,fmt.Errorf("failed to read response body: %w",err)
104+
}
105+
returnmcp.NewToolResultError(fmt.Sprintf("failed to list projects: %s",string(body))),nil
106+
}
107+
r,err:=json.Marshal(projects)
108+
iferr!=nil {
109+
returnnil,fmt.Errorf("failed to marshal response: %w",err)
110+
}
111+
112+
returnmcp.NewToolResultText(string(r)),nil
113+
}
114+
}
115+
116+
typeListProjectsOptionsstruct {
117+
// A cursor, as given in the Link header. If specified, the query only searches for events before this cursor.
118+
Beforestring`url:"before,omitempty"`
119+
120+
// A cursor, as given in the Link header. If specified, the query only searches for events after this cursor.
121+
Afterstring`url:"after,omitempty"`
122+
123+
// For paginated result sets, the number of results to include per page.
124+
PerPageint`url:"per_page,omitempty"`
125+
126+
// Query Limit results to projects of the specified type.
127+
Querystring`url:"q,omitempty"`
128+
}
129+
130+
// addOptions adds the parameters in opts as URL query parameters to s. opts
131+
// must be a struct whose fields may contain "url" tags.
132+
funcaddOptions(sstring,optsany) (string,error) {
133+
v:=reflect.ValueOf(opts)
134+
ifv.Kind()==reflect.Ptr&&v.IsNil() {
135+
returns,nil
136+
}
137+
138+
u,err:=url.Parse(s)
139+
iferr!=nil {
140+
returns,err
141+
}
142+
143+
qs,err:=query.Values(opts)
144+
iferr!=nil {
145+
returns,err
146+
}
147+
148+
u.RawQuery=qs.Encode()
149+
returnu.String(),nil
150+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp