docs: retarget setup to Claude connectors
test / test (push) Has been cancelled
lint / lint (push) Has been cancelled
docker / test (pull_request) Successful in 13s
docker / lint (pull_request) Successful in 2m3s
lint / lint (pull_request) Successful in 16s
test / test (pull_request) Successful in 14s
docker / docker-test (pull_request) Successful in 42s
docker / docker-publish (pull_request) Has been skipped
test / test (push) Has been cancelled
lint / lint (push) Has been cancelled
docker / test (pull_request) Successful in 13s
docker / lint (pull_request) Successful in 2m3s
lint / lint (pull_request) Successful in 16s
test / test (pull_request) Successful in 14s
docker / docker-test (pull_request) Successful in 42s
docker / docker-publish (pull_request) Has been skipped
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
# AegisGitea-MCP
|
||||
|
||||
Security-first MCP server for self-hosted Gitea with per-user OAuth2/OIDC authentication.
|
||||
Security-first MCP server for self-hosted Gitea with per-user OAuth2/OIDC authentication for Claude, Claude Code, and Cowork.
|
||||
|
||||
AegisGitea-MCP exposes MCP tools over HTTP/SSE and validates each user token against Gitea so tool access follows each user's actual repository permissions.
|
||||
AegisGitea-MCP exposes MCP tools over Streamable HTTP and a legacy SSE alias. Each user authenticates with Gitea through OAuth2/OIDC; repository authorization is checked per user before any service PAT call is allowed.
|
||||
|
||||
## Securing MCP with Gitea OAuth
|
||||
|
||||
@@ -10,7 +10,7 @@ AegisGitea-MCP exposes MCP tools over HTTP/SSE and validates each user token aga
|
||||
|
||||
1. Open `https://git.hiddenden.cafe/user/settings/applications` (or admin application settings).
|
||||
2. Create an OAuth2 app.
|
||||
3. Set redirect URI to the ChatGPT callback URL shown after creating a New App.
|
||||
3. Set the redirect URI to this MCP server's callback: `https://<your-mcp-domain>/oauth/callback`.
|
||||
4. Save the app and keep:
|
||||
- `Client ID`
|
||||
- `Client Secret`
|
||||
@@ -32,19 +32,39 @@ GITEA_URL=https://git.hiddenden.cafe
|
||||
OAUTH_MODE=true
|
||||
GITEA_OAUTH_CLIENT_ID=<your-client-id>
|
||||
GITEA_OAUTH_CLIENT_SECRET=<your-client-secret>
|
||||
OAUTH_EXPECTED_AUDIENCE=<optional; defaults to client id>
|
||||
PUBLIC_BASE_URL=https://<your-mcp-domain>
|
||||
OAUTH_STATE_SECRET=<random-32-byte-minimum-secret>
|
||||
```
|
||||
|
||||
### 3) Configure ChatGPT New App
|
||||
`GITEA_TOKEN` is optional in OAuth mode. Without it, Gitea REST calls use the user's OAuth access token directly, so Gitea enforces permissions on every API call. With it, the token acts as a service PAT for API execution, but the MCP server first checks the requesting user's permission on the target repository through Gitea and denies the call if the user lacks the required read/write permission.
|
||||
|
||||
In ChatGPT New App:
|
||||
### 3) Configure Claude, Claude Code, or Cowork
|
||||
|
||||
- MCP server URL: `https://<your-mcp-domain>/mcp/sse`
|
||||
Claude's hosted, desktop, mobile, Claude Code, and Cowork surfaces share the same remote MCP connector infrastructure. There is no Claude-specific server code path.
|
||||
|
||||
In claude.ai:
|
||||
|
||||
1. Open **Settings > Connectors**.
|
||||
2. Choose **Add custom connector**.
|
||||
3. Paste `https://<your-mcp-domain>/mcp`.
|
||||
4. Complete the OAuth consent flow. Dynamic Client Registration (`/register`) handles Claude client registration.
|
||||
|
||||
In Claude Code:
|
||||
|
||||
```bash
|
||||
claude mcp add --transport http aegis-gitea https://<your-mcp-domain>/mcp
|
||||
```
|
||||
|
||||
Cowork uses the same connector model and MCP URL.
|
||||
|
||||
Manual OAuth client configuration remains available for clients that do not use DCR:
|
||||
|
||||
- MCP server URL: `https://<your-mcp-domain>/mcp`
|
||||
- Authentication: OAuth
|
||||
- OAuth client ID: Gitea OAuth app client ID
|
||||
- OAuth client secret: Gitea OAuth app client secret
|
||||
- OAuth client ID: the client id returned by `/register` or your preconfigured client id
|
||||
- OAuth client secret: only for confidential clients
|
||||
|
||||
After creation, copy the ChatGPT callback URL and add it to the Gitea OAuth app redirect URIs.
|
||||
Hosted Claude callbacks are allowed by default: `https://claude.ai/api/mcp/auth_callback` and `https://claude.com/api/mcp/auth_callback`. Loopback redirects for Claude Code local development are allowed for `http://127.0.0.1:*` and `http://localhost:*`.
|
||||
|
||||
### 4) OAuth-protected MCP behavior
|
||||
|
||||
@@ -56,7 +76,7 @@ Example response:
|
||||
|
||||
```json
|
||||
{
|
||||
"resource": "https://git.hiddenden.cafe",
|
||||
"resource": "https://gitea-mcp.hiddenden.cafe",
|
||||
"authorization_servers": [
|
||||
"https://gitea-mcp.hiddenden.cafe",
|
||||
"https://git.hiddenden.cafe"
|
||||
@@ -76,14 +96,16 @@ WWW-Authenticate: Bearer resource_metadata="https://<mcp-host>/.well-known/oauth
|
||||
## Architecture
|
||||
|
||||
```text
|
||||
ChatGPT App
|
||||
Claude / Claude Code / Cowork
|
||||
-> Authorization Code Flow
|
||||
-> Gitea OAuth2/OIDC (issuer: https://git.hiddenden.cafe)
|
||||
-> Access token
|
||||
-> MCP Server (/mcp/sse, /mcp/tool/call)
|
||||
-> MCP Server (/mcp, /mcp/sse, /mcp/tool/call)
|
||||
-> OIDC discovery + JWKS cache
|
||||
-> Scope enforcement (read:repository / write:repository)
|
||||
-> Per-request Gitea API calls with Authorization: Bearer <user token>
|
||||
-> Policy allow/deny
|
||||
-> If GITEA_TOKEN is set: check Gitea collaborator permission for <user, repo>
|
||||
-> Gitea API call with either the user token or the service PAT after authz
|
||||
```
|
||||
|
||||
## Example curl
|
||||
@@ -108,7 +130,7 @@ Authenticated tool call:
|
||||
curl -s https://<mcp-host>/mcp/tool/call \
|
||||
-H "Authorization: Bearer <user_access_token>" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"tool":"list_repositories","arguments":{}}'
|
||||
-d '{"tool":"get_repository_info","arguments":{"owner":"acme","repo":"demo"}}'
|
||||
```
|
||||
|
||||
## Threat model
|
||||
@@ -120,8 +142,9 @@ curl -s https://<mcp-host>/mcp/tool/call \
|
||||
- URLs leak via logs, proxies, browser history, and referers.
|
||||
- bearer tokens must be sent in `Authorization` headers only.
|
||||
- Per-user OAuth reduces lateral access:
|
||||
- each call runs as the signed-in user.
|
||||
- users only see repositories they already have permission for in Gitea.
|
||||
- identity comes from Gitea OIDC/JWKS or userinfo validation.
|
||||
- without `GITEA_TOKEN`, API calls use the user's token and Gitea enforces permissions.
|
||||
- with `GITEA_TOKEN`, every repository-targeted call first checks the user's Gitea permission and fails closed if the check cannot be made.
|
||||
|
||||
## CI/CD
|
||||
|
||||
|
||||
Reference in New Issue
Block a user