MCP Server
The Orvion MCP (Model Context Protocol) server enables AI agents like Claude, GPT-4, and other LLMs to interact with your invoice system through natural language. The server exposes invoice operations as LLM-friendly tools that communicate with your FastAPI backend.
What is MCP?
Model Context Protocol (MCP) is a standard protocol for connecting AI assistants to external data sources and tools. The Orvion MCP server provides invoice management capabilities to AI agents.
Installation
Prerequisites
- Python 3.10+
- Running Orvion FastAPI backend
- Valid API key from Orvion dashboard
Install Package
cd mcp-server
pip install -e .
Or install dependencies directly:
pip install mcp httpx pydantic pydantic-settings python-dotenv structlog
Configuration
Create a .env file in the mcp-server/ directory:
# .envAGENTPAY_API_BASE_URL=http://localhost:8000/v1AGENTPAY_API_KEY=test_your_api_key_hereAGENTPAY_ORG_ID=AGENTPAY_TIMEOUT_SEC=10
Environment Variables
| Variable | Required | Description | Example |
|----------|----------|-------------|---------|
| AGENTPAY_API_BASE_URL | Yes | Base URL of FastAPI backend | http://localhost:8000/v1 |
| AGENTPAY_API_KEY | Yes | API key for authentication | test_xxx... |
| AGENTPAY_ORG_ID | No | Organization ID (usually inferred from API key) | org_01HABC... |
| AGENTPAY_TIMEOUT_SEC | No | HTTP timeout in seconds | 10 |
Running the Server
The MCP server uses stdio transport for communication with MCP clients:
python -m orvion_mcp.server
Available Tools
create_invoice
Create a new invoice for a customer.
Required fields:
customer_name: Customer nameamount: Invoice amount (must be positive)currency: Currency code (e.g., EUR, USD, SAT)
Optional fields:
customer_email: Customer email addresscustomer_wallet: Wallet address or payment identifierissued_at: ISO 8601 timestamp (default: now)due_at: ISO 8601 timestampexternal_id: External reference ID for idempotencystatus: Initial status - "draft" or "sent" (default: "sent")
Example:
{"customer_name": "Acme Corporation","amount": 1250.00,"currency": "USD","status": "sent","due_at": "2025-12-31T23:59:59Z"}
get_invoice
Fetch a single invoice by ID.
Required fields:
id: Invoice ID
Example:
{"id": "inv_01HXYZ123ABC"}
list_invoices
List invoices, optionally filtered by status or customer.
Optional fields:
status: Filter by status - "draft", "sent", "paid", "overdue", "canceled"customer_email: Filter by customer emaillimit: Maximum number of invoices (1-100, default: 20)
Example:
{"status": "sent","limit": 50}
mark_invoice_paid
Mark an invoice as paid.
Required fields:
id: Invoice ID
Optional fields:
paid_at: ISO 8601 timestamp (default: now)amount_paid: Amount paid (defaults to invoice amount)payment_reference: Payment reference or transaction hash
Example:
{"id": "inv_01HXYZ123ABC","paid_at": "2025-01-15T10:30:00Z","payment_reference": "tx_abc123"}
Response Format
All tools return a consistent response format:
Success:
{"ok": true,"data": {"invoice": { /* Invoice object */ }},"error": null}
Error:
{"ok": false,"data": null,"error": {"code": "NOT_FOUND","message": "Invoice inv_123 not found","details": { "http_status": 404 }}}
Error Codes
NOT_FOUND: Invoice doesn't existUNAUTHORIZED: Invalid or missing API keyVALIDATION_ERROR: Invalid input dataRATE_LIMITED: Rate limit exceededINVALID_STATUS: Invoice status doesn't allow this operationCLIENT_ERROR: HTTP client errorINTERNAL_ERROR: Unexpected server error
Idempotency
Use external_id when creating invoices to achieve idempotency. If an invoice with the same external_id already exists, it will be updated instead of creating a duplicate.
Example:
{"customer_name": "Acme Corp","amount": 100.0,"currency": "USD","external_id": "crm-invoice-12345"}
Integration with Claude Desktop
Add to claude_desktop_config.json:
{"mcpServers": {"orvion": {"command": "python","args": ["-m", "orvion_mcp.server"],"env": {"AGENTPAY_API_BASE_URL": "http://localhost:8000/v1","AGENTPAY_API_KEY": "your_api_key_here"}}}}
Rate Limiting
Rate limit errors from the Orvion API are propagated with error.code = "RATE_LIMITED". The MCP server doesn't implement its own rate limiting.
Observability
The MCP server logs:
- Tool invocations (name, success/failure)
- HTTP status codes from backend
- Error codes
Never logged:
- API keys
- Sensitive customer data
- Full request/response bodies