Skip to content

Commit 4ed0310

Browse files
Complete OAuth scope implementation for all tools
- Updated all remaining tools with OAuth scope information - Added scope documentation generation to generate-docs command - Documentation now shows Required and Accepted OAuth scopes for each tool - All 100+ tools now have scope information defined - Tests pass, linter passes, documentation generated successfully Co-authored-by: SamMorrowDrums <[email protected]>
1 parent 099ad57 commit 4ed0310

File tree

8 files changed

+361
-86
lines changed

8 files changed

+361
-86
lines changed

README.md

Lines changed: 192 additions & 0 deletions
Large diffs are not rendered by default.

cmd/github-mcp-server/generate_docs.go

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"github.com/github/github-mcp-server/pkg/inventory"
1212
"github.com/github/github-mcp-server/pkg/translations"
1313
"github.com/google/jsonschema-go/jsonschema"
14-
"github.com/modelcontextprotocol/go-sdk/mcp"
1514
"github.com/spf13/cobra"
1615
)
1716

@@ -190,7 +189,7 @@ func generateToolsDoc(r *inventory.Inventory) string {
190189
currentToolsetID = tool.Toolset.ID
191190
currentToolsetIcon = tool.Toolset.Icon
192191
}
193-
writeToolDoc(&toolBuf, tool.Tool)
192+
writeToolDoc(&toolBuf, tool)
194193
toolBuf.WriteString("\n\n")
195194
}
196195

@@ -224,16 +223,26 @@ func formatToolsetName(name string) string {
224223
}
225224
}
226225

227-
func writeToolDoc(buf *strings.Builder, tool mcp.Tool) {
226+
func writeToolDoc(buf *strings.Builder, tool inventory.ServerTool) {
228227
// Tool name (no icon - section header already has the toolset icon)
229-
fmt.Fprintf(buf, "- **%s** - %s\n", tool.Name, tool.Annotations.Title)
228+
fmt.Fprintf(buf, "- **%s** - %s\n", tool.Tool.Name, tool.Tool.Annotations.Title)
229+
230+
// OAuth scopes if present
231+
if len(tool.RequiredScopes) > 0 || len(tool.AcceptedScopes) > 0 {
232+
if len(tool.RequiredScopes) > 0 {
233+
fmt.Fprintf(buf, " - **Required OAuth Scopes**: `%s`\n", strings.Join(tool.RequiredScopes, "`, `"))
234+
}
235+
if len(tool.AcceptedScopes) > 0 {
236+
fmt.Fprintf(buf, " - **Accepted OAuth Scopes**: `%s`\n", strings.Join(tool.AcceptedScopes, "`, `"))
237+
}
238+
}
230239

231240
// Parameters
232-
if tool.InputSchema == nil {
241+
if tool.Tool.InputSchema == nil {
233242
buf.WriteString(" - No parameters required")
234243
return
235244
}
236-
schema, ok := tool.InputSchema.(*jsonschema.Schema)
245+
schema, ok := tool.Tool.InputSchema.(*jsonschema.Schema)
237246
if !ok || schema == nil {
238247
buf.WriteString(" - No parameters required")
239248
return

pkg/github/actions.go

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ const (
5151

5252
// ListWorkflows creates a tool to list workflows in a repository
5353
func ListWorkflows(t translations.TranslationHelperFunc) inventory.ServerTool {
54-
tool := NewTool(
54+
tool := NewToolWithScopes(
5555
ToolsetMetadataActions,
5656
mcp.Tool{
5757
Name: "list_workflows",
@@ -75,6 +75,8 @@ func ListWorkflows(t translations.TranslationHelperFunc) inventory.ServerTool {
7575
Required: []string{"owner", "repo"},
7676
}),
7777
},
78+
scopes.ToStringSlice(scopes.Repo),
79+
scopes.ToStringSlice(scopes.Repo),
7880
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
7981
client, err := deps.GetClient(ctx)
8082
if err != nil {
@@ -122,7 +124,7 @@ func ListWorkflows(t translations.TranslationHelperFunc) inventory.ServerTool {
122124

123125
// ListWorkflowRuns creates a tool to list workflow runs for a specific workflow
124126
func ListWorkflowRuns(t translations.TranslationHelperFunc) inventory.ServerTool {
125-
tool := NewTool(
127+
tool := NewToolWithScopes(
126128
ToolsetMetadataActions,
127129
mcp.Tool{
128130
Name: "list_workflow_runs",
@@ -201,6 +203,8 @@ func ListWorkflowRuns(t translations.TranslationHelperFunc) inventory.ServerTool
201203
Required: []string{"owner", "repo", "workflow_id"},
202204
}),
203205
},
206+
scopes.ToStringSlice(scopes.Repo),
207+
scopes.ToStringSlice(scopes.Repo),
204208
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
205209
client, err := deps.GetClient(ctx)
206210
if err != nil {
@@ -276,7 +280,7 @@ func ListWorkflowRuns(t translations.TranslationHelperFunc) inventory.ServerTool
276280

277281
// RunWorkflow creates a tool to run an Actions workflow
278282
func RunWorkflow(t translations.TranslationHelperFunc) inventory.ServerTool {
279-
tool := NewTool(
283+
tool := NewToolWithScopes(
280284
ToolsetMetadataActions,
281285
mcp.Tool{
282286
Name: "run_workflow",
@@ -312,6 +316,8 @@ func RunWorkflow(t translations.TranslationHelperFunc) inventory.ServerTool {
312316
Required: []string{"owner", "repo", "workflow_id", "ref"},
313317
},
314318
},
319+
scopes.ToStringSlice(scopes.Repo),
320+
scopes.ToStringSlice(scopes.Repo),
315321
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
316322
client, err := deps.GetClient(ctx)
317323
if err != nil {
@@ -388,7 +394,7 @@ func RunWorkflow(t translations.TranslationHelperFunc) inventory.ServerTool {
388394

389395
// GetWorkflowRun creates a tool to get details of a specific workflow run
390396
func GetWorkflowRun(t translations.TranslationHelperFunc) inventory.ServerTool {
391-
tool := NewTool(
397+
tool := NewToolWithScopes(
392398
ToolsetMetadataActions,
393399
mcp.Tool{
394400
Name: "get_workflow_run",
@@ -416,6 +422,8 @@ func GetWorkflowRun(t translations.TranslationHelperFunc) inventory.ServerTool {
416422
Required: []string{"owner", "repo", "run_id"},
417423
},
418424
},
425+
scopes.ToStringSlice(scopes.Repo),
426+
scopes.ToStringSlice(scopes.Repo),
419427
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
420428
client, err := deps.GetClient(ctx)
421429
if err != nil {
@@ -456,7 +464,7 @@ func GetWorkflowRun(t translations.TranslationHelperFunc) inventory.ServerTool {
456464

457465
// GetWorkflowRunLogs creates a tool to download logs for a specific workflow run
458466
func GetWorkflowRunLogs(t translations.TranslationHelperFunc) inventory.ServerTool {
459-
tool := NewTool(
467+
tool := NewToolWithScopes(
460468
ToolsetMetadataActions,
461469
mcp.Tool{
462470
Name: "get_workflow_run_logs",
@@ -484,6 +492,8 @@ func GetWorkflowRunLogs(t translations.TranslationHelperFunc) inventory.ServerTo
484492
Required: []string{"owner", "repo", "run_id"},
485493
},
486494
},
495+
scopes.ToStringSlice(scopes.Repo),
496+
scopes.ToStringSlice(scopes.Repo),
487497
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
488498
client, err := deps.GetClient(ctx)
489499
if err != nil {
@@ -534,7 +544,7 @@ func GetWorkflowRunLogs(t translations.TranslationHelperFunc) inventory.ServerTo
534544

535545
// ListWorkflowJobs creates a tool to list jobs for a specific workflow run
536546
func ListWorkflowJobs(t translations.TranslationHelperFunc) inventory.ServerTool {
537-
tool := NewTool(
547+
tool := NewToolWithScopes(
538548
ToolsetMetadataActions,
539549
mcp.Tool{
540550
Name: "list_workflow_jobs",
@@ -567,6 +577,8 @@ func ListWorkflowJobs(t translations.TranslationHelperFunc) inventory.ServerTool
567577
Required: []string{"owner", "repo", "run_id"},
568578
}),
569579
},
580+
scopes.ToStringSlice(scopes.Repo),
581+
scopes.ToStringSlice(scopes.Repo),
570582
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
571583
client, err := deps.GetClient(ctx)
572584
if err != nil {
@@ -634,7 +646,7 @@ func ListWorkflowJobs(t translations.TranslationHelperFunc) inventory.ServerTool
634646

635647
// GetJobLogs creates a tool to download logs for a specific workflow job or efficiently get all failed job logs for a workflow run
636648
func GetJobLogs(t translations.TranslationHelperFunc) inventory.ServerTool {
637-
tool := NewTool(
649+
tool := NewToolWithScopes(
638650
ToolsetMetadataActions,
639651
mcp.Tool{
640652
Name: "get_job_logs",
@@ -679,6 +691,8 @@ func GetJobLogs(t translations.TranslationHelperFunc) inventory.ServerTool {
679691
Required: []string{"owner", "repo"},
680692
},
681693
},
694+
scopes.ToStringSlice(scopes.Repo),
695+
scopes.ToStringSlice(scopes.Repo),
682696
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
683697
client, err := deps.GetClient(ctx)
684698
if err != nil {
@@ -899,7 +913,7 @@ func downloadLogContent(ctx context.Context, logURL string, tailLines int, maxLi
899913

900914
// RerunWorkflowRun creates a tool to re-run an entire workflow run
901915
func RerunWorkflowRun(t translations.TranslationHelperFunc) inventory.ServerTool {
902-
tool := NewTool(
916+
tool := NewToolWithScopes(
903917
ToolsetMetadataActions,
904918
mcp.Tool{
905919
Name: "rerun_workflow_run",
@@ -927,6 +941,8 @@ func RerunWorkflowRun(t translations.TranslationHelperFunc) inventory.ServerTool
927941
Required: []string{"owner", "repo", "run_id"},
928942
},
929943
},
944+
scopes.ToStringSlice(scopes.Repo),
945+
scopes.ToStringSlice(scopes.Repo),
930946
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
931947
client, err := deps.GetClient(ctx)
932948
if err != nil {
@@ -974,7 +990,7 @@ func RerunWorkflowRun(t translations.TranslationHelperFunc) inventory.ServerTool
974990

975991
// RerunFailedJobs creates a tool to re-run only the failed jobs in a workflow run
976992
func RerunFailedJobs(t translations.TranslationHelperFunc) inventory.ServerTool {
977-
tool := NewTool(
993+
tool := NewToolWithScopes(
978994
ToolsetMetadataActions,
979995
mcp.Tool{
980996
Name: "rerun_failed_jobs",
@@ -1002,6 +1018,8 @@ func RerunFailedJobs(t translations.TranslationHelperFunc) inventory.ServerTool
10021018
Required: []string{"owner", "repo", "run_id"},
10031019
},
10041020
},
1021+
scopes.ToStringSlice(scopes.Repo),
1022+
scopes.ToStringSlice(scopes.Repo),
10051023
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
10061024
client, err := deps.GetClient(ctx)
10071025
if err != nil {
@@ -1049,7 +1067,7 @@ func RerunFailedJobs(t translations.TranslationHelperFunc) inventory.ServerTool
10491067

10501068
// CancelWorkflowRun creates a tool to cancel a workflow run
10511069
func CancelWorkflowRun(t translations.TranslationHelperFunc) inventory.ServerTool {
1052-
tool := NewTool(
1070+
tool := NewToolWithScopes(
10531071
ToolsetMetadataActions,
10541072
mcp.Tool{
10551073
Name: "cancel_workflow_run",
@@ -1077,6 +1095,8 @@ func CancelWorkflowRun(t translations.TranslationHelperFunc) inventory.ServerToo
10771095
Required: []string{"owner", "repo", "run_id"},
10781096
},
10791097
},
1098+
scopes.ToStringSlice(scopes.Repo),
1099+
scopes.ToStringSlice(scopes.Repo),
10801100
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
10811101
client, err := deps.GetClient(ctx)
10821102
if err != nil {
@@ -1126,7 +1146,7 @@ func CancelWorkflowRun(t translations.TranslationHelperFunc) inventory.ServerToo
11261146

11271147
// ListWorkflowRunArtifacts creates a tool to list artifacts for a workflow run
11281148
func ListWorkflowRunArtifacts(t translations.TranslationHelperFunc) inventory.ServerTool {
1129-
tool := NewTool(
1149+
tool := NewToolWithScopes(
11301150
ToolsetMetadataActions,
11311151
mcp.Tool{
11321152
Name: "list_workflow_run_artifacts",
@@ -1154,6 +1174,8 @@ func ListWorkflowRunArtifacts(t translations.TranslationHelperFunc) inventory.Se
11541174
Required: []string{"owner", "repo", "run_id"},
11551175
}),
11561176
},
1177+
scopes.ToStringSlice(scopes.Repo),
1178+
scopes.ToStringSlice(scopes.Repo),
11571179
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
11581180
client, err := deps.GetClient(ctx)
11591181
if err != nil {
@@ -1206,7 +1228,7 @@ func ListWorkflowRunArtifacts(t translations.TranslationHelperFunc) inventory.Se
12061228

12071229
// DownloadWorkflowRunArtifact creates a tool to download a workflow run artifact
12081230
func DownloadWorkflowRunArtifact(t translations.TranslationHelperFunc) inventory.ServerTool {
1209-
tool := NewTool(
1231+
tool := NewToolWithScopes(
12101232
ToolsetMetadataActions,
12111233
mcp.Tool{
12121234
Name: "download_workflow_run_artifact",
@@ -1234,6 +1256,8 @@ func DownloadWorkflowRunArtifact(t translations.TranslationHelperFunc) inventory
12341256
Required: []string{"owner", "repo", "artifact_id"},
12351257
},
12361258
},
1259+
scopes.ToStringSlice(scopes.Repo),
1260+
scopes.ToStringSlice(scopes.Repo),
12371261
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
12381262
client, err := deps.GetClient(ctx)
12391263
if err != nil {
@@ -1283,7 +1307,7 @@ func DownloadWorkflowRunArtifact(t translations.TranslationHelperFunc) inventory
12831307

12841308
// DeleteWorkflowRunLogs creates a tool to delete logs for a workflow run
12851309
func DeleteWorkflowRunLogs(t translations.TranslationHelperFunc) inventory.ServerTool {
1286-
tool := NewTool(
1310+
tool := NewToolWithScopes(
12871311
ToolsetMetadataActions,
12881312
mcp.Tool{
12891313
Name: "delete_workflow_run_logs",
@@ -1312,6 +1336,8 @@ func DeleteWorkflowRunLogs(t translations.TranslationHelperFunc) inventory.Serve
13121336
Required: []string{"owner", "repo", "run_id"},
13131337
},
13141338
},
1339+
scopes.ToStringSlice(scopes.Repo),
1340+
scopes.ToStringSlice(scopes.Repo),
13151341
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
13161342
client, err := deps.GetClient(ctx)
13171343
if err != nil {
@@ -1359,7 +1385,7 @@ func DeleteWorkflowRunLogs(t translations.TranslationHelperFunc) inventory.Serve
13591385

13601386
// GetWorkflowRunUsage creates a tool to get usage metrics for a workflow run
13611387
func GetWorkflowRunUsage(t translations.TranslationHelperFunc) inventory.ServerTool {
1362-
tool := NewTool(
1388+
tool := NewToolWithScopes(
13631389
ToolsetMetadataActions,
13641390
mcp.Tool{
13651391
Name: "get_workflow_run_usage",
@@ -1387,6 +1413,8 @@ func GetWorkflowRunUsage(t translations.TranslationHelperFunc) inventory.ServerT
13871413
Required: []string{"owner", "repo", "run_id"},
13881414
},
13891415
},
1416+
scopes.ToStringSlice(scopes.Repo),
1417+
scopes.ToStringSlice(scopes.Repo),
13901418
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
13911419
client, err := deps.GetClient(ctx)
13921420
if err != nil {
@@ -1427,7 +1455,7 @@ func GetWorkflowRunUsage(t translations.TranslationHelperFunc) inventory.ServerT
14271455

14281456
// ActionsList returns the tool and handler for listing GitHub Actions resources.
14291457
func ActionsList(t translations.TranslationHelperFunc) inventory.ServerTool {
1430-
tool := NewTool(
1458+
tool := NewToolWithScopes(
14311459
ToolsetMetadataActions,
14321460
mcp.Tool{
14331461
Name: "actions_list",
@@ -1551,6 +1579,8 @@ Use this tool to list workflows in a repository, or list workflow runs, jobs, an
15511579
Required: []string{"method", "owner", "repo"},
15521580
},
15531581
},
1582+
scopes.ToStringSlice(scopes.Repo),
1583+
scopes.ToStringSlice(scopes.Repo),
15541584
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
15551585
owner, err := RequiredParam[string](args, "owner")
15561586
if err != nil {
@@ -1622,7 +1652,7 @@ Use this tool to list workflows in a repository, or list workflow runs, jobs, an
16221652

16231653
// ActionsGet returns the tool and handler for getting GitHub Actions resources.
16241654
func ActionsGet(t translations.TranslationHelperFunc) inventory.ServerTool {
1625-
tool := NewTool(
1655+
tool := NewToolWithScopes(
16261656
ToolsetMetadataActions,
16271657
mcp.Tool{
16281658
Name: "actions_get",
@@ -1669,6 +1699,8 @@ Use this tool to get details about individual workflows, workflow runs, jobs, an
16691699
Required: []string{"method", "owner", "repo", "resource_id"},
16701700
},
16711701
},
1702+
scopes.ToStringSlice(scopes.Repo),
1703+
scopes.ToStringSlice(scopes.Repo),
16721704
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
16731705
owner, err := RequiredParam[string](args, "owner")
16741706
if err != nil {
@@ -1730,7 +1762,7 @@ Use this tool to get details about individual workflows, workflow runs, jobs, an
17301762

17311763
// ActionsRunTrigger returns the tool and handler for triggering GitHub Actions workflows.
17321764
func ActionsRunTrigger(t translations.TranslationHelperFunc) inventory.ServerTool {
1733-
tool := NewTool(
1765+
tool := NewToolWithScopes(
17341766
ToolsetMetadataActions,
17351767
mcp.Tool{
17361768
Name: "actions_run_trigger",
@@ -1782,6 +1814,8 @@ func ActionsRunTrigger(t translations.TranslationHelperFunc) inventory.ServerToo
17821814
Required: []string{"method", "owner", "repo"},
17831815
},
17841816
},
1817+
scopes.ToStringSlice(scopes.Repo),
1818+
scopes.ToStringSlice(scopes.Repo),
17851819
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
17861820
owner, err := RequiredParam[string](args, "owner")
17871821
if err != nil {
@@ -1848,7 +1882,7 @@ func ActionsRunTrigger(t translations.TranslationHelperFunc) inventory.ServerToo
18481882

18491883
// ActionsGetJobLogs returns the tool and handler for getting workflow job logs.
18501884
func ActionsGetJobLogs(t translations.TranslationHelperFunc) inventory.ServerTool {
1851-
tool := NewTool(
1885+
tool := NewToolWithScopes(
18521886
ToolsetMetadataActions,
18531887
mcp.Tool{
18541888
Name: "get_job_logs",
@@ -1896,6 +1930,8 @@ For single job logs, provide job_id. For all failed jobs in a run, provide run_i
18961930
Required: []string{"owner", "repo"},
18971931
},
18981932
},
1933+
scopes.ToStringSlice(scopes.Repo),
1934+
scopes.ToStringSlice(scopes.Repo),
18991935
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
19001936
owner, err := RequiredParam[string](args, "owner")
19011937
if err != nil {

0 commit comments

Comments
 (0)