Quento MCP API Documentation
Version: 1.0.0
Protocol: Model Context Protocol (MCP)
Base URL: https://{subdomain}.quento.app/mcp
Table of Contents
- Overview
- Getting Started
- Authentication
- Architecture
- API Tools Reference
- Request & Response Format
- Error Handling
- Best Practices
- Code Examples
- Troubleshooting
Overview
The Quento MCP (Model Context Protocol) API enables AI assistants and applications to interact with your invoicing system through a standardized protocol. Built on the MCP specification created by Anthropic, it allows natural language interactions with your business data.
What is MCP?
Model Context Protocol (MCP) is an open protocol that connects AI applications to external tools and data sources. It provides:
- Standardized communication between AI models and business applications
- Type-safe tool definitions with JSON Schema validation
- Bidirectional streaming for real-time interactions
- Multi-tool execution for complex workflows
Key Features
- Natural Language Interface: Interact with invoices using plain language commands
- Multi-Tenant Architecture: Automatic account isolation and data scoping
- Auto-Generated CRUD Tools: Dynamically generated API tools from Rails models
- Real-Time Updates: Server-Sent Events (SSE) support for streaming responses
- Secure Authentication: API key-based authentication with Bearer token support
- Type Safety: Full JSON Schema validation for all inputs and outputs
Use Cases
- Invoice Management: Create, update, send, and track invoices via AI
- Client & Product Management: CRUD operations for clients and products
- Analytics & Reporting: Query statistics and generate insights
- Email Automation: Send invoices and payment reminders
- Multi-Step Workflows: Complex operations like "invoice all overdue clients"
Getting Started
Prerequisites
- Active Quento Account: Sign up at https://quento.app
- API Key: Generate from your account settings
- Subdomain: Your unique subdomain (e.g.,
acme.quento.app)
Quick Start
1. Get Your API Key
Navigate to Settings → Integrations → MCP API in your Quento account and click Generate New Key.
Your API key will look like: test_abc123def456...
Important: - Keep your API key secure - treat it like a password - Don't commit it to version control - Use environment variables to store it in your applications
2. Test the Connection
Using curl:
curl -X POST https://yoursubdomain.quento.app/mcp \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {"name": "test-client", "version": "1.0.0"}
}
}'
Expected Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {
"tools": {}
},
"serverInfo": {
"name": "quento",
"version": "1.0.0"
}
}
}
3. List Available Tools
curl -X POST https://yoursubdomain.quento.app/mcp \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list",
"params": {}
}'
Authentication
API Key Authentication
All requests require authentication using a Bearer token in the Authorization header.
Header Format:
Authorization: Bearer YOUR_API_KEY
Security Notes: - API keys are scoped to a single account - Keys have full read/write access to account data - Rotate keys regularly for security - Never commit keys to version control - Use environment variables to store keys
Account Scoping
The API automatically scopes all operations to the authenticated account based on:
- API Key: Identifies the account
- Subdomain: Verified against the API key's account
- Multi-Tenancy: All data is automatically isolated per account
You cannot access data from other accounts, even if you know their resource IDs. Every API request is scoped to your authenticated account.
Architecture
Communication Flow
┌─────────────────┐
│ AI Client │ (Claude Desktop, ChatGPT, Custom App)
│ (MCP Client) │
└────────┬────────┘
│
│ HTTPS POST Request
│ Authorization: Bearer {API_KEY}
│ Content-Type: application/json
│
▼
┌─────────────────────────────────┐
│ https://{subdomain}.quento.app │
│ POST /mcp │
└────────┬────────────────────────┘
│
│ JSON-RPC 2.0 Request
│ {
│ "jsonrpc": "2.0",
│ "method": "tools/call",
│ "params": {...}
│ }
│
▼
┌─────────────────────────────────┐
│ MCP API Endpoint │
│ - Authenticates API key │
│ - Scopes to account │
│ - Executes tool │
│ - Returns JSON-RPC response │
└────────┬────────────────────────┘
│
│ JSON-RPC 2.0 Response
│ {
│ "jsonrpc": "2.0",
│ "result": {...}
│ }
│
▼
┌─────────────────┐
│ AI Client │ Receives structured response
│ (MCP Client) │
└─────────────────┘
Available Tools
The API provides CRUD operations for the following resources. Click each tool name to jump to detailed documentation:
📄 Invoice Management
create_invoice- Create new invoicesupdate_invoice- Modify existing invoiceslist_invoices- Query invoices with filtersget_invoice- Get detailed invoice informationmark_invoice_paid- Record payment receivedchange_invoice_status- Issue, send, or cancel invoicessend_invoice_email- Email invoices to clientsget_invoice_pdf_link- Get PDF download link
👥 Client Management
create_client- Add new clients to your accountupdate_client- Update client informationlist_clients- Search and list all clientsget_client- Get detailed client information
📦 Product Catalog
create_product- Create a new product or serviceupdate_product- Update product details (useactive: falseto deactivate)get_product- Get product detailslist_products- List products and services
🏦 Bank Accounts
create_bank_account- Add a bank account to a companyupdate_bank_account- Update bank account details (useactive: falseto deactivate)list_bank_accounts- List bank accounts
🏢 Company Management
list_companies- List your companies (sellers)create_company- Create a new companyupdate_company- Update company detailsget_company- Get detailed company informationlookup_company- Look up Polish company by NIP (VAT registry)
🇵🇱 KSeF (Polish e-Invoice System)
submit_invoice_to_ksef- Submit invoice to KSeFget_ksef_status- Check KSeF submission statuslist_ksef_submissions- List KSeF submissions
📊 Analytics & Reporting
get_statistics- Get invoice analytics and statistics
Transport Protocol
HTTP Transport:
- Endpoint: POST https://{subdomain}.quento.app/mcp
- Protocol: JSON-RPC 2.0 over HTTPS
- Authentication: Bearer token in Authorization header
- Content-Type: application/json
- Session Management: Stateful sessions maintained per account
- Streaming: Server-Sent Events (SSE) support for real-time updates
API Tools Reference
Invoice Tools
create_invoice
Create a new invoice in draft status.
Input Schema:
{
"client_id": 123,
"company_id": 456,
"items": [
{
"description": "Web Development",
"quantity": 10,
"unit_price": 100.00,
"vat_rate": 23,
"unit": "h",
"product_id": 789
}
],
"payment_terms": 14,
"sale_date": "2025-01-15",
"issue_date": "2025-01-15",
"payment_method": "transfer",
"bank_account_id": 1,
"currency": "EUR",
"notes": "Notes visible on invoice PDF",
"internal_notes": "Private notes (not on PDF)",
"issue_location": "Warsaw",
"purchase_order_number": "PO-2025-001",
"split_payment": false,
"pdf_secondary_language": "en",
"discount_percentage": 0
}
Required Fields: client_id, company_id, items
Optional Fields:
| Field | Type | Description |
|-------|------|-------------|
| payment_terms | integer | Days until due (default: 14) |
| sale_date | string | Sale date in YYYY-MM-DD format |
| issue_date | string | Issue date in YYYY-MM-DD format |
| payment_method | string | transfer, cash, or card |
| bank_account_id | integer | Bank account ID for transfer payments |
| currency | string | Currency code (PLN, EUR, USD, GBP) |
| notes | string | Notes visible on invoice PDF footer |
| internal_notes | string | Private notes (not visible on PDF) |
| issue_location | string | Place of issue (e.g., "Warsaw") |
| purchase_order_number | string | Client's PO number |
| split_payment | boolean | Enable Polish VAT split payment (MPP) |
| pdf_secondary_language | string | Bilingual PDF: en, pl, or de (must differ from company's primary language) |
| discount_percentage | number | Discount percentage (0-100) |
Response:
✓ Invoice created successfully!
Invoice Details:
- ID: 42
- Number: Not yet assigned (draft)
- Client: Acme Corp
- Total: 1,230.00 EUR
- Status: draft
- Due Date: 2025-01-29
- Items: 1
Items:
• Web Development: 10 × 100.00 EUR (VAT: 23%)
Next Steps:
- Use GetInvoiceTool (id: 42) to view full details
- Use UpdateInvoiceTool (id: 42) to make changes
- Use ChangeInvoiceStatusTool (id: 42, action: 'issue') to issue the invoice
- Use SendInvoiceEmailTool (id: 42) to send to client
update_invoice
Update an existing invoice (must be in draft status).
Input Schema:
{
"id": 42,
"client_id": 123,
"payment_terms": 30,
"payment_method": "transfer",
"bank_account_id": 1,
"notes": "Updated notes (use empty string to clear)",
"internal_notes": "Private notes",
"issue_location": "Kraków",
"purchase_order_number": "PO-2025-002",
"split_payment": true,
"pdf_secondary_language": "de",
"discount_percentage": 10,
"items": [
{
"description": "Updated service",
"quantity": 5,
"unit_price": 200.00,
"vat_rate": 23
}
]
}
Required Fields: id or invoice_number
Note: Providing items replaces all existing invoice items.
Response:
Invoice updated successfully! Invoice #INV/001/01/2025 for Acme Corp.
Total: 1,230.00 EUR. Status: draft. Due date: 2025-01-29
list_invoices
List invoices with optional filtering.
Input Schema:
{
"status": "issued",
"client_id": 123,
"currency": "EUR",
"from_date": "2025-01-01",
"to_date": "2025-01-31",
"limit": 10
}
Status Options: draft, issued, sent, paid, overdue, cancelled
Response:
Found 3 invoice(s):
- Invoice #INV/001/01/2025 | Client: Acme Corp | Total: 1,230.00 EUR | Status: issued | Due: 2025-01-29 | Created: 2025-01-15
- Invoice #INV/002/01/2025 | Client: TechStart | Total: 2,500.00 EUR | Status: issued | Due: 2025-02-01 | Created: 2025-01-18
- Invoice #INV/003/01/2025 | Client: SmithCo | Total: 850.00 EUR | Status: paid | Due: 2025-01-25 | Created: 2025-01-11
get_invoice
Get detailed information about a specific invoice.
Input Schema:
{
"id": 42
}
Response:
Invoice #42:
- Invoice number: INV/001/01/2025
- Client: Acme Corp
- Company: My Company Ltd
- Total cents: 123000
- Currency: EUR
- Aasm state: issued
- Sale date: 2025-01-15
- Issue date: 2025-01-15
- Due date: 2025-01-29
- Payment method: bank_transfer
- Payment terms: 14
mark_invoice_paid
Mark an invoice as paid.
Input Schema:
{
"id": 42,
"payment_date": "2025-01-20"
}
Alternative: Use invoice_number instead of id
Response:
Invoice #INV/001/01/2025 marked as paid successfully!
Total: 1,230.00 EUR. Paid at: 2025-01-20
change_invoice_status
Change invoice status (issue, send, cancel).
Input Schema:
{
"id": 42,
"action": "issue"
}
Actions: issue, send_invoice, mark_paid, cancel
Response:
✓ Invoice status changed successfully!
Invoice: #INV/001/01/2025
Previous Status: draft
New Status: issued
send_invoice_email
Send invoice email to client (auto-issues draft invoices).
Input Schema:
{
"id": 42,
"recipient_email": "client@example.com",
"custom_message": "Thank you for your business!"
}
Response:
✓ Invoice sent successfully!
✓ Invoice was automatically issued before sending
Email Details:
- Recipient: client@example.com
- Invoice: #INV/001/01/2025
- Total: 1,230.00 EUR
- Due Date: 2025-01-29
- Status: sent
✓ Custom message included in email
Next Steps:
- Use GetInvoicePdfLinkTool (id: 42) to get preview link
- Use MarkInvoicePaidTool (id: 42) when payment is received
get_invoice_pdf_link
Get a link to view/download the invoice PDF.
Input Schema:
{
"id": 42
}
Response:
Invoice PDF Link: https://acme.quento.app/invoices/42.pdf
Note: Invoice must be issued or later to generate PDF
Client Tools
create_client
Create a new client.
Input Schema:
{
"name": "Acme Corporation",
"email": "contact@acme.com",
"tax_id": "1234567890",
"country": "PL",
"street": "ul. Główna 1",
"city": "Warsaw",
"postal_code": "00-001",
"currency": "EUR",
"default_payment_terms": 30
}
Required Fields: name, country
Response:
Client created successfully! ID: 123
update_client
Update an existing client.
Input Schema:
{
"id": 123,
"email": "newemail@acme.com",
"default_payment_terms": 45
}
Required Fields: id
Response:
Client updated successfully! ID: 123
get_client
Get client details.
Input Schema:
{
"id": 123
}
Response:
Client #123:
- Name: Acme Corporation
- Email: contact@acme.com
- Tax id: 1234567890
- Street: ul. Główna 1
- City: Warsaw
- Postal code: 00-001
- Country: PL
- Currency: EUR
- Default payment terms: 30
list_clients
List all clients with optional search.
Input Schema:
{
"search": "acme",
"limit": 50,
"offset": 0
}
Response:
Found 1 client(s):
Client: Acme Corporation
Email: contact@acme.com
Tax ID: 1234567890
Address: ul. Główna 1, Warsaw, 00-001, PL
Currency: EUR | Payment Terms: 30 days
ID: 123
Product Tools
create_product
Create a new product or service.
Input Schema:
{
"name": "Web Development",
"unit_price": 150.00,
"vat_rate": "23",
"unit": "h",
"sku": "WEB-DEV-01",
"description": "Hourly web development services",
"currency": "EUR"
}
Required Fields: name, unit_price
VAT Rates: 23, 8, 5, 0, zw. (exempt), np. (not applicable)
Units: pcs, kg, g, l, ml, m, m2, m3, h, day, month, year
Response:
Product created successfully!
- Name: Web Development
- Price: 150.00 EUR per h
- VAT: 23%
- SKU: WEB-DEV-01
- ID: 1
update_product
Update an existing product.
Input Schema:
{
"id": 1,
"name": "Web Development (Premium)",
"unit_price": 200.00,
"active": true
}
Required Fields: id
Response:
Product updated successfully!
- Name: Web Development (Premium)
- Price: 200.00 EUR per h
- VAT: 23%
- SKU: WEB-DEV-01
- Active: Yes
- ID: 1
get_product
Get product details.
Input Schema:
{
"id": 1
}
Response:
Product #1:
- Name: Web Development
- Price: 150.00 EUR per h
- VAT: 23%
- SKU: WEB-DEV-01
- Description: Hourly web development services
- Active: Yes
- Used on invoices: 12 time(s)
- Created: 2025-01-15
list_products
List all products/services.
Input Schema:
{
"search": "development",
"limit": 50
}
Response:
Found 2 products:
- Software Development (Hourly) | Price: 150.00 EUR | VAT: 23% | ID: 1
- Web Development (Project) | Price: 5000.00 EUR | VAT: 23% | ID: 2
Bank Account Tools
create_bank_account
Create a new bank account for a company. Bank accounts are used on invoices for payment instructions.
Input Schema:
{
"company_id": 1,
"bank_name": "mBank",
"account_number": "12345678901234567890123456",
"currency": "PLN",
"iban": "PL61109010140000071219812874",
"swift_code": "BREXPLPW",
"default": true,
"active": true
}
Required Fields: company_id, bank_name, account_number, currency
Currencies: PLN, EUR, USD, GBP
Response:
Bank account created successfully!
ID: 1
Company: My Company Ltd
Bank: mBank
Account: 12345678901234567890123456
Currency: PLN
IBAN: PL61109010140000071219812874
SWIFT: BREXPLPW
Default: Yes
Status: Active
update_bank_account
Update an existing bank account. Changes do NOT affect already-issued invoices.
Input Schema:
{
"id": 1,
"bank_name": "mBank S.A.",
"default": true,
"active": true
}
Required Fields: id
Response:
Bank account updated successfully!
ID: 1
Company: My Company Ltd
Bank: mBank S.A.
Account: 12345678901234567890123456
Currency: PLN
Default: Yes
Status: Active
Note: Already-issued invoices retain their original bank details.
list_bank_accounts
List bank accounts for a company.
Input Schema:
{
"company_id": 1,
"currency": "PLN",
"active_only": true
}
Response:
Bank Accounts:
## My Company Ltd
- ID: 1 | mBank | 12345678901234567890123456 | PLN [DEFAULT]
IBAN: PL61109010140000071219812874
SWIFT: BREXPLPW
- ID: 2 | Santander | 98765432109876543210987654 | EUR
IBAN: PL27114020040000300201355387
Company Tools
list_companies
List companies (sellers) in your account.
Input Schema:
{
"search": "acme",
"limit": 10
}
Response:
Found 2 company(ies):
- Acme Corp | Tax ID: 5260250274 | Currency: PLN | ID: 1
- Acme International | Tax ID: DE123456789 | Currency: EUR | ID: 2
create_company
Create a new company (seller) for issuing invoices.
Input Schema:
{
"name": "LUX MED Sp. z o.o.",
"country": "PL",
"currency": "PLN",
"locale": "pl",
"nip": "5272523421",
"regon": "017370029",
"street": "ul. Postępu 21C",
"city": "Warsaw",
"postal_code": "02-676",
"email": "kontakt@luxmed.pl",
"phone": "+48 22 332 28 00",
"website": "https://luxmed.pl",
"default_payment_terms": 14,
"invoice_number_pattern": "FV/{num}/{month}/{year}",
"default": false,
"active": true
}
Required Fields: name, country, currency
Country Codes: PL, DE, US, GB, FR, IT, ES, NL, BE, AT, CH
Tax IDs:
- For Polish companies: use nip (10 digits) and optionally regon
- For other countries: use tax_id
Response:
Company created successfully!
ID: 1
Name: LUX MED Sp. z o.o.
Country: PL
Currency: PLN
Locale: pl
NIP: 5272523421
REGON: 017370029
Address: ul. Postępu 21C, Warsaw, 02-676, PL
Email: kontakt@luxmed.pl
Phone: +48 22 332 28 00
Website: https://luxmed.pl
Payment terms: 14 days
Invoice pattern: FV/{num}/{month}/{year}
Status: Active
Next steps: Use create_bank_account to add a bank account for this company.
update_company
Update an existing company's details.
Input Schema:
{
"id": 1,
"name": "LUX MED Sp. z o.o.",
"email": "nowy-email@luxmed.pl",
"default_payment_terms": 30,
"default": true
}
Required Fields: id
Note: Use empty string "" to clear optional text fields.
Response:
Company updated successfully!
ID: 1
Name: LUX MED Sp. z o.o.
Country: PL
Currency: PLN
Locale: pl
NIP: 5272523421
Address: ul. Postępu 21C, Warsaw, 02-676, PL
Email: nowy-email@luxmed.pl
Payment terms: 30 days
Default company: Yes
Status: Active
get_company
Get detailed information about a company.
Input Schema:
{
"id": 1
}
Alternative: Use name (partial match) or nip instead of id
Response:
=== LUX MED Sp. z o.o. ===
Basic Information:
ID: 1
Country: PL
Currency: PLN
Locale: pl
Status: Active
Default: Yes
Tax Information:
NIP: 5272523421
REGON: 017370029
Address:
Street: ul. Postępu 21C
City: Warsaw
Postal Code: 02-676
Contact:
Email: kontakt@luxmed.pl
Phone: +48 22 332 28 00
Website: https://luxmed.pl
Invoice Settings:
Payment Terms: 14 days
Number Pattern: FV/{num}/{month}/{year}
Bank Accounts:
- mBank: 12345678901234567890123456 (PLN) (default) [ID: 1]
KSeF (Polish e-Invoice):
Status: Enabled (token)
Environment: production
lookup_company
Look up company data from the Polish VAT Registry using NIP (tax ID). Returns company name, address, VAT status, REGON, KRS, registered bank accounts, email, and website. Use this to auto-fill client data.
Input Schema:
{
"nip": "5260250274",
"date": "2025-01-15"
}
Required Fields: nip
NIP Format: Can include dashes (e.g., "526-025-02-74") or just digits
Response:
# Company Found
**Name:** Example Company Sp. z o.o.
**NIP:** 526-025-02-74
**VAT Status:** Active (Czynny) ✓
**REGON:** 012345678
**KRS:** 0000123456
## Address
**Street:** ul. Przykładowa 1
**City:** Warsaw
**Postal Code:** 00-001
**Country:** PL
## Contact
**Email:** contact@example.com
**Website:** https://example.com
## Registered Bank Accounts
- PL 61 1090 1014 0000 0712 1981 2874
- PL 27 1140 2004 0000 3002 0135 5387
---
_Data from Polish VAT Registry (date: 2025-01-15)_
KSeF Tools (Polish e-Invoice System)
KSeF (Krajowy System e-Faktur) is Poland's national e-invoicing system. These tools allow you to submit invoices to KSeF and track their status.
Prerequisites: - Company must be Polish (country: PL) - Company must have KSeF configured with a valid authorization token - Invoice must be issued before submitting to KSeF
submit_invoice_to_ksef
Submit an invoice to Poland's KSeF system.
Input Schema:
{
"id": 42
}
Alternative: Use invoice_number instead of id
Response:
KSeF submission initiated successfully!
Submission Details:
- Submission ID: 1
- Invoice: INV/001/01/2025
- Company: My Company Ltd (NIP: 5260250274)
- Environment: production
- Status: pending
The submission is being processed in the background. This typically takes 10-60 seconds.
Next Steps:
- Use GetKsefStatusTool (invoice_id: 42) to check submission status
- Once accepted, use GetKsefUpoTool (invoice_id: 42) to get the official confirmation (UPO)
get_ksef_status
Check the KSeF submission status for an invoice.
Input Schema:
{
"invoice_id": 42
}
Alternative: Use invoice_number or submission_id
Response:
KSeF Status for Invoice INV/001/01/2025
==================================================
Submission #1 (ID: 1)
------------------------------
Status: ACCEPTED
Created: 2025-01-15 10:30:00
Submitted: 2025-01-15 10:30:15
KSeF Reference: 1234567890-20250115-ABC123DEF456
Next Steps:
- Use GetKsefUpoTool to get the official confirmation (UPO)
- The KSeF reference number can be used for official correspondence
Status Values:
| Status | Description |
|--------|-------------|
| pending | Waiting to be processed |
| submitted | Sent to KSeF, awaiting response |
| accepted | Successfully accepted by KSeF |
| rejected | Rejected by KSeF (check error message) |
| error | Technical error (can retry) |
list_ksef_submissions
List recent KSeF submissions with their statuses.
Input Schema:
{
"status": "accepted",
"company_id": 1,
"limit": 20
}
Status Filter: pending, submitted, accepted, rejected, error
Response:
KSeF Submissions
============================================================
Summary: 25 total submissions
- pending: 1
- submitted: 2
- accepted: 20
- rejected: 1
- error: 1
Recent Submissions (showing 20):
------------------------------------------------------------
[OK] #20 | Invoice: INV/020/01/2025 | Company: My Company Ltd | 2025-01-20 14:30
KSeF Ref: 1234567890-20250120-XYZ789
[OK] #19 | Invoice: INV/019/01/2025 | Company: My Company Ltd | 2025-01-19 11:15
KSeF Ref: 1234567890-20250119-DEF456
[X] #18 | Invoice: INV/018/01/2025 | Company: My Company Ltd | 2025-01-18 09:00
Error: Invalid VAT rate for item 2
Use GetKsefStatusTool (submission_id: ID) for detailed information about a specific submission.
Statistics Tools
get_statistics
Get invoice statistics and analytics.
Input Schema:
{
"period": "current_month",
"currency": "EUR"
}
Period Options: current_month, last_month, current_year, last_year, all_time
Response:
Invoice Statistics (Current month) (EUR only):
Overview:
- Total Invoices: 15
- Draft: 2
- Issued: 5
- Sent: 3
- Paid: 4
- Overdue: 1
- Cancelled: 0
Revenue:
- Total Revenue (Paid): 12,500.00 EUR
- Outstanding Amount: 8,300.00 EUR
Top 5 Clients by Revenue:
- Acme Corp: 5,000.00 EUR
- TechStart: 3,500.00 EUR
- SmithCo: 2,000.00 EUR
Request & Response Format
JSON-RPC 2.0 Protocol
All MCP communication uses JSON-RPC 2.0 over HTTP.
Request Structure:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "create_invoice",
"arguments": {
"client_id": 123,
"company_id": 456,
"items": [...]
}
}
}
Success Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "Invoice created successfully! ID: 42"
}
]
}
}
Error Response:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32600,
"message": "Invalid Request",
"data": {
"details": "Missing required parameter: client_id"
}
}
}
MCP Tool Response Format
All tools return responses in a consistent format with an array of content objects:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "Human-readable result message"
}
]
}
}
Future Support (not yet implemented):
- type: "image" - Embedded images
- type: "resource" - File attachments
Error Handling
Common Error Codes
| Code | Meaning | Example |
|---|---|---|
-32700 | Parse error | Invalid JSON |
-32600 | Invalid Request | Missing jsonrpc field |
-32601 | Method not found | Unknown tool name |
-32602 | Invalid params | Missing required field |
-32603 | Internal error | Database error |
401 | Unauthorized | Missing/invalid API key |
403 | Forbidden | API key doesn't match subdomain |
404 | Not Found | Resource doesn't exist |
422 | Unprocessable | Validation failed |
Tool-Level Errors
Tools return user-friendly error messages in the response text:
Example - Client Not Found:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "Client not found"
}
]
}
}
Example - Validation Error:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "Failed to create invoice: Client can't be blank, Items can't be empty"
}
]
}
}
Error Handling Best Practices
1. Check HTTP Status First:
if (response.status === 401) {
console.error("Authentication failed - check API key");
}
2. Parse JSON-RPC Error:
const data = await response.json();
if (data.error) {
console.error(`MCP Error: ${data.error.message}`);
}
3. Handle Tool Errors:
const text = data.result.content[0].text;
if (text.includes("not found") || text.includes("Failed")) {
console.error(`Tool Error: ${text}`);
}
Best Practices
Security
1. API Key Management:
# ✅ Good: Use environment variables
export QUENTO_API_KEY="test_abc123..."
# ❌ Bad: Hardcode in source code
api_key = "test_abc123..." # NEVER DO THIS
2. Rotate Keys Regularly:
Rotate your API keys every 90 days for enhanced security. You can generate a new key from Settings → Integrations → MCP API.
Performance
1. Use Pagination:
{
"method": "tools/call",
"params": {
"name": "list_invoices",
"arguments": {
"limit": 20,
"offset": 0
}
}
}
2. Filter Server-Side:
// ✅ Good: Filter in database
{"status": "paid", "currency": "EUR"}
// ❌ Bad: Fetch all and filter client-side
{"limit": 1000}
3. Cache Tool List:
// Cache tools/list response for 1 hour
const tools = await fetchAndCache('/mcp', 'tools/list', 3600);
Data Integrity
1. Validate Before Sending:
// ✅ Good: Validate required fields
if (!client_id || !items.length) {
throw new Error("Missing required fields");
}
2. Handle Partial Failures:
// When creating multiple invoices, handle each error separately
const results = await Promise.allSettled(
invoices.map(inv => createInvoice(inv))
);
Code Examples
JavaScript/Node.js
Initialize MCP Client:
const fetch = require('node-fetch');
class QuentoMCP {
constructor(subdomain, apiKey) {
this.baseUrl = `https://${subdomain}.quento.app/mcp`;
this.apiKey = apiKey;
this.requestId = 1;
}
async call(method, params = {}) {
const response = await fetch(this.baseUrl, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
jsonrpc: '2.0',
id: this.requestId++,
method,
params
})
});
const data = await response.json();
if (data.error) {
throw new Error(data.error.message);
}
return data.result;
}
async initialize() {
return this.call('initialize', {
protocolVersion: '2024-11-05',
capabilities: {},
clientInfo: { name: 'quento-js-client', version: '1.0.0' }
});
}
async listTools() {
return this.call('tools/list');
}
async callTool(name, arguments) {
const result = await this.call('tools/call', { name, arguments });
return result.content[0].text;
}
}
// Usage
const client = new QuentoMCP('acme', process.env.QUENTO_API_KEY);
await client.initialize();
// Create invoice
const result = await client.callTool('create_invoice', {
client_id: 123,
company_id: 456,
items: [
{
description: 'Web Development',
quantity: 10,
unit_price: 100,
vat_rate: 23,
unit: 'h'
}
]
});
console.log(result);
Python
MCP Client with Ollama Integration:
import requests
import json
class QuentoMCP:
def __init__(self, subdomain, api_key):
self.base_url = f"https://{subdomain}.quento.app/mcp"
self.api_key = api_key
self.request_id = 1
def call(self, method, params=None):
response = requests.post(
self.base_url,
headers={
'Authorization': f'Bearer {self.api_key}',
'Content-Type': 'application/json'
},
json={
'jsonrpc': '2.0',
'id': self.request_id,
'method': method,
'params': params or {}
}
)
self.request_id += 1
data = response.json()
if 'error' in data:
raise Exception(data['error']['message'])
return data['result']
def initialize(self):
return self.call('initialize', {
'protocolVersion': '2024-11-05',
'capabilities': {},
'clientInfo': {'name': 'quento-py-client', 'version': '1.0.0'}
})
def list_tools(self):
return self.call('tools/list')
def call_tool(self, name, arguments):
result = self.call('tools/call', {'name': name, 'arguments': arguments})
return result['content'][0]['text']
# Usage
client = QuentoMCP('acme', 'test_abc123...')
client.initialize()
# List invoices
result = client.call_tool('list_invoices', {
'status': 'paid',
'limit': 10
})
print(result)
cURL
List Available Tools:
curl -X POST https://acme.quento.app/mcp \
-H "Authorization: Bearer test_abc123..." \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}'
Create Invoice:
curl -X POST https://acme.quento.app/mcp \
-H "Authorization: Bearer test_abc123..." \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "create_invoice",
"arguments": {
"client_id": 123,
"company_id": 456,
"items": [
{
"description": "Web Development",
"quantity": 10,
"unit_price": 100,
"vat_rate": 23,
"unit": "h"
}
]
}
}
}'
Troubleshooting
Common Issues
Issue: "Invalid API key"
Cause: API key is incorrect or doesn't match the subdomain
Solution:
- Verify you're using the correct API key from your account settings
- Check that the subdomain in the URL matches your account
- Ensure the Authorization header is properly formatted: Bearer YOUR_API_KEY
- Regenerate your API key if necessary from Settings → Integrations → MCP API
Issue: "Client not found"
Cause: Client ID doesn't exist or belongs to different account
Solution:
# List all clients
curl -X POST https://yoursubdomain.quento.app/mcp \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_clients",
"arguments": {}
}
}'
Issue: "Failed to create invoice: validation errors"
Cause: Missing required fields or invalid data
Solution:
Check the error message for specific validation failures:
- Client can't be blank - Missing client_id
- Items can't be empty - Missing items array
- VAT rate is invalid - Check VAT rate format (use number, not string)
Example Fix:
// ❌ Bad
{
"vat_rate": "23%"
}
// ✅ Good
{
"vat_rate": 23
}
Issue: "Method not found"
Cause: Tool name is incorrect
Solution: List all available tools:
curl -X POST https://yoursubdomain.quento.app/mcp \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}'
Issue: "Invoice cannot be marked as paid"
Cause: Invoice is in draft or cancelled status
Solution: Issue the invoice first:
{
"name": "change_invoice_status",
"arguments": {
"id": 42,
"action": "issue"
}
}
Then mark as paid:
{
"name": "mark_invoice_paid",
"arguments": {
"id": 42
}
}
Rate Limits
Current Limits: - 100 requests/minute per API key - 1000 requests/hour per account
Rate Limit Response:
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Try again in 60 seconds."
}
}
Best Practice: Implement exponential backoff:
async function callWithRetry(fn, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
if (error.code === 429 && i < maxRetries - 1) {
await sleep(Math.pow(2, i) * 1000);
continue;
}
throw error;
}
}
}
Resources
Official Documentation
- MCP Specification: https://github.com/modelcontextprotocol/specification
- Quento Documentation: https://docs.quento.app
- MCP API Documentation: https://docs.quento.app/api/mcp
- REST API Documentation: https://docs.quento.app/api/v1
Community & Support
- Email Support: support@quento.app
- Community Forum: https://community.quento.app
Changelog
Version 1.2.0 (Current)
Released: 2025-12-05
New Features: - ✅ Company Management: Full CRUD for companies/sellers (create, update, get, list) - Create companies with Polish NIP/REGON or international tax IDs - Configure invoice number patterns, payment terms, locale - Automatic NIP validation for Polish companies
Security Improvements:
- ❌ Removed all delete_* actions from MCP API for safety
- Deletions must be performed through the web UI
- Use update_* with active: false to deactivate records instead
- ❌ Removed create_company and update_company tools
- Company management is handled through the web UI during account setup
- Prevents accidental data corruption or duplicate companies
Tool Count: 26/30 (4 slots reserved for future use)
Version 1.1.0
Released: 2025-12-04
New Features: - ✅ Bank Account Management: Full CRUD for bank accounts (create, update, get, delete, list) - ✅ KSeF Integration: Submit invoices to Poland's e-invoice system (submit, status, UPO, list) - ✅ Product Management: Full CRUD for products (create, update, get, delete) - ✅ Company Lookup: Look up Polish companies by NIP from VAT Registry - ✅ Client Deletion: Delete clients (with invoice protection)
Enhanced Invoice Tools:
- ✅ bank_account_id - Assign bank account for transfer payments
- ✅ internal_notes - Private notes not visible on PDF
- ✅ issue_location - Place of issue for invoices
- ✅ purchase_order_number - Client's PO number reference
- ✅ split_payment - Polish VAT split payment (MPP) support
- ✅ pdf_secondary_language - Bilingual PDF support (en/pl/de)
Security Improvements: - ✅ Safe date parsing (ISO 8601 only) - ✅ Error message sanitization - ✅ Input filtering for CRUD operations
Version 1.0.0
Released: 2025-01-28
Features: - ✅ Full invoice CRUD operations - ✅ Client management (create, update, list, get) - ✅ Product listing - ✅ Statistics and analytics - ✅ Email automation - ✅ PDF generation - ✅ Multi-tenant account scoping - ✅ JSON-RPC 2.0 over HTTPS
License
Quento MCP API is proprietary software.
© 2025 Quento. All rights reserved.
For licensing inquiries, contact: support@quento.app
Last Updated: December 5, 2025
API Version: 1.0.0
Protocol Version: 2024-11-05