@goodsamsoftware/freshbooks-mcp 1.0.17 → 1.0.19

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.
@@ -22,8 +22,8 @@ export declare const callbackCreateTool: {
22
22
  event: z.ZodString;
23
23
  uri: z.ZodString;
24
24
  verified: z.ZodBoolean;
25
- createdAt: z.ZodString;
26
- updatedAt: z.ZodString;
25
+ createdAt: z.ZodOptional<z.ZodString>;
26
+ updatedAt: z.ZodOptional<z.ZodString>;
27
27
  }, z.core.$strip>;
28
28
  execute(input: z.infer<typeof CallbackCreateInputSchema>, client: FreshBooksClientWrapper): Promise<z.infer<typeof CallbackSingleOutputSchema>>;
29
29
  };
@@ -23,8 +23,8 @@ export declare const callbackListTool: {
23
23
  event: z.ZodString;
24
24
  uri: z.ZodString;
25
25
  verified: z.ZodBoolean;
26
- createdAt: z.ZodString;
27
- updatedAt: z.ZodString;
26
+ createdAt: z.ZodOptional<z.ZodString>;
27
+ updatedAt: z.ZodOptional<z.ZodString>;
28
28
  }, z.core.$strip>>;
29
29
  pagination: z.ZodObject<{
30
30
  page: z.ZodNumber;
@@ -1 +1 @@
1
- {"version":3,"file":"callback-list.d.ts","sourceRoot":"","sources":["../../../src/tools/callback/callback-list.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAGjF,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAEhE;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;mBAiClB,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,UACtC,uBAAuB,GAC9B,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;CAsDrD,CAAC"}
1
+ {"version":3,"file":"callback-list.d.ts","sourceRoot":"","sources":["../../../src/tools/callback/callback-list.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAGjF,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAEhE;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;mBAiClB,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,UACtC,uBAAuB,GAC9B,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;CA0DrD,CAAC"}
@@ -41,44 +41,70 @@ Array of webhook configurations with their verification status and event types.`
41
41
  async execute(input, client) {
42
42
  const handler = ErrorHandler.wrapHandler('callback_list', async (input, _context) => {
43
43
  const { accountId, page, perPage } = input;
44
- const result = await client.executeWithRetry('callback_list', async (fbClient) => {
45
- const { PaginationQueryBuilder } = await import('@freshbooks/api/dist/models/builders/index.js');
46
- // Build query builders array
47
- const queryBuilders = [];
48
- // Add pagination if specified
49
- if (page !== undefined || perPage !== undefined) {
50
- const pagination = new PaginationQueryBuilder();
51
- if (page !== undefined)
52
- pagination.page(page);
53
- if (perPage !== undefined)
54
- pagination.perPage(perPage);
55
- queryBuilders.push(pagination);
56
- }
57
- const response = await fbClient.callbacks.list(accountId, queryBuilders);
58
- if (!response.ok) {
59
- throw response.error;
60
- }
61
- return response.data;
62
- });
63
- // Extract data
64
- const callbacks = result.callbacks || [];
65
- const paginationData = result.pages || {
66
- page: 1,
67
- pages: 1,
68
- total: callbacks.length,
69
- per_page: 30,
70
- };
44
+ // The SDK's `callbacks.list` runs every callback's `updated_at` through
45
+ // `transformDateResponse` (luxon `fromSQL(...).toJSDate()`). A single
46
+ // callback with an unparseable `updated_at` yields an Invalid Date, and
47
+ // downstream ISO serialization throws "Invalid time value" — taking down
48
+ // the WHOLE list (live-confirmed, #70). We bypass the SDK transform with a
49
+ // raw GET and guard each date ourselves so one bad webhook can't break the
50
+ // page.
51
+ const query = [];
52
+ if (page !== undefined)
53
+ query.push(`page=${encodeURIComponent(String(page))}`);
54
+ if (perPage !== undefined)
55
+ query.push(`per_page=${encodeURIComponent(String(perPage))}`);
56
+ const queryString = query.length ? `?${query.join('&')}` : '';
57
+ const result = await client.executeRawWithRetry('GET', `/events/account/${accountId}/events/callbacks${queryString}`, undefined, 'callback_list');
58
+ if (!result.ok) {
59
+ throw result.error ?? new Error('Callback list failed');
60
+ }
61
+ // Events API returns { response: { result: { callbacks, page, pages, per_page, total } } }
62
+ const apiResult = result.data?.response?.result ?? {};
63
+ const rawCallbacks = Array.isArray(apiResult.callbacks) ? apiResult.callbacks : [];
64
+ const callbacks = rawCallbacks.map((cb) => ({
65
+ id: cb.callbackid,
66
+ event: cb.event,
67
+ uri: cb.uri,
68
+ verified: cb.verified,
69
+ // Pass dates through a guard: valid → ISO 8601, unparseable → raw string
70
+ // (never throw). The events API emits SQL-style "YYYY-MM-DD HH:mm:ss".
71
+ createdAt: safeIsoDate(cb.created_at),
72
+ updatedAt: safeIsoDate(cb.updated_at),
73
+ }));
71
74
  return {
72
75
  callbacks,
73
76
  pagination: {
74
- page: paginationData.page,
75
- pages: paginationData.pages,
76
- perPage: paginationData.per_page || paginationData.perPage || 30,
77
- total: paginationData.total,
77
+ page: apiResult.page ?? 1,
78
+ pages: apiResult.pages ?? 1,
79
+ perPage: apiResult.per_page ?? perPage ?? 30,
80
+ total: apiResult.total ?? callbacks.length,
78
81
  },
79
82
  };
80
83
  });
81
84
  return handler(input, { accountId: input.accountId });
82
85
  },
83
86
  };
87
+ /**
88
+ * Convert a FreshBooks date string to ISO 8601, or pass it through unchanged if
89
+ * it cannot be parsed. Never throws — this is the guard that prevents one bad
90
+ * `updated_at` from crashing the entire callback list (#70).
91
+ *
92
+ * FreshBooks events API emits SQL-style "YYYY-MM-DD HH:mm:ss" (UTC). We treat a
93
+ * bare SQL timestamp as UTC by appending "Z" before parsing.
94
+ */
95
+ function safeIsoDate(value) {
96
+ if (typeof value !== 'string' || value.trim() === '') {
97
+ return undefined;
98
+ }
99
+ // Normalize "YYYY-MM-DD HH:mm:ss" → "YYYY-MM-DDTHH:mm:ssZ" for Date parsing.
100
+ const normalized = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/.test(value)
101
+ ? `${value.replace(' ', 'T')}Z`
102
+ : value;
103
+ const parsed = new Date(normalized);
104
+ if (Number.isNaN(parsed.getTime())) {
105
+ // Unparseable — return the original string rather than crashing.
106
+ return value;
107
+ }
108
+ return parsed.toISOString();
109
+ }
84
110
  //# sourceMappingURL=callback-list.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"callback-list.js","sourceRoot":"","sources":["../../../src/tools/callback/callback-list.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAI7D;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,IAAI,EAAE,eAAe;IACrB,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;gFAyBiE;IAE9E,WAAW,EAAE,uBAAuB;IACpC,YAAY,EAAE,wBAAwB;IAEtC,KAAK,CAAC,OAAO,CACX,KAA8C,EAC9C,MAA+B;QAE/B,MAAM,OAAO,GAAG,YAAY,CAAC,WAAW,CACtC,eAAe,EACf,KAAK,EAAE,KAA8C,EAAE,QAAqB,EAAE,EAAE;YAC9E,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;YAE3C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,eAAe,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;gBAC/E,MAAM,EAAE,sBAAsB,EAAE,GAAG,MAAM,MAAM,CAC7C,+CAA+C,CAChD,CAAC;gBAEF,6BAA6B;gBAC7B,MAAM,aAAa,GAAU,EAAE,CAAC;gBAEhC,8BAA8B;gBAC9B,IAAI,IAAI,KAAK,SAAS,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;oBAChD,MAAM,UAAU,GAAG,IAAI,sBAAsB,EAAE,CAAC;oBAChD,IAAI,IAAI,KAAK,SAAS;wBAAE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBAC9C,IAAI,OAAO,KAAK,SAAS;wBAAE,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;oBACvD,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBACjC,CAAC;gBAED,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;gBAEzE,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;oBACjB,MAAM,QAAQ,CAAC,KAAK,CAAC;gBACvB,CAAC;gBAED,OAAO,QAAQ,CAAC,IAAI,CAAC;YACvB,CAAC,CAAC,CAAC;YAEH,eAAe;YACf,MAAM,SAAS,GAAI,MAAc,CAAC,SAAS,IAAI,EAAE,CAAC;YAClD,MAAM,cAAc,GAAI,MAAc,CAAC,KAAK,IAAI;gBAC9C,IAAI,EAAE,CAAC;gBACP,KAAK,EAAE,CAAC;gBACR,KAAK,EAAE,SAAS,CAAC,MAAM;gBACvB,QAAQ,EAAE,EAAE;aACb,CAAC;YAEF,OAAO;gBACL,SAAS;gBACT,UAAU,EAAE;oBACV,IAAI,EAAE,cAAc,CAAC,IAAI;oBACzB,KAAK,EAAE,cAAc,CAAC,KAAK;oBAC3B,OAAO,EAAE,cAAc,CAAC,QAAQ,IAAI,cAAc,CAAC,OAAO,IAAI,EAAE;oBAChE,KAAK,EAAE,cAAc,CAAC,KAAK;iBAC5B;aACF,CAAC;QACJ,CAAC,CACF,CAAC;QAEF,OAAO,OAAO,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;IACxD,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"callback-list.js","sourceRoot":"","sources":["../../../src/tools/callback/callback-list.ts"],"names":[],"mappings":"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"}
@@ -21,8 +21,8 @@ export declare const callbackResendVerificationTool: {
21
21
  event: z.ZodString;
22
22
  uri: z.ZodString;
23
23
  verified: z.ZodBoolean;
24
- createdAt: z.ZodString;
25
- updatedAt: z.ZodString;
24
+ createdAt: z.ZodOptional<z.ZodString>;
25
+ updatedAt: z.ZodOptional<z.ZodString>;
26
26
  }, z.core.$strip>;
27
27
  execute(input: z.infer<typeof CallbackResendVerificationInputSchema>, client: FreshBooksClientWrapper): Promise<z.infer<typeof CallbackSingleOutputSchema>>;
28
28
  };
@@ -21,8 +21,8 @@ export declare const callbackSingleTool: {
21
21
  event: z.ZodString;
22
22
  uri: z.ZodString;
23
23
  verified: z.ZodBoolean;
24
- createdAt: z.ZodString;
25
- updatedAt: z.ZodString;
24
+ createdAt: z.ZodOptional<z.ZodString>;
25
+ updatedAt: z.ZodOptional<z.ZodString>;
26
26
  }, z.core.$strip>;
27
27
  execute(input: z.infer<typeof CallbackSingleInputSchema>, client: FreshBooksClientWrapper): Promise<z.infer<typeof CallbackSingleOutputSchema>>;
28
28
  };
@@ -23,8 +23,8 @@ export declare const callbackUpdateTool: {
23
23
  event: z.ZodString;
24
24
  uri: z.ZodString;
25
25
  verified: z.ZodBoolean;
26
- createdAt: z.ZodString;
27
- updatedAt: z.ZodString;
26
+ createdAt: z.ZodOptional<z.ZodString>;
27
+ updatedAt: z.ZodOptional<z.ZodString>;
28
28
  }, z.core.$strip>;
29
29
  execute(input: z.infer<typeof CallbackUpdateInputSchema>, client: FreshBooksClientWrapper): Promise<z.infer<typeof CallbackSingleOutputSchema>>;
30
30
  };
@@ -12,8 +12,8 @@ export declare const CallbackSchema: z.ZodObject<{
12
12
  event: z.ZodString;
13
13
  uri: z.ZodString;
14
14
  verified: z.ZodBoolean;
15
- createdAt: z.ZodString;
16
- updatedAt: z.ZodString;
15
+ createdAt: z.ZodOptional<z.ZodString>;
16
+ updatedAt: z.ZodOptional<z.ZodString>;
17
17
  }, z.core.$strip>;
18
18
  /**
19
19
  * Input schema for creating a callback
@@ -89,8 +89,8 @@ export declare const CallbackListOutputSchema: z.ZodObject<{
89
89
  event: z.ZodString;
90
90
  uri: z.ZodString;
91
91
  verified: z.ZodBoolean;
92
- createdAt: z.ZodString;
93
- updatedAt: z.ZodString;
92
+ createdAt: z.ZodOptional<z.ZodString>;
93
+ updatedAt: z.ZodOptional<z.ZodString>;
94
94
  }, z.core.$strip>>;
95
95
  pagination: z.ZodObject<{
96
96
  page: z.ZodNumber;
@@ -107,8 +107,8 @@ export declare const CallbackSingleOutputSchema: z.ZodObject<{
107
107
  event: z.ZodString;
108
108
  uri: z.ZodString;
109
109
  verified: z.ZodBoolean;
110
- createdAt: z.ZodString;
111
- updatedAt: z.ZodString;
110
+ createdAt: z.ZodOptional<z.ZodString>;
111
+ updatedAt: z.ZodOptional<z.ZodString>;
112
112
  }, z.core.$strip>;
113
113
  /**
114
114
  * Output schema for callback deletion
@@ -1 +1 @@
1
- {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../../src/tools/callback/schemas.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AACH,eAAO,MAAM,cAAc;;;;;;;iBAOzB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,yBAAyB;;;;iBAIpC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,yBAAyB;;;;;iBAKpC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;iBAWlC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,yBAAyB;;;iBAGpC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,yBAAyB;;;;;iBAKpC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,yBAAyB;;;;iBAIpC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,qCAAqC;;;iBAGhD,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,wBAAwB;;;;;iBAKnC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;iBAGnC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,0BAA0B;;;;;;;iBAAiB,CAAC;AAEzD;;GAEG;AACH,eAAO,MAAM,0BAA0B;;;iBAGrC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,0BAA0B;;;;iBAIrC,CAAC"}
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../../src/tools/callback/schemas.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AACH,eAAO,MAAM,cAAc;;;;;;;iBAgBzB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,yBAAyB;;;;iBAIpC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,yBAAyB;;;;;iBAKpC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;iBAWlC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,yBAAyB;;;iBAGpC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,yBAAyB;;;;;iBAKpC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,yBAAyB;;;;iBAIpC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,qCAAqC;;;iBAGhD,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,wBAAwB;;;;;iBAKnC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;iBAGnC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,0BAA0B;;;;;;;iBAAiB,CAAC;AAEzD;;GAEG;AACH,eAAO,MAAM,0BAA0B;;;iBAGrC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,0BAA0B;;;;iBAIrC,CAAC"}
@@ -12,8 +12,17 @@ export const CallbackSchema = z.object({
12
12
  event: z.string().describe('Event type to listen for (e.g., invoice.create, payment.create)'),
13
13
  uri: z.string().url().describe('Webhook endpoint URL to POST events to'),
14
14
  verified: z.boolean().describe('Whether webhook ownership has been verified'),
15
- createdAt: z.string().datetime().describe('Creation timestamp (ISO 8601)'),
16
- updatedAt: z.string().datetime().describe('Last update timestamp (ISO 8601)'),
15
+ // The events API may omit these or return a value the date parser rejects. We
16
+ // surface ISO 8601 when the timestamp parses and the raw string otherwise
17
+ // (rather than crashing the whole list — #70), so these are optional strings.
18
+ createdAt: z
19
+ .string()
20
+ .optional()
21
+ .describe('Creation timestamp (ISO 8601 when parseable; raw API value otherwise)'),
22
+ updatedAt: z
23
+ .string()
24
+ .optional()
25
+ .describe('Last update timestamp (ISO 8601 when parseable; raw API value otherwise)'),
17
26
  });
18
27
  /**
19
28
  * Input schema for creating a callback
@@ -1 +1 @@
1
- {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../../src/tools/callback/schemas.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../../src/tools/callback/schemas.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,4BAA4B,CAAC;IACrD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iEAAiE,CAAC;IAC7F,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC;IACxE,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;IAC7E,8EAA8E;IAC9E,0EAA0E;IAC1E,8EAA8E;IAC9E,SAAS,EAAE,CAAC;SACT,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,uEAAuE,CAAC;IACpF,SAAS,EAAE,CAAC;SACT,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,0EAA0E,CAAC;CACxF,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChD,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;IACvD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,oFAAoF,CAAC;IACvH,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,mEAAmE,CAAC;CACpG,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChD,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;IACvD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;IACxD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;IACxE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;CAClE,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;IACvD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;IACvF,OAAO,EAAE,CAAC;SACP,MAAM,EAAE;SACR,GAAG,EAAE;SACL,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,GAAG,CAAC;SACR,OAAO,CAAC,EAAE,CAAC;SACX,QAAQ,EAAE;SACV,QAAQ,CAAC,sCAAsC,CAAC;CACpD,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChD,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;IACvD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;CAC3D,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChD,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;IACvD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;IACxD,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kDAAkD,CAAC;IAC9F,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,oFAAoF,CAAC;CACrI,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChD,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;IACvD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;IACxD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,qDAAqD,CAAC;CACrF,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,qCAAqC,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5D,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;IACvD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC;CAC1E,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/C,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,qBAAqB,CAAC;IAChD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;IACnD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;IAChD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;CACtD,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/C,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,QAAQ,CAAC,oBAAoB,CAAC;IACjE,UAAU,EAAE,wBAAwB,CAAC,QAAQ,CAAC,wBAAwB,CAAC;CACxE,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,cAAc,CAAC;AAEzD;;GAEG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC;IACjD,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,iCAAiC,CAAC;IAChE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC;CAC1D,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC;IACjD,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,qCAAqC,CAAC;IACpE,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;IAC7D,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;CAC3D,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"project-update.d.ts","sourceRoot":"","sources":["../../../src/tools/project/project-update.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAGnF,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAE5E;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mBA6CnB,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,UACvC,uBAAuB,GAC9B,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;CA+CtD,CAAC;AAEF;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,EAC/C,OAAO,EAAE;IAAE,MAAM,EAAE,uBAAuB,CAAA;CAAE,GAC3C,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC,CAEpD"}
1
+ {"version":3,"file":"project-update.d.ts","sourceRoot":"","sources":["../../../src/tools/project/project-update.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAGnF,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAE5E;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mBA6CnB,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,UACvC,uBAAuB,GAC9B,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;CA2FtD,CAAC;AAqBF;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,EAC/C,OAAO,EAAE;IAAE,MAAM,EAAE,uBAAuB,CAAA;CAAE,GAC3C,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC,CAEpD"}
@@ -53,37 +53,72 @@ for new time entries.`,
53
53
  async execute(input, client) {
54
54
  const handler = ErrorHandler.wrapHandler("project_update", async (input, _context) => {
55
55
  const { businessId, projectId, ...updates } = input;
56
- // Build update object using camelCase properties
57
- // The FreshBooks SDK's transformProjectRequest() will convert to API format
58
- const project = {};
59
- if (updates.title !== undefined)
60
- project.title = updates.title;
61
- if (updates.clientId !== undefined)
62
- project.clientId = updates.clientId;
63
- if (updates.description !== undefined)
64
- project.description = updates.description;
65
- if (updates.dueDate !== undefined)
66
- project.dueDate = updates.dueDate;
67
- if (updates.budget !== undefined)
68
- project.budget = updates.budget;
69
- if (updates.fixedPrice !== undefined)
70
- project.fixedPrice = updates.fixedPrice;
71
- if (updates.rate !== undefined)
72
- project.rate = updates.rate;
73
- if (updates.billingMethod !== undefined)
74
- project.billingMethod = updates.billingMethod;
75
- if (updates.projectType !== undefined)
76
- project.projectType = updates.projectType;
77
- if (updates.internal !== undefined)
78
- project.internal = updates.internal;
79
- if (updates.projectManagerId !== undefined)
80
- project.projectManagerId = updates.projectManagerId;
81
- if (updates.active !== undefined)
82
- project.active = updates.active;
83
- if (updates.complete !== undefined)
84
- project.complete = updates.complete;
56
+ // Require at least one field to change (otherwise the round-trip is wasted
57
+ // and the intent is ambiguous).
58
+ const changedFields = Object.keys(updates).filter((k) => updates[k] !== undefined);
59
+ if (changedFields.length === 0) {
60
+ throw ErrorHandler.createValidationError("No fields provided to update. Please specify at least one field to change.", { tool: "project_update", businessId, projectId });
61
+ }
85
62
  // Execute the API call
86
63
  const result = await client.executeWithRetry("project_update", async (fbClient) => {
64
+ // Read-modify-write: the Projects API 500s ("An internal error has
65
+ // occurred", #70) on a partial PUT — it requires the full editable
66
+ // representation. Fetch the current project, overlay the user's
67
+ // changes, and send the complete object. (Mirrors expense_update.)
68
+ const existingResponse = await fbClient.projects.single(businessId, projectId);
69
+ if (!existingResponse.ok) {
70
+ throw existingResponse.error;
71
+ }
72
+ // projects.single returns the SDK-parsed project directly (not wrapped).
73
+ const existing = (existingResponse.data.project ??
74
+ existingResponse.data);
75
+ // Seed the payload from the existing EDITABLE fields only. Read-only /
76
+ // computed fields (sample, loggedDuration, billedAmount, billedStatus,
77
+ // retainerId, expenseMarkup, group, services, timestamps) are
78
+ // intentionally omitted — echoing them back is what triggers the 500.
79
+ const project = {
80
+ title: existing.title,
81
+ description: existing.description,
82
+ // The SDK parses due_date into a JS Date; the API wants "YYYY-MM-DD".
83
+ dueDate: toApiDate(existing.dueDate),
84
+ clientId: existing.clientId,
85
+ internal: existing.internal,
86
+ budget: existing.budget,
87
+ fixedPrice: existing.fixedPrice,
88
+ rate: existing.rate,
89
+ billingMethod: existing.billingMethod,
90
+ projectType: existing.projectType,
91
+ projectManagerId: existing.projectManagerId,
92
+ active: existing.active,
93
+ complete: existing.complete,
94
+ };
95
+ // Overlay only the fields the user provided.
96
+ if (updates.title !== undefined)
97
+ project.title = updates.title;
98
+ if (updates.clientId !== undefined)
99
+ project.clientId = updates.clientId;
100
+ if (updates.description !== undefined)
101
+ project.description = updates.description;
102
+ if (updates.dueDate !== undefined)
103
+ project.dueDate = updates.dueDate;
104
+ if (updates.budget !== undefined)
105
+ project.budget = updates.budget;
106
+ if (updates.fixedPrice !== undefined)
107
+ project.fixedPrice = updates.fixedPrice;
108
+ if (updates.rate !== undefined)
109
+ project.rate = updates.rate;
110
+ if (updates.billingMethod !== undefined)
111
+ project.billingMethod = updates.billingMethod;
112
+ if (updates.projectType !== undefined)
113
+ project.projectType = updates.projectType;
114
+ if (updates.internal !== undefined)
115
+ project.internal = updates.internal;
116
+ if (updates.projectManagerId !== undefined)
117
+ project.projectManagerId = updates.projectManagerId;
118
+ if (updates.active !== undefined)
119
+ project.active = updates.active;
120
+ if (updates.complete !== undefined)
121
+ project.complete = updates.complete;
87
122
  const response = await fbClient.projects.update(project, businessId, projectId);
88
123
  if (!response.ok) {
89
124
  throw response.error;
@@ -97,6 +132,24 @@ for new time entries.`,
97
132
  return handler(input, { businessId: input.businessId });
98
133
  },
99
134
  };
135
+ /**
136
+ * Coerce a project due_date (which the SDK parses into a JS Date) back to the
137
+ * "YYYY-MM-DD" string the Projects API expects. Passes through strings/null and
138
+ * never throws on an invalid value (returns null rather than crash the update).
139
+ */
140
+ function toApiDate(value) {
141
+ if (value === null || value === undefined) {
142
+ return null;
143
+ }
144
+ if (value instanceof Date) {
145
+ return Number.isNaN(value.getTime()) ? null : value.toISOString().slice(0, 10);
146
+ }
147
+ if (typeof value === "string") {
148
+ // Already "YYYY-MM-DD" — keep as-is; otherwise take the date portion.
149
+ return value.slice(0, 10);
150
+ }
151
+ return null;
152
+ }
100
153
  /**
101
154
  * Wrapped handler for backward compatibility with tests
102
155
  */
@@ -1 +1 @@
1
- {"version":3,"file":"project-update.js","sourceRoot":"","sources":["../../../src/tools/project/project-update.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"project-update.js","sourceRoot":"","sources":["../../../src/tools/project/project-update.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodsamsoftware/freshbooks-mcp",
3
- "version": "1.0.17",
3
+ "version": "1.0.19",
4
4
  "description": "FreshBooks MCP server providing 1:1 parity with the FreshBooks Node.js SDK",
5
5
  "type": "module",
6
6
  "main": "dist/server.js",