Quickstart guides
Quickstart 1: Connect the server in Claude Desktop
By the end of this tutorial, Claude Desktop will be connected to the Zenskar MCP Server and able to respond to prompts about your Zenskar data.
What you'll need:
- Claude Desktop installed
- A Zenskar account with API access
- Node.js 18 or later installed (
node --versionto check) - Your Zenskar Organization ID and API token (see Authentication Reference)
Step 1: Open your Claude Desktop config file
On macOS, open a terminal and run:
open ~/Library/Application\ Support/Claude/claude_desktop_config.jsonIf the file doesn't exist yet, create it:
mkdir -p ~/Library/Application\ Support/Claude
touch ~/Library/Application\ Support/Claude/claude_desktop_config.jsonOn Windows, the config file is located at:
%APPDATA%\Claude\claude_desktop_config.json
Step 2: Add the Zenskar server entry
Paste the following into the config file, replacing the placeholder values with your real credentials:
{
"mcpServers": {
"zenskar": {
"command": "npx",
"args": ["mcp-zenskar"],
"env": {
"ZENSKAR_ORGANIZATION": "your-org-id",
"ZENSKAR_AUTH_TOKEN": "your-bearer-token"
}
}
}
}Note: If you already have other MCP servers configured, add the
"zenskar"entry inside the existing"mcpServers"object — don't replace it.
Step 3: Restart Claude Desktop
Fully quit and reopen Claude Desktop. The server starts automatically on launch.
Step 4: Verify the connection
In Claude Desktop, type:
Show me my Zenskar customers.
If the connection is working, Claude will call listCustomers and return results from your account. If you see an error, check the Authentication Reference to confirm your credentials are correct.
Quickstart 2: Your first Zenskar workflow
This tutorial walks through a complete, realistic workflow: finding a customer, checking their contracts, and listing their unpaid invoices.
Prerequisite: Complete Quickstart 1 first.
Step 1: Find a customer
Ask Claude:
List my Zenskar customers.
Claude calls listCustomers and returns a paginated list. Note the ID or name of a customer you want to explore.
Step 2: Get the customer's contracts
Ask Claude:
Show me all contracts for [customer name].
Claude calls listContracts with a customer filter. You'll see contract IDs, statuses, and date ranges.
Step 3: Check for unpaid invoices
Ask Claude:
List all unpaid invoices for [customer name].
Claude calls listInvoices filtered by customer and status. You now have a clear picture of what's outstanding.
Step 4: Approve an invoice
Pick one of the unpaid invoices and ask:
Approve invoice [invoice ID].
Claude calls approveInvoice. The invoice status changes to approved and is ready for payment collection.
You've completed a full read-then-act workflow using natural language. The same pattern applies to any domain — contracts, payments, products, accounting.
{
"command": "node",
"args": ["/absolute/path/to/mcp-zenskar/src/server.js"],
"env": {
"ZENSKAR_ORGANIZATION": "your-org-id",
"ZENSKAR_AUTH_TOKEN": "your-token"
}
}Reference
Reference material is for looking things up. It is complete, accurate, and consistent. It does not explain how to accomplish goals.
Authentication Reference
Every tool invocation requires two parameters. The server resolves them in this order:
- Values passed directly in the tool call (highest priority)
ZENSKAR_ORGANIZATIONenvironment variableZENSKAR_AUTH_TOKENenvironment variable
Token format detection is automatic:
| Token format | Header sent |
|---|---|
Looks like a JWT (eyJ...) | Authorization: Bearer <token> |
| Any other format | x-api-key: <token> |
No credentials are stored or logged by the server.
Customers, Contacts & Addresses
Customers
| Tool | Description |
|---|---|
listCustomers | List customers with search, filtering, and pagination |
getCustomerById | Get a single customer by ID |
createCustomer | Create a customer with address and tax information |
updateCustomer | Partially update customer details |
Contacts
| Tool | Description |
|---|---|
listContacts | List contacts with pagination |
getContactById | Get a single contact by ID |
createContact | Create a contact for a customer |
updateContact | Update a contact's details |
Customer Addresses
| Tool | Description |
|---|---|
listCustomerAddresses | List addresses for a customer |
createCustomerAddress | Add an address to a customer |
updateCustomerAddress | Update an existing customer address |
Payment Methods
| Tool | Description |
|---|---|
listPaymentMethods | List payment methods for a customer |
attachPaymentMethod | Attach a payment method to a customer |
Contracts
| Tool | Description |
|---|---|
listContracts | List contracts; filter by status, customer, and dates |
getContractById | Get a contract with phases, pricings, and customer details |
createContract | Create a contract with phases and pricing |
updateContract | Update contract terms, status, pricing, or renewal policy |
deleteContract | Delete a draft contract |
getContractAmendments | Get the amendment history for a contract |
createContractPhase | Add a phase to a contract (add-ons, expansions) |
createContractPhasePricing | Add pricing to a contract phase |
expireContract | Expire an active contract |
createContractPrompt | Create a contract prompt |
extractContractFromRaw | Extract structured contract data from raw text using AI |
Invoices & Credit Notes
Invoices
| Tool | Description |
|---|---|
listInvoices | List invoices; filter by customer, status, and dates |
getInvoiceById | Get an invoice by ID |
getInvoiceByExternalId | Get an invoice by external ID |
getInvoiceGenerationStatus | Check the status of an async invoice generation job |
downloadInvoice | Download invoice data in JSON format |
getInvoiceContractJsonActuals | Get contract actuals associated with an invoice |
getInvoicePayments | Get successful payments mapped to an invoice |
getInvoicePaymentsById | Get successful payments for a specific invoice ID |
getInvoicePaymentsWithoutRefunds | Get original payment records, excluding refund rows |
getInvoiceLineItems | Get line items and pricing details for an invoice |
getInvoiceSummary | Get a summary view of an invoice |
getAllInvoiceTags | Get all available invoice tags |
generateInvoicePaymentLink | Generate a hosted payment link for an invoice |
payInvoice | Initiate payment for an invoice |
approveInvoice | Approve an invoice for billing |
voidInvoice | Void an approved, unpaid invoice |
generateInvoice | Generate an invoice for a contract and date range |
createInvoiceCreditNote | Create a credit note against an invoice |
createInvoiceCharge | Auto-charge an invoice via the configured payment gateway |
Credit Notes
| Tool | Description |
|---|---|
listCreditNotes | List credit notes with pagination |
getCreditNoteById | Get a credit note by ID |
Payments
| Tool | Description |
|---|---|
listAllPayments | List all payments with filtering, sorting, and refund records |
getPaymentById | Get a payment by ID |
createPayment | Record a manual payment against an invoice |
updatePayment | Update a payment's invoice allocations (payment_parts) |
deleteManualPayment | Delete a manual payment |
editManualPayment | Edit a manual payment's amount or payment method |
refundPayment | Refund a payment in full or partially |
Products, Plans & Quotes
Products
| Tool | Description |
|---|---|
listProducts | List products in the catalog |
getProductById | Get a product by ID |
createProduct | Create a product |
updateProduct | Update a product's details |
getProductPricings | Get all pricing configurations for a product |
createProductPricing | Create a new pricing configuration for a product |
Plans (Templates)
| Tool | Description |
|---|---|
listPlans | List plan templates |
getPlanById | Get a plan by ID, including phases and pricing |
createPlan | Create a plan template |
addProductsToPlan | Add products to an existing plan |
previewPlanEstimate | Preview estimated billing for a plan configuration |
Quotes
| Tool | Description |
|---|---|
createQuote | Create a quote or proposal |
previewQuoteEstimate | Preview estimated billing for a quote |
getQuoteById | Get a quote by ID |
acceptQuote | Accept a quote, converting it to a contract |
Accounting
| Tool | Description |
|---|---|
getChartOfAccounts | Get the full chart of accounts |
listAccounts | List GL accounts with filtering |
createAccount | Create a GL account |
listJournalEntries | List journal entries with filtering |
createJournalEntry | Create a manual journal entry |
getJournalEntry | Get a journal entry by ID with all its lines |
listJournalLines | List journal lines across all entries |
getBalanceSheet | Get the balance sheet report |
getIncomeStatement | Get the income statement (P&L) |
getAccountBalance | Get the balance for a specific GL account |
recogniseRevenue | Trigger revenue recognition up to a specified date |
Metrics, Events & Other
Billable Metrics (Aggregates)
| Tool | Description |
|---|---|
listAggregates | List billable metrics with filtering |
getAggregateSchemas | Show schemas for billable metrics |
getAggregateEstimates | Get estimates for a billable metric |
getAggregateById | Get a billable metric by ID |
getAggregateLogs | Get logs for a billable metric |
Usage Events (Raw Metrics)
| Tool | Description |
|---|---|
listRawMetrics | List usage events with filtering |
createRawMetric | Create a usage event schema |
getRawMetricById | Get a usage event by ID |
getRawMetricLogs | Get recent event rows for a usage event |
getRawMetricBySlug | Get a usage event by API slug |
ingestRawMetricEvent | Ingest a usage event into the system |
Custom Attributes & Tax
| Tool | Description |
|---|---|
listCustomAttributes | List custom attribute definitions |
createCustomAttribute | Create a custom attribute definition |
listTaxCategories | List tax categories |
createTaxCategory | Create a tax category |
Business Entities
| Tool | Description |
|---|---|
listBusinessEntities | List business entities |
getBusinessEntityById | Get a business entity by ID |
createBusinessEntity | Create a business entity |
updateBusinessEntity | Update a business entity |
Jobs & Utilities
| Tool | Description |
|---|---|
listJobs | List async jobs (invoice generation, revenue recognition, etc.) |
getJobById | Get a job by ID to check its current status |
createEntitlement | Create an entitlement |
getCustomerPortalConfiguration | Get the customer portal configuration |
getCurrentDateTime | Get the current date and time in multiple formats |
Core Concepts
Core concepts are for understanding. They provide context, rationale, and background — not instructions.
What is MCP and why does it matter?
MCP (Model Context Protocol) is an open protocol that allows AI assistants to call external tools and APIs in a structured, reliable way. Instead of asking Claude to "figure out" how to call an API from documentation, MCP gives Claude a typed, discoverable set of tools it can invoke directly.
The Zenskar MCP Server packages the entire Zenskar REST API surface — 103 operations — as MCP tools. This means you can interact with your billing, contracts, and accounting data using plain language, and Claude will translate your intent into precise API calls.
The key benefits are:
- No code required. You don't need to write API clients or know Zenskar's REST endpoints.
- Composability. Claude can chain multiple tool calls to accomplish complex workflows — for example, finding a customer, identifying their open invoices, and approving them in a single conversation.
- Auditability. Every action goes through the Zenskar API and is recorded in your account's audit log.
How the server handles authentication
The server is stateless — it stores no credentials between calls. Every tool invocation independently supplies authentication headers to the Zenskar API.
Token format detection is automatic. If your token is a JWT (starts with eyJ), it's sent as a Bearer token. Otherwise it's sent as an API key via the x-api-key header. You don't need to configure this; the server detects it at runtime.
This design means you can switch between API keys and JWT tokens without changing your configuration — you only need to update the token value.
How credentials are resolved at runtime
Credentials follow a clear precedence chain:
- Inline tool call parameters — if credentials are passed directly in a tool invocation, they take priority. This is useful when working across multiple Zenskar organizations in the same session.
- Environment variables —
ZENSKAR_ORGANIZATIONandZENSKAR_AUTH_TOKENserve as a fallback. Setting these in the config file is the recommended default for single-organization use.
If neither source provides credentials, the tool call will fail with an authentication error. The server will not attempt to prompt interactively outside of Claude's conversation context.
Design decisions and limitations
Why 103 separate tools?
MCP works best when each tool has a single, well-defined purpose. Rather than exposing a generic "call Zenskar API" tool, each operation is discrete. This lets Claude reason accurately about what it's doing, reduces ambiguity in tool selection, and makes error messages meaningful.
Asynchronous operations
Some Zenskar operations — invoice generation and revenue recognition in particular — are asynchronous. The server exposes listJobs and getJobById so Claude can poll for completion. In practice, Claude will do this automatically when it knows an operation is async, but you can also ask explicitly: "Check the status of job [job ID]."
No data stored by the server
The MCP server is a thin proxy. It receives tool calls, constructs HTTP requests to the Zenskar API, and returns the response. No data is cached, logged, or stored by the server itself. All persistence happens in your Zenskar account.
Scope of this server
The server covers the full published Zenskar API surface as of the time of release. If Zenskar adds new API endpoints after a given server version is published, those endpoints won't be available until the server package is updated. Run npm outdated -g mcp-zenskar to check for a newer version.
Updated about 3 hours ago
