MCP tools
The tools the Osorik MCP server exposes to agents.
Tools run as the signed-in member, in the team chosen when the client connected, with that member's role. Each tool does the same as the matching REST API endpoint and returns the same data, as both text and structured content.
Tools that read data need the read scope and are marked read-only. Tools that
create or change data need the write scope. Data follows the
API conventions: IDs are strings, amounts are decimal
strings, and absent values are null. List tools return
{ "data": [...], "nextCursor": ... }; pass nextCursor back as cursor for
the next page.
| Tool | Scope | REST equivalent |
|---|---|---|
get_team | read | GET /v1/team |
list_contacts | read | GET /v1/contacts |
get_contact | read | GET /v1/contacts/{contactId} |
create_contact | write | POST /v1/contacts |
update_contact | write | PATCH /v1/contacts/{contactId} |
list_categories | read | GET /v1/categories |
create_category | write | POST /v1/categories |
list_bank_accounts | read | GET /v1/bank-accounts |
list_transactions | read | GET /v1/transactions |
get_transaction | read | GET /v1/transactions/{transactionId} |
update_transaction | write | PATCH /v1/transactions/{transactionId} |
list_invoices | read | GET /v1/invoices |
get_invoice | read | GET /v1/invoices/{invoiceId} |
create_invoice_draft | write | POST /v1/invoices |
update_invoice_draft | write | PATCH /v1/invoices/{invoiceId} |
delete_invoice_draft | write | DELETE /v1/invoices/{invoiceId} |
get_invoice_settings | read | GET /v1/invoice-settings |
list_expenses | read | GET /v1/expenses |
get_expense | read | GET /v1/expenses/{expenseId} |
update_expense | write | PATCH /v1/expenses/{expenseId} |
list_projects | read | GET /v1/projects |
get_project | read | GET /v1/projects/{projectId} |
create_project | write | POST /v1/projects |
update_project | write | PATCH /v1/projects/{projectId} |
list_time_tasks | read | GET /v1/projects/{projectId}/tasks |
create_time_task | write | POST /v1/projects/{projectId}/tasks |
list_time_entries | read | GET /v1/time-entries |
create_time_entry | write | POST /v1/time-entries |
update_time_entry | write | PATCH /v1/time-entries/{entryId} |
delete_time_entry | write | DELETE /v1/time-entries/{entryId} |
get_timer | read | GET /v1/timer |
start_timer | write | POST /v1/timer/start |
stop_timer | write | POST /v1/timer/stop |
Team
get_team
Returns the team (workspace) the connection acts in.
| Property | Value |
|---|---|
| Arguments | None |
| Scope | read |
| REST equivalent | GET /v1/team |
Team
| Field | Type | Description |
|---|---|---|
id | string | Team ID |
name | string | Team name |
email | string or null | Contact email |
taxId | string or null | Tax identification number |
address | string or null | Street address |
zipCode | string or null | Postal code |
city | string or null | City |
state | string or null | State or region |
country | string | ISO 3166-1 alpha-2 country code, such as PT |
timeZone | string | IANA time zone, such as Europe/Lisbon |
website | string or null | Website URL |
logoUrl | string or null | URL of the team logo |
role | owner, admin, or member | Your role in the team |
Contacts
Contacts are the people and organizations the team pays (payees) or bills (clients).
list_contacts
Lists contacts by name, or by relevance when search is set.
| Property | Value |
|---|---|
| Arguments | search, role (client or payee), limit, cursor |
| Scope | read |
| REST equivalent | GET /v1/contacts |
get_contact
Returns one contact.
| Property | Value |
|---|---|
| Arguments | contactId |
| Scope | read |
| REST equivalent | GET /v1/contacts/{contactId} |
create_contact
Creates a contact. If the team already has a contact with the same tax ID and country, email, or legal name, that contact is returned instead.
| Property | Value |
|---|---|
| Arguments | name (required), entityType, industry, isClient, isPayee, and any contact field below |
| Scope | write |
| REST equivalent | POST /v1/contacts |
update_contact
Changes the fields sent. null clears an optional field; bankAccount and
billing replace the whole object.
| Property | Value |
|---|---|
| Arguments | contactId and any field to change |
| Scope | write |
| REST equivalent | PATCH /v1/contacts/{contactId} |
Contact
| Field | Type | Description |
|---|---|---|
id | string | Contact ID |
name | string | Display name |
legalName | string | Registered name |
entityType | string | organization, individual, government, nonprofit, or other |
industry | string | Industry, such as software_and_cloud |
isClient | boolean | Whether the team bills this contact |
isPayee | boolean | Whether the team pays this contact |
email, phone, website | string or null | Contact details |
address, city, state, zipCode | string or null | Postal address |
country | string or null | ISO 3166-1 alpha-2 country code |
taxId | string or null | Tax identification number |
note | string or null | Internal note |
categoryId | string or null | Default category for the contact's transactions |
bankAccount | object or null | bankName, country, currency, accountNumber, accountNumberType (iban or local), bic |
billing | object or null | For clients: email, bccEmails, address, city, state, zipCode, country, defaultCurrency, paymentTermsDays, reference, portalEnabled |
createdAt | string | ISO 8601 timestamp |
Categories
Accounting categories classify transactions, contacts and invoices. Only team owners and admins can create them.
list_categories
Lists the team's categories, grouped by type and sorted by name. A team has at
most 100 categories, so nextCursor is always null.
| Property | Value |
|---|---|
| Arguments | includeArchived (boolean, default false): also return archived categories |
| Scope | read |
| REST equivalent | GET /v1/categories |
create_category
Creates a custom category and returns it. Fails with
CATEGORY_MANAGEMENT_FORBIDDEN for members and CATEGORY_LIMIT_REACHED when
the team already has 100 categories.
| Property | Value |
|---|---|
| Arguments | name (required, up to 100 characters), description (required, up to 240 characters), type (required: income, expense, asset, tax, financing, owner, transfer or other), accountingCode (up to 32 characters) |
| Scope | write |
| REST equivalent | POST /v1/categories |
Category
| Field | Type | Description |
|---|---|---|
id | string | Category ID |
name | string | Category name |
description | string or null | What belongs in the category |
type | income, expense, asset, tax, financing, owner, transfer, or other | Accounting type |
accountingCode | string or null | Code in the accountant's chart of accounts |
archived | boolean | Whether the category is archived |
systemRole | internal_transfer or null | Workflow role of a required category; null for ordinary categories |
Bank accounts
list_bank_accounts
Lists the team's bank accounts with their account number, currency and last
reported balance. All accounts come back in one page, so nextCursor is always
null.
| Property | Value |
|---|---|
| Arguments | None |
| Scope | read |
| REST equivalent | GET /v1/bank-accounts |
Bank account
Each item in data:
| Field | Type | Description |
|---|---|---|
id | string | Bank account ID; use it as bankAccountId to filter transactions |
displayName | string or null | Name the team gave the account |
accountHolderName | string or null | Account holder |
bankName | string or null | Bank name |
accountType | string or null | Account nature, such as current, savings or card |
accountNumber | string or null | Account number, such as an IBAN |
accountNumberType | string or null | iban, bban, sort-code-account-number, us-routing-account-number, pan, masked-pan, msisdn or other |
bic | string or null | Swift/BIC code |
currency | string or null | ISO 4217 currency code |
balance | string or null | Last balance the bank reported, as a decimal string in currency |
Transactions
list_transactions
Lists the team's booked bank transactions, newest first. Archived transactions
are left out unless archived is true. A page can hold fewer items than
limit before the last one, so keep following nextCursor until it is null.
| Property | Value |
|---|---|
| Arguments | search, bankAccountId, categoryId (an ID or uncategorized), projectId, dateFrom, dateTo (YYYY-MM-DD), direction (credit or debit), status, archived, limit (1–100, default 25), cursor; all optional |
| Scope | read |
| REST equivalent | GET /v1/transactions |
get_transaction
Returns one transaction with its category, contact, project, note and bookkeeping status.
| Property | Value |
|---|---|
| Arguments | transactionId |
| Scope | read |
| REST equivalent | GET /v1/transactions/{transactionId} |
update_transaction
Sets the category, contact, project, note or archive flag of a transaction and
keeps the fields not sent; null clears one. A category on one side of a linked
transfer applies to both sides, debits cannot take income categories, and
transfer categories cannot be combined with a project. Setting or clearing
projectId needs the owner or admin role.
| Property | Value |
|---|---|
| Arguments | transactionId; optional categoryId, note (up to 500 characters), contactId, projectId, archived |
| Scope | write |
| REST equivalent | PATCH /v1/transactions/{transactionId} |
Transaction
| Field | Type | Description |
|---|---|---|
id | string | Transaction ID |
date | string | Booking date, YYYY-MM-DD |
direction | credit, debit, or unknown | Whether money came in or went out |
amount | string | Absolute amount as a decimal string in currency |
currency | string | Account currency |
instructedAmount | string or null | Original amount when paid in another currency |
instructedCurrency | string or null | Currency of instructedAmount |
title | string or null | Display title, usually the counterparty |
subtitle | string or null | Secondary description |
bankAccountId | string | Bank account ID |
categoryId | string or null | Category ID |
contactId | string or null | Counterparty contact ID |
contactName | string or null | Counterparty contact name |
projectId | string or null | Project ID |
note | string or null | Team note |
status | uncategorized, in_progress, complete, needs_review, or no_impact | Bookkeeping status |
reconciliationStatus | string or null | unmatched, partial, matched, difference_accepted or review |
internal | boolean | A transfer between the team's own accounts |
archived | boolean | Hidden from default lists |
createdAt | string | ISO 8601 time Osorik first imported it |
Invoices
Outgoing invoices the team bills its clients. Agents can read every invoice
and create, change and delete drafts. Issuing, voiding and sending invoices
stays in Osorik. Amounts are decimal strings in the invoice currency, such as
1250.00.
list_invoices
Lists invoices without their lines, newest first or by relevance when search is set.
| Property | Value |
|---|---|
| Arguments | status (optional array of draft, issuing, issue_failed, issued, void), clientId (optional), search (optional), limit (1 to 100, default 25), cursor (optional) |
| Scope | read |
| REST equivalent | GET /v1/invoices |
Returns { data, nextCursor }, where data is a list of
invoices and nextCursor is null on the last page.
get_invoice
Returns one invoice with its lines and, once it is issued, a PDF download URL.
| Property | Value |
|---|---|
| Arguments | invoiceId |
| Scope | read |
| REST equivalent | GET /v1/invoices/{invoiceId} |
Returns an invoice with lines.
create_invoice_draft
Creates an unnumbered invoice draft for a client, filling left-out fields from the client's billing defaults and the team's invoice settings.
| Property | Value |
|---|---|
| Arguments | title, clientId, lines (1 to 200 of { description, quantity, unitPrice }), issueDate, and optional categoryId, bankAccountId, currency, dueDate, discountPercentage (0 to 100), note |
| Scope | write |
| REST equivalent | POST /v1/invoices |
quantity and unitPrice are decimal strings with up to 6 decimals.
Left-out fields default as in the invoice editor:
currency: the client's currency, then the bank account's currency, then the team currency.dueDate:issueDateplus the client's payment terms, then the settings' payment terms (30 days unless changed).categoryId: the settings' category. It must be an active income category.bankAccountId: the settings' account, then the first account with payment instructions.note: the settings' note.
Returns the new invoice with lines.
update_invoice_draft
Changes the fields sent on a draft and keeps the rest; lines replaces every line.
| Property | Value |
|---|---|
| Arguments | invoiceId, and any of title, clientId, lines, issueDate, dueDate, categoryId, bankAccountId, currency, discountPercentage, note |
| Scope | write |
| REST equivalent | PATCH /v1/invoices/{invoiceId} |
null clears discountPercentage or note. Invoices that are no longer
drafts fail with INVOICE_IMMUTABLE. Returns the updated
invoice with lines.
delete_invoice_draft
Permanently deletes a draft that was never numbered, with its lines.
| Property | Value |
|---|---|
| Arguments | invoiceId |
| Scope | write |
| REST equivalent | DELETE /v1/invoices/{invoiceId} |
Returns { id, deleted: true }. Issued, voided and numbered invoices fail with
INVOICE_IMMUTABLE.
get_invoice_settings
Returns the team's invoice number prefix and the defaults new drafts use.
| Property | Value |
|---|---|
| Arguments | None |
| Scope | read |
| REST equivalent | GET /v1/invoice-settings |
Invoice
| Field | Type | Description |
|---|---|---|
id | string | Invoice ID |
number | string or null | Invoice number, such as INV-2026-0001; null for drafts |
title | string | Invoice title |
status | draft, issuing, issue_failed, issued, or void | Lifecycle state; only drafts can be changed or deleted |
deliveryStatus | not_sent, queued, sent, or failed | Email delivery state |
paymentStatus | unmatched, partial, matched, difference_accepted, or review | How far bank payments cover the total |
clientId | string | Contact the invoice bills |
clientName | string | Client name, frozen when the invoice is issued |
categoryId | string | Income category ID |
bankAccountId | string | ID of the bank account the client pays into |
currency | string | ISO 4217 currency code, such as EUR |
issueDate | string | Issue date as YYYY-MM-DD |
dueDate | string | Due date as YYYY-MM-DD |
discountPercentage | number or null | Discount on the line subtotal, from 0 to 100 |
discountAmount | string or null | Discount amount; null without a discount |
totalAmount | string | Total after discount |
paidAmount | string | Amount matched to bank payments so far |
note | string or null | Note printed on the invoice |
issuedAt | string or null | When the invoice was issued, ISO 8601 |
voidedAt | string or null | When the invoice was voided, ISO 8601 |
createdAt | string | When the invoice was created, ISO 8601 |
updatedAt | string | When the invoice last changed, ISO 8601 |
Invoice with lines
Every invoice field, plus:
| Field | Type | Description |
|---|---|---|
lines | array | Invoice lines in order, each with the fields below |
lines[].description | string | Line description |
lines[].quantity | string | Decimal quantity |
lines[].unitPrice | string | Decimal unit price |
lines[].lineTotal | string | Quantity times unit price, rounded to the currency |
pdfUrl | string or null | Temporary download URL of the issued PDF; null until it is rendered |
Invoice settings
| Field | Type | Description |
|---|---|---|
prefix | string | Prefix of invoice numbers, such as INV |
defaultPaymentTermsDays | number | Days from issue date to due date for new drafts |
defaultCategoryId | string or null | Income category for new drafts |
defaultBankAccountId | string or null | Bank account for new drafts |
defaultNote | string or null | Note for new drafts |
Expenses
list_expenses
Lists the team's expenses, the bills and receipts it uploaded, newest first.
Archived expenses are left out unless archived is true. A page can hold
fewer items than limit before the last one, so keep following nextCursor
until it is null.
| Property | Value |
|---|---|
| Arguments | status (list of statuses), archived, search, payeeId, limit (1–100, default 25), cursor; all optional |
| Scope | read |
| REST equivalent | GET /v1/expenses |
get_expense
Returns one expense with its extracted details and a short-lived documentUrl
to download the uploaded document.
| Property | Value |
|---|---|
| Arguments | expenseId |
| Scope | read |
| REST equivalent | GET /v1/expenses/{expenseId} |
update_expense
Changes the fields sent and keeps the rest; null clears an optional field.
Details can change only while the expense is unmatched (otherwise
EXPENSE_NOT_EDITABLE); archived can change in any status.
| Property | Value |
|---|---|
| Arguments | expenseId; optional payeeId, reference, date, dueDate, currency, amount, taxType, taxAmount, archived |
| Scope | write |
| REST equivalent | PATCH /v1/expenses/{expenseId} |
Expense
| Field | Type | Description |
|---|---|---|
id | string | Expense ID |
status | processing, failed, unmatched, partial, matched, or difference_accepted | Document reading and matching state |
payeeId | string or null | Payee contact ID |
payeeName | string or null | Payee name |
reference | string or null | Invoice or receipt number |
date | string or null | Issue date, YYYY-MM-DD |
dueDate | string or null | Due date, YYYY-MM-DD |
currency | string or null | ISO 4217 currency code |
amount | string or null | Total including tax, as a decimal string |
taxType | string or null | Tax kind, such as vat |
taxAmount | string or null | Tax amount, as a decimal string |
reconciledAmount | string | Part of amount matched to bank transactions |
archived | boolean | Hidden from default lists |
documentId | string | ID of the uploaded document |
extractionError | string or null | Why reading the document failed |
createdAt | string | ISO 8601 upload time |
documentUrl | string or null | get_expense only: short-lived link to the document |
Projects
Projects group client or internal work for time tracking and cash flow. Every member can read them; only team owners and admins can create or change them.
list_projects
Lists the team's projects, most recently updated first, or by relevance when
search is set.
| Property | Value |
|---|---|
| Arguments | status (planned, active, on_hold, completed or cancelled), clientId, search, limit (1 to 100, default 25), cursor |
| Scope | read |
| REST equivalent | GET /v1/projects |
get_project
Returns one project with its assigned team members. Members' hourly rates are shown only to owners and admins.
| Property | Value |
|---|---|
| Arguments | projectId (required) |
| Scope | read |
| REST equivalent | GET /v1/projects/{projectId} |
create_project
Creates a project in the planned state, assigns you to it at billableRate
and returns it with its members. clientId must be a contact marked as a
client.
| Property | Value |
|---|---|
| Arguments | name (required, up to 120 characters), currency (required, ISO 4217), billableRate (required decimal string, 0 when not charged), description, clientId, startDate, targetEndDate (on or after startDate), timeRoundingMinutes (0, 5, 10, 15 or 30, default 15) |
| Scope | write |
| REST equivalent | POST /v1/projects |
update_project
Changes the fields sent and keeps the rest; null clears description,
clientId, startDate or targetEndDate. completed and cancelled close
the project. A closed project must be reopened before its other fields change,
which can happen in the same call. The client and currency cannot change once
time is tracked (PROJECT_TIME_IDENTITY_LOCKED).
| Property | Value |
|---|---|
| Arguments | projectId (required), name, description, clientId, currency, startDate, targetEndDate, timeRoundingMinutes, status |
| Scope | write |
| REST equivalent | PATCH /v1/projects/{projectId} |
Project
list_projects returns these fields; get_project, create_project and
update_project add members.
| Field | Type | Description |
|---|---|---|
id | string | Project ID |
name | string | Project name |
description | string or null | Project description |
status | planned, active, on_hold, completed, or cancelled | Lifecycle state |
clientId | string or null | Client contact ID; null for internal work |
currency | string | ISO 4217 currency code |
startDate | string or null | Start date, YYYY-MM-DD |
targetEndDate | string or null | Planned end date, YYYY-MM-DD |
timeRoundingMinutes | 0, 5, 10, 15, 30, or null | Rounding applied to billable time entries |
closedAt | string or null | When the project was completed or cancelled (ISO 8601) |
createdAt | string | Creation time (ISO 8601) |
updatedAt | string | Last change (ISO 8601) |
members | array of ProjectMember | Assigned team members (single-project tools only) |
Project member
| Field | Type | Description |
|---|---|---|
userId | string | User ID of the member |
name | string or null | Member's name |
billableRate | string or null | Hourly rate as a decimal string in the project currency; null unless you are an owner or admin |
Time
Time is tracked against reusable tasks on projects. Members log time only on projects they are assigned to, and see and change only their own entries; owners and admins see everyone's entries and billable rates.
list_time_tasks
Lists a project's tasks, up to 200, on a single page (nextCursor is always
null). Archived tasks are left out unless includeArchived is true.
| Property | Value |
|---|---|
| Arguments | projectId (required), includeArchived |
| Scope | read |
| REST equivalent | GET /v1/projects/{projectId}/tasks |
create_time_task
Adds a task to an open project. Task names are unique within a project, ignoring case and spacing, and a project holds at most 200 tasks.
| Property | Value |
|---|---|
| Arguments | projectId, name (required); description |
| Scope | write |
| REST equivalent | POST /v1/projects/{projectId}/tasks |
list_time_entries
Lists entries that start between from and to, which can be at most 62 days
apart. Returns up to 1000 entries; truncated is true when more matched, so
narrow the range or add filters. Members always get only their own entries.
| Property | Value |
|---|---|
| Arguments | from, to (required, ISO 8601 date-times); projectId, clientId, memberId (owners and admins), taskId, billable |
| Scope | read |
| REST equivalent | GET /v1/time-entries |
create_time_entry
Records completed time for you on an active task of a project you are assigned to. Billable minutes follow the project's rounding, and billable time takes your project rate, which must be set.
| Property | Value |
|---|---|
| Arguments | projectId, taskId, startAt, endAt (ISO 8601 date-times), billable, all required |
| Scope | write |
| REST equivalent | POST /v1/time-entries |
update_time_entry
Changes the fields sent on a completed entry and recalculates its minutes and
rate. Owners and admins can move an entry to another assigned member with
memberId. Stop a running timer before editing it.
| Property | Value |
|---|---|
| Arguments | entryId and any of projectId, taskId, startAt, endAt, billable, memberId |
| Scope | write |
| REST equivalent | PATCH /v1/time-entries/{entryId} |
delete_time_entry
Permanently deletes a time entry and returns { id, deleted: true }.
| Property | Value |
|---|---|
| Arguments | entryId |
| Scope | write |
| REST equivalent | DELETE /v1/time-entries/{entryId} |
get_timer
Returns your running timer as { entry }, with entry: null when none is
running. Each member has at most one timer.
| Property | Value |
|---|---|
| Arguments | None |
| Scope | read |
| REST equivalent | GET /v1/timer |
start_timer
Starts a timer for you now and returns the running entry. Fails with
TIME_TIMER_RUNNING when one is already running.
| Property | Value |
|---|---|
| Arguments | projectId, taskId, billable, all required |
| Scope | write |
| REST equivalent | POST /v1/timer/start |
stop_timer
Stops your running timer now and returns the completed entry. Fails with
TIME_TIMER_NOT_FOUND when no timer is running.
| Property | Value |
|---|---|
| Arguments | None |
| Scope | write |
| REST equivalent | POST /v1/timer/stop |
Time task
| Field | Type | Description |
|---|---|---|
id | string | Task ID |
projectId | string | Project the task belongs to |
name | string | Task name |
description | string or null | Description |
archived | boolean | Archived tasks keep their history but take no new time |
Time entry
| Field | Type | Description |
|---|---|---|
id | string | Entry ID |
projectId | string | Project ID |
projectName | string or null | Project name |
taskId | string | Task ID |
taskName | string or null | Task name |
clientId, clientName | string or null | Client of the project; null for internal projects |
member | object | id and name of the member the time belongs to |
status | string | running or completed |
startAt | string | ISO 8601 timestamp |
endAt | string or null | ISO 8601 timestamp; null while running |
actualMinutes | number or null | Tracked minutes; null while running |
billableMinutes | number or null | Minutes after the project's rounding; null while running |
billable | boolean | Whether the time is billable |
billableRate | string or null | Hourly rate as a decimal string, such as 100.00; null for non-billable time and for members |
currency | string | ISO 4217 currency code of the rate |
Errors
When a tool fails, the result has isError: true and a text message in the
form CODE: message, such as
INSUFFICIENT_SCOPE: This requires the "write" scope. or
PROJECT_MANAGEMENT_FORBIDDEN: Only owners and admins can manage projects.
See the error codes.