Skip to main content
Glama
metrxbots

Metrx MCP Server

by metrxbots

Set Budget

metrx_set_budget
Idempotent

Create or update budget configurations to enforce spending limits with configurable enforcement modes for agents or entire organizations.

Instructions

Create or update a budget configuration for an agent or the entire organization. Budgets enforce spending limits with configurable enforcement modes: "alert_only" (notify but don't block), "soft_block" (block with override), or "hard_block" (strict enforcement). Specify limits in dollars. Do NOT use just to change enforcement mode — use update_budget_mode for that.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
agent_idNoAgent to set budget for. Omit for org-wide budget.
periodYesBudget period
limit_dollarsYesSpending limit in dollars (e.g., 100 for $100/month)
warning_pctNoPercentage of limit that triggers a warning (default: 80)
enforcement_modeNoHow to enforce the budget when exceededalert_only

Implementation Reference

  • The set_budget tool registration and handler implementation. This is the core logic that creates or updates budget configurations. It handles the conversion from dollars to microcents, constructs the API request body, and returns formatted success/error messages.
    // ── set_budget ──
    server.registerTool(
      'set_budget',
      {
        title: 'Set Budget',
        description:
          'Create or update a budget configuration for an agent or the entire organization. ' +
          'Budgets enforce spending limits with configurable enforcement modes: ' +
          '"alert_only" (notify but don\'t block), "soft_block" (block with override), ' +
          'or "hard_block" (strict enforcement). Specify limits in dollars. ' +
          'Do NOT use just to change enforcement mode — use update_budget_mode for that.',
        inputSchema: {
          agent_id: z
            .string()
            .uuid()
            .optional()
            .describe('Agent to set budget for. Omit for org-wide budget.'),
          period: z.enum(['daily', 'monthly']).describe('Budget period'),
          limit_dollars: z
            .number()
            .positive()
            .describe('Spending limit in dollars (e.g., 100 for $100/month)'),
          warning_pct: z
            .number()
            .int()
            .min(1)
            .max(99)
            .default(80)
            .describe('Percentage of limit that triggers a warning (default: 80)'),
          enforcement_mode: z
            .enum(['alert_only', 'soft_block', 'hard_block'])
            .default('alert_only')
            .describe('How to enforce the budget when exceeded'),
        },
        annotations: {
          readOnlyHint: false,
          destructiveHint: false,
          idempotentHint: true,
          openWorldHint: false,
        },
      },
      async ({ agent_id, period, limit_dollars, warning_pct, enforcement_mode }) => {
        // Convert dollars to microcents (1 dollar = 100_000_000 microcents)
        const limit_microcents = Math.round(limit_dollars * 100_000_000);
    
        const body: Record<string, unknown> = {
          period,
          limit_microcents,
          warning_pct: warning_pct ?? 80,
          enforcement_mode: enforcement_mode ?? 'alert_only',
        };
        if (agent_id) body.agent_id = agent_id;
    
        const result = await client.post<BudgetConfig>('/budgets', body);
    
        if (result.error) {
          return {
            content: [{ type: 'text', text: `Error setting budget: ${result.error}` }],
            isError: true,
          };
        }
    
        const b = result.data!;
        const scope = b.agent_id ? `agent ${b.agent_id}` : 'organization';
    
        return {
          content: [
            {
              type: 'text',
              text: `✅ Budget set for ${scope}: ${formatMicrocents(b.limit_microcents)}/${
                b.period
              } with ${b.enforcement_mode} enforcement. Warning at ${b.warning_pct}%.`,
            },
          ],
        };
      }
    );
  • src/index.ts:74-103 (registration)
    The wrapper that adds the 'metrx_' prefix to all tool registrations. This is where 'set_budget' becomes 'metrx_set_budget'. Also includes rate limiting middleware and handler wrapping.
    // ── Rate limiting middleware + metrx_ namespace prefix ──
    // All tools are registered exclusively as metrx_{name}.
    // The metrx_ prefix namespaces our tools to avoid collisions when
    // multiple MCP servers are used together.
    const METRX_PREFIX = 'metrx_';
    const originalRegisterTool = server.registerTool.bind(server);
    (server as any).registerTool = function (
      name: string,
      config: any,
      handler: (...handlerArgs: any[]) => Promise<any>
    ) {
      const wrappedHandler = async (...handlerArgs: any[]) => {
        if (!rateLimiter.isAllowed(name)) {
          return {
            content: [
              {
                type: 'text' as const,
                text: `Rate limit exceeded for tool '${name}'. Maximum 60 requests per minute allowed.`,
              },
            ],
            isError: true,
          };
        }
        return handler(...handlerArgs);
      };
    
      // Register with metrx_ prefix (only — no deprecated aliases)
      const prefixedName = name.startsWith(METRX_PREFIX) ? name : `${METRX_PREFIX}${name}`;
      originalRegisterTool(prefixedName, config, wrappedHandler);
    };
  • The BudgetConfig interface defining the structure of budget configuration objects returned from the API, including id, period, limit_microcents, warning_pct, enforcement_mode, paused, and agent_id fields.
    export interface BudgetConfig {
      id: string;
      period: 'daily' | 'monthly';
      limit_microcents: number;
      warning_pct: number;
      enforcement_mode: 'alert_only' | 'soft_block' | 'hard_block';
      paused: boolean;
      agent_id: string | null;
    }
  • The input schema validation using Zod for the set_budget tool parameters: agent_id (optional UUID), period (enum: daily/monthly), limit_dollars (positive number), warning_pct (1-99, default 80), and enforcement_mode (enum: alert_only/soft_block/hard_block, default alert_only).
    inputSchema: {
      agent_id: z
        .string()
        .uuid()
        .optional()
        .describe('Agent to set budget for. Omit for org-wide budget.'),
      period: z.enum(['daily', 'monthly']).describe('Budget period'),
      limit_dollars: z
        .number()
        .positive()
        .describe('Spending limit in dollars (e.g., 100 for $100/month)'),
      warning_pct: z
        .number()
        .int()
        .min(1)
        .max(99)
        .default(80)
        .describe('Percentage of limit that triggers a warning (default: 80)'),
      enforcement_mode: z
        .enum(['alert_only', 'soft_block', 'hard_block'])
        .default('alert_only')
        .describe('How to enforce the budget when exceeded'),
    },
  • The formatMicrocents helper function used by the set_budget handler to convert microcents to dollar strings for user-friendly output formatting.
    export function formatMicrocents(microcents: number): string {
      return `$${(microcents / 100_000_000).toFixed(2)}`;
    }
Behavior4/5

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

The description adds valuable behavioral context beyond annotations: it explains the three enforcement modes ('alert_only', 'soft_block', 'hard_block') with brief descriptions of their effects, which is not covered by annotations. Annotations indicate it's a non-destructive, idempotent mutation (readOnlyHint: false, destructiveHint: false, idempotentHint: true), and the description aligns with this by describing a configuration update without contradictions.

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 front-loaded with the core purpose, followed by key details (enforcement modes, dollar limits) and a critical usage guideline. Every sentence earns its place by adding essential information without redundancy, making it efficient and well-structured for quick comprehension.

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

Completeness4/5

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

Given the tool's complexity (mutation with multiple parameters) and lack of output schema, the description is mostly complete: it covers purpose, usage guidelines, and key behavioral traits. However, it doesn't detail response format or error conditions, which could be helpful for an agent. Annotations provide safety context (non-destructive, idempotent), so the description compensates well but has minor gaps.

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%, so the schema fully documents all parameters. The description adds minimal parameter semantics beyond the schema: it mentions 'Specify limits in dollars' (implied by limit_dollars) and describes enforcement modes, but these are already in the schema's enum descriptions. Thus, it meets the baseline of 3 without significantly enhancing parameter understanding.

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 or update a budget configuration') and resource ('for an agent or the entire organization'), distinguishing it from sibling tools like 'metrx_update_budget_mode' by explicitly mentioning that tool for mode-only changes. It provides a comprehensive overview of what the tool does beyond just restating the name/title.

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

Usage Guidelines5/5

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

The description includes explicit guidance on when to use this tool vs. alternatives: it specifies 'Do NOT use just to change enforcement mode — use update_budget_mode for that,' naming the exact sibling tool for that purpose. This provides clear context for tool selection and helps avoid misuse.

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/metrxbots/metrx-mcp-server'

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