MCP Integration
Model Context Protocol (MCP) endpoint for AI agent integration with Claude Code, GPT, and other AI assistants.
Endpoint
POST https://api.thelawin.dev/mcpProtocol
- Protocol: JSON-RPC 2.0 over HTTP
- Version:
2024-11-05 - Mode: Sandbox (watermarks applied, unlimited requests)
Authentication
Sandbox Mode Only
MCP requests always run in sandbox mode and do not require API keys. Generated PDFs will have watermarks. Use the regular REST API for production invoices.
Available Tools
1. thelawin_generate
Generate a ZUGFeRD/Factur-X compliant PDF invoice.
Input Schema:
{
"template": "minimal", // minimal | classic | compact
"locale": "en", // de | en | fr | es | it
"invoice": {
"number": "MCP-001",
"date": "2026-01-07",
"seller": {
"name": "Test GmbH",
"vat_id": "DE123456789",
"city": "Berlin",
"country": "DE"
},
"buyer": {
"name": "Customer AG",
"city": "München",
"country": "DE"
},
"items": [{
"description": "Service",
"quantity": 1,
"unit_price": 100
}]
}
}Output: Invoice PDF as base64 resource + metadata
2. thelawin_validate
Validate an existing PDF for ZUGFeRD/Factur-X compliance.
Input Schema:
{
"pdf_base64": "JVBERi0xLjQK..."
}Output: Validation result with errors/warnings
JSON-RPC Methods
initialize
Initialize MCP session.
Request:
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {
"name": "claude-code",
"version": "1.0.0"
}
}
}Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {
"tools": {
"listChanged": false
}
},
"serverInfo": {
"name": "thelawin-api",
"version": "0.1.0"
}
}
}Headers:
Mcp-Session-Id: Session ID (UUID)
initialized
Acknowledge initialization (notification, no response).
Request:
{
"jsonrpc": "2.0",
"method": "initialized"
}Response: 202 Accepted (no body)
tools/list
List available tools.
Request:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}Response:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"tools": [
{
"name": "thelawin_generate",
"description": "Generate a ZUGFeRD/Factur-X compliant PDF invoice from structured data. Returns a valid PDF/A-3 with embedded XML.",
"inputSchema": {
"type": "object",
"required": ["invoice"],
"properties": {
"template": { "type": "string", "enum": ["minimal", "classic", "compact"] },
"locale": { "type": "string", "enum": ["de", "en", "fr", "es", "it"] },
"invoice": { ... }
}
}
},
{
"name": "thelawin_validate",
"description": "Validate an existing PDF for ZUGFeRD/Factur-X compliance.",
"inputSchema": { ... }
}
]
}
}tools/call
Execute a tool.
Request:
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "thelawin_generate",
"arguments": {
"template": "minimal",
"invoice": {
"number": "MCP-001",
"date": "2026-01-07",
"seller": { "name": "Test GmbH" },
"buyer": { "name": "Customer AG" },
"items": [{
"description": "Service",
"quantity": 1,
"unit_price": 100
}]
}
}
}
}Response:
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"content": [
{
"type": "text",
"text": "Invoice generated successfully!\n\nFilename: rechnung-MCP-001.pdf\nFormat: ZUGFERD\nProfile: EN16931\nVersion: ZUGFeRD 2.3\n\nPDF size: ~14KB\n\nThe PDF is available as a resource below."
},
{
"type": "resource",
"resource": {
"uri": "data:application/pdf;base64,JVBERi0xLjQK...",
"mimeType": "application/pdf",
"text": "JVBERi0xLjQK..."
}
}
],
"isError": false
}
}Error Handling
Tool Error
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"content": [{
"type": "text",
"text": "Error: Missing 'invoice' in arguments"
}],
"isError": true
}
}JSON-RPC Error
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32601,
"message": "Method not found: unknown_method"
}
}Error Codes:
-32700: Parse error-32600: Invalid request-32601: Method not found-32602: Invalid params-32603: Internal error
Usage Examples
curl
# 1. Initialize
curl -X POST https://api.thelawin.dev/mcp \
-H "Content-Type: application/json" \
-H "MCP-Protocol-Version: 2024-11-05" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"clientInfo": { "name": "curl", "version": "1.0.0" }
}
}'
# 2. List Tools
curl -X POST https://api.thelawin.dev/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}'
# 3. Generate Invoice
curl -X POST https://api.thelawin.dev/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "thelawin_generate",
"arguments": {
"invoice": {
"number": "TEST-001",
"date": "2026-01-07",
"seller": { "name": "Company" },
"buyer": { "name": "Customer" },
"items": [{ "description": "Product", "quantity": 1, "unit_price": 100 }]
}
}
}
}'Claude Code
thelawin.dev's MCP server can be used directly in Claude Code:
// MCP server is available as HTTP endpoint
// Claude Code will discover and use it automaticallyClaude Code Integration
Claude Code can directly interact with the MCP endpoint without additional configuration. The API is discoverable via /llms.txt.
Python
import requests
import json
# MCP client
class TheleminMCPClient:
def __init__(self, base_url="https://api.thelawin.dev/mcp"):
self.base_url = base_url
self.session_id = None
self.next_id = 1
def call(self, method, params=None):
request = {
"jsonrpc": "2.0",
"id": self.next_id,
"method": method
}
if params:
request["params"] = params
headers = {"Content-Type": "application/json"}
if self.session_id:
headers["Mcp-Session-Id"] = self.session_id
response = requests.post(self.base_url, json=request, headers=headers)
if "Mcp-Session-Id" in response.headers:
self.session_id = response.headers["Mcp-Session-Id"]
self.next_id += 1
return response.json()
def initialize(self):
return self.call("initialize", {
"protocolVersion": "2024-11-05",
"clientInfo": {"name": "python-client", "version": "1.0.0"}
})
def list_tools(self):
return self.call("tools/list")
def generate_invoice(self, invoice_data, template="minimal"):
return self.call("tools/call", {
"name": "thelawin_generate",
"arguments": {
"template": template,
"invoice": invoice_data
}
})
# Usage
client = TheleminMCPClient()
client.initialize()
result = client.generate_invoice({
"number": "PYTHON-001",
"date": "2026-01-07",
"seller": {"name": "Test Co"},
"buyer": {"name": "Customer"},
"items": [{"description": "Service", "quantity": 1, "unit_price": 100}]
})
print(result)TypeScript
interface JsonRpcRequest {
jsonrpc: '2.0';
id?: number | string;
method: string;
params?: any;
}
interface JsonRpcResponse {
jsonrpc: '2.0';
id?: number | string;
result?: any;
error?: {
code: number;
message: string;
};
}
class TheleminMCPClient {
private baseUrl: string;
private sessionId?: string;
private nextId = 1;
constructor(baseUrl = 'https://api.thelawin.dev/mcp') {
this.baseUrl = baseUrl;
}
async call(method: string, params?: any): Promise<JsonRpcResponse> {
const request: JsonRpcRequest = {
jsonrpc: '2.0',
id: this.nextId++,
method,
...(params && { params })
};
const headers: Record<string, string> = {
'Content-Type': 'application/json'
};
if (this.sessionId) {
headers['Mcp-Session-Id'] = this.sessionId;
}
const response = await fetch(this.baseUrl, {
method: 'POST',
headers,
body: JSON.stringify(request)
});
const sessionId = response.headers.get('Mcp-Session-Id');
if (sessionId) {
this.sessionId = sessionId;
}
return response.json();
}
initialize() {
return this.call('initialize', {
protocolVersion: '2024-11-05',
clientInfo: { name: 'typescript-client', version: '1.0.0' }
});
}
listTools() {
return this.call('tools/list');
}
generateInvoice(invoiceData: any, template = 'minimal') {
return this.call('tools/call', {
name: 'thelawin_generate',
arguments: { template, invoice: invoiceData }
});
}
}
// Usage
const client = new TheleminMCPClient();
await client.initialize();
const result = await client.generateInvoice({
number: 'TS-001',
date: '2026-01-07',
seller: { name: 'Test Co' },
buyer: { name: 'Customer' },
items: [{ description: 'Service', quantity: 1, unit_price: 100 }]
});
console.log(result);MCP vs REST API
| Feature | MCP Endpoint | REST API |
|---|---|---|
| Protocol | JSON-RPC 2.0 | RESTful HTTP |
| Authentication | None (sandbox) | X-API-Key |
| Watermark | Yes (always) | No (live keys) |
| Quota | Unlimited | Plan-based |
| Use Case | AI agents, testing | Production |
| Output Format | MCP ContentBlock | JSON |
When to use MCP
Use MCP for:
- AI Agent Integration (Claude Code, GPT, etc.)
- Testing (unlimited sandbox requests)
- Prototyping (quick testing without API key)
Use REST API for:
- Production (no watermarks)
- High Volume (better performance)
- Full Features (validation, account management)
Specification
Full MCP specification: modelcontextprotocol.io
Further Reading
- Invoice Formats - All 9 supported formats
- Generate API - REST API reference
- MCP SDK - Official MCP client library