feat: gitea-rest + brain-rest skills — default to direct REST API on CLI to bypass MCP-relay Cloudflare WAF blocks #6

Open
opened 2026-06-20 09:41:44 +00:00 by mathias · 0 comments
Owner

Problem

MCP tool calls to the claude.ai Gitea (and by extension Brain) connectors intermittently fail with a Cloudflare "Sorry, you have been blocked" page. The block is on the Anthropic-hosted MCP relay POST -- the error page names anthropic.com (e.g. IP 5.150.212.35), not git.d-ma.be. It triggers on large or command-shaped bodies (WAF: "a SQL command or malformed data"). Observed 2026-06-20 while filing infra#129 (a multi-code-block issue): issue_create over MCP returned the CF block page; the identical issue filed cleanly via the Gitea REST API.

The WAF sits upstream of our gitea-mcp server, in front of Anthropic's connector gateway -- we cannot tune it. The only durable lever is to route around the relay.

Decision (see brain: homelab/decisions/prefer-rest-api-skills-over-mcp-on-cli-cloudflare-waf)

  • Claude Code CLI (koala/iguana/flamingo): default to direct REST-API skills for Gitea + Brain writes / large / command-shaped payloads. koala -> git.d-ma.be / brain-mcp.d-ma.be directly, never through the Anthropic relay -> sidesteps the WAF class entirely.
  • MCP connectors: keep as fallback AND as the only option on claude.ai Desktop/web (no shell / no ~/.op-env there). This is NOT a removal of the MCP.

Deliverables

1. gitea-rest skill

Wrap the common Gitea ops as REST calls via op run --env-file ~/.op-env:

  • issue: create / comment / get / list / edit / close
  • file: read / write-branch / delete
  • pr: create / list / get / merge
  • repo: get / list / status

Pattern (token stays in the subprocess; body from file, never argv):

op run --env-file ~/.op-env -- python3 - <<'PY'
import os, json, urllib.request
body = open('/tmp/body.md').read()
req = urllib.request.Request(
    'https://git.d-ma.be/api/v1/repos/OWNER/REPO/issues',
    data=json.dumps({'title': T, 'body': body}).encode(),
    headers={'Authorization': 'token '+os.environ['DMABE_GITEA_API_TOKEN'],
             'Content-Type': 'application/json'}, method='POST')
print(json.load(urllib.request.urlopen(req, timeout=30))['html_url'])
PY

2. brain-rest skill

  • query: POST https://brain-mcp.d-ma.be/query {"query": "..."} with $BRAIN_MCP_TOKEN
  • write: POST .../write {"content": "...", "filename": "...", "wing": "...", "hall": "..."}
  • answer: POST .../answer (if exposed)

Acceptance criteria

  • gitea-rest SKILL.md installed in ~/dev/.skills/ + mathias/skills, covering the issue/file/pr/repo ops above.
  • brain-rest SKILL.md covering query/write (+ answer).
  • Both wrap all secret use in op run --env-file ~/.op-env; tokens never echoed or placed in argv; bodies passed via file/stdin.
  • Skill trigger guidance: on Claude Code CLI prefer these over the MCP for writes / large or command-shaped payloads; fall back to MCP if ~/.op-env is absent.
  • SKILLS_INDEX.md updated.
  • Smoke test each: create a throwaway issue + a brain query, confirm no relay/WAF in the path.

Constraints / footguns

  • Requires ~/.op-env; non-interactive Bash lacks on-demand 1P (gitea-mcp#36) -> always op run --env-file ~/.op-env.
  • Accept skill+MCP duplication: the relay WAF is upstream and unfixable from our side.
  • Gitea REST per-repo paths work directly (unlike gitea-mcp per-repo tools that 404 to /api/swagger -- see brain reference_gitea_api_fallback).

Refs: gitea-mcp#36, infra#129, agentsquad#31. Brain: homelab/decisions/prefer-rest-api-skills-over-mcp-on-cli-cloudflare-waf.

## Problem MCP tool calls to the claude.ai **Gitea** (and by extension **Brain**) connectors intermittently fail with a Cloudflare "Sorry, you have been blocked" page. The block is on the **Anthropic-hosted MCP relay POST** -- the error page names `anthropic.com` (e.g. IP 5.150.212.35), not `git.d-ma.be`. It triggers on large or command-shaped bodies (WAF: "a SQL command or malformed data"). Observed 2026-06-20 while filing infra#129 (a multi-code-block issue): `issue_create` over MCP returned the CF block page; the identical issue filed cleanly via the Gitea REST API. The WAF sits **upstream of our `gitea-mcp` server**, in front of Anthropic's connector gateway -- we cannot tune it. The only durable lever is to route around the relay. ## Decision (see brain: homelab/decisions/prefer-rest-api-skills-over-mcp-on-cli-cloudflare-waf) - **Claude Code CLI (koala/iguana/flamingo):** default to direct REST-API skills for Gitea + Brain writes / large / command-shaped payloads. koala -> `git.d-ma.be` / `brain-mcp.d-ma.be` directly, never through the Anthropic relay -> sidesteps the WAF class entirely. - **MCP connectors:** keep as fallback AND as the only option on claude.ai Desktop/web (no shell / no `~/.op-env` there). This is NOT a removal of the MCP. ## Deliverables ### 1. `gitea-rest` skill Wrap the common Gitea ops as REST calls via `op run --env-file ~/.op-env`: - issue: create / comment / get / list / edit / close - file: read / write-branch / delete - pr: create / list / get / merge - repo: get / list / status Pattern (token stays in the subprocess; body from file, never argv): ```bash op run --env-file ~/.op-env -- python3 - <<'PY' import os, json, urllib.request body = open('/tmp/body.md').read() req = urllib.request.Request( 'https://git.d-ma.be/api/v1/repos/OWNER/REPO/issues', data=json.dumps({'title': T, 'body': body}).encode(), headers={'Authorization': 'token '+os.environ['DMABE_GITEA_API_TOKEN'], 'Content-Type': 'application/json'}, method='POST') print(json.load(urllib.request.urlopen(req, timeout=30))['html_url']) PY ``` ### 2. `brain-rest` skill - `query`: `POST https://brain-mcp.d-ma.be/query` `{"query": "..."}` with `$BRAIN_MCP_TOKEN` - `write`: `POST .../write` `{"content": "...", "filename": "...", "wing": "...", "hall": "..."}` - `answer`: `POST .../answer` (if exposed) ## Acceptance criteria - [ ] `gitea-rest` SKILL.md installed in `~/dev/.skills/` + `mathias/skills`, covering the issue/file/pr/repo ops above. - [ ] `brain-rest` SKILL.md covering query/write (+ answer). - [ ] Both wrap all secret use in `op run --env-file ~/.op-env`; tokens never echoed or placed in argv; bodies passed via file/stdin. - [ ] Skill trigger guidance: on Claude Code CLI prefer these over the MCP for writes / large or command-shaped payloads; fall back to MCP if `~/.op-env` is absent. - [ ] SKILLS_INDEX.md updated. - [ ] Smoke test each: create a throwaway issue + a brain query, confirm no relay/WAF in the path. ## Constraints / footguns - Requires `~/.op-env`; non-interactive Bash lacks on-demand 1P (gitea-mcp#36) -> always `op run --env-file ~/.op-env`. - Accept skill+MCP duplication: the relay WAF is upstream and unfixable from our side. - Gitea REST per-repo paths work directly (unlike gitea-mcp per-repo tools that 404 to /api/swagger -- see brain reference_gitea_api_fallback). _Refs: gitea-mcp#36, infra#129, agentsquad#31. Brain: homelab/decisions/prefer-rest-api-skills-over-mcp-on-cli-cloudflare-waf._
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mathias/skills#6