We raised a $50M Series B led by BenchmarkLearn more
Brex logo — MCP server on Gumloop

Brex

Manage your Brex cards, expenses, and spend.

Book a demo

Installation

Set up the Brex MCP server in Gumloop

Do this once to provision your hosted server URL.

1

Create a Gumloop account

To use this MCP, you need a Gumloop account. If you don't have one yet, sign up and start a 14-day free trial.

2

Add and authorize the Brex server

In Gumloop, open Connectors and add Brex. Depending on the app, you'll either sign in via OAuth or paste an API key. Either way, the credential is stored securely in Gumloop.

Then use it in your client

Use in GumloopUse in Gumloop
1

Use Brex in an agent

Once Brex is set up, just open any Gumloop agent, add Brex as a connector, and start chatting with the agent.

Tools (29)

  • Get User By Id

    Get a user by their unique ID This tool retrieves detailed information about a specific user using their unique user ID. Use this when you have a user ID and need to get their complete profile information. Example Input: { "id": "cuuser_123" } Example Output: { "id": "cuuser_123", "first_name": "John", "last_name": "Doe", "email": "john.doe@example.com", "role": "CARD_ADMIN", "status": "ACTIVE", "manager_id": "cuuser_5678", "manager_first_name": "Jane", "manager_last_name": "Smith", "manager_title_id": "ti_1234", "manager_title_name": "Engineering Manager", "department_id": "cudmnt_1234", "department_name": "Engineering", "location_id": "culoc_1234", "location_name": "San Francisco", "title_id": "ti_5678", "title_name": "Software Engineer" }

  • List Users By Name Or Email

    List users by name or email This tool allows you to search for users by name or email. It will return a paginated list of up to 10 users that match the search criteria, sorted by first name. If you only have the name or email, you can use this tool to find the user ID and their full details. Example Input 1 (search by name): { "search_text": "John Smith" } Example Input 2 (search by email): { "search_text": "john.smith@example.com" } Example Output: { "items": [ { "id": "cuuser_123", "first_name": "John", "last_name": "Smith", "email": "john.smith@example.com", "role": "CARD_ADMIN", "status": "ACTIVE" } ], "next_cursor": "cursor_1234" }

  • List Users

    List users with optional filtering and pagination. â„šī¸ Response narrowing for non-admin callers: callers without the `user.list` operation permission receive the same users, but with `email`, `phone_number`, `location_id`, and `location_name` omitted. Names, titles, departments, managers, roles, and status are always returned. Use this tool freely for discovery (e.g. picking attendees); fall back to `get_user_myself` when the caller needs their own contact info. 🚨 CRITICAL — ID filters REQUIRE companion discovery tools FIRST 🚨 The following filters accept ONLY Brex resource IDs (never names, labels, or human-readable strings). If the user describes a filter in plain English (e.g. "Engineering department", "San Francisco office", "Brex Inc. entity", "Software Engineer title", "R&D cost center", "bill pay approvers", "card admins", "reports to Jane Smith"), you MUST call the matching discovery tool first to resolve that string into an ID, then pass the ID here. DO NOT guess IDs. DO NOT pass the human-readable name directly. DO NOT silently drop the filter — always resolve it. Filter → required discovery tool (ALWAYS call the discovery tool first when the user gives you a name instead of an ID): â€ĸ department → list_departments (IDs look like cudmnt_...) â€ĸ location → list_locations (IDs look like culoc_...) â€ĸ cost_center → list_cost_centers (IDs look like cc_...) â€ĸ entity → list_legal_entities (IDs look like le_...) â€ĸ title → list_titles (IDs look like ti_...) â€ĸ role → list_roles with role_type=["FUNCTIONAL"] (IDs look like role_... or aurl_...) â€ĸ access → list_roles with role_type=["ACCESS"] (IDs look like role_... or aurl_...) â€ĸ manager → list_users_by_name_or_email (IDs look like cuuser_...) Decision rule: if the user says a NAME, call the discovery tool; pass only the returned ID(s) into list_users. If the user already supplied an ID with the expected prefix, skip discovery and pass it straight through. ✅ Pagination & sorting (no discovery needed): - cursor: Pagination cursor returned from a previous response. - limit: Number of users to return (1-1000, default: 100). - direction / sort: Sort direction ("asc"/"desc") and field (FIRST_NAME, LAST_NAME, EMAIL, ...). ✅ Enum filters (values listed inline — no discovery tool needed): - status: Array of UserStatus (INVITED, PENDING_ACTIVATION, ACTIVE, INACTIVE, DISABLED, ARCHIVED). Defaults to [INVITED, PENDING_ACTIVATION, ACTIVE, INACTIVE] if omitted. - admin_role: Single value of "ADMINS" | "NON_ADMINS" | "ALL". âš ī¸ When combining filters (e.g. "active users in Finance"), you MUST still resolve every name-based filter via its discovery tool AND include all requested filters in the final list_users call. Never drop a filter just because another filter was already applied. Example Input 1 (basic, with defaults): {} Example Input 2 (filter by department and role — department and role were resolved via list_departments and list_roles first): { "department": ["cudmnt_1234"], "role": ["role_5678"], "status": ["ACTIVE"] } Example Input 3 (sort descending by last name, paginated): { "limit": 50, "direction": "desc", "sort": "LAST_NAME", "cursor": "cursor_1234" } Example Output: { "items": [ { "id": "cuuser_123", "first_name": "John", "last_name": "Doe", "email": "john.doe@example.com", "role": "CARD_ADMIN", "status": "ACTIVE" } ], "next_cursor": "cursor_5678" }

  • Get User Myself

    Get the current authenticated user This tool retrieves the profile information of the currently authenticated user making the request. Use this when you need to get information about who is currently logged in or making the API call. No input parameters required. Example Output: { "id": "cuuser_123", "first_name": "John", "last_name": "Doe", "email": "john.doe@example.com", "role": "CARD_ADMIN", "status": "ACTIVE" }

  • List Cost Centers

    List cost centers (id + display name). REQUIRED prerequisite for the list_users `cost_center` filter: list_users only accepts cost center IDs, so whenever the user mentions a cost center by name (e.g. "R&D", "Sales"), call this tool first and pass the returned `id` into list_users. Parameters: limit (1-200, default 25), cursor (pagination), search_text (narrow by name). Example Output: { "items": [{ "id": "cc_1234", "name": "Engineering" }], "next_cursor": "cursor_abc" }

  • List Departments

    List departments (id + name). REQUIRED prerequisite for the list_users `department` filter: list_users only accepts department IDs, so whenever the user mentions a department by name (e.g. "Engineering", "Finance"), call this tool first and pass the returned `id` into list_users. Parameters: limit (1-200, default 25), cursor (pagination), search_text (narrow by name). Example Output: { "items": [{ "id": "cudmnt_1234", "name": "Engineering" }], "next_cursor": "cursor_abc" }

  • List Locations

    List locations (id + name). Deleted locations are excluded. REQUIRED prerequisite for the list_users `location` filter: list_users only accepts location IDs, so whenever the user mentions a location by name (e.g. "San Francisco", "New York"), call this tool first and pass the returned `id` into list_users. Parameters: limit (1-200, default 25), cursor (pagination), search_text (narrow by name). Example Output: { "items": [{ "id": "culoc_1234", "name": "San Francisco" }], "next_cursor": "cursor_abc" }

  • List Legal Entities

    List legal entities (id + display name). Deleted entities are excluded. REQUIRED prerequisite for the list_users `entity` filter: list_users only accepts legal entity IDs, so whenever the user mentions a legal entity by name (e.g. "Brex Inc.", "Brex UK Ltd."), call this tool first and pass the returned `id` into list_users. Parameters: limit (1-200, default 25), cursor (pagination), search_text (narrow by display name). Example Output: { "items": [{ "id": "le_1234", "name": "Brex Inc." }], "next_cursor": "cursor_abc" }

  • List Titles

    List employee titles (id + display title). REQUIRED prerequisite for the list_users `title` filter: list_users only accepts title IDs, so whenever the user mentions a title by name (e.g. "Software Engineer", "Product Manager"), call this tool first and pass the returned `id` into list_users. Parameters: limit (1-200, default 25), cursor (pagination), search_text (narrow by title name). Example Output: { "items": [{ "id": "ti_1234", "name": "Software Engineer" }], "next_cursor": "cursor_abc" }

  • List Roles

    List Brex account roles. REQUIRED prerequisite for the list_users `role` and `access` filters: list_users only accepts role IDs, so whenever the user mentions a role or access type by name (e.g. "card admin", "employee", "bill pay approver", "card access"), call this tool first and pass the returned `id` into list_users. Roles have two types: - FUNCTIONAL ("what the user is" — CARD_ADMIN, EMPLOYEE, ACCOUNT_ADMIN, ...). These IDs feed the list_users `role` filter. - ACCESS ("what the user can do" — card access, bill pay approver, travel admin, ...). These IDs feed the list_users `access` filter. Pass role_type=["FUNCTIONAL"] to resolve names for the `role` filter, role_type=["ACCESS"] to resolve names for the `access` filter, or omit to return both. For FUNCTIONAL roles, is_admin=true indicates the role grants admin-level access. Parameters: limit (1-200, default 100), cursor (pagination), role_type (filter by type). Example Output: { "items": [ { "id": "role_1234", "name": "CARD_ADMIN", "display_name": "Card Admin", "role_type": "FUNCTIONAL", "is_admin": true } ], "next_cursor": null }

  • Get Expense By Id

    Get an expense by its ID Expand (receipt details): - expand: Use ["RECEIPTS"] to include full receipt details. WITHOUT expand, receipts only contain IDs. WITH expand: ["RECEIPTS"], each receipt includes: * asset_id - FileStore asset ID for the receipt file * download_uri - URL to download the receipt file/image * content.is_real_receipt - whether the file is classified as a real receipt * content.merchant_name - merchant name parsed from the receipt * content.purchased_at - purchase date parsed from the receipt * content.amount - amount parsed from the receipt * content.line_items - itemized charges from the receipt (name, quantity, unit_price, total) âš ī¸ When the user asks ANYTHING about receipts on this expense — including: receipt line items, itemized charges, "what did I buy", receipt content, receipt images/downloads, parsed receipt data, whether a receipt is attached/uploaded ("did the receipt come in", "is there a receipt", "do I have a receipt for this"), or receipt counts ("how many receipts") — you MUST include expand: ["RECEIPTS"]. Without expand, the response's `receipt_count` is null and `receipts` may only contain bare IDs, so questions about receipt presence or quantity cannot be answered. A receipt with only an ID and no content/download_uri means expand was NOT used — re-call with expand: ["RECEIPTS"]. Additional Fields: - additional_fields: Array of optional fields to include in response. Supported values: * "TRAVEL_METADATA" - Includes flight, car rental, lodging, and train travel data * "LOCATION" - Includes expense location details (country, city, coordinates, etc.) * "ACCOUNTING_FIELDS" - Includes accounting_field_values, the accounting coding fields assigned to the expense for accounting categorization and bookkeeping (for example department, class, vendor, or customer-defined accounting fields). IMPORTANT: Location and travel data are ALWAYS null unless you explicitly request them via additional_fields. A null location does NOT mean "no location exists" - it means you did not request it. If the user asks about where an expense occurred, you MUST call this tool again with additional_fields: ["LOCATION"]. Same for travel - use additional_fields: ["TRAVEL_METADATA"]. Example 1: Getting an expense with expanded receipts (includes line items, download URL, parsed content): { "id": "expense_123", "expand": ["RECEIPTS"] } Example 2: Getting an expense with travel metadata and location: { "id": "expense_123", "additional_fields": ["TRAVEL_METADATA", "LOCATION"] } Example 3: Getting an expense with everything: { "id": "expense_123", "expand": ["RECEIPTS"], "additional_fields": ["TRAVEL_METADATA", "LOCATION"] } Understanding Expense Lifecycle and Compliance Status: Expense Lifecycle: 1. New expense created (card transaction or reimbursement submitted) 2. Documentation phase: System checks if documentation is required (receipts, memo, attendees, etc.) 3. Spender submits documentation if needed 4. Review phase: System checks if approval/review is required based on company policy 5. Reviewer reviews and approves/rejects if necessary 6. Expense is finalized Each expense returns TWO sets of compliance-related fields: A. DOCUMENTATION COMPLIANCE (for spenders - receipts, memo, attendees): - documentationComplianceStatus: Status of documentation requirements that the spender must fulfill * "NOT_REQUIRED" - Company policy does not require any documentation for this expense. Empty receipts/memo are acceptable. * "COMPLETED" - All required documentation has been provided according to policy. * "DUE" - Documentation is required by policy but not yet provided. Check missingDocumentations field for specifics. * "OVERDUE" - Required documentation is past its submission deadline. Check missingDocumentations field for specifics. - missingDocumentations: Array of specific items required by policy but not yet provided. Possible values: ["MEMO", "RECEIPT", "ATTENDEES", "EXTENDED_FIELD"] * Empty array [] - Either no documentation is required OR all required documentation is complete * Non-empty array - Lists specific items that must be provided (e.g., ["MEMO", "RECEIPT"]) - documentationSubmissionDeadline: The UTC timestamp by which documentation must be submitted (only present if documentation is required) B. REVIEW COMPLIANCE (for reviewers - approval/rejection): - reviewComplianceStatus: Status of review/approval requirements that the reviewer must fulfill * "NOT_REQUIRED" - Company policy does not require review/approval for this expense. * "COMPLETED" - The expense has been reviewed and approved/rejected. * "DUE" - Review is required by policy but not yet completed. * "OVERDUE" - Required review is past its deadline. - reviewDeadline: The UTC timestamp by which the review must be completed (only present if review is required) KEY DISTINCTIONS: - DocumentationComplianceStatus="NOT_REQUIRED" and missingDocumentations=[] → Documentation not required by company policy - Empty receipts/memo with documentationComplianceStatus="DUE" or "OVERDUE" and missingDocumentations=["RECEIPT","MEMO"] → Documentation IS required by policy but missing - reviewComplianceStatus="DUE" or "OVERDUE" → Expense is waiting for someone to review/approve it - reviewComplianceStatus="NOT_REQUIRED" → No approval needed

  • Update Expense Memo

    Update memo for multiple expenses in bulk. All expenses will receive the same memo. Parameters: - expense_ids: Array of expense IDs to update - memo: The memo text to apply to all expenses Example (single expense): { "expense_ids": ["exp_123"], "memo": "Business lunch with client" } Example (multiple expenses with same memo): { "expense_ids": ["exp_123", "exp_456", "exp_789"], "memo": "Q1 team building event" }

Ship Brex agents in minutes

Connect any AI agent to 100+ MCP servers, zero setup.
Book a demo
Gradient