@stupidcodefactory/freeagent-mcp-server 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. package/README.md +187 -0
  2. package/dist/api/freeagent-client.d.ts +12 -0
  3. package/dist/api/freeagent-client.d.ts.map +1 -0
  4. package/dist/api/freeagent-client.js +114 -0
  5. package/dist/api/freeagent-client.js.map +1 -0
  6. package/dist/api/index.d.ts +7 -0
  7. package/dist/api/index.d.ts.map +1 -0
  8. package/dist/api/index.js +4 -0
  9. package/dist/api/index.js.map +1 -0
  10. package/dist/api/rate-limiter.d.ts +15 -0
  11. package/dist/api/rate-limiter.d.ts.map +1 -0
  12. package/dist/api/rate-limiter.js +62 -0
  13. package/dist/api/rate-limiter.js.map +1 -0
  14. package/dist/api/retry-handler.d.ts +14 -0
  15. package/dist/api/retry-handler.d.ts.map +1 -0
  16. package/dist/api/retry-handler.js +49 -0
  17. package/dist/api/retry-handler.js.map +1 -0
  18. package/dist/auth/index.d.ts +7 -0
  19. package/dist/auth/index.d.ts.map +1 -0
  20. package/dist/auth/index.js +4 -0
  21. package/dist/auth/index.js.map +1 -0
  22. package/dist/auth/oauth.d.ts +16 -0
  23. package/dist/auth/oauth.d.ts.map +1 -0
  24. package/dist/auth/oauth.js +64 -0
  25. package/dist/auth/oauth.js.map +1 -0
  26. package/dist/auth/token-manager.d.ts +10 -0
  27. package/dist/auth/token-manager.d.ts.map +1 -0
  28. package/dist/auth/token-manager.js +71 -0
  29. package/dist/auth/token-manager.js.map +1 -0
  30. package/dist/auth/token-store.d.ts +10 -0
  31. package/dist/auth/token-store.d.ts.map +1 -0
  32. package/dist/auth/token-store.js +84 -0
  33. package/dist/auth/token-store.js.map +1 -0
  34. package/dist/config.d.ts +73 -0
  35. package/dist/config.d.ts.map +1 -0
  36. package/dist/config.js +46 -0
  37. package/dist/config.js.map +1 -0
  38. package/dist/index.d.ts +3 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +44 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/prompts/cash-flow-forecast.d.ts +12 -0
  43. package/dist/prompts/cash-flow-forecast.d.ts.map +1 -0
  44. package/dist/prompts/cash-flow-forecast.js +93 -0
  45. package/dist/prompts/cash-flow-forecast.js.map +1 -0
  46. package/dist/prompts/index.d.ts +8 -0
  47. package/dist/prompts/index.d.ts.map +1 -0
  48. package/dist/prompts/index.js +8 -0
  49. package/dist/prompts/index.js.map +1 -0
  50. package/dist/prompts/invoice-from-description.d.ts +12 -0
  51. package/dist/prompts/invoice-from-description.d.ts.map +1 -0
  52. package/dist/prompts/invoice-from-description.js +49 -0
  53. package/dist/prompts/invoice-from-description.js.map +1 -0
  54. package/dist/prompts/monthly-expense-summary.d.ts +12 -0
  55. package/dist/prompts/monthly-expense-summary.d.ts.map +1 -0
  56. package/dist/prompts/monthly-expense-summary.js +84 -0
  57. package/dist/prompts/monthly-expense-summary.js.map +1 -0
  58. package/dist/prompts/overdue-invoice-followup.d.ts +12 -0
  59. package/dist/prompts/overdue-invoice-followup.d.ts.map +1 -0
  60. package/dist/prompts/overdue-invoice-followup.js +63 -0
  61. package/dist/prompts/overdue-invoice-followup.js.map +1 -0
  62. package/dist/prompts/project-profitability.d.ts +12 -0
  63. package/dist/prompts/project-profitability.d.ts.map +1 -0
  64. package/dist/prompts/project-profitability.js +103 -0
  65. package/dist/prompts/project-profitability.js.map +1 -0
  66. package/dist/prompts/quarterly-tax-estimate.d.ts +12 -0
  67. package/dist/prompts/quarterly-tax-estimate.d.ts.map +1 -0
  68. package/dist/prompts/quarterly-tax-estimate.js +132 -0
  69. package/dist/prompts/quarterly-tax-estimate.js.map +1 -0
  70. package/dist/prompts/transaction-categorization.d.ts +12 -0
  71. package/dist/prompts/transaction-categorization.d.ts.map +1 -0
  72. package/dist/prompts/transaction-categorization.js +81 -0
  73. package/dist/prompts/transaction-categorization.js.map +1 -0
  74. package/dist/resources/bank-accounts.d.ts +8 -0
  75. package/dist/resources/bank-accounts.d.ts.map +1 -0
  76. package/dist/resources/bank-accounts.js +34 -0
  77. package/dist/resources/bank-accounts.js.map +1 -0
  78. package/dist/resources/bank-transactions.d.ts +11 -0
  79. package/dist/resources/bank-transactions.d.ts.map +1 -0
  80. package/dist/resources/bank-transactions.js +34 -0
  81. package/dist/resources/bank-transactions.js.map +1 -0
  82. package/dist/resources/bills.d.ts +13 -0
  83. package/dist/resources/bills.d.ts.map +1 -0
  84. package/dist/resources/bills.js +38 -0
  85. package/dist/resources/bills.js.map +1 -0
  86. package/dist/resources/categories.d.ts +4 -0
  87. package/dist/resources/categories.d.ts.map +1 -0
  88. package/dist/resources/categories.js +21 -0
  89. package/dist/resources/categories.js.map +1 -0
  90. package/dist/resources/company.d.ts +3 -0
  91. package/dist/resources/company.d.ts.map +1 -0
  92. package/dist/resources/company.js +12 -0
  93. package/dist/resources/company.js.map +1 -0
  94. package/dist/resources/contacts.d.ts +9 -0
  95. package/dist/resources/contacts.d.ts.map +1 -0
  96. package/dist/resources/contacts.js +37 -0
  97. package/dist/resources/contacts.js.map +1 -0
  98. package/dist/resources/expenses.d.ts +12 -0
  99. package/dist/resources/expenses.d.ts.map +1 -0
  100. package/dist/resources/expenses.js +36 -0
  101. package/dist/resources/expenses.js.map +1 -0
  102. package/dist/resources/index.d.ts +20 -0
  103. package/dist/resources/index.d.ts.map +1 -0
  104. package/dist/resources/index.js +12 -0
  105. package/dist/resources/index.js.map +1 -0
  106. package/dist/resources/invoices.d.ts +14 -0
  107. package/dist/resources/invoices.d.ts.map +1 -0
  108. package/dist/resources/invoices.js +40 -0
  109. package/dist/resources/invoices.js.map +1 -0
  110. package/dist/resources/projects.d.ts +10 -0
  111. package/dist/resources/projects.d.ts.map +1 -0
  112. package/dist/resources/projects.js +39 -0
  113. package/dist/resources/projects.js.map +1 -0
  114. package/dist/resources/timeslips.d.ts +12 -0
  115. package/dist/resources/timeslips.d.ts.map +1 -0
  116. package/dist/resources/timeslips.js +36 -0
  117. package/dist/resources/timeslips.js.map +1 -0
  118. package/dist/resources/users.d.ts +5 -0
  119. package/dist/resources/users.d.ts.map +1 -0
  120. package/dist/resources/users.js +30 -0
  121. package/dist/resources/users.js.map +1 -0
  122. package/dist/server.d.ts +9 -0
  123. package/dist/server.d.ts.map +1 -0
  124. package/dist/server.js +568 -0
  125. package/dist/server.js.map +1 -0
  126. package/dist/tools/bank-tools.d.ts +112 -0
  127. package/dist/tools/bank-tools.d.ts.map +1 -0
  128. package/dist/tools/bank-tools.js +143 -0
  129. package/dist/tools/bank-tools.js.map +1 -0
  130. package/dist/tools/bill-tools.d.ts +129 -0
  131. package/dist/tools/bill-tools.d.ts.map +1 -0
  132. package/dist/tools/bill-tools.js +121 -0
  133. package/dist/tools/bill-tools.js.map +1 -0
  134. package/dist/tools/contact-tools.d.ts +147 -0
  135. package/dist/tools/contact-tools.d.ts.map +1 -0
  136. package/dist/tools/contact-tools.js +140 -0
  137. package/dist/tools/contact-tools.js.map +1 -0
  138. package/dist/tools/index.d.ts +13 -0
  139. package/dist/tools/index.d.ts.map +1 -0
  140. package/dist/tools/index.js +13 -0
  141. package/dist/tools/index.js.map +1 -0
  142. package/dist/tools/invoice-tools.d.ts +171 -0
  143. package/dist/tools/invoice-tools.d.ts.map +1 -0
  144. package/dist/tools/invoice-tools.js +168 -0
  145. package/dist/tools/invoice-tools.js.map +1 -0
  146. package/dist/tools/project-tools.d.ts +117 -0
  147. package/dist/tools/project-tools.d.ts.map +1 -0
  148. package/dist/tools/project-tools.js +153 -0
  149. package/dist/tools/project-tools.js.map +1 -0
  150. package/dist/tools/query-tools.d.ts +91 -0
  151. package/dist/tools/query-tools.d.ts.map +1 -0
  152. package/dist/tools/query-tools.js +127 -0
  153. package/dist/tools/query-tools.js.map +1 -0
  154. package/dist/transformers/bank-transformer.d.ts +8 -0
  155. package/dist/transformers/bank-transformer.d.ts.map +1 -0
  156. package/dist/transformers/bank-transformer.js +46 -0
  157. package/dist/transformers/bank-transformer.js.map +1 -0
  158. package/dist/transformers/bill-transformer.d.ts +6 -0
  159. package/dist/transformers/bill-transformer.d.ts.map +1 -0
  160. package/dist/transformers/bill-transformer.js +34 -0
  161. package/dist/transformers/bill-transformer.js.map +1 -0
  162. package/dist/transformers/category-transformer.d.ts +5 -0
  163. package/dist/transformers/category-transformer.d.ts.map +1 -0
  164. package/dist/transformers/category-transformer.js +14 -0
  165. package/dist/transformers/category-transformer.js.map +1 -0
  166. package/dist/transformers/common.d.ts +7 -0
  167. package/dist/transformers/common.d.ts.map +1 -0
  168. package/dist/transformers/common.js +33 -0
  169. package/dist/transformers/common.js.map +1 -0
  170. package/dist/transformers/company-transformer.d.ts +4 -0
  171. package/dist/transformers/company-transformer.d.ts.map +1 -0
  172. package/dist/transformers/company-transformer.js +10 -0
  173. package/dist/transformers/company-transformer.js.map +1 -0
  174. package/dist/transformers/contact-transformer.d.ts +5 -0
  175. package/dist/transformers/contact-transformer.d.ts.map +1 -0
  176. package/dist/transformers/contact-transformer.js +18 -0
  177. package/dist/transformers/contact-transformer.js.map +1 -0
  178. package/dist/transformers/expense-transformer.d.ts +5 -0
  179. package/dist/transformers/expense-transformer.d.ts.map +1 -0
  180. package/dist/transformers/expense-transformer.js +19 -0
  181. package/dist/transformers/expense-transformer.js.map +1 -0
  182. package/dist/transformers/index.d.ts +11 -0
  183. package/dist/transformers/index.d.ts.map +1 -0
  184. package/dist/transformers/index.js +11 -0
  185. package/dist/transformers/index.js.map +1 -0
  186. package/dist/transformers/invoice-transformer.d.ts +6 -0
  187. package/dist/transformers/invoice-transformer.d.ts.map +1 -0
  188. package/dist/transformers/invoice-transformer.js +39 -0
  189. package/dist/transformers/invoice-transformer.js.map +1 -0
  190. package/dist/transformers/project-transformer.d.ts +9 -0
  191. package/dist/transformers/project-transformer.d.ts.map +1 -0
  192. package/dist/transformers/project-transformer.js +53 -0
  193. package/dist/transformers/project-transformer.js.map +1 -0
  194. package/dist/transformers/user-transformer.d.ts +5 -0
  195. package/dist/transformers/user-transformer.d.ts.map +1 -0
  196. package/dist/transformers/user-transformer.js +14 -0
  197. package/dist/transformers/user-transformer.js.map +1 -0
  198. package/dist/types/freeagent/index.d.ts +256 -0
  199. package/dist/types/freeagent/index.d.ts.map +1 -0
  200. package/dist/types/freeagent/index.js +3 -0
  201. package/dist/types/freeagent/index.js.map +1 -0
  202. package/dist/types/llm/index.d.ts +159 -0
  203. package/dist/types/llm/index.d.ts.map +1 -0
  204. package/dist/types/llm/index.js +3 -0
  205. package/dist/types/llm/index.js.map +1 -0
  206. package/dist/utils/error-handler.d.ts +11 -0
  207. package/dist/utils/error-handler.d.ts.map +1 -0
  208. package/dist/utils/error-handler.js +57 -0
  209. package/dist/utils/error-handler.js.map +1 -0
  210. package/dist/utils/index.d.ts +5 -0
  211. package/dist/utils/index.d.ts.map +1 -0
  212. package/dist/utils/index.js +5 -0
  213. package/dist/utils/index.js.map +1 -0
  214. package/dist/utils/sanitizer.d.ts +4 -0
  215. package/dist/utils/sanitizer.d.ts.map +1 -0
  216. package/dist/utils/sanitizer.js +42 -0
  217. package/dist/utils/sanitizer.js.map +1 -0
  218. package/dist/utils/validators.d.ts +19 -0
  219. package/dist/utils/validators.d.ts.map +1 -0
  220. package/dist/utils/validators.js +83 -0
  221. package/dist/utils/validators.js.map +1 -0
  222. package/dist/utils/zod-to-json-schema.d.ts +24 -0
  223. package/dist/utils/zod-to-json-schema.d.ts.map +1 -0
  224. package/dist/utils/zod-to-json-schema.js +141 -0
  225. package/dist/utils/zod-to-json-schema.js.map +1 -0
  226. package/package.json +48 -0
@@ -0,0 +1,71 @@
1
+ import { refreshAccessToken } from './oauth.js';
2
+ const TOKEN_REFRESH_BUFFER_MS = 60 * 1000; // 60 seconds before expiry
3
+ const MAX_REFRESH_PER_MINUTE = 15;
4
+ export function createTokenManager(store) {
5
+ let refreshCount = 0;
6
+ let refreshResetTime = Date.now();
7
+ let refreshPromise = null;
8
+ async function doRefresh(currentTokens) {
9
+ // Rate limit refresh attempts
10
+ const now = Date.now();
11
+ if (now - refreshResetTime > 60 * 1000) {
12
+ refreshCount = 0;
13
+ refreshResetTime = now;
14
+ }
15
+ if (refreshCount >= MAX_REFRESH_PER_MINUTE) {
16
+ throw new Error('Token refresh rate limit exceeded (15/minute)');
17
+ }
18
+ refreshCount++;
19
+ try {
20
+ const newTokens = await refreshAccessToken(currentTokens.refreshToken);
21
+ store.set(newTokens);
22
+ await store.persist();
23
+ return newTokens;
24
+ }
25
+ finally {
26
+ refreshPromise = null;
27
+ }
28
+ }
29
+ const manager = {
30
+ async getAccessToken() {
31
+ const tokens = store.get();
32
+ if (!tokens) {
33
+ throw new Error('Not authenticated. Please complete OAuth flow first.');
34
+ }
35
+ const now = Date.now();
36
+ // Check if refresh token has expired
37
+ if (now >= tokens.refreshTokenExpiresAt) {
38
+ store.clear();
39
+ throw new Error('Refresh token expired. Please re-authenticate.');
40
+ }
41
+ // Check if access token needs refresh
42
+ if (now >= tokens.expiresAt - TOKEN_REFRESH_BUFFER_MS) {
43
+ // Use existing refresh promise if one is in progress (prevents concurrent refreshes)
44
+ if (!refreshPromise) {
45
+ refreshPromise = doRefresh(tokens);
46
+ }
47
+ const newTokens = await refreshPromise;
48
+ return newTokens.accessToken;
49
+ }
50
+ return tokens.accessToken;
51
+ },
52
+ async setTokens(tokens) {
53
+ store.set(tokens);
54
+ await store.persist();
55
+ },
56
+ isAuthenticated() {
57
+ const tokens = store.get();
58
+ if (!tokens) {
59
+ return false;
60
+ }
61
+ // Check if refresh token is still valid
62
+ return Date.now() < tokens.refreshTokenExpiresAt;
63
+ },
64
+ async clearTokens() {
65
+ store.clear();
66
+ await store.persist();
67
+ },
68
+ };
69
+ return manager;
70
+ }
71
+ //# sourceMappingURL=token-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-manager.js","sourceRoot":"","sources":["../../src/auth/token-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAkB,MAAM,YAAY,CAAC;AAGhE,MAAM,uBAAuB,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,2BAA2B;AACtE,MAAM,sBAAsB,GAAG,EAAE,CAAC;AASlC,MAAM,UAAU,kBAAkB,CAAC,KAAiB;IAClD,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,gBAAgB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAClC,IAAI,cAAc,GAA8B,IAAI,CAAC;IAErD,KAAK,UAAU,SAAS,CAAC,aAAwB;QAC/C,8BAA8B;QAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,GAAG,GAAG,gBAAgB,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;YACvC,YAAY,GAAG,CAAC,CAAC;YACjB,gBAAgB,GAAG,GAAG,CAAC;QACzB,CAAC;QAED,IAAI,YAAY,IAAI,sBAAsB,EAAE,CAAC;YAC3C,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;QACnE,CAAC;QAED,YAAY,EAAE,CAAC;QAEf,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,kBAAkB,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;YACvE,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACrB,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC;YACtB,OAAO,SAAS,CAAC;QACnB,CAAC;gBAAS,CAAC;YACT,cAAc,GAAG,IAAI,CAAC;QACxB,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAiB;QAC5B,KAAK,CAAC,cAAc;YAClB,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;YAE3B,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;YAC1E,CAAC;YAED,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAEvB,qCAAqC;YACrC,IAAI,GAAG,IAAI,MAAM,CAAC,qBAAqB,EAAE,CAAC;gBACxC,KAAK,CAAC,KAAK,EAAE,CAAC;gBACd,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;YACpE,CAAC;YAED,sCAAsC;YACtC,IAAI,GAAG,IAAI,MAAM,CAAC,SAAS,GAAG,uBAAuB,EAAE,CAAC;gBACtD,qFAAqF;gBACrF,IAAI,CAAC,cAAc,EAAE,CAAC;oBACpB,cAAc,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;gBACrC,CAAC;gBAED,MAAM,SAAS,GAAG,MAAM,cAAc,CAAC;gBACvC,OAAO,SAAS,CAAC,WAAW,CAAC;YAC/B,CAAC;YAED,OAAO,MAAM,CAAC,WAAW,CAAC;QAC5B,CAAC;QAED,KAAK,CAAC,SAAS,CAAC,MAAiB;YAC/B,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAClB,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC;QACxB,CAAC;QAED,eAAe;YACb,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;YAC3B,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,OAAO,KAAK,CAAC;YACf,CAAC;YAED,wCAAwC;YACxC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,qBAAqB,CAAC;QACnD,CAAC;QAED,KAAK,CAAC,WAAW;YACf,KAAK,CAAC,KAAK,EAAE,CAAC;YACd,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC;QACxB,CAAC;KACF,CAAC;IAEF,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { TokenData } from './oauth.js';
2
+ export interface TokenStore {
3
+ get(): TokenData | null;
4
+ set(tokens: TokenData): void;
5
+ clear(): void;
6
+ persist(): Promise<void>;
7
+ load(): Promise<void>;
8
+ }
9
+ export declare function createTokenStore(encryptionKey?: string): TokenStore;
10
+ //# sourceMappingURL=token-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-store.d.ts","sourceRoot":"","sources":["../../src/auth/token-store.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAK5C,MAAM,WAAW,UAAU;IACzB,GAAG,IAAI,SAAS,GAAG,IAAI,CAAC;IACxB,GAAG,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAAC;IAC7B,KAAK,IAAI,IAAI,CAAC;IACd,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED,wBAAgB,gBAAgB,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,UAAU,CAkDnE"}
@@ -0,0 +1,84 @@
1
+ import { createCipheriv, createDecipheriv, randomBytes, scryptSync } from 'crypto';
2
+ import { readFile, writeFile, mkdir } from 'fs/promises';
3
+ import { dirname, join } from 'path';
4
+ import { homedir } from 'os';
5
+ const TOKEN_FILE_PATH = join(homedir(), '.freeagent-mcp', 'tokens.enc');
6
+ const ALGORITHM = 'aes-256-gcm';
7
+ export function createTokenStore(encryptionKey) {
8
+ let currentTokens = null;
9
+ const store = {
10
+ get() {
11
+ return currentTokens;
12
+ },
13
+ set(tokens) {
14
+ currentTokens = tokens;
15
+ },
16
+ clear() {
17
+ currentTokens = null;
18
+ },
19
+ async persist() {
20
+ if (!currentTokens) {
21
+ return;
22
+ }
23
+ if (!encryptionKey) {
24
+ // No encryption key, skip file persistence
25
+ return;
26
+ }
27
+ const data = JSON.stringify(currentTokens);
28
+ const encrypted = encrypt(data, encryptionKey);
29
+ await mkdir(dirname(TOKEN_FILE_PATH), { recursive: true });
30
+ await writeFile(TOKEN_FILE_PATH, encrypted, 'utf-8');
31
+ },
32
+ async load() {
33
+ if (!encryptionKey) {
34
+ return;
35
+ }
36
+ try {
37
+ const encrypted = await readFile(TOKEN_FILE_PATH, 'utf-8');
38
+ const decrypted = decrypt(encrypted, encryptionKey);
39
+ currentTokens = JSON.parse(decrypted);
40
+ }
41
+ catch {
42
+ // File doesn't exist or decryption failed, start fresh
43
+ currentTokens = null;
44
+ }
45
+ },
46
+ };
47
+ return store;
48
+ }
49
+ function deriveKey(password, salt) {
50
+ return scryptSync(password, salt, 32);
51
+ }
52
+ function encrypt(plaintext, password) {
53
+ const salt = randomBytes(16);
54
+ const key = deriveKey(password, salt);
55
+ const iv = randomBytes(12);
56
+ const cipher = createCipheriv(ALGORITHM, key, iv);
57
+ let encrypted = cipher.update(plaintext, 'utf8', 'hex');
58
+ encrypted += cipher.final('hex');
59
+ const authTag = cipher.getAuthTag();
60
+ // Format: salt:iv:authTag:encrypted (all hex)
61
+ return [
62
+ salt.toString('hex'),
63
+ iv.toString('hex'),
64
+ authTag.toString('hex'),
65
+ encrypted,
66
+ ].join(':');
67
+ }
68
+ function decrypt(ciphertext, password) {
69
+ const parts = ciphertext.split(':');
70
+ if (parts.length !== 4) {
71
+ throw new Error('Invalid encrypted data format');
72
+ }
73
+ const [saltHex, ivHex, authTagHex, encrypted] = parts;
74
+ const salt = Buffer.from(saltHex, 'hex');
75
+ const iv = Buffer.from(ivHex, 'hex');
76
+ const authTag = Buffer.from(authTagHex, 'hex');
77
+ const key = deriveKey(password, salt);
78
+ const decipher = createDecipheriv(ALGORITHM, key, iv);
79
+ decipher.setAuthTag(authTag);
80
+ let decrypted = decipher.update(encrypted, 'hex', 'utf8');
81
+ decrypted += decipher.final('utf8');
82
+ return decrypted;
83
+ }
84
+ //# sourceMappingURL=token-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-store.js","sourceRoot":"","sources":["../../src/auth/token-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ import { z } from 'zod';
2
+ declare const configSchema: z.ZodObject<{
3
+ freeagent: z.ZodObject<{
4
+ clientId: z.ZodString;
5
+ clientSecret: z.ZodString;
6
+ redirectUri: z.ZodString;
7
+ environment: z.ZodDefault<z.ZodEnum<["sandbox", "production"]>>;
8
+ }, "strip", z.ZodTypeAny, {
9
+ clientId: string;
10
+ clientSecret: string;
11
+ redirectUri: string;
12
+ environment: "sandbox" | "production";
13
+ }, {
14
+ clientId: string;
15
+ clientSecret: string;
16
+ redirectUri: string;
17
+ environment?: "sandbox" | "production" | undefined;
18
+ }>;
19
+ server: z.ZodObject<{
20
+ port: z.ZodDefault<z.ZodNumber>;
21
+ logLevel: z.ZodDefault<z.ZodEnum<["debug", "info", "warn", "error"]>>;
22
+ }, "strip", z.ZodTypeAny, {
23
+ port: number;
24
+ logLevel: "debug" | "info" | "warn" | "error";
25
+ }, {
26
+ port?: number | undefined;
27
+ logLevel?: "debug" | "info" | "warn" | "error" | undefined;
28
+ }>;
29
+ tokenEncryptionKey: z.ZodOptional<z.ZodString>;
30
+ }, "strip", z.ZodTypeAny, {
31
+ freeagent: {
32
+ clientId: string;
33
+ clientSecret: string;
34
+ redirectUri: string;
35
+ environment: "sandbox" | "production";
36
+ };
37
+ server: {
38
+ port: number;
39
+ logLevel: "debug" | "info" | "warn" | "error";
40
+ };
41
+ tokenEncryptionKey?: string | undefined;
42
+ }, {
43
+ freeagent: {
44
+ clientId: string;
45
+ clientSecret: string;
46
+ redirectUri: string;
47
+ environment?: "sandbox" | "production" | undefined;
48
+ };
49
+ server: {
50
+ port?: number | undefined;
51
+ logLevel?: "debug" | "info" | "warn" | "error" | undefined;
52
+ };
53
+ tokenEncryptionKey?: string | undefined;
54
+ }>;
55
+ export type Config = z.infer<typeof configSchema>;
56
+ export declare const config: {
57
+ freeagent: {
58
+ clientId: string;
59
+ clientSecret: string;
60
+ redirectUri: string;
61
+ environment: "sandbox" | "production";
62
+ };
63
+ server: {
64
+ port: number;
65
+ logLevel: "debug" | "info" | "warn" | "error";
66
+ };
67
+ tokenEncryptionKey?: string | undefined;
68
+ };
69
+ export declare const FREEAGENT_API_BASE: string;
70
+ export declare const FREEAGENT_AUTH_URL: string;
71
+ export declare const FREEAGENT_TOKEN_URL: string;
72
+ export {};
73
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAYhB,CAAC;AAEH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AA2BlD,eAAO,MAAM,MAAM;;;;;;;;;;;;CAAe,CAAC;AAEnC,eAAO,MAAM,kBAAkB,QAGa,CAAC;AAE7C,eAAO,MAAM,kBAAkB,QAGyB,CAAC;AAEzD,eAAO,MAAM,mBAAmB,QAG2B,CAAC"}
package/dist/config.js ADDED
@@ -0,0 +1,46 @@
1
+ import { z } from 'zod';
2
+ const configSchema = z.object({
3
+ freeagent: z.object({
4
+ clientId: z.string().min(1, 'FREEAGENT_CLIENT_ID is required'),
5
+ clientSecret: z.string().min(1, 'FREEAGENT_CLIENT_SECRET is required'),
6
+ redirectUri: z.string().url('FREEAGENT_REDIRECT_URI must be a valid URL'),
7
+ environment: z.enum(['sandbox', 'production']).default('sandbox'),
8
+ }),
9
+ server: z.object({
10
+ port: z.number().int().positive().default(3000),
11
+ logLevel: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
12
+ }),
13
+ tokenEncryptionKey: z.string().length(64).optional(), // 32-byte hex
14
+ });
15
+ function loadConfig() {
16
+ const rawConfig = {
17
+ freeagent: {
18
+ clientId: process.env['FREEAGENT_CLIENT_ID'] ?? '',
19
+ clientSecret: process.env['FREEAGENT_CLIENT_SECRET'] ?? '',
20
+ redirectUri: process.env['FREEAGENT_REDIRECT_URI'] ?? 'http://localhost:3000/callback',
21
+ environment: process.env['FREEAGENT_ENVIRONMENT'] ?? 'sandbox',
22
+ },
23
+ server: {
24
+ port: parseInt(process.env['PORT'] ?? '3000', 10),
25
+ logLevel: process.env['LOG_LEVEL'] ?? 'info',
26
+ },
27
+ tokenEncryptionKey: process.env['TOKEN_ENCRYPTION_KEY'],
28
+ };
29
+ const result = configSchema.safeParse(rawConfig);
30
+ if (!result.success) {
31
+ const errors = result.error.errors.map((e) => `${e.path.join('.')}: ${e.message}`).join('\n');
32
+ throw new Error(`Configuration validation failed:\n${errors}`);
33
+ }
34
+ return result.data;
35
+ }
36
+ export const config = loadConfig();
37
+ export const FREEAGENT_API_BASE = config.freeagent.environment === 'production'
38
+ ? 'https://api.freeagent.com/v2'
39
+ : 'https://api.sandbox.freeagent.com/v2';
40
+ export const FREEAGENT_AUTH_URL = config.freeagent.environment === 'production'
41
+ ? 'https://api.freeagent.com/v2/approve_app'
42
+ : 'https://api.sandbox.freeagent.com/v2/approve_app';
43
+ export const FREEAGENT_TOKEN_URL = config.freeagent.environment === 'production'
44
+ ? 'https://api.freeagent.com/v2/token_endpoint'
45
+ : 'https://api.sandbox.freeagent.com/v2/token_endpoint';
46
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env node
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { createFreeAgentMcpServer } from './server.js';
4
+ import { createTokenStore } from './auth/token-store.js';
5
+ import { config } from './config.js';
6
+ async function main() {
7
+ // Create server
8
+ const { server, getAuthorizationUrl, handleAuthorizationCode, isAuthenticated } = createFreeAgentMcpServer();
9
+ // Load persisted tokens if available
10
+ const tokenStore = createTokenStore(config.tokenEncryptionKey);
11
+ await tokenStore.load();
12
+ // Log startup info
13
+ console.error('FreeAgent MCP Server starting...');
14
+ console.error(`Environment: ${config.freeagent.environment}`);
15
+ if (!isAuthenticated()) {
16
+ console.error('');
17
+ console.error('Not authenticated. To authorize, visit:');
18
+ console.error(getAuthorizationUrl());
19
+ console.error('');
20
+ console.error('After authorization, provide the code via the auth_callback tool.');
21
+ }
22
+ else {
23
+ console.error('Authenticated and ready.');
24
+ }
25
+ // Start stdio transport
26
+ const transport = new StdioServerTransport();
27
+ await server.connect(transport);
28
+ // Handle shutdown
29
+ process.on('SIGINT', async () => {
30
+ console.error('Shutting down...');
31
+ await server.close();
32
+ process.exit(0);
33
+ });
34
+ process.on('SIGTERM', async () => {
35
+ console.error('Shutting down...');
36
+ await server.close();
37
+ process.exit(0);
38
+ });
39
+ }
40
+ main().catch((error) => {
41
+ console.error('Fatal error:', error);
42
+ process.exit(1);
43
+ });
44
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,KAAK,UAAU,IAAI;IACjB,gBAAgB;IAChB,MAAM,EAAE,MAAM,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,eAAe,EAAE,GAC7E,wBAAwB,EAAE,CAAC;IAE7B,qCAAqC;IACrC,MAAM,UAAU,GAAG,gBAAgB,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;IAC/D,MAAM,UAAU,CAAC,IAAI,EAAE,CAAC;IAExB,mBAAmB;IACnB,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;IAClD,OAAO,CAAC,KAAK,CAAC,gBAAgB,MAAM,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC;IAE9D,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;QACvB,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;QACzD,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,CAAC,CAAC;QACrC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,mEAAmE,CAAC,CAAC;IACrF,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC5C,CAAC;IAED,wBAAwB;IACxB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,kBAAkB;IAClB,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;QAC9B,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAClC,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;QAC/B,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAClC,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { GetPromptResult } from '@modelcontextprotocol/sdk/types.js';
2
+ export declare const cashFlowForecastPrompt: {
3
+ name: string;
4
+ description: string;
5
+ arguments: {
6
+ name: string;
7
+ description: string;
8
+ required: boolean;
9
+ }[];
10
+ };
11
+ export declare function getCashFlowForecastMessages(days: string): GetPromptResult;
12
+ //# sourceMappingURL=cash-flow-forecast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cash-flow-forecast.d.ts","sourceRoot":"","sources":["../../src/prompts/cash-flow-forecast.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAiB,MAAM,oCAAoC,CAAC;AAEzF,eAAO,MAAM,sBAAsB;;;;;;;;CAUlC,CAAC;AAEF,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAoFzE"}
@@ -0,0 +1,93 @@
1
+ export const cashFlowForecastPrompt = {
2
+ name: 'cash_flow_forecast',
3
+ description: 'Project cash position for the next 30, 60, or 90 days',
4
+ arguments: [
5
+ {
6
+ name: 'days',
7
+ description: 'Forecast period in days (30, 60, or 90)',
8
+ required: true,
9
+ },
10
+ ],
11
+ };
12
+ export function getCashFlowForecastMessages(days) {
13
+ const daysNum = parseInt(days, 10);
14
+ const today = new Date();
15
+ const todayStr = today.toISOString().split('T')[0];
16
+ const endDate = new Date(today);
17
+ endDate.setDate(endDate.getDate() + daysNum);
18
+ const endDateStr = endDate.toISOString().split('T')[0];
19
+ // Look back 90 days for historical context
20
+ const lookbackDate = new Date(today);
21
+ lookbackDate.setDate(lookbackDate.getDate() - 90);
22
+ const lookbackStr = lookbackDate.toISOString().split('T')[0];
23
+ const messages = [
24
+ {
25
+ role: 'user',
26
+ content: {
27
+ type: 'text',
28
+ text: `Create a ${daysNum}-day cash flow forecast. Analyze:
29
+
30
+ 1. Current bank balances
31
+ 2. Expected income from:
32
+ - Open invoices (by due date)
33
+ - Recurring revenue patterns
34
+ 3. Expected outgoings from:
35
+ - Upcoming bills
36
+ - Recurring expenses
37
+ 4. Project cash position week by week
38
+ 5. Highlight any potential shortfalls
39
+
40
+ Provide a clear summary with key dates to watch.`,
41
+ },
42
+ },
43
+ {
44
+ role: 'user',
45
+ content: {
46
+ type: 'resource',
47
+ resource: {
48
+ uri: 'freeagent://bank_accounts',
49
+ mimeType: 'application/json',
50
+ text: 'Current bank account balances',
51
+ },
52
+ },
53
+ },
54
+ {
55
+ role: 'user',
56
+ content: {
57
+ type: 'resource',
58
+ resource: {
59
+ uri: 'freeagent://invoices?view=recent_open_or_overdue',
60
+ mimeType: 'application/json',
61
+ text: 'Open invoices (expected income)',
62
+ },
63
+ },
64
+ },
65
+ {
66
+ role: 'user',
67
+ content: {
68
+ type: 'resource',
69
+ resource: {
70
+ uri: 'freeagent://bills?view=recent_open_or_overdue',
71
+ mimeType: 'application/json',
72
+ text: 'Open bills (expected outgoings)',
73
+ },
74
+ },
75
+ },
76
+ {
77
+ role: 'user',
78
+ content: {
79
+ type: 'resource',
80
+ resource: {
81
+ uri: `freeagent://expenses?from_date=${lookbackStr}&to_date=${todayStr}`,
82
+ mimeType: 'application/json',
83
+ text: 'Recent expenses for pattern analysis',
84
+ },
85
+ },
86
+ },
87
+ ];
88
+ return {
89
+ description: `${daysNum}-day cash flow forecast`,
90
+ messages,
91
+ };
92
+ }
93
+ //# sourceMappingURL=cash-flow-forecast.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cash-flow-forecast.js","sourceRoot":"","sources":["../../src/prompts/cash-flow-forecast.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EAAE,uDAAuD;IACpE,SAAS,EAAE;QACT;YACE,IAAI,EAAE,MAAM;YACZ,WAAW,EAAE,yCAAyC;YACtD,QAAQ,EAAE,IAAI;SACf;KACF;CACF,CAAC;AAEF,MAAM,UAAU,2BAA2B,CAAC,IAAY;IACtD,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC;IACzB,MAAM,QAAQ,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAEnD,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;IAChC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC;IAC7C,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAEvD,2CAA2C;IAC3C,MAAM,YAAY,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,YAAY,CAAC,OAAO,CAAC,YAAY,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;IAClD,MAAM,WAAW,GAAG,YAAY,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAE7D,MAAM,QAAQ,GAAoB;QAChC;YACE,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE;gBACP,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,YAAY,OAAO;;;;;;;;;;;;iDAYgB;aAC1C;SACF;QACD;YACE,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE;gBACP,IAAI,EAAE,UAAU;gBAChB,QAAQ,EAAE;oBACR,GAAG,EAAE,2BAA2B;oBAChC,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,+BAA+B;iBACtC;aACF;SACF;QACD;YACE,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE;gBACP,IAAI,EAAE,UAAU;gBAChB,QAAQ,EAAE;oBACR,GAAG,EAAE,kDAAkD;oBACvD,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,iCAAiC;iBACxC;aACF;SACF;QACD;YACE,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE;gBACP,IAAI,EAAE,UAAU;gBAChB,QAAQ,EAAE;oBACR,GAAG,EAAE,+CAA+C;oBACpD,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,iCAAiC;iBACxC;aACF;SACF;QACD;YACE,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE;gBACP,IAAI,EAAE,UAAU;gBAChB,QAAQ,EAAE;oBACR,GAAG,EAAE,kCAAkC,WAAW,YAAY,QAAQ,EAAE;oBACxE,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,sCAAsC;iBAC7C;aACF;SACF;KACF,CAAC;IAEF,OAAO;QACL,WAAW,EAAE,GAAG,OAAO,yBAAyB;QAChD,QAAQ;KACT,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ export { monthlyExpenseSummaryPrompt, getMonthlyExpenseSummaryMessages, } from './monthly-expense-summary.js';
2
+ export { invoiceFromDescriptionPrompt, getInvoiceFromDescriptionMessages, } from './invoice-from-description.js';
3
+ export { cashFlowForecastPrompt, getCashFlowForecastMessages, } from './cash-flow-forecast.js';
4
+ export { overdueInvoiceFollowupPrompt, getOverdueInvoiceFollowupMessages, } from './overdue-invoice-followup.js';
5
+ export { transactionCategorizationPrompt, getTransactionCategorizationMessages, } from './transaction-categorization.js';
6
+ export { projectProfitabilityPrompt, getProjectProfitabilityMessages, } from './project-profitability.js';
7
+ export { quarterlyTaxEstimatePrompt, getQuarterlyTaxEstimateMessages, } from './quarterly-tax-estimate.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,2BAA2B,EAC3B,gCAAgC,GACjC,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,4BAA4B,EAC5B,iCAAiC,GAClC,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EACL,sBAAsB,EACtB,2BAA2B,GAC5B,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,4BAA4B,EAC5B,iCAAiC,GAClC,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EACL,+BAA+B,EAC/B,oCAAoC,GACrC,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EACL,0BAA0B,EAC1B,+BAA+B,GAChC,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,0BAA0B,EAC1B,+BAA+B,GAChC,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,8 @@
1
+ export { monthlyExpenseSummaryPrompt, getMonthlyExpenseSummaryMessages, } from './monthly-expense-summary.js';
2
+ export { invoiceFromDescriptionPrompt, getInvoiceFromDescriptionMessages, } from './invoice-from-description.js';
3
+ export { cashFlowForecastPrompt, getCashFlowForecastMessages, } from './cash-flow-forecast.js';
4
+ export { overdueInvoiceFollowupPrompt, getOverdueInvoiceFollowupMessages, } from './overdue-invoice-followup.js';
5
+ export { transactionCategorizationPrompt, getTransactionCategorizationMessages, } from './transaction-categorization.js';
6
+ export { projectProfitabilityPrompt, getProjectProfitabilityMessages, } from './project-profitability.js';
7
+ export { quarterlyTaxEstimatePrompt, getQuarterlyTaxEstimateMessages, } from './quarterly-tax-estimate.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,2BAA2B,EAC3B,gCAAgC,GACjC,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,4BAA4B,EAC5B,iCAAiC,GAClC,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EACL,sBAAsB,EACtB,2BAA2B,GAC5B,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,4BAA4B,EAC5B,iCAAiC,GAClC,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EACL,+BAA+B,EAC/B,oCAAoC,GACrC,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EACL,0BAA0B,EAC1B,+BAA+B,GAChC,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,0BAA0B,EAC1B,+BAA+B,GAChC,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { GetPromptResult } from '@modelcontextprotocol/sdk/types.js';
2
+ export declare const invoiceFromDescriptionPrompt: {
3
+ name: string;
4
+ description: string;
5
+ arguments: {
6
+ name: string;
7
+ description: string;
8
+ required: boolean;
9
+ }[];
10
+ };
11
+ export declare function getInvoiceFromDescriptionMessages(description: string): GetPromptResult;
12
+ //# sourceMappingURL=invoice-from-description.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoice-from-description.d.ts","sourceRoot":"","sources":["../../src/prompts/invoice-from-description.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAiB,MAAM,oCAAoC,CAAC;AAEzF,eAAO,MAAM,4BAA4B;;;;;;;;CAUxC,CAAC;AAEF,wBAAgB,iCAAiC,CAC/C,WAAW,EAAE,MAAM,GAClB,eAAe,CAqCjB"}
@@ -0,0 +1,49 @@
1
+ export const invoiceFromDescriptionPrompt = {
2
+ name: 'invoice_from_description',
3
+ description: 'Create an invoice from a natural language description',
4
+ arguments: [
5
+ {
6
+ name: 'description',
7
+ description: 'Natural language description of the invoice',
8
+ required: true,
9
+ },
10
+ ],
11
+ };
12
+ export function getInvoiceFromDescriptionMessages(description) {
13
+ const messages = [
14
+ {
15
+ role: 'user',
16
+ content: {
17
+ type: 'text',
18
+ text: `Parse this invoice description and create an invoice:
19
+
20
+ "${description}"
21
+
22
+ Steps:
23
+ 1. Identify the contact (search contacts if needed)
24
+ 2. Extract line items with quantities and rates
25
+ 3. Determine payment terms
26
+ 4. Use the create_invoice tool with extracted data
27
+ 5. Confirm creation with me before sending
28
+
29
+ Please start by looking up the contacts to find the correct recipient.`,
30
+ },
31
+ },
32
+ {
33
+ role: 'user',
34
+ content: {
35
+ type: 'resource',
36
+ resource: {
37
+ uri: 'freeagent://contacts?view=active',
38
+ mimeType: 'application/json',
39
+ text: 'Active contacts for matching',
40
+ },
41
+ },
42
+ },
43
+ ];
44
+ return {
45
+ description: 'Create invoice from natural language description',
46
+ messages,
47
+ };
48
+ }
49
+ //# sourceMappingURL=invoice-from-description.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoice-from-description.js","sourceRoot":"","sources":["../../src/prompts/invoice-from-description.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,4BAA4B,GAAG;IAC1C,IAAI,EAAE,0BAA0B;IAChC,WAAW,EAAE,uDAAuD;IACpE,SAAS,EAAE;QACT;YACE,IAAI,EAAE,aAAa;YACnB,WAAW,EAAE,6CAA6C;YAC1D,QAAQ,EAAE,IAAI;SACf;KACF;CACF,CAAC;AAEF,MAAM,UAAU,iCAAiC,CAC/C,WAAmB;IAEnB,MAAM,QAAQ,GAAoB;QAChC;YACE,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE;gBACP,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE;;GAEX,WAAW;;;;;;;;;uEASyD;aAChE;SACF;QACD;YACE,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE;gBACP,IAAI,EAAE,UAAU;gBAChB,QAAQ,EAAE;oBACR,GAAG,EAAE,kCAAkC;oBACvC,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,8BAA8B;iBACrC;aACF;SACF;KACF,CAAC;IAEF,OAAO;QACL,WAAW,EAAE,kDAAkD;QAC/D,QAAQ;KACT,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { GetPromptResult } from '@modelcontextprotocol/sdk/types.js';
2
+ export declare const monthlyExpenseSummaryPrompt: {
3
+ name: string;
4
+ description: string;
5
+ arguments: {
6
+ name: string;
7
+ description: string;
8
+ required: boolean;
9
+ }[];
10
+ };
11
+ export declare function getMonthlyExpenseSummaryMessages(month: string, year: string): GetPromptResult;
12
+ //# sourceMappingURL=monthly-expense-summary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monthly-expense-summary.d.ts","sourceRoot":"","sources":["../../src/prompts/monthly-expense-summary.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAiB,MAAM,oCAAoC,CAAC;AAEzF,eAAO,MAAM,2BAA2B;;;;;;;;CAevC,CAAC;AAEF,wBAAgB,gCAAgC,CAC9C,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,GACX,eAAe,CAsEjB"}