Skip to main content
Glama

Cashfree MCP Server

Official
by cashfree
index.ts7.08 kB
import { validate } from "@mintlify/openapi-parser"; import axios, { isAxiosError } from "axios"; import dashify from "dashify"; import fs from "node:fs"; import { getFileId } from "../utils.js"; import { Endpoint } from "../types.js"; import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { convertEndpointToCategorizedZod, convertStrToTitle, findNextIteration, getEndpointsFromOpenApi, loadEnv, getValFromNestedJson, generateCfSignature, } from "./helpers.js"; export async function createToolsFromOpenApi( openApiPath: string, index: number, server: McpServer, existingTools: Set<string> ): Promise<void> { let openapi: string; try { openapi = fs.readFileSync(openApiPath, "utf8"); } catch (error) { return; // Skip if no file } const { valid, errors, specification } = await validate(openapi); if (!valid || !specification || !specification.paths) { console.error("Invalid OpenAPI file or missing paths:", errors); return; } const endpoints = getEndpointsFromOpenApi(specification); const endpointId = String(getFileId(specification, index)); const envVars = loadEnv(endpointId); endpoints.forEach((endpoint: Endpoint) => { const { url: urlSchema, method: methodSchema, paths: pathsSchema, queries: queriesSchema, body: bodySchema, headers: headersSchema, cookies: cookiesSchema, } = convertEndpointToCategorizedZod(endpointId, endpoint); const serverArgumentsSchemas = Object.assign( Object.assign( Object.assign( Object.assign(Object.assign({}, pathsSchema), queriesSchema), bodySchema ), headersSchema ), cookiesSchema ); if (!endpoint.title) { endpoint.title = `${endpoint.method} ${convertStrToTitle(endpoint.path)}`; } if (existingTools.has(endpoint.title)) { const lastCount = findNextIteration(existingTools, endpoint.title); endpoint.title = `${endpoint.title}---${lastCount}`; } if (endpoint.title.length > 64) { endpoint.title = endpoint.title.slice(0, -64); } existingTools.add(endpoint.title); server.tool( dashify(endpoint.title), endpoint.description || endpoint.title, serverArgumentsSchemas, async (inputArgs: Record<string, any>) => { const inputParams: Record<string, any> = {}; const inputHeaders: Record<string, any> = {}; const inputCookies: Record<string, any> = {}; let urlWithPathParams = urlSchema; let inputBody: any = undefined; if ("body" in inputArgs) { inputBody = inputArgs.body; delete inputArgs.body; } Object.entries(inputArgs).forEach(([key, value]) => { if (key in pathsSchema) { urlWithPathParams = urlWithPathParams.replace(`{${key}}`, value); } else if (key in queriesSchema) { inputParams[key] = value; } else if (key in headersSchema) { inputHeaders[key] = value; } else if (key in cookiesSchema) { inputCookies[key] = value; } }); if (endpoint.request.security.length > 0) { const securityParams = endpoint.request?.security?.[0]?.parameters; if (securityParams?.header) { Object.entries(securityParams.header).forEach(([key, value]) => { let envKey = ""; if ( typeof value === "object" && value !== null && "type" in value ) { const v = value as { type: string; scheme?: string }; if (v.type === "apiKey") { envKey = `header.${key}.API_KEY`; } else if (v.type === "http") { envKey = `header.${key}.HTTP.${v.scheme}`; if (v.scheme === "bearer" && envKey in envVars) { inputHeaders["Authorization"] = `Bearer ${envVars[envKey]}`; return; } } const envValue = getValFromNestedJson(envKey, envVars); if (envKey && envValue) { inputHeaders[key] = envValue; } } }); Object.entries(securityParams.header).forEach(([key]) => { const headerValue = envVars.header?.[key]; if (headerValue) { inputHeaders[key] = headerValue; } }); } } if (openApiPath.includes("PO") || openApiPath.includes("VRS")) { const clientId = typeof envVars.header?.["x-client-id"] === "string" ? envVars.header["x-client-id"] : ""; const publicKey = typeof envVars.TWO_FA_PUBLIC_KEY === "string" ? envVars.TWO_FA_PUBLIC_KEY : ""; inputHeaders["x-cf-signature"] = generateCfSignature( clientId, publicKey ); } const requestConfig = { method: methodSchema, url: urlWithPathParams, params: inputParams, data: inputBody, headers: inputHeaders, }; try { const response = await axios(requestConfig); // Stringify the response data let responseData = JSON.stringify(response.data, undefined, 2); responseData = responseData.replace( /("beneficiary_instrument_details"\s*:\s*)(\[[^\]]*\]|\{[^\}]*\})/gs, '$1"[MASKED]"' ); return { content: [ { type: "text", text: responseData, }, ], }; } catch (error) { if ( typeof error === "object" && error !== null && "config" in error && typeof (error as any).config === "object" && (error as any).config !== null && "headers" in (error as any).config ) { const errConfig = (error as any).config; ["x-client-id", "x-client-secret", "Authorization"].forEach( (header) => { if (errConfig.headers && errConfig.headers[header]) { errConfig.headers[header] = "[MASKED]"; } } ); } const errMsg = JSON.stringify(error, undefined, 2); const data = JSON.stringify( isAxiosError(error) && error.response ? error.response.data : {}, undefined, 2 ); return { isError: true, content: [ { type: "text", text: isAxiosError(error) ? `receivedPayload: ${data}\n\n errorMessage: ${error.message}\n\n${errMsg}` : `receivedPayload: ${data}\n\n errorMessage: ${errMsg}`, }, ], }; } } ); }); }

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/cashfree/cashfree-mcp'

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