Skip to Content
APIs & ToolsMCPBest Practices

Admin MCP Best Practices

Building production-grade AI agents that operate a Finqu merchant store requires careful channel context management, safety gates, robust error recovery, and clear prompt instructions. This guide outlines standard practices for building resilient agent workflows on Admin MCP.

Channel Resolution

Finqu stores operate across multiple sales channels (online webstores, point-of-sale registers, feeds, and partner marketplaces). Because products, themes, and navigation can vary by channel, many admin tools require a channel_id parameter.

Discovery and session caching

At the start of every agent session:

  1. Call list_channels to discover all available channels.
  2. Filter channels by type and identify the primary channel for the user’s intent.
  3. Cache the selected channel_id in the agent’s context window or session state.
{ "merchant_id": 42, "channels": [ { "id": 101, "name": "Flagship Webstore", "type": "webstore", "store": { "url": "https://example.com" } }, { "id": 102, "name": "Downtown POS", "type": "pos", "store": {} } ] }

Channel type compatibility

Different tool groups enforce channel type constraints:

Tool GroupSupported Channel TypesNotes
Theme & Template toolswebstoreLiquid templates, section groups, and theme settings only apply to online storefronts
Navigation & PageswebstoreMenu links, CMS pages, and blog articles belong to a webstore
Marketing & Socialwebstore, posMarketing messages and social media posts support both web and physical channels
Catalog & InventoryAny channelProducts, variants, and stock levels are merchant-wide but can have channel-specific pricing/visibility

Passing a non-webstore channel_id to a theme tool produces an error:

Validation Error: The specified channel (ID: 102) is of type 'pos'. Theme tools require a 'webstore' channel.

If the merchant has multiple webstore channels and the user’s intent does not specify one, your agent should list the matching channels and ask the user to clarify before proceeding.

Safety and Confirmation Gates

Admin agents hold write access to real commerce operations. Unchecked automation can lead to lost revenue, broken storefront layouts, or deleted customer data.

Categorize operations by risk

Separate tools into read, low-risk mutation, and high-risk destructive operations:

Low Risk (Autonomous Execution Allowed) ├── Read tools: search_products, get_order, list_channels, get_theme_file └── Low-impact mutations: add_order_note, tag_customer, create_draft_product High Risk (Require Human Confirmation) ├── Catalog: delete_product, delete_variant, bulk_update_prices, unpublish_product ├── Orders & Finances: cancel_order, issue_refund, create_manual_charge ├── Storefront & Brand: update_theme_file, delete_theme_section, modify_store_settings └── Inventory: adjust_inventory_level, finalize_stock_transfer

Implement confirmation prompts

For any high-risk action, prompt the user with a structured change summary before executing the tool:

interface ActionProposal { tool: string; resourceId: string | number; action: "delete" | "update" | "refund" | "unpublish"; summary: string; changes: Record<string, { current: unknown; proposed: unknown }>; } function formatConfirmationPrompt(proposal: ActionProposal): string { return [ `Action proposal: ${proposal.action} ${proposal.tool}:`, `- Target: ${proposal.resourceId}`, `- Summary: ${proposal.summary}`, "- Changes:", ...Object.entries(proposal.changes).map( ([field, { current, proposed }]) => ` * ${field}: ${JSON.stringify(current)} -> ${JSON.stringify(proposed)}` ), "", "Proceed with this update? (yes/no)", ].join("\n"); }

Do not execute the mutation tool until the user sends an explicit affirmative response.

Error Recovery and Suggestions

Admin MCP tool errors provide structured JSON payloads designed for autonomous agent self-correction.

Structure of an error response

When a tool fails, Admin MCP sets isError: true on the tool result content. The text payload contains:

{ "status": "error", "response": { "message": "Resource revision mismatch. The resource has been modified since it was loaded.", "code": "revision_mismatch", "suggestions": { "current_revision": "a8f9c1b2", "action": "reload_resource" } } }

Handling common error codes

CodeCauseAgent Recovery Strategy
release_missingThe specified theme release ID is inactive or deletedCall list_theme_releases to fetch the current active release ID, update parameters, and retry
revision_mismatchConcurrent edit occurred; resource revision token is staleRe-fetch the target resource with get_* to retrieve the latest state and revision hash, reapply modifications, and retry
write_failedValidation failure on one or more payload fieldsInspect suggestions for field-level error messages. Adjust parameter types or formats and retry
insufficient_scopeThe OAuth token lacks permission for this toolStop execution and inform the merchant which OAuth scope is missing (e.g. themes_write)

Automated retry handler example

interface ToolErrorPayload { status: "error"; response: { message: string; code?: string; suggestions?: Record<string, unknown>; }; } async function handleToolExecution(client: any, toolName: string, args: Record<string, unknown>) { const result = await client.callTool({ name: toolName, arguments: args }); if (result.isError) { const rawText = result.content[0]?.text || "{}"; let errorData: ToolErrorPayload; try { errorData = JSON.parse(rawText); } catch { throw new Error(`Tool execution failed: ${rawText}`); } const { code, message, suggestions } = errorData.response; // Handle stale revision concurrency if (code === "revision_mismatch") { console.warn("Revision mismatch detected. Refreshing resource..."); // Re-fetch resource, update args with latest revision, and retry if (args.product_id) { const fresh = await client.callTool({ name: "get_product", arguments: { product_id: args.product_id }, }); const freshData = JSON.parse(fresh.content[0].text); return await client.callTool({ name: toolName, arguments: { ...args, revision: freshData.revision }, }); } } // Handle missing theme release if (code === "release_missing" && args.channel_id) { console.warn("Release missing. Looking up current active release..."); const releases = await client.callTool({ name: "list_theme_releases", arguments: { channel_id: args.channel_id }, }); const releaseList = JSON.parse(releases.content[0].text); const activeRelease = releaseList.find((r: any) => r.is_active); if (activeRelease) { return await client.callTool({ name: toolName, arguments: { ...args, release_id: activeRelease.id }, }); } } throw new Error(`Unrecoverable tool error [${code}]: ${message}`); } return JSON.parse(result.content[0].text); }

Prompt Engineering for Admin Agents

Equip your agent harness with clear system instructions and tool usage constraints.

You are an authorized Finqu Commerce Admin Assistant. You operate the merchant's store using the Finqu Admin MCP toolset. Core Operational Rules: 1. Discovery First: - Call get_profile at the start of a conversation to identify the merchant and confirmed scopes. - Call list_channels before calling any tool that accepts channel_id. Store the webstore channel ID in context. 2. Precision & Verification: - Never guess resource IDs, SKUs, or variant IDs. Always use search_* or list_* tools first to locate the exact entity. - When updating prices, verify the currency from get_profile and specify exact decimal amounts. 3. Safety & Human Confirmation: - Always ask for merchant confirmation before making destructive or high-impact changes (e.g., deleting products, unpublishing items, modifying Liquid theme templates, altering order records). - Display the current value alongside the proposed new value when requesting confirmation. 4. Error Self-Correction: - If a tool returns an error payload with status="error", inspect the response.code and suggestions object. - If the code is revision_mismatch, re-fetch the item to obtain the new revision and re-apply changes. - If the code is release_missing, query list_theme_releases to find the current active theme release.

Next steps