diff --git a/README.md b/README.md index 2a2ac9d..4a611d0 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,122 @@ -# Goose + Gitea Integration Guide +# Goose + Gitea MCP Extension -Complete guide for integrating the Goose AI agent with a self-hosted Gitea instance using the official Gitea MCP Server. +Integrate the [Goose](https://github.com/AAIF/goose) AI agent with your self-hosted [Gitea](https://gitea.com) instance via the official [gitea-mcp](https://gitea.com/gitea/gitea-mcp) MCP server. -## 📚 Wiki +**53 tools** covering repos, issues, PRs, branches, releases, CI/CD, wiki, and more — all controllable through natural language in Goose. -The full guide is in the [wiki](https://gt.covalente.dk/oval/goose-gitea-guide/wiki): +## What's in This Repo -- [Home](https://gt.covalente.dk/oval/goose-gitea-guide/wiki/Home) -- [Installation](https://gt.covalente.dk/oval/goose-gitea-guide/wiki/Installation) -- [Configuration](https://gt.covalente.dk/oval/goose-gitea-guide/wiki/Configuration) -- [SSH Setup](https://gt.covalente.dk/oval/goose-gitea-guide/wiki/SSH-Setup) -- [Usage](https://gt.covalente.dk/oval/goose-gitea-guide/wiki/Usage) -- [Troubleshooting](https://gt.covalente.dk/oval/goose-gitea-guide/wiki/Troubleshooting) +| File | Purpose | +|------|---------| +| `install.sh` | Cross-platform installer — downloads and installs the `gitea-mcp` binary | +| `goose-config.yaml` | The exact config entry to add to `~/.config/goose/config.yaml` | +| `README.md` | This file | +| [Wiki](https://gt.covalente.dk/oval/goose-gitea-guide/wiki) | Full documentation: setup, usage, troubleshooting | -## 🔜 Quick Start +## Quick Start ```bash -curl -sL "https://gitea.com/gitea/gitea-mcp/releases/download/v1.3.0/gitea-mcp_Darwin_arm64.tar.gz" -O gitea-mcp.tar.gz -tar xzf gitea-mcp.tar.gz -cp gitea-mcp /opt/homebrew/bin/gitea-mcp -chmod +x /opt/homebrew/bin/gitea-mcp -gitea-mcp -v # should output: 1.3.0 +# 1. Install the gitea-mcp binary +bash install.sh + +# 2. Get a Gitea access token +# → Your Gitea → Settings → Applications → Generate Token +# → Scopes: read:repository, write:repository, read:issue, write:issue + +# 3. Edit ~/.config/goose/config.yaml +# Copy the entry from goose-config.yaml into the `extensions:` section +# Replace YOUR_GITEA_INSTANCE and YOUR_ACCESS_TOKEN + +# 4. Restart Goose and start a BRAND NEW chat ``` -## 🩇 Links +## Architecture -- Goose: https://github.com/AAIF/goose -- Gitea MCP Server: https://gitea.com/gitea/gitea-mcp -- This Gitea instance: https://gt.covalente.dk \ No newline at end of file +``` +┌──────────┐ stdio MCP ┌──────────────┐ REST API ┌──────────┐ +│ Goose │ ◄────────────────► │ gitea-mcp │ ◄────────────────► │ Gitea │ +│ (agent) │ (stdin/stdout) │ (Go binary) │ (HTTPS, token) │ Server │ +└──────────┘ └──────────────┘ └──────────┘ +``` + +- Goose spawns `gitea-mcp` as a child process on demand (no background servers) +- `gitea-mcp` translates MCP tool calls into Gitea REST API calls +- SSH (port 222) is configured separately for `git clone/push/pull` + +## Available Tools (53) + +### Repositories & Files +`create_repo`, `fork_repo`, `list_my_repos`, `list_org_repos`, `search_repos`, `create_or_update_file`, `delete_file`, `get_file_contents`, `get_dir_contents`, `get_repository_tree` + +### Branches & Tags +`create_branch`, `delete_branch`, `list_branches`, `create_tag`, `delete_tag`, `list_tags`, `get_tag` + +### Commits & Releases +`list_commits`, `get_commit`, `create_release`, `delete_release`, `get_release`, `get_latest_release`, `list_releases` + +### Issues & Pull Requests +`issue_read`, `issue_write`, `list_issues`, `search_issues`, `pull_request_read`, `pull_request_write`, `pull_request_review_write`, `list_pull_requests` + +### Labels, Milestones, Actions, Wiki, Packages +`label_read`, `label_write`, `milestone_read`, `milestone_write`, `actions_config_read`, `actions_config_write`, `actions_run_read`, `actions_run_write`, `wiki_read`, `wiki_write`, `package_read`, `package_write` + +### Users & Notifications +`get_me`, `get_user_orgs`, `search_org_teams`, `search_users`, `notification_read`, `notification_write`, `timetracking_read`, `timetracking_write`, `get_gitea_mcp_server_version` + +## Configuration Reference + +```yaml +gitea: + enabled: true + type: stdio # Goose spawns the binary as a child process + name: Gitea + cmd: /usr/local/bin/gitea-mcp # Full path to the binary + args: + - -t + - stdio # MCP transport: stdio (not http) + - -H + - https://YOUR_GITEA # Your Gitea instance URL + - -T + - YOUR_TOKEN # Personal access token + envs: {} # Token in args, not env vars + timeout: 300 # 5-minute timeout for long operations + bundled: null # User-installed, not bundled + available_tools: [] # Empty = allow all 53 tools +``` + +### Why `/usr/local/bin/gitea-mcp`? + +Goose's `resolve_command` uses the Rust `which` crate which reliably resolves short command names (like `npx`, `uvx`) from PATH. For absolute paths, the fallback `PathBuf::from(cmd)` is used, which works correctly. Both short names (`gitea-mcp`) and absolute paths work — we recommend absolute paths for clarity. + +## SSH Setup (for git operations) + +The MCP handles API calls. For `git clone/push/pull`, add to `~/.ssh/config`: + +``` +Host YOUR_GITEA_HOST + Port 222 + User git + IdentityFile ~/.ssh/your_key +``` + +## Critical: Start a New Session + +After adding the extension to `config.yaml`, **you must start a brand new chat session** in Goose. Existing sessions cache their extension list and won't pick up newly added extensions. + +## Troubleshooting + +| Symptom | Fix | +|---------|-----| +| Gitea tools don't appear | Start a new chat session | +| "No such file or directory" | Check binary path: `ls -la /usr/local/bin/gitea-mcp` | +| "401 Unauthorized" | Verify token: `curl -H "Authorization: token TOKEN" https://GITEA/api/v1/user` | +| "Extension not valid" | New session needed — extension cached in old session | +| Config entry skipped silently | Check YAML indentation (2 spaces for gitea, 4 for fields) | + +See the [Troubleshooting wiki](https://gt.covalente.dk/oval/goose-gitea-guide/wiki/Troubleshooting) for detailed diagnostics. + +## Links + +- [Full Documentation (Wiki)](https://gt.covalente.dk/oval/goose-gitea-guide/wiki) +- [Goose](https://github.com/AAIF/goose) +- [gitea-mcp Server](https://gitea.com/gitea/gitea-mcp) diff --git a/goose-config.yaml b/goose-config.yaml new file mode 100644 index 0000000..b6c8d10 --- /dev/null +++ b/goose-config.yaml @@ -0,0 +1,25 @@ +# Gitea MCP Extension Configuration +# Copy this entry into the `extensions:` section of ~/.config/goose/config.yaml +# +# 🔴 REPLACE: +# - https://YOUR_GITEA_INSTANCE → your Gitea server URL +# - YOUR_ACCESS_TOKEN → your Gitea personal access token + + gitea: + enabled: true + type: stdio + name: Gitea + description: Manage Gitea repositories, issues, PRs, branches, releases, actions and more + cmd: /usr/local/bin/gitea-mcp + args: + - -t + - stdio + - -H + - https://YOUR_GITEA_INSTANCE + - -T + - YOUR_ACCESS_TOKEN + envs: {} + env_keys: [] + timeout: 300 + bundled: null + available_tools: [] diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..0ceb3bc --- /dev/null +++ b/install.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +# install.sh — Download and install gitea-mcp for Goose+Gitea integration +set -euo pipefail + +VERSION="${GITEA_MCP_VERSION:-1.3.0}" +BINDIR="${BINDIR:-/usr/local/bin}" + +detect_platform() { + local os arch + case "$(uname -s)" in + Darwin) os="Darwin" ;; + Linux) os="Linux" ;; + *) echo "Unsupported OS: $(uname -s)"; exit 1 ;; + esac + case "$(uname -m)" in + arm64|aarch64) arch="arm64" ;; + x86_64|amd64) arch="x86_64" ;; + *) echo "Unsupported arch: $(uname -m)"; exit 1 ;; + esac + echo "${os}_${arch}" +} + +PLATFORM=$(detect_platform) +TARBALL="gitea-mcp_${PLATFORM}.tar.gz" +URL="https://gitea.com/gitea/gitea-mcp/releases/download/v${VERSION}/${TARBALL}" + +echo "==> Platform: ${PLATFORM}" +echo "==> Downloading gitea-mcp v${VERSION}..." +curl -fsSL "$URL" -o "/tmp/${TARBALL}" + +echo "==> Extracting..." +tar -xzf "/tmp/${TARBALL}" -C /tmp/ + +echo "==> Installing to ${BINDIR}/gitea-mcp..." +sudo mkdir -p "$BINDIR" +sudo mv /tmp/gitea-mcp "${BINDIR}/gitea-mcp" +sudo chmod +x "${BINDIR}/gitea-mcp" + +rm -f "/tmp/${TARBALL}" + +echo "==> Done! Version: $(${BINDIR}/gitea-mcp -v)" +echo "" +echo "Next: Add the config entry from goose-config.yaml to ~/.config/goose/config.yaml" +echo " Then restart Goose and start a NEW chat session."