actual-mcp-server 0.15.0 → 0.16.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 +1 -1
- package/dist/src/lib/schemas/common.js +13 -0
- package/dist/src/tools/accounts_close.js +7 -9
- package/dist/src/tools/accounts_create.js +9 -2
- package/dist/src/tools/accounts_delete.js +2 -1
- package/dist/src/tools/accounts_get_balance.js +2 -1
- package/dist/src/tools/accounts_reopen.js +7 -4
- package/dist/src/tools/budget_updates_batch.js +2 -1
- package/dist/src/tools/budgets_setAmount.js +2 -1
- package/dist/src/tools/budgets_setCarryover.js +2 -1
- package/dist/src/tools/budgets_transfer.js +3 -4
- package/dist/src/tools/categories_delete.js +2 -1
- package/dist/src/tools/categories_update.js +3 -2
- package/dist/src/tools/category_groups_delete.js +2 -1
- package/dist/src/tools/category_groups_update.js +2 -1
- package/dist/src/tools/payee_rules_get.js +2 -1
- package/dist/src/tools/rules_delete.js +6 -3
- package/dist/src/tools/rules_update.js +2 -1
- package/dist/src/tools/schedules_create.js +3 -3
- package/dist/src/tools/schedules_delete.js +2 -3
- package/dist/src/tools/schedules_update.js +4 -5
- package/dist/src/tools/transactions_delete.js +2 -1
- package/dist/src/tools/transactions_update.js +9 -5
- package/dist/src/tools/transactions_update_batch.js +2 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -774,7 +774,7 @@ The software is provided **as-is**, without warranty of any kind. The author acc
|
|
|
774
774
|
|
|
775
775
|
---
|
|
776
776
|
|
|
777
|
-
**Version:** 0.
|
|
777
|
+
**Version:** 0.16.0 | **Tool Count:** 74 (verified LibreChat-compatible)
|
|
778
778
|
|
|
779
779
|
## Sponsor
|
|
780
780
|
|
|
@@ -66,6 +66,18 @@ export const tagIdSchema = z
|
|
|
66
66
|
.string()
|
|
67
67
|
.regex(UUID_PATTERN, 'Invalid tag ID format (expected UUID)')
|
|
68
68
|
.describe('Tag UUID');
|
|
69
|
+
/**
|
|
70
|
+
* Schedule UUID validation
|
|
71
|
+
* Used for: schedule management operations (update, delete)
|
|
72
|
+
*
|
|
73
|
+
* #380: added because `schedules_update` and `schedules_delete` were inlining
|
|
74
|
+
* `UUID_PATTERN` directly, which is the same rule expressed twice and is how a fifth way
|
|
75
|
+
* of describing an id appears.
|
|
76
|
+
*/
|
|
77
|
+
export const scheduleIdSchema = z
|
|
78
|
+
.string()
|
|
79
|
+
.regex(UUID_PATTERN, 'Invalid schedule ID format (expected UUID)')
|
|
80
|
+
.describe('Schedule UUID');
|
|
69
81
|
// ============================================================================
|
|
70
82
|
// DATE SCHEMAS
|
|
71
83
|
// ============================================================================
|
|
@@ -214,6 +226,7 @@ export const CommonSchemas = {
|
|
|
214
226
|
payeeId: payeeIdSchema,
|
|
215
227
|
ruleId: ruleIdSchema,
|
|
216
228
|
tagId: tagIdSchema,
|
|
229
|
+
scheduleId: scheduleIdSchema,
|
|
217
230
|
// Dates
|
|
218
231
|
date: dateSchema,
|
|
219
232
|
monthYear: monthYearSchema,
|
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import adapter from '../lib/actual-adapter.js';
|
|
3
|
+
import { CommonSchemas } from '../lib/schemas/common.js';
|
|
3
4
|
const InputSchema = z
|
|
4
5
|
.object({
|
|
5
|
-
id:
|
|
6
|
+
id: CommonSchemas.accountId.describe('Account ID to close'),
|
|
6
7
|
// #357: documented by the Actual API reference as required when the account's
|
|
7
8
|
// balance is non-zero, and previously not exposed at all, which made such an
|
|
8
9
|
// account impossible to close through this server.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
// #380: the same entity type as `id` at the top of this object, so it gets the same schema. It was
|
|
11
|
+
// left on a bounded string because the drift guard could not SEE it: its detector
|
|
12
|
+
// required `z.` on the field's own line, and this declaration breaks after `z`.
|
|
13
|
+
transferAccountId: CommonSchemas.accountId
|
|
13
14
|
.optional()
|
|
14
15
|
.describe('Account ID to move the remaining balance to. REQUIRED when the account has a non-zero balance.'),
|
|
15
|
-
transferCategoryId:
|
|
16
|
-
.string()
|
|
17
|
-
.min(1)
|
|
18
|
-
.max(64)
|
|
16
|
+
transferCategoryId: CommonSchemas.categoryId
|
|
19
17
|
.optional()
|
|
20
18
|
.describe('Category to assign the balancing transaction to. Optional, used with transferAccountId.'),
|
|
21
19
|
})
|
|
@@ -6,12 +6,19 @@ export default createTool({
|
|
|
6
6
|
name: 'actual_accounts_create',
|
|
7
7
|
description: 'Create a new account in Actual Budget',
|
|
8
8
|
schema: z.object({
|
|
9
|
-
|
|
9
|
+
// #380: the `id` field was REMOVED rather than tightened. Upstream ignores it:
|
|
10
|
+
// `handlers['api/account-create']` destructures only name, offbudget, closed and the
|
|
11
|
+
// balance, so `insertWithUUID` always mints a fresh UUID (verified against the
|
|
12
|
+
// @actual-app/api source shipped in dist/index.js.map). A caller who supplied an id got
|
|
13
|
+
// `{ success: true }` and an account with a DIFFERENT id, then a not-found from
|
|
14
|
+
// actual_accounts_get_balance. That is the same success-lie family as #350, so
|
|
15
|
+
// publishing the field at all was the defect; typing it would only have made an
|
|
16
|
+
// unusable field look deliberate.
|
|
10
17
|
name: CommonSchemas.name,
|
|
11
18
|
balance: CommonSchemas.optionalAmountCents
|
|
12
19
|
}),
|
|
13
20
|
handler: async (input) => {
|
|
14
|
-
const accountPayload = {
|
|
21
|
+
const accountPayload = { name: input.name, balance: input.balance };
|
|
15
22
|
return await adapter.createAccount(accountPayload, input.balance);
|
|
16
23
|
},
|
|
17
24
|
examples: [
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import adapter from '../lib/actual-adapter.js';
|
|
3
|
+
import { CommonSchemas } from '../lib/schemas/common.js';
|
|
3
4
|
const InputSchema = z.object({
|
|
4
|
-
id:
|
|
5
|
+
id: CommonSchemas.accountId.describe('Account ID to delete'),
|
|
5
6
|
});
|
|
6
7
|
/**
|
|
7
8
|
* #347: this tool used to return `{success: true}` unconditionally, which was a
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import adapter from '../lib/actual-adapter.js';
|
|
3
|
+
import { CommonSchemas } from '../lib/schemas/common.js';
|
|
3
4
|
import { notFoundMsg } from '../lib/errors.js';
|
|
4
5
|
const InputSchema = z.object({
|
|
5
|
-
id:
|
|
6
|
+
id: CommonSchemas.accountId.describe('The UUID of the account'),
|
|
6
7
|
cutoff: z.string().optional().describe('Optional cutoff date (YYYY-MM-DD format)')
|
|
7
8
|
}).strict();
|
|
8
9
|
const tool = {
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import adapter from '../lib/actual-adapter.js';
|
|
3
|
+
import { CommonSchemas } from '../lib/schemas/common.js';
|
|
3
4
|
const InputSchema = z.object({
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
|
|
5
|
+
// #380: tightened to the shared account schema. This comment previously said the
|
|
6
|
+
// opposite ("not tightened here: several fixtures use short non-UUID ids"), which was
|
|
7
|
+
// true until that sweep happened and would have read as an invitation to revert. The
|
|
8
|
+
// echo-into-logs concern it raised is still real and is now served by the UUID pattern,
|
|
9
|
+
// which is strictly tighter than the length bound it replaced.
|
|
10
|
+
id: CommonSchemas.accountId.describe('Account ID to reopen'),
|
|
8
11
|
});
|
|
9
12
|
/**
|
|
10
13
|
* #358. The guard lives in `adapter.reopenAccount`, which reads, writes and re-reads inside
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import adapter from '../lib/actual-adapter.js';
|
|
3
|
+
import { CommonSchemas } from '../lib/schemas/common.js';
|
|
3
4
|
import api from '@actual-app/api';
|
|
4
5
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5
6
|
const { setBudgetAmount: rawSetBudgetAmount, setBudgetCarryover: rawSetBudgetCarryover } = api;
|
|
6
7
|
const BudgetOperationSchema = z.object({
|
|
7
8
|
month: z.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/, 'month must be in YYYY-MM format (e.g. 2025-01)').describe('Budget month in YYYY-MM format'),
|
|
8
|
-
categoryId:
|
|
9
|
+
categoryId: CommonSchemas.categoryId.describe('Category ID'),
|
|
9
10
|
amount: z.number().optional().describe('Budget amount in cents (if setting amount)'),
|
|
10
11
|
carryover: z.boolean().optional().describe('Carryover flag (if setting carryover)'),
|
|
11
12
|
});
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import adapter from '../lib/actual-adapter.js';
|
|
3
|
+
import { CommonSchemas } from '../lib/schemas/common.js';
|
|
3
4
|
import { isPreflightRefusal } from '../lib/errors.js';
|
|
4
5
|
const InputSchema = z.object({
|
|
5
6
|
// #361: this was a bare z.string().min(1), so 'banana' parsed and reached the API. The
|
|
6
7
|
// regex matches actual_budgets_holdForNextMonth and the other month-taking tools; the
|
|
7
8
|
// adapter additionally checks the month is one this budget actually has.
|
|
8
9
|
month: z.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/, 'month must be in YYYY-MM format'),
|
|
9
|
-
categoryId:
|
|
10
|
+
categoryId: CommonSchemas.categoryId,
|
|
10
11
|
amount: z.number().int('amount must be an integer (cents)'),
|
|
11
12
|
});
|
|
12
13
|
const tool = {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import adapter from '../lib/actual-adapter.js';
|
|
3
|
+
import { CommonSchemas } from '../lib/schemas/common.js';
|
|
3
4
|
const InputSchema = z.object({
|
|
4
5
|
month: z.string().describe('Budget month in YYYY-MM format'),
|
|
5
|
-
categoryId:
|
|
6
|
+
categoryId: CommonSchemas.categoryId.describe('Category ID'),
|
|
6
7
|
flag: z.boolean().describe('Whether to carry over unused budget to next month (true) or not (false)'),
|
|
7
8
|
});
|
|
8
9
|
const tool = {
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import adapter from '../lib/actual-adapter.js';
|
|
3
|
+
import { CommonSchemas } from '../lib/schemas/common.js';
|
|
3
4
|
const InputSchema = z.object({
|
|
4
5
|
month: z.string()
|
|
5
6
|
.regex(/^\d{4}-\d{2}$/, 'month must be YYYY-MM')
|
|
6
7
|
.describe('Month in YYYY-MM format'),
|
|
7
|
-
fromCategoryId:
|
|
8
|
-
.min(1, 'fromCategoryId is required')
|
|
8
|
+
fromCategoryId: CommonSchemas.categoryId
|
|
9
9
|
.describe('Source category ID to transfer from'),
|
|
10
|
-
toCategoryId:
|
|
11
|
-
.min(1, 'toCategoryId is required')
|
|
10
|
+
toCategoryId: CommonSchemas.categoryId
|
|
12
11
|
.describe('Target category ID to transfer to'),
|
|
13
12
|
amount: z.number()
|
|
14
13
|
.int('amount must be an integer (cents)')
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import adapter from '../lib/actual-adapter.js';
|
|
3
|
+
import { CommonSchemas } from '../lib/schemas/common.js';
|
|
3
4
|
const InputSchema = z.object({
|
|
4
|
-
id:
|
|
5
|
+
id: CommonSchemas.categoryId.describe('Category ID to delete'),
|
|
5
6
|
});
|
|
6
7
|
const tool = {
|
|
7
8
|
name: 'actual_categories_delete',
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import adapter from '../lib/actual-adapter.js';
|
|
3
|
+
import { CommonSchemas } from '../lib/schemas/common.js';
|
|
3
4
|
const InputSchema = z.object({
|
|
4
|
-
id:
|
|
5
|
+
id: CommonSchemas.categoryId.describe('Category ID to update'),
|
|
5
6
|
fields: z.object({
|
|
6
7
|
name: z.string().optional().describe('New category name'),
|
|
7
|
-
group_id:
|
|
8
|
+
group_id: CommonSchemas.categoryGroupId.optional().describe('Category group ID to move this category to'),
|
|
8
9
|
is_income: z.boolean().optional().describe('Whether this is an income category'),
|
|
9
10
|
hidden: z.boolean().optional().describe('Whether this category is hidden'),
|
|
10
11
|
}).describe('Fields to update'),
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import adapter from '../lib/actual-adapter.js';
|
|
3
|
+
import { CommonSchemas } from '../lib/schemas/common.js';
|
|
3
4
|
const InputSchema = z.object({
|
|
4
|
-
id:
|
|
5
|
+
id: CommonSchemas.categoryGroupId.describe('Category group ID to delete'),
|
|
5
6
|
});
|
|
6
7
|
/**
|
|
7
8
|
* #376: the existence guard lives in `adapter.deleteCategoryGroup`, which reads and writes
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import adapter from '../lib/actual-adapter.js';
|
|
3
|
+
import { CommonSchemas } from '../lib/schemas/common.js';
|
|
3
4
|
const InputSchema = z.object({
|
|
4
|
-
id:
|
|
5
|
+
id: CommonSchemas.categoryGroupId.describe('Category group ID to update'),
|
|
5
6
|
fields: z.object({
|
|
6
7
|
name: z.string().optional().describe('New group name'),
|
|
7
8
|
is_income: z.boolean().optional().describe('Whether this is an income category group'),
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import adapter from '../lib/actual-adapter.js';
|
|
3
|
+
import { CommonSchemas } from '../lib/schemas/common.js';
|
|
3
4
|
import { notFoundMsg } from '../lib/errors.js';
|
|
4
5
|
const InputSchema = z.object({
|
|
5
|
-
payeeId:
|
|
6
|
+
payeeId: CommonSchemas.payeeId.describe('ID of the payee to get rules for'),
|
|
6
7
|
});
|
|
7
8
|
const tool = {
|
|
8
9
|
name: 'actual_payee_rules_get',
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import adapter from '../lib/actual-adapter.js';
|
|
3
|
+
import { CommonSchemas } from '../lib/schemas/common.js';
|
|
3
4
|
const InputSchema = z.object({
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
|
|
5
|
+
// #380: the shared rule schema. The reason from #356 still holds and is why it is not
|
|
6
|
+
// simply a bare string: this value is echoed into the not-found message, into the
|
|
7
|
+
// schedule-owned refusal, and into logger.error, so it must be bounded. The UUID pattern
|
|
8
|
+
// bounds it more tightly than the .max(64) it replaced.
|
|
9
|
+
id: CommonSchemas.ruleId.describe('Rule ID to delete'),
|
|
7
10
|
});
|
|
8
11
|
/**
|
|
9
12
|
* #355 fixed two defects here (a silent no-op on an unknown id, and success reported for a
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import adapter from '../lib/actual-adapter.js';
|
|
3
|
+
import { CommonSchemas } from '../lib/schemas/common.js';
|
|
3
4
|
// Define the schema for rule conditions and actions (same as create)
|
|
4
5
|
const ConditionSchema = z.object({
|
|
5
6
|
field: z.string().describe('Field to match (e.g., "payee", "notes", "amount", "category")'),
|
|
@@ -26,7 +27,7 @@ const FIELD_OPERATORS = {
|
|
|
26
27
|
'date': { type: 'date', operators: ['is', 'gte', 'lte', 'gt', 'lt'] },
|
|
27
28
|
};
|
|
28
29
|
const InputSchema = z.object({
|
|
29
|
-
id:
|
|
30
|
+
id: CommonSchemas.ruleId.describe('Rule ID to update'),
|
|
30
31
|
fields: z.object({
|
|
31
32
|
// #342: null is Actual's DEFAULT stage; the literal "default" is rejected by
|
|
32
33
|
// its validator. Deliberately NO .default() here: this is a partial update, so
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import adapter from '../lib/actual-adapter.js';
|
|
3
|
-
import {
|
|
3
|
+
import { CommonSchemas } from '../lib/schemas/common.js';
|
|
4
4
|
import { RecurConfigSchema } from '../lib/schemas/recur.js';
|
|
5
5
|
const InputSchema = z.object({
|
|
6
6
|
name: z.string().optional()
|
|
7
7
|
.describe('Unique display name for the schedule'),
|
|
8
|
-
payee:
|
|
8
|
+
payee: CommonSchemas.payeeId.optional()
|
|
9
9
|
.describe('Payee UUID (from actual_payees_get)'),
|
|
10
|
-
account:
|
|
10
|
+
account: CommonSchemas.accountId.optional()
|
|
11
11
|
.describe('Account UUID (from actual_accounts_list). If omitted the schedule is not tied to an account'),
|
|
12
12
|
amount: z.number().int().optional()
|
|
13
13
|
.describe('Amount in cents. Negative = expense (e.g. -5000 = -$50.00), positive = income'),
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import adapter from '../lib/actual-adapter.js';
|
|
3
|
-
import {
|
|
3
|
+
import { CommonSchemas } from '../lib/schemas/common.js';
|
|
4
4
|
const InputSchema = z.object({
|
|
5
|
-
id:
|
|
6
|
-
.describe('UUID of the schedule to delete (from actual_schedules_get)'),
|
|
5
|
+
id: CommonSchemas.scheduleId.describe('UUID of the schedule to delete (from actual_schedules_get)'),
|
|
7
6
|
});
|
|
8
7
|
/**
|
|
9
8
|
* #376: the existence guard and the SQLite constraint-error translation live in
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import adapter from '../lib/actual-adapter.js';
|
|
3
|
-
import {
|
|
3
|
+
import { CommonSchemas } from '../lib/schemas/common.js';
|
|
4
4
|
import { RecurConfigSchema } from '../lib/schemas/recur.js';
|
|
5
5
|
const InputSchema = z.object({
|
|
6
|
-
id:
|
|
7
|
-
.describe('UUID of the schedule to update (from actual_schedules_get)'),
|
|
6
|
+
id: CommonSchemas.scheduleId.describe('UUID of the schedule to update (from actual_schedules_get)'),
|
|
8
7
|
name: z.string().optional()
|
|
9
8
|
.describe('New display name for the schedule'),
|
|
10
|
-
payee:
|
|
9
|
+
payee: CommonSchemas.payeeId.nullable().optional()
|
|
11
10
|
.describe('New payee UUID, or null to clear'),
|
|
12
|
-
account:
|
|
11
|
+
account: CommonSchemas.accountId.nullable().optional()
|
|
13
12
|
.describe('New account UUID, or null to clear'),
|
|
14
13
|
amount: z.number().int().optional()
|
|
15
14
|
.describe('New amount in cents. Negative = expense, positive = income'),
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import adapter from '../lib/actual-adapter.js';
|
|
3
|
+
import { CommonSchemas } from '../lib/schemas/common.js';
|
|
3
4
|
const InputSchema = z.object({
|
|
4
|
-
id:
|
|
5
|
+
id: CommonSchemas.transactionId.describe('Transaction ID to delete'),
|
|
5
6
|
});
|
|
6
7
|
const tool = {
|
|
7
8
|
name: 'actual_transactions_delete',
|
|
@@ -2,7 +2,15 @@ import { z } from 'zod';
|
|
|
2
2
|
import adapter from '../lib/actual-adapter.js';
|
|
3
3
|
import { CommonSchemas } from '../lib/schemas/common.js';
|
|
4
4
|
const InputSchema = z.object({
|
|
5
|
-
|
|
5
|
+
// #380: REQUIRED, and typed. It was `.optional()` with the describe "optional for smoke
|
|
6
|
+
// tests, required for actual usage": a published contract weakened to suit a test. The
|
|
7
|
+
// handler then returned `{ success: true }` for a call with no id, writing nothing, which
|
|
8
|
+
// is the #350 failure this project has spent three releases removing. A model that omitted
|
|
9
|
+
// the id was told its edit had succeeded.
|
|
10
|
+
//
|
|
11
|
+
// The smoke test does supply an id (generated_tools.smoke.test.js), so the escape hatch
|
|
12
|
+
// was not even load bearing when it was removed.
|
|
13
|
+
id: CommonSchemas.transactionId.describe('Transaction ID to update'),
|
|
6
14
|
fields: z.object({
|
|
7
15
|
account: z.string().nullable().optional().describe('Account ID'),
|
|
8
16
|
date: z.string().nullable().optional().describe('Transaction date (YYYY-MM-DD)'),
|
|
@@ -32,10 +40,6 @@ const tool = {
|
|
|
32
40
|
inputSchema: InputSchema,
|
|
33
41
|
call: async (args, _meta) => {
|
|
34
42
|
const input = InputSchema.parse(args || {});
|
|
35
|
-
// For smoke tests, return early if no id provided
|
|
36
|
-
if (!input.id) {
|
|
37
|
-
return { success: true };
|
|
38
|
-
}
|
|
39
43
|
await adapter.updateTransaction(input.id, input.fields);
|
|
40
44
|
return { success: true };
|
|
41
45
|
},
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { z } from 'zod';
|
|
15
15
|
import adapter from '../lib/actual-adapter.js';
|
|
16
|
+
import { CommonSchemas } from '../lib/schemas/common.js';
|
|
16
17
|
const FieldsSchema = z.object({
|
|
17
18
|
account: z.string().nullable().optional().describe('Account ID'),
|
|
18
19
|
date: z.string().nullable().optional().describe('Transaction date (YYYY-MM-DD)'),
|
|
@@ -25,7 +26,7 @@ const FieldsSchema = z.object({
|
|
|
25
26
|
cleared: z.boolean().nullable().optional().describe('Whether transaction is cleared'),
|
|
26
27
|
});
|
|
27
28
|
const UpdateItemSchema = z.object({
|
|
28
|
-
id:
|
|
29
|
+
id: CommonSchemas.transactionId.describe('Transaction ID to update'),
|
|
29
30
|
fields: FieldsSchema.describe('Fields to update for this transaction'),
|
|
30
31
|
});
|
|
31
32
|
const InputSchema = z.object({
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "actual-mcp-server",
|
|
3
3
|
"displayName": "Actual MCP Server",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.16.0",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=22.0.0",
|
|
7
7
|
"npm": ">=10.0.0"
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"verify-tools": "npm run build && node scripts/verify-tools.js",
|
|
31
31
|
"check:coverage": "node scripts/list-actual-api-methods.mjs",
|
|
32
32
|
"direct-sync": "node scripts/direct-sync/bank-sync-direct.mjs",
|
|
33
|
-
"test:unit-js": "node tests/unit/transactions_create.test.js && node tests/unit/generated_tools.smoke.test.js && node tests/unit/schema_validation.test.js && node tests/unit/schema_json_openai_compat.test.js && node tests/unit/config_https_validation.test.js && node tests/unit/config_data_dir.test.js && node tests/unit/config_drift.test.js && node tests/unit/port_alignment.test.js && node tests/unit/dockerfile_data_dir_alignment.test.js && node tests/unit/unraid_template_alignment.test.js && node tests/unit/entrypoint_invariants.test.js && node tests/unit/e2e_spec_collection.test.js && node tests/unit/compose_profile_sync.test.js && node tests/unit/advertised_tools_sync.test.js && node tests/unit/knip_config.test.js && node tests/unit/readme_stats_sync.test.js && node tests/unit/config_insecure_upstream.test.js && node tests/unit/workflow_release_guards.test.js && node tests/unit/report_train_failure.test.js && node tests/unit/unit_chain_membership.test.js && node tests/unit/api_surface_drift.test.js && node tests/unit/write_effect_audit_staleness.test.js && node tests/unit/write_effect_audit_membership.test.js && node tests/unit/tool_annotations.test.js && node tests/unit/api_coverage_baseline.test.js && node tests/unit/train_preflight.test.js && node tests/unit/verify_published_artifacts.test.js && node tests/unit/report_train_stale.test.js && node tests/unit/stdio_framing_check.test.js && node tests/unit/server_info.test.js && node tests/unit/transfers_create.test.js && node tests/unit/bot_target_branch.test.js && node tests/unit/auth_posture.test.js && node tests/unit/auth_posture_wiring.test.js && node tests/unit/auth-acl.test.js && node tests/unit/bug76.test.js && node tests/unit/budgets_setAmount.test.js && node tests/unit/budgets_hold_for_next_month.test.js && node tests/unit/budgets_transfer.test.js && node tests/unit/transactions_uncategorized.test.js && node tests/unit/httpServer_session_init.test.js && node tests/unit/httpServer_session_not_found.test.js && node tests/unit/manual_mcp_client_retry.test.js && node tests/unit/manual_mcp_client_session.test.js && node tests/unit/manual_mcp_client_circuit.test.js && node tests/unit/manual_runner_killswitch.test.js && node tests/unit/adapter_auth_rate_limit.test.js && node tests/unit/adapter_session_reuse.test.js && node tests/unit/retry_classifier.test.js && node tests/unit/adapter_module_surface.test.js && node tests/unit/adapter_nonidempotent_no_retry.test.js && node tests/unit/pool_liveness.test.js && node tests/unit/pool_shutdown_all.test.js && node tests/unit/query_where_operators.test.js && node tests/unit/query_run_validation.test.js && node tests/unit/adapter_with_write_session.test.js && node tests/unit/category_groups_delete.test.js && node tests/unit/rules_delete.test.js && node tests/unit/schedules_delete.test.js && node tests/unit/accounts_delete.test.js && node tests/unit/update_tools_not_found.test.js && node tests/unit/accounts_close.test.js && node tests/unit/accounts_reopen.test.js && node tests/unit/payees_delete.test.js && node tests/unit/payees_merge.test.js && node tests/unit/rules_create_or_update.test.js && node tests/unit/unhandled-rejection.test.js && node tests/unit/rejection-allowlist-purity.test.js && node tests/unit/httpServer_bearer_auth.test.js && node tests/unit/httpServer_oidc_audience.test.js && node tests/unit/httpServer_oidc_auth_verification.test.js && node tests/unit/httpServer_oidc_jwks_discovery.test.js && node tests/unit/httpServer_body_limit.test.js && node tests/unit/httpServer_bind_host.test.js && node tests/unit/adapter_write_pool_cooperation.test.js && node tests/unit/budget_acl_enforcement.test.js && node tests/unit/budget_preference_store.test.js && node tests/unit/budget_preference_restore.test.js && node tests/unit/tags_list.test.js && node tests/unit/tags_create.test.js && node tests/unit/tags_update.test.js && node tests/unit/tags_delete.test.js && node tests/unit/notes_get.test.js && node tests/unit/notes_update.test.js && node tests/unit/payees_common_list.test.js && node tests/unit/transactions_update_guard.test.js && node tests/unit/transactions_update_splits.test.js && node tests/unit/entities_search.test.js && node tests/unit/transactions_import_schema.test.js && node tests/unit/tool_schema_shape.test.js && node tests/unit/zod_error_format.test.js && node tests/unit/tool_count_sync.test.js && node tests/unit/stdio_transport.test.js && node tests/unit/stdio_budget_switch.test.js && node tests/unit/logger_structured.test.js && node tests/unit/logger_redaction.test.js && node tests/unit/logger_correlation.test.js && node tests/unit/check_coverage.test.js && node tests/unit/adapter_op_timeout.test.js && node tests/unit/adapter_write_queue_wakeup.test.js && node tests/unit/ci_workflow_guards.test.js && node tests/unit/node_version_guard.test.js && node tests/unit/node_version_drift.test.js && node tests/unit/observability_smoke.test.js && node tests/unit/residue_pattern.test.js && node tests/unit/dual_transport_gate.test.js && node tests/unit/manual_assertions_use_helper.test.js && node tests/unit/server_version_guard.test.js && node tests/unit/payee_rules_reference_filter.test.js && node tests/unit/oidc_metadata_discovery.test.js && node tests/unit/httpServer_oauth_metadata_route.test.js && node tests/unit/httpServer_mcp_info_route.test.js && node tests/unit/residue_sweep_balance_account.test.js && node tests/unit/tool_factory.test.js && node tests/unit/budget_registry_parse.test.js && node tests/unit/preferences_get.test.js && node tests/unit/budgets_export.test.js && node tests/unit/budgets_import.test.js && node tests/unit/budgets_import_syncid.test.js && node tests/unit/budget_acl_dynamic.test.js && node tests/unit/budget_acl_identity_map.test.js && node tests/unit/budget_acl_userinfo.test.js && node tests/unit/acl_e2e_fixture_contract.test.js && node tests/unit/budget_acl_middleware.test.js && node tests/unit/rules_stage.test.js",
|
|
33
|
+
"test:unit-js": "node tests/unit/transactions_create.test.js && node tests/unit/generated_tools.smoke.test.js && node tests/unit/schema_validation.test.js && node tests/unit/schema_json_openai_compat.test.js && node tests/unit/config_https_validation.test.js && node tests/unit/config_data_dir.test.js && node tests/unit/config_drift.test.js && node tests/unit/port_alignment.test.js && node tests/unit/dockerfile_data_dir_alignment.test.js && node tests/unit/unraid_template_alignment.test.js && node tests/unit/entrypoint_invariants.test.js && node tests/unit/e2e_spec_collection.test.js && node tests/unit/compose_profile_sync.test.js && node tests/unit/advertised_tools_sync.test.js && node tests/unit/knip_config.test.js && node tests/unit/readme_stats_sync.test.js && node tests/unit/config_insecure_upstream.test.js && node tests/unit/workflow_release_guards.test.js && node tests/unit/report_train_failure.test.js && node tests/unit/unit_chain_membership.test.js && node tests/unit/api_surface_drift.test.js && node tests/unit/write_effect_audit_staleness.test.js && node tests/unit/write_effect_audit_membership.test.js && node tests/unit/tool_annotations.test.js && node tests/unit/tool_id_schema_drift.test.js && node tests/unit/api_coverage_baseline.test.js && node tests/unit/train_preflight.test.js && node tests/unit/verify_published_artifacts.test.js && node tests/unit/report_train_stale.test.js && node tests/unit/stdio_framing_check.test.js && node tests/unit/server_info.test.js && node tests/unit/transfers_create.test.js && node tests/unit/bot_target_branch.test.js && node tests/unit/auth_posture.test.js && node tests/unit/auth_posture_wiring.test.js && node tests/unit/auth-acl.test.js && node tests/unit/bug76.test.js && node tests/unit/budgets_setAmount.test.js && node tests/unit/budgets_hold_for_next_month.test.js && node tests/unit/budgets_transfer.test.js && node tests/unit/transactions_uncategorized.test.js && node tests/unit/httpServer_session_init.test.js && node tests/unit/httpServer_session_not_found.test.js && node tests/unit/manual_mcp_client_retry.test.js && node tests/unit/manual_mcp_client_session.test.js && node tests/unit/manual_mcp_client_circuit.test.js && node tests/unit/manual_runner_killswitch.test.js && node tests/unit/adapter_auth_rate_limit.test.js && node tests/unit/adapter_session_reuse.test.js && node tests/unit/retry_classifier.test.js && node tests/unit/adapter_module_surface.test.js && node tests/unit/adapter_nonidempotent_no_retry.test.js && node tests/unit/pool_liveness.test.js && node tests/unit/pool_shutdown_all.test.js && node tests/unit/query_where_operators.test.js && node tests/unit/query_run_validation.test.js && node tests/unit/adapter_with_write_session.test.js && node tests/unit/category_groups_delete.test.js && node tests/unit/rules_delete.test.js && node tests/unit/schedules_delete.test.js && node tests/unit/accounts_delete.test.js && node tests/unit/update_tools_not_found.test.js && node tests/unit/accounts_close.test.js && node tests/unit/accounts_reopen.test.js && node tests/unit/payees_delete.test.js && node tests/unit/payees_merge.test.js && node tests/unit/rules_create_or_update.test.js && node tests/unit/unhandled-rejection.test.js && node tests/unit/rejection-allowlist-purity.test.js && node tests/unit/httpServer_bearer_auth.test.js && node tests/unit/httpServer_oidc_audience.test.js && node tests/unit/httpServer_oidc_auth_verification.test.js && node tests/unit/httpServer_oidc_jwks_discovery.test.js && node tests/unit/httpServer_body_limit.test.js && node tests/unit/httpServer_bind_host.test.js && node tests/unit/adapter_write_pool_cooperation.test.js && node tests/unit/budget_acl_enforcement.test.js && node tests/unit/budget_preference_store.test.js && node tests/unit/budget_preference_restore.test.js && node tests/unit/tags_list.test.js && node tests/unit/tags_create.test.js && node tests/unit/tags_update.test.js && node tests/unit/tags_delete.test.js && node tests/unit/notes_get.test.js && node tests/unit/notes_update.test.js && node tests/unit/payees_common_list.test.js && node tests/unit/transactions_update_guard.test.js && node tests/unit/transactions_update_splits.test.js && node tests/unit/entities_search.test.js && node tests/unit/transactions_import_schema.test.js && node tests/unit/tool_schema_shape.test.js && node tests/unit/zod_error_format.test.js && node tests/unit/tool_count_sync.test.js && node tests/unit/stdio_transport.test.js && node tests/unit/stdio_budget_switch.test.js && node tests/unit/logger_structured.test.js && node tests/unit/logger_redaction.test.js && node tests/unit/logger_correlation.test.js && node tests/unit/check_coverage.test.js && node tests/unit/adapter_op_timeout.test.js && node tests/unit/adapter_write_queue_wakeup.test.js && node tests/unit/ci_workflow_guards.test.js && node tests/unit/node_version_guard.test.js && node tests/unit/node_version_drift.test.js && node tests/unit/observability_smoke.test.js && node tests/unit/residue_pattern.test.js && node tests/unit/dual_transport_gate.test.js && node tests/unit/manual_assertions_use_helper.test.js && node tests/unit/server_version_guard.test.js && node tests/unit/payee_rules_reference_filter.test.js && node tests/unit/oidc_metadata_discovery.test.js && node tests/unit/httpServer_oauth_metadata_route.test.js && node tests/unit/httpServer_mcp_info_route.test.js && node tests/unit/residue_sweep_balance_account.test.js && node tests/unit/tool_factory.test.js && node tests/unit/budget_registry_parse.test.js && node tests/unit/preferences_get.test.js && node tests/unit/budgets_export.test.js && node tests/unit/budgets_import.test.js && node tests/unit/budgets_import_syncid.test.js && node tests/unit/budget_acl_dynamic.test.js && node tests/unit/budget_acl_identity_map.test.js && node tests/unit/budget_acl_userinfo.test.js && node tests/unit/acl_e2e_fixture_contract.test.js && node tests/unit/budget_acl_middleware.test.js && node tests/unit/rules_stage.test.js",
|
|
34
34
|
"test:adapter": "npm run build && node dist/src/tests_adapter_runner.js",
|
|
35
35
|
"test:e2e": "npx playwright test",
|
|
36
36
|
"test:e2e:docker": "./tests/e2e/run-docker-e2e.sh",
|