mirror of
https://gitea.com/gitea/gitea-mcp.git
synced 2025-08-24 14:53:06 +00:00
Compare commits
12 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
da08718e24 | ||
|
44ea8969f4 | ||
|
94aa8dc572 | ||
|
05194ffc1c | ||
|
5c329129f8 | ||
|
52ccf92761 | ||
|
061ea86b0b | ||
|
f14b60fe56 | ||
|
94782a85b6 | ||
|
e94dd26b30 | ||
|
da49bdeb96 | ||
|
3f61299f72 |
52
.air.toml
Normal file
52
.air.toml
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
root = "."
|
||||||
|
testdata_dir = "testdata"
|
||||||
|
tmp_dir = "tmp"
|
||||||
|
|
||||||
|
[build]
|
||||||
|
args_bin = ["-t", "http"]
|
||||||
|
bin = "./gitea-mcp"
|
||||||
|
cmd = "make build"
|
||||||
|
delay = 1000
|
||||||
|
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
|
||||||
|
exclude_file = []
|
||||||
|
exclude_regex = ["_test.go"]
|
||||||
|
exclude_unchanged = false
|
||||||
|
follow_symlink = false
|
||||||
|
full_bin = ""
|
||||||
|
include_dir = []
|
||||||
|
include_ext = ["go", "tpl", "tmpl", "html"]
|
||||||
|
include_file = []
|
||||||
|
kill_delay = "0s"
|
||||||
|
log = "build-errors.log"
|
||||||
|
poll = false
|
||||||
|
poll_interval = 0
|
||||||
|
post_cmd = []
|
||||||
|
pre_cmd = []
|
||||||
|
rerun = false
|
||||||
|
rerun_delay = 500
|
||||||
|
send_interrupt = false
|
||||||
|
stop_on_error = false
|
||||||
|
|
||||||
|
[color]
|
||||||
|
app = ""
|
||||||
|
build = "yellow"
|
||||||
|
main = "magenta"
|
||||||
|
runner = "green"
|
||||||
|
watcher = "cyan"
|
||||||
|
|
||||||
|
[log]
|
||||||
|
main_only = false
|
||||||
|
silent = false
|
||||||
|
time = false
|
||||||
|
|
||||||
|
[misc]
|
||||||
|
clean_on_exit = false
|
||||||
|
|
||||||
|
[proxy]
|
||||||
|
app_port = 0
|
||||||
|
enabled = false
|
||||||
|
proxy_port = 0
|
||||||
|
|
||||||
|
[screen]
|
||||||
|
clear_on_rebuild = false
|
||||||
|
keep_scroll = true
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,3 +2,4 @@
|
|||||||
gitea-mcp
|
gitea-mcp
|
||||||
gitea-mcp.exe
|
gitea-mcp.exe
|
||||||
*.log
|
*.log
|
||||||
|
tmp
|
||||||
|
6
.vscode/mcp.json
vendored
6
.vscode/mcp.json
vendored
@@ -21,7 +21,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"servers": {
|
"servers": {
|
||||||
"gitea": {
|
"gitea-mcp-stdio": {
|
||||||
"type": "stdio",
|
"type": "stdio",
|
||||||
"command": "gitea-mcp",
|
"command": "gitea-mcp",
|
||||||
"args": ["-t", "stdio"],
|
"args": ["-t", "stdio"],
|
||||||
@@ -30,6 +30,10 @@
|
|||||||
"GITEA_ACCESS_TOKEN": "${input:gitea-token}",
|
"GITEA_ACCESS_TOKEN": "${input:gitea-token}",
|
||||||
"GITEA_INSECURE": "${input:gitea-insecure}"
|
"GITEA_INSECURE": "${input:gitea-insecure}"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"gitea-mcp-http": {
|
||||||
|
"type": "http",
|
||||||
|
"url": "http://localhost:8080/mcp",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
39
Dockerfile
39
Dockerfile
@@ -1,39 +1,32 @@
|
|||||||
|
# syntax=docker/dockerfile:1.4
|
||||||
|
|
||||||
# Build stage
|
# Build stage
|
||||||
FROM golang:1.24-bullseye AS builder
|
FROM --platform=$BUILDPLATFORM golang:1.24-alpine AS builder
|
||||||
|
|
||||||
ARG VERSION
|
ARG VERSION=dev
|
||||||
|
ARG TARGETOS
|
||||||
|
ARG TARGETARCH
|
||||||
|
|
||||||
# Set the working directory
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy go.mod and go.sum files
|
|
||||||
COPY go.mod go.sum ./
|
COPY go.mod go.sum ./
|
||||||
|
RUN --mount=type=cache,target=/go/pkg/mod \
|
||||||
|
go mod download
|
||||||
|
|
||||||
# Download dependencies
|
|
||||||
RUN go mod download
|
|
||||||
|
|
||||||
# Copy the source code
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
RUN --mount=type=cache,target=/go/pkg/mod \
|
||||||
RUN CGO_ENABLED=0 go build -ldflags="-s -w -X main.Version=${VERSION}" -o gitea-mcp
|
--mount=type=cache,target=/root/.cache/go-build \
|
||||||
|
CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH:-amd64} \
|
||||||
|
go build -trimpath -ldflags="-s -w -X main.Version=${VERSION}" -o gitea-mcp
|
||||||
|
|
||||||
# Final stage
|
# Final stage
|
||||||
FROM debian:bullseye-slim
|
FROM gcr.io/distroless/static-debian12:nonroot
|
||||||
|
|
||||||
ENV GITEA_MODE=stdio
|
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
COPY --from=builder --chown=nonroot:nonroot /app/gitea-mcp .
|
||||||
|
|
||||||
# Install ca-certificates for HTTPS requests
|
USER nonroot:nonroot
|
||||||
RUN apt-get update && \
|
|
||||||
apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Create a non-root user
|
LABEL org.opencontainers.image.version="${VERSION}"
|
||||||
RUN useradd -r -u 1000 -m gitea-mcp
|
|
||||||
|
|
||||||
COPY --from=builder --chown=1000:1000 /app/gitea-mcp .
|
|
||||||
|
|
||||||
# Use the non-root user
|
|
||||||
USER gitea-mcp
|
|
||||||
|
|
||||||
CMD ["/app/gitea-mcp"]
|
CMD ["/app/gitea-mcp"]
|
@@ -54,7 +54,7 @@ Optionally, you can add it to a file called `.vscode/mcp.json` in your workspace
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"servers": {
|
"servers": {
|
||||||
"github": {
|
"gitea-mcp": {
|
||||||
"command": "docker",
|
"command": "docker",
|
||||||
"args": [
|
"args": [
|
||||||
"run",
|
"run",
|
||||||
@@ -194,6 +194,7 @@ The Gitea MCP Server supports the following tools:
|
|||||||
| list_tags | Tag | List all tags in a repository |
|
| list_tags | Tag | List all tags in a repository |
|
||||||
| list_repo_commits | Commit | List all commits in a repository |
|
| list_repo_commits | Commit | List all commits in a repository |
|
||||||
| get_file_content | File | Get the content and metadata of a file |
|
| get_file_content | File | Get the content and metadata of a file |
|
||||||
|
| get_dir_content | File | Get a list of entries in a directory |
|
||||||
| create_file | File | Create a new file |
|
| create_file | File | Create a new file |
|
||||||
| update_file | File | Update an existing file |
|
| update_file | File | Update an existing file |
|
||||||
| delete_file | File | Delete a file |
|
| delete_file | File | Delete a file |
|
||||||
@@ -202,6 +203,8 @@ The Gitea MCP Server supports the following tools:
|
|||||||
| create_issue | Issue | Create a new issue |
|
| create_issue | Issue | Create a new issue |
|
||||||
| create_issue_comment | Issue | Create a comment on an issue |
|
| create_issue_comment | Issue | Create a comment on an issue |
|
||||||
| edit_issue | Issue | Edit a issue |
|
| edit_issue | Issue | Edit a issue |
|
||||||
|
| edit_issue_comment | Issue | Edit a comment on an issue |
|
||||||
|
| get_issue_comments_by_index | Issue | Get comments of an issue by its index |
|
||||||
| get_pull_request_by_index | Pull Request | Get a pull request by its index |
|
| get_pull_request_by_index | Pull Request | Get a pull request by its index |
|
||||||
| list_repo_pull_requests | Pull Request | List all pull requests in a repository |
|
| list_repo_pull_requests | Pull Request | List all pull requests in a repository |
|
||||||
| create_pull_request | Pull Request | Create a new pull request |
|
| create_pull_request | Pull Request | Create a new pull request |
|
||||||
|
@@ -54,7 +54,7 @@ Model Context Protocol (MCP) 是一种协议,允许通过聊天界面整合各
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"servers": {
|
"servers": {
|
||||||
"github": {
|
"gitea-mcp": {
|
||||||
"command": "docker",
|
"command": "docker",
|
||||||
"args": [
|
"args": [
|
||||||
"run",
|
"run",
|
||||||
@@ -194,6 +194,7 @@ Gitea MCP 服务器支持以下工具:
|
|||||||
| list_tags | 标签 | 列出所有标签 |
|
| list_tags | 标签 | 列出所有标签 |
|
||||||
| list_repo_commits | 提交 | 列出仓库中的所有提交 |
|
| list_repo_commits | 提交 | 列出仓库中的所有提交 |
|
||||||
| get_file_content | 文件 | 获取文件的内容和元数据 |
|
| get_file_content | 文件 | 获取文件的内容和元数据 |
|
||||||
|
| get_dir_content | 文件 | 获取目录的内容列表 |
|
||||||
| create_file | 文件 | 创建一个新文件 |
|
| create_file | 文件 | 创建一个新文件 |
|
||||||
| update_file | 文件 | 更新现有文件 |
|
| update_file | 文件 | 更新现有文件 |
|
||||||
| delete_file | 文件 | 删除一个文件 |
|
| delete_file | 文件 | 删除一个文件 |
|
||||||
@@ -202,6 +203,8 @@ Gitea MCP 服务器支持以下工具:
|
|||||||
| create_issue | 问题 | 创建一个新问题 |
|
| create_issue | 问题 | 创建一个新问题 |
|
||||||
| create_issue_comment | 问题 | 在问题上创建评论 |
|
| create_issue_comment | 问题 | 在问题上创建评论 |
|
||||||
| edit_issue | 问题 | 编辑一个问题 |
|
| edit_issue | 问题 | 编辑一个问题 |
|
||||||
|
| edit_issue_comment | 问题 | 在问题上编辑评论 |
|
||||||
|
| get_issue_comments_by_index | 问题 | 根据索引获取问题的评论 |
|
||||||
| get_pull_request_by_index | 拉取请求 | 根据索引获取拉取请求 |
|
| get_pull_request_by_index | 拉取请求 | 根据索引获取拉取请求 |
|
||||||
| list_repo_pull_requests | 拉取请求 | 列出仓库中的所有拉取请求 |
|
| list_repo_pull_requests | 拉取请求 | 列出仓库中的所有拉取请求 |
|
||||||
| create_pull_request | 拉取请求 | 创建一个新拉取请求 |
|
| create_pull_request | 拉取请求 | 创建一个新拉取请求 |
|
||||||
|
@@ -54,7 +54,7 @@ Model Context Protocol (MCP) 是一種協議,允許通過聊天界面整合各
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"servers": {
|
"servers": {
|
||||||
"github": {
|
"gitea-mcp": {
|
||||||
"command": "docker",
|
"command": "docker",
|
||||||
"args": [
|
"args": [
|
||||||
"run",
|
"run",
|
||||||
@@ -194,6 +194,7 @@ Gitea MCP 伺服器支持以下工具:
|
|||||||
| list_tags | 標籤 | 列出所有標籤 |
|
| list_tags | 標籤 | 列出所有標籤 |
|
||||||
| list_repo_commits | 提交 | 列出倉庫中的所有提交 |
|
| list_repo_commits | 提交 | 列出倉庫中的所有提交 |
|
||||||
| get_file_content | 文件 | 獲取文件的內容和元數據 |
|
| get_file_content | 文件 | 獲取文件的內容和元數據 |
|
||||||
|
| get_dir_content | 文件 | 獲取目錄的內容列表 |
|
||||||
| create_file | 文件 | 創建一個新文件 |
|
| create_file | 文件 | 創建一個新文件 |
|
||||||
| update_file | 文件 | 更新現有文件 |
|
| update_file | 文件 | 更新現有文件 |
|
||||||
| delete_file | 文件 | 刪除一個文件 |
|
| delete_file | 文件 | 刪除一個文件 |
|
||||||
@@ -202,6 +203,8 @@ Gitea MCP 伺服器支持以下工具:
|
|||||||
| create_issue | 問題 | 創建一個新問題 |
|
| create_issue | 問題 | 創建一個新問題 |
|
||||||
| create_issue_comment | 問題 | 在問題上創建評論 |
|
| create_issue_comment | 問題 | 在問題上創建評論 |
|
||||||
| edit_issue | 問題 | 編輯一個問題 |
|
| edit_issue | 問題 | 編輯一個問題 |
|
||||||
|
| edit_issue_comment | 問題 | 在問題上編輯評論 |
|
||||||
|
| get_issue_comments_by_index | 问题 | 根據索引獲取問題的評論 |
|
||||||
| get_pull_request_by_index | 拉取請求 | 根據索引獲取拉取請求 |
|
| get_pull_request_by_index | 拉取請求 | 根據索引獲取拉取請求 |
|
||||||
| list_repo_pull_requests | 拉取請求 | 列出倉庫中的所有拉取請求 |
|
| list_repo_pull_requests | 拉取請求 | 列出倉庫中的所有拉取請求 |
|
||||||
| create_pull_request | 拉取請求 | 創建一個新拉取請求 |
|
| create_pull_request | 拉取請求 | 創建一個新拉取請求 |
|
||||||
|
@@ -80,8 +80,8 @@ func init() {
|
|||||||
flagPkg.Token = os.Getenv("GITEA_ACCESS_TOKEN")
|
flagPkg.Token = os.Getenv("GITEA_ACCESS_TOKEN")
|
||||||
}
|
}
|
||||||
|
|
||||||
if os.Getenv("GITEA_MODE") != "" {
|
if os.Getenv("MCP_MODE") != "" {
|
||||||
flagPkg.Mode = os.Getenv("GITEA_MODE")
|
flagPkg.Mode = os.Getenv("MCP_MODE")
|
||||||
}
|
}
|
||||||
|
|
||||||
if os.Getenv("GITEA_READONLY") == "true" {
|
if os.Getenv("GITEA_READONLY") == "true" {
|
||||||
|
@@ -23,6 +23,8 @@ const (
|
|||||||
CreateIssueToolName = "create_issue"
|
CreateIssueToolName = "create_issue"
|
||||||
CreateIssueCommentToolName = "create_issue_comment"
|
CreateIssueCommentToolName = "create_issue_comment"
|
||||||
EditIssueToolName = "edit_issue"
|
EditIssueToolName = "edit_issue"
|
||||||
|
EditIssueCommentToolName = "edit_issue_comment"
|
||||||
|
GetIssueCommentsByIndexToolName = "get_issue_comments_by_index"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -52,6 +54,7 @@ var (
|
|||||||
mcp.WithString("title", mcp.Required(), mcp.Description("issue title")),
|
mcp.WithString("title", mcp.Required(), mcp.Description("issue title")),
|
||||||
mcp.WithString("body", mcp.Required(), mcp.Description("issue body")),
|
mcp.WithString("body", mcp.Required(), mcp.Description("issue body")),
|
||||||
)
|
)
|
||||||
|
|
||||||
CreateIssueCommentTool = mcp.NewTool(
|
CreateIssueCommentTool = mcp.NewTool(
|
||||||
CreateIssueCommentToolName,
|
CreateIssueCommentToolName,
|
||||||
mcp.WithDescription("create issue comment"),
|
mcp.WithDescription("create issue comment"),
|
||||||
@@ -60,6 +63,7 @@ var (
|
|||||||
mcp.WithNumber("index", mcp.Required(), mcp.Description("repository issue index")),
|
mcp.WithNumber("index", mcp.Required(), mcp.Description("repository issue index")),
|
||||||
mcp.WithString("body", mcp.Required(), mcp.Description("issue comment body")),
|
mcp.WithString("body", mcp.Required(), mcp.Description("issue comment body")),
|
||||||
)
|
)
|
||||||
|
|
||||||
EditIssueTool = mcp.NewTool(
|
EditIssueTool = mcp.NewTool(
|
||||||
EditIssueToolName,
|
EditIssueToolName,
|
||||||
mcp.WithDescription("edit issue"),
|
mcp.WithDescription("edit issue"),
|
||||||
@@ -72,6 +76,23 @@ var (
|
|||||||
mcp.WithNumber("milestone", mcp.Description("milestone number")),
|
mcp.WithNumber("milestone", mcp.Description("milestone number")),
|
||||||
mcp.WithString("state", mcp.Description("issue state, one of open, closed, all")),
|
mcp.WithString("state", mcp.Description("issue state, one of open, closed, all")),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
EditIssueCommentTool = mcp.NewTool(
|
||||||
|
EditIssueCommentToolName,
|
||||||
|
mcp.WithDescription("edit issue comment"),
|
||||||
|
mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")),
|
||||||
|
mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")),
|
||||||
|
mcp.WithNumber("commentID", mcp.Required(), mcp.Description("id of issue comment")),
|
||||||
|
mcp.WithString("body", mcp.Required(), mcp.Description("issue comment body")),
|
||||||
|
)
|
||||||
|
|
||||||
|
GetIssueCommentsByIndexTool = mcp.NewTool(
|
||||||
|
GetIssueCommentsByIndexToolName,
|
||||||
|
mcp.WithDescription("get issue comment by index"),
|
||||||
|
mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")),
|
||||||
|
mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")),
|
||||||
|
mcp.WithNumber("index", mcp.Required(), mcp.Description("repository issue index")),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -95,6 +116,14 @@ func init() {
|
|||||||
Tool: EditIssueTool,
|
Tool: EditIssueTool,
|
||||||
Handler: EditIssueFn,
|
Handler: EditIssueFn,
|
||||||
})
|
})
|
||||||
|
Tool.RegisterWrite(server.ServerTool{
|
||||||
|
Tool: EditIssueCommentTool,
|
||||||
|
Handler: EditIssueCommentFn,
|
||||||
|
})
|
||||||
|
Tool.RegisterRead(server.ServerTool{
|
||||||
|
Tool: GetIssueCommentsByIndexTool,
|
||||||
|
Handler: GetIssueCommentsByIndexFn,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetIssueByIndexFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
func GetIssueByIndexFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||||
@@ -258,3 +287,55 @@ func EditIssueFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolRes
|
|||||||
|
|
||||||
return to.TextResult(issue)
|
return to.TextResult(issue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func EditIssueCommentFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||||
|
log.Debugf("Called EditIssueCommentFn")
|
||||||
|
owner, ok := req.GetArguments()["owner"].(string)
|
||||||
|
if !ok {
|
||||||
|
return to.ErrorResult(fmt.Errorf("owner is required"))
|
||||||
|
}
|
||||||
|
repo, ok := req.GetArguments()["repo"].(string)
|
||||||
|
if !ok {
|
||||||
|
return to.ErrorResult(fmt.Errorf("repo is required"))
|
||||||
|
}
|
||||||
|
commentID, ok := req.GetArguments()["commentID"].(float64)
|
||||||
|
if !ok {
|
||||||
|
return to.ErrorResult(fmt.Errorf("comment ID is required"))
|
||||||
|
}
|
||||||
|
body, ok := req.GetArguments()["body"].(string)
|
||||||
|
if !ok {
|
||||||
|
return to.ErrorResult(fmt.Errorf("body is required"))
|
||||||
|
}
|
||||||
|
opt := gitea_sdk.EditIssueCommentOption{
|
||||||
|
Body: body,
|
||||||
|
}
|
||||||
|
issueComment, _, err := gitea.Client().EditIssueComment(owner, repo, int64(commentID), opt)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("edit %v/%v/issues/comments/%v err: %v", owner, repo, int64(commentID), err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return to.TextResult(issueComment)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetIssueCommentsByIndexFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||||
|
log.Debugf("Called GetIssueCommentsByIndexFn")
|
||||||
|
owner, ok := req.GetArguments()["owner"].(string)
|
||||||
|
if !ok {
|
||||||
|
return to.ErrorResult(fmt.Errorf("owner is required"))
|
||||||
|
}
|
||||||
|
repo, ok := req.GetArguments()["repo"].(string)
|
||||||
|
if !ok {
|
||||||
|
return to.ErrorResult(fmt.Errorf("repo is required"))
|
||||||
|
}
|
||||||
|
index, ok := req.GetArguments()["index"].(float64)
|
||||||
|
if !ok {
|
||||||
|
return to.ErrorResult(fmt.Errorf("index is required"))
|
||||||
|
}
|
||||||
|
opt := gitea_sdk.ListIssueCommentOptions{}
|
||||||
|
issue, _, err := gitea.Client().ListIssueComments(owner, repo, int64(index), opt)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get %v/%v/issues/%v/comments err: %v", owner, repo, int64(index), err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return to.TextResult(issue)
|
||||||
|
}
|
||||||
|
@@ -71,5 +71,6 @@ func newMCPServer(version string) *server.MCPServer {
|
|||||||
version,
|
version,
|
||||||
server.WithToolCapabilities(true),
|
server.WithToolCapabilities(true),
|
||||||
server.WithLogging(),
|
server.WithLogging(),
|
||||||
|
server.WithRecovery(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@@ -16,6 +16,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
GetFileToolName = "get_file_content"
|
GetFileToolName = "get_file_content"
|
||||||
|
GetDirToolName = "get_dir_content"
|
||||||
CreateFileToolName = "create_file"
|
CreateFileToolName = "create_file"
|
||||||
UpdateFileToolName = "update_file"
|
UpdateFileToolName = "update_file"
|
||||||
DeleteFileToolName = "delete_file"
|
DeleteFileToolName = "delete_file"
|
||||||
@@ -31,6 +32,15 @@ var (
|
|||||||
mcp.WithString("filePath", mcp.Required(), mcp.Description("file path")),
|
mcp.WithString("filePath", mcp.Required(), mcp.Description("file path")),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
GetDirContentTool = mcp.NewTool(
|
||||||
|
GetDirToolName,
|
||||||
|
mcp.WithDescription("Get a list of entries in a directory"),
|
||||||
|
mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")),
|
||||||
|
mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")),
|
||||||
|
mcp.WithString("ref", mcp.Required(), mcp.Description("ref can be branch/tag/commit")),
|
||||||
|
mcp.WithString("filePath", mcp.Required(), mcp.Description("directory path")),
|
||||||
|
)
|
||||||
|
|
||||||
CreateFileTool = mcp.NewTool(
|
CreateFileTool = mcp.NewTool(
|
||||||
CreateFileToolName,
|
CreateFileToolName,
|
||||||
mcp.WithDescription("Create file"),
|
mcp.WithDescription("Create file"),
|
||||||
@@ -72,6 +82,10 @@ func init() {
|
|||||||
Tool: GetFileContentTool,
|
Tool: GetFileContentTool,
|
||||||
Handler: GetFileContentFn,
|
Handler: GetFileContentFn,
|
||||||
})
|
})
|
||||||
|
Tool.RegisterRead(server.ServerTool{
|
||||||
|
Tool: GetDirContentTool,
|
||||||
|
Handler: GetDirContentFn,
|
||||||
|
})
|
||||||
Tool.RegisterWrite(server.ServerTool{
|
Tool.RegisterWrite(server.ServerTool{
|
||||||
Tool: CreateFileTool,
|
Tool: CreateFileTool,
|
||||||
Handler: CreateFileFn,
|
Handler: CreateFileFn,
|
||||||
@@ -108,6 +122,28 @@ func GetFileContentFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallTo
|
|||||||
return to.TextResult(content)
|
return to.TextResult(content)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetDirContentFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||||
|
log.Debugf("Called GetDirContentFn")
|
||||||
|
owner, ok := req.GetArguments()["owner"].(string)
|
||||||
|
if !ok {
|
||||||
|
return to.ErrorResult(fmt.Errorf("owner is required"))
|
||||||
|
}
|
||||||
|
repo, ok := req.GetArguments()["repo"].(string)
|
||||||
|
if !ok {
|
||||||
|
return to.ErrorResult(fmt.Errorf("repo is required"))
|
||||||
|
}
|
||||||
|
ref, _ := req.GetArguments()["ref"].(string)
|
||||||
|
filePath, ok := req.GetArguments()["filePath"].(string)
|
||||||
|
if !ok {
|
||||||
|
return to.ErrorResult(fmt.Errorf("filePath is required"))
|
||||||
|
}
|
||||||
|
content, _, err := gitea.Client().ListContents(owner, repo, ref, filePath)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get dir content err: %v", err))
|
||||||
|
}
|
||||||
|
return to.TextResult(content)
|
||||||
|
}
|
||||||
|
|
||||||
func CreateFileFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
func CreateFileFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||||
log.Debugf("Called CreateFileFn")
|
log.Debugf("Called CreateFileFn")
|
||||||
owner, ok := req.GetArguments()["owner"].(string)
|
owner, ok := req.GetArguments()["owner"].(string)
|
||||||
|
@@ -19,12 +19,10 @@ const (
|
|||||||
GetGiteaMCPServerVersion = "get_gitea_mcp_server_version"
|
GetGiteaMCPServerVersion = "get_gitea_mcp_server_version"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var GetGiteaMCPServerVersionTool = mcp.NewTool(
|
||||||
GetGiteaMCPServerVersionTool = mcp.NewTool(
|
|
||||||
GetGiteaMCPServerVersion,
|
GetGiteaMCPServerVersion,
|
||||||
mcp.WithDescription("Get Gitea MCP Server Version"),
|
mcp.WithDescription("Get Gitea MCP Server Version"),
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
Tool.RegisterRead(server.ServerTool{
|
Tool.RegisterRead(server.ServerTool{
|
||||||
|
@@ -22,19 +22,20 @@ func Client() *gitea.Client {
|
|||||||
if client != nil {
|
if client != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
httpClient := &http.Client{
|
||||||
|
Transport: http.DefaultTransport,
|
||||||
|
}
|
||||||
|
|
||||||
opts := []gitea.ClientOption{
|
opts := []gitea.ClientOption{
|
||||||
gitea.SetToken(flag.Token),
|
gitea.SetToken(flag.Token),
|
||||||
}
|
}
|
||||||
if flag.Insecure {
|
if flag.Insecure {
|
||||||
httpClient := &http.Client{
|
httpClient.Transport.(*http.Transport).TLSClientConfig = &tls.Config{
|
||||||
Transport: &http.Transport{
|
|
||||||
TLSClientConfig: &tls.Config{
|
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
},
|
}
|
||||||
},
|
|
||||||
}
|
}
|
||||||
opts = append(opts, gitea.SetHTTPClient(httpClient))
|
opts = append(opts, gitea.SetHTTPClient(httpClient))
|
||||||
}
|
|
||||||
if flag.Debug {
|
if flag.Debug {
|
||||||
opts = append(opts, gitea.SetDebugMode())
|
opts = append(opts, gitea.SetDebugMode())
|
||||||
}
|
}
|
||||||
|
@@ -32,8 +32,14 @@ func Default() *zap.Logger {
|
|||||||
home = os.TempDir()
|
home = os.TempDir()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logDir := fmt.Sprintf("%s/.gitea-mcp", home)
|
||||||
|
if err := os.MkdirAll(logDir, 0o700); err != nil {
|
||||||
|
// Fallback to temp directory if creation fails
|
||||||
|
logDir = os.TempDir()
|
||||||
|
}
|
||||||
|
|
||||||
wss = append(wss, zapcore.AddSync(&lumberjack.Logger{
|
wss = append(wss, zapcore.AddSync(&lumberjack.Logger{
|
||||||
Filename: fmt.Sprintf("%s/.gitea-mcp/gitea-mcp.log", home),
|
Filename: fmt.Sprintf("%s/gitea-mcp.log", logDir),
|
||||||
MaxSize: 100,
|
MaxSize: 100,
|
||||||
MaxBackups: 10,
|
MaxBackups: 10,
|
||||||
MaxAge: 30,
|
MaxAge: 30,
|
||||||
|
Reference in New Issue
Block a user