feat: add install script and rewrite README in Hebrew
One-liner install: curl | bash that builds from source, configures global MCP in ~/.claude/settings.json, handles duplicates, and supports interactive multi-server setup. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,287 +1,132 @@
|
||||
# Gitea MCP Server
|
||||
|
||||
[繁體中文](README.zh-tw.md) | [简体中文](README.zh-cn.md)
|
||||
שרת MCP (Model Context Protocol) לגיטאה — מאפשר ניהול מלא של ריפוזיטוריות, issues, pull requests, wikis, actions ועוד דרך Claude Code וכלי MCP אחרים.
|
||||
|
||||
**Gitea MCP Server** is an integration plugin designed to connect Gitea with Model Context Protocol (MCP) systems. This allows for seamless command execution and repository management through an MCP-compatible chat interface.
|
||||
**תומך בחיבור לכמה שרתי Gitea במקביל.**
|
||||
|
||||
[](https://insiders.vscode.dev/redirect/mcp/install?name=gitea&inputs=[{%22id%22:%22gitea_token%22,%22type%22:%22promptString%22,%22description%22:%22Gitea%20Personal%20Access%20Token%22,%22password%22:true}]&config={%22command%22:%22docker%22,%22args%22:[%22run%22,%22-i%22,%22--rm%22,%22-e%22,%22GITEA_ACCESS_TOKEN%22,%22docker.gitea.com/gitea-mcp-server%22],%22env%22:{%22GITEA_ACCESS_TOKEN%22:%22${input:gitea_token}%22}}) [](https://insiders.vscode.dev/redirect/mcp/install?name=gitea&inputs=[{%22id%22:%22gitea_token%22,%22type%22:%22promptString%22,%22description%22:%22Gitea%20Personal%20Access%20Token%22,%22password%22:true}]&config={%22command%22:%22docker%22,%22args%22:[%22run%22,%22-i%22,%22--rm%22,%22-e%22,%22GITEA_ACCESS_TOKEN%22,%22docker.gitea.com/gitea-mcp-server%22],%22env%22:{%22GITEA_ACCESS_TOKEN%22:%22${input:gitea_token}%22}}&quality=insiders)
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Gitea MCP Server](#gitea-mcp-server)
|
||||
- [Table of Contents](#table-of-contents)
|
||||
- [What is Gitea?](#what-is-gitea)
|
||||
- [What is MCP?](#what-is-mcp)
|
||||
- [🚧 Installation](#-installation)
|
||||
- [Usage with Claude Code](#usage-with-claude-code)
|
||||
- [Usage with VS Code](#usage-with-vs-code)
|
||||
- [📥 Download the official binary release](#-download-the-official-binary-release)
|
||||
- [🔧 Build from Source](#-build-from-source)
|
||||
- [📁 Add to PATH](#-add-to-path)
|
||||
- [🚀 Usage](#-usage)
|
||||
- [✅ Available Tools](#-available-tools)
|
||||
- [🐛 Debugging](#-debugging)
|
||||
- [🛠 Troubleshooting](#-troubleshooting)
|
||||
|
||||
## What is Gitea?
|
||||
|
||||
Gitea is a community-managed lightweight code hosting solution written in Go. It is published under the MIT license. Gitea provides Git hosting including a repository viewer, issue tracking, pull requests, and more.
|
||||
|
||||
## What is MCP?
|
||||
|
||||
Model Context Protocol (MCP) is a protocol that allows for the integration of various tools and systems through a chat interface. It enables seamless command execution and management of repositories, users, and other resources.
|
||||
|
||||
## 🚧 Installation
|
||||
|
||||
### Usage with Claude Code
|
||||
|
||||
This method uses `go run` and requires [Go](https://go.dev) to be installed.
|
||||
## התקנה מהירה
|
||||
|
||||
```bash
|
||||
claude mcp add --transport stdio --scope user gitea \
|
||||
--env GITEA_ACCESS_TOKEN=token \
|
||||
--env GITEA_HOST=https://gitea.com \
|
||||
-- go run gitea.com/gitea/gitea-mcp@latest -t stdio
|
||||
curl -fsSL https://gitea.dev.marcus-law.co.il/Chaim/gitea-mcp/raw/branch/main/install.sh | bash
|
||||
```
|
||||
|
||||
### Usage with VS Code
|
||||
הסקריפט:
|
||||
- משכפל את הריפו ל-`~/.gitea-mcp`
|
||||
- בונה בינארי ומתקין ל-`$GOPATH/bin`
|
||||
- מגדיר MCP server גלובלי ב-`~/.claude/settings.json`
|
||||
- מאפשר הוספת שרתים נוספים באופן אינטראקטיבי
|
||||
- מוחק הגדרות כפולות מקבצי `.mcp.json` ברמת פרויקט
|
||||
|
||||
For quick installation, use one of the one-click install buttons at the top of this README.
|
||||
### דרישות מוקדמות
|
||||
|
||||
For manual installation, add the following JSON block to your User Settings (JSON) file in VS Code. You can do this by pressing `Ctrl + Shift + P` and typing `Preferences: Open User Settings (JSON)`.
|
||||
- [Go](https://go.dev) 1.24+
|
||||
- git
|
||||
- jq
|
||||
|
||||
Optionally, you can add it to a file called `.vscode/mcp.json` in your workspace. This will allow you to share the configuration with others.
|
||||
### שדרוג
|
||||
|
||||
> Note that the `mcp` key is not needed in the `.vscode/mcp.json` file.
|
||||
|
||||
```json
|
||||
{
|
||||
"mcp": {
|
||||
"inputs": [
|
||||
{
|
||||
"type": "promptString",
|
||||
"id": "gitea_token",
|
||||
"description": "Gitea Personal Access Token",
|
||||
"password": true
|
||||
}
|
||||
],
|
||||
"servers": {
|
||||
"gitea-mcp": {
|
||||
"command": "docker",
|
||||
"args": [
|
||||
"run",
|
||||
"-i",
|
||||
"--rm",
|
||||
"-e",
|
||||
"GITEA_ACCESS_TOKEN",
|
||||
"docker.gitea.com/gitea-mcp-server"
|
||||
],
|
||||
"env": {
|
||||
"GITEA_ACCESS_TOKEN": "${input:gitea_token}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 📥 Download the official binary release
|
||||
|
||||
You can download the official release from [official Gitea MCP binary releases](https://gitea.com/gitea/gitea-mcp/releases).
|
||||
|
||||
### 🔧 Build from Source
|
||||
|
||||
You can download the source code by cloning the repository using Git:
|
||||
אותה פקודה בדיוק — הסקריפט מזהה התקנה קיימת ומעדכן:
|
||||
|
||||
```bash
|
||||
git clone https://gitea.com/gitea/gitea-mcp.git
|
||||
curl -fsSL https://gitea.dev.marcus-law.co.il/Chaim/gitea-mcp/raw/branch/main/install.sh | bash
|
||||
```
|
||||
|
||||
Before building, make sure you have the following installed:
|
||||
## הגדרה ידנית
|
||||
|
||||
- make
|
||||
- Golang (Go 1.24 or later recommended)
|
||||
|
||||
Then run:
|
||||
|
||||
```bash
|
||||
make install
|
||||
```
|
||||
|
||||
### 📁 Add to PATH
|
||||
|
||||
After installing, copy the binary gitea-mcp to a directory included in your system's PATH. For example:
|
||||
|
||||
```bash
|
||||
cp gitea-mcp /usr/local/bin/
|
||||
```
|
||||
|
||||
## 🚀 Usage
|
||||
|
||||
This example is for Cursor, you can also use plugins in VSCode.
|
||||
To configure the MCP server for Gitea, add the following to your MCP configuration file:
|
||||
|
||||
- **stdio mode**
|
||||
### שרת יחיד
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"gitea": {
|
||||
"gitea-dev": {
|
||||
"command": "gitea-mcp",
|
||||
"args": [
|
||||
"-t",
|
||||
"stdio",
|
||||
"--host",
|
||||
"https://gitea.com"
|
||||
// "--token", "<your personal access token>"
|
||||
],
|
||||
"args": ["-t", "stdio", "--host", "https://gitea.example.com"],
|
||||
"env": {
|
||||
// "GITEA_HOST": "https://gitea.com",
|
||||
// "GITEA_INSECURE": "true",
|
||||
"GITEA_ACCESS_TOKEN": "<your personal access token>"
|
||||
"GITEA_ACCESS_TOKEN": "<token>"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **http mode**
|
||||
### כמה שרתים
|
||||
|
||||
הוסף את `GITEA_SERVERS` כ-JSON object עם שם → `{host, token, insecure}`:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"gitea": {
|
||||
"url": "http://localhost:8080/mcp",
|
||||
"headers": {
|
||||
"Authorization": "Bearer <your personal access token>"
|
||||
"gitea-dev": {
|
||||
"command": "gitea-mcp",
|
||||
"args": ["-t", "stdio", "--host", "https://gitea.example.com"],
|
||||
"env": {
|
||||
"GITEA_ACCESS_TOKEN": "<default-token>",
|
||||
"GITEA_SERVERS": "{\"prod\":{\"host\":\"https://gitea.prod.example.com\",\"token\":\"<prod-token>\"},\"staging\":{\"host\":\"https://staging.example.com\",\"token\":\"<staging-token>\",\"insecure\":true}}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Default log path**: `$HOME/.gitea-mcp/gitea-mcp.log`
|
||||
כל כלי מקבל פרמטר `server` אופציונלי:
|
||||
|
||||
> [!NOTE]
|
||||
> You can provide your Gitea host and access token either as command-line arguments or environment variables.
|
||||
> Command-line arguments have the highest priority
|
||||
|
||||
> [!NOTE]
|
||||
> Many tools support `page` and `perPage` parameters for pagination. The maximum effective page size is determined by the Gitea server's `[api].MAX_RESPONSE_ITEMS` setting (default: **50**). Requesting a `perPage` value higher than this limit will be silently capped by the server.
|
||||
|
||||
Once everything is set up, try typing the following in your MCP-compatible chatbox:
|
||||
|
||||
```text
|
||||
list all my repositories
|
||||
```
|
||||
list_my_repos # ברירת מחדל
|
||||
list_my_repos(server: "prod") # שרת ספציפי
|
||||
list_servers # הצג שרתים מוגדרים
|
||||
```
|
||||
|
||||
## ✅ Available Tools
|
||||
## משתני סביבה
|
||||
|
||||
The Gitea MCP Server supports the following tools:
|
||||
| משתנה | תיאור |
|
||||
|---|---|
|
||||
| `GITEA_ACCESS_TOKEN` | טוקן גישה לשרת ברירת המחדל |
|
||||
| `GITEA_HOST` | כתובת שרת ברירת המחדל |
|
||||
| `GITEA_SERVERS` | JSON object של שרתים נוספים |
|
||||
| `GITEA_READONLY` | `true` להצגת כלי קריאה בלבד |
|
||||
| `GITEA_DEBUG` | `true` למצב debug |
|
||||
| `GITEA_INSECURE` | `true` לדלג על בדיקת TLS |
|
||||
| `MCP_MODE` | `stdio` (ברירת מחדל) או `http` |
|
||||
|
||||
| Tool | Scope | Description |
|
||||
| :-------------------------------: | :----------: | :------------------------------------------------------: |
|
||||
| get_my_user_info | User | Get the information of the authenticated user |
|
||||
| get_user_orgs | User | Get organizations associated with the authenticated user |
|
||||
| create_repo | Repository | Create a new repository |
|
||||
| fork_repo | Repository | Fork a repository |
|
||||
| list_my_repos | Repository | List all repositories owned by the authenticated user |
|
||||
| create_branch | Branch | Create a new branch |
|
||||
| delete_branch | Branch | Delete a branch |
|
||||
| list_branches | Branch | List all branches in a repository |
|
||||
| create_release | Release | Create a new release in a repository |
|
||||
| delete_release | Release | Delete a release from a repository |
|
||||
| get_release | Release | Get a release |
|
||||
| get_latest_release | Release | Get the latest release in a repository |
|
||||
| list_releases | Release | List all releases in a repository |
|
||||
| create_tag | Tag | Create a new tag |
|
||||
| delete_tag | Tag | Delete a tag |
|
||||
| get_tag | Tag | Get a tag |
|
||||
| list_tags | Tag | List all tags 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_dir_content | File | Get a list of entries in a directory |
|
||||
| create_file | File | Create a new file |
|
||||
| update_file | File | Update an existing file |
|
||||
| delete_file | File | Delete a file |
|
||||
| get_issue_by_index | Issue | Get an issue by its index |
|
||||
| list_repo_issues | Issue | List all issues in a repository |
|
||||
| create_issue | Issue | Create a new issue |
|
||||
| create_issue_comment | Issue | Create a comment on an 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_diff | Pull Request | Get a pull request diff |
|
||||
| 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_reviewer | Pull Request | Add reviewers to a pull request |
|
||||
| delete_pull_request_reviewer | Pull Request | Remove reviewers from a pull request |
|
||||
| list_pull_request_reviews | Pull Request | List all reviews for a pull request |
|
||||
| get_pull_request_review | Pull Request | Get a specific review by ID |
|
||||
| list_pull_request_review_comments | Pull Request | List inline comments for a review |
|
||||
| create_pull_request_review | Pull Request | Create a review with optional inline comments |
|
||||
| submit_pull_request_review | Pull Request | Submit a pending review |
|
||||
| delete_pull_request_review | Pull Request | Delete a review |
|
||||
| dismiss_pull_request_review | Pull Request | Dismiss a review with optional message |
|
||||
| merge_pull_request | Pull Request | Merge a pull request |
|
||||
| search_users | User | Search for users |
|
||||
| search_org_teams | Organization | Search for teams in an organization |
|
||||
| list_org_labels | Organization | List labels defined at organization level |
|
||||
| create_org_label | Organization | Create a label in an organization |
|
||||
| edit_org_label | Organization | Edit a label in an organization |
|
||||
| delete_org_label | Organization | Delete a label in an organization |
|
||||
| search_repos | Repository | Search for repositories |
|
||||
| list_repo_action_secrets | Actions | List repository Actions secrets (metadata only) |
|
||||
| upsert_repo_action_secret | Actions | Create/update (upsert) a repository Actions secret |
|
||||
| delete_repo_action_secret | Actions | Delete a repository Actions secret |
|
||||
| list_org_action_secrets | Actions | List organization Actions secrets (metadata only) |
|
||||
| upsert_org_action_secret | Actions | Create/update (upsert) an organization Actions secret |
|
||||
| delete_org_action_secret | Actions | Delete an organization Actions secret |
|
||||
| list_repo_action_variables | Actions | List repository Actions variables |
|
||||
| get_repo_action_variable | Actions | Get a repository Actions variable |
|
||||
| create_repo_action_variable | Actions | Create a repository Actions variable |
|
||||
| update_repo_action_variable | Actions | Update a repository Actions variable |
|
||||
| delete_repo_action_variable | Actions | Delete a repository Actions variable |
|
||||
| list_org_action_variables | Actions | List organization Actions variables |
|
||||
| get_org_action_variable | Actions | Get an organization Actions variable |
|
||||
| create_org_action_variable | Actions | Create an organization Actions variable |
|
||||
| update_org_action_variable | Actions | Update an organization Actions variable |
|
||||
| delete_org_action_variable | Actions | Delete an organization Actions variable |
|
||||
| list_repo_action_workflows | Actions | List repository Actions workflows |
|
||||
| get_repo_action_workflow | Actions | Get a repository Actions workflow |
|
||||
| dispatch_repo_action_workflow | Actions | Trigger (dispatch) a repository Actions workflow |
|
||||
| list_repo_action_runs | Actions | List repository Actions runs |
|
||||
| get_repo_action_run | Actions | Get a repository Actions run |
|
||||
| cancel_repo_action_run | Actions | Cancel a repository Actions run |
|
||||
| rerun_repo_action_run | Actions | Rerun a repository Actions run |
|
||||
| list_repo_action_jobs | Actions | List repository Actions jobs |
|
||||
| list_repo_action_run_jobs | Actions | List Actions jobs for a run |
|
||||
| get_repo_action_job_log_preview | Actions | Get a job log preview (tail/limited) |
|
||||
| download_repo_action_job_log | Actions | Download a job log to a file |
|
||||
| get_gitea_mcp_server_version | Server | Get the version of the Gitea MCP Server |
|
||||
| list_wiki_pages | Wiki | List all wiki pages in a repository |
|
||||
| get_wiki_page | Wiki | Get a wiki page content and metadata |
|
||||
| get_wiki_revisions | Wiki | Get revisions history of a wiki page |
|
||||
| create_wiki_page | Wiki | Create a new wiki page |
|
||||
| update_wiki_page | Wiki | Update an existing wiki page |
|
||||
| delete_wiki_page | Wiki | Delete a wiki page |
|
||||
## כלים זמינים
|
||||
|
||||
## 🐛 Debugging
|
||||
השרת מספק 60+ כלי MCP:
|
||||
|
||||
To enable debug mode, add the `-d` flag when running the Gitea MCP Server with http mode:
|
||||
| תחום | כלים |
|
||||
|---|---|
|
||||
| משתמש | `get_me`, `get_user_orgs` |
|
||||
| ריפוזיטוריות | `create_repo`, `fork_repo`, `list_my_repos`, `list_org_repos`, `get_repo`, `repo_write`, `list_forks` |
|
||||
| ענפים | `list_branches`, `create_branch`, `delete_branch`, `branch_protection_read/write` |
|
||||
| תגיות | `list_tags`, `get_tag`, `create_tag`, `delete_tag` |
|
||||
| קבצים | `get_file_contents`, `get_dir_contents`, `create_or_update_file`, `delete_file`, `get_repository_tree` |
|
||||
| קומיטים | `list_commits`, `get_commit`, `get_compare` |
|
||||
| Issues | `list_issues`, `issue_read`, `issue_write`, `search_issues` |
|
||||
| Pull Requests | `list_pull_requests`, `pull_request_read`, `pull_request_write`, `pull_request_review_write` |
|
||||
| Labels | `label_read`, `label_write` |
|
||||
| Milestones | `milestone_read`, `milestone_write` |
|
||||
| Releases | `list_releases`, `get_release`, `get_latest_release`, `create_release`, `delete_release` |
|
||||
| Wiki | `wiki_read`, `wiki_write` |
|
||||
| מעקב זמן | `timetracking_read`, `timetracking_write` |
|
||||
| Actions | `actions_run_read`, `actions_run_write`, `actions_config_read`, `actions_config_write` |
|
||||
| התראות | `notification_read`, `notification_write` |
|
||||
| ארגונים | `org_read`, `org_write` |
|
||||
| Webhooks | `webhook_read`, `webhook_write` |
|
||||
| Collaborators | `collaborator_read`, `collaborator_write` |
|
||||
| Deploy Keys | `deploy_key_read`, `deploy_key_write` |
|
||||
| Topics | `topic_read`, `topic_write` |
|
||||
| חיפוש | `search_users`, `search_repos`, `search_org_teams` |
|
||||
| שרת | `get_gitea_mcp_server_version`, `list_servers` |
|
||||
|
||||
```sh
|
||||
./gitea-mcp -t http [--port 8080] --token <your personal access token> -d
|
||||
## פיתוח
|
||||
|
||||
```bash
|
||||
make build # בנייה
|
||||
make install # בנייה + התקנה ל-GOPATH/bin
|
||||
make dev # hot reload (דורש air)
|
||||
make clean # ניקוי
|
||||
go test ./... # טסטים
|
||||
```
|
||||
|
||||
## 🛠 Troubleshooting
|
||||
## רישיון
|
||||
|
||||
If you encounter any issues, here are some common troubleshooting steps:
|
||||
|
||||
1. **Check your PATH**: Ensure that the `gitea-mcp` binary is in a directory included in your system's PATH.
|
||||
2. **Verify dependencies**: Make sure you have all the required dependencies installed, such as `make` and `Golang`.
|
||||
3. **Review configuration**: Double-check your MCP configuration file for any errors or missing information.
|
||||
4. **Consult logs**: Check the logs for any error messages or warnings that can provide more information about the issue.
|
||||
|
||||
Enjoy exploring and managing your Gitea repositories via chat!
|
||||
MIT
|
||||
|
||||
Executable
+376
@@ -0,0 +1,376 @@
|
||||
#!/bin/bash
|
||||
# install.sh - Install/upgrade gitea-mcp and configure global MCP server
|
||||
#
|
||||
# Usage:
|
||||
# curl -fsSL https://gitea.dev.marcus-law.co.il/Chaim/gitea-mcp/raw/branch/main/install.sh | bash
|
||||
# # or locally:
|
||||
# bash install.sh
|
||||
#
|
||||
# Options (via env vars):
|
||||
# GITEA_MCP_DIR=~/custom-dir # Custom install directory (default: ~/.gitea-mcp)
|
||||
# GITEA_MCP_BRANCH=dev # Custom branch (default: main)
|
||||
# GITEA_DEFAULT_HOST=https://... # Default Gitea host
|
||||
# GITEA_DEFAULT_TOKEN=xxx # Default Gitea token
|
||||
# AUTO_YES=1 # Skip all prompts
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
REPO_URL="https://gitea.dev.marcus-law.co.il/Chaim/gitea-mcp.git"
|
||||
INSTALL_DIR="${GITEA_MCP_DIR:-$HOME/.gitea-mcp}"
|
||||
BRANCH="${GITEA_MCP_BRANCH:-main}"
|
||||
AUTO_YES="${AUTO_YES:-0}"
|
||||
|
||||
MCP_NAME="gitea-dev"
|
||||
BINARY_NAME="gitea-mcp"
|
||||
GOBIN="${GOPATH:-$HOME/go}/bin"
|
||||
BINARY_PATH="$GOBIN/$BINARY_NAME"
|
||||
|
||||
CLAUDE_JSON="$HOME/.claude.json"
|
||||
CLAUDE_SETTINGS="$HOME/.claude/settings.json"
|
||||
|
||||
# ── Helpers ─────────────────────────────────────────────────────────────────
|
||||
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m'
|
||||
info() { echo -e "${CYAN}>>>${NC} $*"; }
|
||||
ok() { echo -e "${GREEN} ✓${NC} $*"; }
|
||||
warn() { echo -e "${YELLOW} !${NC} $*"; }
|
||||
error() { echo -e "${RED} ✗${NC} $*" >&2; }
|
||||
|
||||
ask_yes_no() {
|
||||
local prompt="$1"
|
||||
if [ "$AUTO_YES" = "1" ]; then return 0; fi
|
||||
if [ -e /dev/tty ]; then
|
||||
printf "%s [Y/n] " "$prompt"
|
||||
local answer=""
|
||||
read -r answer < /dev/tty 2>/dev/null || answer="y"
|
||||
case "$answer" in [nN]*) return 1 ;; *) return 0 ;; esac
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
ask_input() {
|
||||
local prompt="$1" var_name="$2" default="${3:-}"
|
||||
if [ -e /dev/tty ]; then
|
||||
if [ -n "$default" ]; then
|
||||
printf "%s [%s]: " "$prompt" "$default"
|
||||
else
|
||||
printf "%s: " "$prompt"
|
||||
fi
|
||||
local answer=""
|
||||
read -r answer < /dev/tty 2>/dev/null || answer=""
|
||||
if [ -z "$answer" ]; then answer="$default"; fi
|
||||
eval "$var_name=\$answer"
|
||||
else
|
||||
eval "$var_name=\$default"
|
||||
fi
|
||||
}
|
||||
|
||||
# ── Step 0: Prerequisites ──────────────────────────────────────────────────
|
||||
|
||||
echo ""
|
||||
echo -e "${CYAN}=== Gitea MCP Server Installer ===${NC}"
|
||||
echo ""
|
||||
|
||||
info "Checking prerequisites..."
|
||||
|
||||
if ! command -v go &>/dev/null; then
|
||||
error "Go is required but not found. Install from https://go.dev/dl/"
|
||||
exit 1
|
||||
fi
|
||||
GO_VERSION=$(go version | grep -oP 'go\d+\.\d+')
|
||||
ok "go ($GO_VERSION)"
|
||||
|
||||
if ! command -v git &>/dev/null; then
|
||||
error "git is required but not found"
|
||||
exit 1
|
||||
fi
|
||||
ok "git ($(git --version | cut -d' ' -f3))"
|
||||
|
||||
if ! command -v jq &>/dev/null; then
|
||||
error "jq is required but not found. Install: sudo apt install jq"
|
||||
exit 1
|
||||
fi
|
||||
ok "jq ($(jq --version 2>/dev/null))"
|
||||
|
||||
# ── Step 1: Clone or update ────────────────────────────────────────────────
|
||||
|
||||
echo ""
|
||||
if [ -d "$INSTALL_DIR/.git" ]; then
|
||||
info "Updating existing installation in $INSTALL_DIR ..."
|
||||
cd "$INSTALL_DIR"
|
||||
git fetch origin 2>&1 | tail -2
|
||||
git reset --hard "origin/$BRANCH" 2>&1 | tail -1
|
||||
ok "Updated to latest $BRANCH"
|
||||
elif [ -d "$INSTALL_DIR" ]; then
|
||||
# Directory exists but is not a git repo — remove and re-clone
|
||||
warn "$INSTALL_DIR exists but is not a git repo, re-cloning..."
|
||||
rm -rf "$INSTALL_DIR"
|
||||
git clone --branch "$BRANCH" --single-branch "$REPO_URL" "$INSTALL_DIR" 2>&1 | tail -2
|
||||
cd "$INSTALL_DIR"
|
||||
ok "Cloned"
|
||||
else
|
||||
info "Cloning to $INSTALL_DIR ..."
|
||||
git clone --branch "$BRANCH" --single-branch "$REPO_URL" "$INSTALL_DIR" 2>&1 | tail -2
|
||||
cd "$INSTALL_DIR"
|
||||
ok "Cloned"
|
||||
fi
|
||||
|
||||
# ── Step 2: Build ──────────────────────────────────────────────────────────
|
||||
|
||||
echo ""
|
||||
info "Building $BINARY_NAME ..."
|
||||
mkdir -p "$GOBIN"
|
||||
go build -o "$BINARY_PATH" . 2>&1
|
||||
VERSION=$("$BINARY_PATH" --version 2>/dev/null || echo "unknown")
|
||||
ok "Built $BINARY_PATH ($VERSION)"
|
||||
|
||||
# ── Step 3: Find existing MCP config ───────────────────────────────────────
|
||||
|
||||
echo ""
|
||||
info "Checking existing MCP configuration..."
|
||||
|
||||
# Determine where the MCP entry currently lives
|
||||
MCP_CONFIG_FILE=""
|
||||
EXISTING_ENTRY=""
|
||||
|
||||
# Check global settings.json first (preferred location)
|
||||
if [ -f "$CLAUDE_SETTINGS" ]; then
|
||||
EXISTING_ENTRY=$(jq -r --arg name "$MCP_NAME" '.mcpServers[$name] // empty' "$CLAUDE_SETTINGS" 2>/dev/null || true)
|
||||
if [ -n "$EXISTING_ENTRY" ]; then
|
||||
MCP_CONFIG_FILE="$CLAUDE_SETTINGS"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check ~/.claude.json
|
||||
if [ -z "$EXISTING_ENTRY" ] && [ -f "$CLAUDE_JSON" ]; then
|
||||
EXISTING_ENTRY=$(jq -r --arg name "$MCP_NAME" '.mcpServers[$name] // empty' "$CLAUDE_JSON" 2>/dev/null || true)
|
||||
if [ -n "$EXISTING_ENTRY" ]; then
|
||||
MCP_CONFIG_FILE="$CLAUDE_JSON"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check for project-level .mcp.json files
|
||||
FOUND_PROJECT_MCP=()
|
||||
while IFS= read -r -d '' mcp_file; do
|
||||
if jq -e --arg name "$MCP_NAME" '.mcpServers[$name] != null' "$mcp_file" &>/dev/null; then
|
||||
FOUND_PROJECT_MCP+=("$mcp_file")
|
||||
fi
|
||||
done < <(find "$HOME" -maxdepth 3 -name ".mcp.json" \
|
||||
-not -path "*/.claude/*" \
|
||||
-not -path "*/.gitea-mcp/*" \
|
||||
-not -path "*/node_modules/*" \
|
||||
-print0 2>/dev/null || true)
|
||||
|
||||
# ── Step 4: Migrate / deduplicate ──────────────────────────────────────────
|
||||
|
||||
# If found in project-level files, migrate to global
|
||||
if [ ${#FOUND_PROJECT_MCP[@]} -gt 0 ]; then
|
||||
for mcp_file in "${FOUND_PROJECT_MCP[@]}"; do
|
||||
warn "Found '$MCP_NAME' in project-level config: $mcp_file"
|
||||
|
||||
if [ -z "$EXISTING_ENTRY" ]; then
|
||||
# No global config yet - migrate from project file
|
||||
if ask_yes_no " Migrate to global config ($CLAUDE_SETTINGS)?"; then
|
||||
EXISTING_ENTRY=$(jq --arg name "$MCP_NAME" '.mcpServers[$name]' "$mcp_file")
|
||||
MCP_CONFIG_FILE="$CLAUDE_SETTINGS"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Remove from project-level regardless
|
||||
if ask_yes_no " Remove duplicate from $mcp_file?"; then
|
||||
tmp=$(jq --arg name "$MCP_NAME" 'del(.mcpServers[$name])' "$mcp_file")
|
||||
echo "$tmp" > "$mcp_file"
|
||||
ok "Removed from $mcp_file"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# ── Step 5: Configure default server ───────────────────────────────────────
|
||||
|
||||
echo ""
|
||||
|
||||
# Extract existing values if we have a config
|
||||
CURRENT_HOST=""
|
||||
CURRENT_TOKEN=""
|
||||
CURRENT_SERVERS=""
|
||||
|
||||
if [ -n "$EXISTING_ENTRY" ]; then
|
||||
CURRENT_HOST=$(echo "$EXISTING_ENTRY" | jq -r '
|
||||
(.args // []) | to_entries |
|
||||
map(select(.value == "--host")) | first |
|
||||
if . then (.key + 1) as $k | input | .[$k] else empty end
|
||||
' 2>/dev/null || true)
|
||||
# Simpler extraction
|
||||
CURRENT_HOST=$(echo "$EXISTING_ENTRY" | jq -r '
|
||||
.args as $a | ($a | index("--host")) as $i |
|
||||
if $i then $a[$i + 1] else "" end
|
||||
' 2>/dev/null || true)
|
||||
CURRENT_TOKEN=$(echo "$EXISTING_ENTRY" | jq -r '.env.GITEA_ACCESS_TOKEN // ""' 2>/dev/null || true)
|
||||
CURRENT_SERVERS=$(echo "$EXISTING_ENTRY" | jq -r '.env.GITEA_SERVERS // ""' 2>/dev/null || true)
|
||||
|
||||
ok "Existing config found"
|
||||
echo " Default: ${CURRENT_HOST:-not set}"
|
||||
if [ -n "$CURRENT_SERVERS" ] && [ "$CURRENT_SERVERS" != "" ]; then
|
||||
echo "$CURRENT_SERVERS" | jq -r 'to_entries[] | " \(.key): \(.value.host)"' 2>/dev/null || true
|
||||
fi
|
||||
fi
|
||||
|
||||
# Determine default host and token (env vars > existing > prompt)
|
||||
DEFAULT_HOST="${GITEA_DEFAULT_HOST:-$CURRENT_HOST}"
|
||||
DEFAULT_TOKEN="${GITEA_DEFAULT_TOKEN:-$CURRENT_TOKEN}"
|
||||
|
||||
if [ -z "$DEFAULT_HOST" ]; then
|
||||
info "No default Gitea server configured."
|
||||
ask_input " Default Gitea host URL" DEFAULT_HOST "https://gitea.com"
|
||||
ask_input " Access token" DEFAULT_TOKEN ""
|
||||
fi
|
||||
|
||||
if [ -z "$DEFAULT_TOKEN" ]; then
|
||||
warn "No access token for $DEFAULT_HOST"
|
||||
ask_input " Access token" DEFAULT_TOKEN ""
|
||||
fi
|
||||
|
||||
# ── Step 6: Add additional servers ─────────────────────────────────────────
|
||||
|
||||
SERVERS_JSON="${CURRENT_SERVERS:-}"
|
||||
|
||||
while true; do
|
||||
echo ""
|
||||
if ! ask_yes_no "Add an additional Gitea server?"; then
|
||||
break
|
||||
fi
|
||||
|
||||
srv_name="" srv_host="" srv_token="" srv_insecure="false"
|
||||
ask_input " Server name (e.g. prod, staging)" srv_name ""
|
||||
if [ -z "$srv_name" ]; then break; fi
|
||||
|
||||
# Check if already exists
|
||||
if [ -n "$SERVERS_JSON" ] && echo "$SERVERS_JSON" | jq -e --arg n "$srv_name" '.[$n]' &>/dev/null; then
|
||||
existing_host=$(echo "$SERVERS_JSON" | jq -r --arg n "$srv_name" '.[$n].host')
|
||||
warn "Server '$srv_name' already configured: $existing_host"
|
||||
if ! ask_yes_no " Overwrite?"; then continue; fi
|
||||
fi
|
||||
|
||||
ask_input " Host URL" srv_host ""
|
||||
ask_input " Access token" srv_token ""
|
||||
ask_input " Skip TLS verification? (y/n)" srv_insecure "n"
|
||||
[[ "$srv_insecure" =~ ^[Yy] ]] && srv_insecure="true" || srv_insecure="false"
|
||||
|
||||
if [ -z "$SERVERS_JSON" ] || [ "$SERVERS_JSON" = "" ]; then
|
||||
SERVERS_JSON="{}"
|
||||
fi
|
||||
SERVERS_JSON=$(echo "$SERVERS_JSON" | jq \
|
||||
--arg n "$srv_name" --arg h "$srv_host" --arg t "$srv_token" --argjson i "$srv_insecure" \
|
||||
'.[$n] = {host: $h, token: $t, insecure: $i}')
|
||||
|
||||
ok "Added server '$srv_name': $srv_host"
|
||||
done
|
||||
|
||||
# ── Step 7: Write global MCP config ───────────────────────────────────────
|
||||
|
||||
echo ""
|
||||
info "Writing global MCP configuration..."
|
||||
|
||||
# Build the MCP entry
|
||||
if [ -n "$SERVERS_JSON" ] && [ "$SERVERS_JSON" != "{}" ] && [ "$SERVERS_JSON" != "" ]; then
|
||||
MCP_ENTRY=$(jq -n \
|
||||
--arg cmd "$BINARY_PATH" \
|
||||
--arg host "$DEFAULT_HOST" \
|
||||
--arg token "$DEFAULT_TOKEN" \
|
||||
--arg servers "$SERVERS_JSON" \
|
||||
'{
|
||||
command: $cmd,
|
||||
args: ["-t", "stdio", "--host", $host],
|
||||
env: {
|
||||
GITEA_ACCESS_TOKEN: $token,
|
||||
GITEA_SERVERS: $servers
|
||||
}
|
||||
}')
|
||||
else
|
||||
MCP_ENTRY=$(jq -n \
|
||||
--arg cmd "$BINARY_PATH" \
|
||||
--arg host "$DEFAULT_HOST" \
|
||||
--arg token "$DEFAULT_TOKEN" \
|
||||
'{
|
||||
command: $cmd,
|
||||
args: ["-t", "stdio", "--host", $host],
|
||||
env: {
|
||||
GITEA_ACCESS_TOKEN: $token
|
||||
}
|
||||
}')
|
||||
fi
|
||||
|
||||
# Write to settings.json (global/user level)
|
||||
mkdir -p "$(dirname "$CLAUDE_SETTINGS")"
|
||||
if [ ! -f "$CLAUDE_SETTINGS" ]; then
|
||||
echo '{}' > "$CLAUDE_SETTINGS"
|
||||
fi
|
||||
|
||||
tmp=$(jq --arg name "$MCP_NAME" --argjson entry "$MCP_ENTRY" \
|
||||
'.mcpServers[$name] = $entry' "$CLAUDE_SETTINGS")
|
||||
echo "$tmp" > "$CLAUDE_SETTINGS"
|
||||
ok "Written to $CLAUDE_SETTINGS"
|
||||
|
||||
# Also register via claude CLI if available (belt and suspenders)
|
||||
if command -v claude &>/dev/null; then
|
||||
# Check if claude mcp already has this entry to avoid duplicates
|
||||
if claude mcp list 2>/dev/null | grep -q "$MCP_NAME"; then
|
||||
claude mcp remove "$MCP_NAME" --scope user 2>/dev/null || true
|
||||
fi
|
||||
fi
|
||||
|
||||
# ── Step 8: Clean up duplicates in other config files ──────────────────────
|
||||
|
||||
echo ""
|
||||
info "Checking for duplicate configs..."
|
||||
|
||||
# Clean from project-level .mcp.json files
|
||||
while IFS= read -r -d '' mcp_file; do
|
||||
if jq -e --arg name "$MCP_NAME" '.mcpServers[$name] != null' "$mcp_file" &>/dev/null; then
|
||||
warn "Duplicate found in $mcp_file"
|
||||
if ask_yes_no " Remove '$MCP_NAME' from $mcp_file?"; then
|
||||
tmp=$(jq --arg name "$MCP_NAME" 'del(.mcpServers[$name])' "$mcp_file")
|
||||
echo "$tmp" > "$mcp_file"
|
||||
ok "Removed"
|
||||
fi
|
||||
fi
|
||||
done < <(find "$HOME" -maxdepth 3 -name ".mcp.json" \
|
||||
-not -path "*/.claude/*" \
|
||||
-not -path "*/.gitea-mcp/*" \
|
||||
-not -path "*/node_modules/*" \
|
||||
-print0 2>/dev/null || true)
|
||||
|
||||
# Clean from ~/.claude.json if we wrote to settings.json
|
||||
if [ -f "$CLAUDE_JSON" ]; then
|
||||
if jq -e --arg name "$MCP_NAME" '.mcpServers[$name] != null' "$CLAUDE_JSON" &>/dev/null; then
|
||||
warn "Duplicate found in $CLAUDE_JSON"
|
||||
if ask_yes_no " Remove from $CLAUDE_JSON? (already in settings.json)"; then
|
||||
tmp=$(jq --arg name "$MCP_NAME" 'del(.mcpServers[$name])' "$CLAUDE_JSON")
|
||||
echo "$tmp" > "$CLAUDE_JSON"
|
||||
ok "Removed"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# ── Done ───────────────────────────────────────────────────────────────────
|
||||
|
||||
echo ""
|
||||
echo -e "${CYAN}=== Configured Servers ===${NC}"
|
||||
echo " default: $DEFAULT_HOST"
|
||||
if [ -n "$SERVERS_JSON" ] && [ "$SERVERS_JSON" != "{}" ] && [ "$SERVERS_JSON" != "" ]; then
|
||||
echo "$SERVERS_JSON" | jq -r 'to_entries[] | " \(.key): \(.value.host)\(if .value.insecure then " (insecure)" else "" end)"'
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}=== Installation complete! ===${NC}"
|
||||
echo ""
|
||||
echo " Binary: $BINARY_PATH ($VERSION)"
|
||||
echo " Config: $CLAUDE_SETTINGS"
|
||||
echo " Source: $INSTALL_DIR"
|
||||
echo ""
|
||||
echo "Restart Claude Code to load the new MCP server."
|
||||
echo ""
|
||||
echo "To upgrade later:"
|
||||
echo " curl -fsSL https://gitea.dev.marcus-law.co.il/Chaim/gitea-mcp/raw/branch/main/install.sh | bash"
|
||||
echo ""
|
||||
Reference in New Issue
Block a user