@warmio/mcp 7.0.1 → 9.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 +15 -10
- package/dist/config-paths.d.ts +2 -2
- package/dist/config-paths.js +4 -3
- package/dist/install.d.ts +2 -2
- package/dist/install.js +78 -74
- package/dist/schemas.d.ts +2 -1289
- package/dist/schemas.js +2 -248
- package/dist/server.d.ts +2 -1
- package/dist/server.js +43 -55
- package/dist/types.d.ts +1 -1
- package/dist/warm-api-client.d.ts +20 -183
- package/dist/warm-api-client.js +10 -5
- package/package.json +10 -2
package/dist/schemas.js
CHANGED
|
@@ -1,248 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const dateSchema = z.string().regex(/^\d{4}-\d{2}-\d{2}$/, 'Expected YYYY-MM-DD date.');
|
|
4
|
-
const dateTimeSchema = z.string().datetime({ offset: true });
|
|
5
|
-
export const emptyInputSchema = {};
|
|
6
|
-
export const automationInputSchema = z
|
|
7
|
-
.object({
|
|
8
|
-
body: z.record(z.unknown()).optional(),
|
|
9
|
-
params: z.record(z.string()).optional(),
|
|
10
|
-
})
|
|
11
|
-
.strict();
|
|
12
|
-
export const searchOperationsInputSchema = {
|
|
13
|
-
query: z.string().max(200).optional().describe('Words describing the action or data you need.'),
|
|
14
|
-
};
|
|
15
|
-
export const describeOperationInputSchema = {
|
|
16
|
-
operation_id: z.string().min(1),
|
|
17
|
-
input: automationInputSchema
|
|
18
|
-
.optional()
|
|
19
|
-
.describe('Exact intended input. Required to obtain approval for a write operation.'),
|
|
20
|
-
};
|
|
21
|
-
export const invokeOperationInputSchema = {
|
|
22
|
-
operation_id: z.string().min(1),
|
|
23
|
-
input: automationInputSchema.optional(),
|
|
24
|
-
approval_id: z
|
|
25
|
-
.string()
|
|
26
|
-
.uuid()
|
|
27
|
-
.optional()
|
|
28
|
-
.describe('Approval ID returned by describe_operation for the exact write input.'),
|
|
29
|
-
};
|
|
30
|
-
export const transactionIndexSchema = z
|
|
31
|
-
.object({
|
|
32
|
-
total: z.number().int().nonnegative(),
|
|
33
|
-
months: z.array(z
|
|
34
|
-
.object({
|
|
35
|
-
month: monthSchema,
|
|
36
|
-
count: z.number().int().nonnegative(),
|
|
37
|
-
})
|
|
38
|
-
.strict()),
|
|
39
|
-
})
|
|
40
|
-
.strict();
|
|
41
|
-
export const positionSchema = z
|
|
42
|
-
.object({
|
|
43
|
-
date: dateSchema.nullable(),
|
|
44
|
-
net_worth: z.number().finite().nullable(),
|
|
45
|
-
cash: z.number().finite().nullable(),
|
|
46
|
-
debt: z.number().finite().nullable(),
|
|
47
|
-
investments: z.number().finite().nullable(),
|
|
48
|
-
other_assets: z.number().finite().nullable(),
|
|
49
|
-
total_assets: z.number().finite().nullable(),
|
|
50
|
-
})
|
|
51
|
-
.strict();
|
|
52
|
-
export const accountSchema = z
|
|
53
|
-
.object({
|
|
54
|
-
id: z.string(),
|
|
55
|
-
name: z.string(),
|
|
56
|
-
type: z.enum(['depository', 'credit', 'loan', 'investment', 'brokerage', 'other']),
|
|
57
|
-
subtype: z.string().nullable(),
|
|
58
|
-
group: z.enum(['cash', 'debt', 'investments']).nullable(),
|
|
59
|
-
institution: z.string().nullable(),
|
|
60
|
-
mask: z.string().nullable(),
|
|
61
|
-
balance: z.number().finite().nullable(),
|
|
62
|
-
available: z.number().finite().nullable(),
|
|
63
|
-
currency: z.string().nullable(),
|
|
64
|
-
updated_at: dateTimeSchema.nullable(),
|
|
65
|
-
})
|
|
66
|
-
.strict();
|
|
67
|
-
export const statusSchema = z
|
|
68
|
-
.object({
|
|
69
|
-
position: positionSchema.nullable(),
|
|
70
|
-
accounts: z.array(accountSchema),
|
|
71
|
-
})
|
|
72
|
-
.strict();
|
|
73
|
-
export const recurringSchema = z
|
|
74
|
-
.object({
|
|
75
|
-
id: z.string(),
|
|
76
|
-
account_id: z.string().nullable(),
|
|
77
|
-
direction: z.enum(['inflow', 'outflow']).nullable(),
|
|
78
|
-
frequency: z
|
|
79
|
-
.enum(['WEEKLY', 'BIWEEKLY', 'MONTHLY', 'QUARTERLY', 'SEMI_ANNUALLY', 'ANNUALLY'])
|
|
80
|
-
.nullable(),
|
|
81
|
-
status: z.enum(['active', 'inactive', 'dismissed']).nullable(),
|
|
82
|
-
merchant: z.string().nullable(),
|
|
83
|
-
amount: z.number().finite().nullable(),
|
|
84
|
-
next_date: dateSchema.nullable(),
|
|
85
|
-
})
|
|
86
|
-
.strict();
|
|
87
|
-
export const budgetSchema = z
|
|
88
|
-
.object({
|
|
89
|
-
id: z.string(),
|
|
90
|
-
name: z.string(),
|
|
91
|
-
type: z.enum(['category', 'merchant']),
|
|
92
|
-
period: z.enum(['weekly', 'biweekly', 'monthly']),
|
|
93
|
-
status: z.enum(['under', 'warning', 'over']),
|
|
94
|
-
amount: z.number().finite(),
|
|
95
|
-
spent: z.number().finite(),
|
|
96
|
-
remaining: z.number().finite(),
|
|
97
|
-
used_percent: z.number().finite(),
|
|
98
|
-
})
|
|
99
|
-
.strict();
|
|
100
|
-
export const goalSchema = z
|
|
101
|
-
.object({
|
|
102
|
-
id: z.string(),
|
|
103
|
-
name: z.string(),
|
|
104
|
-
category: z.string(),
|
|
105
|
-
status: z.enum(['not_started', 'in_progress', 'on_track', 'behind', 'completed']),
|
|
106
|
-
target: z.number().finite(),
|
|
107
|
-
current: z.number().finite(),
|
|
108
|
-
progress_percent: z.number().finite(),
|
|
109
|
-
target_date: dateSchema.nullable(),
|
|
110
|
-
})
|
|
111
|
-
.strict();
|
|
112
|
-
export const snapshotSchema = z
|
|
113
|
-
.object({
|
|
114
|
-
date: dateSchema,
|
|
115
|
-
net_worth: z.number().finite().nullable(),
|
|
116
|
-
cash: z.number().finite().nullable(),
|
|
117
|
-
debt: z.number().finite().nullable(),
|
|
118
|
-
income: z.number().finite().nullable(),
|
|
119
|
-
expenses: z.number().finite().nullable(),
|
|
120
|
-
cash_flow: z.number().finite().nullable(),
|
|
121
|
-
savings_rate: z.number().finite().nullable(),
|
|
122
|
-
investments: z.number().finite().nullable(),
|
|
123
|
-
assets: z.number().finite().nullable(),
|
|
124
|
-
health_score: z.number().finite().nullable(),
|
|
125
|
-
})
|
|
126
|
-
.strict();
|
|
127
|
-
export const liabilitySchema = z
|
|
128
|
-
.object({
|
|
129
|
-
account_id: z.string().nullable(),
|
|
130
|
-
type: z.enum(['credit', 'student', 'mortgage', 'other']).nullable(),
|
|
131
|
-
balance: z.number().finite().nullable(),
|
|
132
|
-
minimum_payment: z.number().finite().nullable(),
|
|
133
|
-
due_date: dateSchema.nullable(),
|
|
134
|
-
interest_rate: z.number().finite().nullable(),
|
|
135
|
-
rate_type: z.enum(['fixed', 'variable']).nullable(),
|
|
136
|
-
overdue: z.boolean().nullable(),
|
|
137
|
-
})
|
|
138
|
-
.strict();
|
|
139
|
-
export const holdingSchema = z
|
|
140
|
-
.object({
|
|
141
|
-
account_id: z.string().nullable(),
|
|
142
|
-
symbol: z.string().nullable(),
|
|
143
|
-
name: z.string().nullable(),
|
|
144
|
-
type: z
|
|
145
|
-
.enum(['cash', 'derivative', 'equity', 'etf', 'fixed_income', 'mutual_fund', 'other'])
|
|
146
|
-
.nullable(),
|
|
147
|
-
quantity: z.number().finite().nullable(),
|
|
148
|
-
value: z.number().finite().nullable(),
|
|
149
|
-
cost_basis: z.number().finite().nullable(),
|
|
150
|
-
})
|
|
151
|
-
.strict();
|
|
152
|
-
export const healthSchema = z
|
|
153
|
-
.object({
|
|
154
|
-
score: z.number().finite(),
|
|
155
|
-
label: z.enum(['Needs Attention', 'Good', 'Strong']),
|
|
156
|
-
level: z.enum(['critical', 'poor', 'fair', 'good', 'strong']),
|
|
157
|
-
summary: z.string(),
|
|
158
|
-
data_completeness: z.number().finite(),
|
|
159
|
-
pillars: z
|
|
160
|
-
.object({
|
|
161
|
-
spend: z.number().finite().nullable(),
|
|
162
|
-
save: z.number().finite().nullable(),
|
|
163
|
-
borrow: z.number().finite().nullable(),
|
|
164
|
-
build: z.number().finite().nullable(),
|
|
165
|
-
})
|
|
166
|
-
.strict()
|
|
167
|
-
.nullable(),
|
|
168
|
-
})
|
|
169
|
-
.strict();
|
|
170
|
-
export const financialContextSchema = z
|
|
171
|
-
.object({
|
|
172
|
-
version: z.literal('v1'),
|
|
173
|
-
updated_at: dateTimeSchema,
|
|
174
|
-
currency: z.literal('USD'),
|
|
175
|
-
status: statusSchema,
|
|
176
|
-
transactions: transactionIndexSchema,
|
|
177
|
-
recurring: z.array(recurringSchema),
|
|
178
|
-
budgets: z.array(budgetSchema),
|
|
179
|
-
goals: z.array(goalSchema),
|
|
180
|
-
snapshots: z.array(snapshotSchema),
|
|
181
|
-
liabilities: z.array(liabilitySchema),
|
|
182
|
-
holdings: z.array(holdingSchema),
|
|
183
|
-
health: healthSchema.nullable(),
|
|
184
|
-
})
|
|
185
|
-
.strict();
|
|
186
|
-
export const transactionSchema = z
|
|
187
|
-
.object({
|
|
188
|
-
id: z.string(),
|
|
189
|
-
account_id: z.string().nullable(),
|
|
190
|
-
date: dateSchema.nullable(),
|
|
191
|
-
amount: z.number().finite(),
|
|
192
|
-
merchant: z.string().nullable(),
|
|
193
|
-
name: z.string().nullable(),
|
|
194
|
-
category: z.string().nullable(),
|
|
195
|
-
subcategory: z.string().nullable(),
|
|
196
|
-
pending: z.boolean().nullable(),
|
|
197
|
-
currency: z.string().nullable(),
|
|
198
|
-
})
|
|
199
|
-
.strict();
|
|
200
|
-
export const transactionMonthSchema = z
|
|
201
|
-
.object({
|
|
202
|
-
month: monthSchema,
|
|
203
|
-
start_date: dateSchema,
|
|
204
|
-
end_date: dateSchema,
|
|
205
|
-
count: z.number().int().nonnegative(),
|
|
206
|
-
items: z.array(transactionSchema),
|
|
207
|
-
})
|
|
208
|
-
.strict();
|
|
209
|
-
export const latestTransactionsSchema = z
|
|
210
|
-
.object({
|
|
211
|
-
since: dateSchema,
|
|
212
|
-
window_days: z.literal(10),
|
|
213
|
-
count: z.number().int().nonnegative(),
|
|
214
|
-
items: z.array(transactionSchema),
|
|
215
|
-
})
|
|
216
|
-
.strict();
|
|
217
|
-
export const getTransactionsInputSchema = {
|
|
218
|
-
month: monthSchema
|
|
219
|
-
.optional()
|
|
220
|
-
.describe('Transaction month in YYYY-MM format. Mutually exclusive with latest. Months outside the covered range return an error.'),
|
|
221
|
-
latest: z
|
|
222
|
-
.boolean()
|
|
223
|
-
.optional()
|
|
224
|
-
.describe('When true, return the fixed 10-day latest window. Mutually exclusive with month. A bare call with no arguments defaults to latest: true.'),
|
|
225
|
-
};
|
|
226
|
-
export const financialContextMetaSchema = z
|
|
227
|
-
.object({
|
|
228
|
-
version: z.literal('v1'),
|
|
229
|
-
user_id: z.string(),
|
|
230
|
-
context_id: z.string(),
|
|
231
|
-
generated_at: dateTimeSchema,
|
|
232
|
-
updated_at: dateTimeSchema,
|
|
233
|
-
content_hash: z.string(),
|
|
234
|
-
byte_length: z.number().int().nonnegative(),
|
|
235
|
-
counts: z
|
|
236
|
-
.object({
|
|
237
|
-
accounts: z.number().int().nonnegative(),
|
|
238
|
-
transaction_months: z.number().int().nonnegative(),
|
|
239
|
-
transactions: z.number().int().nonnegative(),
|
|
240
|
-
snapshots: z.number().int().nonnegative(),
|
|
241
|
-
})
|
|
242
|
-
.strict(),
|
|
243
|
-
})
|
|
244
|
-
.strict();
|
|
245
|
-
export const verifyKeyOutputSchema = {
|
|
246
|
-
status: z.string(),
|
|
247
|
-
valid: z.boolean(),
|
|
248
|
-
};
|
|
1
|
+
export { automationInputSchema, financialContextAccountSchema as accountSchema, financialContextMetaSchema, financialContextSchema, financialContextTransactionSchema as transactionSchema, latestTransactionsSchema, transactionMonthSchema, } from '@warmio/contracts/schemas';
|
|
2
|
+
export { describeOperationMcpInputShape as describeOperationInputSchema, emptyMcpInputShape as emptyInputSchema, getTransactionsMcpInputShape as getTransactionsInputSchema, invokeOperationMcpInputShape as invokeOperationInputSchema, searchOperationsMcpInputShape as searchOperationsInputSchema, } from '@warmio/contracts/mcp';
|
package/dist/server.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import { type Implementation } from '@modelcontextprotocol/sdk/types.js';
|
|
3
|
+
import { type PrivateMcpMode } from '@warmio/contracts/mcp';
|
|
3
4
|
import { createWarmApiClient, type WarmApiClientOptions, getConfiguredApiKey, verifyWarmApiKey, WarmApiError } from './warm-api-client.js';
|
|
4
5
|
export { createWarmApiClient, getConfiguredApiKey, verifyWarmApiKey, WarmApiError };
|
|
5
6
|
export type { WarmApiClientOptions } from './warm-api-client.js';
|
|
@@ -7,7 +8,7 @@ export interface WarmServerOptions extends WarmApiClientOptions {
|
|
|
7
8
|
mode?: WarmServerMode;
|
|
8
9
|
serverInfo?: Implementation;
|
|
9
10
|
}
|
|
10
|
-
export type WarmServerMode =
|
|
11
|
+
export type WarmServerMode = PrivateMcpMode;
|
|
11
12
|
export declare const API_URL: string;
|
|
12
13
|
export declare const WARM_SERVER_INFO: {
|
|
13
14
|
name: string;
|
package/dist/server.js
CHANGED
|
@@ -3,8 +3,8 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
3
3
|
import { toJsonSchemaCompat } from '@modelcontextprotocol/sdk/server/zod-json-schema-compat.js';
|
|
4
4
|
import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from '@modelcontextprotocol/sdk/types.js';
|
|
5
5
|
import { z } from 'zod';
|
|
6
|
+
import { getTransactionsMcpInputSchema, normalizeGetTransactionsMcpInput, privateMcpToolDefinitions, } from '@warmio/contracts/mcp';
|
|
6
7
|
import { createWarmApiClient, getConfiguredApiKey, verifyWarmApiKey, WarmApiError, } from './warm-api-client.js';
|
|
7
|
-
import { describeOperationInputSchema, emptyInputSchema, getTransactionsInputSchema, invokeOperationInputSchema, searchOperationsInputSchema, } from './schemas.js';
|
|
8
8
|
export { createWarmApiClient, getConfiguredApiKey, verifyWarmApiKey, WarmApiError };
|
|
9
9
|
export const API_URL = process.env.WARM_API_URL || 'https://app.warm.io';
|
|
10
10
|
function getPackageVersion() {
|
|
@@ -29,8 +29,7 @@ function createStructuredToolResult(structuredContent, isError = false) {
|
|
|
29
29
|
text: JSON.stringify(structuredContent, null, 2),
|
|
30
30
|
},
|
|
31
31
|
],
|
|
32
|
-
...(isError ? { isError: true } : {}),
|
|
33
|
-
structuredContent,
|
|
32
|
+
...(isError ? { isError: true } : { structuredContent }),
|
|
34
33
|
};
|
|
35
34
|
}
|
|
36
35
|
function createToolFailure(error) {
|
|
@@ -48,69 +47,56 @@ function createToolFailure(error) {
|
|
|
48
47
|
},
|
|
49
48
|
}, true);
|
|
50
49
|
}
|
|
51
|
-
function
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
50
|
+
function getToolDefinition(name, mode) {
|
|
51
|
+
const definition = privateMcpToolDefinitions.find((candidate) => candidate.mode === mode && candidate.name === name);
|
|
52
|
+
if (!definition)
|
|
53
|
+
throw new Error(`Missing ${mode} MCP contract for ${name}.`);
|
|
54
|
+
return definition;
|
|
55
|
+
}
|
|
56
|
+
function getListToolOutputSchema(outputSchema) {
|
|
57
|
+
const schema = toJsonSchemaCompat(outputSchema, {
|
|
58
|
+
pipeStrategy: 'output',
|
|
59
|
+
strictUnions: true,
|
|
60
|
+
});
|
|
61
|
+
if (schema.type === 'object')
|
|
62
|
+
return schema;
|
|
63
|
+
if (Array.isArray(schema.anyOf) &&
|
|
64
|
+
schema.anyOf.length > 0 &&
|
|
65
|
+
schema.anyOf.every((candidate) => typeof candidate === 'object' && candidate !== null && candidate.type === 'object')) {
|
|
66
|
+
return { ...schema, type: 'object' };
|
|
63
67
|
}
|
|
64
|
-
|
|
68
|
+
return undefined;
|
|
65
69
|
}
|
|
66
70
|
export function registerWarmTools(server, options = {}, mode = 'context') {
|
|
67
71
|
const client = createWarmApiClient({ ...options, audience: mode });
|
|
68
72
|
const contextTools = [
|
|
69
73
|
{
|
|
70
|
-
|
|
71
|
-
description: 'Read-only compact FinancialContext JSON. Includes status.position, status.accounts, transaction index total/months, recurring, budgets, goals, snapshots, liabilities, holdings, and health. Transaction items are not inline; use get_transactions for items.',
|
|
74
|
+
...getToolDefinition('get_financial_context', 'context'),
|
|
72
75
|
handler: async () => await client.getFinancialContext(),
|
|
73
|
-
inputShape: emptyInputSchema,
|
|
74
|
-
name: 'get_financial_context',
|
|
75
76
|
},
|
|
76
77
|
{
|
|
77
|
-
|
|
78
|
-
description: 'Read-only transactions from the FinancialContext artifact. Pass exactly one selector: `month` in YYYY-MM format for a month page, or `latest: true` for the fixed latest window. A bare call with no arguments defaults to `latest: true`. The latest window is fixed at 10 days and is not caller-configurable. `month` and `latest` are mutually exclusive. Months outside the covered range return an error.',
|
|
78
|
+
...getToolDefinition('get_transactions', 'context'),
|
|
79
79
|
handler: async (args) => {
|
|
80
|
-
return await client.getTransactions(
|
|
80
|
+
return await client.getTransactions(normalizeGetTransactionsMcpInput(args));
|
|
81
81
|
},
|
|
82
|
-
inputShape: getTransactionsInputSchema,
|
|
83
|
-
name: 'get_transactions',
|
|
84
82
|
},
|
|
85
83
|
{
|
|
86
|
-
|
|
87
|
-
description: 'Read-only API key validation for the configured Warm account.',
|
|
84
|
+
...getToolDefinition('verify_key', 'context'),
|
|
88
85
|
handler: async () => await client.validateAudience(),
|
|
89
|
-
inputShape: emptyInputSchema,
|
|
90
|
-
name: 'verify_key',
|
|
91
86
|
},
|
|
92
87
|
];
|
|
93
88
|
const automationTools = [
|
|
94
89
|
{
|
|
95
|
-
|
|
96
|
-
description: 'Search the supported Warm operation catalog. Use this first to find the smallest matching operation.',
|
|
90
|
+
...getToolDefinition('search_operations', 'automation'),
|
|
97
91
|
handler: async (args) => await client.searchOperations(typeof args.query === 'string' ? args.query : undefined),
|
|
98
|
-
inputShape: searchOperationsInputSchema,
|
|
99
|
-
name: 'search_operations',
|
|
100
92
|
},
|
|
101
93
|
{
|
|
102
|
-
|
|
103
|
-
description: 'Describe one operation, including its input schema and risk. For write operations, pass the exact intended input to receive an approval with its ID, status, URL, and expiry.',
|
|
94
|
+
...getToolDefinition('describe_operation', 'automation'),
|
|
104
95
|
handler: async (args) => await client.describeOperation(args.operation_id, args.input),
|
|
105
|
-
inputShape: describeOperationInputSchema,
|
|
106
|
-
name: 'describe_operation',
|
|
107
96
|
},
|
|
108
97
|
{
|
|
109
|
-
|
|
110
|
-
description: 'Invoke one previously discovered Warm operation. Every write operation requires the approval_id returned for the exact same input by describe_operation.',
|
|
98
|
+
...getToolDefinition('invoke_operation', 'automation'),
|
|
111
99
|
handler: async (args) => await client.invokeOperation(args.operation_id, args.input, typeof args.approval_id === 'string' ? args.approval_id : undefined),
|
|
112
|
-
inputShape: invokeOperationInputSchema,
|
|
113
|
-
name: 'invoke_operation',
|
|
114
100
|
},
|
|
115
101
|
];
|
|
116
102
|
const tools = mode === 'automation' ? automationTools : contextTools;
|
|
@@ -120,15 +106,19 @@ export function registerWarmTools(server, options = {}, mode = 'context') {
|
|
|
120
106
|
},
|
|
121
107
|
});
|
|
122
108
|
server.server.setRequestHandler(ListToolsRequestSchema, () => ({
|
|
123
|
-
tools: tools.map((tool) =>
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
109
|
+
tools: tools.map((tool) => {
|
|
110
|
+
const outputSchema = getListToolOutputSchema(tool.outputSchema);
|
|
111
|
+
return {
|
|
112
|
+
description: tool.description,
|
|
113
|
+
annotations: tool.annotations,
|
|
114
|
+
inputSchema: toJsonSchemaCompat(z.object(tool.inputShape).strict(), {
|
|
115
|
+
pipeStrategy: 'input',
|
|
116
|
+
strictUnions: true,
|
|
117
|
+
}),
|
|
118
|
+
...(outputSchema ? { outputSchema } : {}),
|
|
119
|
+
name: tool.name,
|
|
120
|
+
};
|
|
121
|
+
}),
|
|
132
122
|
}));
|
|
133
123
|
server.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
134
124
|
const tool = tools.find((candidate) => candidate.name === request.params.name);
|
|
@@ -141,11 +131,9 @@ export function registerWarmTools(server, options = {}, mode = 'context') {
|
|
|
141
131
|
throw new McpError(ErrorCode.InvalidParams, `Invalid arguments for tool ${request.params.name}: ${parseResult.error.message}`);
|
|
142
132
|
}
|
|
143
133
|
if (tool.name === 'get_transactions') {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
catch (error) {
|
|
148
|
-
throw new McpError(ErrorCode.InvalidParams, error instanceof Error ? error.message : String(error));
|
|
134
|
+
const transactionInput = await getTransactionsMcpInputSchema.safeParseAsync(parseResult.data);
|
|
135
|
+
if (!transactionInput.success) {
|
|
136
|
+
throw new McpError(ErrorCode.InvalidParams, `Invalid arguments for tool ${request.params.name}: ${transactionInput.error.message}`);
|
|
149
137
|
}
|
|
150
138
|
}
|
|
151
139
|
try {
|
package/dist/types.d.ts
CHANGED
|
@@ -3,5 +3,5 @@ export declare const WARM_AUTOMATION_TOOL_NAMES: readonly ["search_operations",
|
|
|
3
3
|
export declare const WARM_TOOL_NAMES: readonly ["get_financial_context", "get_transactions", "verify_key", "search_operations", "describe_operation", "invoke_operation"];
|
|
4
4
|
export type WarmToolName = (typeof WARM_TOOL_NAMES)[number];
|
|
5
5
|
export type { Account, AutomationInput, AutomationOperation, AutomationOperationDescription, Budget, DescribeOperationOutput, FinancialContext, FinancialContextMeta, GetTransactionsInput, GetTransactionsOutput, Goal, Health, Holding, InvokeOperationOutput, LatestTransactions, Liability, Position, Recurring, Snapshot, Status, Transaction, TransactionIndex, TransactionMonth, VerifyKeyOutput, WarmApiClient, WarmApiClientOptions, } from './warm-api-client.js';
|
|
6
|
-
export type {
|
|
6
|
+
export type { PrivateMcpMode } from '@warmio/contracts/mcp';
|
|
7
7
|
export type { WarmServerOptions } from './server.js';
|
|
@@ -1,159 +1,25 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type PrivateMcpMode } from '@warmio/contracts/mcp';
|
|
2
|
+
import type { AutomationInput, AutomationOperation, FinancialContext, FinancialContextAccount, FinancialContextBudget, FinancialContextGoal, FinancialContextHealth, FinancialContextHolding, FinancialContextLiability, FinancialContextMeta, FinancialContextPosition, FinancialContextRecurring, FinancialContextSnapshot, FinancialContextStatus, FinancialContextTransaction, FinancialContextTransactionIndex, LatestTransactions, TransactionMonth } from '@warmio/contracts/types';
|
|
3
|
+
export type { AutomationInput, AutomationOperation, FinancialContext, FinancialContextMeta, LatestTransactions, TransactionMonth, } from '@warmio/contracts/types';
|
|
2
4
|
export interface WarmApiClientOptions {
|
|
3
|
-
audience?:
|
|
5
|
+
audience?: PrivateMcpMode;
|
|
4
6
|
apiKeyResolver?: () => string | null;
|
|
5
7
|
apiUrl?: string;
|
|
6
8
|
fetchImplementation?: typeof fetch;
|
|
7
9
|
requestTimeoutMs?: number;
|
|
8
10
|
}
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
export
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
investments: number | null;
|
|
22
|
-
other_assets: number | null;
|
|
23
|
-
total_assets: number | null;
|
|
24
|
-
}
|
|
25
|
-
export interface Account {
|
|
26
|
-
id: string;
|
|
27
|
-
name: string;
|
|
28
|
-
type: 'depository' | 'credit' | 'loan' | 'investment' | 'brokerage' | 'other';
|
|
29
|
-
subtype: string | null;
|
|
30
|
-
group: 'cash' | 'debt' | 'investments' | null;
|
|
31
|
-
institution: string | null;
|
|
32
|
-
mask: string | null;
|
|
33
|
-
balance: number | null;
|
|
34
|
-
available: number | null;
|
|
35
|
-
currency: string | null;
|
|
36
|
-
updated_at: string | null;
|
|
37
|
-
}
|
|
38
|
-
export interface Status {
|
|
39
|
-
position: Position | null;
|
|
40
|
-
accounts: Account[];
|
|
41
|
-
}
|
|
42
|
-
export interface Recurring {
|
|
43
|
-
id: string;
|
|
44
|
-
account_id: string | null;
|
|
45
|
-
direction: 'inflow' | 'outflow' | null;
|
|
46
|
-
frequency: 'WEEKLY' | 'BIWEEKLY' | 'MONTHLY' | 'QUARTERLY' | 'SEMI_ANNUALLY' | 'ANNUALLY' | null;
|
|
47
|
-
status: 'active' | 'inactive' | 'dismissed' | null;
|
|
48
|
-
merchant: string | null;
|
|
49
|
-
amount: number | null;
|
|
50
|
-
next_date: string | null;
|
|
51
|
-
}
|
|
52
|
-
export interface Budget {
|
|
53
|
-
id: string;
|
|
54
|
-
name: string;
|
|
55
|
-
type: 'category' | 'merchant';
|
|
56
|
-
period: 'weekly' | 'biweekly' | 'monthly';
|
|
57
|
-
status: 'under' | 'warning' | 'over';
|
|
58
|
-
amount: number;
|
|
59
|
-
spent: number;
|
|
60
|
-
remaining: number;
|
|
61
|
-
used_percent: number;
|
|
62
|
-
}
|
|
63
|
-
export interface Goal {
|
|
64
|
-
id: string;
|
|
65
|
-
name: string;
|
|
66
|
-
category: string;
|
|
67
|
-
status: 'not_started' | 'in_progress' | 'on_track' | 'behind' | 'completed';
|
|
68
|
-
target: number;
|
|
69
|
-
current: number;
|
|
70
|
-
progress_percent: number;
|
|
71
|
-
target_date: string | null;
|
|
72
|
-
}
|
|
73
|
-
export interface Snapshot {
|
|
74
|
-
date: string;
|
|
75
|
-
net_worth: number | null;
|
|
76
|
-
cash: number | null;
|
|
77
|
-
debt: number | null;
|
|
78
|
-
income: number | null;
|
|
79
|
-
expenses: number | null;
|
|
80
|
-
cash_flow: number | null;
|
|
81
|
-
savings_rate: number | null;
|
|
82
|
-
investments: number | null;
|
|
83
|
-
assets: number | null;
|
|
84
|
-
health_score: number | null;
|
|
85
|
-
}
|
|
86
|
-
export interface Liability {
|
|
87
|
-
account_id: string | null;
|
|
88
|
-
type: 'credit' | 'student' | 'mortgage' | 'other' | null;
|
|
89
|
-
balance: number | null;
|
|
90
|
-
minimum_payment: number | null;
|
|
91
|
-
due_date: string | null;
|
|
92
|
-
interest_rate: number | null;
|
|
93
|
-
rate_type: 'fixed' | 'variable' | null;
|
|
94
|
-
overdue: boolean | null;
|
|
95
|
-
}
|
|
96
|
-
export interface Holding {
|
|
97
|
-
account_id: string | null;
|
|
98
|
-
symbol: string | null;
|
|
99
|
-
name: string | null;
|
|
100
|
-
type: 'cash' | 'derivative' | 'equity' | 'etf' | 'fixed_income' | 'mutual_fund' | 'other' | null;
|
|
101
|
-
quantity: number | null;
|
|
102
|
-
value: number | null;
|
|
103
|
-
cost_basis: number | null;
|
|
104
|
-
}
|
|
105
|
-
export interface Health {
|
|
106
|
-
score: number;
|
|
107
|
-
label: 'Needs Attention' | 'Good' | 'Strong';
|
|
108
|
-
level: 'critical' | 'poor' | 'fair' | 'good' | 'strong';
|
|
109
|
-
summary: string;
|
|
110
|
-
data_completeness: number;
|
|
111
|
-
pillars: {
|
|
112
|
-
spend: number | null;
|
|
113
|
-
save: number | null;
|
|
114
|
-
borrow: number | null;
|
|
115
|
-
build: number | null;
|
|
116
|
-
} | null;
|
|
117
|
-
}
|
|
118
|
-
export interface FinancialContext extends Record<string, unknown> {
|
|
119
|
-
version: 'v1';
|
|
120
|
-
updated_at: string;
|
|
121
|
-
currency: 'USD';
|
|
122
|
-
status: Status;
|
|
123
|
-
transactions: TransactionIndex;
|
|
124
|
-
recurring: Recurring[];
|
|
125
|
-
budgets: Budget[];
|
|
126
|
-
goals: Goal[];
|
|
127
|
-
snapshots: Snapshot[];
|
|
128
|
-
liabilities: Liability[];
|
|
129
|
-
holdings: Holding[];
|
|
130
|
-
health: Health | null;
|
|
131
|
-
}
|
|
132
|
-
export interface Transaction {
|
|
133
|
-
id: string;
|
|
134
|
-
account_id: string | null;
|
|
135
|
-
date: string | null;
|
|
136
|
-
amount: number;
|
|
137
|
-
merchant: string | null;
|
|
138
|
-
name: string | null;
|
|
139
|
-
category: string | null;
|
|
140
|
-
subcategory: string | null;
|
|
141
|
-
pending: boolean | null;
|
|
142
|
-
currency: string | null;
|
|
143
|
-
}
|
|
144
|
-
export interface TransactionMonth extends Record<string, unknown> {
|
|
145
|
-
month: string;
|
|
146
|
-
start_date: string;
|
|
147
|
-
end_date: string;
|
|
148
|
-
count: number;
|
|
149
|
-
items: Transaction[];
|
|
150
|
-
}
|
|
151
|
-
export interface LatestTransactions extends Record<string, unknown> {
|
|
152
|
-
since: string;
|
|
153
|
-
window_days: 10;
|
|
154
|
-
count: number;
|
|
155
|
-
items: Transaction[];
|
|
156
|
-
}
|
|
11
|
+
export type Account = FinancialContextAccount;
|
|
12
|
+
export type Budget = FinancialContextBudget;
|
|
13
|
+
export type Goal = FinancialContextGoal;
|
|
14
|
+
export type Health = FinancialContextHealth;
|
|
15
|
+
export type Holding = FinancialContextHolding;
|
|
16
|
+
export type Liability = FinancialContextLiability;
|
|
17
|
+
export type Position = FinancialContextPosition;
|
|
18
|
+
export type Recurring = FinancialContextRecurring;
|
|
19
|
+
export type Snapshot = FinancialContextSnapshot;
|
|
20
|
+
export type Status = FinancialContextStatus;
|
|
21
|
+
export type Transaction = FinancialContextTransaction;
|
|
22
|
+
export type TransactionIndex = FinancialContextTransactionIndex;
|
|
157
23
|
export type GetTransactionsInput = {
|
|
158
24
|
month: string;
|
|
159
25
|
latest?: never;
|
|
@@ -162,42 +28,14 @@ export type GetTransactionsInput = {
|
|
|
162
28
|
month?: never;
|
|
163
29
|
};
|
|
164
30
|
export type GetTransactionsOutput = TransactionMonth | LatestTransactions;
|
|
165
|
-
export interface FinancialContextMeta extends Record<string, unknown> {
|
|
166
|
-
version: 'v1';
|
|
167
|
-
user_id: string;
|
|
168
|
-
context_id: string;
|
|
169
|
-
generated_at: string;
|
|
170
|
-
updated_at: string;
|
|
171
|
-
content_hash: string;
|
|
172
|
-
byte_length: number;
|
|
173
|
-
counts: {
|
|
174
|
-
accounts: number;
|
|
175
|
-
transaction_months: number;
|
|
176
|
-
transactions: number;
|
|
177
|
-
snapshots: number;
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
31
|
export interface VerifyKeyOutput extends Record<string, unknown> {
|
|
181
32
|
audience?: 'automation' | 'context' | 'oauth';
|
|
182
33
|
status: string;
|
|
183
34
|
valid: boolean;
|
|
184
35
|
}
|
|
185
|
-
export
|
|
186
|
-
confirmation_required: boolean;
|
|
187
|
-
description: string;
|
|
188
|
-
method: 'DELETE' | 'GET' | 'PATCH' | 'POST' | 'PUT';
|
|
189
|
-
operation_id: string;
|
|
190
|
-
path: string;
|
|
191
|
-
risk: Array<'read' | 'write' | 'destructive' | 'external_effect'>;
|
|
192
|
-
summary: string;
|
|
193
|
-
}
|
|
194
|
-
export interface AutomationInput {
|
|
195
|
-
body?: Record<string, unknown>;
|
|
196
|
-
params?: Record<string, string>;
|
|
197
|
-
}
|
|
198
|
-
export interface AutomationOperationDescription extends AutomationOperation {
|
|
36
|
+
export type AutomationOperationDescription = AutomationOperation & {
|
|
199
37
|
input_schema: Record<string, unknown>;
|
|
200
|
-
}
|
|
38
|
+
};
|
|
201
39
|
export interface DescribeOperationOutput extends Record<string, unknown> {
|
|
202
40
|
approval?: {
|
|
203
41
|
approval_url: string;
|
|
@@ -225,7 +63,7 @@ export interface WarmApiClient {
|
|
|
225
63
|
validateAudience(): Promise<VerifyKeyOutput>;
|
|
226
64
|
verifyKey(): Promise<VerifyKeyOutput>;
|
|
227
65
|
}
|
|
228
|
-
export declare function getConfiguredApiKey(audience?:
|
|
66
|
+
export declare function getConfiguredApiKey(audience?: PrivateMcpMode): string | null;
|
|
229
67
|
export declare function resetConfiguredApiKeyCache(): void;
|
|
230
68
|
interface WarmApiResponse<TBody> {
|
|
231
69
|
body: TBody;
|
|
@@ -239,5 +77,4 @@ export declare class WarmApiError extends Error {
|
|
|
239
77
|
constructor(message: string, response: WarmApiResponse<unknown>);
|
|
240
78
|
}
|
|
241
79
|
export declare function createWarmApiClient(options?: WarmApiClientOptions): WarmApiClient;
|
|
242
|
-
export declare function verifyWarmApiKey(apiKey: string, audience?:
|
|
243
|
-
export {};
|
|
80
|
+
export declare function verifyWarmApiKey(apiKey: string, audience?: PrivateMcpMode): Promise<VerifyKeyOutput>;
|