Skip to main content
Glama
utils.ts2.15 kB
import crypto from "crypto"; import path from "path"; import fs from "fs/promises"; import { exec } from "child_process"; import { promisify } from "util"; import type { PKCEPair } from "./types.js"; const execAsync = promisify(exec); /** * Generate PKCE code verifier and challenge */ export function generatePKCE(): PKCEPair { // Generate 128-character random string for verifier const verifier = base64URLEncode(crypto.randomBytes(96)); // Create SHA256 hash of verifier for challenge const challenge = base64URLEncode( crypto.createHash("sha256").update(verifier).digest() ); return { verifier, challenge, }; } /** * Base64 URL encode (RFC 4648) */ function base64URLEncode(buffer: Buffer): string { return buffer .toString("base64") .replace(/\+/g, "-") .replace(/\//g, "_") .replace(/=/g, ""); } /** * Get the config directory path (~/.mcp-spotify) */ export function getConfigDir(): string { const home = process.env.HOME || process.env.USERPROFILE || "."; return path.join(home, ".mcp-spotify"); } /** * Ensure config directory exists */ export async function ensureConfigDir(): Promise<string> { const dir = getConfigDir(); await fs.mkdir(dir, { recursive: true }); return dir; } /** * Get the tokens file path */ export function getTokensPath(): string { return path.join(getConfigDir(), "tokens.json"); } /** * Open a URL in the default browser (cross-platform) */ export async function openBrowser(url: string): Promise<void> { const platform = process.platform; try { if (platform === "win32") { // Windows await execAsync(`start "" "${url}"`); } else if (platform === "darwin") { // macOS await execAsync(`open "${url}"`); } else { // Linux/Unix await execAsync(`xdg-open "${url}"`); } } catch (error) { // If automatic opening fails, log the URL for manual opening console.error(`Please open this URL manually: ${url}`); throw error; } } /** * Generate a random state parameter for OAuth */ export function generateState(): string { return base64URLEncode(crypto.randomBytes(32)); }

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/nicklaustrup/mcp-spotify'

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