Files
github--github-mcp-server/pkg/errors/error.go
copilot-swe-agent[bot] df19fc28ea
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
Build and Test Go Project / build (macos-latest) (push) Has been cancelled
Build and Test Go Project / build (ubuntu-latest) (push) Has been cancelled
Build and Test Go Project / build (windows-latest) (push) Has been cancelled
Replace context-based error handling with CallToolResult.SetError
Migrate from storing GitHub API errors in context via middleware to
embedding typed errors directly in CallToolResult using the Go SDK
v1.3.0 SetError/GetError API.

Key changes:
- NewGitHubAPIErrorResponse/NewGitHubGraphQLErrorResponse/
  NewGitHubRawAPIErrorResponse now use result.SetError() with typed
  errors instead of storing in context
- Add Unwrap() to all error types for errors.As/errors.Is support
- Export error constructors (NewGitHubAPIError, etc.) for direct use
- Remove context-based error infrastructure (ContextWithGitHubErrors,
  GetGitHubAPIErrors, GitHubCtxErrors, etc.)
- Remove addGitHubAPIErrorToContext middleware from server.go
- Remove NewGitHubAPIErrorToCtx/NewGitHubGraphQLErrorToCtx and their
  callers in repositories_helper.go and actions.go
- Update tests to verify SetError/GetError and errors.As extraction
- Update error-handling.md documentation

Co-authored-by: SamMorrowDrums <4811358+SamMorrowDrums@users.noreply.github.com>
2026-02-18 15:22:37 +00:00

119 lines
3.9 KiB
Go

package errors
import (
"context"
"fmt"
"net/http"
"github.com/google/go-github/v82/github"
"github.com/modelcontextprotocol/go-sdk/mcp"
)
// GitHubAPIError represents an error from the GitHub REST API.
// Use errors.As to extract this from a CallToolResult.GetError().
type GitHubAPIError struct {
Message string `json:"message"`
Response *github.Response `json:"-"`
Err error `json:"-"`
}
// NewGitHubAPIError creates a new GitHubAPIError with the provided message, response, and error.
func NewGitHubAPIError(message string, resp *github.Response, err error) *GitHubAPIError {
return &GitHubAPIError{
Message: message,
Response: resp,
Err: err,
}
}
func (e *GitHubAPIError) Error() string {
return fmt.Errorf("%s: %w", e.Message, e.Err).Error()
}
func (e *GitHubAPIError) Unwrap() error {
return e.Err
}
// GitHubGraphQLError represents an error from the GitHub GraphQL API.
// Use errors.As to extract this from a CallToolResult.GetError().
type GitHubGraphQLError struct {
Message string `json:"message"`
Err error `json:"-"`
}
// NewGitHubGraphQLError creates a new GitHubGraphQLError with the provided message and error.
func NewGitHubGraphQLError(message string, err error) *GitHubGraphQLError {
return &GitHubGraphQLError{
Message: message,
Err: err,
}
}
func (e *GitHubGraphQLError) Error() string {
return fmt.Errorf("%s: %w", e.Message, e.Err).Error()
}
func (e *GitHubGraphQLError) Unwrap() error {
return e.Err
}
// GitHubRawAPIError represents an error from a raw HTTP GitHub API call.
// Use errors.As to extract this from a CallToolResult.GetError().
type GitHubRawAPIError struct {
Message string `json:"message"`
Response *http.Response `json:"-"`
Err error `json:"-"`
}
// NewGitHubRawAPIError creates a new GitHubRawAPIError with the provided message, response, and error.
func NewGitHubRawAPIError(message string, resp *http.Response, err error) *GitHubRawAPIError {
return &GitHubRawAPIError{
Message: message,
Response: resp,
Err: err,
}
}
func (e *GitHubRawAPIError) Error() string {
return fmt.Errorf("%s: %w", e.Message, e.Err).Error()
}
func (e *GitHubRawAPIError) Unwrap() error {
return e.Err
}
// NewGitHubAPIErrorResponse returns a CallToolResult with the error set via SetError,
// embedding a typed GitHubAPIError accessible via result.GetError() and errors.As.
func NewGitHubAPIErrorResponse(_ context.Context, message string, resp *github.Response, err error) *mcp.CallToolResult {
apiErr := NewGitHubAPIError(message, resp, err)
var result mcp.CallToolResult
result.SetError(apiErr)
return &result
}
// NewGitHubGraphQLErrorResponse returns a CallToolResult with the error set via SetError,
// embedding a typed GitHubGraphQLError accessible via result.GetError() and errors.As.
func NewGitHubGraphQLErrorResponse(_ context.Context, message string, err error) *mcp.CallToolResult {
graphQLErr := NewGitHubGraphQLError(message, err)
var result mcp.CallToolResult
result.SetError(graphQLErr)
return &result
}
// NewGitHubRawAPIErrorResponse returns a CallToolResult with the error set via SetError,
// embedding a typed GitHubRawAPIError accessible via result.GetError() and errors.As.
func NewGitHubRawAPIErrorResponse(_ context.Context, message string, resp *http.Response, err error) *mcp.CallToolResult {
rawErr := NewGitHubRawAPIError(message, resp, err)
var result mcp.CallToolResult
result.SetError(rawErr)
return &result
}
// NewGitHubAPIStatusErrorResponse handles cases where the API call succeeds (err == nil)
// but returns an unexpected HTTP status code. It creates a synthetic error from the
// status code and response body, then sets it on the result via SetError.
func NewGitHubAPIStatusErrorResponse(ctx context.Context, message string, resp *github.Response, body []byte) *mcp.CallToolResult {
err := fmt.Errorf("unexpected status %d: %s", resp.StatusCode, string(body))
return NewGitHubAPIErrorResponse(ctx, message, resp, err)
}