Build with Consultainer
MCP Server
Connect Claude Code, Claude Desktop, Cursor or another AI agent to your Consultainer data
Consultainer has a built-in MCP server. Connect an AI agent to it and the agent can read and change your Consultainer data directly: check what's unbilled, log hours, comment on a task, or generate an invoice, without opening a browser tab.
Who can do this: anyone in the organization. The agent acts as you, so it sees what you see and can only do what your role allows (some tools are owner and admin only, see Available tools).
What you need
- The server URL: your instance's address plus
/api/mcp, for examplehttps://consultainer.example.com/api/mcp. The transport is Streamable HTTP. - An API key, sent on every request as the header
Authorization: Bearer <your API key>. It's the same kind of key the REST API uses.
Create an API key
Open your profile
Click your avatar in the top-right corner and choose Profile.
Name the key
In the API keys & AI agents card, type a name under New key name (for example, Claude Code on my laptop) and click Create key.
Copy it now
The key (it starts with
ch_live_) is shown once. Click the copy button next to it. If you lose it, revoke it and create a new one.Copy your client's setup
Below the key, Connect an AI agent shows the exact setup for Claude Code, Cursor, Claude Desktop and Other, already filled in with your instance's URL and the new key. Pick your client and click Copy.
A key belongs to the organization you had open when you created it. If you're in more than one organization, switch to the right one first, and create a separate key for each.
To revoke a key, click the trash icon next to it in the same card. It stops working immediately.
Connect a client
In the examples below, replace <your-instance> with your instance's address
and <your API key> with the key. The Connect an AI agent box in the app
fills both in for you.
Claude Code
Add the server
Run this in a terminal:
claude mcp add --transport http consultainer https://<your-instance>/api/mcp \ --header "Authorization: Bearer <your API key>"Check it
Start Claude Code and run
/mcp. consultainer should be listed as connected. Then ask, for example, "what's unbilled this month?".
Cursor
Edit the config
Open
~/.cursor/mcp.json(all projects) or.cursor/mcp.jsonin a project, and add:{ "mcpServers": { "consultainer": { "url": "https://<your-instance>/api/mcp", "headers": { "Authorization": "Bearer <your API key>" } } } }If the file already has an
mcpServersobject, add theconsultainerentry inside it.Enable it
Open Cursor's settings, find the MCP section, and make sure consultainer is switched on. It should show a green dot and its list of tools.
Claude Desktop
Claude Desktop's config file only starts local servers, so it reaches
Consultainer through the mcp-remote
bridge. You need Node.js installed.
Open the config file
In Claude Desktop, open Settings → Developer and click Edit Config. This opens
claude_desktop_config.json.Add the server
{ "mcpServers": { "consultainer": { "command": "npx", "args": ["-y", "mcp-remote", "https://<your-instance>/api/mcp", "--header", "Authorization:${CONSULTAINER_AUTH}"], "env": { "CONSULTAINER_AUTH": "Bearer <your API key>" } } } }The key goes in
envso the space inBearer …survives. If the file already has anmcpServersobject, add theconsultainerentry inside it.Restart Claude Desktop
Quit it fully and reopen it. consultainer appears under the tools (connectors) menu in a new chat.
VS Code
Add to .vscode/mcp.json in your workspace (or your user MCP configuration):
{
"servers": {
"consultainer": {
"type": "http",
"url": "https://<your-instance>/api/mcp",
"headers": { "Authorization": "Bearer <your API key>" }
}
}
}Any other client
Any MCP client that can connect to a remote server over Streamable HTTP and send a custom header works:
| Setting | Value |
|---|---|
| URL | https://<your-instance>/api/mcp |
| Transport | Streamable HTTP |
| Header | Authorization: Bearer <your API key> |
Clients that can only sign in with OAuth, and can't send a custom header,
can't connect. If your client only runs local (stdio) servers, use
mcp-remote as in the Claude Desktop example.
Check it worked
Ask the agent "list my Consultainer clients". It should call list_clients
and answer with your clients. On Profile, the key now shows last used
with today's date.
Troubleshooting
- 401 / "Unauthorized" / the client says it needs to authenticate: the
header is missing or wrong, or the key was revoked. Check the header is
exactly
Authorization: Bearer ch_live_…and create a new key if needed. A key also stops working if its owner is removed from the organization. - Redirected to a login page, or HTML instead of JSON: something in
front of Consultainer is asking for a login. If the instance sits behind an
authenticating reverse proxy (Cloudflare Access, oauth2-proxy and so on),
let
/api/mcp(and/api/v1/*for the REST API) through without it. The API key is the authentication. - "Only owners and admins can …": that tool needs an owner or admin key.
- "Project not found." for a project you know exists: it's a confidential project you're not on, or the key belongs to a different organization.
- Claude Desktop shows the server as failed: check Node.js is installed
(
npx --versionin a terminal) and that the JSON is valid.
Available tools
Owner/admin-only tools say so. Everything else works for any role, limited to what that person can see.
Clients and projects
| Tool | What it does |
|---|---|
list_clients | List all clients in the organization, or those with one status (ACTIVE, INACTIVE, LEAD). Each has draft: true when it's a draft client from a Cal.com or Calendly booking. A member's key doesn't get the clients' shareToken; the same goes for every client and project tool below. |
create_client | Create a client. |
update_client | Update a client's details; requireClockTimes makes time on its projects need start and end times, and invoiceTimeDetail adds a time detail page to its invoices. Leave out status to keep it; ACTIVE on a draft client makes it a client (owners and admins). |
list_bookings | Meetings booked through Cal.com or Calendly (from, to, clientId, status): time, invitee, client (with draft), join link and the booking form's answers. Owners and admins get all; others the ones they host. |
list_projects | List projects you can see, optionally for one client. |
create_project | Create a project for a client. A member who makes it confidential is added to it so they keep access. |
update_project | Update a project's details. |
list_members | List the organization's members and their roles. For owner and admin keys, also each person's default billRate. |
list_agreements | A client's signed agreements pulled from DocuSign, Documenso or Ironclad: title, signed date, signers, provider link, and whether a signed copy is stored. Includes its projects' agreements you can see; pass projectId for one project. See Signed agreements. |
list_vault_links | A client's credential links: pointers to items in 1Password, Bitwarden or another password manager (label, note, provider, link). Never the secrets. Includes its projects' links you can see; pass projectId for one project's links. Read-only. See Credentials. |
Tasks
| Tool | What it does |
|---|---|
list_my_tasks | Your open (not done) tasks, optionally for one project, soonest due first. |
create_task | Create a task on a project, optionally with a dueDate (YYYY-MM-DD). An assignee must be able to see the project. |
update_task | Change a task's title, description, hour estimate or dueDate (null clears it; leave it out to keep it). |
update_task_status | Set a task to TODO, IN_PROGRESS or DONE. |
list_task_comments | A task's comments, oldest first. |
add_task_comment | Comment on a task. Notifies the assignee and watchers; @[Name](user:<userId>) mentions someone. Internal unless shareWithClient is true. Also posted to Linear on linked tasks unless postToLinear is false. |
delete_task_comment | Delete a comment: your own, or any as an owner or admin. |
watch_task | Follow or stop following a task's comments. |
Time
| Tool | What it does |
|---|---|
log_time | Log time on a project for yourself: hours, or startTime and endTime (HH:MM; hours are worked out), or all three. Returns the entry and any warnings, such as overlapping time. |
list_time_entries | Your time entries, optionally by date range or project, with each one's evidence attachments (names, types, and whether the client can see them). |
update_time_entry | Change one of your entries (not once it's invoiced). Takes the same hours, startTime and endTime as log_time; leaving the times out clears them. |
delete_time_entry | Delete one of your entries (not once it's invoiced). |
start_timer | Start a timer on a task or project. A running timer is stopped and logged first. |
stop_timer | Stop your timer and log it as a time entry with its start and end time. Optional timeZone (IANA, e.g. America/New_York) for those times; UTC by default. |
get_active_timer | Your running timer and how long it's been going, if any. |
submit_timesheet | Submit a week of your time for approval. |
list_pending_timesheets | Owner/admin: submitted timesheets waiting for review. |
review_timesheet | Owner/admin: approve a timesheet, or send it back with a note. |
list_meetings | Unsorted meetings from your connected calendars (last two weeks, already over), each with a suggested project and, for a Cal.com/Calendly booking, bookedBy and suggestedBillable. |
log_meeting | Log a meeting as time on a project, optionally for the whole recurring series. |
ignore_meeting | Mark a meeting as not project work, optionally for the whole series. |
Milestones and expenses
| Tool | What it does |
|---|---|
list_milestones | A project's milestones and deliverables (billable: false). |
create_milestone | Owner/admin: create a payment milestone (amount required), or a deliverable with billable: false (never invoiced). |
update_milestone | Owner/admin: change a milestone or deliverable, including billable (not once it's invoiced). |
complete_milestone | Owner/admin: mark a milestone complete with a note. Evidence files can only be uploaded in the app. |
reopen_milestone | Owner/admin: undo a milestone's completion (not once it's invoiced). |
list_expenses | List expenses, optionally by project or status. |
log_expense | Submit an expense. Receipts can only be uploaded in the app. Auto-approved for owners and admins, or under the organization's approval threshold. |
approve_expense | Owner/admin: approve a pending expense. |
reject_expense | Owner/admin: reject a pending expense. |
Estimates
| Tool | What it does |
|---|---|
list_estimates | List estimates, optionally by status or client, with their line items. A member doesn't see estimates for a confidential project they're not on. |
create_estimate | Owner/admin: create a draft estimate for a client with line items, optional scope text, expiry and proposed billing. Send it from the app. See Estimates. |
Invoices
| Tool | What it does |
|---|---|
list_invoices | List invoices, optionally by status, with isOverdue, daysOverdue, kind (STANDARD or DEPOSIT), amountPaid, creditApplied and balanceDue (a partly paid invoice stays SENT until its balance is 0). A member doesn't see invoices with a line on a confidential project they're not on (the invoice tools answer Invoice not found. for those). |
generate_invoice | Owner/admin: create a draft invoice from unbilled time, completed milestones and approved expenses. |
create_custom_invoice | Owner/admin: create a draft invoice for amounts you name, not logged work: lines of { description, amount }, e.g. Initial deposit, 500. deposit: true makes it an untaxed deposit whose payments become client credit. |
email_invoice | Owner/admin: email an invoice to the client with a tracked link to view and pay it. A draft is marked sent. attachPdf attaches the PDF too (default: the client's setting); includeTimesheet turns this invoice's timesheet on or off. |
schedule_invoice_send | Owner/admin: schedule a draft to be emailed at sendAt (an ISO date-time with a time zone), or null to cancel. See scheduling. |
get_invoice_activity | When an invoice was emailed, reminded and opened, plus its client link. |
mark_invoice_sent | Owner/admin: mark a draft invoice as sent (it needs at least one line item). |
mark_invoice_paid | Owner/admin: mark a sent invoice as paid by recording a payment for its whole balance due (dated today), optionally with the payment method. |
record_invoice_payment | Owner/admin: record money received against a sent invoice: amount (up to the balance due), optional receivedAt (YYYY-MM-DD, default today), method, reference, note. The invoice becomes paid when its balance reaches 0. |
list_invoice_payments | An invoice's payments, credit applied to it and credit notes issued against it, with its balance. |
void_invoice | Owner/admin: void a draft or sent invoice (not a paid one, and not one with payments or credit recorded). Its time entries, milestones and expenses go back to unbilled so they can be invoiced again (the result's released gives the counts); the voided invoice keeps its lines as a record. |
Audit
| Tool | What it does |
|---|---|
list_audit_log | Owner/admin: who changed what, newest first, filtered by person, record type, action and dates. |
Example
> What am I working on for Fintra Labs?
Auth flow security review, API migration (2 open tasks)
> Log 3.5 hours on the API migration
Logged 3.50h to Fintra Labs — API migration
Changes made through MCP are in the audit log with an API badge, under your name.