Production URL: https://mcp.mention.earth/
Canonical user + operator guide. Mention agents: see also AGENTS.md § MCP.
- Settings → Connectors → Add custom connector
- URL:
https://mcp.mention.earth(no trailing slash) - Complete OAuth on mention.earth when prompted
- Revoke anytime: Mention → Settings → Connected AI
Claude blocks duplicate URLs — you cannot add the same MCP URL twice. Use linked accounts (below) to post as multiple Mention users from one connector.
| Step | Action |
|---|---|
| 1 | Connect once → OAuth as your first account (primary) |
| 2 | In chat: link-account → open URL in browser → sign in as other account → Link to Claude |
| 3 | switch-account with target @handle |
| 4 | whoami to confirm → create-post |
| Tool | Purpose |
|---|---|
whoami |
Active account (@handle, display name, user id) |
list-accounts |
All accounts linked to this connector |
link-account |
Browser URL to add another account (single-use, 15 min) |
switch-account |
Set active account by @handle |
Max 8 linked accounts per connector (MCP_MAX_BUNDLE_MEMBERS).
Claude Web → mcp.mention.earth (ECS mention-mcp) → api.mention.earth (ECS mention)
↑ OAuth consent + link UI on mention.earth
| Component | Role |
|---|---|
@mention/mcp |
MCP protocol (streamable HTTP), tool handlers |
api.mention.earth |
REST API + OAuth authorization server (RFC 8414 / 9728 / 7591 DCR) |
mention.earth |
Consent UI (/oauth/mcp/authorize), link UI (/oauth/mcp/link), Settings revoke |
Identity model: Claude holds one OAuth token (primary account). The backend resolves the active account per request via bundleId + Redis/Postgres (activeOxyUserId on the primary McpConnection). Linked accounts approve via browser link flow — not a second Claude OAuth grant.
| Tool | Backend |
|---|---|
whoami |
GET /mcp/bundles/me |
list-accounts |
GET /mcp/bundles/accounts |
link-account |
POST /mcp/bundles/link-token |
switch-account |
POST /mcp/bundles/active |
| Tool | Backend |
|---|---|
create-post |
POST /posts |
create-thread |
POST /posts/thread (no collaborators) |
update-post |
PUT /posts/:id |
delete-post |
DELETE /posts/:id |
accept-collab-invite |
POST /posts/:id/collaborators/accept |
decline-collab-invite |
POST /posts/:id/collaborators/decline |
stop-collab-sharing |
POST /posts/:id/collaborators/stop-sharing |
get-drafts |
GET /posts/drafts |
get-scheduled-posts |
GET /posts/scheduled |
get-saved-posts |
GET /posts/saved |
- Invite up to 5 local co-authors on
create-postorupdate-postviacollaboratorIdsorcollaboratorHandles(@username). The backend resolves handles to user IDs (MCP passes them through unchanged). - Linked bundle accounts are auto-accepted when invited (backend intersects with bundle members).
- External users stay
pendinguntil theyswitch-accountand callaccept-collab-inviteordecline-collab-invite. - Accepted collaborators can call
stop-collab-sharing. - Threads do not support collaborators (backend returns 400).
- Federation is deferred until all invites resolve.
| Tool | Auth | Backend |
|---|---|---|
get-feed |
no | GET /feed/mtn |
get-explore-feed |
no | GET /feed/mtn?descriptor=explore |
get-for-you-feed |
yes | GET /feed/mtn?descriptor=for_you |
get-following-feed |
yes | GET /feed/mtn?descriptor=following |
get-videos-feed |
yes | GET /feed/mtn?descriptor=videos |
get-user-feed |
no | GET /feed/mtn?descriptor=author|<id> |
get-replies |
no | GET /feed/replies/:id |
get-feed-item |
no | GET /feed/item/:id |
get-post |
no | GET /feed/item/:id |
like-post, unlike-post, save-post, unsave-post, boost, quote-post
| Tool | Auth | Backend |
|---|---|---|
follow-user |
yes | POST /federation/follow |
unfollow-user |
yes | POST /federation/unfollow |
get-recommendations |
no | GET /recommendations |
| Tool | Auth | Backend |
|---|---|---|
get-starter-packs |
no | GET /starter-packs |
get-starter-pack |
no | GET /starter-packs/:id |
create-starter-pack |
yes | POST /starter-packs |
update-starter-pack |
yes | PUT /starter-packs/:id |
delete-starter-pack |
yes | DELETE /starter-packs/:id |
add-starter-pack-members |
yes | POST /starter-packs/:id/members |
remove-starter-pack-members |
yes | DELETE /starter-packs/:id/members |
use-starter-pack |
yes | POST /starter-packs/:id/use |
See packages/mcp/tools/*.ts. Most write and personalized reads require auth
through lib/auth-guard.ts.
Session note: Claude must complete OAuth before initialize (POST requires Bearer). Some tools are callable without extra per-tool auth once the session is open, but the connector itself always needs OAuth first.
Implemented in packages/backend/src/mcp/.
| Endpoint | Purpose |
|---|---|
GET /.well-known/oauth-authorization-server |
AS discovery (includes registration_endpoint) |
GET /.well-known/oauth-protected-resource |
Resource metadata (resource = https://mcp.mention.earth, no slash) |
POST /mcp/oauth/register |
RFC 7591 dynamic client registration |
GET /mcp/oauth/authorize |
Start auth code + PKCE flow |
POST /mcp/oauth/token |
Exchange code / refresh token |
GET /mcp/bundles/link/preview?token= |
Link-flow preview (public) |
| Endpoint | Purpose |
|---|---|
POST /mcp/oauth/approve |
Consent approval (Oxy session) |
GET /mcp/connections |
List authorized clients (Settings data) |
DELETE /mcp/connections/:id |
Revoke connection |
GET /mcp/bundles/accounts |
Linked accounts in bundle |
GET /mcp/bundles/me |
Active account summary |
POST /mcp/bundles/link-token |
Mint single-use browser link token |
POST /mcp/bundles/link/complete |
Complete link (Oxy session + token) |
POST /mcp/bundles/active |
Switch active account |
src/mcp/routes/mcpOAuth.routes.ts— OAuth AS + link previewsrc/mcp/routes/mcpBundles.routes.ts— multi-account bundle APIsrc/mcp/routes/mcpConnections.routes.ts— list/revokesrc/mcp/middleware/mcpAuth.ts— dual MCP/Oxy auth + active account resolutionsrc/mcp/services/mcpBundleService.ts— bundles, link tokens, Redis active accountsrc/mcp/models/McpConnection.ts— grants (bundleId,isBundlePrimary,activeOxyUserId)
packages/frontend/app/(app)/oauth/mcp/authorize.tsx— initial OAuth consent (@handle shown)packages/frontend/app/(app)/oauth/mcp/link.tsx— link additional accountpackages/frontend/app/(app)/settings/connected-ai.tsx— revoke + bundle handles
| Variable | Default | Purpose |
|---|---|---|
MENTION_API_URL |
https://api.mention.earth |
Mention REST API |
MENTION_API_TIMEOUT_MS |
10000 |
Per-attempt Mention API timeout; GET retries once |
MENTION_MCP_PUBLIC_URL |
https://mcp.mention.earth |
Public MCP URL (JWT aud) |
MENTION_OAUTH_AS_URL |
https://api.mention.earth |
OAuth AS origin |
MCP_PORT |
3100 |
HTTP listen port |
MENTION_MCP_JWT_SECRET |
(required) | Must match backend secret |
MCP_ALLOWED_ORIGINS |
Claude defaults | Extra CORS origins |
MCP_MAX_REQUEST_BODY_BYTES |
1048576 |
Maximum JSON request body retained in memory |
MCP_MAX_SESSIONS |
1000 |
Per-task cap for active HTTP/SSE sessions |
| Variable | Purpose |
|---|---|
MENTION_MCP_JWT_SECRET |
Sign/verify MCP access tokens |
MENTION_MCP_PUBLIC_URL |
Protected-resource resource + JWT aud |
MENTION_FRONTEND_ORIGIN |
Consent redirect (https://mention.earth) |
MENTION_PUBLIC_API_URL |
OAuth issuer (https://api.mention.earth) |
MCP_LINK_TOKEN_TTL_SECONDS |
Link token lifetime (default 900) |
MCP_MAX_BUNDLE_MEMBERS |
Max accounts per bundle (default 8) |
Secrets: GitHub Actions → SSM /oxy/mention/* and /oxy/mention-mcp/*.
| Service | ECR | Domain | Workflow |
|---|---|---|---|
mention |
oxy/mention |
api.mention.earth, mention.earth |
.github/workflows/deploy-aws.yml |
mention-mcp |
oxy/mention-mcp |
mcp.mention.earth |
.github/workflows/deploy-mcp-aws.yml |
Infra: oxy-infra — ALB rule priority 140, ACM cert mcp.mention.earth, DNS CNAME → ALB (DNS-only/grey cloud like api.mention.earth).
Backend MCP OAuth changes deploy with mention; tool/protocol changes deploy with mention-mcp. Frontend consent/link UI deploys with mention (apex web shell).
# Terminal 1 — backend
cd packages/backend && bun run dev
# Terminal 2 — MCP HTTP server (not for end users)
cd packages/mcp
MENTION_API_URL=http://localhost:4110 bun run dev:httpFrom repo root: bun run dev:mcp:http
curl https://mcp.mention.earth/health→ 200curl -D - -o /dev/null https://mcp.mention.earth/→ 401 +WWW-Authenticate: Bearer ...curl https://mcp.mention.earth/.well-known/oauth-protected-resource→resourcewithout trailing slashcurl https://api.mention.earth/.well-known/oauth-authorization-server→ includesregistration_endpoint- Claude connector → OAuth →
whoami/create-postsucceed link-account→ browser link → second account →switch-account→whoamishows second account- Settings → Connected AI → revoke → writes fail
MENTION_MCP_JWT_SECRETset in GitHub secrets (synced to SSM)
- Link tokens: HMAC-signed, TTL 15 min, single-use (Redis
NX) - Bundle membership: explicit approve on
/oauth/mcp/link; unique index on(bundleId, oxyUserId)when not revoked - Active account: persisted on primary
McpConnection.activeOxyUserId+ Redis; switch fails closed (503) if neither persists - No
as_useroncreate-post— mustswitch-accountfirst