mirror of
https://gitea.com/gitea/gitea-mcp.git
synced 2025-09-13 08:23:15 +00:00
Compare commits
3 Commits
ba07925969
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
d7addd56c4 | ||
|
dc3e120e97 | ||
|
f33b04a3df |
10
README.md
10
README.md
@@ -139,7 +139,10 @@ To configure the MCP server for Gitea, add the following to your MCP configurati
|
|||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"gitea": {
|
"gitea": {
|
||||||
"url": "http://localhost:8080/sse"
|
"url": "http://localhost:8080/sse",
|
||||||
|
"headers": {
|
||||||
|
"Authorization": "Bearer <your personal access token>"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,7 +154,10 @@ To configure the MCP server for Gitea, add the following to your MCP configurati
|
|||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"gitea": {
|
"gitea": {
|
||||||
"url": "http://localhost:8080/mcp"
|
"url": "http://localhost:8080/mcp",
|
||||||
|
"headers": {
|
||||||
|
"Authorization": "Bearer <your personal access token>"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -139,7 +139,10 @@ cp gitea-mcp /usr/local/bin/
|
|||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"gitea": {
|
"gitea": {
|
||||||
"url": "http://localhost:8080/sse"
|
"url": "http://localhost:8080/sse",
|
||||||
|
"headers": {
|
||||||
|
"Authorization": "Bearer <your personal access token>"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,7 +154,10 @@ cp gitea-mcp /usr/local/bin/
|
|||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"gitea": {
|
"gitea": {
|
||||||
"url": "http://localhost:8080/mcp"
|
"url": "http://localhost:8080/mcp",
|
||||||
|
"headers": {
|
||||||
|
"Authorization": "Bearer <your personal access token>"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -139,7 +139,10 @@ cp gitea-mcp /usr/local/bin/
|
|||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"gitea": {
|
"gitea": {
|
||||||
"url": "http://localhost:8080/sse"
|
"url": "http://localhost:8080/sse",
|
||||||
|
"headers": {
|
||||||
|
"Authorization": "Bearer <your personal access token>"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,7 +154,10 @@ cp gitea-mcp /usr/local/bin/
|
|||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"gitea": {
|
"gitea": {
|
||||||
"url": "http://localhost:8080/mcp"
|
"url": "http://localhost:8080/mcp",
|
||||||
|
"headers": {
|
||||||
|
"Authorization": "Bearer <your personal access token>"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -140,7 +140,11 @@ func GetIssueByIndexFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallT
|
|||||||
if !ok {
|
if !ok {
|
||||||
return to.ErrorResult(fmt.Errorf("index is required"))
|
return to.ErrorResult(fmt.Errorf("index is required"))
|
||||||
}
|
}
|
||||||
issue, _, err := gitea.Client().GetIssue(owner, repo, int64(index))
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
issue, _, err := client.GetIssue(owner, repo, int64(index))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("get %v/%v/issue/%v err: %v", owner, repo, int64(index), err))
|
return to.ErrorResult(fmt.Errorf("get %v/%v/issue/%v err: %v", owner, repo, int64(index), err))
|
||||||
}
|
}
|
||||||
@@ -177,7 +181,11 @@ func ListRepoIssuesFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallTo
|
|||||||
PageSize: int(pageSize),
|
PageSize: int(pageSize),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
issues, _, err := gitea.Client().ListRepoIssues(owner, repo, opt)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
issues, _, err := client.ListRepoIssues(owner, repo, opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("get %v/%v/issues err: %v", owner, repo, err))
|
return to.ErrorResult(fmt.Errorf("get %v/%v/issues err: %v", owner, repo, err))
|
||||||
}
|
}
|
||||||
@@ -202,7 +210,11 @@ func CreateIssueFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolR
|
|||||||
if !ok {
|
if !ok {
|
||||||
return to.ErrorResult(fmt.Errorf("body is required"))
|
return to.ErrorResult(fmt.Errorf("body is required"))
|
||||||
}
|
}
|
||||||
issue, _, err := gitea.Client().CreateIssue(owner, repo, gitea_sdk.CreateIssueOption{
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
issue, _, err := client.CreateIssue(owner, repo, gitea_sdk.CreateIssueOption{
|
||||||
Title: title,
|
Title: title,
|
||||||
Body: body,
|
Body: body,
|
||||||
})
|
})
|
||||||
@@ -234,7 +246,11 @@ func CreateIssueCommentFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.Ca
|
|||||||
opt := gitea_sdk.CreateIssueCommentOption{
|
opt := gitea_sdk.CreateIssueCommentOption{
|
||||||
Body: body,
|
Body: body,
|
||||||
}
|
}
|
||||||
issueComment, _, err := gitea.Client().CreateIssueComment(owner, repo, int64(index), opt)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
issueComment, _, err := client.CreateIssueComment(owner, repo, int64(index), opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("create %v/%v/issue/%v/comment err: %v", owner, repo, int64(index), err))
|
return to.ErrorResult(fmt.Errorf("create %v/%v/issue/%v/comment err: %v", owner, repo, int64(index), err))
|
||||||
}
|
}
|
||||||
@@ -280,7 +296,11 @@ func EditIssueFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolRes
|
|||||||
opt.State = ptr.To(gitea_sdk.StateType(state))
|
opt.State = ptr.To(gitea_sdk.StateType(state))
|
||||||
}
|
}
|
||||||
|
|
||||||
issue, _, err := gitea.Client().EditIssue(owner, repo, int64(index), opt)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
issue, _, err := client.EditIssue(owner, repo, int64(index), opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("edit %v/%v/issue/%v err: %v", owner, repo, int64(index), err))
|
return to.ErrorResult(fmt.Errorf("edit %v/%v/issue/%v err: %v", owner, repo, int64(index), err))
|
||||||
}
|
}
|
||||||
@@ -309,7 +329,11 @@ func EditIssueCommentFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.Call
|
|||||||
opt := gitea_sdk.EditIssueCommentOption{
|
opt := gitea_sdk.EditIssueCommentOption{
|
||||||
Body: body,
|
Body: body,
|
||||||
}
|
}
|
||||||
issueComment, _, err := gitea.Client().EditIssueComment(owner, repo, int64(commentID), opt)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
issueComment, _, err := client.EditIssueComment(owner, repo, int64(commentID), opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("edit %v/%v/issues/comments/%v err: %v", owner, repo, int64(commentID), err))
|
return to.ErrorResult(fmt.Errorf("edit %v/%v/issues/comments/%v err: %v", owner, repo, int64(commentID), err))
|
||||||
}
|
}
|
||||||
@@ -332,7 +356,11 @@ func GetIssueCommentsByIndexFn(ctx context.Context, req mcp.CallToolRequest) (*m
|
|||||||
return to.ErrorResult(fmt.Errorf("index is required"))
|
return to.ErrorResult(fmt.Errorf("index is required"))
|
||||||
}
|
}
|
||||||
opt := gitea_sdk.ListIssueCommentOptions{}
|
opt := gitea_sdk.ListIssueCommentOptions{}
|
||||||
issue, _, err := gitea.Client().ListIssueComments(owner, repo, int64(index), opt)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
issue, _, err := client.ListIssueComments(owner, repo, int64(index), opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("get %v/%v/issues/%v/comments err: %v", owner, repo, int64(index), err))
|
return to.ErrorResult(fmt.Errorf("get %v/%v/issues/%v/comments err: %v", owner, repo, int64(index), err))
|
||||||
}
|
}
|
||||||
|
@@ -176,7 +176,11 @@ func ListRepoLabelsFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallTo
|
|||||||
PageSize: int(pageSize),
|
PageSize: int(pageSize),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
labels, _, err := gitea.Client().ListRepoLabels(owner, repo, opt)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
labels, _, err := client.ListRepoLabels(owner, repo, opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("list %v/%v/labels err: %v", owner, repo, err))
|
return to.ErrorResult(fmt.Errorf("list %v/%v/labels err: %v", owner, repo, err))
|
||||||
}
|
}
|
||||||
@@ -198,7 +202,11 @@ func GetRepoLabelFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallTool
|
|||||||
return to.ErrorResult(fmt.Errorf("label ID is required"))
|
return to.ErrorResult(fmt.Errorf("label ID is required"))
|
||||||
}
|
}
|
||||||
|
|
||||||
label, _, err := gitea.Client().GetRepoLabel(owner, repo, int64(id))
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
label, _, err := client.GetRepoLabel(owner, repo, int64(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("get %v/%v/label/%v err: %v", owner, repo, int64(id), err))
|
return to.ErrorResult(fmt.Errorf("get %v/%v/label/%v err: %v", owner, repo, int64(id), err))
|
||||||
}
|
}
|
||||||
@@ -231,7 +239,11 @@ func CreateRepoLabelFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallT
|
|||||||
Description: description,
|
Description: description,
|
||||||
}
|
}
|
||||||
|
|
||||||
label, _, err := gitea.Client().CreateLabel(owner, repo, opt)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
label, _, err := client.CreateLabel(owner, repo, opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("create %v/%v/label err: %v", owner, repo, err))
|
return to.ErrorResult(fmt.Errorf("create %v/%v/label err: %v", owner, repo, err))
|
||||||
}
|
}
|
||||||
@@ -264,7 +276,11 @@ func EditRepoLabelFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToo
|
|||||||
opt.Description = ptr.To(description)
|
opt.Description = ptr.To(description)
|
||||||
}
|
}
|
||||||
|
|
||||||
label, _, err := gitea.Client().EditLabel(owner, repo, int64(id), opt)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
label, _, err := client.EditLabel(owner, repo, int64(id), opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("edit %v/%v/label/%v err: %v", owner, repo, int64(id), err))
|
return to.ErrorResult(fmt.Errorf("edit %v/%v/label/%v err: %v", owner, repo, int64(id), err))
|
||||||
}
|
}
|
||||||
@@ -286,7 +302,11 @@ func DeleteRepoLabelFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallT
|
|||||||
return to.ErrorResult(fmt.Errorf("label ID is required"))
|
return to.ErrorResult(fmt.Errorf("label ID is required"))
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := gitea.Client().DeleteLabel(owner, repo, int64(id))
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
_, err = client.DeleteLabel(owner, repo, int64(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("delete %v/%v/label/%v err: %v", owner, repo, int64(id), err))
|
return to.ErrorResult(fmt.Errorf("delete %v/%v/label/%v err: %v", owner, repo, int64(id), err))
|
||||||
}
|
}
|
||||||
@@ -324,7 +344,11 @@ func AddIssueLabelsFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallTo
|
|||||||
Labels: labels,
|
Labels: labels,
|
||||||
}
|
}
|
||||||
|
|
||||||
issueLabels, _, err := gitea.Client().AddIssueLabels(owner, repo, int64(index), opt)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
issueLabels, _, err := client.AddIssueLabels(owner, repo, int64(index), opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("add labels to %v/%v/issue/%v err: %v", owner, repo, int64(index), err))
|
return to.ErrorResult(fmt.Errorf("add labels to %v/%v/issue/%v err: %v", owner, repo, int64(index), err))
|
||||||
}
|
}
|
||||||
@@ -362,7 +386,11 @@ func ReplaceIssueLabelsFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.Ca
|
|||||||
Labels: labels,
|
Labels: labels,
|
||||||
}
|
}
|
||||||
|
|
||||||
issueLabels, _, err := gitea.Client().ReplaceIssueLabels(owner, repo, int64(index), opt)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
issueLabels, _, err := client.ReplaceIssueLabels(owner, repo, int64(index), opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("replace labels on %v/%v/issue/%v err: %v", owner, repo, int64(index), err))
|
return to.ErrorResult(fmt.Errorf("replace labels on %v/%v/issue/%v err: %v", owner, repo, int64(index), err))
|
||||||
}
|
}
|
||||||
@@ -384,7 +412,11 @@ func ClearIssueLabelsFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.Call
|
|||||||
return to.ErrorResult(fmt.Errorf("issue index is required"))
|
return to.ErrorResult(fmt.Errorf("issue index is required"))
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := gitea.Client().ClearIssueLabels(owner, repo, int64(index))
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
_, err = client.ClearIssueLabels(owner, repo, int64(index))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("clear labels on %v/%v/issue/%v err: %v", owner, repo, int64(index), err))
|
return to.ErrorResult(fmt.Errorf("clear labels on %v/%v/issue/%v err: %v", owner, repo, int64(index), err))
|
||||||
}
|
}
|
||||||
@@ -410,7 +442,11 @@ func RemoveIssueLabelFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.Call
|
|||||||
return to.ErrorResult(fmt.Errorf("label ID is required"))
|
return to.ErrorResult(fmt.Errorf("label ID is required"))
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := gitea.Client().DeleteIssueLabel(owner, repo, int64(index), int64(labelID))
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
_, err = client.DeleteIssueLabel(owner, repo, int64(index), int64(labelID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("remove label %v from %v/%v/issue/%v err: %v", int64(labelID), owner, repo, int64(index), err))
|
return to.ErrorResult(fmt.Errorf("remove label %v from %v/%v/issue/%v err: %v", int64(labelID), owner, repo, int64(index), err))
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,10 @@
|
|||||||
package operation
|
package operation
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gitea.com/gitea/gitea-mcp/operation/issue"
|
"gitea.com/gitea/gitea-mcp/operation/issue"
|
||||||
@@ -11,6 +14,7 @@ import (
|
|||||||
"gitea.com/gitea/gitea-mcp/operation/search"
|
"gitea.com/gitea/gitea-mcp/operation/search"
|
||||||
"gitea.com/gitea/gitea-mcp/operation/user"
|
"gitea.com/gitea/gitea-mcp/operation/user"
|
||||||
"gitea.com/gitea/gitea-mcp/operation/version"
|
"gitea.com/gitea/gitea-mcp/operation/version"
|
||||||
|
mcpContext "gitea.com/gitea/gitea-mcp/pkg/context"
|
||||||
"gitea.com/gitea/gitea-mcp/pkg/flag"
|
"gitea.com/gitea/gitea-mcp/pkg/flag"
|
||||||
"gitea.com/gitea/gitea-mcp/pkg/log"
|
"gitea.com/gitea/gitea-mcp/pkg/log"
|
||||||
|
|
||||||
@@ -44,6 +48,20 @@ func RegisterTool(s *server.MCPServer) {
|
|||||||
s.DeleteTools("")
|
s.DeleteTools("")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getContextWithToken(ctx context.Context, r *http.Request) context.Context {
|
||||||
|
authHeader := r.Header.Get("Authorization")
|
||||||
|
if authHeader == "" {
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := strings.Split(authHeader, " ")
|
||||||
|
if len(parts) != 2 || parts[0] != "Bearer" {
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
return context.WithValue(ctx, mcpContext.TokenContextKey, parts[1])
|
||||||
|
}
|
||||||
|
|
||||||
func Run() error {
|
func Run() error {
|
||||||
mcpServer = newMCPServer(flag.Version)
|
mcpServer = newMCPServer(flag.Version)
|
||||||
RegisterTool(mcpServer)
|
RegisterTool(mcpServer)
|
||||||
@@ -57,6 +75,7 @@ func Run() error {
|
|||||||
case "sse":
|
case "sse":
|
||||||
sseServer := server.NewSSEServer(
|
sseServer := server.NewSSEServer(
|
||||||
mcpServer,
|
mcpServer,
|
||||||
|
server.WithSSEContextFunc(getContextWithToken),
|
||||||
)
|
)
|
||||||
log.Infof("Gitea MCP SSE server listening on :%d", flag.Port)
|
log.Infof("Gitea MCP SSE server listening on :%d", flag.Port)
|
||||||
if err := sseServer.Start(fmt.Sprintf(":%d", flag.Port)); err != nil {
|
if err := sseServer.Start(fmt.Sprintf(":%d", flag.Port)); err != nil {
|
||||||
@@ -67,7 +86,7 @@ func Run() error {
|
|||||||
mcpServer,
|
mcpServer,
|
||||||
server.WithLogger(log.New()),
|
server.WithLogger(log.New()),
|
||||||
server.WithHeartbeatInterval(30*time.Second),
|
server.WithHeartbeatInterval(30*time.Second),
|
||||||
server.WithStateLess(true),
|
server.WithHTTPContextFunc(getContextWithToken),
|
||||||
)
|
)
|
||||||
log.Infof("Gitea MCP HTTP server listening on :%d", flag.Port)
|
log.Infof("Gitea MCP HTTP server listening on :%d", flag.Port)
|
||||||
if err := httpServer.Start(fmt.Sprintf(":%d", flag.Port)); err != nil {
|
if err := httpServer.Start(fmt.Sprintf(":%d", flag.Port)); err != nil {
|
||||||
|
@@ -84,7 +84,11 @@ func GetPullRequestByIndexFn(ctx context.Context, req mcp.CallToolRequest) (*mcp
|
|||||||
if !ok {
|
if !ok {
|
||||||
return to.ErrorResult(fmt.Errorf("index is required"))
|
return to.ErrorResult(fmt.Errorf("index is required"))
|
||||||
}
|
}
|
||||||
pr, _, err := gitea.Client().GetPullRequest(owner, repo, int64(index))
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
pr, _, err := client.GetPullRequest(owner, repo, int64(index))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("get %v/%v/pr/%v err: %v", owner, repo, int64(index), err))
|
return to.ErrorResult(fmt.Errorf("get %v/%v/pr/%v err: %v", owner, repo, int64(index), err))
|
||||||
}
|
}
|
||||||
@@ -125,7 +129,11 @@ func ListRepoPullRequestsFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.
|
|||||||
PageSize: int(pageSize),
|
PageSize: int(pageSize),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
pullRequests, _, err := gitea.Client().ListRepoPullRequests(owner, repo, opt)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
pullRequests, _, err := client.ListRepoPullRequests(owner, repo, opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("list %v/%v/pull_requests err: %v", owner, repo, err))
|
return to.ErrorResult(fmt.Errorf("list %v/%v/pull_requests err: %v", owner, repo, err))
|
||||||
}
|
}
|
||||||
@@ -159,7 +167,11 @@ func CreatePullRequestFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.Cal
|
|||||||
if !ok {
|
if !ok {
|
||||||
return to.ErrorResult(fmt.Errorf("base is required"))
|
return to.ErrorResult(fmt.Errorf("base is required"))
|
||||||
}
|
}
|
||||||
pr, _, err := gitea.Client().CreatePullRequest(owner, repo, gitea_sdk.CreatePullRequestOption{
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
pr, _, err := client.CreatePullRequest(owner, repo, gitea_sdk.CreatePullRequestOption{
|
||||||
Title: title,
|
Title: title,
|
||||||
Body: body,
|
Body: body,
|
||||||
Head: head,
|
Head: head,
|
||||||
|
@@ -76,7 +76,11 @@ func CreateBranchFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallTool
|
|||||||
}
|
}
|
||||||
oldBranch, _ := req.GetArguments()["old_branch"].(string)
|
oldBranch, _ := req.GetArguments()["old_branch"].(string)
|
||||||
|
|
||||||
_, _, err := gitea.Client().CreateBranch(owner, repo, gitea_sdk.CreateBranchOption{
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
_, _, err = client.CreateBranch(owner, repo, gitea_sdk.CreateBranchOption{
|
||||||
BranchName: branch,
|
BranchName: branch,
|
||||||
OldBranchName: oldBranch,
|
OldBranchName: oldBranch,
|
||||||
})
|
})
|
||||||
@@ -101,7 +105,11 @@ func DeleteBranchFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallTool
|
|||||||
if !ok {
|
if !ok {
|
||||||
return to.ErrorResult(fmt.Errorf("branch is required"))
|
return to.ErrorResult(fmt.Errorf("branch is required"))
|
||||||
}
|
}
|
||||||
_, _, err := gitea.Client().DeleteRepoBranch(owner, repo, branch)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
_, _, err = client.DeleteRepoBranch(owner, repo, branch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("delete branch error: %v", err))
|
return to.ErrorResult(fmt.Errorf("delete branch error: %v", err))
|
||||||
}
|
}
|
||||||
@@ -125,7 +133,11 @@ func ListBranchesFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallTool
|
|||||||
PageSize: 100,
|
PageSize: 100,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
branches, _, err := gitea.Client().ListRepoBranches(owner, repo, opt)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
branches, _, err := client.ListRepoBranches(owner, repo, opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("list branches error: %v", err))
|
return to.ErrorResult(fmt.Errorf("list branches error: %v", err))
|
||||||
}
|
}
|
||||||
|
@@ -63,7 +63,11 @@ func ListRepoCommitsFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallT
|
|||||||
SHA: sha,
|
SHA: sha,
|
||||||
Path: path,
|
Path: path,
|
||||||
}
|
}
|
||||||
commits, _, err := gitea.Client().ListRepoCommits(owner, repo, opt)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
commits, _, err := client.ListRepoCommits(owner, repo, opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("list repo commits err: %v", err))
|
return to.ErrorResult(fmt.Errorf("list repo commits err: %v", err))
|
||||||
}
|
}
|
||||||
|
@@ -64,7 +64,7 @@ var (
|
|||||||
mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")),
|
mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")),
|
||||||
mcp.WithString("filePath", mcp.Required(), mcp.Description("file path")),
|
mcp.WithString("filePath", mcp.Required(), mcp.Description("file path")),
|
||||||
mcp.WithString("sha", mcp.Required(), mcp.Description("sha is the SHA for the file that already exists")),
|
mcp.WithString("sha", mcp.Required(), mcp.Description("sha is the SHA for the file that already exists")),
|
||||||
mcp.WithString("content", mcp.Required(), mcp.Description("file content, base64 encoded")),
|
mcp.WithString("content", mcp.Required(), mcp.Description("file content")),
|
||||||
mcp.WithString("message", mcp.Required(), mcp.Description("commit message")),
|
mcp.WithString("message", mcp.Required(), mcp.Description("commit message")),
|
||||||
mcp.WithString("branch_name", mcp.Required(), mcp.Description("branch name")),
|
mcp.WithString("branch_name", mcp.Required(), mcp.Description("branch name")),
|
||||||
)
|
)
|
||||||
@@ -124,7 +124,11 @@ func GetFileContentFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallTo
|
|||||||
if !ok {
|
if !ok {
|
||||||
return to.ErrorResult(fmt.Errorf("filePath is required"))
|
return to.ErrorResult(fmt.Errorf("filePath is required"))
|
||||||
}
|
}
|
||||||
content, _, err := gitea.Client().GetContents(owner, repo, ref, filePath)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
content, _, err := client.GetContents(owner, repo, ref, filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("get file err: %v", err))
|
return to.ErrorResult(fmt.Errorf("get file err: %v", err))
|
||||||
}
|
}
|
||||||
@@ -184,7 +188,11 @@ func GetDirContentFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToo
|
|||||||
if !ok {
|
if !ok {
|
||||||
return to.ErrorResult(fmt.Errorf("filePath is required"))
|
return to.ErrorResult(fmt.Errorf("filePath is required"))
|
||||||
}
|
}
|
||||||
content, _, err := gitea.Client().ListContents(owner, repo, ref, filePath)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
content, _, err := client.ListContents(owner, repo, ref, filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("get dir content err: %v", err))
|
return to.ErrorResult(fmt.Errorf("get dir content err: %v", err))
|
||||||
}
|
}
|
||||||
@@ -216,7 +224,11 @@ func CreateFileFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolRe
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _, err := gitea.Client().CreateFile(owner, repo, filePath, opt)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
_, _, err = client.CreateFile(owner, repo, filePath, opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("create file err: %v", err))
|
return to.ErrorResult(fmt.Errorf("create file err: %v", err))
|
||||||
}
|
}
|
||||||
@@ -253,7 +265,11 @@ func UpdateFileFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolRe
|
|||||||
BranchName: branchName,
|
BranchName: branchName,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, _, err := gitea.Client().UpdateFile(owner, repo, filePath, opt)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
_, _, err = client.UpdateFile(owner, repo, filePath, opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("update file err: %v", err))
|
return to.ErrorResult(fmt.Errorf("update file err: %v", err))
|
||||||
}
|
}
|
||||||
@@ -287,7 +303,11 @@ func DeleteFileFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolRe
|
|||||||
},
|
},
|
||||||
SHA: sha,
|
SHA: sha,
|
||||||
}
|
}
|
||||||
_, err := gitea.Client().DeleteFile(owner, repo, filePath, opt)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
_, err = client.DeleteFile(owner, repo, filePath, opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("delete file err: %v", err))
|
return to.ErrorResult(fmt.Errorf("delete file err: %v", err))
|
||||||
}
|
}
|
||||||
|
@@ -134,7 +134,11 @@ func CreateReleaseFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToo
|
|||||||
isPreRelease, _ := req.GetArguments()["is_pre_release"].(bool)
|
isPreRelease, _ := req.GetArguments()["is_pre_release"].(bool)
|
||||||
body, _ := req.GetArguments()["body"].(string)
|
body, _ := req.GetArguments()["body"].(string)
|
||||||
|
|
||||||
_, _, err := gitea.Client().CreateRelease(owner, repo, gitea_sdk.CreateReleaseOption{
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
_, _, err = client.CreateRelease(owner, repo, gitea_sdk.CreateReleaseOption{
|
||||||
TagName: tagName,
|
TagName: tagName,
|
||||||
Target: target,
|
Target: target,
|
||||||
Title: title,
|
Title: title,
|
||||||
@@ -164,7 +168,11 @@ func DeleteReleaseFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToo
|
|||||||
return nil, fmt.Errorf("id is required")
|
return nil, fmt.Errorf("id is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := gitea.Client().DeleteRelease(owner, repo, int64(id))
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
_, err = client.DeleteRelease(owner, repo, int64(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("delete release error: %v", err)
|
return nil, fmt.Errorf("delete release error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -187,7 +195,11 @@ func GetReleaseFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolRe
|
|||||||
return nil, fmt.Errorf("id is required")
|
return nil, fmt.Errorf("id is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
release, _, err := gitea.Client().GetRelease(owner, repo, int64(id))
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
release, _, err := client.GetRelease(owner, repo, int64(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("get release error: %v", err)
|
return nil, fmt.Errorf("get release error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -206,7 +218,11 @@ func GetLatestReleaseFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.Call
|
|||||||
return nil, fmt.Errorf("repo is required")
|
return nil, fmt.Errorf("repo is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
release, _, err := gitea.Client().GetLatestRelease(owner, repo)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
release, _, err := client.GetLatestRelease(owner, repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("get latest release error: %v", err)
|
return nil, fmt.Errorf("get latest release error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -237,7 +253,11 @@ func ListReleasesFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallTool
|
|||||||
page, _ := req.GetArguments()["page"].(float64)
|
page, _ := req.GetArguments()["page"].(float64)
|
||||||
pageSize, _ := req.GetArguments()["pageSize"].(float64)
|
pageSize, _ := req.GetArguments()["pageSize"].(float64)
|
||||||
|
|
||||||
releases, _, err := gitea.Client().ListReleases(owner, repo, gitea_sdk.ListReleasesOptions{
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
releases, _, err := client.ListReleases(owner, repo, gitea_sdk.ListReleasesOptions{
|
||||||
ListOptions: gitea_sdk.ListOptions{
|
ListOptions: gitea_sdk.ListOptions{
|
||||||
Page: int(page),
|
Page: int(page),
|
||||||
PageSize: int(pageSize),
|
PageSize: int(pageSize),
|
||||||
|
@@ -27,7 +27,7 @@ const (
|
|||||||
var (
|
var (
|
||||||
CreateRepoTool = mcp.NewTool(
|
CreateRepoTool = mcp.NewTool(
|
||||||
CreateRepoToolName,
|
CreateRepoToolName,
|
||||||
mcp.WithDescription("Create repository"),
|
mcp.WithDescription("Create repository in personal account or organization"),
|
||||||
mcp.WithString("name", mcp.Required(), mcp.Description("Name of the repository to create")),
|
mcp.WithString("name", mcp.Required(), mcp.Description("Name of the repository to create")),
|
||||||
mcp.WithString("description", mcp.Description("Description of the repository to create")),
|
mcp.WithString("description", mcp.Description("Description of the repository to create")),
|
||||||
mcp.WithBoolean("private", mcp.Description("Whether the repository is private")),
|
mcp.WithBoolean("private", mcp.Description("Whether the repository is private")),
|
||||||
@@ -38,6 +38,7 @@ var (
|
|||||||
mcp.WithString("license", mcp.Description("License to use")),
|
mcp.WithString("license", mcp.Description("License to use")),
|
||||||
mcp.WithString("readme", mcp.Description("Readme of the repository to create")),
|
mcp.WithString("readme", mcp.Description("Readme of the repository to create")),
|
||||||
mcp.WithString("default_branch", mcp.Description("DefaultBranch of the repository (used when initializes and in template)")),
|
mcp.WithString("default_branch", mcp.Description("DefaultBranch of the repository (used when initializes and in template)")),
|
||||||
|
mcp.WithString("organization", mcp.Description("Organization name to create repository in (optional - defaults to personal account)")),
|
||||||
)
|
)
|
||||||
|
|
||||||
ForkRepoTool = mcp.NewTool(
|
ForkRepoTool = mcp.NewTool(
|
||||||
@@ -120,6 +121,7 @@ func CreateRepoFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolRe
|
|||||||
license, _ := req.GetArguments()["license"].(string)
|
license, _ := req.GetArguments()["license"].(string)
|
||||||
readme, _ := req.GetArguments()["readme"].(string)
|
readme, _ := req.GetArguments()["readme"].(string)
|
||||||
defaultBranch, _ := req.GetArguments()["default_branch"].(string)
|
defaultBranch, _ := req.GetArguments()["default_branch"].(string)
|
||||||
|
organization, _ := req.GetArguments()["organization"].(string)
|
||||||
|
|
||||||
opt := gitea_sdk.CreateRepoOption{
|
opt := gitea_sdk.CreateRepoOption{
|
||||||
Name: name,
|
Name: name,
|
||||||
@@ -133,9 +135,22 @@ func CreateRepoFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolRe
|
|||||||
Readme: readme,
|
Readme: readme,
|
||||||
DefaultBranch: defaultBranch,
|
DefaultBranch: defaultBranch,
|
||||||
}
|
}
|
||||||
repo, _, err := gitea.Client().CreateRepo(opt)
|
|
||||||
|
var repo *gitea_sdk.Repository
|
||||||
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("create repo err: %v", err))
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
if organization != "" {
|
||||||
|
repo, _, err = client.CreateOrgRepo(organization, opt)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("create organization repository '%s' in '%s' err: %v", name, organization, err))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
repo, _, err = client.CreateRepo(opt)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("create repository '%s' err: %v", name, err))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return to.TextResult(repo)
|
return to.TextResult(repo)
|
||||||
}
|
}
|
||||||
@@ -164,7 +179,11 @@ func ForkRepoFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResu
|
|||||||
Organization: organizationPtr,
|
Organization: organizationPtr,
|
||||||
Name: namePtr,
|
Name: namePtr,
|
||||||
}
|
}
|
||||||
_, _, err := gitea.Client().CreateFork(user, repo, opt)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
_, _, err = client.CreateFork(user, repo, opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("fork repository error: %v", err))
|
return to.ErrorResult(fmt.Errorf("fork repository error: %v", err))
|
||||||
}
|
}
|
||||||
@@ -187,7 +206,11 @@ func ListMyReposFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolR
|
|||||||
PageSize: int(pageSize),
|
PageSize: int(pageSize),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
repos, _, err := gitea.Client().ListMyRepos(opt)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
repos, _, err := client.ListMyRepos(opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("list my repositories error: %v", err))
|
return to.ErrorResult(fmt.Errorf("list my repositories error: %v", err))
|
||||||
}
|
}
|
||||||
|
@@ -102,7 +102,11 @@ func CreateTagFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolRes
|
|||||||
target, _ := req.GetArguments()["target"].(string)
|
target, _ := req.GetArguments()["target"].(string)
|
||||||
message, _ := req.GetArguments()["message"].(string)
|
message, _ := req.GetArguments()["message"].(string)
|
||||||
|
|
||||||
_, _, err := gitea.Client().CreateTag(owner, repo, gitea_sdk.CreateTagOption{
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
_, _, err = client.CreateTag(owner, repo, gitea_sdk.CreateTagOption{
|
||||||
TagName: tagName,
|
TagName: tagName,
|
||||||
Target: target,
|
Target: target,
|
||||||
Message: message,
|
Message: message,
|
||||||
@@ -129,7 +133,11 @@ func DeleteTagFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolRes
|
|||||||
return nil, fmt.Errorf("tag_name is required")
|
return nil, fmt.Errorf("tag_name is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := gitea.Client().DeleteTag(owner, repo, tagName)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
_, err = client.DeleteTag(owner, repo, tagName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("delete tag error: %v", err)
|
return nil, fmt.Errorf("delete tag error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -152,7 +160,11 @@ func GetTagFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult
|
|||||||
return nil, fmt.Errorf("tag_name is required")
|
return nil, fmt.Errorf("tag_name is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
tag, _, err := gitea.Client().GetTag(owner, repo, tagName)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
tag, _, err := client.GetTag(owner, repo, tagName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("get tag error: %v", err)
|
return nil, fmt.Errorf("get tag error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -173,7 +185,11 @@ func ListTagsFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResu
|
|||||||
page, _ := req.GetArguments()["page"].(float64)
|
page, _ := req.GetArguments()["page"].(float64)
|
||||||
pageSize, _ := req.GetArguments()["pageSize"].(float64)
|
pageSize, _ := req.GetArguments()["pageSize"].(float64)
|
||||||
|
|
||||||
tags, _, err := gitea.Client().ListRepoTags(owner, repo, gitea_sdk.ListRepoTagsOptions{
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
tags, _, err := client.ListRepoTags(owner, repo, gitea_sdk.ListRepoTagsOptions{
|
||||||
ListOptions: gitea_sdk.ListOptions{
|
ListOptions: gitea_sdk.ListOptions{
|
||||||
Page: int(page),
|
Page: int(page),
|
||||||
PageSize: int(pageSize),
|
PageSize: int(pageSize),
|
||||||
|
@@ -94,7 +94,11 @@ func SearchUsersFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolR
|
|||||||
PageSize: int(pageSize),
|
PageSize: int(pageSize),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
users, _, err := gitea.Client().SearchUsers(opt)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
users, _, err := client.SearchUsers(opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("search users err: %v", err))
|
return to.ErrorResult(fmt.Errorf("search users err: %v", err))
|
||||||
}
|
}
|
||||||
@@ -128,7 +132,11 @@ func SearchOrgTeamsFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallTo
|
|||||||
PageSize: int(pageSize),
|
PageSize: int(pageSize),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
teams, _, err := gitea.Client().SearchOrgTeams(org, &opt)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
teams, _, err := client.SearchOrgTeams(org, &opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("search organization teams error: %v", err))
|
return to.ErrorResult(fmt.Errorf("search organization teams error: %v", err))
|
||||||
}
|
}
|
||||||
@@ -178,7 +186,11 @@ func SearchReposFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolR
|
|||||||
PageSize: int(pageSize),
|
PageSize: int(pageSize),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
repos, _, err := gitea.Client().SearchRepos(opt)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
repos, _, err := client.SearchRepos(opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("search repos error: %v", err))
|
return to.ErrorResult(fmt.Errorf("search repos error: %v", err))
|
||||||
}
|
}
|
||||||
|
@@ -79,7 +79,11 @@ func getIntArg(req mcp.CallToolRequest, name string, def int) int {
|
|||||||
// Logs invocation, fetches current user info from gitea, wraps result for MCP.
|
// Logs invocation, fetches current user info from gitea, wraps result for MCP.
|
||||||
func GetUserInfoFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
func GetUserInfoFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||||
log.Debugf("[User] Called GetUserInfoFn")
|
log.Debugf("[User] Called GetUserInfoFn")
|
||||||
user, _, err := gitea.Client().GetMyUserInfo()
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
user, _, err := client.GetMyUserInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("get user info err: %v", err))
|
return to.ErrorResult(fmt.Errorf("get user info err: %v", err))
|
||||||
}
|
}
|
||||||
@@ -100,7 +104,11 @@ func GetUserOrgsFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolR
|
|||||||
PageSize: pageSize,
|
PageSize: pageSize,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
orgs, _, err := gitea.Client().ListMyOrgs(opt)
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
orgs, _, err := client.ListMyOrgs(opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return to.ErrorResult(fmt.Errorf("get user orgs err: %v", err))
|
return to.ErrorResult(fmt.Errorf("get user orgs err: %v", err))
|
||||||
}
|
}
|
||||||
|
7
pkg/context/context.go
Normal file
7
pkg/context/context.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package context
|
||||||
|
|
||||||
|
type contextKey string
|
||||||
|
|
||||||
|
const (
|
||||||
|
TokenContextKey = contextKey("token")
|
||||||
|
)
|
@@ -1,52 +1,47 @@
|
|||||||
package gitea
|
package gitea
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"gitea.com/gitea/gitea-mcp/pkg/flag"
|
|
||||||
"gitea.com/gitea/gitea-mcp/pkg/log"
|
|
||||||
|
|
||||||
"code.gitea.io/sdk/gitea"
|
"code.gitea.io/sdk/gitea"
|
||||||
|
mcpContext "gitea.com/gitea/gitea-mcp/pkg/context"
|
||||||
|
"gitea.com/gitea/gitea-mcp/pkg/flag"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
func NewClient(token string) (*gitea.Client, error) {
|
||||||
client *gitea.Client
|
httpClient := &http.Client{
|
||||||
clientOnce sync.Once
|
Transport: http.DefaultTransport,
|
||||||
)
|
}
|
||||||
|
|
||||||
func Client() *gitea.Client {
|
opts := []gitea.ClientOption{
|
||||||
clientOnce.Do(func() {
|
gitea.SetToken(token),
|
||||||
var err error
|
}
|
||||||
if client != nil {
|
if flag.Insecure {
|
||||||
return
|
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(flag.Host, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("create gitea client err: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
httpClient := &http.Client{
|
// Set user agent for the client
|
||||||
Transport: http.DefaultTransport,
|
client.SetUserAgent(fmt.Sprintf("gitea-mcp-server/%s", flag.Version))
|
||||||
}
|
return client, nil
|
||||||
|
}
|
||||||
opts := []gitea.ClientOption{
|
|
||||||
gitea.SetToken(flag.Token),
|
func ClientFromContext(ctx context.Context) (*gitea.Client, error) {
|
||||||
}
|
token, ok := ctx.Value(mcpContext.TokenContextKey).(string)
|
||||||
if flag.Insecure {
|
if !ok {
|
||||||
httpClient.Transport.(*http.Transport).TLSClientConfig = &tls.Config{
|
token = flag.Token
|
||||||
InsecureSkipVerify: true,
|
}
|
||||||
}
|
return NewClient(token)
|
||||||
}
|
|
||||||
opts = append(opts, gitea.SetHTTPClient(httpClient))
|
|
||||||
if flag.Debug {
|
|
||||||
opts = append(opts, gitea.SetDebugMode())
|
|
||||||
}
|
|
||||||
client, err = gitea.NewClient(flag.Host, opts...)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("create gitea client err: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set user agent for the client
|
|
||||||
client.SetUserAgent(fmt.Sprintf("gitea-mcp-server/%s", flag.Version))
|
|
||||||
})
|
|
||||||
return client
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user