@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.
- package/README.md +187 -0
- package/dist/api/freeagent-client.d.ts +12 -0
- package/dist/api/freeagent-client.d.ts.map +1 -0
- package/dist/api/freeagent-client.js +114 -0
- package/dist/api/freeagent-client.js.map +1 -0
- package/dist/api/index.d.ts +7 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +4 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/rate-limiter.d.ts +15 -0
- package/dist/api/rate-limiter.d.ts.map +1 -0
- package/dist/api/rate-limiter.js +62 -0
- package/dist/api/rate-limiter.js.map +1 -0
- package/dist/api/retry-handler.d.ts +14 -0
- package/dist/api/retry-handler.d.ts.map +1 -0
- package/dist/api/retry-handler.js +49 -0
- package/dist/api/retry-handler.js.map +1 -0
- package/dist/auth/index.d.ts +7 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +4 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/oauth.d.ts +16 -0
- package/dist/auth/oauth.d.ts.map +1 -0
- package/dist/auth/oauth.js +64 -0
- package/dist/auth/oauth.js.map +1 -0
- package/dist/auth/token-manager.d.ts +10 -0
- package/dist/auth/token-manager.d.ts.map +1 -0
- package/dist/auth/token-manager.js +71 -0
- package/dist/auth/token-manager.js.map +1 -0
- package/dist/auth/token-store.d.ts +10 -0
- package/dist/auth/token-store.d.ts.map +1 -0
- package/dist/auth/token-store.js +84 -0
- package/dist/auth/token-store.js.map +1 -0
- package/dist/config.d.ts +73 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +46 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts/cash-flow-forecast.d.ts +12 -0
- package/dist/prompts/cash-flow-forecast.d.ts.map +1 -0
- package/dist/prompts/cash-flow-forecast.js +93 -0
- package/dist/prompts/cash-flow-forecast.js.map +1 -0
- package/dist/prompts/index.d.ts +8 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +8 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/invoice-from-description.d.ts +12 -0
- package/dist/prompts/invoice-from-description.d.ts.map +1 -0
- package/dist/prompts/invoice-from-description.js +49 -0
- package/dist/prompts/invoice-from-description.js.map +1 -0
- package/dist/prompts/monthly-expense-summary.d.ts +12 -0
- package/dist/prompts/monthly-expense-summary.d.ts.map +1 -0
- package/dist/prompts/monthly-expense-summary.js +84 -0
- package/dist/prompts/monthly-expense-summary.js.map +1 -0
- package/dist/prompts/overdue-invoice-followup.d.ts +12 -0
- package/dist/prompts/overdue-invoice-followup.d.ts.map +1 -0
- package/dist/prompts/overdue-invoice-followup.js +63 -0
- package/dist/prompts/overdue-invoice-followup.js.map +1 -0
- package/dist/prompts/project-profitability.d.ts +12 -0
- package/dist/prompts/project-profitability.d.ts.map +1 -0
- package/dist/prompts/project-profitability.js +103 -0
- package/dist/prompts/project-profitability.js.map +1 -0
- package/dist/prompts/quarterly-tax-estimate.d.ts +12 -0
- package/dist/prompts/quarterly-tax-estimate.d.ts.map +1 -0
- package/dist/prompts/quarterly-tax-estimate.js +132 -0
- package/dist/prompts/quarterly-tax-estimate.js.map +1 -0
- package/dist/prompts/transaction-categorization.d.ts +12 -0
- package/dist/prompts/transaction-categorization.d.ts.map +1 -0
- package/dist/prompts/transaction-categorization.js +81 -0
- package/dist/prompts/transaction-categorization.js.map +1 -0
- package/dist/resources/bank-accounts.d.ts +8 -0
- package/dist/resources/bank-accounts.d.ts.map +1 -0
- package/dist/resources/bank-accounts.js +34 -0
- package/dist/resources/bank-accounts.js.map +1 -0
- package/dist/resources/bank-transactions.d.ts +11 -0
- package/dist/resources/bank-transactions.d.ts.map +1 -0
- package/dist/resources/bank-transactions.js +34 -0
- package/dist/resources/bank-transactions.js.map +1 -0
- package/dist/resources/bills.d.ts +13 -0
- package/dist/resources/bills.d.ts.map +1 -0
- package/dist/resources/bills.js +38 -0
- package/dist/resources/bills.js.map +1 -0
- package/dist/resources/categories.d.ts +4 -0
- package/dist/resources/categories.d.ts.map +1 -0
- package/dist/resources/categories.js +21 -0
- package/dist/resources/categories.js.map +1 -0
- package/dist/resources/company.d.ts +3 -0
- package/dist/resources/company.d.ts.map +1 -0
- package/dist/resources/company.js +12 -0
- package/dist/resources/company.js.map +1 -0
- package/dist/resources/contacts.d.ts +9 -0
- package/dist/resources/contacts.d.ts.map +1 -0
- package/dist/resources/contacts.js +37 -0
- package/dist/resources/contacts.js.map +1 -0
- package/dist/resources/expenses.d.ts +12 -0
- package/dist/resources/expenses.d.ts.map +1 -0
- package/dist/resources/expenses.js +36 -0
- package/dist/resources/expenses.js.map +1 -0
- package/dist/resources/index.d.ts +20 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +12 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/invoices.d.ts +14 -0
- package/dist/resources/invoices.d.ts.map +1 -0
- package/dist/resources/invoices.js +40 -0
- package/dist/resources/invoices.js.map +1 -0
- package/dist/resources/projects.d.ts +10 -0
- package/dist/resources/projects.d.ts.map +1 -0
- package/dist/resources/projects.js +39 -0
- package/dist/resources/projects.js.map +1 -0
- package/dist/resources/timeslips.d.ts +12 -0
- package/dist/resources/timeslips.d.ts.map +1 -0
- package/dist/resources/timeslips.js +36 -0
- package/dist/resources/timeslips.js.map +1 -0
- package/dist/resources/users.d.ts +5 -0
- package/dist/resources/users.d.ts.map +1 -0
- package/dist/resources/users.js +30 -0
- package/dist/resources/users.js.map +1 -0
- package/dist/server.d.ts +9 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +568 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/bank-tools.d.ts +112 -0
- package/dist/tools/bank-tools.d.ts.map +1 -0
- package/dist/tools/bank-tools.js +143 -0
- package/dist/tools/bank-tools.js.map +1 -0
- package/dist/tools/bill-tools.d.ts +129 -0
- package/dist/tools/bill-tools.d.ts.map +1 -0
- package/dist/tools/bill-tools.js +121 -0
- package/dist/tools/bill-tools.js.map +1 -0
- package/dist/tools/contact-tools.d.ts +147 -0
- package/dist/tools/contact-tools.d.ts.map +1 -0
- package/dist/tools/contact-tools.js +140 -0
- package/dist/tools/contact-tools.js.map +1 -0
- package/dist/tools/index.d.ts +13 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +13 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/invoice-tools.d.ts +171 -0
- package/dist/tools/invoice-tools.d.ts.map +1 -0
- package/dist/tools/invoice-tools.js +168 -0
- package/dist/tools/invoice-tools.js.map +1 -0
- package/dist/tools/project-tools.d.ts +117 -0
- package/dist/tools/project-tools.d.ts.map +1 -0
- package/dist/tools/project-tools.js +153 -0
- package/dist/tools/project-tools.js.map +1 -0
- package/dist/tools/query-tools.d.ts +91 -0
- package/dist/tools/query-tools.d.ts.map +1 -0
- package/dist/tools/query-tools.js +127 -0
- package/dist/tools/query-tools.js.map +1 -0
- package/dist/transformers/bank-transformer.d.ts +8 -0
- package/dist/transformers/bank-transformer.d.ts.map +1 -0
- package/dist/transformers/bank-transformer.js +46 -0
- package/dist/transformers/bank-transformer.js.map +1 -0
- package/dist/transformers/bill-transformer.d.ts +6 -0
- package/dist/transformers/bill-transformer.d.ts.map +1 -0
- package/dist/transformers/bill-transformer.js +34 -0
- package/dist/transformers/bill-transformer.js.map +1 -0
- package/dist/transformers/category-transformer.d.ts +5 -0
- package/dist/transformers/category-transformer.d.ts.map +1 -0
- package/dist/transformers/category-transformer.js +14 -0
- package/dist/transformers/category-transformer.js.map +1 -0
- package/dist/transformers/common.d.ts +7 -0
- package/dist/transformers/common.d.ts.map +1 -0
- package/dist/transformers/common.js +33 -0
- package/dist/transformers/common.js.map +1 -0
- package/dist/transformers/company-transformer.d.ts +4 -0
- package/dist/transformers/company-transformer.d.ts.map +1 -0
- package/dist/transformers/company-transformer.js +10 -0
- package/dist/transformers/company-transformer.js.map +1 -0
- package/dist/transformers/contact-transformer.d.ts +5 -0
- package/dist/transformers/contact-transformer.d.ts.map +1 -0
- package/dist/transformers/contact-transformer.js +18 -0
- package/dist/transformers/contact-transformer.js.map +1 -0
- package/dist/transformers/expense-transformer.d.ts +5 -0
- package/dist/transformers/expense-transformer.d.ts.map +1 -0
- package/dist/transformers/expense-transformer.js +19 -0
- package/dist/transformers/expense-transformer.js.map +1 -0
- package/dist/transformers/index.d.ts +11 -0
- package/dist/transformers/index.d.ts.map +1 -0
- package/dist/transformers/index.js +11 -0
- package/dist/transformers/index.js.map +1 -0
- package/dist/transformers/invoice-transformer.d.ts +6 -0
- package/dist/transformers/invoice-transformer.d.ts.map +1 -0
- package/dist/transformers/invoice-transformer.js +39 -0
- package/dist/transformers/invoice-transformer.js.map +1 -0
- package/dist/transformers/project-transformer.d.ts +9 -0
- package/dist/transformers/project-transformer.d.ts.map +1 -0
- package/dist/transformers/project-transformer.js +53 -0
- package/dist/transformers/project-transformer.js.map +1 -0
- package/dist/transformers/user-transformer.d.ts +5 -0
- package/dist/transformers/user-transformer.d.ts.map +1 -0
- package/dist/transformers/user-transformer.js +14 -0
- package/dist/transformers/user-transformer.js.map +1 -0
- package/dist/types/freeagent/index.d.ts +256 -0
- package/dist/types/freeagent/index.d.ts.map +1 -0
- package/dist/types/freeagent/index.js +3 -0
- package/dist/types/freeagent/index.js.map +1 -0
- package/dist/types/llm/index.d.ts +159 -0
- package/dist/types/llm/index.d.ts.map +1 -0
- package/dist/types/llm/index.js +3 -0
- package/dist/types/llm/index.js.map +1 -0
- package/dist/utils/error-handler.d.ts +11 -0
- package/dist/utils/error-handler.d.ts.map +1 -0
- package/dist/utils/error-handler.js +57 -0
- package/dist/utils/error-handler.js.map +1 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +5 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/sanitizer.d.ts +4 -0
- package/dist/utils/sanitizer.d.ts.map +1 -0
- package/dist/utils/sanitizer.js +42 -0
- package/dist/utils/sanitizer.js.map +1 -0
- package/dist/utils/validators.d.ts +19 -0
- package/dist/utils/validators.d.ts.map +1 -0
- package/dist/utils/validators.js +83 -0
- package/dist/utils/validators.js.map +1 -0
- package/dist/utils/zod-to-json-schema.d.ts +24 -0
- package/dist/utils/zod-to-json-schema.d.ts.map +1 -0
- package/dist/utils/zod-to-json-schema.js +141 -0
- package/dist/utils/zod-to-json-schema.js.map +1 -0
- 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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"}
|
package/dist/config.d.ts
ADDED
|
@@ -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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"}
|
package/dist/index.d.ts
ADDED
|
@@ -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"}
|