-
Notifications
You must be signed in to change notification settings - Fork 579
Add support for running an Actions workflow #269
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@@ -0,0 +1,99 @@ | |||
package github |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a lot of Actions APIs, I suspect the single-file per API area will break down at some point.
I tried defining a separate actions
package, but it created some circular dependencies with this github
package.
I'd be happy to explore that more, but I wanted to keep these changes focused on this tool.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Appreciate you mentioning though, it's same reason I didn't consider new packages for tools yet.
Pretty sure the helpers and server can be extracted to their own packages to avoid this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a lot of Actions APIs, I suspect the single-file per API area will break down at some point.
I tried defining a separate
actions
package, but it created some circular dependencies with thisgithub
package.
This might open an interesting debate that really resonates with me!
When I started writing Go, I came from other languages where quickly deciding to use packages was the norm. So I followed suit, and my initial reaction was to do the same. However, over time, I've come to terms with the fact that this might not be entirely idiomatic.
Take go-github
, for example — they implement almost the entire GitHub API within a single package.
So my point here is that maybe we don't need to introduce more packages right away. We might consider another alternative, such as splitting the functionality into files like actions_foo.go
, actions_bar.go
, etc., and that might be more idiomatic.
Having said that, I don't have a strong opinion on it, but I'd like us to consider the above before we make the decision.
Thanks! ❤️
pkg/github/actions.go
Outdated
// Get the optional inputs parameter | ||
var inputs map[string]any | ||
if inputsObj, exists := request.Params.Arguments["inputs"]; exists && inputsObj != nil { | ||
inputs, _ = inputsObj.(map[string]any) | ||
} | ||
|
||
// Convert inputs to the format expected by the GitHub API | ||
inputsMap := make(map[string]any) | ||
if inputs != nil { | ||
for k, v := range inputs { | ||
inputsMap[k] = v | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was mostly generated by Copilot, not sure if there's a better way to process an object parameter.
), | ||
mcp.WithString("repo", | ||
mcp.Required(), | ||
mcp.Description("Repository name"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No mention of case-sensitivity here. Does that imply that it is case-sensitive? Should we be explicit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This matches the description used by most/all of the other repo
MCP inputs in this repo, so I stuck to being consistent with them.
I was thinking it might make sense to define some constant/reusable input definitions for these common inputs like repo & owner for consistency.
pkg/github/actions.go
Outdated
), | ||
mcp.WithString("workflowId", | ||
mcp.Required(), | ||
mcp.Description("The ID of the workflow. You can also pass the workflow file name as a string."), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just the workflow file name itself is acceptable? Or the relative path to the workflow file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The API supports both
Relative path
gh api -X POST /repos/joshmgross/actions-testing/actions/workflows/hello-world.yaml/dispatches -f "ref=main"
Full path (note the /
must be escaped)
gh api -X POST /repos/joshmgross/actions-testing/actions/workflows/.github%2Fworkflows%2Fhello-world.yaml/dispatches -f "ref=main"
I don't think github/go-github
will escape the /
by default though, so we might need to handle that 🤔
func (s *ActionsService) CreateWorkflowDispatchEventByFileName(ctx context.Context, owner, repo, workflowFileName string, event CreateWorkflowDispatchEventRequest) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/dispatches", owner, repo, workflowFileName)
return s.createWorkflowDispatchEvent(ctx, u, &event)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd be tempted to flip this around too, and call it workflow_file
or something, as it has file access already it can probably work out what workflows it can provide. The ID is only useful where it has received it from a list, and the list endpoint can probably return the file location as part of the list, which is also more useful than the ID, in terms of editing the file.
Does that make sense? The goal here is to make an API that LLMs comprehend and use natively, so definitely have a think on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed to workflow_file
- 034621b
@@ -82,6 +86,7 @@ func InitToolsets(passedToolsets []string, readOnly bool, getClient GetClientFn, | |||
tsg.AddToolset(users) | |||
tsg.AddToolset(pullRequests) | |||
tsg.AddToolset(codeSecurity) | |||
tsg.AddToolset(actions) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SamMorrowDrums let me know if I added this correctly
Looking through #188, it seems like we don't want some toolsets enabled by deafult but it's not clear to me what enables that.
Default Enabled Features
By default, the following features are enabled:
...
As far as I can tell, the default is "all"
github-mcp-server/pkg/github/tools.go
Line 14 in 614f226
var DefaultTools = []string{"all"} |
Supports #268
This adds a tool to allow running an Actions workflow via the
workflow_dispatch
API.Demo
CleanShot.2025-04-14.at.15.57.51.mp4
(Tested using these changes built from source per the instructions)
https://github.com/joshmgross/actions-testing/actions/runs/14454560690/job/40534749404