Skip to main content
Glama
crazyrabbitLTC

Brex MCP Server

match_receipt

Generate a pre-signed URL to upload receipts for automatic matching with existing Brex expenses, simplifying expense reconciliation.

Instructions

Create a pre-signed URL for uploading a receipt that will be automatically matched with existing expenses

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
receipt_nameYesName of the receipt file (e.g., 'receipt.jpg')
receipt_typeNoType of the receipt (optional)
notify_emailNoEmail address to notify after matching (optional)

Implementation Reference

  • Core execution logic for the match_receipt tool: validates input, calls Brex API to create receipt match request, returns pre-signed upload URL and instructions.
    registerToolHandler("match_receipt", async (request: ToolCallRequest) => {
      try {
        // Validate parameters
        const params = validateParams(request.params.arguments);
        logDebug(`Creating receipt match for: ${params.receipt_name}`);
        
        // Get Brex client
        const brexClient = getBrexClient();
        
        try {
          // Create receipt match request to get pre-signed URL
          const matchResult = await createReceiptMatch(brexClient, {
            receipt_name: params.receipt_name,
            receipt_type: params.receipt_type,
            notify_email: params.notify_email
          });
          
          logDebug(`Successfully created receipt match with ID: ${matchResult.id}`);
          
          return {
            content: [{
              type: "text",
              text: JSON.stringify({
                status: "success",
                receipt_id: matchResult.id,
                upload_url: matchResult.uri,
                message: "Receipt match created successfully. Use the provided URL to upload the receipt file.",
                instructions: "1. Use this pre-signed URL with a PUT request to upload your receipt.\n2. The URL expires in 30 minutes.\n3. Once uploaded, Brex will automatically try to match the receipt with existing expenses."
              }, null, 2)
            }]
          };
        } catch (apiError) {
          logError(`Error creating receipt match: ${apiError instanceof Error ? apiError.message : String(apiError)}`);
          throw new Error(`Failed to create receipt match: ${apiError instanceof Error ? apiError.message : String(apiError)}`);
        }
      } catch (error) {
        logError(`Error in match_receipt tool: ${error instanceof Error ? error.message : String(error)}`);
        throw error;
      }
    });
  • MCP-exposed input schema for the match_receipt tool, defining parameters and requirements in the list tools response.
    {
      name: "match_receipt",
      description: "Create a pre-signed URL for uploading a receipt that will be automatically matched with existing expenses",
      inputSchema: {
        type: "object",
        properties: {
          receipt_name: {
            type: "string",
            description: "Name of the receipt file (e.g., 'receipt.jpg')"
          },
          receipt_type: {
            type: "string",
            description: "Type of the receipt (optional)"
          },
          notify_email: {
            type: "string",
            description: "Email address to notify after matching (optional)"
          }
        },
        required: ["receipt_name"]
      }
    },
  • Function that registers the match_receipt tool handler with the internal toolHandlers map.
    export function registerMatchReceipt(_server: Server): void {
      registerToolHandler("match_receipt", async (request: ToolCallRequest) => {
        try {
          // Validate parameters
          const params = validateParams(request.params.arguments);
          logDebug(`Creating receipt match for: ${params.receipt_name}`);
          
          // Get Brex client
          const brexClient = getBrexClient();
          
          try {
            // Create receipt match request to get pre-signed URL
            const matchResult = await createReceiptMatch(brexClient, {
              receipt_name: params.receipt_name,
              receipt_type: params.receipt_type,
              notify_email: params.notify_email
            });
            
            logDebug(`Successfully created receipt match with ID: ${matchResult.id}`);
            
            return {
              content: [{
                type: "text",
                text: JSON.stringify({
                  status: "success",
                  receipt_id: matchResult.id,
                  upload_url: matchResult.uri,
                  message: "Receipt match created successfully. Use the provided URL to upload the receipt file.",
                  instructions: "1. Use this pre-signed URL with a PUT request to upload your receipt.\n2. The URL expires in 30 minutes.\n3. Once uploaded, Brex will automatically try to match the receipt with existing expenses."
                }, null, 2)
              }]
            };
          } catch (apiError) {
            logError(`Error creating receipt match: ${apiError instanceof Error ? apiError.message : String(apiError)}`);
            throw new Error(`Failed to create receipt match: ${apiError instanceof Error ? apiError.message : String(apiError)}`);
          }
        } catch (error) {
          logError(`Error in match_receipt tool: ${error instanceof Error ? error.message : String(error)}`);
          throw error;
        }
      });
    } 
  • Top-level call to register the match_receipt tool during overall tools initialization.
    registerMatchReceipt(server);
  • TypeScript interface for input validation of match_receipt parameters.
    interface MatchReceiptParams {
      receipt_name: string;
      receipt_type?: string;
      notify_email?: string;
    }
  • Helper function to validate and type-check input parameters for the tool.
    function validateParams(input: any): MatchReceiptParams {
      if (!input) {
        throw new Error("Missing parameters");
      }
      
      if (!input.receipt_name) {
        throw new Error("Missing required parameter: receipt_name");
      }
      
      const params: MatchReceiptParams = {
        receipt_name: input.receipt_name,
        receipt_type: input.receipt_type,
        notify_email: input.notify_email
      };
      
      return params;
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full burden for behavioral disclosure. It mentions the creation of a pre-signed URL and automatic matching, but doesn't address important behavioral aspects like authentication requirements, rate limits, what happens after matching, whether this is a read-only or write operation, or error conditions. Significant gaps remain for a tool that presumably creates resources.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, well-structured sentence that efficiently communicates the core functionality. Every word earns its place - 'pre-signed URL' specifies the output type, 'uploading a receipt' specifies the action, and 'automatically matched with existing expenses' specifies the purpose. No wasted words or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 3 parameters, no annotations, and no output schema, the description provides adequate basic purpose but lacks important contextual information. It doesn't explain what the pre-signed URL looks like, what format the receipt should be in, how matching works, or what happens after matching. The description is complete enough to understand what the tool does but not how to use it effectively.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema description coverage, the input schema already documents all three parameters thoroughly. The description doesn't add any meaningful parameter semantics beyond what's in the schema - it doesn't explain how parameters affect the matching process, provide examples of receipt_type values, or clarify the notification workflow.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific action ('Create a pre-signed URL for uploading a receipt') and the outcome ('that will be automatically matched with existing expenses'), distinguishing it from the sibling 'upload_receipt' tool which lacks the matching functionality. The verb+resource combination is precise and unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage context for receipt matching with existing expenses, but doesn't explicitly state when to use this versus alternatives like 'upload_receipt' or when not to use it. The context is clear but lacks explicit sibling differentiation or exclusion criteria.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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

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