Skip to main content
Glama
dennisonbertram

Brex MCP Server

expenses.ts3.09 kB
/** * @file Expenses Resource Handler * @version 1.0.0 * @description Handles Brex expenses resource requests */ import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { ResourceTemplate } from "../models/resourceTemplate.js"; import { logDebug, logError } from "../utils/logger.js"; import { BrexClient } from "../services/brex/client.js"; import { isExpense, ListExpensesParams } from "../services/brex/expenses-types.js"; import { parseQueryParams } from "../models/common.js"; import { limitExpensesPayload } from "../utils/responseLimiter.js"; // Get Brex client function getBrexClient(): BrexClient { return new BrexClient(); } // Define expenses resource template const expensesTemplate = new ResourceTemplate("brex://expenses{/id}"); /** Capability only (optional) */ export function registerExpensesCapabilities(server: Server): void { server.registerCapabilities({ resources: { "brex://expenses{/id}": { description: "Brex expenses (list or by ID); supports fields & summary_only", mimeTypes: ["application/json"], } } }); } export function canHandleExpensesUri(uri: string): boolean { return uri.startsWith("brex://expenses") && !uri.includes("/card"); } export async function readExpensesUri(uri: string): Promise<any> { logDebug(`Reading expenses resource: ${uri}`); const brexClient = getBrexClient(); const params = expensesTemplate.parse(uri); if (!params.id) { try { const listParams: ListExpensesParams = { limit: 50, expand: ['merchant', 'budget'] }; const expenses = await brexClient.getExpenses(listParams); const qp = parseQueryParams(uri); const fields = qp.fields ? qp.fields.split(',').map(s => s.trim()).filter(Boolean) : undefined; const summaryOnly = qp.summary_only === 'true'; const limited = limitExpensesPayload(expenses.items as any, { summaryOnly, fields, hardTokenLimit: 24000 }); return { contents: [{ uri, mimeType: 'application/json', text: JSON.stringify(limited.items, null, 2) }] } as any; } catch (error) { logError(`Failed to fetch expenses: ${error instanceof Error ? error.message : String(error)}`); throw error; } } else { try { const expense = await brexClient.getExpense(params.id, { expand: ['merchant','budget','location','department','receipts.download_uris'], load_custom_fields: true }); if (!isExpense(expense)) throw new Error('Invalid expense data received'); const qp = parseQueryParams(uri); const fields = qp.fields ? qp.fields.split(',').map(s => s.trim()).filter(Boolean) : undefined; const summaryOnly = qp.summary_only === 'true'; const limited = limitExpensesPayload([expense] as any, { summaryOnly, fields, hardTokenLimit: 24000 }); return { contents: [{ uri, mimeType: 'application/json', text: JSON.stringify(limited.items[0] || {}, null, 2) }] } as any; } catch (error) { logError(`Failed to fetch expense ${params.id}: ${error instanceof Error ? error.message : String(error)}`); throw error; } } }

Latest Blog Posts

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/dennisonbertram/mcp-brex'

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