Get merchant metrics
deonpay_get_merchant_metricsFetch key business metrics including revenue, transactions, subscriptions snapshot, and revenue mix, with configurable time period.
Instructions
Fetch a curated set of business metrics for the merchant. Use this as the FIRST tool for high-level questions: 'how much have I sold this month', 'what is my MRR', 'how is my conversion rate trending', 'how many active subscribers do I have'. Returns: revenue (gross/net/refunded in centavos), transactions (total/successful/failed/conversion_rate as %/average_ticket in centavos), subscriptions snapshot (active_subscribers, trialing_subscribers, past_due, mrr in centavos, churn_rate as %), and revenue_mix (recurring vs one_time, in centavos). IMPORTANT: subscriptions.active/trialing/past_due AND mrr are SNAPSHOTS — they ignore period. mrr is always a 30-day run-rate. revenue, transactions, churn_rate and revenue_mix DO honor period.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| period | No | Time window. Default '30d'. 'all' goes back to epoch. | |
| environment | No | Override the environment to query. The DeonPay API only honors this if it matches the environment baked into the API token; otherwise it is silently ignored. Useful when the same dashboard exposes both envs. |
Implementation Reference
- src/tools/metrics.ts:32-34 (handler)The actual handler logic for the 'deonpay_get_merchant_metrics' tool. It calls client.get('/merchant/metrics', compact(args)) which sends a GET request to the DeonPay API endpoint /api/v1/merchant/metrics with query parameters (period, environment) stripped of undefined/null values.
safeHandler(async (args) => { return client.get("/merchant/metrics", compact(args)); }), - src/tools/metrics.ts:20-31 (schema)Input schema for the tool: an optional 'period' enum (today, 7d, 30d, 90d, ytd, all) and an optional 'environment' (sandbox, production) from the shared EnvironmentSchema.
{ title: "Get merchant metrics", description: "Fetch a curated set of business metrics for the merchant. Use this as the FIRST tool for high-level questions: 'how much have I sold this month', 'what is my MRR', 'how is my conversion rate trending', 'how many active subscribers do I have'. Returns: revenue (gross/net/refunded in centavos), transactions (total/successful/failed/conversion_rate as %/average_ticket in centavos), subscriptions snapshot (active_subscribers, trialing_subscribers, past_due, mrr in centavos, churn_rate as %), and revenue_mix (recurring vs one_time, in centavos). IMPORTANT: subscriptions.active/trialing/past_due AND mrr are SNAPSHOTS — they ignore `period`. mrr is always a 30-day run-rate. revenue, transactions, churn_rate and revenue_mix DO honor `period`.", inputSchema: { period: z .enum(["today", "7d", "30d", "90d", "ytd", "all"]) .optional() .describe("Time window. Default '30d'. 'all' goes back to epoch."), environment: EnvironmentSchema.optional(), }, }, - src/tools/index.ts:18-28 (registration)The tool is registered via registerMetricsTools(server, client) which is called from registerAllTools, the central registry that wires all tool modules into the MCP server.
import { registerMetricsTools } from "./metrics.js"; export function registerAllTools(server: McpServer, client: DeonpayClient): void { registerLinkTools(server, client); registerCheckoutTools(server, client); registerTransactionTools(server, client); registerProductTools(server, client); registerSubscriptionTools(server, client); registerCustomerSubscriptionTools(server, client); registerCustomerTools(server, client); registerMetricsTools(server, client); - src/tools/_helpers.ts:83-91 (helper)The 'compact' helper removes undefined/null/empty-string fields from the args object before sending as query parameters, ensuring the API defaults are honored.
export function compact<T extends Record<string, unknown>>(obj: T): Partial<T> { const out: Record<string, unknown> = {}; for (const [key, value] of Object.entries(obj)) { if (value === undefined || value === null) continue; if (typeof value === "string" && value.trim() === "") continue; out[key] = value; } return out as Partial<T>; } - src/tools/_helpers.ts:57-68 (helper)The 'safeHandler' wrapper catches any thrown errors and converts them into MCP-shaped error results so the LLM receives a clear error message.
export function safeHandler<TArgs>( fn: (args: TArgs) => Promise<unknown>, ): (args: TArgs) => Promise<CallToolResult> { return async (args: TArgs) => { try { const value = await fn(args); return jsonResult(value); } catch (err) { return errorResult(err); } }; }