nenoDevelopers
⌘K
v1

MCP · Bills

File a bill

WRITEupload_bill

Files an uploaded document as a bill. Neno checks that it is an invoice or receipt, then queues it for extraction and review, so the reply has an id and status rather than the figures. Sending the same document again returns the existing bill.

Scope
bills:write
Upload and edit bills
Permission
neno.manageDocuments
Your role in the company must include it
Annotations
readOnlyHint falseidempotentHint truedestructiveHint false

Description for models

File an invoice or receipt with Neno for bookkeeping. It takes two calls: call create_bill_upload first, PUT the document to the URL it returns, then call this with the token it gave you. That is the path for every document, whatever its size or type. If this bill is already sitting in the user's own mailbox, call get_bill_forwarding_address and forward the supplier's original message there instead: that route has no size limit, because the document never passes through a tool call. The document is checked for being a bill at all and then queued for extraction and review, so the reply gives you an id and a status rather than the figures — those appear once an accountant has reviewed it. Sending the same document twice returns the bill it already made. Be sure which company it belongs to first, with list_workspaces if you need to.

Sent verbatim in tools/list. It's written for the model, so it says when to use the tool.

Arguments

notestring · max 1000

Anything the user told you about this document that the document itself cannot say — that it was already paid, that part of it was refunded, which office it belongs to. Their words, not a summary. Omit it when they said nothing.

upload_tokenstringrequired

The token create_bill_upload returned, after you have PUT the document to the URL it gave you. Call create_bill_upload first if you do not have one.

Added by the server

On every tool that acts on one company
workspacestring

The id of the company this applies to. This connection covers a single company, which is filled in for you, so you can leave this out.

Result

text
Success. The answer as plain text in content[0].text, starting with Company: and the company name.
isError
Refused or failed. A missing permission, an invalid argument or a server failure sets isError: true. The text says what went wrong and what to tell the user.
input
Company needed. With several companies and no workspace argument, the server asks which company the call is for. A client that can't ask gets an error that lists the companies.
POST /mcp · tools/call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "upload_bill",
"arguments": {
"note": "Already paid by card on 17 September.",
"upload_token": "upl_9Qm2…"
}
}
}
Example resultHand-written
content[0].text
Company: Studio Veld BV
Uploaded. Bill id 3d8a5f12-6b90-4c7e-a1f4-0e29b7c6d853, now being read.

Tools return plain text with no output schema. This example follows the tool's real format, but the values are made up.