@crscreditapi/finstack-mcp-server 0.10.0-80b4ec3 → 0.10.0-b823b70
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/.env.example +5 -0
- package/dist/toolLog.d.ts +1 -0
- package/dist/toolLog.js +59 -21
- package/package.json +1 -1
package/.env.example
CHANGED
|
@@ -15,4 +15,9 @@ FINSTACK_CHATBASE_SECRET=
|
|
|
15
15
|
# Support Autopsy observability: insert one row per tool call into the shared tool_calls table
|
|
16
16
|
# (n8n Postgres). Leave unset to emit a JSON log line instead. TOOL_LOG=off disables both.
|
|
17
17
|
TOOL_CALLS_DATABASE_URL=
|
|
18
|
+
# Preferred over the URL (no percent-encoding needed):
|
|
19
|
+
# TOOL_CALLS_PGHOST=
|
|
20
|
+
# TOOL_CALLS_PGUSER=n8n
|
|
21
|
+
# TOOL_CALLS_PGPASSWORD=
|
|
22
|
+
# TOOL_CALLS_PGDATABASE=n8n
|
|
18
23
|
# SSL is on by default (no sslmode needed in the URL). TOOL_CALLS_PGSSL=off for a local DB.
|
package/dist/toolLog.d.ts
CHANGED
package/dist/toolLog.js
CHANGED
|
@@ -18,21 +18,46 @@ const ENABLED = (process.env.TOOL_LOG || 'on').toLowerCase() !== 'off';
|
|
|
18
18
|
// TOOL_CALLS_PGSSL=off disables it for a local database.
|
|
19
19
|
const DB_URL = (process.env.TOOL_CALLS_DATABASE_URL || '').replace(/[?&]sslmode=[^&]+/, '').replace(/\?$/, '');
|
|
20
20
|
const DB_SSL = (process.env.TOOL_CALLS_PGSSL || 'on').toLowerCase() === 'off' ? false : { rejectUnauthorized: false };
|
|
21
|
+
// Either a URL (password must be percent-encoded) or discrete variables, which need no
|
|
22
|
+
// encoding and are therefore preferred: TOOL_CALLS_PGHOST, TOOL_CALLS_PGUSER,
|
|
23
|
+
// TOOL_CALLS_PGPASSWORD, TOOL_CALLS_PGDATABASE (default n8n), TOOL_CALLS_PGPORT (default 5432).
|
|
24
|
+
function poolConfig() {
|
|
25
|
+
const base = { max: 2, idleTimeoutMillis: 30_000, connectionTimeoutMillis: 3_000, ssl: DB_SSL };
|
|
26
|
+
const host = process.env.TOOL_CALLS_PGHOST;
|
|
27
|
+
if (host) {
|
|
28
|
+
return {
|
|
29
|
+
...base,
|
|
30
|
+
host,
|
|
31
|
+
port: Number(process.env.TOOL_CALLS_PGPORT || 5432),
|
|
32
|
+
user: process.env.TOOL_CALLS_PGUSER || 'n8n',
|
|
33
|
+
password: process.env.TOOL_CALLS_PGPASSWORD || '',
|
|
34
|
+
database: process.env.TOOL_CALLS_PGDATABASE || 'n8n',
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
if (DB_URL)
|
|
38
|
+
return { ...base, connectionString: DB_URL };
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
21
41
|
const STREAM = (process.env.MCP_TRANSPORT || 'stdio') === 'http' ? process.stdout : process.stderr;
|
|
22
42
|
let pool = null;
|
|
23
43
|
let lastDbErrorAt = 0;
|
|
44
|
+
let poolBroken = false;
|
|
24
45
|
function getPool() {
|
|
25
|
-
if (
|
|
46
|
+
if (poolBroken)
|
|
26
47
|
return null;
|
|
27
48
|
if (!pool) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
49
|
+
const cfg = poolConfig();
|
|
50
|
+
if (!cfg)
|
|
51
|
+
return null;
|
|
52
|
+
try {
|
|
53
|
+
pool = new pg.Pool(cfg);
|
|
54
|
+
pool.on('error', (err) => warnDb(err));
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
poolBroken = true; // bad config (e.g. unencoded password in the URL): fall back to log lines
|
|
58
|
+
warnDb(err);
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
36
61
|
}
|
|
37
62
|
return pool;
|
|
38
63
|
}
|
|
@@ -79,18 +104,31 @@ const INSERT = `INSERT INTO tool_calls
|
|
|
79
104
|
(trace_id, channel, agent, server, tool, args_hash, args_summary, started_at,
|
|
80
105
|
duration_ms, ok, error_class, error_message, result_bytes, truncated, upstream_status)
|
|
81
106
|
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15)`;
|
|
107
|
+
/** Never throws: a logging problem must never fail a tool call. */
|
|
82
108
|
export function logToolCall(e) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
109
|
+
try {
|
|
110
|
+
if (!ENABLED)
|
|
111
|
+
return;
|
|
112
|
+
const r = toRecord(e);
|
|
113
|
+
const p = getPool();
|
|
114
|
+
if (!p) {
|
|
115
|
+
STREAM.write(JSON.stringify({ ts: new Date().toISOString(), kind: 'tool_call', ...r }) + '\n');
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
try {
|
|
119
|
+
p.query(INSERT, [
|
|
120
|
+
r.trace_id, r.channel, r.agent, r.server, r.tool, r.args_hash, JSON.stringify(r.args_summary),
|
|
121
|
+
r.started_at, r.duration_ms, r.ok, r.error_class, r.error_message, r.result_bytes,
|
|
122
|
+
r.truncated, r.upstream_status,
|
|
123
|
+
]).catch(warnDb);
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
// pg can throw synchronously on an unparseable connection string
|
|
127
|
+
poolBroken = true;
|
|
128
|
+
warnDb(err);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
catch (err) {
|
|
132
|
+
warnDb(err);
|
|
90
133
|
}
|
|
91
|
-
p.query(INSERT, [
|
|
92
|
-
r.trace_id, r.channel, r.agent, r.server, r.tool, r.args_hash, JSON.stringify(r.args_summary),
|
|
93
|
-
r.started_at, r.duration_ms, r.ok, r.error_class, r.error_message, r.result_bytes,
|
|
94
|
-
r.truncated, r.upstream_status,
|
|
95
|
-
]).catch(warnDb);
|
|
96
134
|
}
|