github-pro-mcp 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -7
- package/dist-package/index.js +77 -17
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -7,6 +7,10 @@ GitHub Pro MCP gives Claude Code, Cursor, Copilot, opencode and any MCP host a
|
|
|
7
7
|
complete GitHub toolkit: **34 tools** for issues, pull requests, files, projects,
|
|
8
8
|
labels and organizations.
|
|
9
9
|
|
|
10
|
+
Read-only mode is the default. The server registers 19 read tools and keeps the
|
|
11
|
+
15 write tools out of the agent's context. Set
|
|
12
|
+
`GITHUB_MCP_ENABLE_WRITES=true` to load the full set.
|
|
13
|
+
|
|
10
14
|
It runs locally, connects to your host over stdio, and calls the GitHub API
|
|
11
15
|
directly with your own token. There is no intermediary service.
|
|
12
16
|
|
|
@@ -36,6 +40,10 @@ API details.
|
|
|
36
40
|
|
|
37
41
|
- **34 tools across 8 domains.** Issues, pull requests, repositories, projects,
|
|
38
42
|
labels, organizations, file operations and server info.
|
|
43
|
+
- **Read-only by default.** 19 tools, no write surface. Enable writes explicitly.
|
|
44
|
+
- **Built for the common path.** The daily loop is small: read an issue, review a pull
|
|
45
|
+
request, change a file, update a project field. The long tail stays out of the
|
|
46
|
+
agent's context until you need it.
|
|
39
47
|
- **Organization-aware.** `owner_list_repository` lists every repository in an
|
|
40
48
|
organization.
|
|
41
49
|
- **Built for real API conditions.** Retries with backoff, rate-limit handling
|
|
@@ -43,12 +51,18 @@ API details.
|
|
|
43
51
|
nothing to tune.
|
|
44
52
|
- **Guardrails.** Pin the server to one owner or repository with
|
|
45
53
|
`GITHUB_OWNER` / `GITHUB_REPO`, and mismatched calls are rejected.
|
|
54
|
+
- **Guided token setup.** The generator builds a pre-filled fine-grained token
|
|
55
|
+
with a read-only or read-write preset.
|
|
46
56
|
- **Any MCP host.** A standard stdio server. Works with opencode, Claude
|
|
47
57
|
Desktop, Cursor, VS Code and anything else that speaks MCP.
|
|
48
58
|
- **No runtime dependencies.** The npm package ships one bundled file, so
|
|
49
59
|
installing it does not pull a dependency tree.
|
|
50
60
|
- **GitHub Enterprise Server.** Point `GITHUB_HOST` at your GHES API.
|
|
51
61
|
|
|
62
|
+
If your work is mostly Actions, security scanning, notifications, discussions,
|
|
63
|
+
gists, governance or Copilot, use the official GitHub MCP server. GitHub Pro MCP
|
|
64
|
+
is built for the daily issue, pull request, file and project loop.
|
|
65
|
+
|
|
52
66
|
## Installation
|
|
53
67
|
|
|
54
68
|
Requires Node.js 22 or newer for the npm package. The Docker image includes
|
|
@@ -80,6 +94,10 @@ docker pull anantanandgupta/github-pro-mcp
|
|
|
80
94
|
3. Add it to your MCP host and restart the host.
|
|
81
95
|
4. Verify with the `auth_get_current_login` tool.
|
|
82
96
|
|
|
97
|
+
By default the server is read-only and registers 19 tools. To enable issue,
|
|
98
|
+
pull request, file, label and project writes, set
|
|
99
|
+
`GITHUB_MCP_ENABLE_WRITES=true` in the host environment.
|
|
100
|
+
|
|
83
101
|
### Create a token
|
|
84
102
|
|
|
85
103
|
Use a fine-grained personal access token. The generator builds a pre-filled
|
|
@@ -96,6 +114,9 @@ to an organization that requires approval, request it while creating the token.
|
|
|
96
114
|
The full per-tool permission table is at
|
|
97
115
|
https://mcp.anantanandgupta.net/github-pro-mcp/permissions/
|
|
98
116
|
|
|
117
|
+
The read-only preset pairs with the default read-only mode. The read-write
|
|
118
|
+
preset requires `GITHUB_MCP_ENABLE_WRITES=true` in the host environment.
|
|
119
|
+
|
|
99
120
|
### Connect opencode
|
|
100
121
|
|
|
101
122
|
Add to your opencode config (v2 nests servers under `mcp.servers`):
|
|
@@ -108,7 +129,8 @@ Add to your opencode config (v2 nests servers under `mcp.servers`):
|
|
|
108
129
|
"type": "local",
|
|
109
130
|
"command": ["npx", "-y", "github-pro-mcp"],
|
|
110
131
|
"environment": {
|
|
111
|
-
"GITHUB_PERSONAL_ACCESS_TOKEN": "{env:GITHUB_TOKEN}"
|
|
132
|
+
"GITHUB_PERSONAL_ACCESS_TOKEN": "{env:GITHUB_TOKEN}",
|
|
133
|
+
"GITHUB_MCP_ENABLE_WRITES": "true"
|
|
112
134
|
}
|
|
113
135
|
}
|
|
114
136
|
}
|
|
@@ -117,7 +139,8 @@ Add to your opencode config (v2 nests servers under `mcp.servers`):
|
|
|
117
139
|
```
|
|
118
140
|
|
|
119
141
|
`{env:GITHUB_TOKEN}` reads that variable from the environment opencode starts
|
|
120
|
-
in. Use a literal token instead if you prefer.
|
|
142
|
+
in. Use a literal token instead if you prefer. Remove
|
|
143
|
+
`GITHUB_MCP_ENABLE_WRITES` to stay read-only.
|
|
121
144
|
|
|
122
145
|
### Connect Claude Desktop
|
|
123
146
|
|
|
@@ -133,7 +156,8 @@ Edit `claude_desktop_config.json` and restart Claude Desktop:
|
|
|
133
156
|
"command": "npx",
|
|
134
157
|
"args": ["-y", "github-pro-mcp"],
|
|
135
158
|
"env": {
|
|
136
|
-
"GITHUB_PERSONAL_ACCESS_TOKEN": "github_pat_..."
|
|
159
|
+
"GITHUB_PERSONAL_ACCESS_TOKEN": "github_pat_...",
|
|
160
|
+
"GITHUB_MCP_ENABLE_WRITES": "true"
|
|
137
161
|
}
|
|
138
162
|
}
|
|
139
163
|
}
|
|
@@ -156,9 +180,10 @@ https://mcp.anantanandgupta.net/github-pro-mcp/install/
|
|
|
156
180
|
"servers": {
|
|
157
181
|
"github_pro": {
|
|
158
182
|
"type": "local",
|
|
159
|
-
"command": ["docker", "run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", "anantanandgupta/github-pro-mcp"],
|
|
183
|
+
"command": ["docker", "run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", "-e", "GITHUB_MCP_ENABLE_WRITES", "anantanandgupta/github-pro-mcp"],
|
|
160
184
|
"environment": {
|
|
161
|
-
"GITHUB_PERSONAL_ACCESS_TOKEN": "{env:GITHUB_TOKEN}"
|
|
185
|
+
"GITHUB_PERSONAL_ACCESS_TOKEN": "{env:GITHUB_TOKEN}",
|
|
186
|
+
"GITHUB_MCP_ENABLE_WRITES": "true"
|
|
162
187
|
}
|
|
163
188
|
}
|
|
164
189
|
}
|
|
@@ -183,14 +208,16 @@ The same `docker run` command works as the server command in other hosts.
|
|
|
183
208
|
| `GITHUB_HOST` | GitHub Enterprise Server API, for example `https://github.example.com/api/v3` |
|
|
184
209
|
| `GITHUB_OWNER` | Pin the server to a single owner and reject mismatched calls |
|
|
185
210
|
| `GITHUB_REPO` | Pin the server to a single repository and reject mismatched calls |
|
|
211
|
+
| `GITHUB_MCP_ENABLE_WRITES` | Set to `true`, `1`, `yes` or `on` to register the 15 write tools. Default `false` |
|
|
186
212
|
|
|
187
213
|
Retries, rate limiting and logging have sensible defaults. You do not need to
|
|
188
214
|
tune them for normal use.
|
|
189
215
|
|
|
190
216
|
## Tools
|
|
191
217
|
|
|
192
|
-
34 tools across 8 domains.
|
|
193
|
-
|
|
218
|
+
34 tools across 8 domains. Read-only mode registers 19 of them; the other 15
|
|
219
|
+
are write tools. Tool names appear in your host's tool list after the server
|
|
220
|
+
starts.
|
|
194
221
|
|
|
195
222
|
| Domain | Tools | Count |
|
|
196
223
|
|--------|-------|-------|
|
|
@@ -207,6 +234,9 @@ server starts.
|
|
|
207
234
|
Task-based examples and the prompts they respond to are at
|
|
208
235
|
https://mcp.anantanandgupta.net/github-pro-mcp/tools/
|
|
209
236
|
|
|
237
|
+
A measured comparison with the official GitHub MCP server is at
|
|
238
|
+
https://mcp.anantanandgupta.net/github-pro-mcp/compare/
|
|
239
|
+
|
|
210
240
|
## Troubleshooting
|
|
211
241
|
|
|
212
242
|
| Symptom | Likely cause |
|
|
@@ -217,6 +247,7 @@ https://mcp.anantanandgupta.net/github-pro-mcp/tools/
|
|
|
217
247
|
| `429` | Rate limited. The server retries; wait if it persists |
|
|
218
248
|
| No tools appear in the host | The host was not restarted, or the server failed to start |
|
|
219
249
|
| Server exits immediately | `GITHUB_PERSONAL_ACCESS_TOKEN` is not set in the host's environment |
|
|
250
|
+
| Write tool not in the list | `GITHUB_MCP_ENABLE_WRITES` is not set to `true` |
|
|
220
251
|
|
|
221
252
|
## Support
|
|
222
253
|
|
package/dist-package/index.js
CHANGED
|
@@ -26705,6 +26705,18 @@ function formatRepo(r) {
|
|
|
26705
26705
|
};
|
|
26706
26706
|
}
|
|
26707
26707
|
|
|
26708
|
+
// src/utils/annotations.ts
|
|
26709
|
+
var READ_ONLY = {
|
|
26710
|
+
readOnlyHint: true,
|
|
26711
|
+
idempotentHint: true,
|
|
26712
|
+
openWorldHint: true
|
|
26713
|
+
};
|
|
26714
|
+
var WRITE = {
|
|
26715
|
+
readOnlyHint: false,
|
|
26716
|
+
idempotentHint: false,
|
|
26717
|
+
openWorldHint: true
|
|
26718
|
+
};
|
|
26719
|
+
|
|
26708
26720
|
// src/tools/repos.ts
|
|
26709
26721
|
function toBase64(content) {
|
|
26710
26722
|
return Buffer.from(content, "utf-8").toString("base64");
|
|
@@ -26713,6 +26725,7 @@ function registerAuthGetCurrentLogin(server2) {
|
|
|
26713
26725
|
server2.registerTool(
|
|
26714
26726
|
"auth_get_current_login",
|
|
26715
26727
|
{
|
|
26728
|
+
annotations: READ_ONLY,
|
|
26716
26729
|
description: "Get the authenticated GitHub user's profile. Use this to verify your GitHub token and identity.",
|
|
26717
26730
|
inputSchema: object2({})
|
|
26718
26731
|
},
|
|
@@ -26740,6 +26753,7 @@ function registerFileGetContent(server2) {
|
|
|
26740
26753
|
server2.registerTool(
|
|
26741
26754
|
"file_get_content",
|
|
26742
26755
|
{
|
|
26756
|
+
annotations: READ_ONLY,
|
|
26743
26757
|
description: "Get the contents of a file from a GitHub repository. Returns the decoded file content as text.",
|
|
26744
26758
|
inputSchema: OwnerRepoSchema.extend({
|
|
26745
26759
|
path: string2().min(1).describe("File path within the repository (e.g., 'README.md' or 'src/index.ts')"),
|
|
@@ -26776,6 +26790,7 @@ function registerProfileGet(server2) {
|
|
|
26776
26790
|
server2.registerTool(
|
|
26777
26791
|
"profile_get",
|
|
26778
26792
|
{
|
|
26793
|
+
annotations: READ_ONLY,
|
|
26779
26794
|
description: "Get profile info for any GitHub owner (user or organization). Useful for checking if an owner is an organization before calling organization-only tools like owner_list_issue_field.",
|
|
26780
26795
|
inputSchema: object2({
|
|
26781
26796
|
owner: string2().min(1).describe("Repository owner (user or organization)")
|
|
@@ -26808,6 +26823,7 @@ function registerOwnerListRepository(server2) {
|
|
|
26808
26823
|
server2.registerTool(
|
|
26809
26824
|
"owner_list_repository",
|
|
26810
26825
|
{
|
|
26826
|
+
annotations: READ_ONLY,
|
|
26811
26827
|
description: "List all repositories for a given owner. For an organization, returns every repository in the organization. For a user, returns the repositories the token can access. The 'type' filter applies to user owners only. Unlike search_repositories, results are unranked.",
|
|
26812
26828
|
inputSchema: object2({
|
|
26813
26829
|
owner: string2().min(1).describe("Repository owner (user or organization)"),
|
|
@@ -26844,6 +26860,7 @@ function registerFileCreateUpdate(server2) {
|
|
|
26844
26860
|
server2.registerTool(
|
|
26845
26861
|
"file_create_update",
|
|
26846
26862
|
{
|
|
26863
|
+
annotations: WRITE,
|
|
26847
26864
|
description: "Create or update a single file in a GitHub repository. Content is base64-encoded automatically. Provide sha when updating an existing file (obtain sha from the previous file_create_update response).",
|
|
26848
26865
|
inputSchema: OwnerRepoSchema.extend({
|
|
26849
26866
|
path: string2().min(1).describe("Path where to create/update the file"),
|
|
@@ -26890,6 +26907,7 @@ function registerCodeSearch(server2) {
|
|
|
26890
26907
|
server2.registerTool(
|
|
26891
26908
|
"code_search",
|
|
26892
26909
|
{
|
|
26910
|
+
annotations: READ_ONLY,
|
|
26893
26911
|
description: "Search for code across GitHub repositories. Supports GitHub search qualifiers like 'repo:...', 'language:...', 'path:...'.",
|
|
26894
26912
|
inputSchema: object2({
|
|
26895
26913
|
query: string2().min(1).max(1e3).describe("Search query with GitHub qualifiers, e.g., 'function repo:owner/repo language:python'"),
|
|
@@ -26922,6 +26940,7 @@ function registerFileDelete(server2) {
|
|
|
26922
26940
|
server2.registerTool(
|
|
26923
26941
|
"file_delete",
|
|
26924
26942
|
{
|
|
26943
|
+
annotations: WRITE,
|
|
26925
26944
|
description: "Delete a file from a GitHub repository. Requires the SHA of the file (obtain from file_get_content).",
|
|
26926
26945
|
inputSchema: OwnerRepoSchema.extend({
|
|
26927
26946
|
path: string2().min(1).describe("Path to the file to delete"),
|
|
@@ -26963,6 +26982,7 @@ function registerRepositorySearch(server2) {
|
|
|
26963
26982
|
server2.registerTool(
|
|
26964
26983
|
"repository_search",
|
|
26965
26984
|
{
|
|
26985
|
+
annotations: READ_ONLY,
|
|
26966
26986
|
description: "Search for GitHub repositories by query. Supports GitHub search qualifiers like 'org:...', 'language:...', 'stars:>100'.",
|
|
26967
26987
|
inputSchema: object2({
|
|
26968
26988
|
query: string2().min(1).max(1e3).describe("Search query with GitHub qualifiers, e.g., 'org:microsoft language:python'"),
|
|
@@ -26995,6 +27015,7 @@ function registerOrganizationSearch(server2) {
|
|
|
26995
27015
|
server2.registerTool(
|
|
26996
27016
|
"organization_search",
|
|
26997
27017
|
{
|
|
27018
|
+
annotations: READ_ONLY,
|
|
26998
27019
|
description: "Search for organizations on GitHub by query. Supports qualifiers like 'location:...', 'repos:>...'.",
|
|
26999
27020
|
inputSchema: object2({
|
|
27000
27021
|
query: string2().min(1).max(1e3).describe("Search query, e.g., 'microsoft' or 'location:seattle repos:>5'"),
|
|
@@ -27029,6 +27050,7 @@ function registerOwnerListIssueType(server2) {
|
|
|
27029
27050
|
server2.registerTool(
|
|
27030
27051
|
"owner_list_issue_type",
|
|
27031
27052
|
{
|
|
27053
|
+
annotations: READ_ONLY,
|
|
27032
27054
|
description: "List issue types for an organization (e.g., Bug, Feature, Enhancement). Owner must be an organization.",
|
|
27033
27055
|
inputSchema: object2({
|
|
27034
27056
|
owner: string2().min(1).describe("Organization owner")
|
|
@@ -27053,6 +27075,7 @@ function registerOwnerListOrganization(server2) {
|
|
|
27053
27075
|
server2.registerTool(
|
|
27054
27076
|
"owner_list_organization",
|
|
27055
27077
|
{
|
|
27078
|
+
annotations: READ_ONLY,
|
|
27056
27079
|
description: "List all organizations that a user account belongs to. Provide a username, not an organization name.",
|
|
27057
27080
|
inputSchema: object2({
|
|
27058
27081
|
owner: string2().min(1).describe("Username to list organizations for")
|
|
@@ -27086,6 +27109,7 @@ function registerPullRequestRead(server2) {
|
|
|
27086
27109
|
server2.registerTool(
|
|
27087
27110
|
"pull_request_read",
|
|
27088
27111
|
{
|
|
27112
|
+
annotations: READ_ONLY,
|
|
27089
27113
|
description: "Get details of a pull request. Optionally include commits and reviews. Each include_* flag makes additional API calls.",
|
|
27090
27114
|
inputSchema: OwnerRepoSchema.extend({
|
|
27091
27115
|
pull_number: PullNumberSchema,
|
|
@@ -27148,6 +27172,7 @@ function registerPullRequestCreate(server2) {
|
|
|
27148
27172
|
server2.registerTool(
|
|
27149
27173
|
"pull_request_create",
|
|
27150
27174
|
{
|
|
27175
|
+
annotations: WRITE,
|
|
27151
27176
|
description: "Create a new pull request in a GitHub repository.",
|
|
27152
27177
|
inputSchema: OwnerRepoSchema.extend({
|
|
27153
27178
|
title: string2().min(1).describe("Pull request title"),
|
|
@@ -27183,6 +27208,7 @@ function registerPullRequestMerge(server2) {
|
|
|
27183
27208
|
server2.registerTool(
|
|
27184
27209
|
"pull_request_merge",
|
|
27185
27210
|
{
|
|
27211
|
+
annotations: WRITE,
|
|
27186
27212
|
description: "Merge a pull request in a GitHub repository.",
|
|
27187
27213
|
inputSchema: OwnerRepoSchema.extend({
|
|
27188
27214
|
pull_number: PullNumberSchema,
|
|
@@ -27216,6 +27242,7 @@ function registerIssueRead(server2) {
|
|
|
27216
27242
|
server2.registerTool(
|
|
27217
27243
|
"issue_read",
|
|
27218
27244
|
{
|
|
27245
|
+
annotations: READ_ONLY,
|
|
27219
27246
|
description: "Get details of a specific issue. Optionally include comments, labels, field values, and sub-issues. Each include_* flag makes additional API calls.",
|
|
27220
27247
|
inputSchema: OwnerRepoSchema.extend({
|
|
27221
27248
|
issue_number: IssueNumberSchema,
|
|
@@ -27306,6 +27333,7 @@ function registerIssueList(server2) {
|
|
|
27306
27333
|
server2.registerTool(
|
|
27307
27334
|
"issue_list",
|
|
27308
27335
|
{
|
|
27336
|
+
annotations: READ_ONLY,
|
|
27309
27337
|
description: "List issues in a repository. Optionally include org-level field values (Priority, Effort) and/or project board field values (Status, Application). Supports field-based filtering with filter_fields (AND logic).",
|
|
27310
27338
|
inputSchema: OwnerRepoSchema.extend({
|
|
27311
27339
|
state: _enum(["open", "closed", "all"]).optional().describe("Filter by issue state"),
|
|
@@ -27506,6 +27534,7 @@ function registerIssueSearch(server2) {
|
|
|
27506
27534
|
server2.registerTool(
|
|
27507
27535
|
"issue_search",
|
|
27508
27536
|
{
|
|
27537
|
+
annotations: READ_ONLY,
|
|
27509
27538
|
description: "Search for issues in GitHub repositories using GitHub's search syntax.",
|
|
27510
27539
|
inputSchema: object2({
|
|
27511
27540
|
query: string2().min(1).max(1e3).describe("Search query using GitHub issues search syntax, e.g., 'label:bug repo:owner/repo'"),
|
|
@@ -27545,6 +27574,7 @@ function registerIssueAddComment(server2) {
|
|
|
27545
27574
|
server2.registerTool(
|
|
27546
27575
|
"issue_add_comment",
|
|
27547
27576
|
{
|
|
27577
|
+
annotations: WRITE,
|
|
27548
27578
|
description: "Add a comment to an existing issue in a GitHub repository.",
|
|
27549
27579
|
inputSchema: OwnerRepoSchema.extend({
|
|
27550
27580
|
issue_number: IssueNumberSchema,
|
|
@@ -27574,6 +27604,7 @@ function registerSubIssueWrite(server2) {
|
|
|
27574
27604
|
server2.registerTool(
|
|
27575
27605
|
"sub_issue_write",
|
|
27576
27606
|
{
|
|
27607
|
+
annotations: WRITE,
|
|
27577
27608
|
description: "Add or remove a sub-issue from a parent issue in a GitHub repository. Method 'add' adds sub_issue_number as a sub-issue of issue_number. Method 'remove' removes the sub-issue relationship.",
|
|
27578
27609
|
inputSchema: OwnerRepoSchema.extend({
|
|
27579
27610
|
method: _enum(["add", "remove"]).describe("Operation: add or remove a sub-issue"),
|
|
@@ -27645,6 +27676,7 @@ function registerIssueCreate(server2) {
|
|
|
27645
27676
|
server2.registerTool(
|
|
27646
27677
|
"issue_create",
|
|
27647
27678
|
{
|
|
27679
|
+
annotations: WRITE,
|
|
27648
27680
|
description: "Create a new issue in a GitHub repository.",
|
|
27649
27681
|
inputSchema: OwnerRepoSchema.extend({
|
|
27650
27682
|
title: string2().min(1).describe("Issue title"),
|
|
@@ -27678,6 +27710,7 @@ function registerIssueClose(server2) {
|
|
|
27678
27710
|
server2.registerTool(
|
|
27679
27711
|
"issue_close",
|
|
27680
27712
|
{
|
|
27713
|
+
annotations: WRITE,
|
|
27681
27714
|
description: "Close an issue in a GitHub repository.",
|
|
27682
27715
|
inputSchema: OwnerRepoSchema.extend({
|
|
27683
27716
|
issue_number: IssueNumberSchema,
|
|
@@ -27719,6 +27752,7 @@ function registerIssueReopen(server2) {
|
|
|
27719
27752
|
server2.registerTool(
|
|
27720
27753
|
"issue_reopen",
|
|
27721
27754
|
{
|
|
27755
|
+
annotations: WRITE,
|
|
27722
27756
|
description: "Reopen a closed issue in a GitHub repository.",
|
|
27723
27757
|
inputSchema: OwnerRepoSchema.extend({
|
|
27724
27758
|
issue_number: IssueNumberSchema
|
|
@@ -27746,6 +27780,7 @@ function registerIssueUpdate(server2) {
|
|
|
27746
27780
|
server2.registerTool(
|
|
27747
27781
|
"issue_update",
|
|
27748
27782
|
{
|
|
27783
|
+
annotations: WRITE,
|
|
27749
27784
|
description: "Update an issue's title, body, or state in a GitHub repository.",
|
|
27750
27785
|
inputSchema: OwnerRepoSchema.extend({
|
|
27751
27786
|
issue_number: IssueNumberSchema,
|
|
@@ -27786,6 +27821,7 @@ function registerIssueAddLabel(server2) {
|
|
|
27786
27821
|
server2.registerTool(
|
|
27787
27822
|
"issue_add_label",
|
|
27788
27823
|
{
|
|
27824
|
+
annotations: WRITE,
|
|
27789
27825
|
description: "Add labels to an issue in a GitHub repository.",
|
|
27790
27826
|
inputSchema: OwnerRepoSchema.extend({
|
|
27791
27827
|
issue_number: IssueNumberSchema,
|
|
@@ -27814,6 +27850,7 @@ function registerIssueRemoveLabel(server2) {
|
|
|
27814
27850
|
server2.registerTool(
|
|
27815
27851
|
"issue_remove_label",
|
|
27816
27852
|
{
|
|
27853
|
+
annotations: WRITE,
|
|
27817
27854
|
description: "Remove labels from an issue in a GitHub repository.",
|
|
27818
27855
|
inputSchema: OwnerRepoSchema.extend({
|
|
27819
27856
|
issue_number: IssueNumberSchema,
|
|
@@ -27855,6 +27892,7 @@ function registerOwnerListIssueField(server2) {
|
|
|
27855
27892
|
server2.registerTool(
|
|
27856
27893
|
"owner_list_issue_field",
|
|
27857
27894
|
{
|
|
27895
|
+
annotations: READ_ONLY,
|
|
27858
27896
|
description: "List all issue field definitions for an organization (e.g., Priority, Effort, Start date, Target date). Owner must be an organization.",
|
|
27859
27897
|
inputSchema: object2({
|
|
27860
27898
|
owner: string2().min(1).describe("Organization owner")
|
|
@@ -27879,6 +27917,7 @@ function registerIssueGetFieldValue(server2) {
|
|
|
27879
27917
|
server2.registerTool(
|
|
27880
27918
|
"issue_get_field_value",
|
|
27881
27919
|
{
|
|
27920
|
+
annotations: READ_ONLY,
|
|
27882
27921
|
description: "Get the current field values (Priority, Effort, dates, etc.) assigned to an issue.",
|
|
27883
27922
|
inputSchema: OwnerRepoSchema.extend({
|
|
27884
27923
|
issue_number: IssueNumberSchema
|
|
@@ -27902,6 +27941,7 @@ function registerIssueSetFieldValue(server2) {
|
|
|
27902
27941
|
server2.registerTool(
|
|
27903
27942
|
"issue_set_field_value",
|
|
27904
27943
|
{
|
|
27944
|
+
annotations: WRITE,
|
|
27905
27945
|
description: "Set field values (Priority, Effort, dates, etc.) on an issue. Accepts either field_id (numeric ID) or field_name (e.g. 'Priority'). For single-select fields, value can be the option name (e.g. 'Medium') or option ID. For dates, use ISO 8601 (e.g. '2026-06-15'). Pass null to clear a field.",
|
|
27906
27946
|
inputSchema: OwnerRepoSchema.extend({
|
|
27907
27947
|
issue_number: IssueNumberSchema,
|
|
@@ -27969,6 +28009,7 @@ function registerLabelList(server2) {
|
|
|
27969
28009
|
server2.registerTool(
|
|
27970
28010
|
"label_list",
|
|
27971
28011
|
{
|
|
28012
|
+
annotations: READ_ONLY,
|
|
27972
28013
|
description: "List labels in a GitHub repository.",
|
|
27973
28014
|
inputSchema: OwnerRepoSchema.extend({
|
|
27974
28015
|
page: PaginationSchema.shape.page,
|
|
@@ -27999,6 +28040,7 @@ function registerLabelWrite(server2) {
|
|
|
27999
28040
|
server2.registerTool(
|
|
28000
28041
|
"label_write",
|
|
28001
28042
|
{
|
|
28043
|
+
annotations: WRITE,
|
|
28002
28044
|
description: "Create, update, or delete a label in a GitHub repository. Method 'create' requires name and color. Method 'update' requires name (current name) and optional color/description/new_name. Method 'delete' requires name only.",
|
|
28003
28045
|
inputSchema: OwnerRepoSchema.extend({
|
|
28004
28046
|
method: _enum(["create", "update", "delete"]).describe("Action to perform on the label"),
|
|
@@ -28055,6 +28097,7 @@ function registerOwnerListProject(server2) {
|
|
|
28055
28097
|
server2.registerTool(
|
|
28056
28098
|
"owner_list_project",
|
|
28057
28099
|
{
|
|
28100
|
+
annotations: READ_ONLY,
|
|
28058
28101
|
description: "List GitHub Projects (v2) for an owner. Works for both organizations and individual users.",
|
|
28059
28102
|
inputSchema: object2({
|
|
28060
28103
|
owner: string2().min(1).describe("Organization or user login"),
|
|
@@ -28157,6 +28200,7 @@ function registerProjectsGet(server2) {
|
|
|
28157
28200
|
server2.registerTool(
|
|
28158
28201
|
"projects_get",
|
|
28159
28202
|
{
|
|
28203
|
+
annotations: READ_ONLY,
|
|
28160
28204
|
description: "Get a single GitHub Project (v2) by its GraphQL node ID with optional fields, items, and status updates. Each include_* flag makes additional API calls.",
|
|
28161
28205
|
inputSchema: object2({
|
|
28162
28206
|
project_id: string2().min(1).describe("GraphQL node ID of the project (obtain from owner_list_project)"),
|
|
@@ -28306,6 +28350,7 @@ function registerProjectsWrite(server2) {
|
|
|
28306
28350
|
server2.registerTool(
|
|
28307
28351
|
"projects_write",
|
|
28308
28352
|
{
|
|
28353
|
+
annotations: WRITE,
|
|
28309
28354
|
description: "Manage items in a GitHub Project (v2): add, update field values, delete items, or create status updates. Methods: add_item (requires content_id), update_item (requires item_id + field_values; field_values each need field_id, value, and value_type), delete_item (requires item_id), create_status_update (requires body; optional status/start_date/target_date). Note: update_item sends field values one at a time \u2014 if one fails, earlier updates are already committed. Check partial: true in the response.",
|
|
28310
28355
|
inputSchema: object2({
|
|
28311
28356
|
project_id: string2().min(1).describe("GraphQL node ID of the project"),
|
|
@@ -28500,6 +28545,7 @@ function registerServerInfo(server2, meta) {
|
|
|
28500
28545
|
server2.registerTool(
|
|
28501
28546
|
"server_info",
|
|
28502
28547
|
{
|
|
28548
|
+
annotations: READ_ONLY,
|
|
28503
28549
|
description: "Get information about this MCP server, including version, support links, and runtime configuration.",
|
|
28504
28550
|
inputSchema: object2({})
|
|
28505
28551
|
},
|
|
@@ -28507,6 +28553,8 @@ function registerServerInfo(server2, meta) {
|
|
|
28507
28553
|
const runtime = {
|
|
28508
28554
|
node_version: process.version,
|
|
28509
28555
|
platform: process.platform,
|
|
28556
|
+
read_only: !meta.writesEnabled,
|
|
28557
|
+
writes_enabled: meta.writesEnabled,
|
|
28510
28558
|
pinned_owner: process.env.GITHUB_OWNER ?? null,
|
|
28511
28559
|
pinned_repo: process.env.GITHUB_REPO ?? null,
|
|
28512
28560
|
log_level: process.env.GITHUB_LOG_LEVEL ?? "error",
|
|
@@ -28541,6 +28589,12 @@ function registerServerInfo(server2, meta) {
|
|
|
28541
28589
|
// src/index.ts
|
|
28542
28590
|
var require2 = createRequire(import.meta.url);
|
|
28543
28591
|
var pkg = require2("../package.json");
|
|
28592
|
+
function readBool(name, fallback) {
|
|
28593
|
+
const raw = process.env[name];
|
|
28594
|
+
if (raw === void 0) return fallback;
|
|
28595
|
+
return ["1", "true", "yes", "on"].includes(raw.toLowerCase());
|
|
28596
|
+
}
|
|
28597
|
+
var writesEnabled = readBool("GITHUB_MCP_ENABLE_WRITES", false);
|
|
28544
28598
|
var server = new McpServer(
|
|
28545
28599
|
{ name: pkg.name, version: pkg.version },
|
|
28546
28600
|
{ capabilities: { tools: {} } }
|
|
@@ -28554,46 +28608,52 @@ var serverMeta = {
|
|
|
28554
28608
|
repository: pkg.repository?.url ?? "",
|
|
28555
28609
|
homepage: pkg.homepage ?? "",
|
|
28556
28610
|
bug_tracker: pkg.bugs?.url ?? "",
|
|
28557
|
-
bin: pkg.bin ?? {}
|
|
28611
|
+
bin: pkg.bin ?? {},
|
|
28612
|
+
writesEnabled
|
|
28558
28613
|
};
|
|
28559
28614
|
registerAuthGetCurrentLogin(server);
|
|
28560
28615
|
registerFileGetContent(server);
|
|
28561
|
-
registerFileDelete(server);
|
|
28562
28616
|
registerProfileGet(server);
|
|
28563
28617
|
registerOwnerListRepository(server);
|
|
28564
|
-
registerFileCreateUpdate(server);
|
|
28565
28618
|
registerCodeSearch(server);
|
|
28566
28619
|
registerRepositorySearch(server);
|
|
28567
28620
|
registerOrganizationSearch(server);
|
|
28568
28621
|
registerOwnerListIssueType(server);
|
|
28569
28622
|
registerOwnerListOrganization(server);
|
|
28570
28623
|
registerPullRequestRead(server);
|
|
28571
|
-
registerPullRequestCreate(server);
|
|
28572
|
-
registerPullRequestMerge(server);
|
|
28573
28624
|
registerIssueRead(server);
|
|
28574
28625
|
registerIssueList(server);
|
|
28575
28626
|
registerIssueSearch(server);
|
|
28576
|
-
registerIssueAddComment(server);
|
|
28577
|
-
registerSubIssueWrite(server);
|
|
28578
|
-
registerIssueCreate(server);
|
|
28579
|
-
registerIssueClose(server);
|
|
28580
|
-
registerIssueReopen(server);
|
|
28581
|
-
registerIssueUpdate(server);
|
|
28582
|
-
registerIssueAddLabel(server);
|
|
28583
|
-
registerIssueRemoveLabel(server);
|
|
28584
28627
|
registerOwnerListIssueField(server);
|
|
28585
28628
|
registerIssueGetFieldValue(server);
|
|
28586
|
-
registerIssueSetFieldValue(server);
|
|
28587
28629
|
registerLabelList(server);
|
|
28588
|
-
registerLabelWrite(server);
|
|
28589
28630
|
registerOwnerListProject(server);
|
|
28590
28631
|
registerProjectsGet(server);
|
|
28591
|
-
|
|
28632
|
+
if (writesEnabled) {
|
|
28633
|
+
registerFileCreateUpdate(server);
|
|
28634
|
+
registerFileDelete(server);
|
|
28635
|
+
registerPullRequestCreate(server);
|
|
28636
|
+
registerPullRequestMerge(server);
|
|
28637
|
+
registerIssueAddComment(server);
|
|
28638
|
+
registerSubIssueWrite(server);
|
|
28639
|
+
registerIssueCreate(server);
|
|
28640
|
+
registerIssueClose(server);
|
|
28641
|
+
registerIssueReopen(server);
|
|
28642
|
+
registerIssueUpdate(server);
|
|
28643
|
+
registerIssueAddLabel(server);
|
|
28644
|
+
registerIssueRemoveLabel(server);
|
|
28645
|
+
registerIssueSetFieldValue(server);
|
|
28646
|
+
registerLabelWrite(server);
|
|
28647
|
+
registerProjectsWrite(server);
|
|
28648
|
+
}
|
|
28592
28649
|
registerServerInfo(server, serverMeta);
|
|
28593
28650
|
async function main() {
|
|
28594
28651
|
const transport = new StdioServerTransport();
|
|
28595
28652
|
await server.connect(transport);
|
|
28596
|
-
|
|
28653
|
+
const toolCount = Object.keys(server._registeredTools ?? {}).length;
|
|
28654
|
+
console.error(
|
|
28655
|
+
`github-pro-mcp running on stdio (${writesEnabled ? "writes enabled" : "read-only"}, ${toolCount} tools)`
|
|
28656
|
+
);
|
|
28597
28657
|
}
|
|
28598
28658
|
main().catch((err) => {
|
|
28599
28659
|
console.error("Fatal error:", err);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "github-pro-mcp",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "MCP server providing GitHub API access with hybrid REST + GraphQL support",
|
|
5
5
|
"main": "dist-package/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -29,7 +29,8 @@
|
|
|
29
29
|
"test:consistency": "node --test --test-global-setup='src/__tests__/setup.mjs' 'src/__tests__/consistency.test.mjs'",
|
|
30
30
|
"test:docker": "node --test 'test/docker/**/*.test.mjs'",
|
|
31
31
|
"test:npm": "node --test 'test/integration/**/*.test.mjs'",
|
|
32
|
-
"test:all": "npm test && npm run test:docker && npm run test:npm",
|
|
32
|
+
"test:all": "npm test && npm run test:readonly && npm run test:docker && npm run test:npm",
|
|
33
|
+
"test:readonly": "node --test 'test/readonly.test.mjs'",
|
|
33
34
|
"test:coverage": "node --experimental-test-coverage --test --test-global-setup='src/__tests__/setup.mjs' 'src/__tests__/**/*.test.mjs'",
|
|
34
35
|
"test:inspector": "npx @modelcontextprotocol/inspector node dist/index.js",
|
|
35
36
|
"prepack": "npm run build && npm run bundle",
|
|
@@ -55,7 +56,7 @@
|
|
|
55
56
|
"bugs": {
|
|
56
57
|
"url": "https://github.com/anantanandgupta/mcp-servers/issues"
|
|
57
58
|
},
|
|
58
|
-
"homepage": "https://
|
|
59
|
+
"homepage": "https://mcp.anantanandgupta.net/github-pro-mcp/",
|
|
59
60
|
"type": "module",
|
|
60
61
|
"engines": {
|
|
61
62
|
"node": ">=22.0.0"
|