Repository navigation
Publish 403s for org namespace despite Owner role + public membership (io.github.<org>/*) #1649
Description
Activity
- added a commit that references this issue
on Sep 26, 2026 Same issue, adding a data point since I hit the exact same 403 today (mcp-publisher 1.8.1).
Setup: sole admin of a GitHub org (
GuardBee), org membership flipped from private to public, confirmed independently via the unauthenticated API:$ gh api orgs/GuardBee/public_members/4hmetuyar (200/204 — empty body, confirms public)Error (identical shape to OP's):
Error: publish failed: server returned status 403: {"title":"Forbidden","status":403,"detail":"You do not have permission to publish this server. You have permission to publish: io.github.4hmetuyar/*. Attempting to publish: io.github.GuardBee/*. ..."}Retried with a fresh
mcp-publisher login github(fresh device-flow auth, confirmed "Successfully authenticated!") several hours after making membership public — same 403, no change.I also checked the hypothesis from the OP's point 5 (that the login app isn't installed on the org, only personally authorized): confirmed the same here.
gh api orgs/GuardBee/installationsshows no MCP Registry Login app installed (only an unrelated app). I tried to find an install page for it to test that theory directly, but the app doesn't appear to be listed on the public GitHub Marketplace/App search, so I couldn't self-serve an install to rule this in or out. If org installation actually is a requirement for the token to carry org-publish permission, that's not currently documented inauthentication.mdxas far as I can tell, and there's no accessible way for an org owner to add the installation.Environment:
mcp-publisher1.8.1, GitHub device-flow auth, target namespaceio.github.GuardBee/*.loyderhy2 commented
on Oct 1, 2026 More actionsAdditional data point from
trekmail(GitHub accountloyderhy2, active organization Owner).I am using official
mcp-publisher1.8.1 (commitf52dc852) and the GitHub AppMCP Registry Login (Prod)(client IDIv23liUydBbI7Z2Q9bOZ). A successful device login, while my membership was private, returned Registry publish permission only forio.github.loyderhy2/*, notio.github.trekmail/*. I stopped before publishing.I have now made my membership public: unauthenticated
GET /orgs/trekmail/public_members/loyderhy2returned204on 2026-10-01. No post-change login has occurred, so I am not claiming the problem persists after that change. The app is personally authorized and shows zero organization installations.What is the supported procedure to obtain the organization namespace? If installation is required for this official app, could you provide its supported installation URL and exact minimum permissions?
- added a commit that references this issue
on Oct 3, 2026 Root Cause Identified + Working Workaround
I hit the same 403 and traced it to a specific root cause with a confirmed workaround.
Root Cause: Device-flow token lacks
read:orgscopeThe
mcp-publisher login githubdevice flow uses the GitHub AppMCP Registry Login (Prod)(client IDIv23liUydBbI7Z2Q9bOZ). This app does not requestread:orgscope in the device-flow authorization. The resulting GitHub token therefore has no ability to query org memberships — even public ones are invisible to it.When the registry backend exchanges this token (via
POST /v0/auth/github-at), it calls GitHub'sGET /user/memberships/orgs?state=active(or equivalent) to discover org namespaces. Because the token lacksread:org, GitHub returns only the personal account — no orgs. The registry then mints a JWT with only the personal namespace:{ "permissions": [ {"action": "publish", "resource": "io.github.jcolvin1056/*"} ] }The org namespace (
io.github.aegisgatesecurity/*) is silently omitted.Evidence
- Decoded JWT from
mcp-publisher login github— only personal namespace present (see above). gh auth tokenhasread:org— confirmed viagh api -i /user→X-OAuth-Scopes: ..., read:org, ...- Same token exchanged manually — produces JWT with both namespaces:
{ "permissions": [ {"action": "publish", "resource": "io.github.jcolvin1056/*"}, {"action": "publish", "resource": "io.github.aegisgatesecurity/*"} ] }- All GitHub-side prerequisites confirmed met: org membership public (
GET /orgs/aegisgatesecurity/public_members/jcolvin1056→ 204), org role isadmin(GET /user/memberships/orgs/aegisgatesecurity→role: admin).
Workaround (confirmed working)
Exchange a token that does have
read:orgscope directly with the registry auth endpoint, bypassingmcp-publisher login:# Use any token with read:org scope (gh CLI token works) GH_TOKEN=$(gh auth token) # Exchange for a registry JWT RESPONSE=$(curl -s -X POST https://registry.modelcontextprotocol.io/v0/auth/github-at \ -H "Content-Type: application/json" \ -d "{\"github_token\": \"$GH_TOKEN\"}") # Extract and save the registry token REGISTRY_TOKEN=$(echo "$RESPONSE" | jq -r .registry_token) mkdir -p ~/.config/mcp-publisher echo "{\"method\":\"github\",\"registry\":\"https://registry.modelcontextprotocol.io\",\"token\":\"${REGISTRY_TOKEN}\"}" > ~/.config/mcp-publisher/token.json # Publish mcp-publisher publish
Result:
✓ Successfully published ✓ Server io.github.aegisgatesecurity/aegisgate-mcp version 1.5.0Why
mcp-publisher logout && logindoesn't fix itThe device flow always requests the same scopes from the same GitHub App. No amount of re-login changes the scopes — the token will always lack
read:org. The only way to get org permissions into the registry JWT is to provide a token that already hasread:org.Suggested Fix
The
MCP Registry Login (Prod)GitHub App should requestread:orgscope during the device flow authorization. This would allow the registry backend to see public org memberships and mint JWTs with org namespaces. Alternatively, the registry backend could use the unauthenticatedGET /orgs/{org}/public_members/{user}endpoint (returns 204/404, no auth needed) to verify public org membership without requiringread:orgon the token.This explains all the reported cases in this issue and the related ones (#1527, #1537, #1468, #1551) — the device flow token simply cannot see orgs.
Environment:
mcp-publisher1.8.1, orgaegisgatesecurity, userjcolvin1056, admin role, public membership confirmed.- Decoded JWT from
Summary
mcp-publisher publishreturns 403 for an organization namespace (io.github.librocat/librocat) even though both documented prerequisites indocs/modelcontextprotocol-io/authentication.mdxare met: I am the sole Owner of thelibrocatGitHub org (not just a member), and org membership visibility is Public (confirmed independently via the unauthenticated GitHub API:GET /orgs/librocat/public_members/JohnCari→204).Error
What I checked/tried (5 attempts across 2 browser sessions)
mcp-publisher init→ generatedserver.jsonwith"name": "io.github.librocat/librocat";mcp-publisher validate server.jsonpasses.mcp-publisher login github(interactive device flow) → succeeds, confirms identity asJohnCari.mcp-publisher publish→ 403 as above. Repeated with a fresh login each time (5 times total), including after:github.com/orgs/librocat/people), verified via the public API as above.Third-party access→OAuth app policy) — that governs classic OAuth Apps, and the registry's login uses a GitHub App (MCP Registry Login (Prod), client idIv23liUydBbI7Z2Q9bOZ), not a classic OAuth App.MCP Registry Login (Prod)is not installed on thelibrocatorg (only personally authorized via the device flow) —github.com/organizations/librocat/settings/installationsshows only an unrelated app (Vercel) installed.authentication.mdxdoesn't document org installation as a requirement for the interactive login path (only for CI-style Personal Access Tokens needingread:org/ fine-grainedMembers: Read-only), so I didn't want to grant broader org access speculatively without knowing it's actually needed — flagging this as a possible missing requirement/doc gap if it turns out to be the real cause.Expected
Given I'm the org's sole Owner with public membership,
mcp-publisher publishshould succeed forio.github.librocat/*, per the documented rules inauthentication.mdx.Environment
mcp-publisherversion: 1.8.1 (commitf52dc852, built 2026-08-06)io.github.librocat/librocatio.github.JohnCari/*Happy to provide more detail (org id, timestamps of attempts, etc.) if useful.