AnchorAnchor
Guides

MCP Server

Connect AI agents to Anchor via the MCP server or in-tab WebMCP tools.

Two ways agents connect

Anchor exposes tools to AI agents in two different places. They are not interchangeable.

MCP server (Cursor / Claude Desktop)WebMCP (this browser tab)
Where the agent runsA coding agent on your computerAn AI feature in Chromium (or an extension) on the signed-in dashboard
How you connectAdd https://anchorapp.co.za/api/mcp as an MCP server URLOpen the signed-in dashboard in a supporting Chromium build — the page registers tools itself
AuthOAuth; Bearer tokens (mcp_at_…)Your existing signed-in session cookie
What it can doThe full remote catalogue for that org (create, post, reports, …)Screen-scoped anchor_* tools: reads, navigate, draft creates, and high-risk writes that open the existing confirm/send UI. Never the full remote list at once

Do not add https://anchorapp.co.za (the website origin) as an MCP server URL. That URL is the app, not a tool server. WebMCP is not configured as an MCP server at all. The only MCP server URL is /api/mcp.

WebMCP is Chromium-only and experimental. Firefox and Safari keep the full human UI; they simply do not register in-tab tools. We do not claim it works in every browser.

What is MCP?

The Model Context Protocol (MCP) is an open standard that lets AI coding agents and assistants interact with external tools and data sources. Anchor's built-in MCP server gives any MCP-compatible agent direct access to your accounting data -- creating entries, managing invoices, generating reports, and more.

WebMCP (this browser tab)

WebMCP is a draft browser API (document.modelContext) so an in-tab agent can call typed tools instead of scraping buttons.

When you are signed in to Anchor in a supporting Chromium build:

  1. Use Chrome 149+. This origin serves a WebMCP origin trial token, so you should not need a flag. If tools still do not appear, enable chrome://flags/#enable-webmcp-testing and relaunch (see Chrome WebMCP).
  2. Open the dashboard (not the public marketing or docs pages, and not /admin).
  3. The page registers tools named anchor_* for the screen you are on — typically a few dozen, never the full remote catalogue. anchor_list_available_packs lists packs and whether they are registered in this tab. anchor_navigate moves this tab to an allowlisted dashboard path.
  4. Ask the in-tab agent to list invoices or open a record — it should call those tools. Amounts are integer cents (1250 = R12.50). Draft invoice lines use unitPriceCents. Creating a contact or draft invoice navigates this tab to the new record.

Tools always run as you, on the current organisation. Signing out or leaving the dashboard unregisters them.

Screen-scoped packs

In-tab tools mount from the layout you have open and unregister when you leave. Open Sales → Invoices and you get invoice tools; Quotes, Orders, and Delivery Notes each register their own set. Open Banking and those sales tools go away. Settings registers one tab at a time (General is not Email is not Backups). Reports register that report only, not every report at once.

This is capability parity with the dashboard, not a dump of hundreds of MCP server tools into the tab.

What in-tab tools can do

AreaWhereWhat the agent can do
ShellAny signed-in dashboard screenCurrent user/org, navigate, list packs, dashboard summary, contact list/get/create, marketing-consent update
Contacts/contactsUpdate a contact; merge or delete via the existing confirm dialogs
Sales/salesList/get invoices; create or update a draft invoice; on an open invoice, send, void, or write-off via the existing dialogs
Quotes/sales/quotesList/get/create quotes; send, accept, decline, delete, convert to invoice, or convert to a sales order via the existing dialogs
Orders/sales/ordersList/get/create sales orders; on an open order, send, deliver, invoice, close leftover, or cancel via the existing dialogs
Delivery notes/sales/delivery-notesList/get GDNs; on an open note, send email or cancel via the existing dialogs. A GDN is not a tax invoice
Cash sales/sales/receiptsList/get/create cash sales; post via the existing confirm
Credit notes/sales/credit-notesList/get/create; send, apply, or void via the existing dialogs
Payments/sales/paymentsList/get payments; create, batch, or delete via the existing confirms
Purchases/purchasesBills, purchase orders, expenses, debit notes, requisitions, landed costs, and recurring bills — list/get/create, plus pay/approve/send/void (and similar) via the existing dialogs on the open record
Banking/accounting/bankingList bank accounts and lines; open the existing categorize, match, split, transfer, and statement-check sheets (you complete them)
Journals/accountingList/get/create draft journal entries; post or void this entry via confirm
Chart of accounts/accounting/accountsList/get/create/update accounts; delete via confirm
Fixed assets/accounting/fixed-assetsList/get/create assets and categories; dispose, depreciate, revalue, impair via the existing dialogs
Other accounting/accounting/loans, accruals, budgets, opening balances, recurring journalsList/get/create where the screen supports it; post/run/set via confirm
Reports/reports/…Run that report (read-only). The reports index does not dump every report tool
Inventory/inventoryItems and warehouses; BOMs and assembly orders. Completing an assembly opens the existing Complete dialog
Tax/taxTax rates, currencies, periods, VAT/BAS/sales-tax/Schedule C reads. Filing a period opens the existing confirm
Settings/settings (per tab)Period lock and fiscal-year close/reopen on General; members, roles, control accounts, document numbering, bank rules, email SMTP, backups, trash, import/export, reminders, tags, cost centres, webhooks, Stripe, approvals, procurement, notification prefs — each on its own tab
Documents/documents (and a contact’s Files tab)List and attach files
Notifications/notificationsList inbox items and mark read
CRM/crmList/get/create deals; mark won/lost and move stage via the existing confirms
Projects/projectsList/get projects; time entries and timers on the Time tab

High-risk writes (Class D) — send, void, post, pay, file a tax period, lock dates, restore a backup, complete an assembly, merge a contact, and similar — open the same dialog a human uses. The agent waits; you confirm or cancel. Those tools never call the mutating REST path themselves.

What WebMCP does not do

  • Put the full remote MCP catalogue (hundreds of tools) on one page
  • Payroll (still off for this product)
  • Anything on /admin (no in-tab tools on site-admin screens)
  • Recover a written-off invoice (there is no recover control on the invoice page)
  • Change or reset a password (human-only in Account → Security; agents can read hasPassword via get_password_status / anchor_get_context)
  • Change the sign-in email (human-only in Account → Profile; agents can read the masked status via get_email_change_status / anchor_get_context user.emailChange)
  • Chatwoot / in-app support chat (no MCP tools; use the help widget)
  • Firefox, Safari, or public pages (/, /docs, /pay, /portal, /sign-in)

Prerequisites

  • Any plan -- MCP access is available on all plans, including Free
  • Any MCP-compatible client (Claude Desktop, Claude Code, Cursor, Windsurf, Cline, VS Code Copilot, or other MCP-enabled agents)

Connecting Your Agent

Any MCP-compatible agent can connect to Anchor's MCP server. The server uses Streamable HTTP transport at /api/mcp and OAuth 2.1 for authentication. Most agents handle the OAuth flow automatically -- they will open a browser window for you to sign in and authorize access on first connect.

The examples below use https://anchorapp.co.za/api/mcp (this hosted product).

Claude Desktop

Add to your Claude Desktop config (claude_desktop_config.json):

{
  "mcpServers": {
    "Anchor": {
      "url": "https://anchorapp.co.za/api/mcp"
    }
  }
}

Claude Code

claude mcp add Anchor --transport streamable-http https://anchorapp.co.za/api/mcp

Cursor

Go to Cursor Settings > MCP and add a new server, or add to .cursor/mcp.json in your project:

{
  "mcpServers": {
    "Anchor": {
      "url": "https://anchorapp.co.za/api/mcp"
    }
  }
}

Cursor auto-detects Streamable HTTP transport from the URL and handles OAuth automatically.

Windsurf

Go to Windsurf Settings > Cascade > MCP and click View raw config, or edit ~/.codeium/windsurf/mcp_config.json directly:

{
  "mcpServers": {
    "Anchor": {
      "serverUrl": "https://anchorapp.co.za/api/mcp"
    }
  }
}

VS Code (GitHub Copilot)

Add to .vscode/mcp.json in your workspace (available in VS Code 1.99+):

{
  "servers": {
    "Anchor": {
      "type": "http",
      "url": "https://anchorapp.co.za/api/mcp"
    }
  }
}

Or add to your user settings.json to make it available across all workspaces:

{
  "mcp": {
    "servers": {
      "Anchor": {
        "type": "http",
        "url": "https://anchorapp.co.za/api/mcp"
      }
    }
  }
}

Other MCP Clients

Any agent that supports the MCP Streamable HTTP transport can connect. Point it at:

https://anchorapp.co.za/api/mcp

The client will discover OAuth endpoints automatically via the /.well-known/oauth-authorization-server metadata endpoint.

OAuth Flow

Anchor uses OAuth 2.1 with PKCE for MCP authentication:

  1. The MCP client discovers OAuth endpoints via /.well-known/oauth-authorization-server on the MCP endpoint
  2. The client registers dynamically at /api/mcp/oauth/register
  3. The client redirects you to /api/mcp/oauth/authorize to sign in
  4. You select an organization and approve the connection
  5. The client receives an authorization code and exchanges it for access/refresh tokens at /api/mcp/oauth/token
  6. Access tokens expire after 1 hour; refresh tokens last 30 days

Available Tools

The names below are the MCP server catalogue (/api/mcp). In-tab WebMCP uses anchor_* names on the screen you have open — not this full list at once. See WebMCP.

Organization

  • get_organization -- Get current organization details

Chart of Accounts

  • list_accounts -- List all accounts with optional type filter
  • get_account -- Get account with calculated balance
  • create_account -- Create a new account
  • update_account -- Update account details
  • delete_account -- Delete an account (fails if it has transactions)

Control Account Mappings

  • list_control_account_mappings -- List role → chart account mappings (AR, AP, VAT, bank, …)
  • set_control_account_mapping -- Set or clear one role mapping (accountId UUID or null to reset)

Document numbering

  • list_document_number_sequences -- List prefix, separator, padWidth, nextNumber, and preview (e.g. INV-00001 or INP02401). Document numbers are strings, not money.
  • set_document_number_sequence -- Set one entity (manage:accounts). Sage example: prefix=INP, separator="", padWidth=5, nextNumber=2401 → next auto INP02401.

Journal Entries

  • list_entries -- List entries with status/date filters
  • get_entry -- Get entry with line items
  • create_entry -- Create a new entry (debits must equal credits)
  • post_entry -- Post a draft entry
  • void_entry -- Void a posted entry (creates reversing entry)

Contacts

  • list_contacts -- Search and filter contacts
  • get_contact -- Get contact details (includes addresses)
  • create_contact -- Create a customer, supplier, or both. Optional addresses (billing / shipping street). addresses.billing is printed on invoices and quotes. null clears; omit to leave empty. Country preferably ISO-2 (ZA).
  • update_contact -- Update contact details. Provided scalar fields are patched. When addresses is provided, it replaces the whole JSONB (not a deep-merge) — shipping is dropped if not included. null clears. Omit addresses to leave it unchanged. GET first if you must keep shipping.

Quotes

  • list_quotes -- List sales quotes with optional status filter
  • get_quote -- Get a quote with line items (includes inventoryItemId when set)
  • create_quote -- Create a draft quote. Optional line inventoryItemId is persisted. Does not reserve or decrement stock. Amounts in integer cents. Omit line taxRateId to use the contact’s defaultTaxRateId (or no tax if the contact is tax-exempt / has no default). taxRateId: null is explicit no tax and does not fall back.
  • update_quote -- Update a draft quote. Replacing lines without inventoryItemId stores NULL and drops the catalogue link; GET then put to keep it. Replacing lines that omit taxRateId applies the contact default (not the old line tax).
  • convert_quote_to_invoice -- Invoice lines inherit each quote line's inventoryItemId. Stock is not relieved until the invoice is sent. Blocked with 409 when the quote is already a sales order.
  • convert_quote_to_sales_order -- Copy an accepted quote into a draft sales order. Does not reserve until send_sales_order. Blocked with 409 when the quote already has invoices. Quote → invoice and quote → SO are mutually exclusive.
  • send_quote -- Send a draft quote. By default it only marks the quote sent; with sendEmail: true and recipientEmail it first emails the quote (with a portal link and, if attachPdf, the PDF), as the quote page's Send does
  • accept_quote -- Mark a sent quote as accepted
  • decline_quote -- Mark a sent quote as declined
  • delete_quote -- Soft-delete a quote (draft/sent/accepted/declined/expired with billedTotal 0). Converted to invoice, converted to sales order, or progress-invoiced quotes cannot be deleted. Quote number is not reused.
  • get_quote_pdf -- Download URL for the quote PDF (any status, including sent)

Invoices

  • list_invoices -- List invoices with filters
  • get_invoice -- Get invoice with line items
  • create_invoice -- Create an invoice with line items. Invoice number is auto-assigned from Settings → Document numbering (default INV-#####) unless invoiceNumber is provided. Omit line taxRateId to use the contact’s defaultTaxRateId (or no tax if tax-exempt / unset). taxRateId: null is explicit no tax. REST omit is the same — TaxShopHub no-VAT lines must send null.
  • update_invoice -- Update a draft invoice. Replacing lines that omit taxRateId applies the contact default. Sales-order invoices cannot replace lines.
  • void_invoice -- Void an invoice. SO-linked stock reverses COGS back to GDNI and does not restock.
  • pay_invoice -- Record a customer payment, as the invoice page's Record payment does: a payment (PAY-…) allocated to the invoice and DR Bank / CR Accounts receivable. Amount in cents, at most the amount due. Optional date (default today), method, reference, bankAccountId (the payment then posts to that bank account's ledger account instead of the default bank). Role manage:payments
  • get_invoice_pdf -- Download URL. Optional variant: omit for the tax invoice; pod is not a tax invoice and does not post; with-pod is one PDF (the tax invoice, then the proof of delivery).

Sales orders / delivery notes

Amounts in integer cents. Delivery quantities and stock invoice quantities are whole units. Service and free-text invoice quantities may have two decimal places. get_sales_order remaining fields are still stored ×100 — divide by 100 before passing to create tools. Reservation is not a sale. A GDN is not a tax invoice.

  • list_sales_orders -- List sales orders (status, contactId, quoteId, pagination)
  • get_sales_order -- One order plus lines, remainingToDeliver, remainingToInvoice (×100)
  • create_sales_order -- Draft. Does not reserve. To convert a quote, use convert_quote_to_sales_order
  • update_sales_order -- Draft only. Replacing lines without inventoryItemId stores NULL
  • delete_sales_order -- Soft-delete a draft only
  • send_sales_order -- Always reserves stock lines (on-hand unchanged). Email optional
  • void_sales_order -- Cancel. Blocked when live delivery notes or invoices exist
  • close_sales_order -- Cancel undelivered leftover. Blocked while delivered stock is unbilled
  • create_invoice_from_sales_order -- Draft tax invoice. Omit lines to invoice all remaining (stock: delivered remainder; service: ordered remainder). The dashboard sends lines. Tallies bump on invoice send, not here
  • get_sales_order_pdf -- Download URL for the sales order PDF
  • list_delivery_notes -- List GDNs. Not tax invoices
  • get_delivery_note -- One GDN with lines
  • create_delivery_note -- Issue immediately: reserved down, on-hand down, DR GDNI / CR Inventory. No VAT
  • void_delivery_note -- Restock and reverse GDNI. Blocked if those units are invoiced
  • send_delivery_note -- Email the GDN (no stock change)
  • get_delivery_note_pdf -- Download URL. Not a priced invoice. PDF footer: “This is not a tax invoice.”

Bills

  • list_bills -- List bills; filter by status, unpaidOnly, due dates (dueFrom / dueTo, soonest due first) or supplier
  • get_bill -- One bill with its supplier, lines, amount paid and amount due
  • create_bill -- Create a bill with line items. Optional line inventoryItemId is a stock purchase: posting capitalises Inventory and increases on-hand. Replacing lines without inventoryItemId stores NULL.
  • approve_bill -- Approve a pending bill (or receive a draft) and post it, as the bill page does: the journal (expense or stock and input VAT against accounts payable), stock receipts and GRNI clearing. Refused for a locked period, a missing exchange rate or a broken three-way match. Role approve:bills
  • pay_bill -- Record a supplier payment, as the bill page's Record payment does: a payment (PAY-…) allocated to the bill and DR Accounts payable / CR Bank. Amount in cents, at most the amount due. Optional date (default today), method, reference, bankAccountId (credits that bank account's ledger account instead of the default bank). Role manage:payments
  • void_bill -- Void a bill

Inventory / assembly

Item tools. unitOfMeasure is a display-only label (bag, carton, batch). Stock is still whole units — no conversion. Amounts are integer cents.

  • list_inventory_items -- List items (on-hand is whole units; costs in cents). Also quantityReserved and quantityAvailable (on-hand minus reserved). Optional itemType filter stock or service.
  • get_inventory_item -- One item by ID (itemType is stock or service; includes reserved and available)
  • create_inventory_item -- Create an item. Optional itemType (stock default, or service). Service items cannot have quantityOnHand > 0. Optional unitOfMeasure is display-only. Prices in cents.
  • update_inventory_item -- Patch master fields (not stock). Optional itemType. Converting stock → service is rejected while quantity is on hand.
  • delete_inventory_item -- Soft-delete an item
  • adjust_inventory_stock -- Quantity, write-down, or revaluation; posts the matching journal. Rejected for service items.
  • transfer_inventory_stock -- Move whole units between warehouses (no journal). Blocked if it would steal warehouse-reserved units
  • apply_stock_take -- Apply counted quantities and complete the take
  • list_inventory_movements -- Stock ledger

BOM tools:

  • list_boms -- List BOMs with components and costBreakdown (cents, per finished unit)
  • get_bom -- One BOM + costBreakdown
  • create_bom -- Finished item, name, optional labour/overhead cents. Components added separately. Does not move stock.
  • update_bom -- Patch name, description, labour/overhead, isActive
  • delete_bom -- Hide a BOM (blocked if draft or in-progress orders exist)
  • add_bom_component -- Item, quantity, optional wastage %. Quantity may be decimal; build ceils to whole units.
  • update_bom_component -- Patch qty / wastage
  • remove_bom_component -- Remove a component line

Assembly tools. Amounts in integer cents. Order quantity is whole units. build_assembly is complete.

  • list_assembly_orders -- List orders (no consumption preview)
  • get_assembly_order -- One order + consumptionPreview
  • create_assembly_order -- Draft against an active BOM. Does not move stock.
  • update_assembly_order -- Quantity / notes only (no status)
  • start_assembly_order -- Draft → in progress. Does not reserve stock or post WIP.
  • cancel_assembly_order -- Status only. Nothing to reverse.
  • build_assembly -- Complete the order: issue components, receive the finished item, post the journal. Optional date. Returns totalCost / unitCost (cents). There is no second complete tool.

On the dashboard Inventory → Assembly / BOM screens, in-tab WebMCP can list/create those records. Completing an assembly opens the existing Complete dialog (you confirm). Amounts are still integer cents.

Reports

  • trial_balance -- Trial balance (mode: as_at default / ytd optional)
  • balance_sheet -- Balance sheet
  • profit_and_loss -- P&L with date range
  • aged_receivables -- AR aging buckets
  • aged_payables -- AP aging buckets
  • get_vat_return -- VAT report for a date range without filing: South Africa F4 / F14 / F20 plus supporting S1 / P1 (other countries: 9-box). The same figures as Reports → VAT Return. Not a full VAT201 and not tax advice.
  • get_spend_by_account -- Total spent on 1–20 expense accounts for a date range, with the posted lines behind it. Matches profit_and_loss to the cent; refunds reduce spend.
  • get_general_ledger -- General ledger for a date range: per account the opening balance, period debits and credits, closing balance and lines with running balances; or one account's lines a page at a time. Optional cost centre or project filter. The same figures as Reports → General Ledger.
  • get_profitability -- Profit per customer (invoice totals against bill totals) or per project (job costing) for a date range, as on Reports → Profitability
  • find_duplicate_transactions -- Possible duplicate invoices or bills (same contact and total within 7 days), as on Reports → Duplicate Detection
  • get_financial_calendar -- Due invoices and bills, the next recurring invoices and budget periods between two dates, as on Reports → Financial Calendar
  • get_unrealized_fx -- Unrealised exchange gains and losses on unpaid foreign-currency invoices and bills at today's rates, as on Tax → Currencies
  • get_recurring_transactions -- Repeating bank statement lines (debit orders, subscriptions) with frequency and average amount
  • list_bank_accounts -- Bank accounts with their statement balance, as on Accounting → Banking (use reconciliation_report for the ledger balance)
  • get_vendor_spend -- Spend per supplier for a date range (bills that are not draft or void), with a monthly trend for the top five. The same figures as Reports → Vendor Spend.
  • get_expense_analytics -- Expenses per expense account and per month for a date range, net of refunds. The same figures as Reports → Expense Analytics.
  • get_payment_performance -- Average days from issue to payment for paid invoices and bills, per customer and supplier, with late counts and on-time rates. The same figures as Reports → Payment Performance.
  • get_tax_summary -- Output and input tax per tax rate for a date range, from invoice and bill lines. The same figures as Reports → Tax Summary; for the South African VAT201 use get_vat_return.
  • get_pnl_comparison -- Profit and loss for the last N months, quarters or years side by side, with the change from each previous period. The same figures as Reports → P&L Comparison.
  • get_monthly_trends -- Revenue, expenses and net income for each of the last N months, as in the dashboard trend charts.
  • get_bank_cash_flow -- Money in and out of one or all bank accounts per day, week or month, from the bank lines. The same figures as Reports → Bank Cash Flow.
  • get_financial_ratios -- Liquidity, leverage, margin, DSO/DPO and return ratios with the balances behind them. The same figures as Reports → Financial Ratios; Anchor's figures, not advice.
  • get_inventory_valuation -- Active items valued at purchase price and sale price, with margins. The same figures as Inventory → Valuation.

ARIA

  • set_aria_allowed -- Allow or turn off ARIA for this organisation (manage:billing). The site-wide switch must also be on.
  • ask_aria -- Ask Anchor's built-in assistant a question in plain language (English or Afrikaans). It runs one Anchor report or search with your permissions and answers from that result only; every figure comes from the tool. Returns kind, text, an optional table and links, the tool used, and clarify options. Refuses tax advice; never writes. Each question is recorded in the audit log. Errors while ARIA is switched off.
  • search_documents -- Find invoices, bills, quotes or credit notes by meaning (supplier or customer, what was bought, a reference), in English or Afrikaans. Filters: types, date range, amount in cents with a tolerance, status. A document number in the query comes first. score is a similarity rank, never an amount.
  • search_contacts -- Find customers or suppliers by what they do or what you bought from them, or by part of a name or code.
  • search_help -- Search Anchor's help pages; returns section links under /docs.

Each returns mode: vector (meaning search) or keyword when the search index is not available yet.

Amount Conventions

  • All monetary amounts in tool inputs/outputs are in integer cents (e.g. 1250 = $12.50)
  • Invoice/bill line item unitPrice and quantity are decimal numbers (the system converts to cents internally)
  • Exchange rates are stored as integers with 6 decimal places (1000000 = 1.0)

Testing

With MCP Inspector

The MCP Inspector is the easiest way to test the MCP server interactively during development.

# Start the dev server first
pnpm dev

# Launch MCP Inspector pointed at your local instance
npx @modelcontextprotocol/inspector --url http://localhost:3000/api/mcp

The Inspector will open in your browser and walk you through the OAuth flow. Once authenticated, you can browse available tools, invoke them with custom inputs, and inspect the JSON-RPC responses.

Manual OAuth Flow

If you want to test the OAuth flow step by step:

1. Check metadata discovery

curl http://localhost:3000/.well-known/oauth-authorization-server/api/mcp

This should return JSON with all OAuth endpoint URLs.

2. Register a client

curl -X POST http://localhost:3000/api/mcp/oauth/register \
  -H "Content-Type: application/json" \
  -d '{"redirect_uris": ["http://localhost:9999/callback"], "client_name": "Test Client"}'

Save the client_id from the response.

3. Start the authorization flow

Open this URL in your browser (replace CLIENT_ID with the value from step 2):

http://localhost:3000/api/mcp/oauth/authorize?client_id=CLIENT_ID&redirect_uri=http://localhost:9999/callback&code_challenge=TEST_CHALLENGE&code_challenge_method=S256&state=test123&response_type=code

You will be redirected to sign in (if needed) and then to the consent page. After approving, you'll be redirected to the callback URL with a code parameter.

4. Exchange code for tokens

curl -X POST http://localhost:3000/api/mcp/oauth/token \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "authorization_code",
    "code": "THE_CODE_FROM_STEP_3",
    "redirect_uri": "http://localhost:9999/callback",
    "client_id": "CLIENT_ID",
    "code_verifier": "THE_VERIFIER_MATCHING_YOUR_CHALLENGE"
  }'

This returns access_token and refresh_token.

5. Call the MCP endpoint

curl -X POST http://localhost:3000/api/mcp \
  -H "Authorization: Bearer mcp_at_YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
      "protocolVersion": "2025-03-26",
      "capabilities": {},
      "clientInfo": { "name": "test", "version": "1.0" }
    }
  }'

6. List available tools

curl -X POST http://localhost:3000/api/mcp \
  -H "Authorization: Bearer mcp_at_YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/list",
    "params": {}
  }'

7. Call a tool

curl -X POST http://localhost:3000/api/mcp \
  -H "Authorization: Bearer mcp_at_YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 3,
    "method": "tools/call",
    "params": {
      "name": "get_organization",
      "arguments": {}
    }
  }'

With an MCP Client (local)

For local testing with any MCP client, point it at localhost:

http://localhost:3000/api/mcp

For example, in Claude Desktop config:

{
  "mcpServers": {
    "Anchor-local": {
      "url": "http://localhost:3000/api/mcp"
    }
  }
}

Or in Cursor's .cursor/mcp.json:

{
  "mcpServers": {
    "Anchor-local": {
      "url": "http://localhost:3000/api/mcp"
    }
  }
}

Restart your agent and it will initiate the OAuth flow in your browser.

Troubleshooting

MCP or API access is blocked

API and MCP access is included. If a client is refused, contact support.

"Invalid access token"

Your access token has expired. MCP clients should automatically refresh tokens using the refresh token. If this persists, disconnect and reconnect the MCP server.

"Not a member of this organization"

Your user account has been removed from the organization. Ask an admin to re-add you.

In-tab agent does not see anchor_* tools

WebMCP only registers on the signed-in dashboard, and only in Chromium with the WebMCP API enabled. Public pages (/, /docs, /pay, …) and /admin register nothing. This is not an MCP server connection problem — do not add the website origin as an MCP server URL.

If the agent is on /dashboard and you asked it to list bills, navigate to Purchases first (anchor_navigate / anchor_list_available_packs). Tools are screen-scoped; they are not all registered at once.

On this page