Skip to main content
Glama

RAD Security

Official
by rad-security
client.ts4.55 kB
const USER_AGENT = `rad-security/mcp-server`; type RequestOptions = { method?: string; body?: unknown; headers?: Record<string, string>; }; export class RadSecurityClient { private sessionToken: string; private accessKeyId: string; private secretKey: string; private baseUrl: string; private accountId: string; private tokenCache: { token: string; expiry: Date } | null = null; constructor( sessionToken: string, accessKeyId: string, secretKey: string, baseUrl: string, accountId: string ) { this.sessionToken = sessionToken; this.accessKeyId = accessKeyId; this.secretKey = secretKey; this.baseUrl = baseUrl; this.accountId = accountId; } static fromEnv(): RadSecurityClient { const sessionToken = process.env.RAD_SECURITY_SESSION_TOKEN || ""; const accessKeyId = process.env.RAD_SECURITY_ACCESS_KEY_ID || ""; const secretKey = process.env.RAD_SECURITY_SECRET_KEY || ""; const accountId = process.env.RAD_SECURITY_ACCOUNT_ID || ""; const baseUrl = process.env.RAD_SECURITY_API_URL || "https://api.rad.security"; return new RadSecurityClient(sessionToken, accessKeyId, secretKey, baseUrl, accountId); } private isTokenValid(): boolean { if (!this.tokenCache) { return false; } return new Date() < this.tokenCache.expiry; } getBaseUrl(): string { return this.baseUrl; } getAccountId(): string { return this.accountId; } private async getToken(): Promise<string> { if (!this.accountId) { throw new Error( "You can't access the Rad Security API without setting the RAD_SECURITY_ACCOUNT_ID environment variable." ); } if (!this.sessionToken && (!this.accessKeyId || !this.secretKey)) { throw new Error( "You can't access the Rad Security API without setting the RAD_SECURITY_SESSION_TOKEN or RAD_SECURITY_ACCESS_KEY_ID and RAD_SECURITY_SECRET_KEY." + "Only few operations are available without authentication." ); } if (this.sessionToken) { return this.sessionToken; } if (this.isTokenValid()) { return this.tokenCache!.token; } try { const response = await fetch( `${this.baseUrl}/authentication/authenticate`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ access_key_id: this.accessKeyId, secret_key: this.secretKey, }), } ); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const tokenData = await response.json() as { token: string }; // Cache token with 5 min buffer before expiry (assuming 4 hour token validity) const expiry = new Date(); expiry.setMinutes(expiry.getMinutes() + 235); // 3h 55m this.tokenCache = { token: tokenData.token, expiry, }; return this.tokenCache.token; } catch (error) { throw new Error(`Error getting authentication token: ${error}`); } } async makeRequest( endpoint: string, params: Record<string, any> = {}, options: RequestOptions = {} ): Promise<any> { const headers: Record<string, string> = { "Content-Type": "application/json", "User-Agent": USER_AGENT, ...options.headers, }; const token = await this.getToken(); if (token && token.startsWith("ory_st_")) { headers["Authorization"] = `Bearer ${token}`; } else { headers["Cookie"] = `ory_kratos_session=${token}`; } const url = new URL(`${this.getBaseUrl()}${endpoint}`); if (params) { Object.entries(params).forEach(([key, value]) => { if (value !== undefined) { url.searchParams.append(key, String(value)); } }); } const response = await fetch(url, { method: options.method || "GET", headers, body: options.body ? JSON.stringify(options.body) : undefined, }); const responseBody = await this.parseResponseBody(response); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status} error: ${JSON.stringify(responseBody, null, 2)}`); } return responseBody; } private async parseResponseBody(response: Response): Promise<unknown> { const contentType = response.headers.get("content-type"); if (contentType?.includes("application/json")) { return response.json(); } return response.text(); } }

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/rad-security/mcp-server'

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