@goodsamsoftware/freshbooks-mcp 1.0.5 → 1.0.7
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/LICENSE +21 -21
- package/README.md +357 -357
- package/dist/tools/client/client-create.js +38 -38
- package/dist/tools/client/client-list.js +47 -47
- package/dist/tools/client/client-update.js +34 -34
- package/dist/tools/credit-note/creditnote-single.js +18 -18
- package/dist/tools/expense/expense-update.d.ts.map +1 -1
- package/dist/tools/expense/expense-update.js +4 -4
- package/dist/tools/expense/expense-update.js.map +1 -1
- package/dist/tools/invoice/invoice-list.js +40 -40
- package/dist/tools/project/project-create.js +34 -34
- package/dist/tools/project/project-delete.js +38 -38
- package/dist/tools/project/project-list.js +38 -38
- package/dist/tools/project/project-single.js +23 -23
- package/dist/tools/project/project-update.js +37 -37
- package/dist/tools/task/task-create.js +36 -36
- package/dist/tools/task/task-delete.js +35 -35
- package/dist/tools/task/task-list.js +28 -28
- package/dist/tools/task/task-single.js +25 -25
- package/dist/tools/task/task-update.js +39 -39
- package/dist/tools/time-entry/timeentry-create.js +49 -49
- package/dist/tools/time-entry/timeentry-delete.js +48 -48
- package/dist/tools/time-entry/timeentry-list.js +53 -53
- package/dist/tools/time-entry/timeentry-single.js +28 -28
- package/dist/tools/time-entry/timeentry-update.js +61 -61
- package/dist/tools/timer/timer-current.js +54 -54
- package/dist/tools/timer/timer-discard.js +41 -41
- package/dist/tools/timer/timer-start.js +43 -43
- package/dist/tools/timer/timer-stop.js +33 -33
- package/package.json +88 -88
|
@@ -13,47 +13,47 @@ import { ErrorHandler } from "../../errors/error-handler.js";
|
|
|
13
13
|
*/
|
|
14
14
|
export const timerDiscardTool = {
|
|
15
15
|
name: "timer_discard",
|
|
16
|
-
description: `Discard a running timer without logging the time in FreshBooks.
|
|
17
|
-
|
|
18
|
-
WHEN TO USE:
|
|
19
|
-
- User says "discard timer", "delete timer", "cancel tracking"
|
|
20
|
-
- Timer was started by mistake
|
|
21
|
-
- Work was not actually performed
|
|
22
|
-
- Want to abandon tracked time without saving
|
|
23
|
-
|
|
24
|
-
IMPORTANT DIFFERENCE: Discard vs Stop
|
|
25
|
-
- timer_stop: Logs the time, saves the time entry with calculated duration
|
|
26
|
-
- timer_discard: DELETES the timer completely, no record is kept
|
|
27
|
-
|
|
28
|
-
USE WITH CAUTION:
|
|
29
|
-
- This permanently deletes the timer and all its time entries
|
|
30
|
-
- The tracked time CANNOT be recovered after discarding
|
|
31
|
-
- Use timer_stop if you want to keep and log the time entry
|
|
32
|
-
|
|
33
|
-
HOW IT WORKS:
|
|
34
|
-
Deletes the timer completely:
|
|
35
|
-
- Timer and all time entries are removed from FreshBooks
|
|
36
|
-
- No duration is logged
|
|
37
|
-
- No record remains
|
|
38
|
-
|
|
39
|
-
REQUIRED:
|
|
40
|
-
- businessId: FreshBooks business ID (get from user_me -> businessMemberships[].business.id)
|
|
41
|
-
|
|
42
|
-
OPTIONAL:
|
|
43
|
-
- timerId: ID of the timer to discard (from timer_current). If not provided, discards the current timer.
|
|
44
|
-
|
|
45
|
-
WHAT IF NO TIMER EXISTS:
|
|
46
|
-
- Returns error if no timer found
|
|
47
|
-
|
|
48
|
-
EXAMPLE USAGE:
|
|
49
|
-
- "Discard my current timer" (auto-detects current timer)
|
|
50
|
-
- "Delete timer - I didn't actually work on it"
|
|
51
|
-
- "Cancel time tracking"
|
|
52
|
-
|
|
53
|
-
RETURNS:
|
|
54
|
-
Confirmation object with:
|
|
55
|
-
- success: true if deletion succeeded
|
|
56
|
-
- timeEntryId: The first time entry ID that was deleted
|
|
16
|
+
description: `Discard a running timer without logging the time in FreshBooks.
|
|
17
|
+
|
|
18
|
+
WHEN TO USE:
|
|
19
|
+
- User says "discard timer", "delete timer", "cancel tracking"
|
|
20
|
+
- Timer was started by mistake
|
|
21
|
+
- Work was not actually performed
|
|
22
|
+
- Want to abandon tracked time without saving
|
|
23
|
+
|
|
24
|
+
IMPORTANT DIFFERENCE: Discard vs Stop
|
|
25
|
+
- timer_stop: Logs the time, saves the time entry with calculated duration
|
|
26
|
+
- timer_discard: DELETES the timer completely, no record is kept
|
|
27
|
+
|
|
28
|
+
USE WITH CAUTION:
|
|
29
|
+
- This permanently deletes the timer and all its time entries
|
|
30
|
+
- The tracked time CANNOT be recovered after discarding
|
|
31
|
+
- Use timer_stop if you want to keep and log the time entry
|
|
32
|
+
|
|
33
|
+
HOW IT WORKS:
|
|
34
|
+
Deletes the timer completely:
|
|
35
|
+
- Timer and all time entries are removed from FreshBooks
|
|
36
|
+
- No duration is logged
|
|
37
|
+
- No record remains
|
|
38
|
+
|
|
39
|
+
REQUIRED:
|
|
40
|
+
- businessId: FreshBooks business ID (get from user_me -> businessMemberships[].business.id)
|
|
41
|
+
|
|
42
|
+
OPTIONAL:
|
|
43
|
+
- timerId: ID of the timer to discard (from timer_current). If not provided, discards the current timer.
|
|
44
|
+
|
|
45
|
+
WHAT IF NO TIMER EXISTS:
|
|
46
|
+
- Returns error if no timer found
|
|
47
|
+
|
|
48
|
+
EXAMPLE USAGE:
|
|
49
|
+
- "Discard my current timer" (auto-detects current timer)
|
|
50
|
+
- "Delete timer - I didn't actually work on it"
|
|
51
|
+
- "Cancel time tracking"
|
|
52
|
+
|
|
53
|
+
RETURNS:
|
|
54
|
+
Confirmation object with:
|
|
55
|
+
- success: true if deletion succeeded
|
|
56
|
+
- timeEntryId: The first time entry ID that was deleted
|
|
57
57
|
- message: Confirmation message`,
|
|
58
58
|
inputSchema: TimerDiscardInputSchema,
|
|
59
59
|
outputSchema: TimerDiscardOutputSchema,
|
|
@@ -13,49 +13,49 @@ import { ErrorHandler } from "../../errors/error-handler.js";
|
|
|
13
13
|
*/
|
|
14
14
|
export const timerStartTool = {
|
|
15
15
|
name: "timer_start",
|
|
16
|
-
description: `Start a new timer for time tracking in FreshBooks.
|
|
17
|
-
|
|
18
|
-
WHEN TO USE:
|
|
19
|
-
- User says "start timer", "begin tracking time", "clock in"
|
|
20
|
-
- User wants to track time on a task or project
|
|
21
|
-
- Starting work on billable hours
|
|
22
|
-
|
|
23
|
-
HOW IT WORKS:
|
|
24
|
-
Creates a new time entry with:
|
|
25
|
-
- active=true (timer is running)
|
|
26
|
-
- duration=0 (will auto-calculate when stopped)
|
|
27
|
-
- startedAt=now (start time)
|
|
28
|
-
- isLogged=false (not yet logged as completed time)
|
|
29
|
-
|
|
30
|
-
IMPORTANT NOTES:
|
|
31
|
-
- FreshBooks typically allows only ONE active timer per user
|
|
32
|
-
- If a timer is already running, you may need to stop it first
|
|
33
|
-
- The timer will continue running until explicitly stopped
|
|
34
|
-
- Duration is auto-calculated from startedAt when stopped
|
|
35
|
-
|
|
36
|
-
REQUIRED:
|
|
37
|
-
- businessId: FreshBooks business ID (get from user_me -> businessMemberships[].business.id)
|
|
38
|
-
|
|
39
|
-
OPTIONAL BUT HELPFUL:
|
|
40
|
-
- projectId: Associate timer with a specific project (recommended for billing)
|
|
41
|
-
- clientId: Associate timer with a client
|
|
42
|
-
- serviceId: Type of service/work being performed
|
|
43
|
-
- taskId: Specific task within a project
|
|
44
|
-
- note: Description of work being performed (can be updated when stopping)
|
|
45
|
-
- billable: Whether time is billable (default: true)
|
|
46
|
-
- internal: Whether this is internal work (default: false)
|
|
47
|
-
|
|
48
|
-
EXAMPLE USAGE:
|
|
49
|
-
- "Start a timer for Project Alpha"
|
|
50
|
-
- "Begin tracking time on bug fixes"
|
|
51
|
-
- "Clock in for client meeting"
|
|
52
|
-
|
|
53
|
-
RETURNS:
|
|
54
|
-
Created time entry with:
|
|
55
|
-
- id: Use this ID to stop or discard the timer later
|
|
56
|
-
- active: true (timer is running)
|
|
57
|
-
- duration: 0 (will be calculated when stopped)
|
|
58
|
-
- startedAt: When timer started
|
|
16
|
+
description: `Start a new timer for time tracking in FreshBooks.
|
|
17
|
+
|
|
18
|
+
WHEN TO USE:
|
|
19
|
+
- User says "start timer", "begin tracking time", "clock in"
|
|
20
|
+
- User wants to track time on a task or project
|
|
21
|
+
- Starting work on billable hours
|
|
22
|
+
|
|
23
|
+
HOW IT WORKS:
|
|
24
|
+
Creates a new time entry with:
|
|
25
|
+
- active=true (timer is running)
|
|
26
|
+
- duration=0 (will auto-calculate when stopped)
|
|
27
|
+
- startedAt=now (start time)
|
|
28
|
+
- isLogged=false (not yet logged as completed time)
|
|
29
|
+
|
|
30
|
+
IMPORTANT NOTES:
|
|
31
|
+
- FreshBooks typically allows only ONE active timer per user
|
|
32
|
+
- If a timer is already running, you may need to stop it first
|
|
33
|
+
- The timer will continue running until explicitly stopped
|
|
34
|
+
- Duration is auto-calculated from startedAt when stopped
|
|
35
|
+
|
|
36
|
+
REQUIRED:
|
|
37
|
+
- businessId: FreshBooks business ID (get from user_me -> businessMemberships[].business.id)
|
|
38
|
+
|
|
39
|
+
OPTIONAL BUT HELPFUL:
|
|
40
|
+
- projectId: Associate timer with a specific project (recommended for billing)
|
|
41
|
+
- clientId: Associate timer with a client
|
|
42
|
+
- serviceId: Type of service/work being performed
|
|
43
|
+
- taskId: Specific task within a project
|
|
44
|
+
- note: Description of work being performed (can be updated when stopping)
|
|
45
|
+
- billable: Whether time is billable (default: true)
|
|
46
|
+
- internal: Whether this is internal work (default: false)
|
|
47
|
+
|
|
48
|
+
EXAMPLE USAGE:
|
|
49
|
+
- "Start a timer for Project Alpha"
|
|
50
|
+
- "Begin tracking time on bug fixes"
|
|
51
|
+
- "Clock in for client meeting"
|
|
52
|
+
|
|
53
|
+
RETURNS:
|
|
54
|
+
Created time entry with:
|
|
55
|
+
- id: Use this ID to stop or discard the timer later
|
|
56
|
+
- active: true (timer is running)
|
|
57
|
+
- duration: 0 (will be calculated when stopped)
|
|
58
|
+
- startedAt: When timer started
|
|
59
59
|
- timer: Active timer object with isRunning=true`,
|
|
60
60
|
inputSchema: TimerStartInputSchema,
|
|
61
61
|
outputSchema: TimerStartOutputSchema,
|
|
@@ -13,39 +13,39 @@ import { ErrorHandler } from "../../errors/error-handler.js";
|
|
|
13
13
|
*/
|
|
14
14
|
export const timerStopTool = {
|
|
15
15
|
name: "timer_stop",
|
|
16
|
-
description: `Stop a running timer and log the time in FreshBooks.
|
|
17
|
-
|
|
18
|
-
WHEN TO USE:
|
|
19
|
-
- User says "stop timer", "stop tracking", "clock out"
|
|
20
|
-
- User finishes work on a task/project and wants to log the time
|
|
21
|
-
- User wants to save and log the time entry
|
|
22
|
-
|
|
23
|
-
HOW IT WORKS:
|
|
24
|
-
1. Gets the current timer to calculate total duration
|
|
25
|
-
2. Aggregates duration across all time entry segments
|
|
26
|
-
3. Updates the timer to mark time as logged and billable
|
|
27
|
-
|
|
28
|
-
REQUIRED:
|
|
29
|
-
- businessId: FreshBooks business ID (get from user_me -> businessMemberships[].business.id)
|
|
30
|
-
|
|
31
|
-
OPTIONAL:
|
|
32
|
-
- timerId: ID of the timer to stop (from timer_current). If not provided, stops the current running timer.
|
|
33
|
-
- note: Update the description before stopping
|
|
34
|
-
|
|
35
|
-
WHAT IF NO TIMER IS RUNNING:
|
|
36
|
-
- Returns error if no active timer found
|
|
37
|
-
|
|
38
|
-
EXAMPLE USAGE:
|
|
39
|
-
- "Stop my timer" (auto-detects current timer)
|
|
40
|
-
- "Stop timer and add note: completed bug fixes"
|
|
41
|
-
|
|
42
|
-
RETURNS:
|
|
43
|
-
Stopped time entry with:
|
|
44
|
-
- id: The time entry ID
|
|
45
|
-
- timerId: The timer ID
|
|
46
|
-
- active: false (timer has stopped)
|
|
47
|
-
- duration: Total calculated time in seconds
|
|
48
|
-
- isLogged: true (time is now logged)
|
|
16
|
+
description: `Stop a running timer and log the time in FreshBooks.
|
|
17
|
+
|
|
18
|
+
WHEN TO USE:
|
|
19
|
+
- User says "stop timer", "stop tracking", "clock out"
|
|
20
|
+
- User finishes work on a task/project and wants to log the time
|
|
21
|
+
- User wants to save and log the time entry
|
|
22
|
+
|
|
23
|
+
HOW IT WORKS:
|
|
24
|
+
1. Gets the current timer to calculate total duration
|
|
25
|
+
2. Aggregates duration across all time entry segments
|
|
26
|
+
3. Updates the timer to mark time as logged and billable
|
|
27
|
+
|
|
28
|
+
REQUIRED:
|
|
29
|
+
- businessId: FreshBooks business ID (get from user_me -> businessMemberships[].business.id)
|
|
30
|
+
|
|
31
|
+
OPTIONAL:
|
|
32
|
+
- timerId: ID of the timer to stop (from timer_current). If not provided, stops the current running timer.
|
|
33
|
+
- note: Update the description before stopping
|
|
34
|
+
|
|
35
|
+
WHAT IF NO TIMER IS RUNNING:
|
|
36
|
+
- Returns error if no active timer found
|
|
37
|
+
|
|
38
|
+
EXAMPLE USAGE:
|
|
39
|
+
- "Stop my timer" (auto-detects current timer)
|
|
40
|
+
- "Stop timer and add note: completed bug fixes"
|
|
41
|
+
|
|
42
|
+
RETURNS:
|
|
43
|
+
Stopped time entry with:
|
|
44
|
+
- id: The time entry ID
|
|
45
|
+
- timerId: The timer ID
|
|
46
|
+
- active: false (timer has stopped)
|
|
47
|
+
- duration: Total calculated time in seconds
|
|
48
|
+
- isLogged: true (time is now logged)
|
|
49
49
|
- billable: true (time is marked billable)`,
|
|
50
50
|
inputSchema: TimerStopInputSchema,
|
|
51
51
|
outputSchema: TimerStopOutputSchema,
|
package/package.json
CHANGED
|
@@ -1,88 +1,88 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@goodsamsoftware/freshbooks-mcp",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "FreshBooks MCP server providing 1:1 parity with the FreshBooks Node.js SDK",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "dist/server.js",
|
|
7
|
-
"types": "dist/server.d.ts",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": {
|
|
10
|
-
"types": "./dist/server.d.ts",
|
|
11
|
-
"import": "./dist/server.js",
|
|
12
|
-
"require": "./dist/server.js"
|
|
13
|
-
},
|
|
14
|
-
"./tools": {
|
|
15
|
-
"types": "./dist/tools/index.d.ts",
|
|
16
|
-
"import": "./dist/tools/index.js",
|
|
17
|
-
"require": "./dist/tools/index.js"
|
|
18
|
-
},
|
|
19
|
-
"./client": {
|
|
20
|
-
"types": "./dist/client/index.d.ts",
|
|
21
|
-
"import": "./dist/client/index.js",
|
|
22
|
-
"require": "./dist/client/index.js"
|
|
23
|
-
},
|
|
24
|
-
"./auth": {
|
|
25
|
-
"types": "./dist/auth/index.d.ts",
|
|
26
|
-
"import": "./dist/auth/index.js",
|
|
27
|
-
"require": "./dist/auth/index.js"
|
|
28
|
-
},
|
|
29
|
-
"./errors": {
|
|
30
|
-
"types": "./dist/errors/index.d.ts",
|
|
31
|
-
"import": "./dist/errors/index.js",
|
|
32
|
-
"require": "./dist/errors/index.js"
|
|
33
|
-
},
|
|
34
|
-
"./utils": {
|
|
35
|
-
"types": "./dist/utils/index.d.ts",
|
|
36
|
-
"import": "./dist/utils/index.js",
|
|
37
|
-
"require": "./dist/utils/index.js"
|
|
38
|
-
}
|
|
39
|
-
},
|
|
40
|
-
"bin": {
|
|
41
|
-
"freshbooks-mcp": "./dist/server.js"
|
|
42
|
-
},
|
|
43
|
-
"files": [
|
|
44
|
-
"dist",
|
|
45
|
-
"README.md",
|
|
46
|
-
"LICENSE"
|
|
47
|
-
],
|
|
48
|
-
"scripts": {
|
|
49
|
-
"build": "tsc",
|
|
50
|
-
"start": "node dist/server.js",
|
|
51
|
-
"dev": "tsx watch src/server.ts",
|
|
52
|
-
"test": "vitest",
|
|
53
|
-
"test:coverage": "vitest --coverage",
|
|
54
|
-
"lint": "eslint src/",
|
|
55
|
-
"typecheck": "tsc --noEmit"
|
|
56
|
-
},
|
|
57
|
-
"keywords": [
|
|
58
|
-
"freshbooks",
|
|
59
|
-
"mcp",
|
|
60
|
-
"model-context-protocol",
|
|
61
|
-
"time-tracking",
|
|
62
|
-
"invoicing"
|
|
63
|
-
],
|
|
64
|
-
"author": "Chadwick Posey <chadwick.posey@goodsamsoftware.com>",
|
|
65
|
-
"license": "MIT",
|
|
66
|
-
"repository": {
|
|
67
|
-
"type": "git",
|
|
68
|
-
"url": "git+https://github.com/Good-Samaritan-Software-LLC/freshbooks-mcp.git"
|
|
69
|
-
},
|
|
70
|
-
"bugs": {
|
|
71
|
-
"url": "https://github.com/Good-Samaritan-Software-LLC/freshbooks-mcp/issues"
|
|
72
|
-
},
|
|
73
|
-
"homepage": "https://freshbooks.goodsamsoftware.com/",
|
|
74
|
-
"dependencies": {
|
|
75
|
-
"@freshbooks/api": "^4.1.0",
|
|
76
|
-
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
77
|
-
"zod": "^3.22.0"
|
|
78
|
-
},
|
|
79
|
-
"devDependencies": {
|
|
80
|
-
"@faker-js/faker": "^8.3.1",
|
|
81
|
-
"@types/node": "^20.0.0",
|
|
82
|
-
"@vitest/coverage-v8": "^4.0.16",
|
|
83
|
-
"eslint": "^8.0.0",
|
|
84
|
-
"tsx": "^4.0.0",
|
|
85
|
-
"typescript": "^5.3.0",
|
|
86
|
-
"vitest": "^4.0.16"
|
|
87
|
-
}
|
|
88
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@goodsamsoftware/freshbooks-mcp",
|
|
3
|
+
"version": "1.0.7",
|
|
4
|
+
"description": "FreshBooks MCP server providing 1:1 parity with the FreshBooks Node.js SDK",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/server.js",
|
|
7
|
+
"types": "dist/server.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/server.d.ts",
|
|
11
|
+
"import": "./dist/server.js",
|
|
12
|
+
"require": "./dist/server.js"
|
|
13
|
+
},
|
|
14
|
+
"./tools": {
|
|
15
|
+
"types": "./dist/tools/index.d.ts",
|
|
16
|
+
"import": "./dist/tools/index.js",
|
|
17
|
+
"require": "./dist/tools/index.js"
|
|
18
|
+
},
|
|
19
|
+
"./client": {
|
|
20
|
+
"types": "./dist/client/index.d.ts",
|
|
21
|
+
"import": "./dist/client/index.js",
|
|
22
|
+
"require": "./dist/client/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./auth": {
|
|
25
|
+
"types": "./dist/auth/index.d.ts",
|
|
26
|
+
"import": "./dist/auth/index.js",
|
|
27
|
+
"require": "./dist/auth/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./errors": {
|
|
30
|
+
"types": "./dist/errors/index.d.ts",
|
|
31
|
+
"import": "./dist/errors/index.js",
|
|
32
|
+
"require": "./dist/errors/index.js"
|
|
33
|
+
},
|
|
34
|
+
"./utils": {
|
|
35
|
+
"types": "./dist/utils/index.d.ts",
|
|
36
|
+
"import": "./dist/utils/index.js",
|
|
37
|
+
"require": "./dist/utils/index.js"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"bin": {
|
|
41
|
+
"freshbooks-mcp": "./dist/server.js"
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"dist",
|
|
45
|
+
"README.md",
|
|
46
|
+
"LICENSE"
|
|
47
|
+
],
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsc",
|
|
50
|
+
"start": "node dist/server.js",
|
|
51
|
+
"dev": "tsx watch src/server.ts",
|
|
52
|
+
"test": "vitest",
|
|
53
|
+
"test:coverage": "vitest --coverage",
|
|
54
|
+
"lint": "eslint src/",
|
|
55
|
+
"typecheck": "tsc --noEmit"
|
|
56
|
+
},
|
|
57
|
+
"keywords": [
|
|
58
|
+
"freshbooks",
|
|
59
|
+
"mcp",
|
|
60
|
+
"model-context-protocol",
|
|
61
|
+
"time-tracking",
|
|
62
|
+
"invoicing"
|
|
63
|
+
],
|
|
64
|
+
"author": "Chadwick Posey <chadwick.posey@goodsamsoftware.com>",
|
|
65
|
+
"license": "MIT",
|
|
66
|
+
"repository": {
|
|
67
|
+
"type": "git",
|
|
68
|
+
"url": "git+https://github.com/Good-Samaritan-Software-LLC/freshbooks-mcp.git"
|
|
69
|
+
},
|
|
70
|
+
"bugs": {
|
|
71
|
+
"url": "https://github.com/Good-Samaritan-Software-LLC/freshbooks-mcp/issues"
|
|
72
|
+
},
|
|
73
|
+
"homepage": "https://freshbooks.goodsamsoftware.com/",
|
|
74
|
+
"dependencies": {
|
|
75
|
+
"@freshbooks/api": "^4.1.0",
|
|
76
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
77
|
+
"zod": "^3.22.0"
|
|
78
|
+
},
|
|
79
|
+
"devDependencies": {
|
|
80
|
+
"@faker-js/faker": "^8.3.1",
|
|
81
|
+
"@types/node": "^20.0.0",
|
|
82
|
+
"@vitest/coverage-v8": "^4.0.16",
|
|
83
|
+
"eslint": "^8.0.0",
|
|
84
|
+
"tsx": "^4.0.0",
|
|
85
|
+
"typescript": "^5.3.0",
|
|
86
|
+
"vitest": "^4.0.16"
|
|
87
|
+
}
|
|
88
|
+
}
|