@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.
Files changed (50) hide show
  1. package/README.md +74 -39
  2. package/dist/_zod-helpers.js +10 -0
  3. package/dist/cli-doctor.js +300 -0
  4. package/dist/cli-env.js +91 -0
  5. package/dist/cli-install.js +236 -0
  6. package/dist/cli-login.js +101 -0
  7. package/dist/cli-orders.js +175 -0
  8. package/dist/cli-setup.js +270 -0
  9. package/dist/cli-ui.js +168 -0
  10. package/dist/cli-vault.js +75 -0
  11. package/dist/cli.js +61 -1152
  12. package/dist/config.js +3 -2
  13. package/dist/enrichment-router.js +5 -18
  14. package/dist/finch-output.js +30 -29
  15. package/dist/finch-status.js +105 -40
  16. package/dist/local-vault.js +5 -12
  17. package/dist/output-schemas.js +3 -12
  18. package/dist/project.js +4 -13
  19. package/dist/server.js +13 -35
  20. package/dist/tool-filter.js +4 -13
  21. package/dist/tools/_solidity-scan.js +5 -14
  22. package/dist/tools/agents.js +14 -26
  23. package/dist/tools/deep-research-constants.js +33 -0
  24. package/dist/tools/deep-research-firecrawl.js +88 -0
  25. package/dist/tools/deep-research-planning.js +249 -0
  26. package/dist/tools/deep-research-synthesis.js +343 -0
  27. package/dist/tools/deep-research-text.js +158 -0
  28. package/dist/tools/deep-research-tools.js +90 -0
  29. package/dist/tools/deep-research.js +47 -938
  30. package/dist/tools/defi.js +4 -3
  31. package/dist/tools/insider.js +4 -14
  32. package/dist/tools/insight.js +7 -6
  33. package/dist/tools/market.js +16 -15
  34. package/dist/tools/memory.js +43 -61
  35. package/dist/tools/monitor.js +7 -6
  36. package/dist/tools/os.js +7 -85
  37. package/dist/tools/research.js +7 -6
  38. package/dist/tools/rh-mcp-constants.js +65 -0
  39. package/dist/tools/rh-mcp-dex.js +107 -0
  40. package/dist/tools/rh-mcp-provider.js +127 -0
  41. package/dist/tools/rh-mcp-resolve.js +137 -0
  42. package/dist/tools/rh-mcp-risk.js +230 -0
  43. package/dist/tools/rh-mcp-safety.js +234 -0
  44. package/dist/tools/rh-mcp-swap.js +181 -0
  45. package/dist/tools/rh-mcp-tools.js +137 -0
  46. package/dist/tools/rh-mcp.js +75 -1191
  47. package/dist/tools/scanner.js +10 -9
  48. package/dist/tools/stake.js +7 -20
  49. package/dist/tools/vault.js +52 -59
  50. package/package.json +12 -9
package/README.md CHANGED
@@ -1,20 +1,12 @@
1
1
  <div align="center">
2
2
 
3
- <img src="assets/banner.svg" alt="Finch MCP" width="100%"/>
4
-
5
- # Finch MCP
6
-
7
- [![npm version](https://img.shields.io/npm/v/@finchagentic/mcp?color=000000&label=npm&logo=npm)](https://www.npmjs.com/package/@finchagentic/mcp)
8
- [![Official MCP Registry](https://img.shields.io/badge/MCP_Registry-io.github.finchagentic%2Fmcp-000000)](https://registry.modelcontextprotocol.io)
9
- [![License: MIT](https://img.shields.io/badge/license-MIT-000000.svg)](LICENSE)
10
- [![Node](https://img.shields.io/badge/node-%E2%89%A518-000000?logo=node.js&logoColor=white)](package.json)
11
- [![Tools: 116](https://img.shields.io/badge/tools-116-000000)](#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
- [App](https://app.finchagentic.com) · [Docs](https://docs.finch.com) · [npm](https://www.npmjs.com/package/@finchagentic/mcp) · [X](https://x.com/finchagentic)
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.6.5 finch install
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.6.5
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.6.2", "finch-mcp"]
48
+ "args": ["-y", "-p", "@finchagentic/mcp@4.7.3", "finch-mcp"]
57
49
  }
58
50
  }
59
51
  }
60
52
  ```
61
53
 
62
- ### Hermes
54
+ ### VS Code
63
55
 
64
- ```bash
65
- hermes mcp add finch -- npx -y @finchagentic/mcp@4.6.5
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. `vault_save` and `agent_spawn` accept an optional `workspaceProject` matching the webapp's Projects.
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.6.5 finch setup
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's model |
136
+ | Brain | your MCP clients model |
134
137
 
135
- ## Registry
138
+ Scheduled/cloud features still need an account. Core memory, vault, and public-data tools work offline of Finch cloud.
136
139
 
137
- Finch is listed in the [official MCP Registry](https://registry.modelcontextprotocol.io):
140
+ ## Configuration
138
141
 
139
- ```json
140
- { "name": "io.github.finchagentic/mcp", "version": "4.6.2" }
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
- ## Development
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
- This repository ships the published npm distribution. See [CHANGELOG.md](CHANGELOG.md) for release history and [SECURITY.md](SECURITY.md) for the security model.
156
+ Guided setup:
146
157
 
147
158
  ```bash
148
- npm ci
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
- ## Support
153
-
154
- - Issues: [github.com/finchagentic/mcp/issues](https://github.com/finchagentic/mcp/issues)
155
- - Docs: [docs.finch.com](https://docs.finch.com)
156
- - X: [@finchagentic](https://x.com/finchagentic)
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
- <div align="center">
159
-
160
- **Finch** — memory that survives every session.
195
+ ---
161
196
 
162
- </div>
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
+ }
@@ -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
+ }