commitResourceHandler wrapped parse errors with fmt.Errorf, losing the *resource.ResourceError type so callers using direct type assertion got nil. Sibling handlers (issue, pr) already route parse errors through MapForgejoError. Align commit handler to the same pattern. Note: MapForgejoError currently maps unrecognized parse-error strings to -32603 (substring matching); forgejo-mcp-wgs will introduce a sentinel-error path that lifts these to -32602 invalid- params. This commit is the precondition for wgs. Closes forgejo-mcp-vzz. Ref PR #172 review https://codeberg.org/goern/forgejo-mcp/pulls/172#issuecomment-16022165
77 lines
2.1 KiB
Go
77 lines
2.1 KiB
Go
package repo
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
"codeberg.org/goern/forgejo-mcp/v2/operation/resource"
|
|
"codeberg.org/goern/forgejo-mcp/v2/pkg/forgejo"
|
|
"codeberg.org/goern/forgejo-mcp/v2/pkg/log"
|
|
|
|
"github.com/mark3labs/mcp-go/mcp"
|
|
"github.com/mark3labs/mcp-go/server"
|
|
)
|
|
|
|
const commitResourceURITemplate = "forgejo://repo/{owner}/{repo}/commit/{sha}"
|
|
|
|
// RegisterCommitResource registers the forgejo://repo/{owner}/{repo}/commit/{sha} resource template.
|
|
func RegisterCommitResource(s *server.MCPServer) {
|
|
resource.RegisterTemplate(
|
|
s,
|
|
commitResourceURITemplate,
|
|
"Forgejo Commit",
|
|
commitResourceHandler,
|
|
mcp.WithTemplateDescription(
|
|
"Immutable commit metadata for a Forgejo repository commit. "+
|
|
"URI: forgejo://repo/{owner}/{repo}/commit/{sha} — sha must be a full 40-character hex SHA. "+
|
|
"Returns JSON metadata plus a text/markdown body sidecar for the commit message.",
|
|
),
|
|
mcp.WithTemplateMIMEType("application/json"),
|
|
)
|
|
log.Debug("Registered commit resource template")
|
|
}
|
|
|
|
func commitResourceHandler(ctx context.Context, req mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
|
|
uri := req.Params.URI
|
|
params, err := resource.ParseCommit(uri)
|
|
if err != nil {
|
|
return nil, resource.MapForgejoError(uri, err)
|
|
}
|
|
|
|
client, err := forgejo.Client(ctx)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("forgejo client: %w", err)
|
|
}
|
|
|
|
commit, resp, err := client.GetSingleCommit(params.Owner, params.Repo, params.SHA)
|
|
if err != nil {
|
|
if resp != nil {
|
|
return nil, resource.MapForgejoError(uri, fmt.Errorf("%d %s", resp.StatusCode, err.Error()))
|
|
}
|
|
return nil, resource.MapForgejoError(uri, err)
|
|
}
|
|
|
|
jsonBytes, err := json.Marshal(commit)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("marshal commit: %w", err)
|
|
}
|
|
|
|
contents := []mcp.ResourceContents{
|
|
mcp.TextResourceContents{
|
|
URI: uri,
|
|
MIMEType: "application/json",
|
|
Text: string(jsonBytes),
|
|
},
|
|
}
|
|
|
|
if commit.RepoCommit != nil && commit.RepoCommit.Message != "" {
|
|
contents = append(contents, mcp.TextResourceContents{
|
|
URI: uri,
|
|
MIMEType: "text/markdown",
|
|
Text: commit.RepoCommit.Message,
|
|
})
|
|
}
|
|
|
|
return contents, nil
|
|
}
|