Source Integrations
GitHub
Connect a GitHub repository to an MCP server with either OAuth or a classic Personal Access Token. This page covers the two flows, the trade-offs between them, and the GitHub-specific caps you should know about before you import a large repo.
When to pick GitHub
GitHub is the mainline integration. Pick it if your repository is hosted on github.com (cloud) and you want either the OAuth experience for a human operator or a Personal Access Token for a service account. Authenticated callers get GitHub's 5,000 requests/hour rate limit, which is comfortably above what import or refresh ever needs.
Option A — Connect with GitHub (OAuth)
Click the "Connect with GitHub" button on the Source Integration form, complete the consent screen on GitHub, and land back on the integration's edit page with the credential already stored. The OAuth path is the right choice for human operators connecting their own account.
Scopes requested
- repo — required for private repositories. Finer-grained scopes need GitHub Apps, which is out of scope for this flow.
- read:user — used to capture the connecting user's GitHub identity for display labels.
Option B — Personal Access Token
For environments without OAuth, or for service accounts, paste a classic Personal Access Token into the Access Token field on the form. The backend validates the token against GET /user before the row is persisted — a bad token surfaces as a field-level error.
- Classic PAT scopes: repo and read:user.
- Fine-grained PATs also work — grant Contents: Read-only and Metadata: Read-only on the repositories you intend to import. Both shapes validate against the same /user endpoint, so the integration accepts whichever you paste.
OAuth vs PAT
| Axis | OAuth | Personal Access Token |
|---|---|---|
| Ease of provisioning | One click — approve the consent screen on GitHub. | Mint a token in GitHub settings, paste it. |
| Rotation | Standard GitHub revocation UX. | Manual — the user re-mints and re-pastes. |
| Storage | Encrypted in source_integrations.access_token. | Encrypted in source_integrations.access_token. |
API endpoints used
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /user |
Authenticate token, capture identity |
| GET | /user/repos |
List accessible repositories |
| GET | /repos/{owner}/{repo}/branches |
List branches for the picker |
| GET | /repos/{owner}/{repo}/git/trees/{branch}?recursive=1 |
List the entire branch tree in one call |
| GET | /repos/{owner}/{repo}/contents/{path} |
Fetch a single file body |
Caps to know about
- Maximum blob size is 10 MB. Larger files are skipped with a per-file error and the import continues.
- GitHub may truncate the recursive-tree response on very wide monorepos. The integration surfaces this as a tree-truncated error rather than silently importing a partial set.
- The pagination cap on repository and branch listings is 10 pages — sufficient for nearly every account, generous enough not to bite normal users.
Troubleshooting
| Symptom | What it means |
|---|---|
| 401 on token validation | The token is bad, revoked, or missing the read:user scope. Mint a new one. |
| 403 with rate-limit body | You are over the 5,000 requests/hour limit. The integration surfaces a Retry-After hint; wait and retry. |
| 5xx or connection timeout | Transient provider error. The queued path retries; the inline path asks you to retry manually. |
| Tree truncated | The repository is too wide for GitHub's single-shot recursive listing. Consider a path filter to scope the import. |
Self-hosted GitHub Enterprise?: Self-hosted variants are tracked separately and not yet shipped. The integration is hard-pinned to api.github.com so an env-configurable base URL cannot be used to divert authenticated traffic to a foreign host.