@warmio/mcp 4.3.2 → 5.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 CHANGED
@@ -1,26 +1,14 @@
1
- # Warm MCP
1
+ # Warmio
2
2
 
3
- Read-only MCP server for Warm financial data.
4
-
5
- This package starts in local `stdio` mode by default and also supports optional Streamable HTTP.
3
+ Warmio is the one-command CLI and read-only MCP server for Warm financial data.
6
4
 
7
5
  ## Install
8
6
 
9
7
  ```bash
10
- npx -y @warmio/mcp@latest
8
+ npx @warmio/mcp
11
9
  ```
12
10
 
13
- The installer detects supported MCP clients, prompts for your Warm API key, and writes the local
14
- `stdio` server config automatically. The key is stored once in your local Warm profile instead of
15
- being duplicated into every MCP client config.
16
-
17
- Use `@latest` when you want the newest published package. Bare `npx @warmio/mcp` can reuse a
18
- cached or local copy and leave you on an older version. If you want a deterministic install,
19
- replace `@latest` with an exact version such as `@warmio/mcp@4.3.2`.
20
-
21
- When launched without arguments in a non-interactive context, the binary automatically starts the
22
- `stdio` server instead of the installer. This keeps MCP clients that invoke the package directly
23
- from falling into the interactive setup flow.
11
+ The installer detects supported MCP clients, prompts for your Warm API key, validates it, and writes the local `stdio` MCP config automatically. The key is stored once in your local Warm profile instead of being duplicated into every MCP client config.
24
12
 
25
13
  ## Requirements
26
14
 
@@ -28,41 +16,64 @@ from falling into the interactive setup flow.
28
16
  - A Warm API key from [Settings -> API Keys](https://warm.io/settings)
29
17
  - Node.js 18+
30
18
 
31
- ## Manual `stdio` Config
19
+ ## Manual MCP Config
32
20
 
33
- The installer stores your API key in the Warm config directory and generated MCP client configs can
34
- stay secret-free:
21
+ Use this when a client asks you to paste an MCP JSON config:
35
22
 
36
23
  ```json
37
24
  {
38
25
  "mcpServers": {
39
26
  "warm": {
40
27
  "command": "npx",
41
- "args": ["-y", "@warmio/mcp@latest", "--server"]
28
+ "args": ["-y", "@warmio/mcp", "mcp"]
42
29
  }
43
30
  }
44
31
  }
45
32
  ```
46
33
 
47
- If you already have a client config that uses bare `@warmio/mcp`, update it to `@warmio/mcp@latest`
48
- or an exact version and restart the client.
34
+ On Windows, prefer:
35
+
36
+ ```json
37
+ {
38
+ "mcpServers": {
39
+ "warm": {
40
+ "command": "cmd",
41
+ "args": ["/c", "npx", "-y", "@warmio/mcp", "mcp"]
42
+ }
43
+ }
44
+ }
45
+ ```
49
46
 
50
47
  Optional auth overrides:
51
48
 
52
49
  - `WARM_API_KEY`
53
50
  - `WARM_API_KEY_FILE`
54
51
 
55
- On Windows, prefer:
52
+ ## Universal copy/paste setup prompt
53
+
54
+ ```text
55
+ I want to connect Warm to this AI app using MCP.
56
+
57
+ Use this MCP server config:
56
58
 
57
- ```json
58
59
  {
59
60
  "mcpServers": {
60
61
  "warm": {
61
- "command": "cmd",
62
- "args": ["/c", "npx", "-y", "@warmio/mcp@latest", "--server"]
62
+ "command": "npx",
63
+ "args": ["-y", "@warmio/mcp", "mcp"]
63
64
  }
64
65
  }
65
66
  }
67
+
68
+ If this app supports MCP configuration, add a server named "warm" with that command.
69
+
70
+ Do not ask me to paste my Warm API key into this chat. Help me store it locally using Warm's setup flow, then test the connection by calling Warm's verify_key tool.
71
+
72
+ After setup, I should be able to ask:
73
+ - What’s my net worth?
74
+ - Summarize my recent transactions.
75
+ - What changed recently?
76
+ - What recurring charges do I have?
66
77
  ```
67
78
 
68
79
  ## Optional Streamable HTTP
@@ -70,7 +81,7 @@ On Windows, prefer:
70
81
  If your MCP client supports Streamable HTTP, you can run:
71
82
 
72
83
  ```bash
73
- npx -y @warmio/mcp@latest http --host 127.0.0.1 --port 3000 --path /mcp
84
+ npx -y @warmio/mcp http --host 127.0.0.1 --port 3000 --path /mcp
74
85
  ```
75
86
 
76
87
  Relevant optional environment variables:
package/dist/index.js CHANGED
@@ -9,24 +9,20 @@ function isInteractiveSession() {
9
9
  }
10
10
  function printUsage() {
11
11
  console.log('');
12
- console.log(' Warm MCP');
13
- console.log(' --------');
12
+ console.log(' Warmio');
13
+ console.log(' ------');
14
14
  console.log('');
15
- console.log(' warm-mcp');
16
- console.log(' Interactive terminal: runs installer');
17
- console.log(' Non-interactive launch: starts stdio server');
15
+ console.log(' warmio');
16
+ console.log(' Run the interactive installer');
18
17
  console.log('');
19
- console.log(' warm-mcp install [--force] [--no-validate]');
20
- console.log(' warm-mcp stdio');
21
- console.log(' warm-mcp http [--host 127.0.0.1] [--port 3000] [--path /mcp]');
22
- console.log('');
23
- console.log(' Aliases:');
24
- console.log(' --server, --stdio Start stdio mode');
18
+ console.log(' warmio install [--force] [--no-validate]');
19
+ console.log(' warmio mcp');
20
+ console.log(' warmio http [--host 127.0.0.1] [--port 3000] [--path /mcp]');
25
21
  console.log('');
26
22
  }
27
23
  function parseCliArgs(args) {
28
24
  const options = {
29
- command: isInteractiveSession() ? 'install' : 'stdio',
25
+ command: isInteractiveSession() ? 'install' : 'mcp',
30
26
  force: false,
31
27
  validateApiKey: true,
32
28
  };
@@ -40,8 +36,8 @@ function parseCliArgs(args) {
40
36
  options.command = 'install';
41
37
  continue;
42
38
  }
43
- if (arg === 'stdio' || arg === 'server' || arg === '--stdio' || arg === '--server') {
44
- options.command = 'stdio';
39
+ if (arg === 'mcp') {
40
+ options.command = 'mcp';
45
41
  continue;
46
42
  }
47
43
  if (arg === 'http') {
@@ -96,7 +92,7 @@ async function main() {
96
92
  case 'help':
97
93
  printUsage();
98
94
  return;
99
- case 'stdio':
95
+ case 'mcp':
100
96
  await startStdioServer();
101
97
  return;
102
98
  case 'http':
package/dist/install.js CHANGED
@@ -46,10 +46,10 @@ const GLOBAL_CLIENTS = [
46
46
  { name: 'Gemini CLI', configPath: join(HOME, '.gemini', 'settings.json'), format: 'json' },
47
47
  ];
48
48
  const PROJECT_CONFIGS = ['.mcp.json', '.cursor/mcp.json', '.vscode/mcp.json'];
49
- const MCP_PACKAGE_SPEC = '@warmio/mcp@latest';
49
+ const MCP_PACKAGE_SPEC = '@warmio/mcp';
50
50
  const MCP_CONFIG = platform() === 'win32'
51
- ? { command: 'cmd', args: ['/c', 'npx', '-y', MCP_PACKAGE_SPEC, '--server'] }
52
- : { command: 'npx', args: ['-y', MCP_PACKAGE_SPEC, '--server'] };
51
+ ? { command: 'cmd', args: ['/c', 'npx', '-y', MCP_PACKAGE_SPEC, 'mcp'] }
52
+ : { command: 'npx', args: ['-y', MCP_PACKAGE_SPEC, 'mcp'] };
53
53
  const WARM_API_KEY_PATH = getWarmApiKeyPath();
54
54
  const WARM_TOML_BLOCK_PATTERN = /\n?\[mcp_servers\.warm\][\s\S]*?(?=\n\[[^\n]+\]|\s*$)/g;
55
55
  const WARM_TOML_ENV_BLOCK_PATTERN = /\n?\[mcp_servers\.warm\.env\][\s\S]*?(?=\n\[[^\n]+\]|\s*$)/g;
@@ -81,24 +81,13 @@ function getStringArray(value) {
81
81
  return value.filter((entry) => typeof entry === 'string');
82
82
  }
83
83
  function isWarmPackageSpecifier(value) {
84
- return /^@warmio\/mcp(?:@.+)?$/.test(value);
85
- }
86
- function isLegacyWarmPackageSpecifier(value) {
87
- return /^@anthropic\/warm-mcp-server(?:@.+)?$/.test(value);
88
- }
89
- function normalizePathLikeValue(value) {
90
- return value.replace(/\\/g, '/').toLowerCase();
91
- }
92
- function isLocalWarmMcpPath(value) {
93
- const normalized = normalizePathLikeValue(value);
94
- return normalized.includes('/warm-mcp/dist/index.js') || normalized.endsWith('/warm-mcp');
84
+ return /^@warmio\/warmio(?:@.+)?$/.test(value);
95
85
  }
96
86
  function isSupportedWarmInvocation(command, args) {
97
- return [command, ...args].some((value) => typeof value === 'string' &&
98
- (isWarmPackageSpecifier(value) || isLocalWarmMcpPath(value)));
99
- }
100
- function isLegacyWarmInvocation(command, args) {
101
- return [command, ...args].some((value) => typeof value === 'string' && isLegacyWarmPackageSpecifier(value));
87
+ if (command !== 'npx' && command !== 'cmd') {
88
+ return false;
89
+ }
90
+ return args.some((value) => isWarmPackageSpecifier(value)) && args.includes('mcp');
102
91
  }
103
92
  function getJsonEnvStatus(server) {
104
93
  const env = isRecord(server?.env) ? server.env : undefined;
@@ -121,13 +110,10 @@ function getJsonStatus(client, content) {
121
110
  }
122
111
  const command = typeof server.command === 'string' ? server.command : undefined;
123
112
  const args = getStringArray(server.args);
124
- if (client.isProjectLevel && command && !isLegacyWarmInvocation(command, args)) {
125
- return { client, state: 'configured', ...envStatus };
126
- }
127
113
  if (isSupportedWarmInvocation(command, args)) {
128
114
  return { client, state: 'configured', ...envStatus };
129
115
  }
130
- return { client, state: 'needs_migration', ...envStatus };
116
+ return { client, state: 'needs_setup', ...envStatus };
131
117
  }
132
118
  catch {
133
119
  return { client, state: 'missing', hasApiKeyFileOverride: false, inlineApiKey: null };
@@ -190,7 +176,7 @@ function getTomlStatus(client, content) {
190
176
  if (isSupportedWarmInvocation(command, args)) {
191
177
  return { client, state: 'configured', ...envStatus };
192
178
  }
193
- return { client, state: 'needs_migration', ...envStatus };
179
+ return { client, state: 'needs_setup', ...envStatus };
194
180
  }
195
181
  function getClientStatus(client) {
196
182
  if (!existsSync(client.configPath)) {
@@ -223,8 +209,7 @@ function configureJson(client) {
223
209
  const existingArgs = getStringArray(existing?.args);
224
210
  const preserveProjectCommand = client.isProjectLevel &&
225
211
  !!existingCommand &&
226
- !isLegacyWarmInvocation(existingCommand, existingArgs) &&
227
- !isWarmPackageSpecifier(existingCommand);
212
+ isSupportedWarmInvocation(existingCommand, existingArgs);
228
213
  delete nextEnv.WARM_API_KEY;
229
214
  if (preserveProjectCommand) {
230
215
  servers.warm = {
@@ -252,8 +237,8 @@ function configureToml(client) {
252
237
  }
253
238
  const tomlCommand = platform() === 'win32' ? 'cmd' : 'npx';
254
239
  const tomlArgs = platform() === 'win32'
255
- ? `["/c", "npx", "-y", "${MCP_PACKAGE_SPEC}", "--server"]`
256
- : `["-y", "${MCP_PACKAGE_SPEC}", "--server"]`;
240
+ ? `["/c", "npx", "-y", "${MCP_PACKAGE_SPEC}", "mcp"]`
241
+ : `["-y", "${MCP_PACKAGE_SPEC}", "mcp"]`;
257
242
  const warmBlock = `[mcp_servers.warm]\ncommand = "${tomlCommand}"\nargs = ${tomlArgs}\n`;
258
243
  const preservedEnvLines = getTomlEnvStatus(content).envLines.filter((line) => !/^\s*WARM_API_KEY\s*=/.test(line));
259
244
  let nextContent = content
@@ -332,8 +317,8 @@ function getStatusLabel(status, force) {
332
317
  if (status === 'configured') {
333
318
  return 'configured';
334
319
  }
335
- if (status === 'needs_migration') {
336
- return 'needs migration';
320
+ if (status === 'needs_setup') {
321
+ return 'needs setup';
337
322
  }
338
323
  return 'not configured';
339
324
  }
@@ -341,8 +326,8 @@ export async function install(options = {}) {
341
326
  const force = options.force ?? false;
342
327
  const shouldValidateApiKey = options.validateApiKey ?? true;
343
328
  console.log('');
344
- console.log(' Warm MCP Server Installer');
345
- console.log(' -------------------------');
329
+ console.log(' Warmio Installer');
330
+ console.log(' ----------------');
346
331
  console.log('');
347
332
  const globalClients = GLOBAL_CLIENTS.filter(isDetected);
348
333
  const projectClients = detectProjectClients();
@@ -163,7 +163,7 @@ export async function apiRequest(endpoint, params = {}, options = {}) {
163
163
  const requestOptions = createWarmApiClientConfig(options);
164
164
  const apiKey = requestOptions.apiKeyResolver?.() ?? getConfiguredApiKey();
165
165
  if (!apiKey) {
166
- throw new Error('WARM_API_KEY not set. Run "npx -y @warmio/mcp@latest" to configure or set WARM_API_KEY.');
166
+ throw new Error('WARM_API_KEY not set. Run "npx @warmio/mcp" to configure or set WARM_API_KEY.');
167
167
  }
168
168
  const url = new URL(endpoint, requestOptions.apiUrl);
169
169
  Object.entries(params).forEach(([key, value]) => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@warmio/mcp",
3
- "version": "4.3.2",
4
- "description": "Warm MCP server for local stdio and Streamable HTTP access",
3
+ "version": "5.0.0",
4
+ "description": "Warm CLI and MCP server for personal financial data",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -27,24 +27,27 @@
27
27
  }
28
28
  },
29
29
  "bin": {
30
- "warm-mcp": "dist/index.js"
30
+ "warmio": "dist/index.js"
31
31
  },
32
32
  "files": [
33
33
  "dist"
34
34
  ],
35
35
  "scripts": {
36
36
  "build": "tsc",
37
- "start": "node dist/index.js --stdio",
37
+ "start": "node dist/index.js mcp",
38
38
  "start:http": "node dist/index.js http",
39
39
  "start:install": "node dist/index.js install",
40
- "prepublishOnly": "npm run build"
40
+ "prepublishOnly": "npm run build",
41
+ "start:mcp": "node dist/index.js mcp"
41
42
  },
42
43
  "keywords": [
43
44
  "mcp",
44
45
  "warm",
46
+ "warmio",
45
47
  "financial",
46
48
  "api",
47
- "claude"
49
+ "claude",
50
+ "chatgpt"
48
51
  ],
49
52
  "license": "MIT",
50
53
  "dependencies": {