package gitea import ( "context" "crypto/tls" "errors" "fmt" "net/http" "code.gitea.io/sdk/gitea" mcpContext "gitea.com/gitea/gitea-mcp/pkg/context" "gitea.com/gitea/gitea-mcp/pkg/flag" ) func newClientForHost(host, token string, insecure bool) (*gitea.Client, error) { httpClient := &http.Client{ Transport: http.DefaultTransport.(*http.Transport).Clone(), CheckRedirect: checkRedirect, } opts := []gitea.ClientOption{ gitea.SetToken(token), } if insecure { httpClient.Transport.(*http.Transport).TLSClientConfig = &tls.Config{ InsecureSkipVerify: true, } } opts = append(opts, gitea.SetHTTPClient(httpClient)) if flag.Debug { opts = append(opts, gitea.SetDebugMode()) } client, err := gitea.NewClient(host, opts...) if err != nil { return nil, fmt.Errorf("create gitea client err: %w", err) } client.SetUserAgent("gitea-mcp-server/" + flag.Version) return client, nil } // NewClient creates a Gitea client using the default host and the given token. func NewClient(token string) (*gitea.Client, error) { return newClientForHost(flag.Host, token, flag.Insecure) } // checkRedirect prevents Go from silently changing mutating requests (POST, PATCH, etc.) // to GET when following 301/302/303 redirects, which would drop the request body and // make writes appear to succeed when they didn't. func checkRedirect(_ *http.Request, via []*http.Request) error { if len(via) >= 10 { return errors.New("stopped after 10 redirects") } if via[0].Method != http.MethodGet && via[0].Method != http.MethodHead { return http.ErrUseLastResponse } return nil } // ClientFromContext creates a Gitea client using connection details from the // context (set by the multi-server wrapper) or falling back to global defaults. func ClientFromContext(ctx context.Context) (*gitea.Client, error) { host := flag.Host token := flag.Token insecure := flag.Insecure if h, ok := ctx.Value(mcpContext.HostContextKey).(string); ok && h != "" { host = h } if t, ok := ctx.Value(mcpContext.TokenContextKey).(string); ok && t != "" { token = t } if i, ok := ctx.Value(mcpContext.InsecureContextKey).(bool); ok { insecure = i } return newClientForHost(host, token, insecure) }