Skip to main content
Glama
get-access-token.js3.7 kB
#!/usr/bin/env node import crypto from 'crypto'; import { createInterface } from 'readline'; import axios from 'axios'; import open from 'open'; // ClickUp OAuth configuration // You'll need to replace these with your actual app credentials const CLIENT_ID = process.env.CLICKUP_CLIENT_ID || 'your_client_id_here'; const REDIRECT_URI = 'http://localhost:3000/callback'; // or your configured redirect URI if (CLIENT_ID === 'your_client_id_here') { console.error('Please set CLICKUP_CLIENT_ID environment variable or edit the script with your Client ID'); process.exit(1); } // Generate PKCE code verifier and challenge function generatePKCE() { const codeVerifier = crypto.randomBytes(32).toString('base64url'); const codeChallenge = crypto.createHash('sha256').update(codeVerifier).digest('base64url'); return { codeVerifier, codeChallenge }; } // Create authorization URL function createAuthUrl(codeChallenge) { const params = new URLSearchParams({ client_id: CLIENT_ID, redirect_uri: REDIRECT_URI, response_type: 'code', scope: 'task:read task:write', // Adjust scopes as needed code_challenge: codeChallenge, code_challenge_method: 'S256' }); return `https://app.clickup.com/api?${params.toString()}`; } // Exchange authorization code for access token async function exchangeCodeForToken(code, codeVerifier) { try { const response = await axios.post('https://api.clickup.com/api/v2/oauth/token', { client_id: CLIENT_ID, client_secret: process.env.CLICKUP_CLIENT_SECRET || '', // If required code: code, grant_type: 'authorization_code', redirect_uri: REDIRECT_URI, code_verifier: codeVerifier }); return response.data; } catch (error) { console.error('Error exchanging code for token:', error.response?.data || error.message); throw error; } } // Main function async function main() { console.log('ClickUp OAuth Token Setup'); console.log('========================'); // Generate PKCE const { codeVerifier, codeChallenge } = generatePKCE(); console.log('Generated PKCE code challenge'); // Create and open authorization URL const authUrl = createAuthUrl(codeChallenge); console.log('\nOpening browser for authorization...'); console.log('If browser doesn\'t open, visit this URL manually:'); console.log(authUrl); try { await open(authUrl); } catch (error) { console.log('Could not open browser automatically. Please visit the URL above manually.'); } // Wait for user to paste the authorization code const rl = createInterface({ input: process.stdin, output: process.stdout }); const code = await new Promise((resolve) => { rl.question('\nAfter authorizing, paste the authorization code from the redirect URL: ', (answer) => { resolve(answer.trim()); rl.close(); }); }); if (!code) { console.error('No authorization code provided'); process.exit(1); } console.log('\nExchanging code for access token...'); try { const tokenData = await exchangeCodeForToken(code, codeVerifier); console.log('\n✅ Success! Your ClickUp access token is:'); console.log(tokenData.access_token); if (tokenData.refresh_token) { console.log('\nRefresh token (keep this secure):'); console.log(tokenData.refresh_token); } console.log('\nAdd this to your MCP settings as CLICKUP_ACCESS_TOKEN environment variable.'); console.log('Example:'); console.log(`"env": { "CLICKUP_ACCESS_TOKEN": "${tokenData.access_token}" }`); } catch (error) { console.error('Failed to get access token:', error.message); process.exit(1); } } main().catch(console.error);

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/rubenaguir/clickup-mcp-server'

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