Skip to main content
Glama
check-token-permissions.ts6.48 kB
/** * Utility script to check if GitHub PAT has permissions to access a repository */ import 'dotenv/config'; import { graphql } from '@octokit/graphql'; const token = process.env.GITHUB_TOKEN; const repoToCheck = process.argv[2] || 'radireddy/AiApps'; if (!token) { console.error('❌ Error: GITHUB_TOKEN is required'); console.error(' Set it in .env file: GITHUB_TOKEN=your_token_here'); console.error(' Or as environment variable: export GITHUB_TOKEN=your_token_here'); process.exit(1); } const client = graphql.defaults({ headers: { authorization: `token ${token}`, }, }); async function checkTokenPermissions() { console.log('🔍 Checking GitHub Token Permissions\n'); console.log(`Repository: ${repoToCheck}\n`); console.log('='.repeat(60)); try { // Check 1: Verify token is valid and get user info console.log('\n1️⃣ Checking token validity...'); const userQuery = ` query { viewer { login email } } `; const userResult = (await client(userQuery)) as any; console.log(`✅ Token is valid`); console.log(` Authenticated as: ${userResult.viewer.login}`); if (userResult.viewer.email) { console.log(` Email: ${userResult.viewer.email}`); } // Check 2: Check repository access console.log(`\n2️⃣ Checking access to repository: ${repoToCheck}...`); const [owner, repoName] = repoToCheck.split('/'); const repoQuery = ` query($owner: String!, $repo: String!) { repository(owner: $owner, name: $repo) { id name nameWithOwner isPrivate viewerPermission visibility } } `; try { const repoResult = (await client(repoQuery, { owner, repo: repoName, })) as any; const repo = repoResult.repository; console.log(`✅ Repository access granted`); console.log(` Repository: ${repo.nameWithOwner}`); console.log(` Visibility: ${repo.visibility}`); console.log(` Is Private: ${repo.isPrivate}`); console.log(` Your Permission: ${repo.viewerPermission || 'NONE'}`); if (repo.viewerPermission) { console.log(`\n✅ You have ${repo.viewerPermission} permission to this repository`); console.log(` This should be sufficient to query PRs and reviews.`); } else { console.log(`\n⚠️ Warning: No explicit permission shown (may still have read access)`); } } catch (error: any) { if (error.status === 404 || error.message?.includes('Could not resolve')) { console.log(`❌ Repository not found or no access`); console.log(` This could mean:`); console.log(` - Repository doesn't exist or name is incorrect`); console.log(` - Token doesn't have access to this repository`); console.log(` - Repository is private and token lacks 'repo' scope`); console.log(` - For organization repos, token needs 'read:org' scope`); console.log(` - Your account may not be a member of the organization`); } else if (error.status === 401 || error.message?.includes('Bad credentials')) { console.log(`❌ Authentication failed`); console.log(` Token may be invalid or expired`); } else if (error.status === 403) { console.log(`❌ Access forbidden`); console.log(` Token may lack required permissions:`); console.log(` - 'repo' scope (for private repos)`); console.log(` - 'read:org' scope (for organization repos)`); } else { console.log(`❌ Error checking repository: ${error.message}`); } } // Check 3: Test search query for PRs console.log(`\n3️⃣ Testing search query for PRs in ${repoToCheck}...`); const searchQueryGraphQL = ` query($searchQuery: String!) { search(query: $searchQuery, type: ISSUE, first: 1) { issueCount } } `; try { const searchResult = (await client(searchQueryGraphQL, { searchQuery: `is:pr repo:${repoToCheck}`, })) as any; const count = searchResult.search.issueCount; console.log(`✅ Search query works`); console.log(` Found ${count} PRs in this repository`); if (count === 0) { console.log(` (This is normal if the repo has no PRs)`); } } catch (error: any) { console.log(`❌ Search query failed: ${error.message}`); if (error.message?.includes('rate limit')) { console.log(` Rate limit exceeded - wait and try again`); } else if (error.message?.includes('query') && error.message?.includes('variable name')) { console.log(` (This is a code issue, not a permission issue)`); } else if (error.status === 403) { console.log(` Access forbidden - token may lack 'read:org' or 'repo' scope`); console.log(` For private organization repos, both scopes are typically required`); } } // Check 4: Verify required scopes console.log(`\n4️⃣ Checking token scopes...`); const isOrgRepo = repoToCheck.includes('/') && !repoToCheck.startsWith(repoToCheck.split('/')[0] + '/'); console.log(` Required scopes for this MCP server:`); console.log(` - repo (REQUIRED for private repos)`); console.log(` - read:org (REQUIRED for organization repos like ${repoToCheck.split('/')[0]})`); console.log(` - read:user (for user data)`); console.log(`\n For private organization repositories:`); console.log(` ✅ Token MUST have both 'repo' AND 'read:org' scopes`); console.log(` ✅ Your account must be a member of the organization`); console.log(` ✅ Organization must allow third-party access (if using OAuth)`); console.log(`\n To check/update your token scopes, visit:`); console.log(` https://github.com/settings/tokens`); console.log(` (Look for the token and check its scopes)`); console.log('\n' + '='.repeat(60)); console.log('✅ Permission check completed\n'); } catch (error: any) { console.error('\n❌ Error:', error.message); if (error.status === 401) { console.error(' Token authentication failed. Check your GITHUB_TOKEN.'); } else if (error.status === 403) { console.error(' Access forbidden. Token may lack required permissions.'); } process.exit(1); } } checkTokenPermissions().catch(console.error);

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/radireddy/github-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server