We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Thinh-nguyen-03/virtual-assistant-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
import { randomBytes, scrypt } from 'crypto';
import { promisify } from 'util';
const scryptAsync = promisify(scrypt);
export class EncryptedTokenStore {
key;
ttlMs;
constructor(config) {
this.key = Buffer.from(config.encryptionKey, 'base64');
this.ttlMs = config.ttlMs || 7 * 24 * 60 * 60 * 1000;
}
async encryptTokens(tokens) {
const iv = randomBytes(16);
const cipher = require('crypto').createCipher('aes-256-gcm', this.key);
cipher.setAAD(Buffer.from('mcp-router-tokens'));
let encrypted = cipher.update(JSON.stringify(tokens), 'utf8', 'hex');
encrypted += cipher.final('hex');
const authTag = cipher.getAuthTag();
return iv.toString('hex') + ':' + authTag.toString('hex') + ':' + encrypted;
}
async decryptTokens(encryptedData) {
const parts = encryptedData.split(':');
if (parts.length !== 3) {
throw new Error('Invalid encrypted token format');
}
const iv = Buffer.from(parts[0], 'hex');
const authTag = Buffer.from(parts[1], 'hex');
const encrypted = parts[2];
const decipher = require('crypto').createDecipher('aes-256-gcm', this.key);
decipher.setAAD(Buffer.from('mcp-router-tokens'));
decipher.setAuthTag(authTag);
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return JSON.parse(decrypted);
}
async storeTokens(userId, tokens) {
const now = new Date().toISOString();
const storedTokens = {
...tokens,
user_id: userId,
created_at: now,
updated_at: now
};
const encrypted = await this.encryptTokens(storedTokens);
this.memoryStore.set(userId, encrypted);
}
async getTokens(userId) {
const encrypted = this.memoryStore.get(userId);
if (!encrypted) {
return null;
}
try {
const tokens = await this.decryptTokens(encrypted);
if (Date.now() > tokens.expires_at) {
this.memoryStore.delete(userId);
return null;
}
return tokens;
}
catch (error) {
this.memoryStore.delete(userId);
return null;
}
}
async updateTokens(userId, tokens) {
const existing = await this.getTokens(userId);
if (!existing) {
throw new Error('No existing tokens found for user');
}
const updatedTokens = {
...existing,
...tokens,
updated_at: new Date().toISOString()
};
const encrypted = await this.encryptTokens(updatedTokens);
this.memoryStore.set(userId, encrypted);
}
async deleteTokens(userId) {
this.memoryStore.delete(userId);
}
async hasValidTokens(userId) {
const tokens = await this.getTokens(userId);
return tokens !== null && !this.isTokenExpired(tokens);
}
isTokenExpired(tokens) {
return Date.now() >= tokens.expires_at;
}
async getRefreshToken(userId) {
const tokens = await this.getTokens(userId);
return tokens?.refresh_token || null;
}
async updateAccessToken(userId, accessToken, expiresAt) {
await this.updateTokens(userId, {
access_token: accessToken,
expires_at: expiresAt
});
}
memoryStore = new Map();
}
export function createTokenStore(config) {
return new EncryptedTokenStore(config);
}
export function generateEncryptionKey() {
return randomBytes(32).toString('base64');
}
//# sourceMappingURL=token-store.js.map