@finchagentic/mcp 4.7.2 → 4.7.3
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 +74 -39
- package/dist/_zod-helpers.js +10 -0
- package/dist/cli-doctor.js +300 -0
- package/dist/cli-env.js +91 -0
- package/dist/cli-install.js +236 -0
- package/dist/cli-login.js +101 -0
- package/dist/cli-orders.js +175 -0
- package/dist/cli-setup.js +270 -0
- package/dist/cli-ui.js +168 -0
- package/dist/cli-vault.js +75 -0
- package/dist/cli.js +61 -1152
- package/dist/config.js +3 -2
- package/dist/enrichment-router.js +5 -18
- package/dist/finch-output.js +30 -29
- package/dist/finch-status.js +105 -40
- package/dist/local-vault.js +5 -12
- package/dist/output-schemas.js +3 -12
- package/dist/project.js +4 -13
- package/dist/server.js +13 -35
- package/dist/tool-filter.js +4 -13
- package/dist/tools/_solidity-scan.js +5 -14
- package/dist/tools/agents.js +14 -26
- package/dist/tools/deep-research-constants.js +33 -0
- package/dist/tools/deep-research-firecrawl.js +88 -0
- package/dist/tools/deep-research-planning.js +249 -0
- package/dist/tools/deep-research-synthesis.js +343 -0
- package/dist/tools/deep-research-text.js +158 -0
- package/dist/tools/deep-research-tools.js +90 -0
- package/dist/tools/deep-research.js +47 -938
- package/dist/tools/defi.js +4 -3
- package/dist/tools/insider.js +4 -14
- package/dist/tools/insight.js +7 -6
- package/dist/tools/market.js +16 -15
- package/dist/tools/memory.js +43 -61
- package/dist/tools/monitor.js +7 -6
- package/dist/tools/os.js +7 -85
- package/dist/tools/research.js +7 -6
- package/dist/tools/rh-mcp-constants.js +65 -0
- package/dist/tools/rh-mcp-dex.js +107 -0
- package/dist/tools/rh-mcp-provider.js +127 -0
- package/dist/tools/rh-mcp-resolve.js +137 -0
- package/dist/tools/rh-mcp-risk.js +230 -0
- package/dist/tools/rh-mcp-safety.js +234 -0
- package/dist/tools/rh-mcp-swap.js +181 -0
- package/dist/tools/rh-mcp-tools.js +137 -0
- package/dist/tools/rh-mcp.js +75 -1191
- package/dist/tools/scanner.js +10 -9
- package/dist/tools/stake.js +7 -20
- package/dist/tools/vault.js +52 -59
- package/package.json +12 -9
package/README.md
CHANGED
|
@@ -1,20 +1,12 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
# Finch MCP
|
|
6
|
-
|
|
7
|
-
[](https://www.npmjs.com/package/@finchagentic/mcp)
|
|
8
|
-
[](https://registry.modelcontextprotocol.io)
|
|
9
|
-
[](LICENSE)
|
|
10
|
-
[](package.json)
|
|
11
|
-
[](#what-you-get)
|
|
3
|
+
# Finch
|
|
12
4
|
|
|
13
5
|
**The runtime layer for Agentic AI.**
|
|
14
6
|
|
|
15
7
|
Persistent memory, autonomous agents, and workflows that survive every session.
|
|
16
8
|
|
|
17
|
-
[
|
|
9
|
+
[Docs](https://docs.finch.com) · [App](https://app.finchagentic.com) · [npm](https://www.npmjs.com/package/@finchagentic/mcp) · [GitHub](https://github.com/finchagentic/mcp) · [X](https://x.com/finchagentic)
|
|
18
10
|
|
|
19
11
|
</div>
|
|
20
12
|
|
|
@@ -37,13 +29,13 @@ Always pin the version. Never use `@latest`.
|
|
|
37
29
|
|
|
38
30
|
```bash
|
|
39
31
|
# One-command installer (detects common MCP clients)
|
|
40
|
-
npx -y @finchagentic/mcp@4.
|
|
32
|
+
npx -y -p @finchagentic/mcp@4.7.3 finch install
|
|
41
33
|
```
|
|
42
34
|
|
|
43
35
|
### Claude Code
|
|
44
36
|
|
|
45
37
|
```bash
|
|
46
|
-
claude mcp add finch -s user -- npx -y @finchagentic/mcp@4.
|
|
38
|
+
claude mcp add finch -s user -- npx -y -p @finchagentic/mcp@4.7.3 finch-mcp
|
|
47
39
|
```
|
|
48
40
|
|
|
49
41
|
### Cursor / Windsurf / Claude Desktop
|
|
@@ -53,16 +45,24 @@ claude mcp add finch -s user -- npx -y @finchagentic/mcp@4.6.5
|
|
|
53
45
|
"mcpServers": {
|
|
54
46
|
"finch": {
|
|
55
47
|
"command": "npx",
|
|
56
|
-
"args": ["-y", "-p", "@finchagentic/mcp@4.
|
|
48
|
+
"args": ["-y", "-p", "@finchagentic/mcp@4.7.3", "finch-mcp"]
|
|
57
49
|
}
|
|
58
50
|
}
|
|
59
51
|
}
|
|
60
52
|
```
|
|
61
53
|
|
|
62
|
-
###
|
|
54
|
+
### VS Code
|
|
63
55
|
|
|
64
|
-
```
|
|
65
|
-
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"servers": {
|
|
59
|
+
"finch": {
|
|
60
|
+
"type": "stdio",
|
|
61
|
+
"command": "npx",
|
|
62
|
+
"args": ["-y", "-p", "@finchagentic/mcp@4.7.3", "finch-mcp"]
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
66
|
```
|
|
67
67
|
|
|
68
68
|
<details>
|
|
@@ -79,7 +79,7 @@ hermes mcp add finch -- npx -y @finchagentic/mcp@4.6.5
|
|
|
79
79
|
|
|
80
80
|
</details>
|
|
81
81
|
|
|
82
|
-
No LLM API key required to start — 111 of 116 tools are plain reads/writes/on-chain calls your client's model already drives. Tools load on first use.
|
|
82
|
+
No LLM API key is required to start — 111 of 116 tools are plain reads/writes/on-chain calls that your MCP client's own model already drives; only 5 (`ask_finch`, `deep_research`, and scheduled agent learning) do their own multi-step reasoning server-side and need a key (see [Configuration](#configuration)). Tools load on first use.
|
|
83
83
|
|
|
84
84
|
## Quick start
|
|
85
85
|
|
|
@@ -105,11 +105,13 @@ save this thesis to vault
|
|
|
105
105
|
| Pillar | What it does |
|
|
106
106
|
|--------|----------------|
|
|
107
107
|
| **Memory** | Full-text searchable memory + versioned vault + chronicle |
|
|
108
|
-
| **Agents** | Spawn, recall, update named agents — `agent_recall` also pulls related memory/vault context matching the agent's goal |
|
|
108
|
+
| **Agents** | Spawn, recall, update named agents — `agent_recall` also pulls related memory/vault context matching the agent's goal, not just its own logged updates |
|
|
109
109
|
| **Workflows** | Automations, monitors, packets, deep research (auto-saves reports + auto-links related past research) |
|
|
110
110
|
| **Execution** | Base DeFi, Robinhood Chain, market data, web, GitHub |
|
|
111
111
|
|
|
112
|
-
`deep_research` auto-saves its report to vault and links related past reports; `code_session_save` does the same for coding sessions
|
|
112
|
+
Coding and research sessions persist the same way: `deep_research` auto-saves its report to vault and links it to related past reports; `code_session_save` does the same for coding/debugging sessions (`vault_save type=code`, versioned per project, auto-linked). Both exist so the next session — yours or another agent's — starts with real context instead of cold.
|
|
113
|
+
|
|
114
|
+
`vault_save` and `agent_spawn` also take an optional `workspaceProject` - the same named Projects a user organizes their Agents/vault content into on the webapp's Agents page. Pass a name and it's matched case-insensitively or created automatically (`list_projects` to browse what exists first). Hosted vault only - local-vault mode has no project concept.
|
|
113
115
|
|
|
114
116
|
Default palette is `core` (lighter context). Full set:
|
|
115
117
|
|
|
@@ -122,7 +124,8 @@ Default palette is `core` (lighter context). Full set:
|
|
|
122
124
|
Finch is the runtime. **Your LLM is the brain. Your data stays yours.**
|
|
123
125
|
|
|
124
126
|
```bash
|
|
125
|
-
npx -y @finchagentic/mcp@4.
|
|
127
|
+
npx -y -p @finchagentic/mcp@4.7.3 finch setup
|
|
128
|
+
# enable local vault (and optional local memory)
|
|
126
129
|
```
|
|
127
130
|
|
|
128
131
|
| Piece | Location |
|
|
@@ -130,33 +133,65 @@ npx -y @finchagentic/mcp@4.6.5 finch setup
|
|
|
130
133
|
| Vault | `~/.finch/vault/` |
|
|
131
134
|
| Wallet | `~/.finch/wallet.json` |
|
|
132
135
|
| Config | `~/.finch/config.json` |
|
|
133
|
-
| Brain | your MCP client
|
|
136
|
+
| Brain | your MCP client’s model |
|
|
134
137
|
|
|
135
|
-
|
|
138
|
+
Scheduled/cloud features still need an account. Core memory, vault, and public-data tools work offline of Finch cloud.
|
|
136
139
|
|
|
137
|
-
|
|
140
|
+
## Configuration
|
|
138
141
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
+
| Variable | Purpose |
|
|
143
|
+
|----------|---------|
|
|
144
|
+
| `FINCH_SESSION_TOKEN` | Signed-in session (vault/memory/agents against your account) |
|
|
145
|
+
| `FINCH_API_KEY` | API key (`finch_sk_…`) |
|
|
146
|
+
| `FINCH_TOOLS` | `core` (default) · `all` · or palettes like `memory,defi` |
|
|
147
|
+
| `FINCH_PROVIDER` | Force `bankr` · `anthropic` · `openai` · `grok` |
|
|
148
|
+
| `FINCH_MODEL` | Model override for host-side loops |
|
|
149
|
+
| `BANKR_API_KEY` / `ANTHROPIC_API_KEY` / `OPENAI_API_KEY` / `GROK_API_KEY` | Required for `ask_finch`, `deep_research`'s synthesis stages, and scheduled-agent learning extraction — these do their own multi-step reasoning server-side and there is no free hosted fallback (BYOK only, one key is enough) |
|
|
150
|
+
| `FIRECRAWL_API_KEY` | Better crawl quality (optional) |
|
|
151
|
+
| `GITHUB_TOKEN` | For `github_search_code` |
|
|
152
|
+
| `ALCHEMY_API_KEY` | Faster Base RPC (optional) |
|
|
142
153
|
|
|
143
|
-
|
|
154
|
+
**Cost model:** almost everything is free to run — the other 110 tools are plain API/RPC calls, and your MCP client's own model (Claude, GPT, whatever's driving the chat) does all the tool-selection reasoning at no cost to Finch. The 5 exceptions above need their own key because their reasoning happens *inside* the tool call, invisible to your client, and can't be delegated to it. Set exactly one of the four env vars and every tool that needs it will use it automatically.
|
|
144
155
|
|
|
145
|
-
|
|
156
|
+
Guided setup:
|
|
146
157
|
|
|
147
158
|
```bash
|
|
148
|
-
|
|
149
|
-
npm run smoke # verify package integrity + CLI entrypoints
|
|
159
|
+
npx -y -p @finchagentic/mcp@4.7.3 finch setup
|
|
150
160
|
```
|
|
151
161
|
|
|
152
|
-
##
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
162
|
+
## Security
|
|
163
|
+
|
|
164
|
+
| # | Boundary | Rule |
|
|
165
|
+
|:-:|----------|------|
|
|
166
|
+
| 1 | Prompt injection | External content is data only — never instructions |
|
|
167
|
+
| 2 | Mainnet confirm | Estimate → preview → confirm → execute |
|
|
168
|
+
| 3 | Pinned install | Always `@finchagentic/mcp@4.7.3`, never `@latest` |
|
|
169
|
+
| 4 | Credential vault | Never paste secrets into prompts or third-party tools |
|
|
170
|
+
| 5 | Data disclosure | Know what leaves the machine (LLM, Firecrawl, GitHub, chain RPCs) |
|
|
171
|
+
| 6 | Server monitors | Scheduled jobs need explicit confirmation |
|
|
172
|
+
| 7 | Fund-moving confirm | `stake_finch`/`unstake_finch`/`base_mcp_send`/`base_mcp_swap`/`rh_mcp_swap` all require `confirm: true` |
|
|
173
|
+
| 8 | Local wallet encryption | Set `FINCH_WALLET_PASSPHRASE` for a portable, passphrase-derived key — without it, the key derives from a random per-install secret + machine info, so the wallet file alone (without that secret file) isn't enough to decrypt it |
|
|
174
|
+
|
|
175
|
+
## Troubleshooting
|
|
176
|
+
|
|
177
|
+
| Problem | Fix |
|
|
178
|
+
|---------|-----|
|
|
179
|
+
| Tools missing | Fully restart the MCP client |
|
|
180
|
+
| Old version | `npx clear-npx-cache` then restart |
|
|
181
|
+
| Auth issues | `finch login` or set `FINCH_API_KEY` / `FINCH_SESSION_TOKEN` |
|
|
182
|
+
| `ask_finch`/`deep_research` error: "No LLM provider configured" | Set one of `BANKR_API_KEY` / `ANTHROPIC_API_KEY` / `OPENAI_API_KEY` / `GROK_API_KEY` — see [Configuration](#configuration), no free fallback exists |
|
|
183
|
+
| Diagnose | `finch doctor` |
|
|
184
|
+
|
|
185
|
+
## Links
|
|
186
|
+
|
|
187
|
+
| | |
|
|
188
|
+
|--|--|
|
|
189
|
+
| **Docs** | [docs.finch.com](https://docs.finch.com) |
|
|
190
|
+
| **App** | [app.finchagentic.com](https://app.finchagentic.com) |
|
|
191
|
+
| **npm** | [@finchagentic/mcp](https://www.npmjs.com/package/@finchagentic/mcp) |
|
|
192
|
+
| **GitHub** | [github.com/finchagentic/mcp](https://github.com/finchagentic/mcp) |
|
|
193
|
+
| **X** | [@finchagentic](https://x.com/finchagentic) |
|
|
157
194
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
**Finch** — memory that survives every session.
|
|
195
|
+
---
|
|
161
196
|
|
|
162
|
-
|
|
197
|
+
MIT License · Finch
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseOrError = parseOrError;
|
|
4
|
+
function parseOrError(schema, args) {
|
|
5
|
+
const parsed = schema.safeParse(args);
|
|
6
|
+
if (!parsed.success) {
|
|
7
|
+
return { ok: false, error: { content: [{ type: "text", text: `${parsed.error.issues[0].message}` }], isError: true } };
|
|
8
|
+
}
|
|
9
|
+
return { ok: true, data: parsed.data };
|
|
10
|
+
}
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// `finch doctor` - comprehensive health check. Detects broken installs and
|
|
3
|
+
// missing config in <5s; output is concise and tells the user exactly what
|
|
4
|
+
// to fix next. Designed to be the first command a new user runs after install.
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.doctorFlow = doctorFlow;
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
const os = __importStar(require("os"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
const config_js_1 = require("./config.js");
|
|
44
|
+
const local_memory_js_1 = require("./local-memory.js");
|
|
45
|
+
const cli_ui_js_1 = require("./cli-ui.js");
|
|
46
|
+
const cli_env_js_1 = require("./cli-env.js");
|
|
47
|
+
async function doctorFlow() {
|
|
48
|
+
console.log(`\n ${cli_ui_js_1.C.cyan}${cli_ui_js_1.C.bold}finch doctor${cli_ui_js_1.C.reset} ${cli_ui_js_1.C.dim}v${cli_env_js_1.PKG_VERSION}${cli_ui_js_1.C.reset}\n`);
|
|
49
|
+
console.log(` ${cli_ui_js_1.C.dim}Running diagnostic - this takes ~5 seconds.${cli_ui_js_1.C.reset}\n`);
|
|
50
|
+
const checks = [];
|
|
51
|
+
const cfg = (0, config_js_1.readConfig)();
|
|
52
|
+
const authHeader = cfg.sessionToken ? { Authorization: `Bearer ${cfg.sessionToken}` } : {};
|
|
53
|
+
// 1. LLM provider
|
|
54
|
+
const provider = process.env.BANKR_API_KEY ? "bankr"
|
|
55
|
+
: process.env.ANTHROPIC_API_KEY ? "anthropic"
|
|
56
|
+
: process.env.OPENAI_API_KEY ? "openai"
|
|
57
|
+
: "finch-proxy";
|
|
58
|
+
// Tools never call an LLM of their own - they return data and structure for
|
|
59
|
+
// the calling model. A key is what makes *finch itself* a host: the CLI
|
|
60
|
+
// agent loop and scheduled agents, which have no client model to borrow.
|
|
61
|
+
checks.push({
|
|
62
|
+
name: "LLM provider",
|
|
63
|
+
status: "✓",
|
|
64
|
+
detail: provider === "finch-proxy"
|
|
65
|
+
? `none set · all ${cli_env_js_1.TOTAL_TOOL_COUNT} tools work without one`
|
|
66
|
+
: `${provider} (direct) · used by \`finch run\` and scheduled agents`,
|
|
67
|
+
fix: provider === "finch-proxy"
|
|
68
|
+
? `Only needed for \`finch run\` and scheduled agents — \`finch setup\` adds one`
|
|
69
|
+
: undefined,
|
|
70
|
+
});
|
|
71
|
+
// 2. Backend reachable
|
|
72
|
+
try {
|
|
73
|
+
const t0 = Date.now();
|
|
74
|
+
const res = await fetch(`${cli_env_js_1.CONVEX_SITE}/memory/profile`, {
|
|
75
|
+
headers: authHeader,
|
|
76
|
+
signal: AbortSignal.timeout(8000),
|
|
77
|
+
});
|
|
78
|
+
const latency = Date.now() - t0;
|
|
79
|
+
if (res.status === 401) {
|
|
80
|
+
checks.push({
|
|
81
|
+
name: "Backend reachable", status: "⚠",
|
|
82
|
+
detail: `${cli_env_js_1.CONVEX_SITE} → 401 (not signed in)`,
|
|
83
|
+
fix: `Run \`finch login\` to authenticate.`,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
else if (res.ok) {
|
|
87
|
+
checks.push({
|
|
88
|
+
name: "Backend reachable", status: "✓",
|
|
89
|
+
detail: `${cli_env_js_1.CONVEX_SITE} → ${res.status} (${latency}ms)`,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
checks.push({
|
|
94
|
+
name: "Backend reachable", status: "✗",
|
|
95
|
+
detail: `${cli_env_js_1.CONVEX_SITE} → ${res.status}`,
|
|
96
|
+
fix: `Check FINCH_CONVEX_URL env var, or wait if the service is down.`,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
checks.push({
|
|
102
|
+
name: "Backend reachable", status: "✗",
|
|
103
|
+
detail: `${cli_env_js_1.CONVEX_SITE} → ${err.message}`,
|
|
104
|
+
fix: `Network issue or wrong URL. Default: https://valuable-fish-533.convex.site`,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
// 3. Auth state
|
|
108
|
+
if (cfg.sessionToken) {
|
|
109
|
+
checks.push({
|
|
110
|
+
name: "Authentication",
|
|
111
|
+
status: "✓",
|
|
112
|
+
detail: cfg.email
|
|
113
|
+
? `Signed in as ${cfg.email}`
|
|
114
|
+
: `Session token present`,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
checks.push({
|
|
119
|
+
name: "Authentication",
|
|
120
|
+
status: "⚠",
|
|
121
|
+
detail: `No session token - running with local wallet signature only`,
|
|
122
|
+
fix: `Run \`finch login\` for persistent identity across MCP clients.`,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
// 4. Local wallet
|
|
126
|
+
const walletPath = path.join(os.homedir(), ".finch", "wallet.json");
|
|
127
|
+
if (fs.existsSync(walletPath)) {
|
|
128
|
+
try {
|
|
129
|
+
const wallet = JSON.parse(fs.readFileSync(walletPath, "utf8"));
|
|
130
|
+
const addr = wallet.address ? (wallet.address.startsWith("0x") ? wallet.address : `0x${wallet.address}`) : "unknown";
|
|
131
|
+
checks.push({
|
|
132
|
+
name: "Local wallet", status: "✓",
|
|
133
|
+
detail: `${addr.slice(0, 6)}...${addr.slice(-4)} at ~/.finch/wallet.json`,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
checks.push({
|
|
138
|
+
name: "Local wallet", status: "⚠",
|
|
139
|
+
detail: `wallet.json present but unreadable`,
|
|
140
|
+
fix: `Delete ~/.finch/wallet.json and re-run finch - new wallet auto-creates.`,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
checks.push({
|
|
146
|
+
name: "Local wallet", status: "⚠",
|
|
147
|
+
detail: `Not created yet`,
|
|
148
|
+
fix: `Auto-creates on first DeFi tool call (base_mcp_balance, etc).`,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
// 5. Profile entries
|
|
152
|
+
if (cfg.sessionToken) {
|
|
153
|
+
try {
|
|
154
|
+
const res = await fetch(`${cli_env_js_1.CONVEX_SITE}/vault/profile-context?maxChars=100`, {
|
|
155
|
+
headers: authHeader,
|
|
156
|
+
signal: AbortSignal.timeout(6000),
|
|
157
|
+
});
|
|
158
|
+
const data = await res.json();
|
|
159
|
+
if (data?.hasProfile) {
|
|
160
|
+
checks.push({
|
|
161
|
+
name: "Profile context", status: "✓",
|
|
162
|
+
detail: `Profile entries found - Claude auto-loads your context across sessions`,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
checks.push({
|
|
167
|
+
name: "Profile context", status: "⚠",
|
|
168
|
+
detail: `No profile entries yet`,
|
|
169
|
+
fix: `Run: vault_save type=memory key=profile/business content="<who you are, what you build>"`,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
checks.push({
|
|
175
|
+
name: "Profile context", status: "⚠",
|
|
176
|
+
detail: `Could not fetch (backend issue)`,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
// 6. Tool palette mode
|
|
181
|
+
const toolMode = process.env.FINCH_TOOLS ?? "core";
|
|
182
|
+
checks.push({
|
|
183
|
+
name: "Tool palette",
|
|
184
|
+
status: "✓",
|
|
185
|
+
detail: `Mode: ${toolMode}${toolMode === "core" ? ` (default - ${cli_env_js_1.CORE_TOOL_COUNT} essential tools)` : toolMode === "all" ? ` (power user - ${cli_env_js_1.TOTAL_TOOL_COUNT} tools)` : ` (custom subset)`}`,
|
|
186
|
+
fix: toolMode === "core"
|
|
187
|
+
? `Set FINCH_TOOLS=all to expose all ${cli_env_js_1.TOTAL_TOOL_COUNT} tools (raises LLM context cost).`
|
|
188
|
+
: undefined,
|
|
189
|
+
});
|
|
190
|
+
// 7. MEV-protect broadcast (optional belt-and-suspenders for swaps)
|
|
191
|
+
if (process.env.FINCH_BROADCAST_RPC) {
|
|
192
|
+
const host = (() => {
|
|
193
|
+
try {
|
|
194
|
+
return new URL(process.env.FINCH_BROADCAST_RPC).host;
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
return "custom";
|
|
198
|
+
}
|
|
199
|
+
})();
|
|
200
|
+
checks.push({
|
|
201
|
+
name: "MEV-protect", status: "✓",
|
|
202
|
+
detail: `Broadcasts routed through ${host} (private/MEV-protected)`,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
checks.push({
|
|
207
|
+
name: "MEV-protect", status: "⚠",
|
|
208
|
+
detail: `Standard Base RPC (sequencer is centralized, MEV is naturally low)`,
|
|
209
|
+
fix: `Optional: set FINCH_BROADCAST_RPC=<private-relay-url> for belt-and-suspenders routing.`,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
// 8. GITHUB_TOKEN (optional but affects github_search_code)
|
|
213
|
+
if (process.env.GITHUB_TOKEN) {
|
|
214
|
+
checks.push({
|
|
215
|
+
name: "GitHub token", status: "✓",
|
|
216
|
+
detail: `GITHUB_TOKEN set - github_search_code + private repos work`,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
checks.push({
|
|
221
|
+
name: "GitHub token", status: "⚠",
|
|
222
|
+
detail: `No GITHUB_TOKEN - github_search_code disabled, other tools rate-limited to 60/hr`,
|
|
223
|
+
fix: `Optional. Create at https://github.com/settings/tokens (scopes: public_repo) and add to MCP env.`,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
// 9. Local memory (self-hosted) - optional, zero-cost alternative to the
|
|
227
|
+
// Convex-proxied cloud memory backend. Two flavors: zero-dependency file
|
|
228
|
+
// store, or a separately-run supermemory server.
|
|
229
|
+
const localMemCfg = (0, local_memory_js_1.getLocalMemoryConfig)();
|
|
230
|
+
if (localMemCfg?.kind === "file") {
|
|
231
|
+
checks.push({
|
|
232
|
+
name: "Local memory", status: "✓",
|
|
233
|
+
detail: `file-based at ~/.finch/memory - memory tools run fully local, zero cost, no server`,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
else if (localMemCfg?.kind === "supermemory") {
|
|
237
|
+
const reachable = await (0, local_memory_js_1.isLocalMemoryReachable)(localMemCfg);
|
|
238
|
+
checks.push(reachable ? {
|
|
239
|
+
name: "Local memory", status: "✓",
|
|
240
|
+
detail: `supermemory reachable at ${localMemCfg.url} - memory tools run fully local, zero cost`,
|
|
241
|
+
} : {
|
|
242
|
+
name: "Local memory", status: "⚠",
|
|
243
|
+
detail: `memoryBackend is "local" but ${localMemCfg.url} isn't reachable`,
|
|
244
|
+
fix: `Start the local server (see \`npx supermemory local\`), or run \`finch setup\` again.`,
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
checks.push({
|
|
249
|
+
name: "Local memory", status: "⚠",
|
|
250
|
+
detail: `Not configured - memory tools use the Finch-hosted proxy`,
|
|
251
|
+
fix: `Run \`finch setup\` to switch to a free, self-hosted local memory backend.`,
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
// 10. Local vault (user-owned, on-disk) - the account-free alternative to the
|
|
255
|
+
// Convex-hosted vault.
|
|
256
|
+
if (cfg.vaultBackend === "local") {
|
|
257
|
+
const vaultDir = path.join(os.homedir(), ".finch", "vault");
|
|
258
|
+
let entryCount = 0;
|
|
259
|
+
try {
|
|
260
|
+
const idx = JSON.parse(fs.readFileSync(path.join(vaultDir, "index.json"), "utf8"));
|
|
261
|
+
entryCount = Object.keys(idx.entries ?? {}).length;
|
|
262
|
+
}
|
|
263
|
+
catch { /* no index yet */ }
|
|
264
|
+
checks.push({
|
|
265
|
+
name: "Local vault", status: "✓",
|
|
266
|
+
detail: `on-disk at ~/.finch/vault (${entryCount} entr${entryCount === 1 ? "y" : "ies"}) - you own the data, no account needed`,
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
checks.push({
|
|
271
|
+
name: "Local vault", status: "⚠",
|
|
272
|
+
detail: `Not configured - vault tools use the Finch-hosted store (needs login)`,
|
|
273
|
+
fix: `Run \`finch setup\` to store vault artifacts locally, no account required.`,
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
// ── Render ────────────────────────────────────────────────────────────────
|
|
277
|
+
const colorFor = (s) => s === "✓" ? cli_ui_js_1.C.green : s === "⚠" ? cli_ui_js_1.C.yellow : cli_ui_js_1.C.red;
|
|
278
|
+
const widest = Math.max(...checks.map((c) => c.name.length));
|
|
279
|
+
for (const c of checks) {
|
|
280
|
+
const pad = c.name.padEnd(widest);
|
|
281
|
+
console.log(` ${colorFor(c.status)}${c.status}${cli_ui_js_1.C.reset} ${cli_ui_js_1.C.cyan}${pad}${cli_ui_js_1.C.reset} ${c.detail}`);
|
|
282
|
+
if (c.fix)
|
|
283
|
+
console.log(` ${" ".repeat(widest)} ${cli_ui_js_1.C.dim}→ ${c.fix}${cli_ui_js_1.C.reset}`);
|
|
284
|
+
}
|
|
285
|
+
const counts = { "✓": 0, "⚠": 0, "✗": 0 };
|
|
286
|
+
checks.forEach((c) => counts[c.status]++);
|
|
287
|
+
console.log("");
|
|
288
|
+
console.log(` ${cli_ui_js_1.C.dim}Summary:${cli_ui_js_1.C.reset} ${cli_ui_js_1.C.green}${counts["✓"]} ok${cli_ui_js_1.C.reset} · ${cli_ui_js_1.C.yellow}${counts["⚠"]} warning${cli_ui_js_1.C.reset} · ${cli_ui_js_1.C.red}${counts["✗"]} critical${cli_ui_js_1.C.reset}`);
|
|
289
|
+
console.log("");
|
|
290
|
+
if (counts["✗"] > 0) {
|
|
291
|
+
console.log(` ${cli_ui_js_1.C.red}Critical issues found - fix the lines above before relying on finch.${cli_ui_js_1.C.reset}\n`);
|
|
292
|
+
process.exit(1);
|
|
293
|
+
}
|
|
294
|
+
else if (counts["⚠"] > 0) {
|
|
295
|
+
console.log(` ${cli_ui_js_1.C.dim}Warnings are non-blocking - finch works but could be smoother.${cli_ui_js_1.C.reset}\n`);
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
console.log(` ${cli_ui_js_1.C.green}All systems healthy.${cli_ui_js_1.C.reset}\n`);
|
|
299
|
+
}
|
|
300
|
+
}
|
package/dist/cli-env.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Bootstrap state shared across every cli-*.ts module: env hydration (must
|
|
3
|
+
// run before anything else reads process.env), tool counts, backend URL,
|
|
4
|
+
// package version, and the local wallet address reader.
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.PKG_VERSION = exports.CONVEX_SITE = exports.CORE_TOOL_COUNT = exports.TOTAL_TOOL_COUNT = void 0;
|
|
40
|
+
exports.getLocalWalletAddress = getLocalWalletAddress;
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const os = __importStar(require("os"));
|
|
43
|
+
const path = __importStar(require("path"));
|
|
44
|
+
const server_js_1 = require("./server.js");
|
|
45
|
+
const tool_filter_js_1 = require("./tool-filter.js");
|
|
46
|
+
const config_js_1 = require("./config.js");
|
|
47
|
+
(0, config_js_1.hydrateEnvFromConfig)();
|
|
48
|
+
// Derived tool counts - single source of truth, kept in sync with the
|
|
49
|
+
// actual registered tools. Updates here propagate to banner, login,
|
|
50
|
+
// and doctor without manual edits.
|
|
51
|
+
exports.TOTAL_TOOL_COUNT = server_js_1.ALL_TOOLS.length;
|
|
52
|
+
exports.CORE_TOOL_COUNT = (() => {
|
|
53
|
+
const prev = process.env.FINCH_TOOLS;
|
|
54
|
+
try {
|
|
55
|
+
process.env.FINCH_TOOLS = "core";
|
|
56
|
+
return (0, tool_filter_js_1.filterTools)(server_js_1.ALL_TOOLS).length;
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
if (prev === undefined)
|
|
60
|
+
delete process.env.FINCH_TOOLS;
|
|
61
|
+
else
|
|
62
|
+
process.env.FINCH_TOOLS = prev;
|
|
63
|
+
}
|
|
64
|
+
})();
|
|
65
|
+
exports.CONVEX_SITE = process.env.FINCH_CONVEX_URL ?? "https://valuable-fish-533.convex.site";
|
|
66
|
+
exports.PKG_VERSION = (() => {
|
|
67
|
+
try {
|
|
68
|
+
const raw = fs.readFileSync(path.join(__dirname, "..", "package.json"), "utf8");
|
|
69
|
+
return JSON.parse(raw).version ?? "unknown";
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return "unknown";
|
|
73
|
+
}
|
|
74
|
+
})();
|
|
75
|
+
// Read wallet address from the encrypted JSON without decrypting -
|
|
76
|
+
// ethers stores the address in plaintext inside the keystore file.
|
|
77
|
+
function getLocalWalletAddress() {
|
|
78
|
+
try {
|
|
79
|
+
const walletPath = path.join(os.homedir(), ".finch", "wallet.json");
|
|
80
|
+
if (!fs.existsSync(walletPath))
|
|
81
|
+
return null;
|
|
82
|
+
const data = JSON.parse(fs.readFileSync(walletPath, "utf8"));
|
|
83
|
+
const addr = data.address;
|
|
84
|
+
if (!addr)
|
|
85
|
+
return null;
|
|
86
|
+
return addr.startsWith("0x") ? addr : `0x${addr}`;
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|