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):
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).
## 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._
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
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), notgit.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_createover MCP returned the CF block page; the identical issue filed cleanly via the Gitea REST API.The WAF sits upstream of our
gitea-mcpserver, 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)
git.d-ma.be/brain-mcp.d-ma.bedirectly, never through the Anthropic relay -> sidesteps the WAF class entirely.~/.op-envthere). This is NOT a removal of the MCP.Deliverables
1.
gitea-restskillWrap the common Gitea ops as REST calls via
op run --env-file ~/.op-env:Pattern (token stays in the subprocess; body from file, never argv):
2.
brain-restskillquery:POST https://brain-mcp.d-ma.be/query{"query": "..."}with$BRAIN_MCP_TOKENwrite:POST .../write{"content": "...", "filename": "...", "wing": "...", "hall": "..."}answer:POST .../answer(if exposed)Acceptance criteria
gitea-restSKILL.md installed in~/dev/.skills/+mathias/skills, covering the issue/file/pr/repo ops above.brain-restSKILL.md covering query/write (+ answer).op run --env-file ~/.op-env; tokens never echoed or placed in argv; bodies passed via file/stdin.~/.op-envis absent.Constraints / footguns
~/.op-env; non-interactive Bash lacks on-demand 1P (gitea-mcp#36) -> alwaysop run --env-file ~/.op-env.Refs: gitea-mcp#36, infra#129, agentsquad#31. Brain: homelab/decisions/prefer-rest-api-skills-over-mcp-on-cli-cloudflare-waf.