Skip to main content
Glama
whitebirchio

Monarch Money MCP Server

by whitebirchio

search_transactions

Find financial transactions by description, merchant, or amount range using Monarch Money's data. Filter and retrieve specific transaction records to analyze spending patterns.

Instructions

Search transactions by description, merchant, or amount

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryNoSearch query for transaction description or merchant
minAmountNoMinimum transaction amount
maxAmountNoMaximum transaction amount
limitNoNumber of results to return (default: 50)

Implementation Reference

  • The main handler function searchTransactions() that implements the search logic - fetches transactions, filters by query (merchant, notes, plaidName), minAmount, maxAmount, and returns limited results
    private async searchTransactions(args: any): Promise<any> {
      try {
        const limit = args.limit || 50;
        const transactions = await this.api.getTransactions({ limit: 1000 }); // Get more to search through
    
        let filteredTransactions = transactions || [];
    
        if (args.query) {
          const query = args.query.toLowerCase();
          filteredTransactions = filteredTransactions.filter(
            (t: Transaction) =>
              t.plaidName?.toLowerCase().includes(query) ||
              t.notes?.toLowerCase().includes(query) ||
              t.merchant?.name?.toLowerCase().includes(query)
          );
        }
    
        if (args.minAmount !== undefined) {
          filteredTransactions = filteredTransactions.filter(
            (t: Transaction) => Math.abs(t.amount) >= args.minAmount
          );
        }
    
        if (args.maxAmount !== undefined) {
          filteredTransactions = filteredTransactions.filter(
            (t: Transaction) => Math.abs(t.amount) <= args.maxAmount
          );
        }
    
        const results = filteredTransactions.slice(0, limit);
    
        return {
          success: true,
          data: results,
          summary: `Found ${results.length} transactions matching criteria`,
        };
      } catch (error) {
        throw new Error(
          `Failed to search transactions: ${
            error instanceof Error ? error.message : 'Unknown error'
          }`
        );
      }
    }
  • src/tools.ts:95-121 (registration)
    Tool definition/registration in getToolDefinitions() specifying name, description, and inputSchema with properties for query, minAmount, maxAmount, and limit
      name: 'search_transactions',
      description: 'Search transactions by description, merchant, or amount',
      inputSchema: {
        type: 'object',
        properties: {
          query: {
            type: 'string',
            description:
              'Search query for transaction description or merchant',
          },
          minAmount: {
            type: 'number',
            description: 'Minimum transaction amount',
          },
          maxAmount: {
            type: 'number',
            description: 'Maximum transaction amount',
          },
          limit: {
            type: 'number',
            description: 'Number of results to return (default: 50)',
            default: 50,
          },
        },
        required: [],
      },
    },
  • src/tools.ts:221-222 (registration)
    Switch case in executeTool() that routes 'search_transactions' tool calls to the searchTransactions handler method
    case 'search_transactions':
      return await this.searchTransactions(args);
  • Helper API method getTransactions() that fetches transactions from Monarch Money GraphQL API with optional filters for limit, accountId, startDate, and endDate
    async getTransactions(
      options: {
        limit?: number;
        accountId?: string;
        startDate?: string;
        endDate?: string;
        offset?: number;
      } = {}
    ): Promise<Transaction[]> {
      const { limit = 100, accountId, startDate, endDate, offset = 0 } = options;
    
      const query = `
        query GetTransactionsList($offset: Int, $limit: Int, $filters: TransactionFilterInput, $orderBy: TransactionOrdering) {
          allTransactions(filters: $filters) {
            totalCount
            results(offset: $offset, limit: $limit, orderBy: $orderBy) {
              id
              amount
              pending
              date
              plaidName
              notes
              category {
                id
                name
                __typename
              }
              merchant {
                name
                id
                __typename
              }
              account {
                id
                displayName
              }
              __typename
            }
            __typename
          }
        }
      `;
    
      const variables: any = {
        offset,
        limit,
        filters: {},
        orderBy: 'date',
      };
    
      if (accountId) variables.filters.accountId = accountId;
      if (startDate) variables.filters.startDate = startDate;
      if (endDate) variables.filters.endDate = endDate;
    
      try {
        const data: any = await this.graphQLClient.request(query, variables);
        return data.allTransactions?.results || [];
      } catch (error: any) {
        if (
          error.message.includes('401') ||
          error.message.includes('unauthorized')
        ) {
          throw new Error(
            'Authentication failed. Please check your MONARCH_TOKEN environment variable.'
          );
        }
        throw new Error(`Failed to get transactions: ${error.message}`);
      }
    }
  • Transaction interface type definition that defines the structure of transaction objects including id, amount, date, plaidName, notes, merchant, and account fields used throughout the search implementation
    export interface Transaction {
      id: string;
      amount: number;
      date: string;
      plaidName?: string;
      notes?: string;
      pending?: boolean;
      category?: {
        id: string;
        name: string;
      };
      merchant?: {
        id: string;
        name: string;
      };
      account: {
        id: string;
        displayName: string;
      };
    }
Behavior2/5

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

No annotations are provided, so the description carries the full burden of behavioral disclosure. While 'Search' implies a read operation, the description doesn't address important behavioral aspects like whether this is a filtered subset of 'get_transactions', what authentication is required, whether there are rate limits, what the return format looks like, or how results are ordered. For a search tool with zero annotation coverage, this is inadequate.

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, efficient sentence that communicates the core functionality without unnecessary words. It's appropriately sized for a search tool and front-loads the essential information. Every word earns its place in this concise formulation.

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

Completeness2/5

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

Given the complexity of a search operation with four parameters, no annotations, and no output schema, the description is incomplete. It doesn't explain what the tool returns, how results are structured, whether there's pagination, or how the search logic works (exact match, partial match, etc.). For a search tool in a financial context with multiple sibling tools, more contextual information would be helpful.

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?

Schema description coverage is 100%, with all four parameters well-documented in the input schema. The description adds minimal value by mentioning 'description, merchant, or amount' which corresponds to the query and amount parameters, but doesn't provide additional context beyond what's already in the schema descriptions. This meets the baseline for high schema coverage.

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

Purpose4/5

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

The description clearly states the tool's purpose with a specific verb ('Search') and resource ('transactions'), and specifies searchable fields (description, merchant, amount). However, it doesn't distinguish this tool from its sibling 'get_transactions', which appears to be a similar transaction retrieval tool. The description is specific about what can be searched but lacks sibling differentiation.

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

Usage Guidelines2/5

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

The description provides no guidance on when to use this tool versus alternatives like 'get_transactions' or other sibling tools. There's no mention of prerequisites, use cases, or exclusions. The agent must infer usage from the name and description alone without explicit context about when this search tool is preferable to a simple get operation.

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/whitebirchio/monarch-mcp'

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