Skip to content

Commit fc48cfe

Browse files
committed
update actions run trigger tool to include delete
1 parent b7d0d6e commit fc48cfe

File tree

4 files changed

+122
-204
lines changed

4 files changed

+122
-204
lines changed

README.md

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -458,23 +458,14 @@ The following sets of tools are available:
458458
- `workflow_jobs_filter`: Filters for workflow jobs. **ONLY** used when action is 'list_workflow_jobs' (object, optional)
459459
- `workflow_runs_filter`: Filters for workflow runs. **ONLY** used when action is 'list_workflow_runs' (object, optional)
460460

461-
- **actions_run_trigger** - Trigger GitHub Actions workflow actions for a specific workflow run.
461+
- **actions_run_trigger** - Trigger GitHub Actions workflow actions
462462
- `action`: The action to trigger (string, required)
463+
- `inputs`: Inputs the workflow accepts. Only used for 'run_workflow' action. (object, optional)
463464
- `owner`: Repository owner (string, required)
465+
- `ref`: The git reference for the workflow. The reference can be a branch or tag name. Required for 'run_workflow' action. (string, optional)
464466
- `repo`: Repository name (string, required)
465-
- `run_id`: The ID of the workflow run to trigger (number, required)
466-
467-
- **delete_workflow_run_logs** - Delete workflow logs
468-
- `owner`: Repository owner (string, required)
469-
- `repo`: Repository name (string, required)
470-
- `run_id`: The unique identifier of the workflow run (number, required)
471-
472-
- **run_workflow** - Run workflow
473-
- `inputs`: Inputs the workflow accepts (object, optional)
474-
- `owner`: Repository owner (string, required)
475-
- `ref`: The git reference for the workflow. The reference can be a branch or tag name. (string, required)
476-
- `repo`: Repository name (string, required)
477-
- `workflow_id`: The workflow ID (numeric) or workflow file name (e.g., main.yml, ci.yaml) (string, required)
467+
- `run_id`: The ID of the workflow run. Required for all actions except 'run_workflow'. (number, optional)
468+
- `workflow_id`: The workflow ID (numeric) or workflow file name (e.g., main.yml, ci.yaml). Required for 'run_workflow' action. (string, optional)
478469

479470
</details>
480471

pkg/github/actions.go

Lines changed: 99 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const (
4141
actionsActionTypeRerunWorkflowRun
4242
actionsActionTypeRerunFailedJobs
4343
actionsActionTypeCancelWorkflowRun
44+
actionsActionTypeDeleteWorkflowRunLogs
4445
)
4546

4647
var actionsResourceTypes = map[actionsActionType]string{
@@ -59,6 +60,7 @@ var actionsResourceTypes = map[actionsActionType]string{
5960
actionsActionTypeRerunWorkflowRun: "rerun_workflow_run",
6061
actionsActionTypeRerunFailedJobs: "rerun_failed_jobs",
6162
actionsActionTypeCancelWorkflowRun: "cancel_workflow_run",
63+
actionsActionTypeDeleteWorkflowRunLogs: "delete_workflow_run_logs",
6264
}
6365

6466
func (r actionsActionType) String() string {
@@ -406,24 +408,23 @@ Use this tool to get details about individual workflows, workflow runs, jobs, an
406408

407409
func ActionsRunTrigger(getClient GetClientFn, t translations.TranslationHelperFunc) (tool mcp.Tool, handler server.ToolHandlerFunc) {
408410
return mcp.NewTool("actions_run_trigger",
409-
mcp.WithDescription(t("TOOL_ACTIONS_TRIGGER_DESCRIPTION", "Trigger GitHub Actions workflow actions for a specific workflow run.")),
411+
mcp.WithDescription(t("TOOL_ACTIONS_TRIGGER_DESCRIPTION", "Trigger GitHub Actions workflow actions, including running, re-running, cancelling, and deleting workflow runs.")),
410412
mcp.WithToolAnnotation(mcp.ToolAnnotation{
411-
Title: t("TOOL_ACTIONS_TRIGGER_USER_TITLE", "Trigger GitHub Actions workflow actions for a specific workflow run."),
412-
ReadOnlyHint: ToBoolPtr(false),
413+
Title: t("TOOL_ACTIONS_TRIGGER_USER_TITLE", "Trigger GitHub Actions workflow actions"),
414+
ReadOnlyHint: ToBoolPtr(false),
415+
DestructiveHint: ToBoolPtr(false),
413416
}),
414417
mcp.WithString("action",
415418
mcp.Required(),
416419
mcp.Description("The action to trigger"),
417420
mcp.Enum(
421+
actionsActionTypeRunWorkflow.String(),
418422
actionsActionTypeRerunWorkflowRun.String(),
419423
actionsActionTypeRerunFailedJobs.String(),
420424
actionsActionTypeCancelWorkflowRun.String(),
425+
actionsActionTypeDeleteWorkflowRunLogs.String(),
421426
),
422427
),
423-
mcp.WithNumber("run_id",
424-
mcp.Required(),
425-
mcp.Description("The ID of the workflow run to trigger"),
426-
),
427428
mcp.WithString("owner",
428429
mcp.Required(),
429430
mcp.Description(DescriptionRepositoryOwner),
@@ -432,6 +433,18 @@ func ActionsRunTrigger(getClient GetClientFn, t translations.TranslationHelperFu
432433
mcp.Required(),
433434
mcp.Description(DescriptionRepositoryName),
434435
),
436+
mcp.WithString("workflow_id",
437+
mcp.Description("The workflow ID (numeric) or workflow file name (e.g., main.yml, ci.yaml). Required for 'run_workflow' action."),
438+
),
439+
mcp.WithString("ref",
440+
mcp.Description("The git reference for the workflow. The reference can be a branch or tag name. Required for 'run_workflow' action."),
441+
),
442+
mcp.WithObject("inputs",
443+
mcp.Description("Inputs the workflow accepts. Only used for 'run_workflow' action."),
444+
),
445+
mcp.WithNumber("run_id",
446+
mcp.Description("The ID of the workflow run. Required for all actions except 'run_workflow'."),
447+
),
435448
),
436449
func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
437450
owner, err := RequiredParam[string](request, "owner")
@@ -452,9 +465,29 @@ func ActionsRunTrigger(getClient GetClientFn, t translations.TranslationHelperFu
452465
return mcp.NewToolResultError(fmt.Sprintf("unknown action: %s", actionTypeStr)), nil
453466
}
454467

455-
runID, err := RequiredInt(request, "run_id")
456-
if err != nil {
457-
return mcp.NewToolResultError(err.Error()), nil
468+
// Get optional parameters
469+
workflowID, _ := OptionalParam[string](request, "workflow_id")
470+
ref, _ := OptionalParam[string](request, "ref")
471+
runID, _ := OptionalIntParam(request, "run_id")
472+
473+
// Get optional inputs parameter
474+
var inputs map[string]interface{}
475+
if requestInputs, ok := request.GetArguments()["inputs"]; ok {
476+
if inputsMap, ok := requestInputs.(map[string]interface{}); ok {
477+
inputs = inputsMap
478+
}
479+
}
480+
481+
// Validate required parameters based on action type
482+
if resourceType == actionsActionTypeRunWorkflow {
483+
if workflowID == "" {
484+
return mcp.NewToolResultError("workflow_id is required for run_workflow action"), nil
485+
}
486+
if ref == "" {
487+
return mcp.NewToolResultError("ref is required for run_workflow action"), nil
488+
}
489+
} else if runID == 0 {
490+
return mcp.NewToolResultError("run_id is required for this action"), nil
458491
}
459492

460493
client, err := getClient(ctx)
@@ -463,12 +496,16 @@ func ActionsRunTrigger(getClient GetClientFn, t translations.TranslationHelperFu
463496
}
464497

465498
switch resourceType {
499+
case actionsActionTypeRunWorkflow:
500+
return runWorkflow(ctx, client, request, owner, repo, workflowID, ref, inputs)
466501
case actionsActionTypeRerunWorkflowRun:
467502
return rerunWorkflowRun(ctx, client, request, owner, repo, int64(runID))
468503
case actionsActionTypeRerunFailedJobs:
469504
return rerunFailedJobs(ctx, client, request, owner, repo, int64(runID))
470505
case actionsActionTypeCancelWorkflowRun:
471506
return cancelWorkflowRun(ctx, client, request, owner, repo, int64(runID))
507+
case actionsActionTypeDeleteWorkflowRunLogs:
508+
return deleteWorkflowRunLogs(ctx, client, request, owner, repo, int64(runID))
472509
case actionsActionTypeUnknown:
473510
return mcp.NewToolResultError(fmt.Sprintf("unknown action: %s", actionTypeStr)), nil
474511
default:
@@ -684,103 +721,46 @@ func listWorkflows(ctx context.Context, client *github.Client, _ mcp.CallToolReq
684721
return mcp.NewToolResultText(string(r)), nil
685722
}
686723

687-
// RunWorkflow creates a tool to run an Actions workflow
688-
func RunWorkflow(getClient GetClientFn, t translations.TranslationHelperFunc) (tool mcp.Tool, handler server.ToolHandlerFunc) {
689-
return mcp.NewTool("run_workflow",
690-
mcp.WithDescription(t("TOOL_RUN_WORKFLOW_DESCRIPTION", "Run an Actions workflow by workflow ID or filename")),
691-
mcp.WithToolAnnotation(mcp.ToolAnnotation{
692-
Title: t("TOOL_RUN_WORKFLOW_USER_TITLE", "Run workflow"),
693-
ReadOnlyHint: ToBoolPtr(false),
694-
}),
695-
mcp.WithString("owner",
696-
mcp.Required(),
697-
mcp.Description(DescriptionRepositoryOwner),
698-
),
699-
mcp.WithString("repo",
700-
mcp.Required(),
701-
mcp.Description(DescriptionRepositoryName),
702-
),
703-
mcp.WithString("workflow_id",
704-
mcp.Required(),
705-
mcp.Description("The workflow ID (numeric) or workflow file name (e.g., main.yml, ci.yaml)"),
706-
),
707-
mcp.WithString("ref",
708-
mcp.Required(),
709-
mcp.Description("The git reference for the workflow. The reference can be a branch or tag name."),
710-
),
711-
mcp.WithObject("inputs",
712-
mcp.Description("Inputs the workflow accepts"),
713-
),
714-
),
715-
func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
716-
owner, err := RequiredParam[string](request, "owner")
717-
if err != nil {
718-
return mcp.NewToolResultError(err.Error()), nil
719-
}
720-
repo, err := RequiredParam[string](request, "repo")
721-
if err != nil {
722-
return mcp.NewToolResultError(err.Error()), nil
723-
}
724-
workflowID, err := RequiredParam[string](request, "workflow_id")
725-
if err != nil {
726-
return mcp.NewToolResultError(err.Error()), nil
727-
}
728-
ref, err := RequiredParam[string](request, "ref")
729-
if err != nil {
730-
return mcp.NewToolResultError(err.Error()), nil
731-
}
732-
733-
// Get optional inputs parameter
734-
var inputs map[string]interface{}
735-
if requestInputs, ok := request.GetArguments()["inputs"]; ok {
736-
if inputsMap, ok := requestInputs.(map[string]interface{}); ok {
737-
inputs = inputsMap
738-
}
739-
}
740-
741-
client, err := getClient(ctx)
742-
if err != nil {
743-
return nil, fmt.Errorf("failed to get GitHub client: %w", err)
744-
}
724+
// runWorkflow runs an Actions workflow by workflow ID or filename
725+
func runWorkflow(ctx context.Context, client *github.Client, _ mcp.CallToolRequest, owner, repo, workflowID, ref string, inputs map[string]interface{}) (*mcp.CallToolResult, error) {
726+
event := github.CreateWorkflowDispatchEventRequest{
727+
Ref: ref,
728+
Inputs: inputs,
729+
}
745730

746-
event := github.CreateWorkflowDispatchEventRequest{
747-
Ref: ref,
748-
Inputs: inputs,
749-
}
731+
var resp *github.Response
732+
var err error
733+
var workflowType string
750734

751-
var resp *github.Response
752-
var workflowType string
735+
if workflowIDInt, parseErr := strconv.ParseInt(workflowID, 10, 64); parseErr == nil {
736+
resp, err = client.Actions.CreateWorkflowDispatchEventByID(ctx, owner, repo, workflowIDInt, event)
737+
workflowType = "workflow_id"
738+
} else {
739+
resp, err = client.Actions.CreateWorkflowDispatchEventByFileName(ctx, owner, repo, workflowID, event)
740+
workflowType = "workflow_file"
741+
}
753742

754-
if workflowIDInt, parseErr := strconv.ParseInt(workflowID, 10, 64); parseErr == nil {
755-
resp, err = client.Actions.CreateWorkflowDispatchEventByID(ctx, owner, repo, workflowIDInt, event)
756-
workflowType = "workflow_id"
757-
} else {
758-
resp, err = client.Actions.CreateWorkflowDispatchEventByFileName(ctx, owner, repo, workflowID, event)
759-
workflowType = "workflow_file"
760-
}
743+
if err != nil {
744+
return ghErrors.NewGitHubAPIErrorResponse(ctx, "failed to run workflow", resp, err), nil
745+
}
746+
defer func() { _ = resp.Body.Close() }()
761747

762-
if err != nil {
763-
return nil, fmt.Errorf("failed to run workflow: %w", err)
764-
}
765-
defer func() { _ = resp.Body.Close() }()
766-
767-
result := map[string]any{
768-
"message": "Workflow run has been queued",
769-
"workflow_type": workflowType,
770-
"workflow_id": workflowID,
771-
"ref": ref,
772-
"inputs": inputs,
773-
"status": resp.Status,
774-
"status_code": resp.StatusCode,
775-
}
748+
result := map[string]any{
749+
"message": "Workflow run has been queued",
750+
"workflow_type": workflowType,
751+
"workflow_id": workflowID,
752+
"ref": ref,
753+
"inputs": inputs,
754+
"status": resp.Status,
755+
"status_code": resp.StatusCode,
756+
}
776757

777-
r, err := json.Marshal(result)
778-
if err != nil {
779-
return nil, fmt.Errorf("failed to marshal response: %w", err)
780-
}
758+
r, err := json.Marshal(result)
759+
if err != nil {
760+
return nil, fmt.Errorf("failed to marshal response: %w", err)
761+
}
781762

782-
return mcp.NewToolResultText(string(r)), nil
783-
}
763+
return mcp.NewToolResultText(string(r)), nil
784764
}
785765

786766
// GetWorkflowRunLogs creates a tool to download logs for a specific workflow run
@@ -1060,68 +1040,27 @@ func cancelWorkflowRun(ctx context.Context, client *github.Client, _ mcp.CallToo
10601040
return mcp.NewToolResultText(string(r)), nil
10611041
}
10621042

1063-
// DeleteWorkflowRunLogs creates a tool to delete logs for a workflow run
1064-
func DeleteWorkflowRunLogs(getClient GetClientFn, t translations.TranslationHelperFunc) (tool mcp.Tool, handler server.ToolHandlerFunc) {
1065-
return mcp.NewTool("delete_workflow_run_logs",
1066-
mcp.WithDescription(t("TOOL_DELETE_WORKFLOW_RUN_LOGS_DESCRIPTION", "Delete logs for a workflow run")),
1067-
mcp.WithToolAnnotation(mcp.ToolAnnotation{
1068-
Title: t("TOOL_DELETE_WORKFLOW_RUN_LOGS_USER_TITLE", "Delete workflow logs"),
1069-
ReadOnlyHint: ToBoolPtr(false),
1070-
DestructiveHint: ToBoolPtr(true),
1071-
}),
1072-
mcp.WithString("owner",
1073-
mcp.Required(),
1074-
mcp.Description(DescriptionRepositoryOwner),
1075-
),
1076-
mcp.WithString("repo",
1077-
mcp.Required(),
1078-
mcp.Description(DescriptionRepositoryName),
1079-
),
1080-
mcp.WithNumber("run_id",
1081-
mcp.Required(),
1082-
mcp.Description("The unique identifier of the workflow run"),
1083-
),
1084-
),
1085-
func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
1086-
owner, err := RequiredParam[string](request, "owner")
1087-
if err != nil {
1088-
return mcp.NewToolResultError(err.Error()), nil
1089-
}
1090-
repo, err := RequiredParam[string](request, "repo")
1091-
if err != nil {
1092-
return mcp.NewToolResultError(err.Error()), nil
1093-
}
1094-
runIDInt, err := RequiredInt(request, "run_id")
1095-
if err != nil {
1096-
return mcp.NewToolResultError(err.Error()), nil
1097-
}
1098-
runID := int64(runIDInt)
1099-
1100-
client, err := getClient(ctx)
1101-
if err != nil {
1102-
return nil, fmt.Errorf("failed to get GitHub client: %w", err)
1103-
}
1104-
1105-
resp, err := client.Actions.DeleteWorkflowRunLogs(ctx, owner, repo, runID)
1106-
if err != nil {
1107-
return ghErrors.NewGitHubAPIErrorResponse(ctx, "failed to delete workflow run logs", resp, err), nil
1108-
}
1109-
defer func() { _ = resp.Body.Close() }()
1043+
// deleteWorkflowRunLogs deletes logs for a workflow run
1044+
func deleteWorkflowRunLogs(ctx context.Context, client *github.Client, _ mcp.CallToolRequest, owner, repo string, runID int64) (*mcp.CallToolResult, error) {
1045+
resp, err := client.Actions.DeleteWorkflowRunLogs(ctx, owner, repo, runID)
1046+
if err != nil {
1047+
return ghErrors.NewGitHubAPIErrorResponse(ctx, "failed to delete workflow run logs", resp, err), nil
1048+
}
1049+
defer func() { _ = resp.Body.Close() }()
11101050

1111-
result := map[string]any{
1112-
"message": "Workflow run logs have been deleted",
1113-
"run_id": runID,
1114-
"status": resp.Status,
1115-
"status_code": resp.StatusCode,
1116-
}
1051+
result := map[string]any{
1052+
"message": "Workflow run logs have been deleted",
1053+
"run_id": runID,
1054+
"status": resp.Status,
1055+
"status_code": resp.StatusCode,
1056+
}
11171057

1118-
r, err := json.Marshal(result)
1119-
if err != nil {
1120-
return nil, fmt.Errorf("failed to marshal response: %w", err)
1121-
}
1058+
r, err := json.Marshal(result)
1059+
if err != nil {
1060+
return nil, fmt.Errorf("failed to marshal response: %w", err)
1061+
}
11221062

1123-
return mcp.NewToolResultText(string(r)), nil
1124-
}
1063+
return mcp.NewToolResultText(string(r)), nil
11251064
}
11261065

11271066
// GetWorkflowRunUsage creates a tool to get usage metrics for a workflow run

0 commit comments

Comments
 (0)