/**
* 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);