mercury_list_cards
List all physical and virtual cards (debit, virtual, IO Credit) for a Mercury account. Returns card ID, last4, type, status, holder, and expiry to support spend audits and freeze reviews.
Instructions
List physical and virtual cards attached to a Mercury account.
USE WHEN: enumerating cards (debit, virtual debit, IO Credit) issued against an account — for spend audits, freezing review, or cardholder lookups.
DO NOT USE: to list IO Credit transactions (use mercury_list_credit_transactions). Card creation, freezing, and PIN ops are not exposed by this MCP — the Mercury API does not currently support them.
RETURNS: { cards: [{ id, last4, type, status, holderName, expiry, ... }] }.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| accountId | Yes | The Mercury account ID |
Implementation Reference
- src/tools/cards.ts:6-28 (handler)The handler/registration for the mercury_list_cards tool. Defines the tool with a Zod schema accepting an accountId (UUID), makes a GET request to /account/{accountId}/cards via the MercuryClient, and returns the JSON result.
export function registerCardTools(server: McpServer, client: MercuryClient): void { defineTool( server, "mercury_list_cards", [ "List physical and virtual cards attached to a Mercury account.", "", "USE WHEN: enumerating cards (debit, virtual debit, IO Credit) issued against an account — for spend audits, freezing review, or cardholder lookups.", "", "DO NOT USE: to list IO Credit transactions (use `mercury_list_credit_transactions`). Card creation, freezing, and PIN ops are not exposed by this MCP — the Mercury API does not currently support them.", "", "RETURNS: `{ cards: [{ id, last4, type, status, holderName, expiry, ... }] }`.", ].join("\n"), { accountId: z.uuid().describe("The Mercury account ID"), }, async ({ accountId }) => { const data = await client.get(`/account/${accountId}/cards`); return textResult(data); }, { title: "List Cards", readOnlyHint: true, openWorldHint: true }, ); } - src/tools/cards.ts:1-4 (registration)Imports for the cards tool file. The registerCardTools function is called from src/tools/index.ts (line 23) to register mercury_list_cards on the MCP server.
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { defineTool, textResult } from "./_shared.js"; import { z } from "zod"; import { MercuryClient } from "../client.js"; - src/tools/_shared.ts:28-54 (helper)The defineTool helper function used by mercury_list_cards to register itself on the McpServer with schema, handler, and annotations. Wraps the handler with rate-limit/audit middleware.
export function defineTool<S extends ZodRawShape>( server: McpServer, name: string, description: string, inputSchema: S, handler: (args: z.infer<z.ZodObject<S>>) => Promise<ToolResult>, annotations: ToolAnnotations, ): void { const wrapped = wrapToolHandler(name, handler); const strictSchema = z.object(inputSchema).strict(); // MCP behavioral annotations (readOnlyHint / destructiveHint / // idempotentHint / openWorldHint) — declared machine-readable so // hosts and rubrics (TDQS / Glama Behavior dimension) can detect // tool semantics without scraping the prose description. Required // (not optional) so every new tool ships with explicit semantics — // forgetting the annotation now fails typecheck instead of // silently shipping a tool with no hint set. // The MCP SDK overloads `registerTool` with shape narrowing the runtime // strict-schema and the wrapped callback can't satisfy through generics. // Both casts are runtime-safe — the signatures only diverge at the type // level. Asserted by the existing tool-registration tests. (server.registerTool as unknown as (...a: unknown[]) => unknown)( name, { description, inputSchema: strictSchema, annotations }, wrapped, ); } - src/tools/_shared.ts:16-26 (helper)The textResult helper used by the handler to format the API response as a ToolResult with sanitized JSON.
export function textResult(data: unknown): ToolResult { // Walk the payload once, reuse the sanitized value for both the // LLM-display JSON string and the `structuredContent` object. // Calling sanitizeJsonForLlm(data) + sanitizeJsonValues(data) // separately would run the walker twice on the same input. const sanitized = sanitizeJsonValues(data); return { content: [{ type: "text", text: JSON.stringify(sanitized, null, 2) }], structuredContent: (sanitized ?? {}) as Record<string, unknown>, }; } - src/client.ts:150-153 (helper)The MercuryClient.get method called by the handler (client.get('/account/{accountId}/cards')).
// Convenience helpers get<T = unknown>(path: string, query?: Record<string, string | number | undefined>) { return this.request<T>("GET", path, { query }); }