Files
teahub/mcp
teahubxyzandClaude Opus 5.5 9fece6d818 mcp 2.2: domain search needs the MCP's sign-in; the Domains tab sends people through it once
/domains/sign-in and /domains/callback do Tea MCP's own Gitea OAuth (the
Green Tea MCP app) in the browser, keep only the name from Gitea, and leave a
signed, HttpOnly cookie on mcp.teahub.xyz for 30 days. GET /domains wants it
(401 with a sign-in link otherwise) and rate-limits per person. The Domains
tab sends that cookie, offers the sign-in on a 401, and runs the waiting
search on the way back. Tested end to end against a Gitea 28 and Cloudflare.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CYHXFvWMCs1GUmRmpySqQ6
2026-10-14 22:07:03 -07:00
..
…
2026-10-14 05:28:46 +00:00

Teahub MCP

Teahub's MCP (Fly app green-tea-mcp, https://mcp.teahub.xyz/mcp) against the Gitea at GITEA_URL. Sign-in is Gitea's OAuth (Gitea signs people in with GitHub or nostr), and every tool acts with the caller's own Gitea token: no service token, no allowlist, nothing that outruns the caller's own permissions. Reads and writes are bounded, and no tool deletes a repository, branch, file, issue or comment.

Env: GITEA_URL, PUBLIC_URL, ALLOWED_HOSTS; secrets GITEA_OAUTH_CLIENT_ID, GITEA_OAUTH_CLIENT_SECRET (an OAuth2 application on the Gitea with redirect PUBLIC_URL/auth/callback), JWT_SIGNING_KEY. State: /data (FastMCP's OAuth store).

Tools (30), all acting as you. Their parameters are typed, so a bad argument is refused before Gitea is asked anything.

  • Issues and pull requests: tea_issues, tea_issue_get/create/edit, tea_issue_comments/comment, tea_labels, tea_label (add or remove by name), tea_pull_get (branches, mergeability, checks, diff), tea_pull_create, tea_pull_review, tea_pull_merge (keeps the head branch).
  • Repositories and organisations: tea_whoami, tea_repo, tea_repo_edit (description, website, visibility, default branch, archived), tea_repo_create, tea_org_create, tea_org_repo_create, tea_org_add_member (name the team), tea_hook_create (one hook per URL).
  • Files: tea_tree, tea_file_get, tea_file_change, tea_commit (up to 50 files, text or base64, 3 MB in all), tea_branch_create.
  • Actions: tea_actions (recent runs), tea_action_logs (a run's jobs, steps and log tails), tea_workflow_dispatch, tea_secret_set (never echoed), tea_variable_set.

Beside the tools, GET /domains?q=<name or domain> answers the Domains tab of Teahub's dashboard: Cloudflare Registrar's live check of the exact names and its suggestions, with prices. It is for people signed in: the tab sends them once through /domains/sign-in, which is this server's own Gitea OAuth (the app Claude's connector uses, so it needs PUBLIC_URL/domains/callback as a second redirect), and a signed, HttpOnly cookie on this host keeps them for 30 days; Gitea's token is used once to learn the name and dropped. Only GITEA_URL may read answers from a browser (CORS); each person gets 8 searches a minute and everyone together 20, and answers are kept ten minutes. It needs the secrets CLOUDFLARE_API_TOKEN (Registrar read) and CLOUDFLARE_ACCOUNT_ID, and says it is not set up without them. Nothing is registered or bought.

New repositories are private unless asked otherwise, and labels must already exist. The Actions tools need Gitea 1.25 or later (prod runs 28).

Tests: from mcp/, python -m unittest discover -s tests (a fake Gitea and a fake Cloudflare; needs requirements.txt).