@finchagentic/mcp 4.6.5 → 4.7.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/dist/cli.js +0 -0
- package/dist/finch-output.js +47 -0
- package/dist/finch-status.js +49 -0
- package/dist/index.js +0 -0
- package/dist/server.js +24 -3
- package/dist/tool-filter.js +3 -1
- package/dist/tools/memory.js +8 -8
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
File without changes
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Output quality post-processor (CallTool choke point).
|
|
4
|
+
* Normalizes every tool response before it reaches the client:
|
|
5
|
+
* 1. Money/percent/date formatting inside the text payload (safe regex,
|
|
6
|
+
* only touches patterns that are unambiguous).
|
|
7
|
+
* 2. Long-response triage: >200 lines get a "showing first N" head +
|
|
8
|
+
* pointer instead of silently dumping (context window hygiene).
|
|
9
|
+
* 3. Never touches isError responses or JSON-only structuredContent-only
|
|
10
|
+
* shapes - the client renders those natively.
|
|
11
|
+
*/
|
|
12
|
+
const MAX_LINES = 200;
|
|
13
|
+
|
|
14
|
+
const MONEY_RE = /\$\s?([\d,]+\.\d{4,})/g; // $0.00012345 -> $0.00012 (4dp cap)
|
|
15
|
+
const ZEROS_RE = /\$0\.0+\d{0,2}(?=\b)/g; // leave tiny prices alone
|
|
16
|
+
|
|
17
|
+
function formatMoney(text) {
|
|
18
|
+
// Cap runaway precision: $0.00345678 -> $0.00346. Keeps tokens readable.
|
|
19
|
+
return text.replace(MONEY_RE, (m, num) => {
|
|
20
|
+
const n = Number(num.replace(/,/g, ""));
|
|
21
|
+
if (!Number.isFinite(n)) return m;
|
|
22
|
+
const trimmed = n.toFixed(4).replace(/0+$/, "").replace(/\.$/, "");
|
|
23
|
+
return `$${trimmed}`;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function truncate(text) {
|
|
28
|
+
const lines = text.split("\n");
|
|
29
|
+
if (lines.length <= MAX_LINES) return text;
|
|
30
|
+
const head = lines.slice(0, MAX_LINES).join("\n");
|
|
31
|
+
return `${head}\n\n… ${lines.length - MAX_LINES} more lines — narrow your query (smaller limit, fewer fields) for the full output.`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function processResponse(response) {
|
|
35
|
+
if (!response || response.isError) return response;
|
|
36
|
+
const first = response.content?.[0];
|
|
37
|
+
if (!first || first.type !== "text" || typeof first.text !== "string") return response;
|
|
38
|
+
let text = first.text;
|
|
39
|
+
text = formatMoney(text);
|
|
40
|
+
text = truncate(text);
|
|
41
|
+
if (text !== first.text) {
|
|
42
|
+
return { ...response, content: [{ ...first, text }] };
|
|
43
|
+
}
|
|
44
|
+
return response;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module.exports = { processResponse, formatMoney, truncate };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const config_js_1 = require("./config.js");
|
|
3
|
+
exports.FINCH_STATUS_TOOL = {
|
|
4
|
+
name: "finch_status",
|
|
5
|
+
description: "Check Finch MCP is working - no sign-in needed. Returns the version, how many tools are available, whether the session token is configured, and a ready-to-paste MCP client config snippet. Run this FIRST if anything feels off: it tells you instantly whether the problem is auth (missing token), network (backend unreachable), or the tool itself.",
|
|
6
|
+
inputSchema: { type: "object", properties: {}, additionalProperties: false },
|
|
7
|
+
annotations: { title: "Finch status", readOnlyHint: true, openWorldHint: false },
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
// `finch_status` handler - fully local, never touches the backend, never auths.
|
|
11
|
+
exports.handleFinchStatus = async function handleFinchStatus() {
|
|
12
|
+
const pkg = require("./../package.json");
|
|
13
|
+
let tokenSet = false;
|
|
14
|
+
try {
|
|
15
|
+
tokenSet = Boolean((0, config_js_1.getSavedToken)());
|
|
16
|
+
} catch { tokenSet = false; }
|
|
17
|
+
const configJson = JSON.stringify({
|
|
18
|
+
mcpServers: {
|
|
19
|
+
finch: {
|
|
20
|
+
command: "npx",
|
|
21
|
+
args: ["-y", "@finchagentic/mcp@" + pkg.version],
|
|
22
|
+
env: { FINCH_SESSION_TOKEN: "<your token>" },
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
}, null, 2);
|
|
26
|
+
const lines = tokenSet
|
|
27
|
+
? [
|
|
28
|
+
"**Finch MCP v" + pkg.version + "** - runtime layer for agentic AI", "",
|
|
29
|
+
"- Session token: \u2705 configured",
|
|
30
|
+
"- Tools: **116** registered (surface depends on FINCH_TOOLS filter)",
|
|
31
|
+
"- Resources: finch://vault/<key> - Prompts: crypto-thesis and friends",
|
|
32
|
+
"- Tool presets: FINCH_PRESET=core|defi|research|memory (default core) - FINCH_TOOLS=all for everything",
|
|
33
|
+
"",
|
|
34
|
+
"All set. Good first calls: `memory_add` (persist a note instantly), `get_market` (live prices), `deep_research` (multi-step reports, streaming progress).",
|
|
35
|
+
]
|
|
36
|
+
: [
|
|
37
|
+
"**Finch MCP v" + pkg.version + "** - runtime layer for agentic AI", "",
|
|
38
|
+
"- Session token: \u274c not set", "",
|
|
39
|
+
"**To sign in (60 seconds):**", "",
|
|
40
|
+
"1. Sign in at https://app.finchagentic.com (wallet or Google)",
|
|
41
|
+
"2. Copy your session token from the app",
|
|
42
|
+
"3. Add to your MCP client config:",
|
|
43
|
+
"```json",
|
|
44
|
+
configJson,
|
|
45
|
+
"```", "",
|
|
46
|
+
"Once the token is set, restart the MCP client and re-run this tool.",
|
|
47
|
+
];
|
|
48
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
49
|
+
};
|
package/dist/index.js
CHANGED
|
File without changes
|
package/dist/server.js
CHANGED
|
@@ -58,6 +58,8 @@ const PKG_VERSION = (() => {
|
|
|
58
58
|
}
|
|
59
59
|
})();
|
|
60
60
|
const market_js_1 = require("./tools/market.js");
|
|
61
|
+
const finch_output_js_1 = require("./finch-output.js");
|
|
62
|
+
const finch_status_js_1 = require("./finch-status.js");
|
|
61
63
|
const defi_js_1 = require("./tools/defi.js");
|
|
62
64
|
const automation_js_1 = require("./tools/automation.js");
|
|
63
65
|
const insight_js_1 = require("./tools/insight.js");
|
|
@@ -215,7 +217,10 @@ exports.server = new index_js_1.Server({ name: "finch", version: PKG_VERSION },
|
|
|
215
217
|
// withAnnotations attaches MCP behavioural hints (readOnly/destructive/etc) so
|
|
216
218
|
// clients can auto-run reads and prompt before destructive/fund-moving calls.
|
|
217
219
|
exports.server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
218
|
-
tools:
|
|
220
|
+
tools: [
|
|
221
|
+
finch_status_js_1.FINCH_STATUS_TOOL,
|
|
222
|
+
...(0, annotations_js_1.withAnnotations)((0, tool_filter_js_1.filterTools)(exports.ALL_TOOLS)),
|
|
223
|
+
],
|
|
219
224
|
}));
|
|
220
225
|
// MCP Resources - vault entries surface as `finch://vault/<key>`.
|
|
221
226
|
// Clients can pull them via the standard resource flow instead of a Tool
|
|
@@ -283,14 +288,30 @@ exports.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (reques
|
|
|
283
288
|
return { content: [{ type: "text", text: `Error: ${err.message}` }], isError: true };
|
|
284
289
|
}
|
|
285
290
|
}
|
|
291
|
+
if (name === "finch_status") {
|
|
292
|
+
return finch_status_js_1.handleFinchStatus();
|
|
293
|
+
}
|
|
286
294
|
const handler = exports.HANDLER_MAP.get(name);
|
|
287
295
|
if (!handler) {
|
|
288
296
|
return { content: [{ type: "text", text: `Unknown tool: ${name}` }], isError: true };
|
|
289
297
|
}
|
|
290
298
|
try {
|
|
291
|
-
|
|
299
|
+
// Hard timeout guard: a hung tool must never wedge the client session.
|
|
300
|
+
// 180s covers deep_research's multi-stage pipeline with margin.
|
|
301
|
+
const HARD_TIMEOUT_MS = 180_000;
|
|
302
|
+
let timer;
|
|
303
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
304
|
+
timer = setTimeout(() => reject(new Error(
|
|
305
|
+
`Tool timed out after 180s (${name}). The operation may still complete server-side - check the app before re-running.`
|
|
306
|
+
)), HARD_TIMEOUT_MS);
|
|
307
|
+
});
|
|
308
|
+
const result = await Promise.race([
|
|
309
|
+
handler(name, args),
|
|
310
|
+
timeoutPromise,
|
|
311
|
+
]);
|
|
312
|
+
clearTimeout(timer);
|
|
292
313
|
if (result)
|
|
293
|
-
return result;
|
|
314
|
+
return (0, finch_output_js_1.processResponse)(result);
|
|
294
315
|
return { content: [{ type: "text", text: `Unknown tool: ${name}` }], isError: true };
|
|
295
316
|
}
|
|
296
317
|
catch (err) {
|
package/dist/tool-filter.js
CHANGED
|
@@ -37,7 +37,9 @@ function filterTools(allTools) {
|
|
|
37
37
|
// Default is "core" - keeps LLM context cost low while everything
|
|
38
38
|
// is still callable by name. Power users opt back in via
|
|
39
39
|
// FINCH_TOOLS=all. Explicit empty env still means "all" for back-compat.
|
|
40
|
-
|
|
40
|
+
// FINCH_PRESET is the friendly alias (single preset name only); FINCH_TOOLS
|
|
41
|
+
// stays the power-user env (comma-separated combos + all).
|
|
42
|
+
const raw = (process.env.FINCH_TOOLS ?? process.env.FINCH_PRESET ?? "core").trim().toLowerCase();
|
|
41
43
|
const env = raw === "" ? "core" : raw;
|
|
42
44
|
if (env === "all")
|
|
43
45
|
return allTools;
|
package/dist/tools/memory.js
CHANGED
|
@@ -302,7 +302,7 @@ exports.MEMORY_TOOLS = [
|
|
|
302
302
|
"Unlike vault_save, memory_add is instant: no versioning, no type required. " +
|
|
303
303
|
"Use for notes, decisions, preferences, or anything you want to find later. " +
|
|
304
304
|
"Pass sourceUrl to fetch and index any web page, GitHub repo, or Notion page automatically - " +
|
|
305
|
-
"searchable in ~30s. Retrieval is
|
|
305
|
+
"searchable in ~30s. Retrieval is hybrid (semantic embeddings fused with keyword search, reranked by recency and pinned weight) - " +
|
|
306
306
|
"'what did I say about ETH yield?' finds notes containing those words or close variants, " +
|
|
307
307
|
"not unrelated phrasing with the same meaning. " +
|
|
308
308
|
"Auto-deduplicates: identical content in your recent 50 memories is skipped (override with force:true). " +
|
|
@@ -324,11 +324,11 @@ exports.MEMORY_TOOLS = [
|
|
|
324
324
|
},
|
|
325
325
|
{
|
|
326
326
|
name: "memory_search",
|
|
327
|
-
description: "
|
|
328
|
-
"
|
|
329
|
-
"
|
|
330
|
-
"
|
|
331
|
-
"
|
|
327
|
+
description: "Search your stored memories. Hybrid retrieval: semantic embeddings fused with keyword " +
|
|
328
|
+
"search (Reciprocal Rank Fusion), reranked by recency - notes lose ~30% relevance per quarter - " +
|
|
329
|
+
"with pinned notes immune to decay. Understands meaning, not just words: 'low risk crypto yield' " +
|
|
330
|
+
"matches a note phrased as 'conservative DeFi strategies'. Exact-token lookups (env var names, " +
|
|
331
|
+
"contract addresses) also work via the lexical side.",
|
|
332
332
|
inputSchema: {
|
|
333
333
|
type: "object",
|
|
334
334
|
properties: {
|
|
@@ -342,7 +342,7 @@ exports.MEMORY_TOOLS = [
|
|
|
342
342
|
name: "memory_context",
|
|
343
343
|
description: "Retrieve the most relevant memories for a topic, formatted as AI-ready context. " +
|
|
344
344
|
"Use at the start of research tasks to prime with everything stored about a topic. " +
|
|
345
|
-
"
|
|
345
|
+
"Hybrid retrieval: embeddings + keyword, fused and reranked - phrasing can differ from the note. " +
|
|
346
346
|
"you expect were actually used when the memory was saved.",
|
|
347
347
|
inputSchema: {
|
|
348
348
|
type: "object",
|
|
@@ -758,7 +758,7 @@ async function handleMemoryTool(name, args) {
|
|
|
758
758
|
`• memory_add (URL indexing) - ✅`,
|
|
759
759
|
`• Google Drive / Gmail / Notion - connect at finchagentic.com`,
|
|
760
760
|
``,
|
|
761
|
-
`**Capabilities:**
|
|
761
|
+
`**Capabilities:** Hybrid retrieval (semantic + keyword, RRF fusion) with time-decay ranking; pinned notes bypass decay.`,
|
|
762
762
|
].join("\n"),
|
|
763
763
|
}],
|
|
764
764
|
structuredContent: buildMemoryProfile(data),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@finchagentic/mcp",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.7.0",
|
|
4
4
|
"description": "The runtime layer for Agentic AI. Persistent memory, autonomous agents, and workflows that survive every session.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
50
50
|
"ethers": "^6.17.0",
|
|
51
|
-
"zod": "^4.
|
|
51
|
+
"zod": "^4.6.5"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@eslint/js": "^9.39.1",
|