diff --git a/.github/agents/go-sdk-tool-migrator.md b/.github/agents/go-sdk-tool-migrator.md index f8003fd25..b14824d2d 100644 --- a/.github/agents/go-sdk-tool-migrator.md +++ b/.github/agents/go-sdk-tool-migrator.md @@ -18,7 +18,7 @@ When generating the migration guide, consider the following aspects: * The return type for the tool constructor function should be updated from `mcp.Tool, server.ToolHandlerFunc` to `(mcp.Tool, mcp.ToolHandlerFor[map[string]any, any])`. * The tool handler function signature should be updated to use generics, changing from `func(ctx context.Context, mcp.CallToolRequest) (*mcp.CallToolResult, error)` to `func(context.Context, *mcp.CallToolRequest, map[string]any) (*mcp.CallToolResult, any, error)`. * The `RequiredParam`, `RequiredInt`, `RequiredBigInt`, `OptionalParamOK`, `OptionalParam`, `OptionalIntParam`, `OptionalIntParamWithDefault`, `OptionalBoolParamWithDefault`, `OptionalStringArrayParam`, `OptionalBigIntArrayParam` and `OptionalCursorPaginationParams` functions should be changed to use the tool arguments that are now passed as a map in the tool handler function, rather than extracting them from the `mcp.CallToolRequest`. -* `mcp.NewToolResultText`, `mcp.NewToolResultError`, `mcp.NewToolResultErrorFromErr` and `mcp.NewToolResultResource` no longer available in `modelcontextprotocol/go-sdk`. There are a few helper functions available in `pkg/utils/result.go` that can be used to replace these, in the `utils` package. +* `mcp.NewToolResultText`, `mcp.NewToolResultError`, `mcp.NewToolResultErrorFromErr` and `mcp.NewToolResultResource` no longer available in `modelcontextprotocol/go-sdk`. There are a few helper functions available in `pkg/mcpresult/mcpresult.go` that can be used to replace these, in the `mcpresult` package. ### Schema Changes diff --git a/pkg/errors/error.go b/pkg/errors/error.go index 93ea852a8..f0f2e2f9b 100644 --- a/pkg/errors/error.go +++ b/pkg/errors/error.go @@ -5,7 +5,7 @@ import ( "fmt" "net/http" - "github.com/github/github-mcp-server/pkg/utils" + "github.com/github/github-mcp-server/pkg/mcpresult" "github.com/google/go-github/v79/github" "github.com/modelcontextprotocol/go-sdk/mcp" ) @@ -153,31 +153,31 @@ func addRawAPIErrorToContext(ctx context.Context, err *GitHubRawAPIError) (conte return nil, fmt.Errorf("context does not contain GitHubCtxErrors") } -// NewGitHubAPIErrorResponse returns an mcp.NewToolResultError and retains the error in the context for access via middleware +// NewGitHubAPIErrorResponse returns an mcp.CallToolResult and retains the error in the context for access via middleware func NewGitHubAPIErrorResponse(ctx context.Context, message string, resp *github.Response, err error) *mcp.CallToolResult { apiErr := newGitHubAPIError(message, resp, err) if ctx != nil { _, _ = addGitHubAPIErrorToContext(ctx, apiErr) // Explicitly ignore error for graceful handling } - return utils.NewToolResultErrorFromErr(message, err) + return mcpresult.NewErrorFromErr(message, err) } -// NewGitHubGraphQLErrorResponse returns an mcp.NewToolResultError and retains the error in the context for access via middleware +// NewGitHubGraphQLErrorResponse returns an mcp.CallToolResult and retains the error in the context for access via middleware func NewGitHubGraphQLErrorResponse(ctx context.Context, message string, err error) *mcp.CallToolResult { graphQLErr := newGitHubGraphQLError(message, err) if ctx != nil { _, _ = addGitHubGraphQLErrorToContext(ctx, graphQLErr) // Explicitly ignore error for graceful handling } - return utils.NewToolResultErrorFromErr(message, err) + return mcpresult.NewErrorFromErr(message, err) } -// NewGitHubRawAPIErrorResponse returns an mcp.NewToolResultError and retains the error in the context for access via middleware +// NewGitHubRawAPIErrorResponse returns an mcp.CallToolResult and retains the error in the context for access via middleware func NewGitHubRawAPIErrorResponse(ctx context.Context, message string, resp *http.Response, err error) *mcp.CallToolResult { rawErr := newGitHubRawAPIError(message, resp, err) if ctx != nil { _, _ = addRawAPIErrorToContext(ctx, rawErr) // Explicitly ignore error for graceful handling } - return utils.NewToolResultErrorFromErr(message, err) + return mcpresult.NewErrorFromErr(message, err) } // NewGitHubAPIStatusErrorResponse handles cases where the API call succeeds (err == nil) diff --git a/pkg/github/actions.go b/pkg/github/actions.go index d3e5aad8e..52c3863a3 100644 --- a/pkg/github/actions.go +++ b/pkg/github/actions.go @@ -13,9 +13,9 @@ import ( buffer "github.com/github/github-mcp-server/pkg/buffer" ghErrors "github.com/github/github-mcp-server/pkg/errors" "github.com/github/github-mcp-server/pkg/inventory" + "github.com/github/github-mcp-server/pkg/mcpresult" "github.com/github/github-mcp-server/pkg/scopes" "github.com/github/github-mcp-server/pkg/translations" - "github.com/github/github-mcp-server/pkg/utils" "github.com/google/go-github/v79/github" "github.com/google/jsonschema-go/jsonschema" "github.com/modelcontextprotocol/go-sdk/mcp" @@ -79,22 +79,22 @@ func ListWorkflows(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Get optional pagination parameters pagination, err := OptionalPaginationParams(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Set up list options @@ -114,7 +114,7 @@ func ListWorkflows(t translations.TranslationHelperFunc) inventory.ServerTool { return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) tool.FeatureFlagEnable = FeatureFlagHoldbackConsolidatedActions @@ -206,44 +206,44 @@ func ListWorkflowRuns(t translations.TranslationHelperFunc) inventory.ServerTool func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } workflowID, err := RequiredParam[string](args, "workflow_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Get optional filtering parameters actor, err := OptionalParam[string](args, "actor") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } branch, err := OptionalParam[string](args, "branch") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } event, err := OptionalParam[string](args, "event") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } status, err := OptionalParam[string](args, "status") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Get optional pagination parameters pagination, err := OptionalPaginationParams(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Set up list options @@ -269,7 +269,7 @@ func ListWorkflowRuns(t translations.TranslationHelperFunc) inventory.ServerTool return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) tool.FeatureFlagEnable = FeatureFlagHoldbackConsolidatedActions @@ -318,24 +318,24 @@ func RunWorkflow(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } workflowID, err := RequiredParam[string](args, "workflow_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } ref, err := RequiredParam[string](args, "ref") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Get optional inputs parameter @@ -382,7 +382,7 @@ func RunWorkflow(t translations.TranslationHelperFunc) inventory.ServerTool { return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) tool.FeatureFlagEnable = FeatureFlagHoldbackConsolidatedActions @@ -423,20 +423,20 @@ func GetWorkflowRun(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } runIDInt, err := RequiredInt(args, "run_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } runID := int64(runIDInt) @@ -451,7 +451,7 @@ func GetWorkflowRun(t translations.TranslationHelperFunc) inventory.ServerTool { return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) tool.FeatureFlagEnable = FeatureFlagHoldbackConsolidatedActions @@ -492,20 +492,20 @@ func GetWorkflowRunLogs(t translations.TranslationHelperFunc) inventory.ServerTo func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } runIDInt, err := RequiredInt(args, "run_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } runID := int64(runIDInt) @@ -530,7 +530,7 @@ func GetWorkflowRunLogs(t translations.TranslationHelperFunc) inventory.ServerTo return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) tool.FeatureFlagEnable = FeatureFlagHoldbackConsolidatedActions @@ -576,33 +576,33 @@ func ListWorkflowJobs(t translations.TranslationHelperFunc) inventory.ServerTool func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } runIDInt, err := RequiredInt(args, "run_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } runID := int64(runIDInt) // Get optional filtering parameters filter, err := OptionalParam[string](args, "filter") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Get optional pagination parameters pagination, err := OptionalPaginationParams(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Set up list options @@ -631,7 +631,7 @@ func ListWorkflowJobs(t translations.TranslationHelperFunc) inventory.ServerTool return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) tool.FeatureFlagEnable = FeatureFlagHoldbackConsolidatedActions @@ -689,38 +689,38 @@ func GetJobLogs(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Get optional parameters jobID, err := OptionalIntParam(args, "job_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } runID, err := OptionalIntParam(args, "run_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } failedOnly, err := OptionalParam[bool](args, "failed_only") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } returnContent, err := OptionalParam[bool](args, "return_content") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } tailLines, err := OptionalIntParam(args, "tail_lines") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Default to 500 lines if not specified if tailLines == 0 { @@ -729,10 +729,10 @@ func GetJobLogs(t translations.TranslationHelperFunc) inventory.ServerTool { // Validate parameters if failedOnly && runID == 0 { - return utils.NewToolResultError("run_id is required when failed_only is true"), nil, nil + return mcpresult.NewError("run_id is required when failed_only is true"), nil, nil } if !failedOnly && jobID == 0 { - return utils.NewToolResultError("job_id is required when failed_only is false"), nil, nil + return mcpresult.NewError("job_id is required when failed_only is false"), nil, nil } if failedOnly && runID > 0 { @@ -743,7 +743,7 @@ func GetJobLogs(t translations.TranslationHelperFunc) inventory.ServerTool { return handleSingleJobLogs(ctx, client, owner, repo, int64(jobID), returnContent, tailLines, deps.GetContentWindowSize()) } - return utils.NewToolResultError("Either job_id must be provided for single job logs, or run_id with failed_only=true for failed job logs"), nil, nil + return mcpresult.NewError("Either job_id must be provided for single job logs, or run_id with failed_only=true for failed job logs"), nil, nil }, ) tool.FeatureFlagEnable = FeatureFlagHoldbackConsolidatedActions @@ -777,7 +777,7 @@ func handleFailedJobLogs(ctx context.Context, client *github.Client, owner, repo "failed_jobs": 0, } r, _ := json.Marshal(result) - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } // Collect logs for all failed jobs @@ -812,7 +812,7 @@ func handleFailedJobLogs(ctx context.Context, client *github.Client, owner, repo return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } // handleSingleJobLogs gets logs for a single job @@ -827,7 +827,7 @@ func handleSingleJobLogs(ctx context.Context, client *github.Client, owner, repo return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } // getJobLogData retrieves log data for a single job, either as URL or content @@ -938,20 +938,20 @@ func RerunWorkflowRun(t translations.TranslationHelperFunc) inventory.ServerTool func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } runIDInt, err := RequiredInt(args, "run_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } runID := int64(runIDInt) @@ -973,7 +973,7 @@ func RerunWorkflowRun(t translations.TranslationHelperFunc) inventory.ServerTool return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) tool.FeatureFlagEnable = FeatureFlagHoldbackConsolidatedActions @@ -1014,20 +1014,20 @@ func RerunFailedJobs(t translations.TranslationHelperFunc) inventory.ServerTool func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } runIDInt, err := RequiredInt(args, "run_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } runID := int64(runIDInt) @@ -1049,7 +1049,7 @@ func RerunFailedJobs(t translations.TranslationHelperFunc) inventory.ServerTool return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) tool.FeatureFlagEnable = FeatureFlagHoldbackConsolidatedActions @@ -1090,20 +1090,20 @@ func CancelWorkflowRun(t translations.TranslationHelperFunc) inventory.ServerToo func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } runIDInt, err := RequiredInt(args, "run_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } runID := int64(runIDInt) @@ -1127,7 +1127,7 @@ func CancelWorkflowRun(t translations.TranslationHelperFunc) inventory.ServerToo return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) tool.FeatureFlagEnable = FeatureFlagHoldbackConsolidatedActions @@ -1168,27 +1168,27 @@ func ListWorkflowRunArtifacts(t translations.TranslationHelperFunc) inventory.Se func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } runIDInt, err := RequiredInt(args, "run_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } runID := int64(runIDInt) // Get optional pagination parameters pagination, err := OptionalPaginationParams(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Set up list options @@ -1208,7 +1208,7 @@ func ListWorkflowRunArtifacts(t translations.TranslationHelperFunc) inventory.Se return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) tool.FeatureFlagEnable = FeatureFlagHoldbackConsolidatedActions @@ -1249,20 +1249,20 @@ func DownloadWorkflowRunArtifact(t translations.TranslationHelperFunc) inventory func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } artifactIDInt, err := RequiredInt(args, "artifact_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } artifactID := int64(artifactIDInt) @@ -1286,7 +1286,7 @@ func DownloadWorkflowRunArtifact(t translations.TranslationHelperFunc) inventory return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) tool.FeatureFlagEnable = FeatureFlagHoldbackConsolidatedActions @@ -1328,20 +1328,20 @@ func DeleteWorkflowRunLogs(t translations.TranslationHelperFunc) inventory.Serve func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } runIDInt, err := RequiredInt(args, "run_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } runID := int64(runIDInt) @@ -1363,7 +1363,7 @@ func DeleteWorkflowRunLogs(t translations.TranslationHelperFunc) inventory.Serve return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) tool.FeatureFlagEnable = FeatureFlagHoldbackConsolidatedActions @@ -1404,20 +1404,20 @@ func GetWorkflowRunUsage(t translations.TranslationHelperFunc) inventory.ServerT func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } runIDInt, err := RequiredInt(args, "run_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } runID := int64(runIDInt) @@ -1432,7 +1432,7 @@ func GetWorkflowRunUsage(t translations.TranslationHelperFunc) inventory.ServerT return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) tool.FeatureFlagEnable = FeatureFlagHoldbackConsolidatedActions @@ -1569,27 +1569,27 @@ Use this tool to list workflows in a repository, or list workflow runs, jobs, an func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } method, err := RequiredParam[string](args, "method") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } resourceID, err := OptionalParam[string](args, "resource_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } pagination, err := OptionalPaginationParams(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) @@ -1607,13 +1607,13 @@ Use this tool to list workflows in a repository, or list workflow runs, jobs, an // If not provided, list all workflow runs in the repository default: if resourceID == "" { - return utils.NewToolResultError(fmt.Sprintf("missing required parameter for method %s: resource_id", method)), nil, nil + return mcpresult.NewError(fmt.Sprintf("missing required parameter for method %s: resource_id", method)), nil, nil } // resource ID must be an integer for jobs and artifacts resourceIDInt, parseErr = strconv.ParseInt(resourceID, 10, 64) if parseErr != nil { - return utils.NewToolResultError(fmt.Sprintf("invalid resource_id, must be an integer for method %s: %v", method, parseErr)), nil, nil + return mcpresult.NewError(fmt.Sprintf("invalid resource_id, must be an integer for method %s: %v", method, parseErr)), nil, nil } } @@ -1627,7 +1627,7 @@ Use this tool to list workflows in a repository, or list workflow runs, jobs, an case actionsMethodListWorkflowArtifacts: return listWorkflowArtifacts(ctx, client, owner, repo, resourceIDInt, pagination) default: - return utils.NewToolResultError(fmt.Sprintf("unknown method: %s", method)), nil, nil + return mcpresult.NewError(fmt.Sprintf("unknown method: %s", method)), nil, nil } }, ) @@ -1688,20 +1688,20 @@ Use this tool to get details about individual workflows, workflow runs, jobs, an func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } method, err := RequiredParam[string](args, "method") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } resourceID, err := RequiredParam[string](args, "resource_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) @@ -1718,7 +1718,7 @@ Use this tool to get details about individual workflows, workflow runs, jobs, an // For other methods, resource ID must be an integer resourceIDInt, parseErr = strconv.ParseInt(resourceID, 10, 64) if parseErr != nil { - return utils.NewToolResultError(fmt.Sprintf("invalid resource_id, must be an integer for method %s: %v", method, parseErr)), nil, nil + return mcpresult.NewError(fmt.Sprintf("invalid resource_id, must be an integer for method %s: %v", method, parseErr)), nil, nil } } @@ -1736,7 +1736,7 @@ Use this tool to get details about individual workflows, workflow runs, jobs, an case actionsMethodGetWorkflowRunLogsURL: return getWorkflowRunLogsURL(ctx, client, owner, repo, resourceIDInt) default: - return utils.NewToolResultError(fmt.Sprintf("unknown method: %s", method)), nil, nil + return mcpresult.NewError(fmt.Sprintf("unknown method: %s", method)), nil, nil } }, ) @@ -1802,15 +1802,15 @@ func ActionsRunTrigger(t translations.TranslationHelperFunc) inventory.ServerToo func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } method, err := RequiredParam[string](args, "method") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Get optional parameters @@ -1829,13 +1829,13 @@ func ActionsRunTrigger(t translations.TranslationHelperFunc) inventory.ServerToo // Validate required parameters based on action type if method == actionsMethodRunWorkflow { if workflowID == "" { - return utils.NewToolResultError("workflow_id is required for run_workflow action"), nil, nil + return mcpresult.NewError("workflow_id is required for run_workflow action"), nil, nil } if ref == "" { - return utils.NewToolResultError("ref is required for run_workflow action"), nil, nil + return mcpresult.NewError("ref is required for run_workflow action"), nil, nil } } else if runID == 0 { - return utils.NewToolResultError("missing required parameter: run_id"), nil, nil + return mcpresult.NewError("missing required parameter: run_id"), nil, nil } client, err := deps.GetClient(ctx) @@ -1855,7 +1855,7 @@ func ActionsRunTrigger(t translations.TranslationHelperFunc) inventory.ServerToo case actionsMethodDeleteWorkflowRunLogs: return deleteWorkflowRunLogs(ctx, client, owner, repo, int64(runID)) default: - return utils.NewToolResultError(fmt.Sprintf("unknown method: %s", method)), nil, nil + return mcpresult.NewError(fmt.Sprintf("unknown method: %s", method)), nil, nil } }, ) @@ -1917,36 +1917,36 @@ For single job logs, provide job_id. For all failed jobs in a run, provide run_i func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } jobID, err := OptionalIntParam(args, "job_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } runID, err := OptionalIntParam(args, "run_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } failedOnly, err := OptionalParam[bool](args, "failed_only") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } returnContent, err := OptionalParam[bool](args, "return_content") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } tailLines, err := OptionalIntParam(args, "tail_lines") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Default to 500 lines if not specified if tailLines == 0 { @@ -1960,10 +1960,10 @@ For single job logs, provide job_id. For all failed jobs in a run, provide run_i // Validate parameters if failedOnly && runID == 0 { - return utils.NewToolResultError("run_id is required when failed_only is true"), nil, nil + return mcpresult.NewError("run_id is required when failed_only is true"), nil, nil } if !failedOnly && jobID == 0 { - return utils.NewToolResultError("job_id is required when failed_only is false"), nil, nil + return mcpresult.NewError("job_id is required when failed_only is false"), nil, nil } if failedOnly && runID > 0 { @@ -1974,7 +1974,7 @@ For single job logs, provide job_id. For all failed jobs in a run, provide run_i return handleSingleJobLogs(ctx, client, owner, repo, int64(jobID), returnContent, tailLines, deps.GetContentWindowSize()) } - return utils.NewToolResultError("Either job_id must be provided for single job logs, or run_id with failed_only=true for failed job logs"), nil, nil + return mcpresult.NewError("Either job_id must be provided for single job logs, or run_id with failed_only=true for failed job logs"), nil, nil }, ) tool.FeatureFlagDisable = FeatureFlagHoldbackConsolidatedActions @@ -2004,7 +2004,7 @@ func getWorkflow(ctx context.Context, client *github.Client, owner, repo, resour return nil, nil, fmt.Errorf("failed to marshal workflow: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } func getWorkflowRun(ctx context.Context, client *github.Client, owner, repo string, resourceID int64) (*mcp.CallToolResult, any, error) { @@ -2017,7 +2017,7 @@ func getWorkflowRun(ctx context.Context, client *github.Client, owner, repo stri if err != nil { return nil, nil, fmt.Errorf("failed to marshal workflow run: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } func getWorkflowJob(ctx context.Context, client *github.Client, owner, repo string, resourceID int64) (*mcp.CallToolResult, any, error) { @@ -2030,7 +2030,7 @@ func getWorkflowJob(ctx context.Context, client *github.Client, owner, repo stri if err != nil { return nil, nil, fmt.Errorf("failed to marshal workflow job: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } func listWorkflows(ctx context.Context, client *github.Client, owner, repo string, pagination PaginationParams) (*mcp.CallToolResult, any, error) { @@ -2050,13 +2050,13 @@ func listWorkflows(ctx context.Context, client *github.Client, owner, repo strin return nil, nil, fmt.Errorf("failed to marshal workflows: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } func listWorkflowRuns(ctx context.Context, client *github.Client, args map[string]any, owner, repo, resourceID string, pagination PaginationParams) (*mcp.CallToolResult, any, error) { filterArgs, err := OptionalParam[map[string]any](args, "workflow_runs_filter") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } filterArgsTyped := make(map[string]string) @@ -2100,13 +2100,13 @@ func listWorkflowRuns(ctx context.Context, client *github.Client, args map[strin return nil, nil, fmt.Errorf("failed to marshal workflow runs: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } func listWorkflowJobs(ctx context.Context, client *github.Client, args map[string]any, owner, repo string, resourceID int64, pagination PaginationParams) (*mcp.CallToolResult, any, error) { filterArgs, err := OptionalParam[map[string]any](args, "workflow_jobs_filter") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } filterArgsTyped := make(map[string]string) @@ -2139,7 +2139,7 @@ func listWorkflowJobs(ctx context.Context, client *github.Client, args map[strin return nil, nil, fmt.Errorf("failed to marshal workflow jobs: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } func listWorkflowArtifacts(ctx context.Context, client *github.Client, owner, repo string, resourceID int64, pagination PaginationParams) (*mcp.CallToolResult, any, error) { @@ -2159,7 +2159,7 @@ func listWorkflowArtifacts(ctx context.Context, client *github.Client, owner, re return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } func downloadWorkflowArtifact(ctx context.Context, client *github.Client, owner, repo string, resourceID int64) (*mcp.CallToolResult, any, error) { @@ -2183,7 +2183,7 @@ func downloadWorkflowArtifact(ctx context.Context, client *github.Client, owner, return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } func getWorkflowRunLogsURL(ctx context.Context, client *github.Client, owner, repo string, runID int64) (*mcp.CallToolResult, any, error) { @@ -2208,7 +2208,7 @@ func getWorkflowRunLogsURL(ctx context.Context, client *github.Client, owner, re return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } func getWorkflowRunUsage(ctx context.Context, client *github.Client, owner, repo string, resourceID int64) (*mcp.CallToolResult, any, error) { @@ -2223,7 +2223,7 @@ func getWorkflowRunUsage(ctx context.Context, client *github.Client, owner, repo return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } func runWorkflow(ctx context.Context, client *github.Client, owner, repo, workflowID, ref string, inputs map[string]interface{}) (*mcp.CallToolResult, any, error) { @@ -2264,7 +2264,7 @@ func runWorkflow(ctx context.Context, client *github.Client, owner, repo, workfl return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } func rerunWorkflowRun(ctx context.Context, client *github.Client, owner, repo string, runID int64) (*mcp.CallToolResult, any, error) { @@ -2286,7 +2286,7 @@ func rerunWorkflowRun(ctx context.Context, client *github.Client, owner, repo st return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } func rerunFailedJobs(ctx context.Context, client *github.Client, owner, repo string, runID int64) (*mcp.CallToolResult, any, error) { @@ -2308,7 +2308,7 @@ func rerunFailedJobs(ctx context.Context, client *github.Client, owner, repo str return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } func cancelWorkflowRun(ctx context.Context, client *github.Client, owner, repo string, runID int64) (*mcp.CallToolResult, any, error) { @@ -2333,7 +2333,7 @@ func cancelWorkflowRun(ctx context.Context, client *github.Client, owner, repo s return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } func deleteWorkflowRunLogs(ctx context.Context, client *github.Client, owner, repo string, runID int64) (*mcp.CallToolResult, any, error) { @@ -2355,5 +2355,5 @@ func deleteWorkflowRunLogs(ctx context.Context, client *github.Client, owner, re return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } diff --git a/pkg/github/code_scanning.go b/pkg/github/code_scanning.go index ccc00661a..fd1349ab4 100644 --- a/pkg/github/code_scanning.go +++ b/pkg/github/code_scanning.go @@ -8,9 +8,9 @@ import ( ghErrors "github.com/github/github-mcp-server/pkg/errors" "github.com/github/github-mcp-server/pkg/inventory" + "github.com/github/github-mcp-server/pkg/mcpresult" "github.com/github/github-mcp-server/pkg/scopes" "github.com/github/github-mcp-server/pkg/translations" - "github.com/github/github-mcp-server/pkg/utils" "github.com/google/go-github/v79/github" "github.com/google/jsonschema-go/jsonschema" "github.com/modelcontextprotocol/go-sdk/mcp" @@ -49,20 +49,20 @@ func GetCodeScanningAlert(t translations.TranslationHelperFunc) inventory.Server func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } alertNumber, err := RequiredInt(args, "alertNumber") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } alert, resp, err := client.CodeScanning.GetAlert(ctx, owner, repo, int64(alertNumber)) @@ -78,17 +78,17 @@ func GetCodeScanningAlert(t translations.TranslationHelperFunc) inventory.Server if resp.StatusCode != http.StatusOK { body, err := io.ReadAll(resp.Body) if err != nil { - return utils.NewToolResultErrorFromErr("failed to read response body", err), nil, nil + return mcpresult.NewErrorFromErr("failed to read response body", err), nil, nil } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to get alert", resp, body), nil, nil } r, err := json.Marshal(alert) if err != nil { - return utils.NewToolResultErrorFromErr("failed to marshal alert", err), nil, nil + return mcpresult.NewErrorFromErr("failed to marshal alert", err), nil, nil } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -141,32 +141,32 @@ func ListCodeScanningAlerts(t translations.TranslationHelperFunc) inventory.Serv func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } ref, err := OptionalParam[string](args, "ref") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } state, err := OptionalParam[string](args, "state") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } severity, err := OptionalParam[string](args, "severity") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } toolName, err := OptionalParam[string](args, "tool_name") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } alerts, resp, err := client.CodeScanning.ListAlertsForRepo(ctx, owner, repo, &github.AlertListOptions{Ref: ref, State: state, Severity: severity, ToolName: toolName}) if err != nil { @@ -181,17 +181,17 @@ func ListCodeScanningAlerts(t translations.TranslationHelperFunc) inventory.Serv if resp.StatusCode != http.StatusOK { body, err := io.ReadAll(resp.Body) if err != nil { - return utils.NewToolResultErrorFromErr("failed to read response body", err), nil, nil + return mcpresult.NewErrorFromErr("failed to read response body", err), nil, nil } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to list alerts", resp, body), nil, nil } r, err := json.Marshal(alerts) if err != nil { - return utils.NewToolResultErrorFromErr("failed to marshal alerts", err), nil, nil + return mcpresult.NewErrorFromErr("failed to marshal alerts", err), nil, nil } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } diff --git a/pkg/github/context_tools.go b/pkg/github/context_tools.go index 29fa2925d..8f86a7c95 100644 --- a/pkg/github/context_tools.go +++ b/pkg/github/context_tools.go @@ -7,9 +7,9 @@ import ( ghErrors "github.com/github/github-mcp-server/pkg/errors" "github.com/github/github-mcp-server/pkg/inventory" + "github.com/github/github-mcp-server/pkg/mcpresult" "github.com/github/github-mcp-server/pkg/scopes" "github.com/github/github-mcp-server/pkg/translations" - "github.com/github/github-mcp-server/pkg/utils" "github.com/google/jsonschema-go/jsonschema" "github.com/modelcontextprotocol/go-sdk/mcp" "github.com/shurcooL/githubv4" @@ -56,7 +56,7 @@ func GetMe(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, _ map[string]any) (*mcp.CallToolResult, any, error) { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } user, res, err := client.Users.Get(ctx, "") @@ -135,7 +135,7 @@ func GetTeams(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { user, err := OptionalParam[string](args, "user") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } var username string @@ -144,7 +144,7 @@ func GetTeams(t translations.TranslationHelperFunc) inventory.ServerTool { } else { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } userResp, res, err := client.Users.Get(ctx, "") @@ -160,7 +160,7 @@ func GetTeams(t translations.TranslationHelperFunc) inventory.ServerTool { gqlClient, err := deps.GetGQLClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub GQL client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub GQL client", err), nil, nil } var q struct { @@ -238,17 +238,17 @@ func GetTeamMembers(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { org, err := RequiredParam[string](args, "org") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } teamSlug, err := RequiredParam[string](args, "team_slug") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } gqlClient, err := deps.GetGQLClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub GQL client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub GQL client", err), nil, nil } var q struct { diff --git a/pkg/github/dependabot.go b/pkg/github/dependabot.go index b6b2eeaba..9ea41954d 100644 --- a/pkg/github/dependabot.go +++ b/pkg/github/dependabot.go @@ -9,9 +9,9 @@ import ( ghErrors "github.com/github/github-mcp-server/pkg/errors" "github.com/github/github-mcp-server/pkg/inventory" + "github.com/github/github-mcp-server/pkg/mcpresult" "github.com/github/github-mcp-server/pkg/scopes" "github.com/github/github-mcp-server/pkg/translations" - "github.com/github/github-mcp-server/pkg/utils" "github.com/google/go-github/v79/github" "github.com/google/jsonschema-go/jsonschema" "github.com/modelcontextprotocol/go-sdk/mcp" @@ -50,20 +50,20 @@ func GetDependabotAlert(t translations.TranslationHelperFunc) inventory.ServerTo func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } alertNumber, err := RequiredInt(args, "alertNumber") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, err + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, err } alert, resp, err := client.Dependabot.GetRepoAlert(ctx, owner, repo, alertNumber) @@ -79,17 +79,17 @@ func GetDependabotAlert(t translations.TranslationHelperFunc) inventory.ServerTo if resp.StatusCode != http.StatusOK { body, err := io.ReadAll(resp.Body) if err != nil { - return utils.NewToolResultErrorFromErr("failed to read response body", err), nil, err + return mcpresult.NewErrorFromErr("failed to read response body", err), nil, err } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to get alert", resp, body), nil, nil } r, err := json.Marshal(alert) if err != nil { - return utils.NewToolResultErrorFromErr("failed to marshal alert", err), nil, err + return mcpresult.NewErrorFromErr("failed to marshal alert", err), nil, err } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -134,24 +134,24 @@ func ListDependabotAlerts(t translations.TranslationHelperFunc) inventory.Server func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } state, err := OptionalParam[string](args, "state") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } severity, err := OptionalParam[string](args, "severity") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, err + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, err } alerts, resp, err := client.Dependabot.ListRepoAlerts(ctx, owner, repo, &github.ListAlertsOptions{ @@ -170,17 +170,17 @@ func ListDependabotAlerts(t translations.TranslationHelperFunc) inventory.Server if resp.StatusCode != http.StatusOK { body, err := io.ReadAll(resp.Body) if err != nil { - return utils.NewToolResultErrorFromErr("failed to read response body", err), nil, err + return mcpresult.NewErrorFromErr("failed to read response body", err), nil, err } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to list alerts", resp, body), nil, nil } r, err := json.Marshal(alerts) if err != nil { - return utils.NewToolResultErrorFromErr("failed to marshal alerts", err), nil, err + return mcpresult.NewErrorFromErr("failed to marshal alerts", err), nil, err } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } diff --git a/pkg/github/discussions.go b/pkg/github/discussions.go index c03670818..cde9200f9 100644 --- a/pkg/github/discussions.go +++ b/pkg/github/discussions.go @@ -6,9 +6,9 @@ import ( "fmt" "github.com/github/github-mcp-server/pkg/inventory" + "github.com/github/github-mcp-server/pkg/mcpresult" "github.com/github/github-mcp-server/pkg/scopes" "github.com/github/github-mcp-server/pkg/translations" - "github.com/github/github-mcp-server/pkg/utils" "github.com/go-viper/mapstructure/v2" "github.com/google/go-github/v79/github" "github.com/google/jsonschema-go/jsonschema" @@ -166,11 +166,11 @@ func ListDiscussions(t translations.TranslationHelperFunc) inventory.ServerTool func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := OptionalParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // when not provided, default to the .github repository // this will query discussions at the organisation level @@ -180,17 +180,17 @@ func ListDiscussions(t translations.TranslationHelperFunc) inventory.ServerTool category, err := OptionalParam[string](args, "category") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } orderBy, err := OptionalParam[string](args, "orderBy") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } direction, err := OptionalParam[string](args, "direction") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Get pagination parameters and convert to GraphQL format @@ -205,7 +205,7 @@ func ListDiscussions(t translations.TranslationHelperFunc) inventory.ServerTool client, err := deps.GetGQLClient(ctx) if err != nil { - return utils.NewToolResultError(fmt.Sprintf("failed to get GitHub GQL client: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("failed to get GitHub GQL client: %v", err)), nil, nil } var categoryID *githubv4.ID @@ -239,7 +239,7 @@ func ListDiscussions(t translations.TranslationHelperFunc) inventory.ServerTool discussionQuery := getQueryType(useOrdering, categoryID) if err := client.Query(ctx, discussionQuery, vars); err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Extract and convert all discussion nodes using the common interface @@ -271,7 +271,7 @@ func ListDiscussions(t translations.TranslationHelperFunc) inventory.ServerTool if err != nil { return nil, nil, fmt.Errorf("failed to marshal discussions: %w", err) } - return utils.NewToolResultText(string(out)), nil, nil + return mcpresult.NewText(string(out)), nil, nil }, ) } @@ -314,11 +314,11 @@ func GetDiscussion(t translations.TranslationHelperFunc) inventory.ServerTool { DiscussionNumber int32 } if err := mapstructure.Decode(args, ¶ms); err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetGQLClient(ctx) if err != nil { - return utils.NewToolResultError(fmt.Sprintf("failed to get GitHub GQL client: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("failed to get GitHub GQL client: %v", err)), nil, nil } var q struct { @@ -344,7 +344,7 @@ func GetDiscussion(t translations.TranslationHelperFunc) inventory.ServerTool { "discussionNumber": githubv4.Int(params.DiscussionNumber), } if err := client.Query(ctx, &q, vars); err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } d := q.Repository.Discussion @@ -375,7 +375,7 @@ func GetDiscussion(t translations.TranslationHelperFunc) inventory.ServerTool { return nil, nil, fmt.Errorf("failed to marshal discussion: %w", err) } - return utils.NewToolResultText(string(out)), nil, nil + return mcpresult.NewText(string(out)), nil, nil }, ) } @@ -418,7 +418,7 @@ func GetDiscussionComments(t translations.TranslationHelperFunc) inventory.Serve DiscussionNumber int32 } if err := mapstructure.Decode(args, ¶ms); err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Get pagination parameters and convert to GraphQL format @@ -444,7 +444,7 @@ func GetDiscussionComments(t translations.TranslationHelperFunc) inventory.Serve client, err := deps.GetGQLClient(ctx) if err != nil { - return utils.NewToolResultError(fmt.Sprintf("failed to get GitHub GQL client: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("failed to get GitHub GQL client: %v", err)), nil, nil } var q struct { @@ -477,7 +477,7 @@ func GetDiscussionComments(t translations.TranslationHelperFunc) inventory.Serve vars["after"] = (*githubv4.String)(nil) } if err := client.Query(ctx, &q, vars); err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } var comments []*github.IssueComment @@ -502,7 +502,7 @@ func GetDiscussionComments(t translations.TranslationHelperFunc) inventory.Serve return nil, nil, fmt.Errorf("failed to marshal comments: %w", err) } - return utils.NewToolResultText(string(out)), nil, nil + return mcpresult.NewText(string(out)), nil, nil }, ) } @@ -536,11 +536,11 @@ func ListDiscussionCategories(t translations.TranslationHelperFunc) inventory.Se func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := OptionalParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // when not provided, default to the .github repository // this will query discussion categories at the organisation level @@ -550,7 +550,7 @@ func ListDiscussionCategories(t translations.TranslationHelperFunc) inventory.Se client, err := deps.GetGQLClient(ctx) if err != nil { - return utils.NewToolResultError(fmt.Sprintf("failed to get GitHub GQL client: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("failed to get GitHub GQL client: %v", err)), nil, nil } var q struct { @@ -576,7 +576,7 @@ func ListDiscussionCategories(t translations.TranslationHelperFunc) inventory.Se "first": githubv4.Int(25), } if err := client.Query(ctx, &q, vars); err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } var categories []map[string]string @@ -603,7 +603,7 @@ func ListDiscussionCategories(t translations.TranslationHelperFunc) inventory.Se if err != nil { return nil, nil, fmt.Errorf("failed to marshal discussion categories: %w", err) } - return utils.NewToolResultText(string(out)), nil, nil + return mcpresult.NewText(string(out)), nil, nil }, ) } diff --git a/pkg/github/dynamic_tools.go b/pkg/github/dynamic_tools.go index 5c7d31d4e..d47477662 100644 --- a/pkg/github/dynamic_tools.go +++ b/pkg/github/dynamic_tools.go @@ -6,8 +6,8 @@ import ( "fmt" "github.com/github/github-mcp-server/pkg/inventory" + "github.com/github/github-mcp-server/pkg/mcpresult" "github.com/github/github-mcp-server/pkg/translations" - "github.com/github/github-mcp-server/pkg/utils" "github.com/google/jsonschema-go/jsonschema" "github.com/modelcontextprotocol/go-sdk/mcp" ) @@ -84,17 +84,17 @@ func EnableToolset(r *inventory.Inventory) inventory.ServerTool { return func(_ context.Context, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { toolsetName, err := RequiredParam[string](args, "toolset") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } toolsetID := inventory.ToolsetID(toolsetName) if !deps.Inventory.HasToolset(toolsetID) { - return utils.NewToolResultError(fmt.Sprintf("Toolset %s not found", toolsetName)), nil, nil + return mcpresult.NewError(fmt.Sprintf("Toolset %s not found", toolsetName)), nil, nil } if deps.Inventory.IsToolsetEnabled(toolsetID) { - return utils.NewToolResultText(fmt.Sprintf("Toolset %s is already enabled", toolsetName)), nil, nil + return mcpresult.NewText(fmt.Sprintf("Toolset %s is already enabled", toolsetName)), nil, nil } // Mark the toolset as enabled so IsToolsetEnabled returns true @@ -106,7 +106,7 @@ func EnableToolset(r *inventory.Inventory) inventory.ServerTool { st.RegisterFunc(deps.Server, deps.ToolDeps) } - return utils.NewToolResultText(fmt.Sprintf("Toolset %s enabled with %d tools", toolsetName, len(toolsForToolset))), nil, nil + return mcpresult.NewText(fmt.Sprintf("Toolset %s enabled with %d tools", toolsetName, len(toolsForToolset))), nil, nil } }, ) @@ -149,7 +149,7 @@ func ListAvailableToolsets() inventory.ServerTool { return nil, nil, fmt.Errorf("failed to marshal features: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } }, ) @@ -182,13 +182,13 @@ func GetToolsetsTools(r *inventory.Inventory) inventory.ServerTool { return func(_ context.Context, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { toolsetName, err := RequiredParam[string](args, "toolset") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } toolsetID := inventory.ToolsetID(toolsetName) if !deps.Inventory.HasToolset(toolsetID) { - return utils.NewToolResultError(fmt.Sprintf("Toolset %s not found", toolsetName)), nil, nil + return mcpresult.NewError(fmt.Sprintf("Toolset %s not found", toolsetName)), nil, nil } // Get all tools for this toolset (ignoring current filters for discovery) @@ -210,7 +210,7 @@ func GetToolsetsTools(r *inventory.Inventory) inventory.ServerTool { return nil, nil, fmt.Errorf("failed to marshal features: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } }, ) diff --git a/pkg/github/feature_flags_test.go b/pkg/github/feature_flags_test.go index fb50448af..779f97080 100644 --- a/pkg/github/feature_flags_test.go +++ b/pkg/github/feature_flags_test.go @@ -5,6 +5,7 @@ import ( "encoding/json" "testing" + "github.com/github/github-mcp-server/pkg/mcpresult" "github.com/github/github-mcp-server/pkg/translations" "github.com/modelcontextprotocol/go-sdk/mcp" "github.com/stretchr/testify/assert" @@ -12,7 +13,6 @@ import ( "github.com/github/github-mcp-server/pkg/inventory" "github.com/github/github-mcp-server/pkg/scopes" - "github.com/github/github-mcp-server/pkg/utils" ) // RemoteMCPEnthusiasticGreeting is a dummy test feature flag . @@ -56,10 +56,10 @@ func HelloWorldTool(t translations.TranslationHelperFunc) inventory.ServerTool { jsonBytes, err := json.Marshal(response) if err != nil { - return utils.NewToolResultError("failed to marshal response"), nil, nil + return mcpresult.NewError("failed to marshal response"), nil, nil } - return utils.NewToolResultText(string(jsonBytes)), nil, nil + return mcpresult.NewText(string(jsonBytes)), nil, nil }, ) } diff --git a/pkg/github/gists.go b/pkg/github/gists.go index 0f43ebdf9..557850088 100644 --- a/pkg/github/gists.go +++ b/pkg/github/gists.go @@ -9,9 +9,9 @@ import ( ghErrors "github.com/github/github-mcp-server/pkg/errors" "github.com/github/github-mcp-server/pkg/inventory" + "github.com/github/github-mcp-server/pkg/mcpresult" "github.com/github/github-mcp-server/pkg/scopes" "github.com/github/github-mcp-server/pkg/translations" - "github.com/github/github-mcp-server/pkg/utils" "github.com/google/go-github/v79/github" "github.com/google/jsonschema-go/jsonschema" "github.com/modelcontextprotocol/go-sdk/mcp" @@ -46,17 +46,17 @@ func ListGists(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { username, err := OptionalParam[string](args, "username") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } since, err := OptionalParam[string](args, "since") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } pagination, err := OptionalPaginationParams(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } opts := &github.GistListOptions{ @@ -70,14 +70,14 @@ func ListGists(t translations.TranslationHelperFunc) inventory.ServerTool { if since != "" { sinceTime, err := parseISOTimestamp(since) if err != nil { - return utils.NewToolResultError(fmt.Sprintf("invalid since timestamp: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("invalid since timestamp: %v", err)), nil, nil } opts.Since = sinceTime } client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } gists, resp, err := client.Gists.List(ctx, username, opts) @@ -89,17 +89,17 @@ func ListGists(t translations.TranslationHelperFunc) inventory.ServerTool { if resp.StatusCode != http.StatusOK { body, err := io.ReadAll(resp.Body) if err != nil { - return utils.NewToolResultErrorFromErr("failed to read response body", err), nil, nil + return mcpresult.NewErrorFromErr("failed to read response body", err), nil, nil } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to list gists", resp, body), nil, nil } r, err := json.Marshal(gists) if err != nil { - return utils.NewToolResultErrorFromErr("failed to marshal response", err), nil, nil + return mcpresult.NewErrorFromErr("failed to marshal response", err), nil, nil } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -130,12 +130,12 @@ func GetGist(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { gistID, err := RequiredParam[string](args, "gist_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } gist, resp, err := client.Gists.Get(ctx, gistID) @@ -147,17 +147,17 @@ func GetGist(t translations.TranslationHelperFunc) inventory.ServerTool { if resp.StatusCode != http.StatusOK { body, err := io.ReadAll(resp.Body) if err != nil { - return utils.NewToolResultErrorFromErr("failed to read response body", err), nil, nil + return mcpresult.NewErrorFromErr("failed to read response body", err), nil, nil } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to get gist", resp, body), nil, nil } r, err := json.Marshal(gist) if err != nil { - return utils.NewToolResultErrorFromErr("failed to marshal response", err), nil, nil + return mcpresult.NewErrorFromErr("failed to marshal response", err), nil, nil } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -201,22 +201,22 @@ func CreateGist(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { description, err := OptionalParam[string](args, "description") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } filename, err := RequiredParam[string](args, "filename") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } content, err := RequiredParam[string](args, "content") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } public, err := OptionalParam[bool](args, "public") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } files := make(map[github.GistFilename]github.GistFile) @@ -233,7 +233,7 @@ func CreateGist(t translations.TranslationHelperFunc) inventory.ServerTool { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } createdGist, resp, err := client.Gists.Create(ctx, gist) @@ -245,7 +245,7 @@ func CreateGist(t translations.TranslationHelperFunc) inventory.ServerTool { if resp.StatusCode != http.StatusCreated { body, err := io.ReadAll(resp.Body) if err != nil { - return utils.NewToolResultErrorFromErr("failed to read response body", err), nil, nil + return mcpresult.NewErrorFromErr("failed to read response body", err), nil, nil } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to create gist", resp, body), nil, nil } @@ -257,10 +257,10 @@ func CreateGist(t translations.TranslationHelperFunc) inventory.ServerTool { r, err := json.Marshal(minimalResponse) if err != nil { - return utils.NewToolResultErrorFromErr("failed to marshal response", err), nil, nil + return mcpresult.NewErrorFromErr("failed to marshal response", err), nil, nil } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -303,22 +303,22 @@ func UpdateGist(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { gistID, err := RequiredParam[string](args, "gist_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } description, err := OptionalParam[string](args, "description") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } filename, err := RequiredParam[string](args, "filename") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } content, err := RequiredParam[string](args, "content") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } files := make(map[github.GistFilename]github.GistFile) @@ -334,7 +334,7 @@ func UpdateGist(t translations.TranslationHelperFunc) inventory.ServerTool { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } updatedGist, resp, err := client.Gists.Edit(ctx, gistID, gist) @@ -346,7 +346,7 @@ func UpdateGist(t translations.TranslationHelperFunc) inventory.ServerTool { if resp.StatusCode != http.StatusOK { body, err := io.ReadAll(resp.Body) if err != nil { - return utils.NewToolResultErrorFromErr("failed to read response body", err), nil, nil + return mcpresult.NewErrorFromErr("failed to read response body", err), nil, nil } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to update gist", resp, body), nil, nil } @@ -358,10 +358,10 @@ func UpdateGist(t translations.TranslationHelperFunc) inventory.ServerTool { r, err := json.Marshal(minimalResponse) if err != nil { - return utils.NewToolResultErrorFromErr("failed to marshal response", err), nil, nil + return mcpresult.NewErrorFromErr("failed to marshal response", err), nil, nil } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } diff --git a/pkg/github/git.go b/pkg/github/git.go index ec7159b9b..8efc1b009 100644 --- a/pkg/github/git.go +++ b/pkg/github/git.go @@ -8,9 +8,9 @@ import ( ghErrors "github.com/github/github-mcp-server/pkg/errors" "github.com/github/github-mcp-server/pkg/inventory" + "github.com/github/github-mcp-server/pkg/mcpresult" "github.com/github/github-mcp-server/pkg/scopes" "github.com/github/github-mcp-server/pkg/translations" - "github.com/github/github-mcp-server/pkg/utils" "github.com/google/go-github/v79/github" "github.com/google/jsonschema-go/jsonschema" "github.com/modelcontextprotocol/go-sdk/mcp" @@ -81,28 +81,28 @@ func GetRepositoryTree(t translations.TranslationHelperFunc) inventory.ServerToo func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } treeSHA, err := OptionalParam[string](args, "tree_sha") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } recursive, err := OptionalBoolParamWithDefault(args, "recursive", false) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } pathFilter, err := OptionalParam[string](args, "path_filter") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultError("failed to get GitHub client"), nil, nil + return mcpresult.NewError("failed to get GitHub client"), nil, nil } // If no tree_sha is provided, use the repository's default branch @@ -171,7 +171,7 @@ func GetRepositoryTree(t translations.TranslationHelperFunc) inventory.ServerToo return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } diff --git a/pkg/github/issues.go b/pkg/github/issues.go index 62e1a0bac..e9ade3cfe 100644 --- a/pkg/github/issues.go +++ b/pkg/github/issues.go @@ -12,11 +12,11 @@ import ( ghErrors "github.com/github/github-mcp-server/pkg/errors" "github.com/github/github-mcp-server/pkg/inventory" "github.com/github/github-mcp-server/pkg/lockdown" + "github.com/github/github-mcp-server/pkg/mcpresult" "github.com/github/github-mcp-server/pkg/octicons" "github.com/github/github-mcp-server/pkg/sanitize" "github.com/github/github-mcp-server/pkg/scopes" "github.com/github/github-mcp-server/pkg/translations" - "github.com/github/github-mcp-server/pkg/utils" "github.com/go-viper/mapstructure/v2" "github.com/google/go-github/v79/github" "github.com/google/jsonschema-go/jsonschema" @@ -279,35 +279,35 @@ Options are: func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { method, err := RequiredParam[string](args, "method") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } issueNumber, err := RequiredInt(args, "issue_number") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } pagination, err := OptionalPaginationParams(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } gqlClient, err := deps.GetGQLClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub graphql client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub graphql client", err), nil, nil } switch method { @@ -324,7 +324,7 @@ Options are: result, err := GetIssueLabels(ctx, gqlClient, owner, repo, issueNumber) return result, nil, err default: - return utils.NewToolResultError(fmt.Sprintf("unknown method: %s", method)), nil, nil + return mcpresult.NewError(fmt.Sprintf("unknown method: %s", method)), nil, nil } }) } @@ -352,10 +352,10 @@ func GetIssue(ctx context.Context, client *github.Client, cache *lockdown.RepoAc if login != "" { isSafeContent, err := cache.IsSafeContent(ctx, login, owner, repo) if err != nil { - return utils.NewToolResultError(fmt.Sprintf("failed to check lockdown mode: %v", err)), nil + return mcpresult.NewError(fmt.Sprintf("failed to check lockdown mode: %v", err)), nil } if !isSafeContent { - return utils.NewToolResultError("access to issue details is restricted by lockdown mode"), nil + return mcpresult.NewError("access to issue details is restricted by lockdown mode"), nil } } } @@ -375,7 +375,7 @@ func GetIssue(ctx context.Context, client *github.Client, cache *lockdown.RepoAc return nil, fmt.Errorf("failed to marshal issue: %w", err) } - return utils.NewToolResultText(string(r)), nil + return mcpresult.NewText(string(r)), nil } func GetIssueComments(ctx context.Context, client *github.Client, cache *lockdown.RepoAccessCache, owner string, repo string, issueNumber int, pagination PaginationParams, flags FeatureFlags) (*mcp.CallToolResult, error) { @@ -415,7 +415,7 @@ func GetIssueComments(ctx context.Context, client *github.Client, cache *lockdow } isSafeContent, err := cache.IsSafeContent(ctx, login, owner, repo) if err != nil { - return utils.NewToolResultError(fmt.Sprintf("failed to check lockdown mode: %v", err)), nil + return mcpresult.NewError(fmt.Sprintf("failed to check lockdown mode: %v", err)), nil } if isSafeContent { filteredComments = append(filteredComments, comment) @@ -429,7 +429,7 @@ func GetIssueComments(ctx context.Context, client *github.Client, cache *lockdow return nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil + return mcpresult.NewText(string(r)), nil } func GetSubIssues(ctx context.Context, client *github.Client, cache *lockdown.RepoAccessCache, owner string, repo string, issueNumber int, pagination PaginationParams, featureFlags FeatureFlags) (*mcp.CallToolResult, error) { @@ -475,7 +475,7 @@ func GetSubIssues(ctx context.Context, client *github.Client, cache *lockdown.Re } isSafeContent, err := cache.IsSafeContent(ctx, login, owner, repo) if err != nil { - return utils.NewToolResultError(fmt.Sprintf("failed to check lockdown mode: %v", err)), nil + return mcpresult.NewError(fmt.Sprintf("failed to check lockdown mode: %v", err)), nil } if isSafeContent { filteredSubIssues = append(filteredSubIssues, subIssue) @@ -489,7 +489,7 @@ func GetSubIssues(ctx context.Context, client *github.Client, cache *lockdown.Re return nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil + return mcpresult.NewText(string(r)), nil } func GetIssueLabels(ctx context.Context, client *githubv4.Client, owner string, repo string, issueNumber int) (*mcp.CallToolResult, error) { @@ -541,7 +541,7 @@ func GetIssueLabels(ctx context.Context, client *githubv4.Client, owner string, return nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(out)), nil + return mcpresult.NewText(string(out)), nil } @@ -571,33 +571,33 @@ func ListIssueTypes(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } issueTypes, resp, err := client.Organizations.ListIssueTypes(ctx, owner) if err != nil { - return utils.NewToolResultErrorFromErr("failed to list issue types", err), nil, nil + return mcpresult.NewErrorFromErr("failed to list issue types", err), nil, nil } defer func() { _ = resp.Body.Close() }() if resp.StatusCode != http.StatusOK { body, err := io.ReadAll(resp.Body) if err != nil { - return utils.NewToolResultErrorFromErr("failed to read response body", err), nil, nil + return mcpresult.NewErrorFromErr("failed to read response body", err), nil, nil } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to list issue types", resp, body), nil, nil } r, err := json.Marshal(issueTypes) if err != nil { - return utils.NewToolResultErrorFromErr("failed to marshal issue types", err), nil, nil + return mcpresult.NewErrorFromErr("failed to marshal issue types", err), nil, nil } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }) } @@ -639,19 +639,19 @@ func AddIssueComment(t translations.TranslationHelperFunc) inventory.ServerTool func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } issueNumber, err := RequiredInt(args, "issue_number") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } body, err := RequiredParam[string](args, "body") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } comment := &github.IssueComment{ @@ -660,28 +660,28 @@ func AddIssueComment(t translations.TranslationHelperFunc) inventory.ServerTool client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } createdComment, resp, err := client.Issues.CreateComment(ctx, owner, repo, issueNumber, comment) if err != nil { - return utils.NewToolResultErrorFromErr("failed to create comment", err), nil, nil + return mcpresult.NewErrorFromErr("failed to create comment", err), nil, nil } defer func() { _ = resp.Body.Close() }() if resp.StatusCode != http.StatusCreated { body, err := io.ReadAll(resp.Body) if err != nil { - return utils.NewToolResultErrorFromErr("failed to read response body", err), nil, nil + return mcpresult.NewErrorFromErr("failed to read response body", err), nil, nil } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to create comment", resp, body), nil, nil } r, err := json.Marshal(createdComment) if err != nil { - return utils.NewToolResultErrorFromErr("failed to marshal response", err), nil, nil + return mcpresult.NewErrorFromErr("failed to marshal response", err), nil, nil } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }) } @@ -744,41 +744,41 @@ Options are: func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { method, err := RequiredParam[string](args, "method") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } issueNumber, err := RequiredInt(args, "issue_number") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } subIssueID, err := RequiredInt(args, "sub_issue_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } replaceParent, err := OptionalParam[bool](args, "replace_parent") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } afterID, err := OptionalIntParam(args, "after_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } beforeID, err := OptionalIntParam(args, "before_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } switch strings.ToLower(method) { @@ -794,7 +794,7 @@ Options are: result, err := ReprioritizeSubIssue(ctx, client, owner, repo, issueNumber, subIssueID, afterID, beforeID) return result, nil, err default: - return utils.NewToolResultError(fmt.Sprintf("unknown method: %s", method)), nil, nil + return mcpresult.NewError(fmt.Sprintf("unknown method: %s", method)), nil, nil } }) } @@ -829,7 +829,7 @@ func AddSubIssue(ctx context.Context, client *github.Client, owner string, repo return nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil + return mcpresult.NewText(string(r)), nil } @@ -861,16 +861,16 @@ func RemoveSubIssue(ctx context.Context, client *github.Client, owner string, re return nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil + return mcpresult.NewText(string(r)), nil } func ReprioritizeSubIssue(ctx context.Context, client *github.Client, owner string, repo string, issueNumber int, subIssueID int, afterID int, beforeID int) (*mcp.CallToolResult, error) { // Validate that either after_id or before_id is specified, but not both if afterID == 0 && beforeID == 0 { - return utils.NewToolResultError("either after_id or before_id must be specified"), nil + return mcpresult.NewError("either after_id or before_id must be specified"), nil } if afterID != 0 && beforeID != 0 { - return utils.NewToolResultError("only one of after_id or before_id should be specified, not both"), nil + return mcpresult.NewError("only one of after_id or before_id should be specified, not both"), nil } subIssueRequest := github.SubIssueRequest{ @@ -910,7 +910,7 @@ func ReprioritizeSubIssue(ctx context.Context, client *github.Client, owner stri return nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil + return mcpresult.NewText(string(r)), nil } // SearchIssues creates a tool to search for issues. @@ -1062,44 +1062,44 @@ Options are: func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { method, err := RequiredParam[string](args, "method") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } title, err := OptionalParam[string](args, "title") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Optional parameters body, err := OptionalParam[string](args, "body") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Get assignees assignees, err := OptionalStringArrayParam(args, "assignees") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Get labels labels, err := OptionalStringArrayParam(args, "labels") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Get optional milestone milestone, err := OptionalIntParam(args, "milestone") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } var milestoneNum int @@ -1110,36 +1110,36 @@ Options are: // Get optional type issueType, err := OptionalParam[string](args, "type") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Handle state, state_reason and duplicateOf parameters state, err := OptionalParam[string](args, "state") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } stateReason, err := OptionalParam[string](args, "state_reason") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } duplicateOf, err := OptionalIntParam(args, "duplicate_of") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } if duplicateOf != 0 && stateReason != "duplicate" { - return utils.NewToolResultError("duplicate_of can only be used when state_reason is 'duplicate'"), nil, nil + return mcpresult.NewError("duplicate_of can only be used when state_reason is 'duplicate'"), nil, nil } client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } gqlClient, err := deps.GetGQLClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GraphQL client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GraphQL client", err), nil, nil } switch method { @@ -1149,19 +1149,19 @@ Options are: case "update": issueNumber, err := RequiredInt(args, "issue_number") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } result, err := UpdateIssue(ctx, client, gqlClient, owner, repo, issueNumber, title, body, assignees, labels, milestoneNum, issueType, state, stateReason, duplicateOf) return result, nil, err default: - return utils.NewToolResultError("invalid method, must be either 'create' or 'update'"), nil, nil + return mcpresult.NewError("invalid method, must be either 'create' or 'update'"), nil, nil } }) } func CreateIssue(ctx context.Context, client *github.Client, owner string, repo string, title string, body string, assignees []string, labels []string, milestoneNum int, issueType string) (*mcp.CallToolResult, error) { if title == "" { - return utils.NewToolResultError("missing required parameter: title"), nil + return mcpresult.NewError("missing required parameter: title"), nil } // Create the issue request @@ -1193,7 +1193,7 @@ func CreateIssue(ctx context.Context, client *github.Client, owner string, repo if resp.StatusCode != http.StatusCreated { body, err := io.ReadAll(resp.Body) if err != nil { - return utils.NewToolResultErrorFromErr("failed to read response body", err), nil + return mcpresult.NewErrorFromErr("failed to read response body", err), nil } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to create issue", resp, body), nil } @@ -1206,10 +1206,10 @@ func CreateIssue(ctx context.Context, client *github.Client, owner string, repo r, err := json.Marshal(minimalResponse) if err != nil { - return utils.NewToolResultErrorFromErr("failed to marshal response", err), nil + return mcpresult.NewErrorFromErr("failed to marshal response", err), nil } - return utils.NewToolResultText(string(r)), nil + return mcpresult.NewText(string(r)), nil } func UpdateIssue(ctx context.Context, client *github.Client, gqlClient *githubv4.Client, owner string, repo string, issueNumber int, title string, body string, assignees []string, labels []string, milestoneNum int, issueType string, state string, stateReason string, duplicateOf int) (*mcp.CallToolResult, error) { @@ -1263,7 +1263,7 @@ func UpdateIssue(ctx context.Context, client *github.Client, gqlClient *githubv4 if state != "" { // Mandate specifying duplicateOf when trying to close as duplicate if state == "closed" && stateReason == "duplicate" && duplicateOf == 0 { - return utils.NewToolResultError("duplicate_of must be provided when state_reason is 'duplicate'"), nil + return mcpresult.NewError("duplicate_of must be provided when state_reason is 'duplicate'"), nil } // Get target issue ID (and duplicate issue ID if needed) @@ -1334,7 +1334,7 @@ func UpdateIssue(ctx context.Context, client *github.Client, gqlClient *githubv4 return nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil + return mcpresult.NewText(string(r)), nil } // ListIssues creates a tool to list and filter repository issues @@ -1396,17 +1396,17 @@ func ListIssues(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Set optional parameters if provided state, err := OptionalParam[string](args, "state") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Normalize and filter by state @@ -1423,17 +1423,17 @@ func ListIssues(t translations.TranslationHelperFunc) inventory.ServerTool { // Get labels labels, err := OptionalStringArrayParam(args, "labels") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } orderBy, err := OptionalParam[string](args, "orderBy") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } direction, err := OptionalParam[string](args, "direction") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Normalize and validate orderBy @@ -1456,7 +1456,7 @@ func ListIssues(t translations.TranslationHelperFunc) inventory.ServerTool { since, err := OptionalParam[string](args, "since") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // There are two optional parameters: since and labels. @@ -1465,7 +1465,7 @@ func ListIssues(t translations.TranslationHelperFunc) inventory.ServerTool { if since != "" { sinceTime, err = parseISOTimestamp(since) if err != nil { - return utils.NewToolResultError(fmt.Sprintf("failed to list issues: %s", err.Error())), nil, nil + return mcpresult.NewError(fmt.Sprintf("failed to list issues: %s", err.Error())), nil, nil } hasSince = true } @@ -1479,7 +1479,7 @@ func ListIssues(t translations.TranslationHelperFunc) inventory.ServerTool { // Check if someone tried to use page-based pagination instead of cursor-based if _, pageProvided := args["page"]; pageProvided { - return utils.NewToolResultError("This tool uses cursor-based pagination. Use the 'after' parameter with the 'endCursor' value from the previous response instead of 'page'."), nil, nil + return mcpresult.NewError("This tool uses cursor-based pagination. Use the 'after' parameter with the 'endCursor' value from the previous response instead of 'page'."), nil, nil } // Check if pagination parameters were explicitly provided @@ -1499,7 +1499,7 @@ func ListIssues(t translations.TranslationHelperFunc) inventory.ServerTool { client, err := deps.GetGQLClient(ctx) if err != nil { - return utils.NewToolResultError(fmt.Sprintf("failed to get GitHub GQL client: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("failed to get GitHub GQL client: %v", err)), nil, nil } vars := map[string]interface{}{ @@ -1575,7 +1575,7 @@ func ListIssues(t translations.TranslationHelperFunc) inventory.ServerTool { if err != nil { return nil, nil, fmt.Errorf("failed to marshal issues: %w", err) } - return utils.NewToolResultText(string(out)), nil, nil + return mcpresult.NewText(string(out)), nil, nil }) } @@ -1766,7 +1766,7 @@ func AssignCopilotToIssue(t translations.TranslationHelperFunc) inventory.Server CustomInstructions string `mapstructure:"custom_instructions"` } if err := mapstructure.Decode(args, ¶ms); err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetGQLClient(ctx) @@ -1829,7 +1829,7 @@ func AssignCopilotToIssue(t translations.TranslationHelperFunc) inventory.Server // If we didn't find the copilot bot, we can't proceed any further. if copilotAssignee == nil { // The e2e tests depend upon this specific message to skip the test. - return utils.NewToolResultError("copilot isn't available as an assignee for this issue. Please inform the user to visit https://docs.github.com/en/copilot/using-github-copilot/using-copilot-coding-agent-to-work-on-tasks/about-assigning-tasks-to-copilot for more information."), nil, nil + return mcpresult.NewError("copilot isn't available as an assignee for this issue. Please inform the user to visit https://docs.github.com/en/copilot/using-github-copilot/using-copilot-coding-agent-to-work-on-tasks/about-assigning-tasks-to-copilot for more information."), nil, nil } // Next, get the issue ID and repository ID @@ -1984,10 +1984,10 @@ func AssignCopilotToIssue(t translations.TranslationHelperFunc) inventory.Server r, err := json.Marshal(result) if err != nil { - return utils.NewToolResultError(fmt.Sprintf("failed to marshal response: %s", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("failed to marshal response: %s", err)), nil, nil } - return utils.NewToolResultText(string(r)), result, nil + return mcpresult.NewText(string(r)), result, nil }) } diff --git a/pkg/github/labels.go b/pkg/github/labels.go index 0dbb622d9..3903142df 100644 --- a/pkg/github/labels.go +++ b/pkg/github/labels.go @@ -8,9 +8,9 @@ import ( ghErrors "github.com/github/github-mcp-server/pkg/errors" "github.com/github/github-mcp-server/pkg/inventory" + "github.com/github/github-mcp-server/pkg/mcpresult" "github.com/github/github-mcp-server/pkg/scopes" "github.com/github/github-mcp-server/pkg/translations" - "github.com/github/github-mcp-server/pkg/utils" "github.com/google/jsonschema-go/jsonschema" "github.com/modelcontextprotocol/go-sdk/mcp" "github.com/shurcooL/githubv4" @@ -50,17 +50,17 @@ func GetLabel(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } name, err := RequiredParam[string](args, "name") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } var query struct { @@ -90,7 +90,7 @@ func GetLabel(t translations.TranslationHelperFunc) inventory.ServerTool { } if query.Repository.Label.Name == "" { - return utils.NewToolResultError(fmt.Sprintf("label '%s' not found in %s/%s", name, owner, repo)), nil, nil + return mcpresult.NewError(fmt.Sprintf("label '%s' not found in %s/%s", name, owner, repo)), nil, nil } label := map[string]any{ @@ -105,7 +105,7 @@ func GetLabel(t translations.TranslationHelperFunc) inventory.ServerTool { return nil, nil, fmt.Errorf("failed to marshal label: %w", err) } - return utils.NewToolResultText(string(out)), nil, nil + return mcpresult.NewText(string(out)), nil, nil }, ) } @@ -148,12 +148,12 @@ func ListLabels(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetGQLClient(ctx) @@ -204,7 +204,7 @@ func ListLabels(t translations.TranslationHelperFunc) inventory.ServerTool { return nil, nil, fmt.Errorf("failed to marshal labels: %w", err) } - return utils.NewToolResultText(string(out)), nil, nil + return mcpresult.NewText(string(out)), nil, nil }, ) } @@ -261,23 +261,23 @@ func LabelWrite(t translations.TranslationHelperFunc) inventory.ServerTool { // Get and validate required parameters method, err := RequiredParam[string](args, "method") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } method = strings.ToLower(method) owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } name, err := RequiredParam[string](args, "name") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Get optional parameters @@ -294,7 +294,7 @@ func LabelWrite(t translations.TranslationHelperFunc) inventory.ServerTool { case "create": // Validate required params for create if color == "" { - return utils.NewToolResultError("color is required for create"), nil, nil + return mcpresult.NewError("color is required for create"), nil, nil } // Get repository ID @@ -326,18 +326,18 @@ func LabelWrite(t translations.TranslationHelperFunc) inventory.ServerTool { return ghErrors.NewGitHubGraphQLErrorResponse(ctx, "Failed to create label", err), nil, nil } - return utils.NewToolResultText(fmt.Sprintf("label '%s' created successfully", mutation.CreateLabel.Label.Name)), nil, nil + return mcpresult.NewText(fmt.Sprintf("label '%s' created successfully", mutation.CreateLabel.Label.Name)), nil, nil case "update": // Validate required params for update if newName == "" && color == "" && description == "" { - return utils.NewToolResultError("at least one of new_name, color, or description must be provided for update"), nil, nil + return mcpresult.NewError("at least one of new_name, color, or description must be provided for update"), nil, nil } // Get the label ID labelID, err := getLabelID(ctx, client, owner, repo, name) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } input := githubv4.UpdateLabelInput{ @@ -369,13 +369,13 @@ func LabelWrite(t translations.TranslationHelperFunc) inventory.ServerTool { return ghErrors.NewGitHubGraphQLErrorResponse(ctx, "Failed to update label", err), nil, nil } - return utils.NewToolResultText(fmt.Sprintf("label '%s' updated successfully", mutation.UpdateLabel.Label.Name)), nil, nil + return mcpresult.NewText(fmt.Sprintf("label '%s' updated successfully", mutation.UpdateLabel.Label.Name)), nil, nil case "delete": // Get the label ID labelID, err := getLabelID(ctx, client, owner, repo, name) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } input := githubv4.DeleteLabelInput{ @@ -392,10 +392,10 @@ func LabelWrite(t translations.TranslationHelperFunc) inventory.ServerTool { return ghErrors.NewGitHubGraphQLErrorResponse(ctx, "Failed to delete label", err), nil, nil } - return utils.NewToolResultText(fmt.Sprintf("label '%s' deleted successfully", name)), nil, nil + return mcpresult.NewText(fmt.Sprintf("label '%s' deleted successfully", name)), nil, nil default: - return utils.NewToolResultError(fmt.Sprintf("unknown method: %s. Supported methods are: create, update, delete", method)), nil, nil + return mcpresult.NewError(fmt.Sprintf("unknown method: %s. Supported methods are: create, update, delete", method)), nil, nil } }, ) diff --git a/pkg/github/notifications.go b/pkg/github/notifications.go index 1d695beb3..22925165f 100644 --- a/pkg/github/notifications.go +++ b/pkg/github/notifications.go @@ -11,9 +11,9 @@ import ( ghErrors "github.com/github/github-mcp-server/pkg/errors" "github.com/github/github-mcp-server/pkg/inventory" + "github.com/github/github-mcp-server/pkg/mcpresult" "github.com/github/github-mcp-server/pkg/scopes" "github.com/github/github-mcp-server/pkg/translations" - "github.com/github/github-mcp-server/pkg/utils" "github.com/google/go-github/v79/github" "github.com/google/jsonschema-go/jsonschema" "github.com/modelcontextprotocol/go-sdk/mcp" @@ -67,36 +67,36 @@ func ListNotifications(t translations.TranslationHelperFunc) inventory.ServerToo func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } filter, err := OptionalParam[string](args, "filter") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } since, err := OptionalParam[string](args, "since") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } before, err := OptionalParam[string](args, "before") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } owner, err := OptionalParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := OptionalParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } paginationParams, err := OptionalPaginationParams(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Build options @@ -113,7 +113,7 @@ func ListNotifications(t translations.TranslationHelperFunc) inventory.ServerToo if since != "" { sinceTime, err := time.Parse(time.RFC3339, since) if err != nil { - return utils.NewToolResultError(fmt.Sprintf("invalid since time format, should be RFC3339/ISO8601: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("invalid since time format, should be RFC3339/ISO8601: %v", err)), nil, nil } opts.Since = sinceTime } @@ -121,7 +121,7 @@ func ListNotifications(t translations.TranslationHelperFunc) inventory.ServerToo if before != "" { beforeTime, err := time.Parse(time.RFC3339, before) if err != nil { - return utils.NewToolResultError(fmt.Sprintf("invalid before time format, should be RFC3339/ISO8601: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("invalid before time format, should be RFC3339/ISO8601: %v", err)), nil, nil } opts.Before = beforeTime } @@ -146,7 +146,7 @@ func ListNotifications(t translations.TranslationHelperFunc) inventory.ServerToo if resp.StatusCode != http.StatusOK { body, err := io.ReadAll(resp.Body) if err != nil { - return utils.NewToolResultErrorFromErr("failed to read response body", err), nil, nil + return mcpresult.NewErrorFromErr("failed to read response body", err), nil, nil } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to get notifications", resp, body), nil, nil } @@ -154,10 +154,10 @@ func ListNotifications(t translations.TranslationHelperFunc) inventory.ServerToo // Marshal response to JSON r, err := json.Marshal(notifications) if err != nil { - return utils.NewToolResultErrorFromErr("failed to marshal response", err), nil, nil + return mcpresult.NewErrorFromErr("failed to marshal response", err), nil, nil } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -193,17 +193,17 @@ func DismissNotification(t translations.TranslationHelperFunc) inventory.ServerT func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } threadID, err := RequiredParam[string](args, "threadID") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } state, err := RequiredParam[string](args, "state") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } var resp *github.Response @@ -213,13 +213,13 @@ func DismissNotification(t translations.TranslationHelperFunc) inventory.ServerT var threadIDInt int64 threadIDInt, err = strconv.ParseInt(threadID, 10, 64) if err != nil { - return utils.NewToolResultError(fmt.Sprintf("invalid threadID format: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("invalid threadID format: %v", err)), nil, nil } resp, err = client.Activity.MarkThreadDone(ctx, threadIDInt) case "read": resp, err = client.Activity.MarkThreadRead(ctx, threadID) default: - return utils.NewToolResultError("Invalid state. Must be one of: read, done."), nil, nil + return mcpresult.NewError("Invalid state. Must be one of: read, done."), nil, nil } if err != nil { @@ -234,12 +234,12 @@ func DismissNotification(t translations.TranslationHelperFunc) inventory.ServerT if resp.StatusCode != http.StatusResetContent && resp.StatusCode != http.StatusNoContent && resp.StatusCode != http.StatusOK { body, err := io.ReadAll(resp.Body) if err != nil { - return utils.NewToolResultErrorFromErr("failed to read response body", err), nil, nil + return mcpresult.NewErrorFromErr("failed to read response body", err), nil, nil } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, fmt.Sprintf("failed to mark notification as %s", state), resp, body), nil, nil } - return utils.NewToolResultText(fmt.Sprintf("Notification marked as %s", state)), nil, nil + return mcpresult.NewText(fmt.Sprintf("Notification marked as %s", state)), nil, nil }, ) } @@ -277,28 +277,28 @@ func MarkAllNotificationsRead(t translations.TranslationHelperFunc) inventory.Se func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } lastReadAt, err := OptionalParam[string](args, "lastReadAt") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } owner, err := OptionalParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := OptionalParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } var lastReadTime time.Time if lastReadAt != "" { lastReadTime, err = time.Parse(time.RFC3339, lastReadAt) if err != nil { - return utils.NewToolResultError(fmt.Sprintf("invalid lastReadAt time format, should be RFC3339/ISO8601: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("invalid lastReadAt time format, should be RFC3339/ISO8601: %v", err)), nil, nil } } else { lastReadTime = time.Now() @@ -326,12 +326,12 @@ func MarkAllNotificationsRead(t translations.TranslationHelperFunc) inventory.Se if resp.StatusCode != http.StatusResetContent && resp.StatusCode != http.StatusOK { body, err := io.ReadAll(resp.Body) if err != nil { - return utils.NewToolResultErrorFromErr("failed to read response body", err), nil, nil + return mcpresult.NewErrorFromErr("failed to read response body", err), nil, nil } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to mark all notifications as read", resp, body), nil, nil } - return utils.NewToolResultText("All notifications marked as read"), nil, nil + return mcpresult.NewText("All notifications marked as read"), nil, nil }, ) } @@ -362,12 +362,12 @@ func GetNotificationDetails(t translations.TranslationHelperFunc) inventory.Serv func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } notificationID, err := RequiredParam[string](args, "notificationID") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } thread, resp, err := client.Activity.GetThread(ctx, notificationID) @@ -383,17 +383,17 @@ func GetNotificationDetails(t translations.TranslationHelperFunc) inventory.Serv if resp.StatusCode != http.StatusOK { body, err := io.ReadAll(resp.Body) if err != nil { - return utils.NewToolResultErrorFromErr("failed to read response body", err), nil, nil + return mcpresult.NewErrorFromErr("failed to read response body", err), nil, nil } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to get notification details", resp, body), nil, nil } r, err := json.Marshal(thread) if err != nil { - return utils.NewToolResultErrorFromErr("failed to marshal response", err), nil, nil + return mcpresult.NewErrorFromErr("failed to marshal response", err), nil, nil } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -436,16 +436,16 @@ func ManageNotificationSubscription(t translations.TranslationHelperFunc) invent func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } notificationID, err := RequiredParam[string](args, "notificationID") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } action, err := RequiredParam[string](args, "action") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } var ( @@ -464,7 +464,7 @@ func ManageNotificationSubscription(t translations.TranslationHelperFunc) invent case NotificationActionDelete: resp, apiErr = client.Activity.DeleteThreadSubscription(ctx, notificationID) default: - return utils.NewToolResultError("Invalid action. Must be one of: ignore, watch, delete."), nil, nil + return mcpresult.NewError("Invalid action. Must be one of: ignore, watch, delete."), nil, nil } if apiErr != nil { @@ -483,14 +483,14 @@ func ManageNotificationSubscription(t translations.TranslationHelperFunc) invent if action == NotificationActionDelete { // Special case for delete as there is no response body - return utils.NewToolResultText("Notification subscription deleted"), nil, nil + return mcpresult.NewText("Notification subscription deleted"), nil, nil } r, err := json.Marshal(result) if err != nil { - return utils.NewToolResultErrorFromErr("failed to marshal response", err), nil, nil + return mcpresult.NewErrorFromErr("failed to marshal response", err), nil, nil } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -536,20 +536,20 @@ func ManageRepositoryNotificationSubscription(t translations.TranslationHelperFu func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } action, err := RequiredParam[string](args, "action") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } var ( @@ -568,7 +568,7 @@ func ManageRepositoryNotificationSubscription(t translations.TranslationHelperFu case RepositorySubscriptionActionDelete: resp, apiErr = client.Activity.DeleteRepositorySubscription(ctx, owner, repo) default: - return utils.NewToolResultError("Invalid action. Must be one of: ignore, watch, delete."), nil, nil + return mcpresult.NewError("Invalid action. Must be one of: ignore, watch, delete."), nil, nil } if apiErr != nil { @@ -590,14 +590,14 @@ func ManageRepositoryNotificationSubscription(t translations.TranslationHelperFu if action == RepositorySubscriptionActionDelete { // Special case for delete as there is no response body - return utils.NewToolResultText("Repository subscription deleted"), nil, nil + return mcpresult.NewText("Repository subscription deleted"), nil, nil } r, err := json.Marshal(result) if err != nil { - return utils.NewToolResultErrorFromErr("failed to marshal response", err), nil, nil + return mcpresult.NewErrorFromErr("failed to marshal response", err), nil, nil } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } diff --git a/pkg/github/projects.go b/pkg/github/projects.go index 4fed6364f..9922ecff6 100644 --- a/pkg/github/projects.go +++ b/pkg/github/projects.go @@ -10,9 +10,9 @@ import ( ghErrors "github.com/github/github-mcp-server/pkg/errors" "github.com/github/github-mcp-server/pkg/inventory" + "github.com/github/github-mcp-server/pkg/mcpresult" "github.com/github/github-mcp-server/pkg/scopes" "github.com/github/github-mcp-server/pkg/translations" - "github.com/github/github-mcp-server/pkg/utils" "github.com/google/go-github/v79/github" "github.com/google/jsonschema-go/jsonschema" "github.com/modelcontextprotocol/go-sdk/mcp" @@ -91,27 +91,27 @@ func ListProjects(t translations.TranslationHelperFunc) inventory.ServerTool { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } ownerType, err := RequiredParam[string](args, "owner_type") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } queryStr, err := OptionalParam[string](args, "query") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } pagination, err := extractPaginationOptionsFromArgs(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } var resp *github.Response @@ -157,7 +157,7 @@ func ListProjects(t translations.TranslationHelperFunc) inventory.ServerTool { return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) tool.FeatureFlagEnable = FeatureFlagHoldbackConsolidatedProjects @@ -199,22 +199,22 @@ func GetProject(t translations.TranslationHelperFunc) inventory.ServerTool { projectNumber, err := RequiredInt(args, "project_number") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } ownerType, err := RequiredParam[string](args, "owner_type") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } var resp *github.Response @@ -248,7 +248,7 @@ func GetProject(t translations.TranslationHelperFunc) inventory.ServerTool { return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) tool.FeatureFlagEnable = FeatureFlagHoldbackConsolidatedProjects @@ -302,27 +302,27 @@ func ListProjectFields(t translations.TranslationHelperFunc) inventory.ServerToo owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } ownerType, err := RequiredParam[string](args, "owner_type") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } projectNumber, err := RequiredInt(args, "project_number") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } pagination, err := extractPaginationOptionsFromArgs(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } var resp *github.Response @@ -357,7 +357,7 @@ func ListProjectFields(t translations.TranslationHelperFunc) inventory.ServerToo return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) tool.FeatureFlagEnable = FeatureFlagHoldbackConsolidatedProjects @@ -403,23 +403,23 @@ func GetProjectField(t translations.TranslationHelperFunc) inventory.ServerTool owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } ownerType, err := RequiredParam[string](args, "owner_type") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } projectNumber, err := RequiredInt(args, "project_number") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } fieldID, err := RequiredBigInt(args, "field_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } var resp *github.Response @@ -452,7 +452,7 @@ func GetProjectField(t translations.TranslationHelperFunc) inventory.ServerTool return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) tool.FeatureFlagEnable = FeatureFlagHoldbackConsolidatedProjects @@ -517,37 +517,37 @@ func ListProjectItems(t translations.TranslationHelperFunc) inventory.ServerTool owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } ownerType, err := RequiredParam[string](args, "owner_type") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } projectNumber, err := RequiredInt(args, "project_number") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } queryStr, err := OptionalParam[string](args, "query") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } fields, err := OptionalBigIntArrayParam(args, "fields") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } pagination, err := extractPaginationOptionsFromArgs(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } var resp *github.Response @@ -591,7 +591,7 @@ func ListProjectItems(t translations.TranslationHelperFunc) inventory.ServerTool return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) tool.FeatureFlagEnable = FeatureFlagHoldbackConsolidatedProjects @@ -644,30 +644,30 @@ func GetProjectItem(t translations.TranslationHelperFunc) inventory.ServerTool { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } ownerType, err := RequiredParam[string](args, "owner_type") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } projectNumber, err := RequiredInt(args, "project_number") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } itemID, err := RequiredBigInt(args, "item_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } fields, err := OptionalBigIntArrayParam(args, "fields") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } var resp *github.Response @@ -700,7 +700,7 @@ func GetProjectItem(t translations.TranslationHelperFunc) inventory.ServerTool { return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) tool.FeatureFlagEnable = FeatureFlagHoldbackConsolidatedProjects @@ -751,32 +751,32 @@ func AddProjectItem(t translations.TranslationHelperFunc) inventory.ServerTool { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } ownerType, err := RequiredParam[string](args, "owner_type") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } projectNumber, err := RequiredInt(args, "project_number") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } itemID, err := RequiredBigInt(args, "item_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } itemType, err := RequiredParam[string](args, "item_type") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } if itemType != "issue" && itemType != "pull_request" { - return utils.NewToolResultError("item_type must be either 'issue' or 'pull_request'"), nil, nil + return mcpresult.NewError("item_type must be either 'issue' or 'pull_request'"), nil, nil } client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } newItem := &github.AddProjectItemOptions{ @@ -814,7 +814,7 @@ func AddProjectItem(t translations.TranslationHelperFunc) inventory.ServerTool { return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) tool.FeatureFlagEnable = FeatureFlagHoldbackConsolidatedProjects @@ -864,39 +864,39 @@ func UpdateProjectItem(t translations.TranslationHelperFunc) inventory.ServerToo owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } ownerType, err := RequiredParam[string](args, "owner_type") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } projectNumber, err := RequiredInt(args, "project_number") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } itemID, err := RequiredBigInt(args, "item_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } rawUpdatedField, exists := args["updated_field"] if !exists { - return utils.NewToolResultError("missing required parameter: updated_field"), nil, nil + return mcpresult.NewError("missing required parameter: updated_field"), nil, nil } fieldValue, ok := rawUpdatedField.(map[string]any) if !ok || fieldValue == nil { - return utils.NewToolResultError("field_value must be an object"), nil, nil + return mcpresult.NewError("field_value must be an object"), nil, nil } updatePayload, err := buildUpdateProjectItem(fieldValue) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } var resp *github.Response @@ -929,7 +929,7 @@ func UpdateProjectItem(t translations.TranslationHelperFunc) inventory.ServerToo return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) tool.FeatureFlagEnable = FeatureFlagHoldbackConsolidatedProjects @@ -976,23 +976,23 @@ func DeleteProjectItem(t translations.TranslationHelperFunc) inventory.ServerToo owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } ownerType, err := RequiredParam[string](args, "owner_type") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } projectNumber, err := RequiredInt(args, "project_number") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } itemID, err := RequiredBigInt(args, "item_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } var resp *github.Response @@ -1018,7 +1018,7 @@ func DeleteProjectItem(t translations.TranslationHelperFunc) inventory.ServerToo } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, ProjectDeleteFailedError, resp, body), nil, nil } - return utils.NewToolResultText("project item successfully deleted"), nil, nil + return mcpresult.NewText("project item successfully deleted"), nil, nil }, ) tool.FeatureFlagEnable = FeatureFlagHoldbackConsolidatedProjects @@ -1095,22 +1095,22 @@ Use this tool to list projects for a user or organization, or list project field func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { method, err := RequiredParam[string](args, "method") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } ownerType, err := OptionalParam[string](args, "owner_type") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } switch method { @@ -1121,11 +1121,11 @@ Use this tool to list projects for a user or organization, or list project field if ownerType == "" { projectNumber, err := RequiredInt(args, "project_number") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } ownerType, err = detectOwnerType(ctx, client, owner, projectNumber) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } } return listProjectFields(ctx, client, args, owner, ownerType) @@ -1134,16 +1134,16 @@ Use this tool to list projects for a user or organization, or list project field if ownerType == "" { projectNumber, err := RequiredInt(args, "project_number") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } ownerType, err = detectOwnerType(ctx, client, owner, projectNumber) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } } return listProjectItems(ctx, client, args, owner, ownerType) default: - return utils.NewToolResultError(fmt.Sprintf("unknown method: %s", method)), nil, nil + return mcpresult.NewError(fmt.Sprintf("unknown method: %s", method)), nil, nil } }, ) @@ -1212,34 +1212,34 @@ Use this tool to get details about individual projects, project fields, and proj func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { method, err := RequiredParam[string](args, "method") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } ownerType, err := OptionalParam[string](args, "owner_type") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } projectNumber, err := RequiredInt(args, "project_number") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Detect owner type if not provided if ownerType == "" { ownerType, err = detectOwnerType(ctx, client, owner, projectNumber) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } } @@ -1249,21 +1249,21 @@ Use this tool to get details about individual projects, project fields, and proj case projectsMethodGetProjectField: fieldID, err := RequiredBigInt(args, "field_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } return getProjectField(ctx, client, owner, ownerType, projectNumber, fieldID) case projectsMethodGetProjectItem: itemID, err := RequiredBigInt(args, "item_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } fields, err := OptionalBigIntArrayParam(args, "fields") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } return getProjectItem(ctx, client, owner, ownerType, projectNumber, itemID, fields) default: - return utils.NewToolResultError(fmt.Sprintf("unknown method: %s", method)), nil, nil + return mcpresult.NewError(fmt.Sprintf("unknown method: %s", method)), nil, nil } }, ) @@ -1345,39 +1345,39 @@ func ProjectsWrite(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { method, err := RequiredParam[string](args, "method") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } ownerType, err := OptionalParam[string](args, "owner_type") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } projectNumber, err := RequiredInt(args, "project_number") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } gqlClient, err := deps.GetGQLClient(ctx) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Detect owner type if not provided if ownerType == "" { ownerType, err = detectOwnerType(ctx, client, owner, projectNumber) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } } @@ -1385,15 +1385,15 @@ func ProjectsWrite(t translations.TranslationHelperFunc) inventory.ServerTool { case projectsMethodAddProjectItem: itemType, err := RequiredParam[string](args, "item_type") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } itemOwner, err := RequiredParam[string](args, "item_owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } itemRepo, err := RequiredParam[string](args, "item_repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } var itemNumber int @@ -1401,40 +1401,40 @@ func ProjectsWrite(t translations.TranslationHelperFunc) inventory.ServerTool { case "issue": itemNumber, err = RequiredInt(args, "issue_number") if err != nil { - return utils.NewToolResultError("issue_number is required when item_type is 'issue'"), nil, nil + return mcpresult.NewError("issue_number is required when item_type is 'issue'"), nil, nil } case "pull_request": itemNumber, err = RequiredInt(args, "pull_request_number") if err != nil { - return utils.NewToolResultError("pull_request_number is required when item_type is 'pull_request'"), nil, nil + return mcpresult.NewError("pull_request_number is required when item_type is 'pull_request'"), nil, nil } default: - return utils.NewToolResultError("item_type must be either 'issue' or 'pull_request'"), nil, nil + return mcpresult.NewError("item_type must be either 'issue' or 'pull_request'"), nil, nil } return addProjectItem(ctx, gqlClient, owner, ownerType, projectNumber, itemOwner, itemRepo, itemNumber, itemType) case projectsMethodUpdateProjectItem: itemID, err := RequiredBigInt(args, "item_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } rawUpdatedField, exists := args["updated_field"] if !exists { - return utils.NewToolResultError("missing required parameter: updated_field"), nil, nil + return mcpresult.NewError("missing required parameter: updated_field"), nil, nil } fieldValue, ok := rawUpdatedField.(map[string]any) if !ok || fieldValue == nil { - return utils.NewToolResultError("updated_field must be an object"), nil, nil + return mcpresult.NewError("updated_field must be an object"), nil, nil } return updateProjectItem(ctx, client, owner, ownerType, projectNumber, itemID, fieldValue) case projectsMethodDeleteProjectItem: itemID, err := RequiredBigInt(args, "item_id") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } return deleteProjectItem(ctx, client, owner, ownerType, projectNumber, itemID) default: - return utils.NewToolResultError(fmt.Sprintf("unknown method: %s", method)), nil, nil + return mcpresult.NewError(fmt.Sprintf("unknown method: %s", method)), nil, nil } }, ) @@ -1447,12 +1447,12 @@ func ProjectsWrite(t translations.TranslationHelperFunc) inventory.ServerTool { func listProjects(ctx context.Context, client *github.Client, args map[string]any, owner, ownerType string) (*mcp.CallToolResult, any, error) { queryStr, err := OptionalParam[string](args, "query") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } pagination, err := extractPaginationOptionsFromArgs(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } var resp *github.Response @@ -1513,7 +1513,7 @@ func listProjects(ctx context.Context, client *github.Client, args map[string]an return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } return nil, nil, fmt.Errorf("unexpected state in listProjects") @@ -1552,7 +1552,7 @@ func listProjectsFromBothOwnerTypes(ctx context.Context, client *github.Client, // If both failed, return error if (userErr != nil || userResp == nil || userResp.StatusCode != http.StatusOK) && (orgErr != nil || orgResp == nil || orgResp.StatusCode != http.StatusOK) { - return utils.NewToolResultError(fmt.Sprintf("failed to list projects for owner '%s': not found as user or organization", owner)), nil, nil + return mcpresult.NewError(fmt.Sprintf("failed to list projects for owner '%s': not found as user or organization", owner)), nil, nil } response := map[string]any{ @@ -1568,18 +1568,18 @@ func listProjectsFromBothOwnerTypes(ctx context.Context, client *github.Client, if err != nil { return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } func listProjectFields(ctx context.Context, client *github.Client, args map[string]any, owner, ownerType string) (*mcp.CallToolResult, any, error) { projectNumber, err := RequiredInt(args, "project_number") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } pagination, err := extractPaginationOptionsFromArgs(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } var resp *github.Response @@ -1614,28 +1614,28 @@ func listProjectFields(ctx context.Context, client *github.Client, args map[stri return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } func listProjectItems(ctx context.Context, client *github.Client, args map[string]any, owner, ownerType string) (*mcp.CallToolResult, any, error) { projectNumber, err := RequiredInt(args, "project_number") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } queryStr, err := OptionalParam[string](args, "query") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } fields, err := OptionalBigIntArrayParam(args, "fields") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } pagination, err := extractPaginationOptionsFromArgs(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } var resp *github.Response @@ -1679,7 +1679,7 @@ func listProjectItems(ctx context.Context, client *github.Client, args map[strin return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } func getProject(ctx context.Context, client *github.Client, owner, ownerType string, projectNumber int) (*mcp.CallToolResult, any, error) { @@ -1715,7 +1715,7 @@ func getProject(ctx context.Context, client *github.Client, owner, ownerType str return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } func getProjectField(ctx context.Context, client *github.Client, owner, ownerType string, projectNumber int, fieldID int64) (*mcp.CallToolResult, any, error) { @@ -1750,7 +1750,7 @@ func getProjectField(ctx context.Context, client *github.Client, owner, ownerTyp return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } func getProjectItem(ctx context.Context, client *github.Client, owner, ownerType string, projectNumber int, itemID int64, fields []int64) (*mcp.CallToolResult, any, error) { @@ -1793,13 +1793,13 @@ func getProjectItem(ctx context.Context, client *github.Client, owner, ownerType return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } func updateProjectItem(ctx context.Context, client *github.Client, owner, ownerType string, projectNumber int, itemID int64, fieldValue map[string]any) (*mcp.CallToolResult, any, error) { updatePayload, err := buildUpdateProjectItem(fieldValue) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } var resp *github.Response @@ -1832,7 +1832,7 @@ func updateProjectItem(ctx context.Context, client *github.Client, owner, ownerT return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } func deleteProjectItem(ctx context.Context, client *github.Client, owner, ownerType string, projectNumber int, itemID int64) (*mcp.CallToolResult, any, error) { @@ -1861,13 +1861,13 @@ func deleteProjectItem(ctx context.Context, client *github.Client, owner, ownerT } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, ProjectDeleteFailedError, resp, body), nil, nil } - return utils.NewToolResultText("project item successfully deleted"), nil, nil + return mcpresult.NewText("project item successfully deleted"), nil, nil } // addProjectItem adds an item to a project by resolving the issue/PR number to a node ID func addProjectItem(ctx context.Context, gqlClient *githubv4.Client, owner, ownerType string, projectNumber int, itemOwner, itemRepo string, itemNumber int, itemType string) (*mcp.CallToolResult, any, error) { if itemType != "issue" && itemType != "pull_request" { - return utils.NewToolResultError("item_type must be either 'issue' or 'pull_request'"), nil, nil + return mcpresult.NewError("item_type must be either 'issue' or 'pull_request'"), nil, nil } // Resolve the item number to a node ID @@ -1879,7 +1879,7 @@ func addProjectItem(ctx context.Context, gqlClient *githubv4.Client, owner, owne nodeID, err = resolvePullRequestNodeID(ctx, gqlClient, itemOwner, itemRepo, itemNumber) } if err != nil { - return utils.NewToolResultError(fmt.Sprintf("failed to resolve %s: %v", itemType, err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("failed to resolve %s: %v", itemType, err)), nil, nil } // Use GraphQL to add the item to the project @@ -1914,7 +1914,7 @@ func addProjectItem(ctx context.Context, gqlClient *githubv4.Client, owner, owne "projectNumber": githubv4.Int(int32(projectNumber)), //nolint:gosec // Project numbers are small integers }) if err != nil { - return utils.NewToolResultError(fmt.Sprintf("failed to get project ID: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("failed to get project ID: %v", err)), nil, nil } projectID = projectIDQueryOrg.Organization.ProjectV2.ID } else { @@ -1923,7 +1923,7 @@ func addProjectItem(ctx context.Context, gqlClient *githubv4.Client, owner, owne "projectNumber": githubv4.Int(int32(projectNumber)), //nolint:gosec // Project numbers are small integers }) if err != nil { - return utils.NewToolResultError(fmt.Sprintf("failed to get project ID: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("failed to get project ID: %v", err)), nil, nil } projectID = projectIDQuery.User.ProjectV2.ID } @@ -1936,7 +1936,7 @@ func addProjectItem(ctx context.Context, gqlClient *githubv4.Client, owner, owne err = gqlClient.Mutate(ctx, &mutation, input, nil) if err != nil { - return utils.NewToolResultError(fmt.Sprintf(ProjectAddFailedError+": %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf(ProjectAddFailedError+": %v", err)), nil, nil } result := map[string]any{ @@ -1949,7 +1949,7 @@ func addProjectItem(ctx context.Context, gqlClient *githubv4.Client, owner, owne return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } type pageInfo struct { diff --git a/pkg/github/pullrequests.go b/pkg/github/pullrequests.go index 62952783e..0d3d28c05 100644 --- a/pkg/github/pullrequests.go +++ b/pkg/github/pullrequests.go @@ -16,11 +16,11 @@ import ( ghErrors "github.com/github/github-mcp-server/pkg/errors" "github.com/github/github-mcp-server/pkg/inventory" "github.com/github/github-mcp-server/pkg/lockdown" + "github.com/github/github-mcp-server/pkg/mcpresult" "github.com/github/github-mcp-server/pkg/octicons" "github.com/github/github-mcp-server/pkg/sanitize" "github.com/github/github-mcp-server/pkg/scopes" "github.com/github/github-mcp-server/pkg/translations" - "github.com/github/github-mcp-server/pkg/utils" ) // PullRequestRead creates a tool to get details of a specific pull request. @@ -74,29 +74,29 @@ Possible options: func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { method, err := RequiredParam[string](args, "method") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } pullNumber, err := RequiredInt(args, "pullNumber") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } pagination, err := OptionalPaginationParams(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } switch method { @@ -115,11 +115,11 @@ Possible options: case "get_review_comments": gqlClient, err := deps.GetGQLClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub GQL client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub GQL client", err), nil, nil } cursorPagination, err := OptionalCursorPaginationParams(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } result, err := GetPullRequestReviewComments(ctx, gqlClient, deps.GetRepoAccessCache(), owner, repo, pullNumber, cursorPagination, deps.GetFlags()) return result, nil, err @@ -130,7 +130,7 @@ Possible options: result, err := GetIssueComments(ctx, client, deps.GetRepoAccessCache(), owner, repo, pullNumber, pagination, deps.GetFlags()) return result, nil, err default: - return utils.NewToolResultError(fmt.Sprintf("unknown method: %s", method)), nil, nil + return mcpresult.NewError(fmt.Sprintf("unknown method: %s", method)), nil, nil } }) } @@ -176,7 +176,7 @@ func GetPullRequest(ctx context.Context, client *github.Client, cache *lockdown. } if !isSafeContent { - return utils.NewToolResultError("access to pull request is restricted by lockdown mode"), nil + return mcpresult.NewError("access to pull request is restricted by lockdown mode"), nil } } } @@ -186,7 +186,7 @@ func GetPullRequest(ctx context.Context, client *github.Client, cache *lockdown. return nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil + return mcpresult.NewText(string(r)), nil } func GetPullRequestDiff(ctx context.Context, client *github.Client, owner, repo string, pullNumber int) (*mcp.CallToolResult, error) { @@ -216,7 +216,7 @@ func GetPullRequestDiff(ctx context.Context, client *github.Client, owner, repo defer func() { _ = resp.Body.Close() }() // Return the raw response - return utils.NewToolResultText(string(raw)), nil + return mcpresult.NewText(string(raw)), nil } func GetPullRequestStatus(ctx context.Context, client *github.Client, owner, repo string, pullNumber int) (*mcp.CallToolResult, error) { @@ -262,7 +262,7 @@ func GetPullRequestStatus(ctx context.Context, client *github.Client, owner, rep return nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil + return mcpresult.NewText(string(r)), nil } func GetPullRequestFiles(ctx context.Context, client *github.Client, owner, repo string, pullNumber int, pagination PaginationParams) (*mcp.CallToolResult, error) { @@ -293,7 +293,7 @@ func GetPullRequestFiles(ctx context.Context, client *github.Client, owner, repo return nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil + return mcpresult.NewText(string(r)), nil } // GraphQL types for review threads query @@ -344,7 +344,7 @@ func GetPullRequestReviewComments(ctx context.Context, gqlClient *githubv4.Clien // Convert pagination parameters to GraphQL format gqlParams, err := pagination.ToGraphQLParams() if err != nil { - return utils.NewToolResultError(fmt.Sprintf("invalid pagination parameters: %v", err)), nil + return mcpresult.NewError(fmt.Sprintf("invalid pagination parameters: %v", err)), nil } // Build variables for GraphQL query @@ -418,7 +418,7 @@ func GetPullRequestReviewComments(ctx context.Context, gqlClient *githubv4.Clien return nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil + return mcpresult.NewText(string(r)), nil } func GetPullRequestReviews(ctx context.Context, client *github.Client, cache *lockdown.RepoAccessCache, owner, repo string, pullNumber int, ff FeatureFlags) (*mcp.CallToolResult, error) { @@ -465,7 +465,7 @@ func GetPullRequestReviews(ctx context.Context, client *github.Client, cache *lo return nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil + return mcpresult.NewText(string(r)), nil } // CreatePullRequest creates a tool to create a new pull request. @@ -524,38 +524,38 @@ func CreatePullRequest(t translations.TranslationHelperFunc) inventory.ServerToo func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } title, err := RequiredParam[string](args, "title") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } head, err := RequiredParam[string](args, "head") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } base, err := RequiredParam[string](args, "base") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } body, err := OptionalParam[string](args, "body") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } draft, err := OptionalParam[bool](args, "draft") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } maintainerCanModify, err := OptionalParam[bool](args, "maintainer_can_modify") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } newPR := &github.NewPullRequest{ @@ -573,7 +573,7 @@ func CreatePullRequest(t translations.TranslationHelperFunc) inventory.ServerToo client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } pr, resp, err := client.PullRequests.Create(ctx, owner, repo, newPR) if err != nil { @@ -588,7 +588,7 @@ func CreatePullRequest(t translations.TranslationHelperFunc) inventory.ServerToo if resp.StatusCode != http.StatusCreated { bodyBytes, err := io.ReadAll(resp.Body) if err != nil { - return utils.NewToolResultErrorFromErr("failed to read response body", err), nil, nil + return mcpresult.NewErrorFromErr("failed to read response body", err), nil, nil } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to create pull request", resp, bodyBytes), nil, nil } @@ -601,10 +601,10 @@ func CreatePullRequest(t translations.TranslationHelperFunc) inventory.ServerToo r, err := json.Marshal(minimalResponse) if err != nil { - return utils.NewToolResultErrorFromErr("failed to marshal response", err), nil, nil + return mcpresult.NewErrorFromErr("failed to marshal response", err), nil, nil } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }) } @@ -676,15 +676,15 @@ func UpdatePullRequest(t translations.TranslationHelperFunc) inventory.ServerToo func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } pullNumber, err := RequiredInt(args, "pullNumber") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } _, draftProvided := args["draft"] @@ -692,7 +692,7 @@ func UpdatePullRequest(t translations.TranslationHelperFunc) inventory.ServerToo if draftProvided { draftValue, err = OptionalParam[bool](args, "draft") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } } @@ -700,35 +700,35 @@ func UpdatePullRequest(t translations.TranslationHelperFunc) inventory.ServerToo restUpdateNeeded := false if title, ok, err := OptionalParamOK[string](args, "title"); err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } else if ok { update.Title = github.Ptr(title) restUpdateNeeded = true } if body, ok, err := OptionalParamOK[string](args, "body"); err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } else if ok { update.Body = github.Ptr(body) restUpdateNeeded = true } if state, ok, err := OptionalParamOK[string](args, "state"); err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } else if ok { update.State = github.Ptr(state) restUpdateNeeded = true } if base, ok, err := OptionalParamOK[string](args, "base"); err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } else if ok { update.Base = &github.PullRequestBranch{Ref: github.Ptr(base)} restUpdateNeeded = true } if maintainerCanModify, ok, err := OptionalParamOK[bool](args, "maintainer_can_modify"); err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } else if ok { update.MaintainerCanModify = github.Ptr(maintainerCanModify) restUpdateNeeded = true @@ -737,19 +737,19 @@ func UpdatePullRequest(t translations.TranslationHelperFunc) inventory.ServerToo // Handle reviewers separately reviewers, err := OptionalStringArrayParam(args, "reviewers") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // If no updates, no draft change, and no reviewers, return error early if !restUpdateNeeded && !draftProvided && len(reviewers) == 0 { - return utils.NewToolResultError("No update parameters provided."), nil, nil + return mcpresult.NewError("No update parameters provided."), nil, nil } // Handle REST API updates (title, body, state, base, maintainer_can_modify) if restUpdateNeeded { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } _, resp, err := client.PullRequests.Edit(ctx, owner, repo, pullNumber, update) @@ -765,7 +765,7 @@ func UpdatePullRequest(t translations.TranslationHelperFunc) inventory.ServerToo if resp.StatusCode != http.StatusOK { bodyBytes, err := io.ReadAll(resp.Body) if err != nil { - return utils.NewToolResultErrorFromErr("failed to read response body", err), nil, nil + return mcpresult.NewErrorFromErr("failed to read response body", err), nil, nil } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to update pull request", resp, bodyBytes), nil, nil } @@ -775,7 +775,7 @@ func UpdatePullRequest(t translations.TranslationHelperFunc) inventory.ServerToo if draftProvided { gqlClient, err := deps.GetGQLClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub GraphQL client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub GraphQL client", err), nil, nil } var prQuery struct { @@ -841,7 +841,7 @@ func UpdatePullRequest(t translations.TranslationHelperFunc) inventory.ServerToo if len(reviewers) > 0 { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } reviewersRequest := github.ReviewersRequest{ @@ -865,7 +865,7 @@ func UpdatePullRequest(t translations.TranslationHelperFunc) inventory.ServerToo if resp.StatusCode != http.StatusCreated && resp.StatusCode != http.StatusOK { bodyBytes, err := io.ReadAll(resp.Body) if err != nil { - return utils.NewToolResultErrorFromErr("failed to read response body", err), nil, nil + return mcpresult.NewErrorFromErr("failed to read response body", err), nil, nil } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to request reviewers", resp, bodyBytes), nil, nil } @@ -874,7 +874,7 @@ func UpdatePullRequest(t translations.TranslationHelperFunc) inventory.ServerToo // Get the final state of the PR to return client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } finalPR, resp, err := client.PullRequests.Get(ctx, owner, repo, pullNumber) @@ -895,10 +895,10 @@ func UpdatePullRequest(t translations.TranslationHelperFunc) inventory.ServerToo r, err := json.Marshal(minimalResponse) if err != nil { - return utils.NewToolResultErrorFromErr("Failed to marshal response", err), nil, nil + return mcpresult.NewErrorFromErr("Failed to marshal response", err), nil, nil } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }) } @@ -958,35 +958,35 @@ func ListPullRequests(t translations.TranslationHelperFunc) inventory.ServerTool func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } state, err := OptionalParam[string](args, "state") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } head, err := OptionalParam[string](args, "head") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } base, err := OptionalParam[string](args, "base") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } sort, err := OptionalParam[string](args, "sort") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } direction, err := OptionalParam[string](args, "direction") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } pagination, err := OptionalPaginationParams(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } opts := &github.PullRequestListOptions{ @@ -1003,7 +1003,7 @@ func ListPullRequests(t translations.TranslationHelperFunc) inventory.ServerTool client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } prs, resp, err := client.PullRequests.List(ctx, owner, repo, opts) if err != nil { @@ -1018,7 +1018,7 @@ func ListPullRequests(t translations.TranslationHelperFunc) inventory.ServerTool if resp.StatusCode != http.StatusOK { bodyBytes, err := io.ReadAll(resp.Body) if err != nil { - return utils.NewToolResultErrorFromErr("failed to read response body", err), nil, nil + return mcpresult.NewErrorFromErr("failed to read response body", err), nil, nil } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to list pull requests", resp, bodyBytes), nil, nil } @@ -1038,10 +1038,10 @@ func ListPullRequests(t translations.TranslationHelperFunc) inventory.ServerTool r, err := json.Marshal(prs) if err != nil { - return utils.NewToolResultErrorFromErr("failed to marshal response", err), nil, nil + return mcpresult.NewErrorFromErr("failed to marshal response", err), nil, nil } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }) } @@ -1095,27 +1095,27 @@ func MergePullRequest(t translations.TranslationHelperFunc) inventory.ServerTool func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } pullNumber, err := RequiredInt(args, "pullNumber") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } commitTitle, err := OptionalParam[string](args, "commit_title") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } commitMessage, err := OptionalParam[string](args, "commit_message") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } mergeMethod, err := OptionalParam[string](args, "merge_method") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } options := &github.PullRequestOptions{ @@ -1125,7 +1125,7 @@ func MergePullRequest(t translations.TranslationHelperFunc) inventory.ServerTool client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } result, resp, err := client.PullRequests.Merge(ctx, owner, repo, pullNumber, commitMessage, options) if err != nil { @@ -1140,17 +1140,17 @@ func MergePullRequest(t translations.TranslationHelperFunc) inventory.ServerTool if resp.StatusCode != http.StatusOK { bodyBytes, err := io.ReadAll(resp.Body) if err != nil { - return utils.NewToolResultErrorFromErr("failed to read response body", err), nil, nil + return mcpresult.NewErrorFromErr("failed to read response body", err), nil, nil } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to merge pull request", resp, bodyBytes), nil, nil } r, err := json.Marshal(result) if err != nil { - return utils.NewToolResultErrorFromErr("failed to marshal response", err), nil, nil + return mcpresult.NewErrorFromErr("failed to marshal response", err), nil, nil } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }) } @@ -1256,19 +1256,19 @@ func UpdatePullRequestBranch(t translations.TranslationHelperFunc) inventory.Ser func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } pullNumber, err := RequiredInt(args, "pullNumber") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } expectedHeadSHA, err := OptionalParam[string](args, "expectedHeadSha") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } opts := &github.PullRequestBranchUpdateOptions{} if expectedHeadSHA != "" { @@ -1277,14 +1277,14 @@ func UpdatePullRequestBranch(t translations.TranslationHelperFunc) inventory.Ser client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } result, resp, err := client.PullRequests.UpdateBranch(ctx, owner, repo, pullNumber, opts) if err != nil { // Check if it's an acceptedError. An acceptedError indicates that the update is in progress, // and it's not a real error. if resp != nil && resp.StatusCode == http.StatusAccepted && isAcceptedError(err) { - return utils.NewToolResultText("Pull request branch update is in progress"), nil, nil + return mcpresult.NewText("Pull request branch update is in progress"), nil, nil } return ghErrors.NewGitHubAPIErrorResponse(ctx, "failed to update pull request branch", @@ -1297,17 +1297,17 @@ func UpdatePullRequestBranch(t translations.TranslationHelperFunc) inventory.Ser if resp.StatusCode != http.StatusAccepted { bodyBytes, err := io.ReadAll(resp.Body) if err != nil { - return utils.NewToolResultErrorFromErr("failed to read response body", err), nil, nil + return mcpresult.NewErrorFromErr("failed to read response body", err), nil, nil } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to update pull request branch", resp, bodyBytes), nil, nil } r, err := json.Marshal(result) if err != nil { - return utils.NewToolResultErrorFromErr("failed to marshal response", err), nil, nil + return mcpresult.NewErrorFromErr("failed to marshal response", err), nil, nil } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }) } @@ -1383,13 +1383,13 @@ Available methods: func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { var params PullRequestReviewWriteParams if err := mapstructure.Decode(args, ¶ms); err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Given our owner, repo and PR number, lookup the GQL ID of the PR. client, err := deps.GetGQLClient(ctx) if err != nil { - return utils.NewToolResultError(fmt.Sprintf("failed to get GitHub GQL client: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("failed to get GitHub GQL client: %v", err)), nil, nil } switch params.Method { @@ -1403,7 +1403,7 @@ Available methods: result, err := DeletePendingPullRequestReview(ctx, client, params) return result, nil, err default: - return utils.NewToolResultError(fmt.Sprintf("unknown method: %s", params.Method)), nil, nil + return mcpresult.NewError(fmt.Sprintf("unknown method: %s", params.Method)), nil, nil } }) } @@ -1454,16 +1454,16 @@ func CreatePullRequestReview(ctx context.Context, client *githubv4.Client, param addPullRequestReviewInput, nil, ); err != nil { - return utils.NewToolResultError(err.Error()), nil + return mcpresult.NewError(err.Error()), nil } // Return nothing interesting, just indicate success for the time being. // In future, we may want to return the review ID, but for the moment, we're not leaking // API implementation details to the LLM. if params.Event == "" { - return utils.NewToolResultText("pending pull request created"), nil + return mcpresult.NewText("pending pull request created"), nil } - return utils.NewToolResultText("pull request review submitted successfully"), nil + return mcpresult.NewText("pull request review submitted successfully"), nil } func SubmitPendingPullRequestReview(ctx context.Context, client *githubv4.Client, params PullRequestReviewWriteParams) (*mcp.CallToolResult, error) { @@ -1511,13 +1511,13 @@ func SubmitPendingPullRequestReview(ctx context.Context, client *githubv4.Client // Validate there is one review and the state is pending if len(getLatestReviewForViewerQuery.Repository.PullRequest.Reviews.Nodes) == 0 { - return utils.NewToolResultError("No pending review found for the viewer"), nil + return mcpresult.NewError("No pending review found for the viewer"), nil } review := getLatestReviewForViewerQuery.Repository.PullRequest.Reviews.Nodes[0] if review.State != githubv4.PullRequestReviewStatePending { errText := fmt.Sprintf("The latest review, found at %s is not pending", review.URL) - return utils.NewToolResultError(errText), nil + return mcpresult.NewError(errText), nil } // Prepare the mutation @@ -1548,7 +1548,7 @@ func SubmitPendingPullRequestReview(ctx context.Context, client *githubv4.Client // Return nothing interesting, just indicate success for the time being. // In future, we may want to return the review ID, but for the moment, we're not leaking // API implementation details to the LLM. - return utils.NewToolResultText("pending pull request review successfully submitted"), nil + return mcpresult.NewText("pending pull request review successfully submitted"), nil } func DeletePendingPullRequestReview(ctx context.Context, client *githubv4.Client, params PullRequestReviewWriteParams) (*mcp.CallToolResult, error) { @@ -1596,13 +1596,13 @@ func DeletePendingPullRequestReview(ctx context.Context, client *githubv4.Client // Validate there is one review and the state is pending if len(getLatestReviewForViewerQuery.Repository.PullRequest.Reviews.Nodes) == 0 { - return utils.NewToolResultError("No pending review found for the viewer"), nil + return mcpresult.NewError("No pending review found for the viewer"), nil } review := getLatestReviewForViewerQuery.Repository.PullRequest.Reviews.Nodes[0] if review.State != githubv4.PullRequestReviewStatePending { errText := fmt.Sprintf("The latest review, found at %s is not pending", review.URL) - return utils.NewToolResultError(errText), nil + return mcpresult.NewError(errText), nil } // Prepare the mutation @@ -1622,13 +1622,13 @@ func DeletePendingPullRequestReview(ctx context.Context, client *githubv4.Client }, nil, ); err != nil { - return utils.NewToolResultError(err.Error()), nil + return mcpresult.NewError(err.Error()), nil } // Return nothing interesting, just indicate success for the time being. // In future, we may want to return the review ID, but for the moment, we're not leaking // API implementation details to the LLM. - return utils.NewToolResultText("pending pull request review successfully deleted"), nil + return mcpresult.NewText("pending pull request review successfully deleted"), nil } // AddCommentToPendingReview creates a tool to add a comment to a pull request review. @@ -1718,12 +1718,12 @@ func AddCommentToPendingReview(t translations.TranslationHelperFunc) inventory.S StartSide *string } if err := mapstructure.Decode(args, ¶ms); err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetGQLClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub GQL client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub GQL client", err), nil, nil } // First we'll get the current user @@ -1770,13 +1770,13 @@ func AddCommentToPendingReview(t translations.TranslationHelperFunc) inventory.S // Validate there is one review and the state is pending if len(getLatestReviewForViewerQuery.Repository.PullRequest.Reviews.Nodes) == 0 { - return utils.NewToolResultError("No pending review found for the viewer"), nil, nil + return mcpresult.NewError("No pending review found for the viewer"), nil, nil } review := getLatestReviewForViewerQuery.Repository.PullRequest.Reviews.Nodes[0] if review.State != githubv4.PullRequestReviewStatePending { errText := fmt.Sprintf("The latest review, found at %s is not pending", review.URL) - return utils.NewToolResultError(errText), nil, nil + return mcpresult.NewError(errText), nil, nil } // Then we can create a new review thread comment on the review. @@ -1803,11 +1803,11 @@ func AddCommentToPendingReview(t translations.TranslationHelperFunc) inventory.S }, nil, ); err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } if addPullRequestReviewThreadMutation.AddPullRequestReviewThread.Thread.ID == nil { - return utils.NewToolResultError(`Failed to add comment to pending review. Possible reasons: + return mcpresult.NewError(`Failed to add comment to pending review. Possible reasons: - The line number doesn't exist in the pull request diff - The file path is incorrect - The side (LEFT/RIGHT) is invalid for the specified line @@ -1817,7 +1817,7 @@ func AddCommentToPendingReview(t translations.TranslationHelperFunc) inventory.S // Return nothing interesting, just indicate success for the time being. // In future, we may want to return the review ID, but for the moment, we're not leaking // API implementation details to the LLM. - return utils.NewToolResultText("pull request review comment successfully added to pending review"), nil, nil + return mcpresult.NewText("pull request review comment successfully added to pending review"), nil, nil }) } @@ -1860,22 +1860,22 @@ func RequestCopilotReview(t translations.TranslationHelperFunc) inventory.Server func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } pullNumber, err := RequiredInt(args, "pullNumber") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } _, resp, err := client.PullRequests.RequestReviewers( @@ -1900,13 +1900,13 @@ func RequestCopilotReview(t translations.TranslationHelperFunc) inventory.Server if resp.StatusCode != http.StatusCreated { bodyBytes, err := io.ReadAll(resp.Body) if err != nil { - return utils.NewToolResultErrorFromErr("failed to read response body", err), nil, nil + return mcpresult.NewErrorFromErr("failed to read response body", err), nil, nil } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to request copilot review", resp, bodyBytes), nil, nil } // Return nothing on success, as there's not much value in returning the Pull Request itself - return utils.NewToolResultText(""), nil, nil + return mcpresult.NewText(""), nil, nil }) } diff --git a/pkg/github/repositories.go b/pkg/github/repositories.go index f6203f39f..1398eabc1 100644 --- a/pkg/github/repositories.go +++ b/pkg/github/repositories.go @@ -11,10 +11,10 @@ import ( ghErrors "github.com/github/github-mcp-server/pkg/errors" "github.com/github/github-mcp-server/pkg/inventory" + "github.com/github/github-mcp-server/pkg/mcpresult" "github.com/github/github-mcp-server/pkg/octicons" "github.com/github/github-mcp-server/pkg/scopes" "github.com/github/github-mcp-server/pkg/translations" - "github.com/github/github-mcp-server/pkg/utils" "github.com/google/go-github/v79/github" "github.com/google/jsonschema-go/jsonschema" "github.com/modelcontextprotocol/go-sdk/mcp" @@ -58,23 +58,23 @@ func GetCommit(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } sha, err := RequiredParam[string](args, "sha") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } includeDiff, err := OptionalBoolParamWithDefault(args, "include_diff", true) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } pagination, err := OptionalPaginationParams(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } opts := &github.ListOptions{ @@ -112,7 +112,7 @@ func GetCommit(t translations.TranslationHelperFunc) inventory.ServerTool { return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -155,23 +155,23 @@ func ListCommits(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } sha, err := OptionalParam[string](args, "sha") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } author, err := OptionalParam[string](args, "author") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } pagination, err := OptionalPaginationParams(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Set default perPage to 30 if not provided perPage := pagination.PerPage @@ -220,7 +220,7 @@ func ListCommits(t translations.TranslationHelperFunc) inventory.ServerTool { return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -255,15 +255,15 @@ func ListBranches(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } pagination, err := OptionalPaginationParams(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } opts := &github.BranchListOptions{ @@ -307,7 +307,7 @@ func ListBranches(t translations.TranslationHelperFunc) inventory.ServerTool { return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -369,27 +369,27 @@ If the SHA is not provided, the tool will attempt to acquire it by fetching the func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } path, err := RequiredParam[string](args, "path") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } content, err := RequiredParam[string](args, "content") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } message, err := RequiredParam[string](args, "message") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } branch, err := RequiredParam[string](args, "branch") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // json.Marshal encodes byte arrays with base64, which is required for the API. @@ -405,7 +405,7 @@ If the SHA is not provided, the tool will attempt to acquire it by fetching the // If SHA is provided, set it (for updates) sha, err := OptionalParam[string](args, "sha") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } if sha != "" { opts.SHA = github.Ptr(sha) @@ -442,7 +442,7 @@ If the SHA is not provided, the tool will attempt to acquire it by fetching the case http.StatusOK: // SHA is stale - reject with current SHA so user can check diff currentSHA := strings.Trim(resp.Header.Get("ETag"), `"`) - return utils.NewToolResultError(fmt.Sprintf( + return mcpresult.NewError(fmt.Sprintf( "SHA mismatch: provided SHA %s is stale. Current file SHA is %s. "+ "Use get_file_contents or compare commits to review changes before updating.", sha, currentSHA)), nil, nil @@ -495,9 +495,9 @@ If the SHA is not provided, the tool will attempt to acquire it by fetching the // Warn if file was updated without SHA validation (blind update) if sha == "" && previousSHA != "" { - return utils.NewToolResultText(fmt.Sprintf( + return mcpresult.NewText(fmt.Sprintf( "Warning: File updated without SHA validation. Previous file SHA was %s. "+ - `Verify no unintended changes were overwritten: + `Verify no unintended changes were overwritten: 1. Extract the SHA of the local version using git ls-tree HEAD %s. 2. Compare with the previous SHA above. 3. Revert changes if shas do not match. @@ -506,7 +506,7 @@ If the SHA is not provided, the tool will attempt to acquire it by fetching the previousSHA, path, string(r))), nil, nil } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -553,23 +553,23 @@ func CreateRepository(t translations.TranslationHelperFunc) inventory.ServerTool func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { name, err := RequiredParam[string](args, "name") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } description, err := OptionalParam[string](args, "description") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } organization, err := OptionalParam[string](args, "organization") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } private, err := OptionalParam[bool](args, "private") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } autoInit, err := OptionalParam[bool](args, "autoInit") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo := &github.Repository{ @@ -612,7 +612,7 @@ func CreateRepository(t translations.TranslationHelperFunc) inventory.ServerTool return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -660,38 +660,38 @@ func GetFileContents(t translations.TranslationHelperFunc) inventory.ServerTool func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } path, err := OptionalParam[string](args, "path") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } path = strings.TrimPrefix(path, "/") ref, err := OptionalParam[string](args, "ref") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } originalRef := ref sha, err := OptionalParam[string](args, "sha") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultError("failed to get GitHub client"), nil, nil + return mcpresult.NewError("failed to get GitHub client"), nil, nil } rawOpts, fallbackUsed, err := resolveGitReference(ctx, client, owner, repo, ref, sha) if err != nil { - return utils.NewToolResultError(fmt.Sprintf("failed to resolve git reference: %s", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("failed to resolve git reference: %s", err)), nil, nil } if rawOpts.SHA != "" { @@ -718,11 +718,11 @@ func GetFileContents(t translations.TranslationHelperFunc) inventory.ServerTool rawClient, err := deps.GetRawClient(ctx) if err != nil { - return utils.NewToolResultError("failed to get GitHub raw content client"), nil, nil + return mcpresult.NewError("failed to get GitHub raw content client"), nil, nil } resp, err := rawClient.GetRawContent(ctx, owner, repo, path, rawOpts) if err != nil { - return utils.NewToolResultError("failed to get raw repository content"), nil, nil + return mcpresult.NewError("failed to get raw repository content"), nil, nil } defer func() { _ = resp.Body.Close() @@ -776,9 +776,9 @@ func GetFileContents(t translations.TranslationHelperFunc) inventory.ServerTool } // Include SHA in the result metadata if fileSHA != "" { - return utils.NewToolResultResource(fmt.Sprintf("successfully downloaded text file (SHA: %s)", fileSHA)+successNote, result), nil, nil + return mcpresult.NewResource(fmt.Sprintf("successfully downloaded text file (SHA: %s)", fileSHA)+successNote, result), nil, nil } - return utils.NewToolResultResource("successfully downloaded text file"+successNote, result), nil, nil + return mcpresult.NewResource("successfully downloaded text file"+successNote, result), nil, nil } result := &mcp.ResourceContents{ @@ -788,9 +788,9 @@ func GetFileContents(t translations.TranslationHelperFunc) inventory.ServerTool } // Include SHA in the result metadata if fileSHA != "" { - return utils.NewToolResultResource(fmt.Sprintf("successfully downloaded binary file (SHA: %s)", fileSHA)+successNote, result), nil, nil + return mcpresult.NewResource(fmt.Sprintf("successfully downloaded binary file (SHA: %s)", fileSHA)+successNote, result), nil, nil } - return utils.NewToolResultResource("successfully downloaded binary file"+successNote, result), nil, nil + return mcpresult.NewResource("successfully downloaded binary file"+successNote, result), nil, nil } // Raw API call failed @@ -799,12 +799,12 @@ func GetFileContents(t translations.TranslationHelperFunc) inventory.ServerTool // file content or file SHA is nil which means it's a directory r, err := json.Marshal(dirContent) if err != nil { - return utils.NewToolResultError("failed to marshal response"), nil, nil + return mcpresult.NewError("failed to marshal response"), nil, nil } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } - return utils.NewToolResultError("failed to get file contents"), nil, nil + return mcpresult.NewError("failed to get file contents"), nil, nil }, ) } @@ -844,15 +844,15 @@ func ForkRepository(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } org, err := OptionalParam[string](args, "organization") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } opts := &github.RepositoryCreateForkOptions{} @@ -869,7 +869,7 @@ func ForkRepository(t translations.TranslationHelperFunc) inventory.ServerTool { // Check if it's an acceptedError. An acceptedError indicates that the update is in progress, // and it's not a real error. if resp != nil && resp.StatusCode == http.StatusAccepted && isAcceptedError(err) { - return utils.NewToolResultText("Fork is in progress"), nil, nil + return mcpresult.NewText("Fork is in progress"), nil, nil } return ghErrors.NewGitHubAPIErrorResponse(ctx, "failed to fork repository", @@ -898,7 +898,7 @@ func ForkRepository(t translations.TranslationHelperFunc) inventory.ServerTool { return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -951,23 +951,23 @@ func DeleteFile(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } path, err := RequiredParam[string](args, "path") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } message, err := RequiredParam[string](args, "message") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } branch, err := RequiredParam[string](args, "branch") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) @@ -1088,7 +1088,7 @@ func DeleteFile(t translations.TranslationHelperFunc) inventory.ServerTool { return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -1131,19 +1131,19 @@ func CreateBranch(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } branch, err := RequiredParam[string](args, "branch") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } fromBranch, err := OptionalParam[string](args, "from_branch") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) @@ -1201,7 +1201,7 @@ func CreateBranch(t translations.TranslationHelperFunc) inventory.ServerTool { return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -1262,25 +1262,25 @@ func PushFiles(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } branch, err := RequiredParam[string](args, "branch") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } message, err := RequiredParam[string](args, "message") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } // Parse files parameter - this should be an array of objects with path and content filesObj, ok := args["files"].([]interface{}) if !ok { - return utils.NewToolResultError("files parameter must be an array of objects with path and content"), nil, nil + return mcpresult.NewError("files parameter must be an array of objects with path and content"), nil, nil } client, err := deps.GetClient(ctx) @@ -1320,7 +1320,7 @@ func PushFiles(t translations.TranslationHelperFunc) inventory.ServerTool { if branchNotFound { ref, err = createReferenceFromDefaultBranch(ctx, client, owner, repo, branch) if err != nil { - return utils.NewToolResultError(fmt.Sprintf("failed to create branch from default: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("failed to create branch from default: %v", err)), nil, nil } } @@ -1341,7 +1341,7 @@ func PushFiles(t translations.TranslationHelperFunc) inventory.ServerTool { // Repository is empty, need to initialize it first ref, base, err = initializeRepository(ctx, client, owner, repo) if err != nil { - return utils.NewToolResultError(fmt.Sprintf("failed to initialize repository: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("failed to initialize repository: %v", err)), nil, nil } defaultBranch := strings.TrimPrefix(*ref.Ref, "refs/heads/") @@ -1349,7 +1349,7 @@ func PushFiles(t translations.TranslationHelperFunc) inventory.ServerTool { // Create the requested branch from the default branch ref, err = createReferenceFromDefaultBranch(ctx, client, owner, repo, branch) if err != nil { - return utils.NewToolResultError(fmt.Sprintf("failed to create branch from default: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("failed to create branch from default: %v", err)), nil, nil } } @@ -1362,17 +1362,17 @@ func PushFiles(t translations.TranslationHelperFunc) inventory.ServerTool { for _, file := range filesObj { fileMap, ok := file.(map[string]interface{}) if !ok { - return utils.NewToolResultError("each file must be an object with path and content"), nil, nil + return mcpresult.NewError("each file must be an object with path and content"), nil, nil } path, ok := fileMap["path"].(string) if !ok || path == "" { - return utils.NewToolResultError("each file must have a path"), nil, nil + return mcpresult.NewError("each file must have a path"), nil, nil } content, ok := fileMap["content"].(string) if !ok { - return utils.NewToolResultError("each file must have content"), nil, nil + return mcpresult.NewError("each file must have content"), nil, nil } // Create a tree entry for the file @@ -1435,7 +1435,7 @@ func PushFiles(t translations.TranslationHelperFunc) inventory.ServerTool { return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -1470,15 +1470,15 @@ func ListTags(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } pagination, err := OptionalPaginationParams(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } opts := &github.ListOptions{ @@ -1514,7 +1514,7 @@ func ListTags(t translations.TranslationHelperFunc) inventory.ServerTool { return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -1553,15 +1553,15 @@ func GetTag(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } tag, err := RequiredParam[string](args, "tag") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) @@ -1612,7 +1612,7 @@ func GetTag(t translations.TranslationHelperFunc) inventory.ServerTool { return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -1647,15 +1647,15 @@ func ListReleases(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } pagination, err := OptionalPaginationParams(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } opts := &github.ListOptions{ @@ -1687,7 +1687,7 @@ func ListReleases(t translations.TranslationHelperFunc) inventory.ServerTool { return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -1722,11 +1722,11 @@ func GetLatestRelease(t translations.TranslationHelperFunc) inventory.ServerTool func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) @@ -1753,7 +1753,7 @@ func GetLatestRelease(t translations.TranslationHelperFunc) inventory.ServerTool return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -1791,15 +1791,15 @@ func GetReleaseByTag(t translations.TranslationHelperFunc) inventory.ServerTool func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } tag, err := RequiredParam[string](args, "tag") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) @@ -1830,7 +1830,7 @@ func GetReleaseByTag(t translations.TranslationHelperFunc) inventory.ServerTool return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -1870,19 +1870,19 @@ func ListStarredRepositories(t translations.TranslationHelperFunc) inventory.Ser func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { username, err := OptionalParam[string](args, "username") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } sort, err := OptionalParam[string](args, "sort") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } direction, err := OptionalParam[string](args, "direction") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } pagination, err := OptionalPaginationParams(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } opts := &github.ActivityListStarredOptions{ @@ -1962,7 +1962,7 @@ func ListStarredRepositories(t translations.TranslationHelperFunc) inventory.Ser return nil, nil, fmt.Errorf("failed to marshal starred repositories: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -1998,11 +1998,11 @@ func StarRepository(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) @@ -2028,7 +2028,7 @@ func StarRepository(t translations.TranslationHelperFunc) inventory.ServerTool { return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to star repository", resp, body), nil, nil } - return utils.NewToolResultText(fmt.Sprintf("Successfully starred repository %s/%s", owner, repo)), nil, nil + return mcpresult.NewText(fmt.Sprintf("Successfully starred repository %s/%s", owner, repo)), nil, nil }, ) } @@ -2063,11 +2063,11 @@ func UnstarRepository(t translations.TranslationHelperFunc) inventory.ServerTool func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) @@ -2093,7 +2093,7 @@ func UnstarRepository(t translations.TranslationHelperFunc) inventory.ServerTool return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to unstar repository", resp, body), nil, nil } - return utils.NewToolResultText(fmt.Sprintf("Successfully unstarred repository %s/%s", owner, repo)), nil, nil + return mcpresult.NewText(fmt.Sprintf("Successfully unstarred repository %s/%s", owner, repo)), nil, nil }, ) } diff --git a/pkg/github/repositories_helper.go b/pkg/github/repositories_helper.go index de5065d48..d88aeeda4 100644 --- a/pkg/github/repositories_helper.go +++ b/pkg/github/repositories_helper.go @@ -8,8 +8,8 @@ import ( "strings" ghErrors "github.com/github/github-mcp-server/pkg/errors" + "github.com/github/github-mcp-server/pkg/mcpresult" "github.com/github/github-mcp-server/pkg/raw" - "github.com/github/github-mcp-server/pkg/utils" "github.com/google/go-github/v79/github" "github.com/modelcontextprotocol/go-sdk/mcp" ) @@ -110,18 +110,18 @@ func matchFiles(ctx context.Context, client *github.Client, owner, repo, ref, pa if len(matchingFiles) > 0 { matchingFilesJSON, err := json.Marshal(matchingFiles) if err != nil { - return utils.NewToolResultError(fmt.Sprintf("failed to marshal matching files: %s", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("failed to marshal matching files: %s", err)), nil, nil } resolvedRefs, err := json.Marshal(rawOpts) if err != nil { - return utils.NewToolResultError(fmt.Sprintf("failed to marshal resolved refs: %s", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("failed to marshal resolved refs: %s", err)), nil, nil } if rawAPIResponseCode > 0 { - return utils.NewToolResultText(fmt.Sprintf("Resolved potential matches in the repository tree (resolved refs: %s, matching files: %s), but the content API returned an unexpected status code %d.", string(resolvedRefs), string(matchingFilesJSON), rawAPIResponseCode)), nil, nil + return mcpresult.NewText(fmt.Sprintf("Resolved potential matches in the repository tree (resolved refs: %s, matching files: %s), but the content API returned an unexpected status code %d.", string(resolvedRefs), string(matchingFilesJSON), rawAPIResponseCode)), nil, nil } - return utils.NewToolResultText(fmt.Sprintf("Resolved potential matches in the repository tree (resolved refs: %s, matching files: %s).", string(resolvedRefs), string(matchingFilesJSON))), nil, nil + return mcpresult.NewText(fmt.Sprintf("Resolved potential matches in the repository tree (resolved refs: %s, matching files: %s).", string(resolvedRefs), string(matchingFilesJSON))), nil, nil } - return utils.NewToolResultError("Failed to get file contents. The path does not point to a file or directory, or the file does not exist in the repository."), nil, nil + return mcpresult.NewError("Failed to get file contents. The path does not point to a file or directory, or the file does not exist in the repository."), nil, nil } // filterPaths filters the entries in a GitHub tree to find paths that diff --git a/pkg/github/repositories_test.go b/pkg/github/repositories_test.go index d91af8851..d261ff540 100644 --- a/pkg/github/repositories_test.go +++ b/pkg/github/repositories_test.go @@ -11,9 +11,9 @@ import ( "time" "github.com/github/github-mcp-server/internal/toolsnaps" + "github.com/github/github-mcp-server/pkg/mcpresult" "github.com/github/github-mcp-server/pkg/raw" "github.com/github/github-mcp-server/pkg/translations" - "github.com/github/github-mcp-server/pkg/utils" "github.com/google/go-github/v79/github" "github.com/google/jsonschema-go/jsonschema" "github.com/modelcontextprotocol/go-sdk/mcp" @@ -339,7 +339,7 @@ func Test_GetFileContents(t *testing.T) { "ref": "refs/heads/main", }, expectError: false, - expectedResult: utils.NewToolResultError("Failed to get file contents. The path does not point to a file or directory, or the file does not exist in the repository."), + expectedResult: mcpresult.NewError("Failed to get file contents. The path does not point to a file or directory, or the file does not exist in the repository."), }, } diff --git a/pkg/github/search.go b/pkg/github/search.go index 552fbfe78..3bb95d4be 100644 --- a/pkg/github/search.go +++ b/pkg/github/search.go @@ -9,9 +9,9 @@ import ( ghErrors "github.com/github/github-mcp-server/pkg/errors" "github.com/github/github-mcp-server/pkg/inventory" + "github.com/github/github-mcp-server/pkg/mcpresult" "github.com/github/github-mcp-server/pkg/scopes" "github.com/github/github-mcp-server/pkg/translations" - "github.com/github/github-mcp-server/pkg/utils" "github.com/google/go-github/v79/github" "github.com/google/jsonschema-go/jsonschema" "github.com/modelcontextprotocol/go-sdk/mcp" @@ -61,23 +61,23 @@ func SearchRepositories(t translations.TranslationHelperFunc) inventory.ServerTo func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { query, err := RequiredParam[string](args, "query") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } sort, err := OptionalParam[string](args, "sort") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } order, err := OptionalParam[string](args, "order") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } pagination, err := OptionalPaginationParams(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } minimalOutput, err := OptionalBoolParamWithDefault(args, "minimal_output", true) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } opts := &github.SearchOptions{ Sort: sort, @@ -90,7 +90,7 @@ func SearchRepositories(t translations.TranslationHelperFunc) inventory.ServerTo client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } result, resp, err := client.Search.Repositories(ctx, query, opts) if err != nil { @@ -105,7 +105,7 @@ func SearchRepositories(t translations.TranslationHelperFunc) inventory.ServerTo if resp.StatusCode != http.StatusOK { body, err := io.ReadAll(resp.Body) if err != nil { - return utils.NewToolResultErrorFromErr("failed to read response body", err), nil, nil + return mcpresult.NewErrorFromErr("failed to read response body", err), nil, nil } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to search repositories", resp, body), nil, nil } @@ -152,16 +152,16 @@ func SearchRepositories(t translations.TranslationHelperFunc) inventory.ServerTo r, err = json.Marshal(minimalResult) if err != nil { - return utils.NewToolResultErrorFromErr("failed to marshal minimal response", err), nil, nil + return mcpresult.NewErrorFromErr("failed to marshal minimal response", err), nil, nil } } else { r, err = json.Marshal(result) if err != nil { - return utils.NewToolResultErrorFromErr("failed to marshal full response", err), nil, nil + return mcpresult.NewErrorFromErr("failed to marshal full response", err), nil, nil } } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -204,19 +204,19 @@ func SearchCode(t translations.TranslationHelperFunc) inventory.ServerTool { func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { query, err := RequiredParam[string](args, "query") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } sort, err := OptionalParam[string](args, "sort") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } order, err := OptionalParam[string](args, "order") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } pagination, err := OptionalPaginationParams(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } opts := &github.SearchOptions{ @@ -230,7 +230,7 @@ func SearchCode(t translations.TranslationHelperFunc) inventory.ServerTool { client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } result, resp, err := client.Search.Code(ctx, query, opts) @@ -246,17 +246,17 @@ func SearchCode(t translations.TranslationHelperFunc) inventory.ServerTool { if resp.StatusCode != http.StatusOK { body, err := io.ReadAll(resp.Body) if err != nil { - return utils.NewToolResultErrorFromErr("failed to read response body", err), nil, nil + return mcpresult.NewErrorFromErr("failed to read response body", err), nil, nil } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to search code", resp, body), nil, nil } r, err := json.Marshal(result) if err != nil { - return utils.NewToolResultErrorFromErr("failed to marshal response", err), nil, nil + return mcpresult.NewErrorFromErr("failed to marshal response", err), nil, nil } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -264,19 +264,19 @@ func SearchCode(t translations.TranslationHelperFunc) inventory.ServerTool { func userOrOrgHandler(ctx context.Context, accountType string, deps ToolDependencies, args map[string]any) (*mcp.CallToolResult, any, error) { query, err := RequiredParam[string](args, "query") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } sort, err := OptionalParam[string](args, "sort") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } order, err := OptionalParam[string](args, "order") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } pagination, err := OptionalPaginationParams(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } opts := &github.SearchOptions{ @@ -290,7 +290,7 @@ func userOrOrgHandler(ctx context.Context, accountType string, deps ToolDependen client, err := deps.GetClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil + return mcpresult.NewErrorFromErr("failed to get GitHub client", err), nil, nil } searchQuery := query @@ -310,7 +310,7 @@ func userOrOrgHandler(ctx context.Context, accountType string, deps ToolDependen if resp.StatusCode != http.StatusOK { body, err := io.ReadAll(resp.Body) if err != nil { - return utils.NewToolResultErrorFromErr("failed to read response body", err), nil, nil + return mcpresult.NewErrorFromErr("failed to read response body", err), nil, nil } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, fmt.Sprintf("failed to search %ss", accountType), resp, body), nil, nil } @@ -342,9 +342,9 @@ func userOrOrgHandler(ctx context.Context, accountType string, deps ToolDependen r, err := json.Marshal(minimalResp) if err != nil { - return utils.NewToolResultErrorFromErr("failed to marshal response", err), nil, nil + return mcpresult.NewErrorFromErr("failed to marshal response", err), nil, nil } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil } // SearchUsers creates a tool to search for GitHub users. diff --git a/pkg/github/search_utils.go b/pkg/github/search_utils.go index 1008200d1..77eed5d2b 100644 --- a/pkg/github/search_utils.go +++ b/pkg/github/search_utils.go @@ -9,7 +9,7 @@ import ( "regexp" ghErrors "github.com/github/github-mcp-server/pkg/errors" - "github.com/github/github-mcp-server/pkg/utils" + "github.com/github/github-mcp-server/pkg/mcpresult" "github.com/google/go-github/v79/github" "github.com/modelcontextprotocol/go-sdk/mcp" ) @@ -46,7 +46,7 @@ func searchHandler( ) (*mcp.CallToolResult, error) { query, err := RequiredParam[string](args, "query") if err != nil { - return utils.NewToolResultError(err.Error()), nil + return mcpresult.NewError(err.Error()), nil } if !hasSpecificFilter(query, "is", searchType) { @@ -55,12 +55,12 @@ func searchHandler( owner, err := OptionalParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil + return mcpresult.NewError(err.Error()), nil } repo, err := OptionalParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil + return mcpresult.NewError(err.Error()), nil } if owner != "" && repo != "" && !hasRepoFilter(query) { @@ -69,15 +69,15 @@ func searchHandler( sort, err := OptionalParam[string](args, "sort") if err != nil { - return utils.NewToolResultError(err.Error()), nil + return mcpresult.NewError(err.Error()), nil } order, err := OptionalParam[string](args, "order") if err != nil { - return utils.NewToolResultError(err.Error()), nil + return mcpresult.NewError(err.Error()), nil } pagination, err := OptionalPaginationParams(args) if err != nil { - return utils.NewToolResultError(err.Error()), nil + return mcpresult.NewError(err.Error()), nil } opts := &github.SearchOptions{ @@ -92,26 +92,26 @@ func searchHandler( client, err := getClient(ctx) if err != nil { - return utils.NewToolResultErrorFromErr(errorPrefix+": failed to get GitHub client", err), nil + return mcpresult.NewErrorFromErr(errorPrefix+": failed to get GitHub client", err), nil } result, resp, err := client.Search.Issues(ctx, query, opts) if err != nil { - return utils.NewToolResultErrorFromErr(errorPrefix, err), nil + return mcpresult.NewErrorFromErr(errorPrefix, err), nil } defer func() { _ = resp.Body.Close() }() if resp.StatusCode != http.StatusOK { body, err := io.ReadAll(resp.Body) if err != nil { - return utils.NewToolResultErrorFromErr(errorPrefix+": failed to read response body", err), nil + return mcpresult.NewErrorFromErr(errorPrefix+": failed to read response body", err), nil } return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, errorPrefix, resp, body), nil } r, err := json.Marshal(result) if err != nil { - return utils.NewToolResultErrorFromErr(errorPrefix+": failed to marshal response", err), nil + return mcpresult.NewErrorFromErr(errorPrefix+": failed to marshal response", err), nil } - return utils.NewToolResultText(string(r)), nil + return mcpresult.NewText(string(r)), nil } diff --git a/pkg/github/secret_scanning.go b/pkg/github/secret_scanning.go index fa60021e5..26817992c 100644 --- a/pkg/github/secret_scanning.go +++ b/pkg/github/secret_scanning.go @@ -9,9 +9,9 @@ import ( ghErrors "github.com/github/github-mcp-server/pkg/errors" "github.com/github/github-mcp-server/pkg/inventory" + "github.com/github/github-mcp-server/pkg/mcpresult" "github.com/github/github-mcp-server/pkg/scopes" "github.com/github/github-mcp-server/pkg/translations" - "github.com/github/github-mcp-server/pkg/utils" "github.com/google/go-github/v79/github" "github.com/google/jsonschema-go/jsonschema" "github.com/modelcontextprotocol/go-sdk/mcp" @@ -50,15 +50,15 @@ func GetSecretScanningAlert(t translations.TranslationHelperFunc) inventory.Serv func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } alertNumber, err := RequiredInt(args, "alertNumber") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) @@ -89,7 +89,7 @@ func GetSecretScanningAlert(t translations.TranslationHelperFunc) inventory.Serv return nil, nil, fmt.Errorf("failed to marshal alert: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -137,23 +137,23 @@ func ListSecretScanningAlerts(t translations.TranslationHelperFunc) inventory.Se func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } state, err := OptionalParam[string](args, "state") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } secretType, err := OptionalParam[string](args, "secret_type") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } resolution, err := OptionalParam[string](args, "resolution") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) @@ -183,7 +183,7 @@ func ListSecretScanningAlerts(t translations.TranslationHelperFunc) inventory.Se return nil, nil, fmt.Errorf("failed to marshal alerts: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } diff --git a/pkg/github/security_advisories.go b/pkg/github/security_advisories.go index 7bdb978cd..176d308ac 100644 --- a/pkg/github/security_advisories.go +++ b/pkg/github/security_advisories.go @@ -9,9 +9,9 @@ import ( ghErrors "github.com/github/github-mcp-server/pkg/errors" "github.com/github/github-mcp-server/pkg/inventory" + "github.com/github/github-mcp-server/pkg/mcpresult" "github.com/github/github-mcp-server/pkg/scopes" "github.com/github/github-mcp-server/pkg/translations" - "github.com/github/github-mcp-server/pkg/utils" "github.com/google/go-github/v79/github" "github.com/google/jsonschema-go/jsonschema" "github.com/modelcontextprotocol/go-sdk/mcp" @@ -93,57 +93,57 @@ func ListGlobalSecurityAdvisories(t translations.TranslationHelperFunc) inventor ghsaID, err := OptionalParam[string](args, "ghsaId") if err != nil { - return utils.NewToolResultError(fmt.Sprintf("invalid ghsaId: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("invalid ghsaId: %v", err)), nil, nil } typ, err := OptionalParam[string](args, "type") if err != nil { - return utils.NewToolResultError(fmt.Sprintf("invalid type: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("invalid type: %v", err)), nil, nil } cveID, err := OptionalParam[string](args, "cveId") if err != nil { - return utils.NewToolResultError(fmt.Sprintf("invalid cveId: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("invalid cveId: %v", err)), nil, nil } eco, err := OptionalParam[string](args, "ecosystem") if err != nil { - return utils.NewToolResultError(fmt.Sprintf("invalid ecosystem: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("invalid ecosystem: %v", err)), nil, nil } sev, err := OptionalParam[string](args, "severity") if err != nil { - return utils.NewToolResultError(fmt.Sprintf("invalid severity: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("invalid severity: %v", err)), nil, nil } cwes, err := OptionalStringArrayParam(args, "cwes") if err != nil { - return utils.NewToolResultError(fmt.Sprintf("invalid cwes: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("invalid cwes: %v", err)), nil, nil } isWithdrawn, err := OptionalParam[bool](args, "isWithdrawn") if err != nil { - return utils.NewToolResultError(fmt.Sprintf("invalid isWithdrawn: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("invalid isWithdrawn: %v", err)), nil, nil } affects, err := OptionalParam[string](args, "affects") if err != nil { - return utils.NewToolResultError(fmt.Sprintf("invalid affects: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("invalid affects: %v", err)), nil, nil } published, err := OptionalParam[string](args, "published") if err != nil { - return utils.NewToolResultError(fmt.Sprintf("invalid published: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("invalid published: %v", err)), nil, nil } updated, err := OptionalParam[string](args, "updated") if err != nil { - return utils.NewToolResultError(fmt.Sprintf("invalid updated: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("invalid updated: %v", err)), nil, nil } modified, err := OptionalParam[string](args, "modified") if err != nil { - return utils.NewToolResultError(fmt.Sprintf("invalid modified: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("invalid modified: %v", err)), nil, nil } opts := &github.ListGlobalSecurityAdvisoriesOptions{} @@ -203,7 +203,7 @@ func ListGlobalSecurityAdvisories(t translations.TranslationHelperFunc) inventor return nil, nil, fmt.Errorf("failed to marshal advisories: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -252,24 +252,24 @@ func ListRepositorySecurityAdvisories(t translations.TranslationHelperFunc) inve func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { owner, err := RequiredParam[string](args, "owner") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } repo, err := RequiredParam[string](args, "repo") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } direction, err := OptionalParam[string](args, "direction") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } sortField, err := OptionalParam[string](args, "sort") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } state, err := OptionalParam[string](args, "state") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) @@ -307,7 +307,7 @@ func ListRepositorySecurityAdvisories(t translations.TranslationHelperFunc) inve return nil, nil, fmt.Errorf("failed to marshal advisories: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -342,7 +342,7 @@ func GetGlobalSecurityAdvisory(t translations.TranslationHelperFunc) inventory.S ghsaID, err := RequiredParam[string](args, "ghsaId") if err != nil { - return utils.NewToolResultError(fmt.Sprintf("invalid ghsaId: %v", err)), nil, nil + return mcpresult.NewError(fmt.Sprintf("invalid ghsaId: %v", err)), nil, nil } advisory, resp, err := client.SecurityAdvisories.GetGlobalSecurityAdvisories(ctx, ghsaID) @@ -364,7 +364,7 @@ func GetGlobalSecurityAdvisory(t translations.TranslationHelperFunc) inventory.S return nil, nil, fmt.Errorf("failed to marshal advisory: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } @@ -409,19 +409,19 @@ func ListOrgRepositorySecurityAdvisories(t translations.TranslationHelperFunc) i func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { org, err := RequiredParam[string](args, "org") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } direction, err := OptionalParam[string](args, "direction") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } sortField, err := OptionalParam[string](args, "sort") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } state, err := OptionalParam[string](args, "state") if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil + return mcpresult.NewError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) @@ -459,7 +459,7 @@ func ListOrgRepositorySecurityAdvisories(t translations.TranslationHelperFunc) i return nil, nil, fmt.Errorf("failed to marshal advisories: %w", err) } - return utils.NewToolResultText(string(r)), nil, nil + return mcpresult.NewText(string(r)), nil, nil }, ) } diff --git a/pkg/github/server.go b/pkg/github/server.go index 8248da58f..9355bce54 100644 --- a/pkg/github/server.go +++ b/pkg/github/server.go @@ -8,8 +8,8 @@ import ( "strconv" "strings" + "github.com/github/github-mcp-server/pkg/mcpresult" "github.com/github/github-mcp-server/pkg/octicons" - "github.com/github/github-mcp-server/pkg/utils" "github.com/google/go-github/v79/github" "github.com/google/jsonschema-go/jsonschema" "github.com/modelcontextprotocol/go-sdk/mcp" @@ -435,8 +435,8 @@ func (p PaginationParams) ToGraphQLParams() (*GraphQLPaginationParams, error) { func MarshalledTextResult(v any) *mcp.CallToolResult { data, err := json.Marshal(v) if err != nil { - return utils.NewToolResultErrorFromErr("failed to marshal text result to json", err) + return mcpresult.NewErrorFromErr("failed to marshal text result to json", err) } - return utils.NewToolResultText(string(data)) + return mcpresult.NewText(string(data)) } diff --git a/pkg/mcpresult/mcpresult.go b/pkg/mcpresult/mcpresult.go new file mode 100644 index 000000000..355959c73 --- /dev/null +++ b/pkg/mcpresult/mcpresult.go @@ -0,0 +1,53 @@ +package mcpresult + +import "github.com/modelcontextprotocol/go-sdk/mcp" + +// NewText wraps MCP call result creation for a successful text-only response. +func NewText(message string) *mcp.CallToolResult { + return &mcp.CallToolResult{ + Content: []mcp.Content{ + &mcp.TextContent{ + Text: message, + }, + }, + } +} + +// NewError wraps MCP call result creation for an error response with just a message. +func NewError(message string) *mcp.CallToolResult { + return &mcp.CallToolResult{ + Content: []mcp.Content{ + &mcp.TextContent{ + Text: message, + }, + }, + IsError: true, + } +} + +// NewErrorFromErr wraps MCP call result creation for an error that includes context and the underlying error. +func NewErrorFromErr(message string, err error) *mcp.CallToolResult { + return &mcp.CallToolResult{ + Content: []mcp.Content{ + &mcp.TextContent{ + Text: message + ": " + err.Error(), + }, + }, + IsError: true, + } +} + +// NewResource wraps MCP call result creation for a success response with text plus an embedded resource. +func NewResource(message string, contents *mcp.ResourceContents) *mcp.CallToolResult { + return &mcp.CallToolResult{ + Content: []mcp.Content{ + &mcp.TextContent{ + Text: message, + }, + &mcp.EmbeddedResource{ + Resource: contents, + }, + }, + IsError: false, + } +} diff --git a/pkg/utils/result.go b/pkg/utils/result.go index 533fe0573..6ce62042b 100644 --- a/pkg/utils/result.go +++ b/pkg/utils/result.go @@ -1,49 +1,27 @@ -package utils //nolint:revive //TODO: figure out a better name for this package +// Package utils is deprecated: use pkg/mcpresult instead +package utils //nolint:revive // vague package name -import "github.com/modelcontextprotocol/go-sdk/mcp" +import ( + "github.com/github/github-mcp-server/pkg/mcpresult" + "github.com/modelcontextprotocol/go-sdk/mcp" +) +// Deprecated: use [mcpresult.NewText] instead. func NewToolResultText(message string) *mcp.CallToolResult { - return &mcp.CallToolResult{ - Content: []mcp.Content{ - &mcp.TextContent{ - Text: message, - }, - }, - } + return mcpresult.NewText(message) } +// Deprecated: use [mcpresult.NewError] instead. func NewToolResultError(message string) *mcp.CallToolResult { - return &mcp.CallToolResult{ - Content: []mcp.Content{ - &mcp.TextContent{ - Text: message, - }, - }, - IsError: true, - } + return mcpresult.NewError(message) } +// Deprecated: use [mcpresult.NewErrorFromErr] instead. func NewToolResultErrorFromErr(message string, err error) *mcp.CallToolResult { - return &mcp.CallToolResult{ - Content: []mcp.Content{ - &mcp.TextContent{ - Text: message + ": " + err.Error(), - }, - }, - IsError: true, - } + return mcpresult.NewErrorFromErr(message, err) } +// Deprecated: use [mcpresult.NewResource] instead. func NewToolResultResource(message string, contents *mcp.ResourceContents) *mcp.CallToolResult { - return &mcp.CallToolResult{ - Content: []mcp.Content{ - &mcp.TextContent{ - Text: message, - }, - &mcp.EmbeddedResource{ - Resource: contents, - }, - }, - IsError: false, - } + return mcpresult.NewResource(message, contents) }