beeswax-mcp 1.6.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -1
- package/dist/client.js +12 -7
- package/dist/tools.js +57 -76
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -150,10 +150,16 @@ reports the same on demand.
|
|
|
150
150
|
| `list_themes`, `get_theme_spec`, `get_theme`, `upsert_theme` (write), `validate_theme` (write), `preview_theme`, `activate_theme` (write), `delete_theme` (write) | `/themes` (custom document themes, THEME_SPEC v1) |
|
|
151
151
|
| `list_products_services`, `get_product_service`, `create_product_service` (write), `update_product_service` (write), `delete_product_service` (write) | `/transaction_templates` |
|
|
152
152
|
| `list_manual_journals`, `get_manual_journal`, `create_manual_journal` (write), `finalise_manual_journal` (write) | `/raw_journal_entries` |
|
|
153
|
-
| `list_tax_returns`, `get_tax_return`, `get_tax_return_field_transactions`, `
|
|
153
|
+
| `list_tax_returns`, `get_tax_return`, `get_tax_return_field_transactions`, `compare_tax_returns`, `tax_return_preflight_check`, `list_tax_return_field_notes`, `get_tax_return_conversation`, `create_tax_return` (write), `repopulate_tax_return` (write), `update_tax_return_field` (write), `add_tax_return_field_note` (write), `edit_tax_return_field_note` (write), `post_tax_return_message` (write), `confirm_tax_return_section` / `unconfirm_tax_return_section` (write), `finalise_tax_return` / `unfinalise_tax_return` (write) | `/tax_returns` — the assistant is the reviewer: it reads the figures and the transactions behind them and records its reasoning as field notes and discussion messages |
|
|
154
154
|
|
|
155
155
|
### Notes
|
|
156
156
|
|
|
157
|
+
- The create tools and `apply_payment` accept `idempotency_key`. Reuse it on a
|
|
158
|
+
retry and the API replays the original result instead of posting twice.
|
|
159
|
+
- Every `list_*` tool accepts `updated_since` (ISO 8601) so an agent can ask
|
|
160
|
+
for "what changed since yesterday" instead of re-reading everything; rows
|
|
161
|
+
carry `updated_at`.
|
|
162
|
+
|
|
157
163
|
- **Scopes.** `query_journal_entries` / `get_journal_entry` need an `all`-scoped
|
|
158
164
|
token for a bare listing, a show, or a long-tail type (credits, bank_transfers,
|
|
159
165
|
payrolls); a typed listing (`type: "invoices"`) accepts that type's read scope.
|
package/dist/client.js
CHANGED
|
@@ -124,18 +124,23 @@ export class BeeswaxClient {
|
|
|
124
124
|
}
|
|
125
125
|
// Write request (POST / PATCH / DELETE) with a JSON body. Returns the parsed
|
|
126
126
|
// response body, or throws with the API's error message on a non-2xx.
|
|
127
|
-
async mutate(method, path, body = {}) {
|
|
127
|
+
async mutate(method, path, body = {}, opts = {}) {
|
|
128
128
|
const url = new URL(this.baseUrl + path);
|
|
129
|
+
const headers = {
|
|
130
|
+
Authorization: `Bearer ${this.token}`,
|
|
131
|
+
Accept: "application/json",
|
|
132
|
+
"Content-Type": "application/json",
|
|
133
|
+
"User-Agent": USER_AGENT,
|
|
134
|
+
};
|
|
135
|
+
// Idempotency-Key: the API replays the original response for a retried
|
|
136
|
+
// write instead of posting twice (see the API tokens help).
|
|
137
|
+
if (opts.idempotencyKey)
|
|
138
|
+
headers["Idempotency-Key"] = String(opts.idempotencyKey).slice(0, 255);
|
|
129
139
|
let res;
|
|
130
140
|
try {
|
|
131
141
|
res = await fetch(url, {
|
|
132
142
|
method,
|
|
133
|
-
headers
|
|
134
|
-
Authorization: `Bearer ${this.token}`,
|
|
135
|
-
Accept: "application/json",
|
|
136
|
-
"Content-Type": "application/json",
|
|
137
|
-
"User-Agent": USER_AGENT,
|
|
138
|
-
},
|
|
143
|
+
headers,
|
|
139
144
|
body: JSON.stringify(body),
|
|
140
145
|
});
|
|
141
146
|
}
|
package/dist/tools.js
CHANGED
|
@@ -38,7 +38,26 @@ const DATE_PROPS = {
|
|
|
38
38
|
},
|
|
39
39
|
to: { type: "string", description: "Latest document date (sent_on). Same format as `from`." },
|
|
40
40
|
};
|
|
41
|
+
// Optional on every create/apply tool: reuse the same key when retrying a call
|
|
42
|
+
// that may have gone through (timeout, unclear error) and the API returns the
|
|
43
|
+
// original result instead of creating a second record.
|
|
44
|
+
const IDEMPOTENCY_PROP = {
|
|
45
|
+
idempotency_key: {
|
|
46
|
+
type: "string",
|
|
47
|
+
description: "Optional. A unique string (e.g. a UUID) for this operation. If you retry the same call after a timeout or an unclear error, pass the SAME key and Beeswax returns the original result instead of creating a duplicate. Use a new key for a genuinely new record.",
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
// Incremental sync: every listing accepts updated_since (ISO 8601) and the
|
|
51
|
+
// API echoes meta.filter.updated_since + meta.server_time.
|
|
52
|
+
const SYNC_PROPS = {
|
|
53
|
+
updated_since: {
|
|
54
|
+
type: "string",
|
|
55
|
+
description: "Incremental sync: only rows updated on or after this ISO 8601 instant (e.g. 2026-09-05T00:00:00Z). " +
|
|
56
|
+
"Line and contact-person edits touch their parent, so a changed line surfaces the document.",
|
|
57
|
+
},
|
|
58
|
+
};
|
|
41
59
|
const ACCOUNTING_LIST_PROPS = {
|
|
60
|
+
...SYNC_PROPS,
|
|
42
61
|
state: { type: "string", description: "Filter by state (draft, finalised, pdf_sent, partial_paid, paid, …)." },
|
|
43
62
|
project_id: { type: "integer", description: "Filter to a single project." },
|
|
44
63
|
company_id: { type: "integer", description: "Filter to a single client/supplier company by id." },
|
|
@@ -98,6 +117,7 @@ function accountingTools(resource, singular, label, listName, opts = {}) {
|
|
|
98
117
|
(payable ? " Pass overdue:true to get just the overdue ones (with due dates) in a single call." : ""),
|
|
99
118
|
inputSchema: { type: "object", properties: { ...listProps, ...POSTED_PROPS } },
|
|
100
119
|
handler: (client, args) => client.fetchAll(`/${resource}`, resource, {
|
|
120
|
+
updated_since: args.updated_since,
|
|
101
121
|
posted: args.posted,
|
|
102
122
|
include_drafts: args.include_drafts,
|
|
103
123
|
state: args.state,
|
|
@@ -182,7 +202,7 @@ function ledgerDocumentTools(resource) {
|
|
|
182
202
|
`Requires ${scope}.`,
|
|
183
203
|
inputSchema: {
|
|
184
204
|
type: "object",
|
|
185
|
-
properties: {
|
|
205
|
+
properties: { ...IDEMPOTENCY_PROP,
|
|
186
206
|
project_id: { type: "integer", description: "Project the document belongs to. Required." },
|
|
187
207
|
...partyProp,
|
|
188
208
|
title: { type: "string" },
|
|
@@ -230,7 +250,7 @@ function ledgerDocumentTools(resource) {
|
|
|
230
250
|
default_tax_id: args.default_tax_id,
|
|
231
251
|
groups: (args.groups ?? []).map((g) => ({ ...g, due_on: normalizeDate(g.due_on) })),
|
|
232
252
|
},
|
|
233
|
-
}),
|
|
253
|
+
}, { idempotencyKey: args.idempotency_key }),
|
|
234
254
|
},
|
|
235
255
|
{
|
|
236
256
|
name: `update_${singular}`,
|
|
@@ -411,7 +431,7 @@ const PAYMENT_TOOLS = [
|
|
|
411
431
|
"There is no edit: remove a wrong payment (remove_payment) and apply it again. Confirm amounts with the user first. Requires payments:write.",
|
|
412
432
|
inputSchema: {
|
|
413
433
|
type: "object",
|
|
414
|
-
properties: {
|
|
434
|
+
properties: { ...IDEMPOTENCY_PROP,
|
|
415
435
|
bank_account_id: { type: "integer", description: "A transaction account flagged as a bank account." },
|
|
416
436
|
paid_on: { type: "string", description: "Payment date, e.g. '2026-09-04'." },
|
|
417
437
|
allocations: {
|
|
@@ -431,7 +451,7 @@ const PAYMENT_TOOLS = [
|
|
|
431
451
|
},
|
|
432
452
|
handler: (client, args) => client.mutate("POST", "/payments", {
|
|
433
453
|
payment: { bank_account_id: args.bank_account_id, paid_on: normalizeDate(args.paid_on), allocations: args.allocations },
|
|
434
|
-
}),
|
|
454
|
+
}, { idempotencyKey: args.idempotency_key }),
|
|
435
455
|
},
|
|
436
456
|
{
|
|
437
457
|
name: "remove_payment",
|
|
@@ -553,13 +573,13 @@ export const TOOLS = [
|
|
|
553
573
|
"Long-tail types (credits, bank_transfers, payrolls) and bare listings require an `all`-scoped token.",
|
|
554
574
|
inputSchema: {
|
|
555
575
|
type: "object",
|
|
556
|
-
properties: {
|
|
576
|
+
properties: { ...SYNC_PROPS,
|
|
557
577
|
type: { type: "string", description: "STI type filter, e.g. invoices, payments, payrolls, credits, bank_transfers." },
|
|
558
578
|
state: { type: "string", description: "Filter by state (switches the posted default off)." },
|
|
559
579
|
...POSTED_PROPS,
|
|
560
580
|
},
|
|
561
581
|
},
|
|
562
|
-
handler: (client, args) => client.fetchAll("/journal_entries", "journal_entries", {
|
|
582
|
+
handler: (client, args) => client.fetchAll("/journal_entries", "journal_entries", { updated_since: args.updated_since,
|
|
563
583
|
type: args.type, state: args.state, posted: args.posted, include_drafts: args.include_drafts,
|
|
564
584
|
}),
|
|
565
585
|
},
|
|
@@ -583,12 +603,12 @@ export const TOOLS = [
|
|
|
583
603
|
description: "List all time entries for the configured account (every page).",
|
|
584
604
|
inputSchema: {
|
|
585
605
|
type: "object",
|
|
586
|
-
properties: {
|
|
606
|
+
properties: { ...SYNC_PROPS,
|
|
587
607
|
project_id: { type: "integer", description: "Filter to a single project." },
|
|
588
608
|
billable: { type: "boolean", description: "Filter by billable flag." },
|
|
589
609
|
},
|
|
590
610
|
},
|
|
591
|
-
handler: (client, args) => client.fetchAll("/time_entries", "time_entries", { project_id: args.project_id, billable: args.billable }),
|
|
611
|
+
handler: (client, args) => client.fetchAll("/time_entries", "time_entries", { updated_since: args.updated_since, project_id: args.project_id, billable: args.billable }),
|
|
592
612
|
},
|
|
593
613
|
{
|
|
594
614
|
name: "get_time_entry",
|
|
@@ -601,9 +621,9 @@ export const TOOLS = [
|
|
|
601
621
|
description: "List calendar events visible to the token's user (private events the user is not invited to are excluded).",
|
|
602
622
|
inputSchema: {
|
|
603
623
|
type: "object",
|
|
604
|
-
properties: { project_id: { type: "integer", description: "Filter to a single project." }, ...DATE_PROPS },
|
|
624
|
+
properties: { ...SYNC_PROPS, project_id: { type: "integer", description: "Filter to a single project." }, ...DATE_PROPS },
|
|
605
625
|
},
|
|
606
|
-
handler: (client, args) => client.fetchAll("/events", "events", {
|
|
626
|
+
handler: (client, args) => client.fetchAll("/events", "events", { updated_since: args.updated_since,
|
|
607
627
|
project_id: args.project_id,
|
|
608
628
|
from: normalizeDate(args.from),
|
|
609
629
|
to: normalizeDate(args.to),
|
|
@@ -620,12 +640,12 @@ export const TOOLS = [
|
|
|
620
640
|
description: "List all milestones (project TaskLists) for the configured account.",
|
|
621
641
|
inputSchema: {
|
|
622
642
|
type: "object",
|
|
623
|
-
properties: {
|
|
643
|
+
properties: { ...SYNC_PROPS,
|
|
624
644
|
project_id: { type: "integer", description: "Filter to a single project." },
|
|
625
645
|
complete: { type: "boolean", description: "Filter by completion." },
|
|
626
646
|
},
|
|
627
647
|
},
|
|
628
|
-
handler: (client, args) => client.fetchAll("/milestones", "milestones", { project_id: args.project_id, complete: args.complete }),
|
|
648
|
+
handler: (client, args) => client.fetchAll("/milestones", "milestones", { updated_since: args.updated_since, project_id: args.project_id, complete: args.complete }),
|
|
629
649
|
},
|
|
630
650
|
{
|
|
631
651
|
name: "get_milestone",
|
|
@@ -636,8 +656,8 @@ export const TOOLS = [
|
|
|
636
656
|
{
|
|
637
657
|
name: "list_projects",
|
|
638
658
|
description: "List the account's active projects. Use this to resolve a project name to the project_id that create_quote and the other document tools need.",
|
|
639
|
-
inputSchema: { type: "object", properties: {} },
|
|
640
|
-
handler: (client) => client.getList("/active_account/projects", "projects"),
|
|
659
|
+
inputSchema: { type: "object", properties: { ...SYNC_PROPS } },
|
|
660
|
+
handler: (client, args) => client.getList("/active_account/projects", "projects", { updated_since: args.updated_since }),
|
|
641
661
|
},
|
|
642
662
|
{
|
|
643
663
|
name: "get_project",
|
|
@@ -668,12 +688,12 @@ export const TOOLS = [
|
|
|
668
688
|
description: "List project documents. Freeform documents are markdown written in Beeswax's document editor — proposals, briefs, meeting notes — styled by the account's invoice theme; other document_types are generated from library templates and are read-only via this API. Each row carries state (draft/published/finalized/archived), current_version_number, and editing_lock (who has it open in the web editor right now). Filter with project_id and/or document_type (e.g. 'freeform').",
|
|
669
689
|
inputSchema: {
|
|
670
690
|
type: "object",
|
|
671
|
-
properties: {
|
|
691
|
+
properties: { ...SYNC_PROPS,
|
|
672
692
|
project_id: { type: "integer", description: "Only documents on this project" },
|
|
673
693
|
document_type: { type: "string", description: "e.g. 'freeform' for markdown documents" },
|
|
674
694
|
},
|
|
675
695
|
},
|
|
676
|
-
handler: (client, args) => client.fetchAll("/project_documents", "project_documents", {
|
|
696
|
+
handler: (client, args) => client.fetchAll("/project_documents", "project_documents", { updated_since: args.updated_since,
|
|
677
697
|
project_id: args.project_id,
|
|
678
698
|
document_type: args.document_type,
|
|
679
699
|
}),
|
|
@@ -689,7 +709,7 @@ export const TOOLS = [
|
|
|
689
709
|
description: "Create a freeform (markdown) document on a project. `body` is markdown (headings, lists, tables, blockquotes all render through the account's invoice theme). The optional `note` becomes the first version's 'what changed' line. Requires a token with the `project_documents:write` scope.",
|
|
690
710
|
inputSchema: {
|
|
691
711
|
type: "object",
|
|
692
|
-
properties: {
|
|
712
|
+
properties: { ...IDEMPOTENCY_PROP,
|
|
693
713
|
project_id: { type: "integer" },
|
|
694
714
|
name: { type: "string", description: "Document title (defaults to 'Untitled document')" },
|
|
695
715
|
body: { type: "string", description: "Markdown content" },
|
|
@@ -699,7 +719,7 @@ export const TOOLS = [
|
|
|
699
719
|
},
|
|
700
720
|
handler: (client, args) => client.mutate("POST", "/project_documents", {
|
|
701
721
|
project_document: { project_id: args.project_id, name: args.name, body: args.body, note: args.note },
|
|
702
|
-
}),
|
|
722
|
+
}, { idempotencyKey: args.idempotency_key }),
|
|
703
723
|
},
|
|
704
724
|
{
|
|
705
725
|
name: "update_project_document",
|
|
@@ -829,7 +849,7 @@ export const TOOLS = [
|
|
|
829
849
|
description: "List the account's products & services catalogue (stored as 'transaction templates'): everything the business sells or buys as a line item — products and services/activities with their unit, sell/buy prices, linked income/expense accounts and taxes. Use this whenever the user asks about products, services, price lists, rates or catalogue items.",
|
|
830
850
|
inputSchema: {
|
|
831
851
|
type: "object",
|
|
832
|
-
properties: {
|
|
852
|
+
properties: { ...SYNC_PROPS,
|
|
833
853
|
kind: {
|
|
834
854
|
type: "string",
|
|
835
855
|
enum: ["sell", "buy", "buy_and_sell", "product", "service"],
|
|
@@ -849,7 +869,7 @@ export const TOOLS = [
|
|
|
849
869
|
},
|
|
850
870
|
},
|
|
851
871
|
},
|
|
852
|
-
handler: (client, args) => client.fetchAll("/transaction_templates", "transaction_templates", {
|
|
872
|
+
handler: (client, args) => client.fetchAll("/transaction_templates", "transaction_templates", { updated_since: args.updated_since,
|
|
853
873
|
kind: args.kind,
|
|
854
874
|
side: args.side,
|
|
855
875
|
active: args.active,
|
|
@@ -876,7 +896,7 @@ export const TOOLS = [
|
|
|
876
896
|
"Titles must be unique within the account, and prices default to 0 if you omit them, so pass them explicitly. Requires a token with transaction_templates:write.",
|
|
877
897
|
inputSchema: {
|
|
878
898
|
type: "object",
|
|
879
|
-
properties: {
|
|
899
|
+
properties: { ...IDEMPOTENCY_PROP,
|
|
880
900
|
title: { type: "string", description: "Catalogue name, e.g. 'Shaker Door — Painted'. Must be unique in the account." },
|
|
881
901
|
kind: {
|
|
882
902
|
type: "string",
|
|
@@ -930,7 +950,7 @@ export const TOOLS = [
|
|
|
930
950
|
physical_resource: args.physical_resource,
|
|
931
951
|
gantt_color: args.gantt_color,
|
|
932
952
|
},
|
|
933
|
-
}),
|
|
953
|
+
}, { idempotencyKey: args.idempotency_key }),
|
|
934
954
|
},
|
|
935
955
|
{
|
|
936
956
|
name: "update_product_service",
|
|
@@ -999,7 +1019,7 @@ export const TOOLS = [
|
|
|
999
1019
|
// ── Tax returns (Australian company / sole-trader) ──────────────────
|
|
1000
1020
|
{
|
|
1001
1021
|
name: "list_tax_returns",
|
|
1002
|
-
description: "List the account's tax returns (most recent financial year first) with status
|
|
1022
|
+
description: "List the account's tax returns (most recent financial year first) with status and completion %. Australian accounts only.",
|
|
1003
1023
|
inputSchema: { type: "object", properties: {} },
|
|
1004
1024
|
handler: (client) => client.getList("/tax_returns", "tax_returns"),
|
|
1005
1025
|
},
|
|
@@ -1027,22 +1047,9 @@ export const TOOLS = [
|
|
|
1027
1047
|
},
|
|
1028
1048
|
handler: (client, args) => client.getOne(`/tax_returns/${args.id}/sections/${args.section_key}/fields/${args.field_key}/transactions`, ""),
|
|
1029
1049
|
},
|
|
1030
|
-
{
|
|
1031
|
-
name: "list_tax_return_findings",
|
|
1032
|
-
description: "List the AI review findings for a tax return. Optionally filter by status (pending, accepted, rejected, deferred, stale).",
|
|
1033
|
-
inputSchema: {
|
|
1034
|
-
type: "object",
|
|
1035
|
-
properties: {
|
|
1036
|
-
id: { type: "integer", description: "Tax return id." },
|
|
1037
|
-
status: { type: "string", description: "Optional status filter." },
|
|
1038
|
-
},
|
|
1039
|
-
required: ["id"],
|
|
1040
|
-
},
|
|
1041
|
-
handler: (client, args) => client.getList(`/tax_returns/${args.id}/findings`, "findings", { status: args.status }),
|
|
1042
|
-
},
|
|
1043
1050
|
{
|
|
1044
1051
|
name: "update_tax_return_field",
|
|
1045
|
-
description: "Set a manual override on one tax-return field — the same as a person editing it in the web form. Recomputes the totals
|
|
1052
|
+
description: "Set a manual override on one tax-return field — the same as a person editing it in the web form. Recomputes the totals. Pass an empty value to clear an override and revert to the auto-filled figure. Fails on calculated/read-only fields and on finalised or lodged returns. Requires a token with the tax_returns:write scope.",
|
|
1046
1053
|
inputSchema: {
|
|
1047
1054
|
type: "object",
|
|
1048
1055
|
properties: {
|
|
@@ -1126,32 +1133,6 @@ export const TOOLS = [
|
|
|
1126
1133
|
},
|
|
1127
1134
|
handler: (client, args) => client.mutate("POST", `/tax_returns/${args.id}/repopulate`, {}),
|
|
1128
1135
|
},
|
|
1129
|
-
{
|
|
1130
|
-
name: "request_tax_return_ai_review",
|
|
1131
|
-
description: "Start an AI review of the tax return. The review runs in the background — poll get_tax_return (latest_review) or list_tax_return_findings to see the outcome. Requires a token with the tax_returns:write scope.",
|
|
1132
|
-
inputSchema: {
|
|
1133
|
-
type: "object",
|
|
1134
|
-
properties: { id: { type: "integer", description: "Tax return id." } },
|
|
1135
|
-
required: ["id"],
|
|
1136
|
-
},
|
|
1137
|
-
handler: (client, args) => client.mutate("POST", `/tax_returns/${args.id}/review`, {}),
|
|
1138
|
-
},
|
|
1139
|
-
{
|
|
1140
|
-
name: "resolve_tax_return_finding",
|
|
1141
|
-
description: "Resolve one pending AI review finding: accept (applies the suggested value to the field), reject, or defer. Every pending finding in a section must be resolved before that section can be confirmed. Requires a token with the tax_returns:write scope.",
|
|
1142
|
-
inputSchema: {
|
|
1143
|
-
type: "object",
|
|
1144
|
-
properties: {
|
|
1145
|
-
id: { type: "integer", description: "Tax return id." },
|
|
1146
|
-
finding_id: { type: "integer", description: "Finding id (from list_tax_return_findings)." },
|
|
1147
|
-
resolution: { type: "string", enum: ["accept", "reject", "defer"], description: "How to resolve the finding." },
|
|
1148
|
-
},
|
|
1149
|
-
required: ["id", "finding_id", "resolution"],
|
|
1150
|
-
},
|
|
1151
|
-
handler: (client, args) => client.mutate("POST", `/tax_returns/${args.id}/findings/${args.finding_id}/resolve`, {
|
|
1152
|
-
resolution: args.resolution,
|
|
1153
|
-
}),
|
|
1154
|
-
},
|
|
1155
1136
|
{
|
|
1156
1137
|
name: "finalise_tax_return",
|
|
1157
1138
|
description: "Finalise a tax return once every section is confirmed. A finalised return is locked against edits (use unfinalise_tax_return to unlock it). This does NOT lodge the return with the ATO. Requires a token with the tax_returns:write scope.",
|
|
@@ -1266,12 +1247,12 @@ export const TOOLS = [
|
|
|
1266
1247
|
"Requires journal_entries:read (write implies read).",
|
|
1267
1248
|
inputSchema: {
|
|
1268
1249
|
type: "object",
|
|
1269
|
-
properties: {
|
|
1250
|
+
properties: { ...SYNC_PROPS,
|
|
1270
1251
|
state: { type: "string", enum: ["draft", "finalised"], description: "Optional state filter (switches the posted default off)." },
|
|
1271
1252
|
...POSTED_PROPS,
|
|
1272
1253
|
},
|
|
1273
1254
|
},
|
|
1274
|
-
handler: (client, args) => client.fetchAll("/raw_journal_entries", "raw_journal_entries", {
|
|
1255
|
+
handler: (client, args) => client.fetchAll("/raw_journal_entries", "raw_journal_entries", { updated_since: args.updated_since,
|
|
1275
1256
|
state: args.state, posted: args.posted, include_drafts: args.include_drafts,
|
|
1276
1257
|
}),
|
|
1277
1258
|
},
|
|
@@ -1293,9 +1274,9 @@ export const TOOLS = [
|
|
|
1293
1274
|
"Requires a token with the journal_entries:write scope.",
|
|
1294
1275
|
inputSchema: {
|
|
1295
1276
|
type: "object",
|
|
1296
|
-
properties: {
|
|
1277
|
+
properties: { ...IDEMPOTENCY_PROP,
|
|
1297
1278
|
date: { type: "string", description: "Entry date, e.g. '2024-04-01'." },
|
|
1298
|
-
narration: { type: "string", description: "What the journal is for, e.g. 'BMW write-off'." },
|
|
1279
|
+
narration: { type: "string", maxLength: 255, description: "What the journal is for, e.g. 'BMW write-off'. At most 255 characters — put detail in the line descriptions." },
|
|
1299
1280
|
status: { type: "string", enum: ["finalised", "draft"], description: "Optional. Default 'finalised' posts to the ledger immediately; 'draft' stages it for review." },
|
|
1300
1281
|
lines: {
|
|
1301
1282
|
type: "array",
|
|
@@ -1321,7 +1302,7 @@ export const TOOLS = [
|
|
|
1321
1302
|
status: args.status,
|
|
1322
1303
|
lines: args.lines,
|
|
1323
1304
|
},
|
|
1324
|
-
}),
|
|
1305
|
+
}, { idempotencyKey: args.idempotency_key }),
|
|
1325
1306
|
},
|
|
1326
1307
|
{
|
|
1327
1308
|
name: "finalise_manual_journal",
|
|
@@ -1344,7 +1325,7 @@ export const TOOLS = [
|
|
|
1344
1325
|
"Requires a token with transaction_accounts:read.",
|
|
1345
1326
|
inputSchema: {
|
|
1346
1327
|
type: "object",
|
|
1347
|
-
properties: {
|
|
1328
|
+
properties: { ...SYNC_PROPS,
|
|
1348
1329
|
account_type: {
|
|
1349
1330
|
type: "string",
|
|
1350
1331
|
enum: ["income", "expense", "asset", "loan", "equity", "transfer"],
|
|
@@ -1354,7 +1335,7 @@ export const TOOLS = [
|
|
|
1354
1335
|
bank: { type: "boolean", description: "true returns only bank accounts." },
|
|
1355
1336
|
},
|
|
1356
1337
|
},
|
|
1357
|
-
handler: (client, args) => client.getList("/active_account/transaction_accounts", "transaction_accounts", {
|
|
1338
|
+
handler: (client, args) => client.getList("/active_account/transaction_accounts", "transaction_accounts", { updated_since: args.updated_since,
|
|
1358
1339
|
account_type: args.account_type,
|
|
1359
1340
|
active: args.active,
|
|
1360
1341
|
bank: args.bank,
|
|
@@ -1404,12 +1385,12 @@ export const TOOLS = [
|
|
|
1404
1385
|
"Fetches every page. Requires a token with companies:read.",
|
|
1405
1386
|
inputSchema: {
|
|
1406
1387
|
type: "object",
|
|
1407
|
-
properties: {
|
|
1388
|
+
properties: { ...SYNC_PROPS,
|
|
1408
1389
|
role: { type: "string", enum: ["client", "supplier"], description: "Filter to one role. A quote is addressed to a client." },
|
|
1409
1390
|
name: { type: "string", description: "Case-insensitive substring match on the company name." },
|
|
1410
1391
|
},
|
|
1411
1392
|
},
|
|
1412
|
-
handler: (client, args) => client.fetchAll("/active_account/companies", "companies", { role: args.role, name: args.name }),
|
|
1393
|
+
handler: (client, args) => client.fetchAll("/active_account/companies", "companies", { updated_since: args.updated_since, role: args.role, name: args.name }),
|
|
1413
1394
|
},
|
|
1414
1395
|
{
|
|
1415
1396
|
name: "get_company",
|
|
@@ -1424,7 +1405,7 @@ export const TOOLS = [
|
|
|
1424
1405
|
"Check list_companies first — names are unique per account and a duplicate is refused. Nothing here emails anyone. Requires companies:write.",
|
|
1425
1406
|
inputSchema: {
|
|
1426
1407
|
type: "object",
|
|
1427
|
-
properties: {
|
|
1408
|
+
properties: { ...IDEMPOTENCY_PROP,
|
|
1428
1409
|
name: { type: "string" },
|
|
1429
1410
|
client: { type: "boolean", description: "You sell to them." },
|
|
1430
1411
|
supplier: { type: "boolean", description: "You buy from them." },
|
|
@@ -1451,7 +1432,7 @@ export const TOOLS = [
|
|
|
1451
1432
|
},
|
|
1452
1433
|
required: ["name"],
|
|
1453
1434
|
},
|
|
1454
|
-
handler: (client, args) => client.mutate("POST", "/active_account/companies", { company: args }),
|
|
1435
|
+
handler: (client, args) => client.mutate("POST", "/active_account/companies", { company: args }, { idempotencyKey: args.idempotency_key }),
|
|
1455
1436
|
},
|
|
1456
1437
|
{
|
|
1457
1438
|
name: "update_company",
|
|
@@ -1508,7 +1489,7 @@ export const TOOLS = [
|
|
|
1508
1489
|
"Requires a token with the quotes:write scope.",
|
|
1509
1490
|
inputSchema: {
|
|
1510
1491
|
type: "object",
|
|
1511
|
-
properties: {
|
|
1492
|
+
properties: { ...IDEMPOTENCY_PROP,
|
|
1512
1493
|
project_id: { type: "integer", description: "Project the quote belongs to. Required." },
|
|
1513
1494
|
company_id: { type: "integer", description: "Client the quote is addressed to. Required — see list_companies." },
|
|
1514
1495
|
title: { type: "string", description: "Quote title, e.g. 'Cambridge Market Admin App Website'." },
|
|
@@ -1574,7 +1555,7 @@ export const TOOLS = [
|
|
|
1574
1555
|
start_on: normalizeDate(group.start_on),
|
|
1575
1556
|
})),
|
|
1576
1557
|
},
|
|
1577
|
-
}),
|
|
1558
|
+
}, { idempotencyKey: args.idempotency_key }),
|
|
1578
1559
|
},
|
|
1579
1560
|
{
|
|
1580
1561
|
name: "update_quote",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "beeswax-mcp",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Official MCP server for Beeswax (beeswaxapp.com) — query invoices, quotes, expenses, payments, journals, time entries, projects, products & services and tax returns from Claude and other MCP clients, and build quotes priced from your catalogue.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://www.beeswaxapp.com/support/mcp-setup",
|