@goodsamsoftware/freshbooks-mcp 1.0.1 → 1.0.2
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/dist/auth/confirmation-store.d.ts +94 -0
- package/dist/auth/confirmation-store.d.ts.map +1 -0
- package/dist/auth/confirmation-store.js +126 -0
- package/dist/auth/confirmation-store.js.map +1 -0
- package/dist/auth/state-store.d.ts +96 -0
- package/dist/auth/state-store.d.ts.map +1 -0
- package/dist/auth/state-store.js +122 -0
- package/dist/auth/state-store.js.map +1 -0
- package/dist/auth/types.d.ts +1 -1
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/auth/types.js.map +1 -1
- package/dist/config/environment.d.ts +25 -0
- package/dist/config/environment.d.ts.map +1 -0
- package/dist/config/environment.js +39 -0
- package/dist/config/environment.js.map +1 -0
- package/dist/errors/error-handler.d.ts.map +1 -1
- package/dist/errors/error-handler.js +18 -5
- package/dist/errors/error-handler.js.map +1 -1
- package/dist/errors/response-formatter.d.ts +3 -2
- package/dist/errors/response-formatter.d.ts.map +1 -1
- package/dist/errors/response-formatter.js +19 -2
- package/dist/errors/response-formatter.js.map +1 -1
- package/dist/server.js +85 -11
- package/dist/server.js.map +1 -1
- package/dist/tools/base-tool.d.ts +2 -2
- package/dist/tools/bill/bill-create.d.ts +4 -4
- package/dist/tools/bill/bill-delete.d.ts +6 -0
- package/dist/tools/bill/bill-delete.d.ts.map +1 -1
- package/dist/tools/bill/bill-list.d.ts +12 -12
- package/dist/tools/bill/bill-single.d.ts +4 -4
- package/dist/tools/bill/schemas.d.ts +28 -22
- package/dist/tools/bill/schemas.d.ts.map +1 -1
- package/dist/tools/bill/schemas.js +2 -0
- package/dist/tools/bill/schemas.js.map +1 -1
- package/dist/tools/bill-payment/billpayment-create.d.ts +4 -4
- package/dist/tools/bill-payment/billpayment-delete.d.ts +6 -0
- package/dist/tools/bill-payment/billpayment-delete.d.ts.map +1 -1
- package/dist/tools/bill-payment/billpayment-list.d.ts +12 -12
- package/dist/tools/bill-payment/billpayment-single.d.ts +4 -4
- package/dist/tools/bill-payment/billpayment-update.d.ts +4 -4
- package/dist/tools/bill-payment/schemas.d.ts +28 -22
- package/dist/tools/bill-payment/schemas.d.ts.map +1 -1
- package/dist/tools/bill-payment/schemas.js +2 -0
- package/dist/tools/bill-payment/schemas.js.map +1 -1
- package/dist/tools/bill-vendor/billvendor-create.d.ts +6 -6
- package/dist/tools/bill-vendor/billvendor-delete.d.ts +6 -0
- package/dist/tools/bill-vendor/billvendor-delete.d.ts.map +1 -1
- package/dist/tools/bill-vendor/billvendor-list.d.ts +14 -14
- package/dist/tools/bill-vendor/billvendor-single.d.ts +4 -4
- package/dist/tools/bill-vendor/billvendor-update.d.ts +6 -6
- package/dist/tools/bill-vendor/schemas.d.ts +34 -28
- package/dist/tools/bill-vendor/schemas.d.ts.map +1 -1
- package/dist/tools/bill-vendor/schemas.js +2 -0
- package/dist/tools/bill-vendor/schemas.js.map +1 -1
- package/dist/tools/callback/callback-create.d.ts +6 -6
- package/dist/tools/callback/callback-delete.d.ts +6 -0
- package/dist/tools/callback/callback-delete.d.ts.map +1 -1
- package/dist/tools/callback/callback-list.d.ts +12 -12
- package/dist/tools/callback/callback-resend-verification.d.ts +4 -4
- package/dist/tools/callback/callback-single.d.ts +4 -4
- package/dist/tools/callback/callback-update.d.ts +6 -6
- package/dist/tools/callback/schemas.d.ts +32 -26
- package/dist/tools/callback/schemas.d.ts.map +1 -1
- package/dist/tools/callback/schemas.js +2 -0
- package/dist/tools/callback/schemas.js.map +1 -1
- package/dist/tools/client/client-create.d.ts +2 -2
- package/dist/tools/client/client-delete.d.ts +8 -2
- package/dist/tools/client/client-delete.d.ts.map +1 -1
- package/dist/tools/client/client-list.d.ts +9 -9
- package/dist/tools/client/client-update.d.ts +2 -2
- package/dist/tools/client/schemas.d.ts +26 -20
- package/dist/tools/client/schemas.d.ts.map +1 -1
- package/dist/tools/client/schemas.js +2 -0
- package/dist/tools/client/schemas.js.map +1 -1
- package/dist/tools/credit-note/creditnote-create.d.ts +10 -10
- package/dist/tools/credit-note/creditnote-delete.d.ts +6 -0
- package/dist/tools/credit-note/creditnote-delete.d.ts.map +1 -1
- package/dist/tools/credit-note/creditnote-list.d.ts +14 -14
- package/dist/tools/credit-note/creditnote-single.d.ts +6 -6
- package/dist/tools/credit-note/creditnote-update.d.ts +10 -10
- package/dist/tools/credit-note/schemas.d.ts +42 -36
- package/dist/tools/credit-note/schemas.d.ts.map +1 -1
- package/dist/tools/credit-note/schemas.js +2 -0
- package/dist/tools/credit-note/schemas.js.map +1 -1
- package/dist/tools/expense/expense-create.d.ts +2 -2
- package/dist/tools/expense/expense-delete.d.ts +6 -0
- package/dist/tools/expense/expense-delete.d.ts.map +1 -1
- package/dist/tools/expense/expense-list.d.ts +8 -8
- package/dist/tools/expense/expense-single.d.ts +2 -2
- package/dist/tools/expense/expense-update.d.ts +2 -2
- package/dist/tools/expense/expense-update.d.ts.map +1 -1
- package/dist/tools/expense/expense-update.js +88 -63
- package/dist/tools/expense/expense-update.js.map +1 -1
- package/dist/tools/expense/schemas.d.ts +18 -12
- package/dist/tools/expense/schemas.d.ts.map +1 -1
- package/dist/tools/expense/schemas.js +2 -0
- package/dist/tools/expense/schemas.js.map +1 -1
- package/dist/tools/expense-category/expensecategory-list.d.ts +4 -4
- package/dist/tools/expense-category/schemas.d.ts +4 -4
- package/dist/tools/invoice/invoice-create.d.ts +10 -10
- package/dist/tools/invoice/invoice-delete.d.ts +6 -0
- package/dist/tools/invoice/invoice-delete.d.ts.map +1 -1
- package/dist/tools/invoice/invoice-list.d.ts +24 -24
- package/dist/tools/invoice/invoice-single.d.ts +10 -10
- package/dist/tools/invoice/invoice-update.d.ts +12 -12
- package/dist/tools/invoice/schemas.d.ts +56 -50
- package/dist/tools/invoice/schemas.d.ts.map +1 -1
- package/dist/tools/invoice/schemas.js +2 -0
- package/dist/tools/invoice/schemas.js.map +1 -1
- package/dist/tools/item/item-create.d.ts +8 -8
- package/dist/tools/item/item-list.d.ts +18 -18
- package/dist/tools/item/item-single.d.ts +6 -6
- package/dist/tools/item/item-update.d.ts +10 -10
- package/dist/tools/item/schemas.d.ts +38 -38
- package/dist/tools/journal-entry/journalentry-create.d.ts +4 -4
- package/dist/tools/journal-entry/schemas.d.ts +8 -8
- package/dist/tools/journal-entry-account/journalentryaccount-list.d.ts +14 -14
- package/dist/tools/journal-entry-account/schemas.d.ts +24 -24
- package/dist/tools/metadata.d.ts +13 -1
- package/dist/tools/metadata.d.ts.map +1 -1
- package/dist/tools/metadata.js +68 -1
- package/dist/tools/metadata.js.map +1 -1
- package/dist/tools/other-income/otherincome-create.d.ts +10 -10
- package/dist/tools/other-income/otherincome-delete.d.ts +6 -0
- package/dist/tools/other-income/otherincome-delete.d.ts.map +1 -1
- package/dist/tools/other-income/otherincome-list.d.ts +14 -14
- package/dist/tools/other-income/otherincome-single.d.ts +6 -6
- package/dist/tools/other-income/otherincome-update.d.ts +10 -10
- package/dist/tools/other-income/schemas.d.ts +40 -34
- package/dist/tools/other-income/schemas.d.ts.map +1 -1
- package/dist/tools/other-income/schemas.js +2 -0
- package/dist/tools/other-income/schemas.js.map +1 -1
- package/dist/tools/payment/payment-create.d.ts +2 -2
- package/dist/tools/payment/payment-delete.d.ts +6 -0
- package/dist/tools/payment/payment-delete.d.ts.map +1 -1
- package/dist/tools/payment/payment-list.d.ts +8 -8
- package/dist/tools/payment/payment-single.d.ts +2 -2
- package/dist/tools/payment/payment-update.d.ts +2 -2
- package/dist/tools/payment/schemas.d.ts +18 -12
- package/dist/tools/payment/schemas.d.ts.map +1 -1
- package/dist/tools/payment/schemas.js +3 -1
- package/dist/tools/payment/schemas.js.map +1 -1
- package/dist/tools/project/project-create.d.ts +8 -8
- package/dist/tools/project/project-delete.d.ts +8 -2
- package/dist/tools/project/project-delete.d.ts.map +1 -1
- package/dist/tools/project/project-list.d.ts +21 -21
- package/dist/tools/project/project-single.d.ts +6 -6
- package/dist/tools/project/project-update.d.ts +10 -10
- package/dist/tools/project/schemas.d.ts +52 -46
- package/dist/tools/project/schemas.d.ts.map +1 -1
- package/dist/tools/project/schemas.js +2 -0
- package/dist/tools/project/schemas.js.map +1 -1
- package/dist/tools/service/schemas.d.ts +11 -11
- package/dist/tools/service/service-create.d.ts +2 -2
- package/dist/tools/service/service-list.d.ts +8 -8
- package/dist/tools/task/schemas.d.ts +34 -28
- package/dist/tools/task/schemas.d.ts.map +1 -1
- package/dist/tools/task/schemas.js +2 -0
- package/dist/tools/task/schemas.js.map +1 -1
- package/dist/tools/task/task-create.d.ts +6 -6
- package/dist/tools/task/task-delete.d.ts +6 -0
- package/dist/tools/task/task-delete.d.ts.map +1 -1
- package/dist/tools/task/task-list.d.ts +18 -18
- package/dist/tools/task/task-single.d.ts +4 -4
- package/dist/tools/task/task-update.d.ts +8 -8
- package/dist/tools/time-entry/schemas.d.ts +42 -36
- package/dist/tools/time-entry/schemas.d.ts.map +1 -1
- package/dist/tools/time-entry/schemas.js +2 -0
- package/dist/tools/time-entry/schemas.js.map +1 -1
- package/dist/tools/time-entry/timeentry-create.d.ts +6 -6
- package/dist/tools/time-entry/timeentry-delete.d.ts +8 -2
- package/dist/tools/time-entry/timeentry-delete.d.ts.map +1 -1
- package/dist/tools/time-entry/timeentry-list.d.ts +17 -17
- package/dist/tools/time-entry/timeentry-single.d.ts +4 -4
- package/dist/tools/time-entry/timeentry-update.d.ts +6 -6
- package/dist/tools/timer/schemas.d.ts +30 -24
- package/dist/tools/timer/schemas.d.ts.map +1 -1
- package/dist/tools/timer/schemas.js +2 -0
- package/dist/tools/timer/schemas.js.map +1 -1
- package/dist/tools/timer/timer-current.d.ts +8 -8
- package/dist/tools/timer/timer-discard.d.ts +8 -2
- package/dist/tools/timer/timer-discard.d.ts.map +1 -1
- package/dist/tools/timer/timer-start.d.ts +6 -6
- package/dist/tools/timer/timer-stop.d.ts +4 -4
- package/dist/tools/types.d.ts +16 -0
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/types.js.map +1 -1
- package/dist/tools/user/schemas.d.ts +14 -14
- package/dist/tools/user/user-me.d.ts +6 -6
- package/dist/utils/logger.d.ts +9 -0
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +114 -20
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/sanitizer.d.ts +49 -0
- package/dist/utils/sanitizer.d.ts.map +1 -0
- package/dist/utils/sanitizer.js +163 -0
- package/dist/utils/sanitizer.js.map +1 -0
- package/package.json +2 -2
|
@@ -14,14 +14,14 @@ export declare const BusinessMembershipSchema: z.ZodObject<{
|
|
|
14
14
|
role: z.ZodString;
|
|
15
15
|
}, "strip", z.ZodTypeAny, {
|
|
16
16
|
accountId: string;
|
|
17
|
+
id: number;
|
|
17
18
|
name: string;
|
|
18
19
|
role: string;
|
|
19
|
-
id: number;
|
|
20
20
|
}, {
|
|
21
21
|
accountId: string;
|
|
22
|
+
id: number;
|
|
22
23
|
name: string;
|
|
23
24
|
role: string;
|
|
24
|
-
id: number;
|
|
25
25
|
}>;
|
|
26
26
|
/**
|
|
27
27
|
* Full User schema with all properties
|
|
@@ -38,14 +38,14 @@ export declare const UserSchema: z.ZodObject<{
|
|
|
38
38
|
role: z.ZodString;
|
|
39
39
|
}, "strip", z.ZodTypeAny, {
|
|
40
40
|
accountId: string;
|
|
41
|
+
id: number;
|
|
41
42
|
name: string;
|
|
42
43
|
role: string;
|
|
43
|
-
id: number;
|
|
44
44
|
}, {
|
|
45
45
|
accountId: string;
|
|
46
|
+
id: number;
|
|
46
47
|
name: string;
|
|
47
48
|
role: string;
|
|
48
|
-
id: number;
|
|
49
49
|
}>, "many">;
|
|
50
50
|
phoneNumbers: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
51
51
|
title: z.ZodOptional<z.ZodString>;
|
|
@@ -85,15 +85,15 @@ export declare const UserSchema: z.ZodObject<{
|
|
|
85
85
|
me: string;
|
|
86
86
|
}>>;
|
|
87
87
|
}, "strip", z.ZodTypeAny, {
|
|
88
|
-
email: string;
|
|
89
88
|
id: number;
|
|
89
|
+
email: string;
|
|
90
90
|
firstName: string;
|
|
91
91
|
lastName: string;
|
|
92
92
|
businessMemberships: {
|
|
93
93
|
accountId: string;
|
|
94
|
+
id: number;
|
|
94
95
|
name: string;
|
|
95
96
|
role: string;
|
|
96
|
-
id: number;
|
|
97
97
|
}[];
|
|
98
98
|
phoneNumbers?: {
|
|
99
99
|
number: string;
|
|
@@ -111,15 +111,15 @@ export declare const UserSchema: z.ZodObject<{
|
|
|
111
111
|
me: string;
|
|
112
112
|
} | undefined;
|
|
113
113
|
}, {
|
|
114
|
-
email: string;
|
|
115
114
|
id: number;
|
|
115
|
+
email: string;
|
|
116
116
|
firstName: string;
|
|
117
117
|
lastName: string;
|
|
118
118
|
businessMemberships: {
|
|
119
119
|
accountId: string;
|
|
120
|
+
id: number;
|
|
120
121
|
name: string;
|
|
121
122
|
role: string;
|
|
122
|
-
id: number;
|
|
123
123
|
}[];
|
|
124
124
|
phoneNumbers?: {
|
|
125
125
|
number: string;
|
|
@@ -156,14 +156,14 @@ export declare const UserMeOutputSchema: z.ZodObject<{
|
|
|
156
156
|
role: z.ZodString;
|
|
157
157
|
}, "strip", z.ZodTypeAny, {
|
|
158
158
|
accountId: string;
|
|
159
|
+
id: number;
|
|
159
160
|
name: string;
|
|
160
161
|
role: string;
|
|
161
|
-
id: number;
|
|
162
162
|
}, {
|
|
163
163
|
accountId: string;
|
|
164
|
+
id: number;
|
|
164
165
|
name: string;
|
|
165
166
|
role: string;
|
|
166
|
-
id: number;
|
|
167
167
|
}>, "many">;
|
|
168
168
|
phoneNumbers: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
169
169
|
title: z.ZodOptional<z.ZodString>;
|
|
@@ -203,15 +203,15 @@ export declare const UserMeOutputSchema: z.ZodObject<{
|
|
|
203
203
|
me: string;
|
|
204
204
|
}>>;
|
|
205
205
|
}, "strip", z.ZodTypeAny, {
|
|
206
|
-
email: string;
|
|
207
206
|
id: number;
|
|
207
|
+
email: string;
|
|
208
208
|
firstName: string;
|
|
209
209
|
lastName: string;
|
|
210
210
|
businessMemberships: {
|
|
211
211
|
accountId: string;
|
|
212
|
+
id: number;
|
|
212
213
|
name: string;
|
|
213
214
|
role: string;
|
|
214
|
-
id: number;
|
|
215
215
|
}[];
|
|
216
216
|
phoneNumbers?: {
|
|
217
217
|
number: string;
|
|
@@ -229,15 +229,15 @@ export declare const UserMeOutputSchema: z.ZodObject<{
|
|
|
229
229
|
me: string;
|
|
230
230
|
} | undefined;
|
|
231
231
|
}, {
|
|
232
|
-
email: string;
|
|
233
232
|
id: number;
|
|
233
|
+
email: string;
|
|
234
234
|
firstName: string;
|
|
235
235
|
lastName: string;
|
|
236
236
|
businessMemberships: {
|
|
237
237
|
accountId: string;
|
|
238
|
+
id: number;
|
|
238
239
|
name: string;
|
|
239
240
|
role: string;
|
|
240
|
-
id: number;
|
|
241
241
|
}[];
|
|
242
242
|
phoneNumbers?: {
|
|
243
243
|
number: string;
|
|
@@ -25,14 +25,14 @@ export declare const userMeTool: {
|
|
|
25
25
|
role: z.ZodString;
|
|
26
26
|
}, "strip", z.ZodTypeAny, {
|
|
27
27
|
accountId: string;
|
|
28
|
+
id: number;
|
|
28
29
|
name: string;
|
|
29
30
|
role: string;
|
|
30
|
-
id: number;
|
|
31
31
|
}, {
|
|
32
32
|
accountId: string;
|
|
33
|
+
id: number;
|
|
33
34
|
name: string;
|
|
34
35
|
role: string;
|
|
35
|
-
id: number;
|
|
36
36
|
}>, "many">;
|
|
37
37
|
phoneNumbers: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
38
38
|
title: z.ZodOptional<z.ZodString>;
|
|
@@ -72,15 +72,15 @@ export declare const userMeTool: {
|
|
|
72
72
|
me: string;
|
|
73
73
|
}>>;
|
|
74
74
|
}, "strip", z.ZodTypeAny, {
|
|
75
|
-
email: string;
|
|
76
75
|
id: number;
|
|
76
|
+
email: string;
|
|
77
77
|
firstName: string;
|
|
78
78
|
lastName: string;
|
|
79
79
|
businessMemberships: {
|
|
80
80
|
accountId: string;
|
|
81
|
+
id: number;
|
|
81
82
|
name: string;
|
|
82
83
|
role: string;
|
|
83
|
-
id: number;
|
|
84
84
|
}[];
|
|
85
85
|
phoneNumbers?: {
|
|
86
86
|
number: string;
|
|
@@ -98,15 +98,15 @@ export declare const userMeTool: {
|
|
|
98
98
|
me: string;
|
|
99
99
|
} | undefined;
|
|
100
100
|
}, {
|
|
101
|
-
email: string;
|
|
102
101
|
id: number;
|
|
102
|
+
email: string;
|
|
103
103
|
firstName: string;
|
|
104
104
|
lastName: string;
|
|
105
105
|
businessMemberships: {
|
|
106
106
|
accountId: string;
|
|
107
|
+
id: number;
|
|
107
108
|
name: string;
|
|
108
109
|
role: string;
|
|
109
|
-
id: number;
|
|
110
110
|
}[];
|
|
111
111
|
phoneNumbers?: {
|
|
112
112
|
number: string;
|
package/dist/utils/logger.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type { LogLevel } from '../types/index.js';
|
|
|
7
7
|
declare class Logger {
|
|
8
8
|
private currentLevel;
|
|
9
9
|
private requestId;
|
|
10
|
+
private static readonly MAX_DEPTH;
|
|
10
11
|
constructor(level?: LogLevel);
|
|
11
12
|
/**
|
|
12
13
|
* Set the current log level
|
|
@@ -24,6 +25,14 @@ declare class Logger {
|
|
|
24
25
|
* Check if a log level should be output
|
|
25
26
|
*/
|
|
26
27
|
private shouldLog;
|
|
28
|
+
/**
|
|
29
|
+
* Check if a key name indicates sensitive data
|
|
30
|
+
*/
|
|
31
|
+
private isSensitiveKey;
|
|
32
|
+
/**
|
|
33
|
+
* Heuristically detect if a string value looks like a secret
|
|
34
|
+
*/
|
|
35
|
+
private looksLikeSecret;
|
|
27
36
|
/**
|
|
28
37
|
* Sanitize data to prevent logging sensitive information
|
|
29
38
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAgFlD,cAAM,MAAM;IACV,OAAO,CAAC,YAAY,CAAW;IAC/B,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAM;gBAE3B,KAAK,GAAE,QAAiB;IAIpC;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAI/B;;OAEG;IACH,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAI9B;;OAEG;IACH,cAAc,IAAI,IAAI;IAItB;;OAEG;IACH,OAAO,CAAC,SAAS;IAIjB;;OAEG;IACH,OAAO,CAAC,cAAc;IAatB;;OAEG;IACH,OAAO,CAAC,eAAe;IAwBvB;;OAEG;IACH,OAAO,CAAC,QAAQ;IA8BhB;;OAEG;IACH,OAAO,CAAC,KAAK;IAiBb;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI/D;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI9D;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI9D;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAgBzF;AAGD,eAAO,MAAM,MAAM,QAAe,CAAC"}
|
package/dist/utils/logger.js
CHANGED
|
@@ -3,15 +3,80 @@
|
|
|
3
3
|
*
|
|
4
4
|
* IMPORTANT: All logs go to stderr (stdout is reserved for MCP protocol)
|
|
5
5
|
*/
|
|
6
|
+
import { isProduction } from '../config/environment.js';
|
|
6
7
|
const LOG_LEVELS = {
|
|
7
8
|
debug: 0,
|
|
8
9
|
info: 1,
|
|
9
10
|
warn: 2,
|
|
10
11
|
error: 3,
|
|
11
12
|
};
|
|
13
|
+
/**
|
|
14
|
+
* Regex patterns for detecting sensitive keys
|
|
15
|
+
* These patterns catch various naming conventions (camelCase, snake_case, etc.)
|
|
16
|
+
*/
|
|
17
|
+
const SENSITIVE_KEY_PATTERNS = [
|
|
18
|
+
// Tokens and authentication
|
|
19
|
+
/token/i,
|
|
20
|
+
/bearer/i,
|
|
21
|
+
/jwt/i,
|
|
22
|
+
/oauth/i,
|
|
23
|
+
/session/i,
|
|
24
|
+
/auth/i,
|
|
25
|
+
// Secrets and passwords
|
|
26
|
+
/secret/i,
|
|
27
|
+
/password/i,
|
|
28
|
+
/passwd/i,
|
|
29
|
+
/pwd/i,
|
|
30
|
+
/credential/i,
|
|
31
|
+
// API keys
|
|
32
|
+
/api[-_]?key/i,
|
|
33
|
+
/apikey/i,
|
|
34
|
+
/key/i,
|
|
35
|
+
// Cryptographic
|
|
36
|
+
/private[-_]?key/i,
|
|
37
|
+
/signing/i,
|
|
38
|
+
/cipher/i,
|
|
39
|
+
/encrypt/i,
|
|
40
|
+
/salt/i,
|
|
41
|
+
/hash/i,
|
|
42
|
+
/\biv\b/i, // initialization vector
|
|
43
|
+
// Personal identifiable information
|
|
44
|
+
/ssn/i,
|
|
45
|
+
/social[-_]?security/i,
|
|
46
|
+
/credit[-_]?card/i,
|
|
47
|
+
/card[-_]?number/i,
|
|
48
|
+
/cvv/i,
|
|
49
|
+
/\bpin\b/i,
|
|
50
|
+
// Headers
|
|
51
|
+
/x-api/i,
|
|
52
|
+
/x-auth/i,
|
|
53
|
+
/x-secret/i,
|
|
54
|
+
];
|
|
55
|
+
/**
|
|
56
|
+
* Exact key matches (case-insensitive, normalized)
|
|
57
|
+
* These are checked after removing hyphens and underscores
|
|
58
|
+
*/
|
|
59
|
+
const SENSITIVE_EXACT_KEYS = new Set([
|
|
60
|
+
'password',
|
|
61
|
+
'token',
|
|
62
|
+
'secret',
|
|
63
|
+
'key',
|
|
64
|
+
'accesstoken',
|
|
65
|
+
'refreshtoken',
|
|
66
|
+
'apikey',
|
|
67
|
+
'clientsecret',
|
|
68
|
+
'privatekey',
|
|
69
|
+
'authorization',
|
|
70
|
+
'bearer',
|
|
71
|
+
'jwt',
|
|
72
|
+
'sessionid',
|
|
73
|
+
'cookie',
|
|
74
|
+
'credentials',
|
|
75
|
+
]);
|
|
12
76
|
class Logger {
|
|
13
77
|
currentLevel;
|
|
14
78
|
requestId = null;
|
|
79
|
+
static MAX_DEPTH = 10;
|
|
15
80
|
constructor(level = 'info') {
|
|
16
81
|
this.currentLevel = level;
|
|
17
82
|
}
|
|
@@ -39,38 +104,66 @@ class Logger {
|
|
|
39
104
|
shouldLog(level) {
|
|
40
105
|
return LOG_LEVELS[level] >= LOG_LEVELS[this.currentLevel];
|
|
41
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Check if a key name indicates sensitive data
|
|
109
|
+
*/
|
|
110
|
+
isSensitiveKey(key) {
|
|
111
|
+
// Normalize key: lowercase and remove separators
|
|
112
|
+
const normalizedKey = key.toLowerCase().replace(/[-_]/g, '');
|
|
113
|
+
// Check exact matches
|
|
114
|
+
if (SENSITIVE_EXACT_KEYS.has(normalizedKey)) {
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
// Check patterns
|
|
118
|
+
return SENSITIVE_KEY_PATTERNS.some((pattern) => pattern.test(key));
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Heuristically detect if a string value looks like a secret
|
|
122
|
+
*/
|
|
123
|
+
looksLikeSecret(value) {
|
|
124
|
+
// Skip short values
|
|
125
|
+
if (value.length < 20) {
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
// JWT pattern: eyJ...
|
|
129
|
+
if (/^eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(value)) {
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
// Long hex strings (32+ chars) - likely keys/tokens
|
|
133
|
+
if (/^[a-f0-9]{32,}$/i.test(value)) {
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
// Base64-ish strings that are long (50+ chars) - likely tokens
|
|
137
|
+
if (/^[A-Za-z0-9+/=_-]{50,}$/.test(value)) {
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
42
142
|
/**
|
|
43
143
|
* Sanitize data to prevent logging sensitive information
|
|
44
144
|
*/
|
|
45
|
-
sanitize(data) {
|
|
145
|
+
sanitize(data, depth = 0) {
|
|
146
|
+
// Prevent infinite recursion
|
|
147
|
+
if (depth > Logger.MAX_DEPTH) {
|
|
148
|
+
return '[DEPTH_LIMIT]';
|
|
149
|
+
}
|
|
46
150
|
if (typeof data !== 'object' || data === null) {
|
|
47
151
|
return data;
|
|
48
152
|
}
|
|
49
153
|
if (Array.isArray(data)) {
|
|
50
|
-
return data.map((item) => this.sanitize(item));
|
|
154
|
+
return data.map((item) => this.sanitize(item, depth + 1));
|
|
51
155
|
}
|
|
52
156
|
const sanitized = {};
|
|
53
|
-
const sensitiveKeys = [
|
|
54
|
-
'token',
|
|
55
|
-
'accessToken',
|
|
56
|
-
'refreshToken',
|
|
57
|
-
'access_token',
|
|
58
|
-
'refresh_token',
|
|
59
|
-
'secret',
|
|
60
|
-
'password',
|
|
61
|
-
'clientSecret',
|
|
62
|
-
'client_secret',
|
|
63
|
-
'authorization',
|
|
64
|
-
'apiKey',
|
|
65
|
-
'api_key',
|
|
66
|
-
];
|
|
67
157
|
for (const [key, value] of Object.entries(data)) {
|
|
68
|
-
|
|
69
|
-
if (sensitiveKeys.some((sensitive) => lowerKey.includes(sensitive))) {
|
|
158
|
+
if (this.isSensitiveKey(key)) {
|
|
70
159
|
sanitized[key] = '[REDACTED]';
|
|
71
160
|
}
|
|
161
|
+
else if (typeof value === 'string' && this.looksLikeSecret(value)) {
|
|
162
|
+
// Detect secret-like values even if key doesn't match
|
|
163
|
+
sanitized[key] = '[REDACTED_VALUE]';
|
|
164
|
+
}
|
|
72
165
|
else {
|
|
73
|
-
sanitized[key] = this.sanitize(value);
|
|
166
|
+
sanitized[key] = this.sanitize(value, depth + 1);
|
|
74
167
|
}
|
|
75
168
|
}
|
|
76
169
|
return sanitized;
|
|
@@ -119,7 +212,8 @@ class Logger {
|
|
|
119
212
|
errorContext.error = {
|
|
120
213
|
name: error.name,
|
|
121
214
|
message: error.message,
|
|
122
|
-
stack
|
|
215
|
+
// Only include stack traces in non-production environments
|
|
216
|
+
...(isProduction() ? {} : { stack: error.stack }),
|
|
123
217
|
};
|
|
124
218
|
}
|
|
125
219
|
else if (error) {
|
package/dist/utils/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output sanitization utilities for MCP responses
|
|
3
|
+
*
|
|
4
|
+
* Prevents prompt injection attacks by sanitizing user-controlled data
|
|
5
|
+
* before returning it to Claude in MCP tool responses.
|
|
6
|
+
*/
|
|
7
|
+
export interface SanitizeOptions {
|
|
8
|
+
/** Maximum string length before truncation (default: 10000) */
|
|
9
|
+
maxStringLength?: number;
|
|
10
|
+
/** Strip control characters (default: true) */
|
|
11
|
+
stripControlChars?: boolean;
|
|
12
|
+
/** Maximum recursion depth (default: 50) */
|
|
13
|
+
maxDepth?: number;
|
|
14
|
+
/** Flag suspicious content in metadata (default: true) */
|
|
15
|
+
flagSuspiciousContent?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface SanitizeResult {
|
|
18
|
+
data: unknown;
|
|
19
|
+
warnings: string[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Check if a string contains suspicious content that might be prompt injection
|
|
23
|
+
*/
|
|
24
|
+
export declare function containsSuspiciousContent(str: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Sanitize data for MCP response with warnings
|
|
27
|
+
*
|
|
28
|
+
* Returns both the sanitized data and any warnings about suspicious content.
|
|
29
|
+
* Warnings are for logging purposes - the data is still returned.
|
|
30
|
+
*/
|
|
31
|
+
export declare function sanitizeWithWarnings(data: unknown, options?: SanitizeOptions): SanitizeResult;
|
|
32
|
+
/**
|
|
33
|
+
* Sanitize data for MCP response
|
|
34
|
+
*
|
|
35
|
+
* This is the main function to use when preparing tool responses.
|
|
36
|
+
* It sanitizes user-controlled data to prevent prompt injection.
|
|
37
|
+
*
|
|
38
|
+
* @param data - The data to sanitize (typically from FreshBooks API)
|
|
39
|
+
* @param options - Optional sanitization options
|
|
40
|
+
* @returns Sanitized data safe for MCP response
|
|
41
|
+
*/
|
|
42
|
+
export declare function sanitizeForMcpResponse(data: unknown, options?: SanitizeOptions): unknown;
|
|
43
|
+
/**
|
|
44
|
+
* Create a sanitized JSON string for MCP response content
|
|
45
|
+
*
|
|
46
|
+
* Convenience function that sanitizes and stringifies in one call.
|
|
47
|
+
*/
|
|
48
|
+
export declare function toSanitizedJson(data: unknown, options?: SanitizeOptions): string;
|
|
49
|
+
//# sourceMappingURL=sanitizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitizer.d.ts","sourceRoot":"","sources":["../../src/utils/sanitizer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,eAAe;IAC9B,+DAA+D;IAC/D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,+CAA+C;IAC/C,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAsDD;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAM9D;AA0FD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,OAAO,EACb,OAAO,CAAC,EAAE,eAAe,GACxB,cAAc,CAahB;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAExF;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,MAAM,CAGhF"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output sanitization utilities for MCP responses
|
|
3
|
+
*
|
|
4
|
+
* Prevents prompt injection attacks by sanitizing user-controlled data
|
|
5
|
+
* before returning it to Claude in MCP tool responses.
|
|
6
|
+
*/
|
|
7
|
+
const DEFAULT_OPTIONS = {
|
|
8
|
+
maxStringLength: 10000,
|
|
9
|
+
stripControlChars: true,
|
|
10
|
+
maxDepth: 50,
|
|
11
|
+
flagSuspiciousContent: true,
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Patterns that may indicate prompt injection attempts
|
|
15
|
+
* These are flagged but not blocked to avoid false positives
|
|
16
|
+
*/
|
|
17
|
+
const SUSPICIOUS_PATTERNS = [
|
|
18
|
+
// Direct instruction overrides
|
|
19
|
+
/ignore\s+(all\s+)?previous\s+instructions?/i,
|
|
20
|
+
/ignore\s+(all\s+)?prior\s+instructions?/i,
|
|
21
|
+
/disregard\s+(all\s+)?previous/i,
|
|
22
|
+
/forget\s+(all\s+)?previous/i,
|
|
23
|
+
// Role manipulation
|
|
24
|
+
/you\s+are\s+now\s+a/i,
|
|
25
|
+
/pretend\s+you\s+are/i,
|
|
26
|
+
/act\s+as\s+(if\s+you\s+are\s+)?a/i,
|
|
27
|
+
/from\s+now\s+on,?\s+you/i,
|
|
28
|
+
// System prompt references
|
|
29
|
+
/system\s*prompt/i,
|
|
30
|
+
/\[system\]/i,
|
|
31
|
+
/\[INST\]/i,
|
|
32
|
+
/<\|system\|>/i,
|
|
33
|
+
// Jailbreak attempts
|
|
34
|
+
/do\s+anything\s+now/i,
|
|
35
|
+
/DAN\s+mode/i,
|
|
36
|
+
/developer\s+mode/i,
|
|
37
|
+
/jailbreak/i,
|
|
38
|
+
// Instruction injection markers
|
|
39
|
+
/\n\n---\n\nNew instructions:/i,
|
|
40
|
+
/END\s+OF\s+DOCUMENT/i,
|
|
41
|
+
/IMPORTANT:\s*As\s+an?\s+AI/i,
|
|
42
|
+
// Tool manipulation
|
|
43
|
+
/call\s+(the\s+)?tool/i,
|
|
44
|
+
/execute\s+(the\s+)?function/i,
|
|
45
|
+
/invoke\s+.*_delete/i,
|
|
46
|
+
];
|
|
47
|
+
/**
|
|
48
|
+
* Control characters to strip (excluding common whitespace)
|
|
49
|
+
*/
|
|
50
|
+
const CONTROL_CHAR_REGEX = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g;
|
|
51
|
+
/**
|
|
52
|
+
* Check if a string contains suspicious content that might be prompt injection
|
|
53
|
+
*/
|
|
54
|
+
export function containsSuspiciousContent(str) {
|
|
55
|
+
if (typeof str !== 'string') {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
return SUSPICIOUS_PATTERNS.some((pattern) => pattern.test(str));
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Sanitize a string value
|
|
62
|
+
*/
|
|
63
|
+
function sanitizeString(str, options) {
|
|
64
|
+
let result = str;
|
|
65
|
+
// Strip control characters
|
|
66
|
+
if (options.stripControlChars) {
|
|
67
|
+
result = result.replace(CONTROL_CHAR_REGEX, '');
|
|
68
|
+
}
|
|
69
|
+
// Truncate if too long
|
|
70
|
+
if (result.length > options.maxStringLength) {
|
|
71
|
+
result = result.substring(0, options.maxStringLength) + '... [TRUNCATED]';
|
|
72
|
+
}
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Recursively sanitize data for MCP response
|
|
77
|
+
*/
|
|
78
|
+
function sanitizeValue(data, options, warnings, path, depth) {
|
|
79
|
+
// Check depth limit
|
|
80
|
+
if (depth > options.maxDepth) {
|
|
81
|
+
warnings.push(`Max depth exceeded at path: ${path}`);
|
|
82
|
+
return '[MAX_DEPTH_EXCEEDED]';
|
|
83
|
+
}
|
|
84
|
+
// Handle null/undefined
|
|
85
|
+
if (data === null || data === undefined) {
|
|
86
|
+
return data;
|
|
87
|
+
}
|
|
88
|
+
// Handle primitives
|
|
89
|
+
if (typeof data === 'string') {
|
|
90
|
+
const sanitized = sanitizeString(data, options);
|
|
91
|
+
// Check for suspicious content
|
|
92
|
+
if (options.flagSuspiciousContent && containsSuspiciousContent(data)) {
|
|
93
|
+
warnings.push(`Suspicious content detected at path: ${path}`);
|
|
94
|
+
}
|
|
95
|
+
return sanitized;
|
|
96
|
+
}
|
|
97
|
+
if (typeof data === 'number' || typeof data === 'boolean') {
|
|
98
|
+
return data;
|
|
99
|
+
}
|
|
100
|
+
// Handle arrays
|
|
101
|
+
if (Array.isArray(data)) {
|
|
102
|
+
return data.map((item, index) => sanitizeValue(item, options, warnings, `${path}[${index}]`, depth + 1));
|
|
103
|
+
}
|
|
104
|
+
// Handle objects
|
|
105
|
+
if (typeof data === 'object') {
|
|
106
|
+
// Handle Date objects
|
|
107
|
+
if (data instanceof Date) {
|
|
108
|
+
return data.toISOString();
|
|
109
|
+
}
|
|
110
|
+
// Handle regular objects
|
|
111
|
+
const sanitized = {};
|
|
112
|
+
for (const [key, value] of Object.entries(data)) {
|
|
113
|
+
sanitized[key] = sanitizeValue(value, options, warnings, `${path}.${key}`, depth + 1);
|
|
114
|
+
}
|
|
115
|
+
return sanitized;
|
|
116
|
+
}
|
|
117
|
+
// Handle functions (shouldn't appear in JSON, but be safe)
|
|
118
|
+
if (typeof data === 'function') {
|
|
119
|
+
return '[FUNCTION]';
|
|
120
|
+
}
|
|
121
|
+
return data;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Sanitize data for MCP response with warnings
|
|
125
|
+
*
|
|
126
|
+
* Returns both the sanitized data and any warnings about suspicious content.
|
|
127
|
+
* Warnings are for logging purposes - the data is still returned.
|
|
128
|
+
*/
|
|
129
|
+
export function sanitizeWithWarnings(data, options) {
|
|
130
|
+
const mergedOptions = {
|
|
131
|
+
...DEFAULT_OPTIONS,
|
|
132
|
+
...options,
|
|
133
|
+
};
|
|
134
|
+
const warnings = [];
|
|
135
|
+
const sanitizedData = sanitizeValue(data, mergedOptions, warnings, '$', 0);
|
|
136
|
+
return {
|
|
137
|
+
data: sanitizedData,
|
|
138
|
+
warnings,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Sanitize data for MCP response
|
|
143
|
+
*
|
|
144
|
+
* This is the main function to use when preparing tool responses.
|
|
145
|
+
* It sanitizes user-controlled data to prevent prompt injection.
|
|
146
|
+
*
|
|
147
|
+
* @param data - The data to sanitize (typically from FreshBooks API)
|
|
148
|
+
* @param options - Optional sanitization options
|
|
149
|
+
* @returns Sanitized data safe for MCP response
|
|
150
|
+
*/
|
|
151
|
+
export function sanitizeForMcpResponse(data, options) {
|
|
152
|
+
return sanitizeWithWarnings(data, options).data;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Create a sanitized JSON string for MCP response content
|
|
156
|
+
*
|
|
157
|
+
* Convenience function that sanitizes and stringifies in one call.
|
|
158
|
+
*/
|
|
159
|
+
export function toSanitizedJson(data, options) {
|
|
160
|
+
const sanitized = sanitizeForMcpResponse(data, options);
|
|
161
|
+
return JSON.stringify(sanitized, null, 2);
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=sanitizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitizer.js","sourceRoot":"","sources":["../../src/utils/sanitizer.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.
|
|
3
|
+
"version": "1.0.2",
|
|
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",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
}
|
|
39
39
|
},
|
|
40
40
|
"bin": {
|
|
41
|
-
"freshbooks-mcp": "
|
|
41
|
+
"freshbooks-mcp": "dist/server.js"
|
|
42
42
|
},
|
|
43
43
|
"files": [
|
|
44
44
|
"dist",
|