ERPSpan docs

MCP setup

Expose your Dynamics GP data to AI agents over the Model Context Protocol.

ERPSpan exposes your GP data to AI agents (Claude Desktop, Claude Code, any MCP client) at one endpoint: POST /mcp. It runs the same machinery as the REST API — the MCP tools call the identical internal services — so an agent reads and (with a human in the loop) writes GP exactly as the REST API does.

  • Read toolslist_connections, list_<object> / get_<object> for every read object (customers, vendors, items, accounts, ar-invoices, …), and search_customers / search_vendors / search_items. Every list is capped at 50 rows; page with the returned nextCursor.
  • Write tools — writes are always draft → commit (never a single call): draft_<object> validates and previews without executing, commit_draft executes it, discard_draft cancels.

Connect a client (Claude Desktop)

Add ERPSpan to your claude_desktop_config.json. It's a remote, streamable-HTTP server authenticated with an API key — nothing to install locally:

{
  "mcpServers": {
    "erpspan": {
      "type": "http",
      "url": "https://api.erpspan.com/mcp",
      "headers": { "Authorization": "Bearer lb_live_YOUR_KEY" }
    }
  }
}
  • The key must have the mcp scope to reach /mcp, and additionally the write scope to use the draft/commit write tools.
  • Writes are off by default per connection: a draft_/commit_ is refused with WRITE_NOT_ENABLED until you enable that object under Connections → Write access. Sandbox connections are always read-only.

A worked example

A typical hands-free session — the model picks each tool from its description:

You sayThe model callsResult
"List my GP connections."list_connectionsyour connections (id, name, status, companies)
"Who are our 5 biggest customers by credit limit?"list_customers, then rankstop-5 by creditLimit
"Any AR invoices past due?"list_ar_invoices { dueBefore }open AR docs due before today
"Draft a journal entry accruing $1,250 to 000-6120-00 against 000-2100-00."draft_journal_entries{ draftId, preview }balanced: true, willCreateUnpostedBatch: true
"Commit it."commit_draft { draftId }{ data: { journalEntryNumber, batchId, status: "unposted" } }
"Show me the batch it created."list_batchesthe LBAPI-YYYYMMDD unposted batch

Safety

  • A draft_ call never touches GP — an unbalanced or malformed body is rejected in the draft and never reaches the tunnel.
  • commit_draft runs the same eConnect pipeline as a REST write. The result lands in an unposted batch — a person still posts it in GP. Re-committing the same draftId replays the first result (idempotent); it never double-posts.
  • Every write requires the write scope and the object on the connection's whitelist and the draft→commit two-step — none can be bypassed.

On this page