@amonstack/gitea-mcp 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -19
- package/README.zh-CN.md +69 -17
- package/dist/assets/instructions.md +19 -7
- package/dist/assets/skills/gitea-comment-issue/SKILL.md +34 -0
- package/dist/assets/skills/gitea-configure/SKILL.md +60 -0
- package/dist/assets/skills/gitea-create-issue/SKILL.md +44 -1
- package/dist/assets/skills/gitea-plan-milestones/SKILL.md +17 -0
- package/dist/assets/skills/gitea-resolve-repo/SKILL.md +17 -6
- package/dist/assets/skills/gitea-summarize-issue/SKILL.md +1 -1
- package/dist/cli.js +18 -12
- package/dist/cli.js.map +1 -1
- package/dist/git-config.d.ts +73 -0
- package/dist/git-config.js +195 -0
- package/dist/git-config.js.map +1 -0
- package/dist/gitea-client.d.ts +3 -2
- package/dist/gitea-client.js +3 -4
- package/dist/gitea-client.js.map +1 -1
- package/dist/server.d.ts +2 -2
- package/dist/server.js +20 -20
- package/dist/server.js.map +1 -1
- package/dist/skills.d.ts +32 -12
- package/dist/skills.js +99 -29
- package/dist/skills.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -52,13 +52,50 @@ node dist/cli.js
|
|
|
52
52
|
|
|
53
53
|
## Configuration
|
|
54
54
|
|
|
55
|
+
All variables are optional — `gitea-mcp` auto-discovers the Gitea instance, repository,
|
|
56
|
+
and token from the project's local git config so a single global install can serve many
|
|
57
|
+
projects. Set them only to override the discovery.
|
|
58
|
+
|
|
55
59
|
| Variable | Required | Description |
|
|
56
60
|
|----------|:--------:|-------------|
|
|
57
|
-
| `GITEA_BASE_URL` |
|
|
58
|
-
| `GITEA_TOKEN` |
|
|
61
|
+
| `GITEA_BASE_URL` | No | Gitea instance URL (e.g. `https://gitea.example.com`). Auto-detected from the project's git remote when omitted. |
|
|
62
|
+
| `GITEA_TOKEN` | No | Gitea API access token. Resolved from `.git/config`, the git credential store, then this variable (see [Token discovery](#token-discovery)). |
|
|
59
63
|
| `GITEA_DEFAULT_OWNER` | No | Default repository owner — skip passing `owner` on every call |
|
|
60
64
|
| `GITEA_DEFAULT_REPO` | No | Default repository name — skip passing `repo` on every call |
|
|
61
65
|
|
|
66
|
+
### How auto-discovery works
|
|
67
|
+
|
|
68
|
+
On start, `gitea-mcp` reads `<cwd>/.git/config` and derives:
|
|
69
|
+
|
|
70
|
+
- **Instance URL** — from the selected remote's host. SSH remotes (`git@host:owner/repo`)
|
|
71
|
+
resolve to `https://host`. Override with `GITEA_BASE_URL`.
|
|
72
|
+
- **owner / repo** — from the selected remote's URL. Override with `GITEA_DEFAULT_OWNER` /
|
|
73
|
+
`GITEA_DEFAULT_REPO`, or detect ad hoc with the `resolve_repo` tool.
|
|
74
|
+
- **Remote selection** — the `upstream` remote is preferred, falling back to `origin`, then
|
|
75
|
+
any other remote. Both are reported by `resolve_repo` when they differ.
|
|
76
|
+
|
|
77
|
+
If the current directory has no git remote and `GITEA_BASE_URL` is not set, the server does
|
|
78
|
+
**not** start — it prints a skip reason and exits 0. Run it from inside a cloned Gitea
|
|
79
|
+
repository, or set `GITEA_BASE_URL` / `GITEA_TOKEN` explicitly.
|
|
80
|
+
|
|
81
|
+
### Token discovery
|
|
82
|
+
|
|
83
|
+
The token is resolved in this order (first match wins):
|
|
84
|
+
|
|
85
|
+
1. A `[gitea "<baseUrl>"]` section in `.git/config`:
|
|
86
|
+
```ini
|
|
87
|
+
[gitea "https://gitea.example.com"]
|
|
88
|
+
token = <your-token>
|
|
89
|
+
```
|
|
90
|
+
A bare `[gitea]` section with `token = ...` is a host-wide fallback.
|
|
91
|
+
2. The git credential store (`~/.git-credentials`, or `$XDG_CONFIG_HOME/git/credentials`) —
|
|
92
|
+
a line whose host matches the instance, e.g. `https://oauth2:<token>@gitea.example.com`.
|
|
93
|
+
3. The `GITEA_TOKEN` environment variable.
|
|
94
|
+
|
|
95
|
+
If none resolves, the server still starts without a token (anonymous). Public repositories
|
|
96
|
+
may be read; private repos and write operations return `401` — use the `gitea-configure`
|
|
97
|
+
skill to guide setup, or set `GITEA_TOKEN`.
|
|
98
|
+
|
|
62
99
|
When `GITEA_DEFAULT_OWNER` and `GITEA_DEFAULT_REPO` are set, you can omit the
|
|
63
100
|
`owner` and `repo` parameters in tool calls. The `resolve_repo` tool can also
|
|
64
101
|
auto-detect them from a local git repository.
|
|
@@ -107,22 +144,38 @@ Add to your opencode MCP configuration:
|
|
|
107
144
|
|
|
108
145
|
If you built from source, use `node /path/to/gitea-mcp/dist/cli.js` instead.
|
|
109
146
|
|
|
110
|
-
opencode
|
|
111
|
-
label, summarize, plan milestones, resolve repo) — that
|
|
112
|
-
safest workflow for that action, including pre-use checks
|
|
113
|
-
them once
|
|
147
|
+
opencode and other AI tools can load native **skills** — one per action (find,
|
|
148
|
+
create, update, label, comment, summarize, plan milestones, resolve repo) — that
|
|
149
|
+
teach the assistant the safest workflow for that action, including pre-use checks
|
|
150
|
+
and pitfalls. Install them once with the `init` command, targeting your tool
|
|
151
|
+
(`--tool`, default `opencode`):
|
|
114
152
|
|
|
115
153
|
```bash
|
|
116
|
-
gitea-mcp
|
|
117
|
-
gitea-mcp
|
|
154
|
+
gitea-mcp init # opencode (global ~/.config/opencode/skills/)
|
|
155
|
+
gitea-mcp init --tool claude # Claude Code (~/.claude/skills/)
|
|
156
|
+
gitea-mcp init --tool cursor # Cursor (~/.cursor/skills/)
|
|
157
|
+
gitea-mcp init --project # this project (./.<tool>/skills/)
|
|
158
|
+
gitea-mcp init --dir /exact/path # custom location
|
|
118
159
|
```
|
|
119
160
|
|
|
120
|
-
|
|
161
|
+
Supported `--tool` values: `amazon-q`, `antigravity`, `auggie`, `claude`,
|
|
162
|
+
`cline`, `codex`, `codebuddy`, `continue`, `costrict`, `crush`, `cursor`,
|
|
163
|
+
`factory`, `gemini`, `github-copilot`, `iflow`, `kilocode`, `opencode`, `qoder`,
|
|
164
|
+
`qwen`, `roocode`, `windsurf`. Paths follow each tool's conventional skills
|
|
165
|
+
directory; use `--dir` for an exact location. Then restart your tool. See
|
|
166
|
+
[AI Guidance & Skills](#ai-guidance--skills) below.
|
|
121
167
|
|
|
122
168
|
### Other MCP Clients
|
|
123
169
|
|
|
124
170
|
Any client that supports stdio-based MCP servers can use `gitea-mcp`. After
|
|
125
|
-
installation,
|
|
171
|
+
installation, run it from inside a cloned Gitea repository (config is auto-discovered):
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
cd /path/to/your/gitea-repo
|
|
175
|
+
gitea-mcp
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Or set the variables explicitly if you prefer:
|
|
126
179
|
|
|
127
180
|
```bash
|
|
128
181
|
export GITEA_BASE_URL="https://gitea.example.com"
|
|
@@ -180,7 +233,7 @@ gitea-mcp
|
|
|
180
233
|
| Tool | Description |
|
|
181
234
|
|------|-------------|
|
|
182
235
|
| `list_my_repos` | List repositories accessible to the authenticated user |
|
|
183
|
-
| `resolve_repo` |
|
|
236
|
+
| `resolve_repo` | Detect `baseUrl`, `owner`, and `repo` from the project's git remotes (`upstream` preferred, then `origin`) |
|
|
184
237
|
|
|
185
238
|
## AI Guidance & Skills
|
|
186
239
|
|
|
@@ -195,12 +248,12 @@ through three channels:
|
|
|
195
248
|
`summarize_issue`, `audit_labels`, `milestone_report`) and on-demand reference
|
|
196
249
|
docs (field reference, label guide, tool cookbook) for clients that surface them.
|
|
197
250
|
|
|
198
|
-
###
|
|
251
|
+
### Action skills
|
|
199
252
|
|
|
200
|
-
For opencode, the server ships a set of **action-scoped skills**
|
|
201
|
-
workflow, so the assistant loads only the guidance it needs (and never,
|
|
202
|
-
delete instructions while creating). Install them with the
|
|
203
|
-
`gitea-mcp
|
|
253
|
+
For opencode and other tools, the server ships a set of **action-scoped skills**
|
|
254
|
+
— one per workflow, so the assistant loads only the guidance it needs (and never,
|
|
255
|
+
say, delete instructions while creating). Install them with the
|
|
256
|
+
`gitea-mcp init --tool <name>` command shown above.
|
|
204
257
|
|
|
205
258
|
| Skill | Invoke when |
|
|
206
259
|
|-------|-------------|
|
|
@@ -209,14 +262,18 @@ delete instructions while creating). Install them with the
|
|
|
209
262
|
| `gitea-update-issue` | editing fields, closing, clearing assignee/milestone |
|
|
210
263
|
| `gitea-label-issue` | adding / replacing / removing / clearing labels on an issue |
|
|
211
264
|
| `gitea-manage-labels` | creating or editing label definitions |
|
|
265
|
+
| `gitea-comment-issue` | posting a comment that advances an issue's discussion |
|
|
212
266
|
| `gitea-summarize-issue` | reading and summarizing an issue's discussion |
|
|
213
267
|
| `gitea-plan-milestones` | creating / editing / closing milestones |
|
|
214
268
|
| `gitea-resolve-repo` | resolving owner/repo or listing repositories |
|
|
269
|
+
| `gitea-configure` | fixing the connection — instance URL, token, or 401/403 errors |
|
|
215
270
|
|
|
216
271
|
Each skill is a short, AI-facing action flow (purpose, when to use, when not to,
|
|
217
|
-
rules, and what to check first).
|
|
218
|
-
|
|
219
|
-
|
|
272
|
+
rules, and what to check first). The create, comment, and milestone skills also
|
|
273
|
+
embed **body templates** (bug / feature / performance issue, comment, milestone)
|
|
274
|
+
that standardize the format of what the assistant writes. Destructive
|
|
275
|
+
single-tool actions (delete issue / comment / label / milestone) are intentionally
|
|
276
|
+
left to the tool descriptions so they never contaminate a creative workflow.
|
|
220
277
|
|
|
221
278
|
## Development
|
|
222
279
|
|
package/README.zh-CN.md
CHANGED
|
@@ -50,13 +50,47 @@ node dist/cli.js
|
|
|
50
50
|
|
|
51
51
|
## 配置
|
|
52
52
|
|
|
53
|
+
所有变量都是可选的——`gitea-mcp` 会从项目本地 git 配置自动发现 Gitea 实例、仓库和令牌,
|
|
54
|
+
因此一次全局安装即可服务多个项目。仅在需要覆盖自动发现结果时才设置它们。
|
|
55
|
+
|
|
53
56
|
| 变量 | 必填 | 说明 |
|
|
54
57
|
|------|:----:|------|
|
|
55
|
-
| `GITEA_BASE_URL` |
|
|
56
|
-
| `GITEA_TOKEN` |
|
|
58
|
+
| `GITEA_BASE_URL` | 否 | Gitea 实例地址(如 `https://gitea.example.com`)。未设置时从项目 git 远程地址自动推导。 |
|
|
59
|
+
| `GITEA_TOKEN` | 否 | Gitea API 访问令牌。依次从 `.git/config`、git 凭据存储、本变量解析(见[令牌发现](#令牌发现))。 |
|
|
57
60
|
| `GITEA_DEFAULT_OWNER` | 否 | 默认仓库所有者,免去每次传入 `owner` 参数 |
|
|
58
61
|
| `GITEA_DEFAULT_REPO` | 否 | 默认仓库名称,免去每次传入 `repo` 参数 |
|
|
59
62
|
|
|
63
|
+
### 自动发现的工作方式
|
|
64
|
+
|
|
65
|
+
启动时,`gitea-mcp` 读取 `<cwd>/.git/config` 并推导:
|
|
66
|
+
|
|
67
|
+
- **实例地址** —— 取自选中远程地址的 host。SSH 远程(`git@host:owner/repo`)会被推导为
|
|
68
|
+
`https://host`。可用 `GITEA_BASE_URL` 覆盖。
|
|
69
|
+
- **owner / repo** —— 取自选中远程地址。可用 `GITEA_DEFAULT_OWNER` / `GITEA_DEFAULT_REPO`
|
|
70
|
+
覆盖,或随时用 `resolve_repo` 工具检测。
|
|
71
|
+
- **远程选择** —— 优先 `upstream`,回退 `origin`,再回退其它远程。两者不同时 `resolve_repo`
|
|
72
|
+
会同时返回。
|
|
73
|
+
|
|
74
|
+
若当前目录没有 git 远程、且未设置 `GITEA_BASE_URL`,服务器**不会启动**——它会打印跳过原因并
|
|
75
|
+
以 exit 0 退出。请在克隆的 Gitea 仓库内运行,或显式设置 `GITEA_BASE_URL` / `GITEA_TOKEN`。
|
|
76
|
+
|
|
77
|
+
### 令牌发现
|
|
78
|
+
|
|
79
|
+
令牌按以下顺序解析(先匹配者胜出):
|
|
80
|
+
|
|
81
|
+
1. `.git/config` 中的 `[gitea "<baseUrl>"]` 段:
|
|
82
|
+
```ini
|
|
83
|
+
[gitea "https://gitea.example.com"]
|
|
84
|
+
token = <your-token>
|
|
85
|
+
```
|
|
86
|
+
不带地址的 `[gitea]` 段中的 `token = ...` 作为全局兜底。
|
|
87
|
+
2. git 凭据存储(`~/.git-credentials`,或 `$XDG_CONFIG_HOME/git/credentials`)——host 匹配实例
|
|
88
|
+
的那一行,如 `https://oauth2:<token>@gitea.example.com`。
|
|
89
|
+
3. `GITEA_TOKEN` 环境变量。
|
|
90
|
+
|
|
91
|
+
若都未解析到,服务器仍会以匿名方式启动。公开仓库可读;私有仓库和写操作返回 `401`——此时使用
|
|
92
|
+
`gitea-configure` 技能引导配置,或设置 `GITEA_TOKEN`。
|
|
93
|
+
|
|
60
94
|
设置 `GITEA_DEFAULT_OWNER` 和 `GITEA_DEFAULT_REPO` 后,调用工具时可以省略
|
|
61
95
|
`owner` 和 `repo` 参数。也可以使用 `resolve_repo` 工具自动从本地 git 仓库
|
|
62
96
|
检测这两个值。
|
|
@@ -105,21 +139,36 @@ node dist/cli.js
|
|
|
105
139
|
|
|
106
140
|
如果从源码构建,将 `command` 改为 `node /path/to/gitea-mcp/dist/cli.js`。
|
|
107
141
|
|
|
108
|
-
opencode
|
|
109
|
-
|
|
110
|
-
|
|
142
|
+
opencode 及其它 AI 工具可加载原生**技能(skills)**——按动作拆分(查找、创建、
|
|
143
|
+
更新、打标签、评论、总结、规划里程碑、解析仓库等),教会助手针对该动作的最安全
|
|
144
|
+
工作流,含使用前检查与各类陷阱。用 `init` 命令一次性安装,并通过 `--tool` 指定
|
|
145
|
+
目标工具(默认 `opencode`):
|
|
111
146
|
|
|
112
147
|
```bash
|
|
113
|
-
gitea-mcp
|
|
114
|
-
gitea-mcp
|
|
148
|
+
gitea-mcp init # opencode(全局 ~/.config/opencode/skills/)
|
|
149
|
+
gitea-mcp init --tool claude # Claude Code(~/.claude/skills/)
|
|
150
|
+
gitea-mcp init --tool cursor # Cursor(~/.cursor/skills/)
|
|
151
|
+
gitea-mcp init --project # 仅当前项目(./.<tool>/skills/)
|
|
152
|
+
gitea-mcp init --dir /exact/path # 自定义路径
|
|
115
153
|
```
|
|
116
154
|
|
|
117
|
-
|
|
155
|
+
支持的 `--tool` 取值:`amazon-q`、`antigravity`、`auggie`、`claude`、`cline`、
|
|
156
|
+
`codex`、`codebuddy`、`continue`、`costrict`、`crush`、`cursor`、`factory`、
|
|
157
|
+
`gemini`、`github-copilot`、`iflow`、`kilocode`、`opencode`、`qoder`、`qwen`、
|
|
158
|
+
`roocode`、`windsurf`。路径遵循各工具约定的 skills 目录;如需精确位置请用 `--dir`。
|
|
159
|
+
随后重启对应工具。详见下方 [AI 引导与技能](#ai-引导与技能)。
|
|
118
160
|
|
|
119
161
|
### 其他 MCP 客户端
|
|
120
162
|
|
|
121
|
-
任何支持 stdio 方式运行 MCP
|
|
122
|
-
|
|
163
|
+
任何支持 stdio 方式运行 MCP 服务端的客户端都可以使用。安装完成后,在克隆的 Gitea 仓库内
|
|
164
|
+
吏动即可(配置会自动发现):
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
cd /path/to/your/gitea-repo
|
|
168
|
+
gitea-mcp
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
也可显式设置环境变量:
|
|
123
172
|
|
|
124
173
|
```bash
|
|
125
174
|
export GITEA_BASE_URL="https://gitea.example.com"
|
|
@@ -177,7 +226,7 @@ gitea-mcp
|
|
|
177
226
|
| 工具 | 说明 |
|
|
178
227
|
|------|------|
|
|
179
228
|
| `list_my_repos` | 列出当前用户可访问的仓库 |
|
|
180
|
-
| `resolve_repo` |
|
|
229
|
+
| `resolve_repo` | 从项目 git 远程地址检测 `baseUrl`、`owner`、`repo`(优先 `upstream`,回退 `origin`) |
|
|
181
230
|
|
|
182
231
|
## AI 引导与技能
|
|
183
232
|
|
|
@@ -191,11 +240,11 @@ gitea-mcp
|
|
|
191
240
|
`audit_labels`、`milestone_report`)与按需参考文档(字段参考、标签指南、工具
|
|
192
241
|
食谱),供支持的客户端使用。
|
|
193
242
|
|
|
194
|
-
###
|
|
243
|
+
### 动作技能
|
|
195
244
|
|
|
196
|
-
对 opencode
|
|
197
|
-
|
|
198
|
-
|
|
245
|
+
对 opencode 及其它工具,服务端内置了一组**按动作划分的技能**——每个工作流一
|
|
246
|
+
个,助手只加载所需指引(避免例如创建时把删除说明一并带入造成幻觉)。用上方展示的
|
|
247
|
+
`gitea-mcp init --tool <name>` 命令安装。
|
|
199
248
|
|
|
200
249
|
| 技能 | 何时触发 |
|
|
201
250
|
|------|----------|
|
|
@@ -204,13 +253,16 @@ gitea-mcp
|
|
|
204
253
|
| `gitea-update-issue` | 编辑字段、关闭、清空负责人/里程碑 |
|
|
205
254
|
| `gitea-label-issue` | 为 issue 增加 / 替换 / 移除 / 清空标签 |
|
|
206
255
|
| `gitea-manage-labels` | 创建或编辑标签定义 |
|
|
256
|
+
| `gitea-comment-issue` | 在 issue 下发表推动讨论的评论 |
|
|
207
257
|
| `gitea-summarize-issue` | 读取并总结某 issue 的讨论 |
|
|
208
258
|
| `gitea-plan-milestones` | 创建 / 编辑 / 关闭里程碑 |
|
|
209
259
|
| `gitea-resolve-repo` | 解析 owner/repo 或列出仓库 |
|
|
260
|
+
| `gitea-configure` | 修复连接——实例地址、令牌或 401/403 报错 |
|
|
210
261
|
|
|
211
262
|
每个技能都是面向 AI 的简短动作流程(目的、何时用、何时不用、规则、先检查什么)。
|
|
212
|
-
|
|
213
|
-
|
|
263
|
+
创建、评论、里程碑三类技能还内嵌**正文模板**(bug / 新功能 / 性能 issue、评论、
|
|
264
|
+
里程碑),用以规范助手所写内容的格式。破坏性的单工具操作(删除 issue / 评论 /
|
|
265
|
+
标签 / 里程碑)有意仅保留在工具描述里,不会污染创建类工作流。
|
|
214
266
|
|
|
215
267
|
## 二次开发
|
|
216
268
|
|
|
@@ -4,18 +4,29 @@ You manage Gitea issues, comments, labels, and milestones through this MCP serve
|
|
|
4
4
|
Every tool returns Gitea's JSON verbatim as text. Follow these rules to use them
|
|
5
5
|
correctly.
|
|
6
6
|
|
|
7
|
+
## Config is auto-discovered from git (env vars optional)
|
|
8
|
+
|
|
9
|
+
On start the server reads `<cwd>/.git/config` and derives `baseUrl`, `owner`, `repo`,
|
|
10
|
+
and `token` so one global install can serve many projects. The `GITEA_BASE_URL` /
|
|
11
|
+
`GITEA_TOKEN` / `GITEA_DEFAULT_OWNER` / `GITEA_DEFAULT_REPO` env vars are OPTIONAL
|
|
12
|
+
overrides; when set they take precedence over git discovery. The remote is chosen
|
|
13
|
+
`upstream` first, then `origin`. If the cwd has no git remote and `GITEA_BASE_URL` is
|
|
14
|
+
unset, the server does not start (it prints a skip reason and exits 0). If you hit a
|
|
15
|
+
401/403 or the connection looks unset, use the **gitea-configure** skill.
|
|
16
|
+
|
|
7
17
|
## Resolve owner/repo FIRST (most common failure)
|
|
8
18
|
|
|
9
19
|
Most tools target one repository and need both `owner` and `repo`. They resolve in
|
|
10
20
|
this order:
|
|
11
21
|
|
|
12
22
|
1. The `owner` / `repo` arguments you pass to the call.
|
|
13
|
-
2. `GITEA_DEFAULT_OWNER` / `GITEA_DEFAULT_REPO` env vars (
|
|
14
|
-
|
|
23
|
+
2. `GITEA_DEFAULT_OWNER` / `GITEA_DEFAULT_REPO` env vars (or the git-discovered defaults
|
|
24
|
+
captured at server start).
|
|
25
|
+
3. The `resolve_repo` tool (re-reads `.git/config` and returns `baseUrl`, `owner`, `repo`,
|
|
26
|
+
the selected `remote`, and every parsed remote under `remotes`).
|
|
15
27
|
|
|
16
|
-
If
|
|
17
|
-
|
|
18
|
-
once and reuse the result — do not guess.
|
|
28
|
+
If none resolve, the call errors. Before a batch of work on a repo you have not used this
|
|
29
|
+
session, call `resolve_repo` once and reuse the result — do not guess.
|
|
19
30
|
|
|
20
31
|
## Labels: IDs vs names (critical gotcha)
|
|
21
32
|
|
|
@@ -59,5 +70,6 @@ Confirm the target id/index and scope with the user before calling. For labels,
|
|
|
59
70
|
## Error format
|
|
60
71
|
|
|
61
72
|
Failed calls throw `Gitea API error (<status>): <body>`. Read the status: 401/403 →
|
|
62
|
-
token
|
|
63
|
-
|
|
73
|
+
token missing, wrong, or lacks scope — run the **gitea-configure** skill to fix the
|
|
74
|
+
connection; 404 → wrong owner/repo or no permission; 409 → conflict; 422 → validation.
|
|
75
|
+
Do not retry blindly on 4xx.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gitea-comment-issue
|
|
3
|
+
description: Invoke to POST a new comment on a Gitea issue or pull request. The flow confirms the issue exists first, then posts. Do NOT invoke to edit or delete a comment (author/admin only, partly destructive — no skill), read or summarize the thread (gitea-summarize-issue), or create/edit the issue itself (gitea-create-issue / gitea-update-issue).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# gitea-comment-issue
|
|
7
|
+
|
|
8
|
+
Post one new comment that advances an issue's discussion. Tools: `get_issue`, `create_comment`.
|
|
9
|
+
|
|
10
|
+
## Prerequisites
|
|
11
|
+
- Resolve `owner`+`repo`: pass explicitly, else `GITEA_DEFAULT_OWNER`/`GITEA_DEFAULT_REPO`, else `resolve_repo` (gitea-resolve-repo). Never guess — wrong values post to the wrong place.
|
|
12
|
+
- `index` = the issue `number` (URL #N → N), never the internal `id`.
|
|
13
|
+
|
|
14
|
+
## Flow
|
|
15
|
+
1. CONFIRM TARGET: `get_issue({ index })` — verify the issue exists and is the one you mean. Do NOT post blind.
|
|
16
|
+
2. POST: `create_comment({ index, body })`.
|
|
17
|
+
|
|
18
|
+
## create_comment
|
|
19
|
+
- RULES: `body` required, Markdown. The comment APPENDS to the thread — it never edits or replaces prior content. The response carries the comment `id`; retain it only if a follow-up `update_comment` / `delete_comment` is planned.
|
|
20
|
+
- CHECK FIRST: re-read the latest thread (gitea-summarize-issue) so your comment is not redundant or contradicting a newer message.
|
|
21
|
+
- CHECK AFTER: the comment appears with the returned `id`.
|
|
22
|
+
|
|
23
|
+
## Body template — standardize what you write into `body`
|
|
24
|
+
A useful comment is contextual, evidence-backed, and proposes a next step. Structure `body` with this template; drop sections that add nothing.
|
|
25
|
+
|
|
26
|
+
```markdown
|
|
27
|
+
**Context:** <the point you are responding to>
|
|
28
|
+
|
|
29
|
+
**Finding / proposal:** <what you discovered or suggest>
|
|
30
|
+
|
|
31
|
+
**Evidence:** <log excerpt, link, reproduction, or metric>
|
|
32
|
+
|
|
33
|
+
**Suggested next step:** <the concrete action you propose>
|
|
34
|
+
```
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gitea-configure
|
|
3
|
+
description: Invoke to CONFIGURE / SET UP / FIX the Gitea connection — instance URL, token, or owner/repo discovery. Use when a tool fails with 401/403 (bad or missing token), when the user asks how to wire up gitea-mcp, or when baseUrl/owner/repo could not be auto-detected. Do NOT invoke for normal issue/label/milestone work once the connection works.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# gitea-configure
|
|
7
|
+
|
|
8
|
+
Diagnose and fix the Gitea connection. The server auto-discovers its config from the
|
|
9
|
+
project's git remotes; this skill is the fallback when that fails or the token is wrong.
|
|
10
|
+
|
|
11
|
+
## How gitea-mcp discovers config (no env vars required)
|
|
12
|
+
|
|
13
|
+
On start, the server reads `<cwd>/.git/config` and resolves in this order:
|
|
14
|
+
|
|
15
|
+
1. **baseUrl** — `GITEA_BASE_URL` env var, else derived from the selected remote's host.
|
|
16
|
+
SSH remotes (`git@host:owner/repo`) resolve to `https://host`.
|
|
17
|
+
2. **owner / repo** — `GITEA_DEFAULT_OWNER` / `GITEA_DEFAULT_REPO` env vars, else from the
|
|
18
|
+
selected remote's URL.
|
|
19
|
+
3. **Remote selection** — `upstream` remote first, falling back to `origin`, then any
|
|
20
|
+
other remote. Both are surfaced in `resolve_repo` output.
|
|
21
|
+
|
|
22
|
+
If the working directory has NO git remote and `GITEA_BASE_URL` is unset, the server does
|
|
23
|
+
NOT start (it prints a skip reason and exits 0). That is intentional, not a crash.
|
|
24
|
+
|
|
25
|
+
## Token discovery chain (tried in order)
|
|
26
|
+
|
|
27
|
+
1. `.git/config` — a `[gitea "<baseUrl>"]` section, e.g.
|
|
28
|
+
```ini
|
|
29
|
+
[gitea "https://gitea.example.com"]
|
|
30
|
+
token = <your-token>
|
|
31
|
+
```
|
|
32
|
+
A bare `[gitea]` section with `token = ...` is a host-wide fallback.
|
|
33
|
+
2. The git credential store (`~/.git-credentials`, or `$XDG_CONFIG_HOME/git/credentials`)
|
|
34
|
+
— a line whose host matches the instance, e.g.
|
|
35
|
+
`https://oauth2:<token>@gitea.example.com`.
|
|
36
|
+
3. `GITEA_TOKEN` env var.
|
|
37
|
+
4. If none of the above yield a token, the server starts WITHOUT a token (anonymous). Public
|
|
38
|
+
repos may be read; writes and private repos return 401 — that is the signal to help the
|
|
39
|
+
user add a token via one of the sources above.
|
|
40
|
+
|
|
41
|
+
## Fix flow — when a tool returns 401 / 403
|
|
42
|
+
|
|
43
|
+
1. Confirm the instance: run `resolve_repo` (no args) and read its `baseUrl` and `remote`.
|
|
44
|
+
If it throws, the cwd has no usable git remote — tell the user to run gitea-mcp from a
|
|
45
|
+
cloned repo, or set `GITEA_BASE_URL` + `GITEA_TOKEN`.
|
|
46
|
+
2. Ask the user to create a token at `<baseUrl>/user/settings/applications` (Gitea → Settings
|
|
47
|
+
→ Applications → Access Tokens). Capture the scopes they need: `issue`, `comment`,
|
|
48
|
+
`label`, `milestone` (read+write). NEVER have the user paste a token into chat unless they
|
|
49
|
+
explicitly choose to — prefer having them run a git command themselves.
|
|
50
|
+
3. Have the user store it so discovery finds it. Recommend, in priority order:
|
|
51
|
+
- `git config --file=.git/config gitea."<baseUrl>".token "<token>"` (project-scoped), or
|
|
52
|
+
- add to the credential store, or
|
|
53
|
+
- export `GITEA_TOKEN` (and `GITEA_BASE_URL`) in their MCP client config.
|
|
54
|
+
`<baseUrl>` is the EXACT value `resolve_repo` reported (scheme + host, with port if any).
|
|
55
|
+
4. The server must be restarted for new config to take effect — discovery runs once at start.
|
|
56
|
+
|
|
57
|
+
## Never log the token
|
|
58
|
+
|
|
59
|
+
Tokens are secret. Do not echo, paste into notes, or include in issue/comment bodies. Pass
|
|
60
|
+
configuration values to the user as commands to run themselves; never print a token back.
|
|
@@ -11,7 +11,7 @@ Open one new issue after ruling out a duplicate. Tools: `search_issues`, `create
|
|
|
11
11
|
- Resolve `owner`+`repo`: pass explicitly, else `GITEA_DEFAULT_OWNER`/`GITEA_DEFAULT_REPO`, else `resolve_repo` (gitea-resolve-repo). Never guess — wrong values create the issue in the wrong repo.
|
|
12
12
|
|
|
13
13
|
## Flow
|
|
14
|
-
1. DUPLICATE CHECK (always first): `search_issues({ query: "<title keywords>", type: "issues" })`. If a match exists, comment on it (gitea-
|
|
14
|
+
1. DUPLICATE CHECK (always first): `search_issues({ query: "<title keywords>", type: "issues" })`. If a match exists, comment on it (gitea-comment-issue) instead of creating a duplicate. Do NOT skip this — creation does not de-duplicate.
|
|
15
15
|
2. CREATE: `create_issue({ title, body?, assignees? })`.
|
|
16
16
|
|
|
17
17
|
## create_issue
|
|
@@ -19,3 +19,46 @@ Open one new issue after ruling out a duplicate. Tools: `search_issues`, `create
|
|
|
19
19
|
- Do NOT pass `labels` or `milestone` here: `labels` expect IDs (error-prone) and milestone needs an id. Create WITHOUT them, then attach labels by name via `add_issue_labels` (gitea-label-issue) and set the milestone via `update_issue` (gitea-update-issue).
|
|
20
20
|
- CHECK FIRST: confirm no duplicate (step 1) and that `owner`/`repo` are correct before writing.
|
|
21
21
|
- CHECK AFTER: the returned object's `number` is the new issue index.
|
|
22
|
+
|
|
23
|
+
## Body templates — standardize what you write into `body`
|
|
24
|
+
Always structure `body` with the template matching the issue type. Ask the user which type if it is not obvious. Drop a section only when it is genuinely empty; never invent data. These are GitHub-OSS conventions adapted for the Markdown body that `create_issue` accepts.
|
|
25
|
+
|
|
26
|
+
### Bug report
|
|
27
|
+
```markdown
|
|
28
|
+
**Summary:** <one-line description of what is wrong>
|
|
29
|
+
|
|
30
|
+
**Steps to reproduce**
|
|
31
|
+
1. <step>
|
|
32
|
+
2. <step>
|
|
33
|
+
|
|
34
|
+
**Expected:** <what should happen>
|
|
35
|
+
**Actual:** <what happens instead>
|
|
36
|
+
|
|
37
|
+
**Environment**
|
|
38
|
+
- gitea-mcp version:
|
|
39
|
+
- Gitea version:
|
|
40
|
+
- Node / runtime:
|
|
41
|
+
- OS:
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Feature request
|
|
45
|
+
```markdown
|
|
46
|
+
**Motivation:** <the problem or need this addresses>
|
|
47
|
+
|
|
48
|
+
**Proposal:** <what to add or change>
|
|
49
|
+
|
|
50
|
+
**Alternatives considered:** <other approaches and why they fall short>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Performance issue
|
|
54
|
+
```markdown
|
|
55
|
+
**Symptom:** <what is slow, or which metric regressed>
|
|
56
|
+
|
|
57
|
+
**How to reproduce:** <scenario + data size / load>
|
|
58
|
+
|
|
59
|
+
**Measurements**
|
|
60
|
+
- Before: <baseline metric>
|
|
61
|
+
- After / target: <current or goal metric>
|
|
62
|
+
|
|
63
|
+
**Suspected bottleneck:** <where the cost seems to come from>
|
|
64
|
+
```
|
|
@@ -22,3 +22,20 @@ Create / edit / close milestones. Tools: `list_milestones`, `get_milestone`, `cr
|
|
|
22
22
|
|
|
23
23
|
## get_milestone
|
|
24
24
|
- Read one milestone by `id`: includes `open_issues` / `closed_issues` counts for progress (progress = closed / (open + closed)).
|
|
25
|
+
|
|
26
|
+
## Description template — standardize what you write into `description`
|
|
27
|
+
Milestones succeed when scope is explicit. When creating or editing, structure `description` with this template; keep it short and drop empty sections.
|
|
28
|
+
|
|
29
|
+
```markdown
|
|
30
|
+
**Goal:** <the single outcome this milestone delivers>
|
|
31
|
+
|
|
32
|
+
**Scope**
|
|
33
|
+
- In: <what this milestone covers>
|
|
34
|
+
- Out: <what is explicitly deferred>
|
|
35
|
+
|
|
36
|
+
**Acceptance criteria**
|
|
37
|
+
- <observable, checkable condition>
|
|
38
|
+
- <observable, checkable condition>
|
|
39
|
+
|
|
40
|
+
**Owners:** <who is accountable>
|
|
41
|
+
```
|
|
@@ -1,18 +1,29 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gitea-resolve-repo
|
|
3
|
-
description: Invoke to RESOLVE which owner/repo the other gitea tools should target (auto-detect from a git remote) or to LIST repositories the token can access. Run FIRST when the target repository is unknown. Do NOT invoke for issue/comment/label/milestone work once owner/repo are known.
|
|
3
|
+
description: Invoke to RESOLVE which owner/repo (and baseUrl) the other gitea tools should target (auto-detect from a git remote) or to LIST repositories the token can access. Run FIRST when the target repository is unknown. Do NOT invoke for issue/comment/label/milestone work once owner/repo are known.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# gitea-resolve-repo
|
|
7
7
|
|
|
8
|
-
Discover the target repository. Tools: `resolve_repo`, `list_my_repos`.
|
|
8
|
+
Discover the target repository and instance. Tools: `resolve_repo`, `list_my_repos`.
|
|
9
9
|
|
|
10
10
|
## resolve_repo
|
|
11
|
-
- Reads
|
|
12
|
-
|
|
11
|
+
- Reads `.git/config` of the git repo at `path` (default: current directory) and parses
|
|
12
|
+
EVERY remote from SSH (`git@gitea.example:owner/repo.git`) or HTTPS
|
|
13
|
+
(`https://gitea.example/owner/repo.git`) URLs.
|
|
14
|
+
- Selects the remote to target in this priority: `upstream` → `origin` → any other.
|
|
15
|
+
SSH remotes resolve to `baseUrl = https://<host>` (the API is assumed HTTPS).
|
|
16
|
+
- Returns `{ baseUrl, owner, repo, remote, remote_url, remotes: { <name>: {baseUrl, owner, repo, url} } }`.
|
|
17
|
+
Read `baseUrl` to know which instance a token must be valid for; read `remotes` to see
|
|
18
|
+
upstream vs origin when they differ.
|
|
19
|
+
- Throws `No parseable git remotes found` if the cwd has no git remote or none parse. Do
|
|
20
|
+
NOT guess owner/repo from context — call this, or ask the user.
|
|
13
21
|
|
|
14
22
|
## list_my_repos
|
|
15
|
-
- Lists repositories the token can access. GLOBAL. Returns large objects — paginate (`limit` ≤ 100) and read only the fields you need (name, full_name, owner.login).
|
|
23
|
+
- Lists repositories the token can access. GLOBAL. Returns large objects — paginate (`limit` ≤ 100) and read only the fields you need (name, full_name, owner.login). If this returns
|
|
24
|
+
401/403 there is no usable token — switch to the **gitea-configure** skill.
|
|
16
25
|
|
|
17
26
|
## Resolution order (every repo-scoped tool)
|
|
18
|
-
explicit `owner`/`repo` args → `GITEA_DEFAULT_OWNER`/`GITEA_DEFAULT_REPO`
|
|
27
|
+
explicit `owner`/`repo` args → `GITEA_DEFAULT_OWNER`/`GITEA_DEFAULT_REPO` (or git-discovered
|
|
28
|
+
defaults) → `resolve_repo`. If none resolve, the tool throws `owner and repo are required`.
|
|
29
|
+
Wrong values 404 or silently target the wrong repo — never guess.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gitea-summarize-issue
|
|
3
|
-
description: Invoke to READ and SUMMARIZE an issue's discussion — the issue body plus its comment thread. Do NOT invoke to create/edit an issue (gitea-create-issue / gitea-update-issue), post
|
|
3
|
+
description: Invoke to READ and SUMMARIZE an issue's discussion — the issue body plus its comment thread. Do NOT invoke to create/edit an issue (gitea-create-issue / gitea-update-issue), post a comment (gitea-comment-issue), or manage labels/milestones.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# gitea-summarize-issue
|
package/dist/cli.js
CHANGED
|
@@ -1,25 +1,31 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { runServer } from "./server.js";
|
|
3
|
+
import { discoverConfig } from "./git-config.js";
|
|
3
4
|
const argv = process.argv.slice(2);
|
|
4
|
-
if (argv[0] === "
|
|
5
|
-
// `gitea-mcp
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
if (argv[0] === "init") {
|
|
6
|
+
// `gitea-mcp init [--tool <name>]` installs the bundled skills into a target
|
|
7
|
+
// AI tool's skills directory. It needs no Gitea credentials, so it is
|
|
8
|
+
// dispatched before the config-discovery logic below.
|
|
9
|
+
const { runInitCommand } = await import("./skills.js");
|
|
10
|
+
runInitCommand(argv.slice(1)).catch((err) => {
|
|
9
11
|
console.error("Fatal error:", err);
|
|
10
12
|
process.exit(1);
|
|
11
13
|
});
|
|
12
14
|
}
|
|
13
15
|
else {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
console.error("
|
|
16
|
+
// Resolve baseUrl/owner/repo/token from env first, then the local git context
|
|
17
|
+
// (`.git/config` remotes + credential store). When neither env nor any git
|
|
18
|
+
// remote provides a baseUrl, the server is intentionally skipped: a single
|
|
19
|
+
// global install should stay dormant outside of git projects.
|
|
20
|
+
const discovered = await discoverConfig().catch((err) => {
|
|
21
|
+
console.error("Fatal error:", err);
|
|
20
22
|
process.exit(1);
|
|
23
|
+
});
|
|
24
|
+
if (!discovered) {
|
|
25
|
+
console.error(`gitea-mcp: no git remote found in ${process.cwd()} and GITEA_BASE_URL is not set; skipping server start.`);
|
|
26
|
+
process.exit(0);
|
|
21
27
|
}
|
|
22
|
-
runServer(baseUrl, token, defaultOwner, defaultRepo).catch((err) => {
|
|
28
|
+
runServer(discovered.baseUrl, discovered.token, discovered.defaultOwner, discovered.defaultRepo).catch((err) => {
|
|
23
29
|
console.error("Fatal error:", err);
|
|
24
30
|
process.exit(1);
|
|
25
31
|
});
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;IACvB,6EAA6E;IAC7E,sEAAsE;IACtE,sDAAsD;IACtD,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;IACvD,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;QACnD,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;QACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;KAAM,CAAC;IACN,8EAA8E;IAC9E,2EAA2E;IAC3E,2EAA2E;IAC3E,8DAA8D;IAC9D,MAAM,UAAU,GAAG,MAAM,cAAc,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;QAC/D,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;QACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CACX,qCAAqC,OAAO,CAAC,GAAG,EAAE,wDAAwD,CAC3G,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,SAAS,CACP,UAAU,CAAC,OAAO,EAClB,UAAU,CAAC,KAAK,EAChB,UAAU,CAAC,YAAY,EACvB,UAAU,CAAC,WAAW,CACvB,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;QACvB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;QACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
|