WeSearch

GitHub shipped a compliant MCP server. Most authors can't

·6 min read · 0 reactions · 0 comments · 0 views
GitHub shipped a compliant MCP server. Most authors can't

Weekly security audits of remote MCP servers. OAuth 2.1, PKCE, DCR, token hygiene, and the spec gaps nobody's reading. - korrel-dev/mcp-audits

Original article
GitHub
Read full at GitHub →
Full article excerpt tap to expand

GitHub shipped a compliant MCP server. Most authors can't. Audit 01. GitHub Remote MCP Server. 2026-04-27. GitHub's remote MCP server is a careful OAuth 2.1 implementation. It works because GitHub has owned its OAuth infrastructure for over a decade. Most MCP server authors don't have that, and the spec quietly assumes they will. This is the first in a weekly series auditing remote MCP servers against the OAuth 2.1 authorization requirements of the Model Context Protocol specification. I picked GitHub first because it's the highest-stakes, most-integrated, most-resourced MCP server in the ecosystem. If anyone is going to get the spec right, it's them. They got the structural pieces right. Where they fell short, the gaps point to something about the ecosystem, not something about GitHub. All findings below link to raw HTTP evidence committed in evidence/. Methodology is documented in METHODOLOGY.md. What GitHub got right Discovery probe. An unauthenticated request to https://api.githubcopilot.com/mcp/ returns HTTP/1.1 401 with a well-formed WWW-Authenticate header pointing to the Protected Resource Metadata document (RFC 9728): HTTP/1.1 401 Unauthorized WWW-Authenticate: Bearer error="invalid_request", error_description="No access token was provided in this request", resource_metadata="https://api.githubcopilot.com/.well-known/oauth-protected-resource/mcp/" Small nit: RFC 6750 §3.1 says the resource server SHOULD NOT include an error code or other error information when the request lacks any authentication. GitHub's response carries error="invalid_request" and a description anyway. Runtime impact is zero, every client I've seen ignores both fields, and it's the kind of detail that suggests the code predates a careful re-read of the RFC. Unsurprising for infrastructure this old. Protected Resource Metadata. The PRM is served at the per-resource path (/.well-known/oauth-protected-resource/mcp/), not the top-level form. This is a deliberate choice: it lets a single host serve multiple resources, each with distinct auth requirements. The document itself is minimal and correct: { "resource": "https://api.githubcopilot.com/mcp/", "authorization_servers": ["https://github.com/login/oauth"], "scopes_supported": ["repo", "read:org", "read:user", "user:email", "read:packages", "write:packages", "read:project", "project", "gist", "notifications", "workflow", "codespace"], "bearer_methods_supported": ["header"], "resource_name": "GitHub MCP Server" } The bearer_methods_supported: ["header"] is the detail worth flagging. It explicitly rejects query-string and form-parameter token transmission. Query-string tokens end up in server access logs, browser history, and referrer headers. GitHub's PRM says: don't do that. Good. Authorization server metadata. This one is a teaching moment. The AS issuer is https://github.com/login/oauth, an issuer with a path component. RFC 8414 specifies two forms for the well-known location, and §3.1 gives the path-insertion form for issuers like this one: https://github.com/.well-known/oauth-authorization-server/login/oauth Not the more obvious https://github.com/login/oauth/.well-known/oauth-authorization-server, which returns 404. A quick audit that tests only the naive form would conclude GitHub has no AS metadata document at all. They do. It's at the spec-correct location, and the document is clean: { "issuer": "https://github.com/login/oauth", "authorization_endpoint": "https://github.com/login/oauth/authorize",…

This excerpt is published under fair use for community discussion. Read the full article at GitHub.

Anonymous · no account needed
Share 𝕏 Facebook Reddit LinkedIn Email

Discussion

0 comments

More from GitHub