@tacuchi/agent-workflow-cli 23.0.0 → 24.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 +37 -1
- package/dist/adapters/postgres-readonly-tools.js +277 -0
- package/dist/adapters/postgres-readonly-tools.js.map +1 -0
- package/dist/application/database-mcp-server.js +168 -0
- package/dist/application/database-mcp-server.js.map +1 -0
- package/dist/application/database-mcp-stdio.js +137 -0
- package/dist/application/database-mcp-stdio.js.map +1 -0
- package/dist/application/database-tool-catalog.js +226 -0
- package/dist/application/database-tool-catalog.js.map +1 -0
- package/dist/application/dsn-reader-service.js +1 -1
- package/dist/application/lock-service.js +96 -31
- package/dist/application/lock-service.js.map +1 -1
- package/dist/application/logging/log-events.js +19 -3
- package/dist/application/logging/log-events.js.map +1 -1
- package/dist/application/logging/logger.js +2 -2
- package/dist/application/logging/logger.js.map +1 -1
- package/dist/application/mcp-connections-service.js +115 -41
- package/dist/application/mcp-connections-service.js.map +1 -1
- package/dist/application/mcp-doctor-service.js +98 -54
- package/dist/application/mcp-doctor-service.js.map +1 -1
- package/dist/application/mcp-entry-classification.js +60 -0
- package/dist/application/mcp-entry-classification.js.map +1 -0
- package/dist/application/mcp-host-reader.js +102 -86
- package/dist/application/mcp-host-reader.js.map +1 -1
- package/dist/application/mcp-host-receipt-service.js +399 -0
- package/dist/application/mcp-host-receipt-service.js.map +1 -0
- package/dist/application/mcp-host-receipt-store.js +122 -0
- package/dist/application/mcp-host-receipt-store.js.map +1 -0
- package/dist/application/mcp-host-receipts.js +28 -0
- package/dist/application/mcp-host-receipts.js.map +1 -0
- package/dist/application/mcp-host-writer.js +209 -38
- package/dist/application/mcp-host-writer.js.map +1 -1
- package/dist/application/mcp-launch-probe-service.js +142 -0
- package/dist/application/mcp-launch-probe-service.js.map +1 -0
- package/dist/application/mcp-migration-service.js +351 -0
- package/dist/application/mcp-migration-service.js.map +1 -0
- package/dist/application/mcp-native-host-check-service.js +154 -0
- package/dist/application/mcp-native-host-check-service.js.map +1 -0
- package/dist/application/mcp-receipt-registration-service.js +105 -0
- package/dist/application/mcp-receipt-registration-service.js.map +1 -0
- package/dist/application/mcp-receipt-removal-service.js +62 -0
- package/dist/application/mcp-receipt-removal-service.js.map +1 -0
- package/dist/application/mcp-remove-service.js +83 -24
- package/dist/application/mcp-remove-service.js.map +1 -1
- package/dist/application/mcp-scope-common.js +1 -1
- package/dist/application/mcp-scope-common.js.map +1 -1
- package/dist/application/mcp-setup-service.js +59 -24
- package/dist/application/mcp-setup-service.js.map +1 -1
- package/dist/application/mcp-stdio-probe.js +526 -0
- package/dist/application/mcp-stdio-probe.js.map +1 -0
- package/dist/application/mcp-test-connection-service.js +23 -50
- package/dist/application/mcp-test-connection-service.js.map +1 -1
- package/dist/application/self/host-states.js.map +1 -1
- package/dist/application/self/install-skill.js +4 -34
- package/dist/application/self/install-skill.js.map +1 -1
- package/dist/application/self/mcp-config.js +369 -59
- package/dist/application/self/mcp-config.js.map +1 -1
- package/dist/application/self/mcp-via-state.js +9 -6
- package/dist/application/self/mcp-via-state.js.map +1 -1
- package/dist/application/self/uninstall-skill.js +3 -18
- package/dist/application/self/uninstall-skill.js.map +1 -1
- package/dist/application/self/uninstall.js +4 -23
- package/dist/application/self/uninstall.js.map +1 -1
- package/dist/application/workspace-init-service.js +4 -6
- package/dist/application/workspace-init-service.js.map +1 -1
- package/dist/cli/commands/index.js +2 -0
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/mcp.js +642 -55
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/tool.js +141 -0
- package/dist/cli/commands/tool.js.map +1 -0
- package/dist/cli/help-groups.js +1 -1
- package/dist/cli/help-groups.js.map +1 -1
- package/dist/cli/main.js +189 -57
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/parser.js +5 -1
- package/dist/cli/parser.js.map +1 -1
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli/render.js +15 -2
- package/dist/cli/render.js.map +1 -1
- package/dist/cli/tui/components/host-admin-section.js +2 -46
- package/dist/cli/tui/components/host-admin-section.js.map +1 -1
- package/dist/cli/tui/tabs/mcp-tab-helpers.js +71 -0
- package/dist/cli/tui/tabs/mcp-tab-helpers.js.map +1 -1
- package/dist/cli/tui/tabs/mcp-tab.js +101 -42
- package/dist/cli/tui/tabs/mcp-tab.js.map +1 -1
- package/dist/domain/database-tools.js +445 -0
- package/dist/domain/database-tools.js.map +1 -0
- package/dist/domain/flow/authority.js +4 -0
- package/dist/domain/flow/authority.js.map +1 -1
- package/dist/domain/mcp-entry.js +131 -17
- package/dist/domain/mcp-entry.js.map +1 -1
- package/dist/domain/postgres-object-search.js +320 -0
- package/dist/domain/postgres-object-search.js.map +1 -0
- package/dist/domain/redaction.js +47 -0
- package/dist/domain/redaction.js.map +1 -0
- package/dist/domain/workline-mcp-entry.js +6 -9
- package/dist/domain/workline-mcp-entry.js.map +1 -1
- package/dist/ports/postgres-tools.js +10 -0
- package/dist/ports/postgres-tools.js.map +1 -0
- package/package.json +5 -1
- package/dist/application/mcp-dbhub-launcher.js +0 -216
- package/dist/application/mcp-dbhub-launcher.js.map +0 -1
- package/dist/application/self/mcp-offer.js +0 -96
- package/dist/application/self/mcp-offer.js.map +0 -1
|
@@ -1,7 +1,14 @@
|
|
|
1
|
-
import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
1
|
+
import { chmodSync, closeSync, existsSync, mkdirSync, openSync, readFileSync, renameSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
2
2
|
import { dirname } from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { validateDsnVarName, validateMcpInstance, } from "../domain/mcp-entry.js";
|
|
4
4
|
import { readDsnFile } from "./dsn-reader-service.js";
|
|
5
|
+
/** A corrupt registry is never silently treated as an empty registry. */
|
|
6
|
+
export class McpConnectionsError extends Error {
|
|
7
|
+
constructor(message = "mcp-connections.json no contiene una forma válida de registro MCP.") {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "McpConnectionsError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
5
12
|
export function readMcpConnections(paths, env) {
|
|
6
13
|
const stored = readStoredConnections(paths);
|
|
7
14
|
const dsn = readDsnFile(paths);
|
|
@@ -22,7 +29,16 @@ export function resolveMcpConnectionSelection(paths, input = {}) {
|
|
|
22
29
|
if (input.allConnections && input.instance !== undefined) {
|
|
23
30
|
return selectionFailure("MCP_CONNECTION_SELECTION_CONFLICT", "Usá --instance <nombre> o --all-connections, no ambos.");
|
|
24
31
|
}
|
|
25
|
-
|
|
32
|
+
let connections;
|
|
33
|
+
try {
|
|
34
|
+
connections = readStoredConnections(paths);
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
if (error instanceof McpConnectionsError) {
|
|
38
|
+
return selectionFailure("MCP_CONNECTION_INVALID", error.message);
|
|
39
|
+
}
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
26
42
|
if (connections.length === 0) {
|
|
27
43
|
return selectionFailure("NO_MCP_CONNECTIONS", "No hay conexiones MCP registradas. Registrá una con 'aw self mcp use-env --name <nombre> --dsn-var <VARIABLE>'.");
|
|
28
44
|
}
|
|
@@ -43,22 +59,26 @@ export function resolveMcpConnectionSelection(paths, input = {}) {
|
|
|
43
59
|
return selectionFailure("MCP_INSTANCE_REQUIRED", `Hay ${connections.length} conexiones MCP registradas. Indicá --instance <nombre> o --all-connections.`);
|
|
44
60
|
}
|
|
45
61
|
export function upsertMcpConnection(paths, input) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
62
|
+
return withConnectionsLock(paths, () => {
|
|
63
|
+
const connection = normalizeConnection(input);
|
|
64
|
+
const existing = readStoredConnections(paths);
|
|
65
|
+
const byName = new Map(existing.map((item) => [item.name, item]));
|
|
66
|
+
byName.set(connection.name, connection);
|
|
67
|
+
writeStoredConnections(paths, [...byName.values()].sort(compareConnections));
|
|
68
|
+
return { path: paths.userMcpConnectionsFile(), connection };
|
|
69
|
+
});
|
|
52
70
|
}
|
|
53
71
|
export function deleteMcpConnection(paths, input) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
72
|
+
return withConnectionsLock(paths, () => {
|
|
73
|
+
const validation = validateMcpInstance(input.name);
|
|
74
|
+
if (!validation.ok)
|
|
75
|
+
throw new Error(validation.error);
|
|
76
|
+
const name = validation.value;
|
|
77
|
+
const existing = readStoredConnections(paths);
|
|
78
|
+
const next = existing.filter((item) => item.name !== name);
|
|
79
|
+
writeStoredConnections(paths, next);
|
|
80
|
+
return { path: paths.userMcpConnectionsFile(), removed: next.length !== existing.length };
|
|
81
|
+
});
|
|
62
82
|
}
|
|
63
83
|
export function validateMcpConnectionInput(input) {
|
|
64
84
|
const name = validateMcpInstance(input.name);
|
|
@@ -67,7 +87,13 @@ export function validateMcpConnectionInput(input) {
|
|
|
67
87
|
const dsnVar = validateDsnVarName(input.dsnVar);
|
|
68
88
|
if (!dsnVar.ok)
|
|
69
89
|
return dsnVar;
|
|
70
|
-
|
|
90
|
+
if (input.provider !== undefined && input.provider !== "postgres") {
|
|
91
|
+
return {
|
|
92
|
+
ok: false,
|
|
93
|
+
error: `provider MCP inválido: '${input.provider}'. V1 sólo admite postgres.`,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
return { ok: true, value: { name: name.value, dsnVar: dsnVar.value, provider: "postgres" } };
|
|
71
97
|
}
|
|
72
98
|
function normalizeConnection(input) {
|
|
73
99
|
const validation = validateMcpConnectionInput(input);
|
|
@@ -84,49 +110,97 @@ function readStoredConnections(paths) {
|
|
|
84
110
|
return [];
|
|
85
111
|
const raw = readFileSync(file, "utf-8");
|
|
86
112
|
if (raw.trim().length === 0)
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
113
|
+
throw new McpConnectionsError();
|
|
114
|
+
let parsed;
|
|
115
|
+
try {
|
|
116
|
+
parsed = JSON.parse(raw);
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
throw new McpConnectionsError();
|
|
120
|
+
}
|
|
121
|
+
if (!isRecord(parsed) || !Array.isArray(parsed.connections))
|
|
122
|
+
throw new McpConnectionsError();
|
|
123
|
+
const version = parsed.version;
|
|
124
|
+
if (version !== 1 && version !== 2 && version !== undefined)
|
|
125
|
+
throw new McpConnectionsError();
|
|
91
126
|
const out = [];
|
|
127
|
+
const names = new Set();
|
|
92
128
|
for (const item of parsed.connections) {
|
|
93
|
-
if (!
|
|
94
|
-
|
|
129
|
+
if (!isStoredConnectionForVersion(item, version))
|
|
130
|
+
throw new McpConnectionsError();
|
|
95
131
|
const validation = validateMcpConnectionInput(item);
|
|
96
|
-
if (validation.ok)
|
|
97
|
-
|
|
132
|
+
if (!validation.ok)
|
|
133
|
+
throw new McpConnectionsError();
|
|
134
|
+
if (names.has(validation.value.name))
|
|
135
|
+
throw new McpConnectionsError();
|
|
136
|
+
names.add(validation.value.name);
|
|
137
|
+
out.push(validation.value);
|
|
98
138
|
}
|
|
99
|
-
return
|
|
139
|
+
return out.sort(compareConnections);
|
|
100
140
|
}
|
|
101
141
|
function writeStoredConnections(paths, connections) {
|
|
102
142
|
const file = paths.userMcpConnectionsFile();
|
|
103
143
|
mkdirSync(dirname(file), { recursive: true });
|
|
104
|
-
const payload = { version:
|
|
105
|
-
|
|
144
|
+
const payload = { version: 2, connections };
|
|
145
|
+
const temporary = `${file}.${process.pid}.${Date.now()}.tmp`;
|
|
146
|
+
writeFileSync(temporary, `${JSON.stringify(payload, null, 2)}\n`, "utf-8");
|
|
106
147
|
try {
|
|
107
|
-
chmodSync(
|
|
148
|
+
chmodSync(temporary, 0o600);
|
|
108
149
|
}
|
|
109
150
|
catch {
|
|
110
151
|
// ignore chmod failures
|
|
111
152
|
}
|
|
153
|
+
renameSync(temporary, file);
|
|
112
154
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
155
|
+
/** Serialize registry read-modify-write rather than risking a silent lost alias. */
|
|
156
|
+
function withConnectionsLock(paths, work) {
|
|
157
|
+
const file = paths.userMcpConnectionsFile();
|
|
158
|
+
const lock = `${file}.lock`;
|
|
159
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
160
|
+
let descriptor;
|
|
161
|
+
try {
|
|
162
|
+
descriptor = openSync(lock, "wx", 0o600);
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
const code = error !== null && typeof error === "object" ? error.code : undefined;
|
|
166
|
+
if (code === "EEXIST") {
|
|
167
|
+
throw new Error("Otro proceso está actualizando mcp-connections.json; reintentá la operación.");
|
|
168
|
+
}
|
|
169
|
+
throw error;
|
|
170
|
+
}
|
|
171
|
+
try {
|
|
172
|
+
return work();
|
|
173
|
+
}
|
|
174
|
+
finally {
|
|
175
|
+
try {
|
|
176
|
+
closeSync(descriptor);
|
|
177
|
+
}
|
|
178
|
+
finally {
|
|
179
|
+
try {
|
|
180
|
+
unlinkSync(lock);
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
// Fail closed on the next write instead of assuming a concurrent lock is stale.
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
122
187
|
}
|
|
123
188
|
function compareConnections(a, b) {
|
|
124
189
|
return a.name.localeCompare(b.name);
|
|
125
190
|
}
|
|
126
|
-
function
|
|
191
|
+
function isStoredConnectionForVersion(value, version) {
|
|
127
192
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
128
193
|
return false;
|
|
129
194
|
const record = value;
|
|
130
|
-
|
|
195
|
+
const keys = Object.keys(record).sort();
|
|
196
|
+
const expected = version === 2 ? ["dsnVar", "name", "provider"] : ["dsnVar", "name"];
|
|
197
|
+
return (keys.length === expected.length &&
|
|
198
|
+
keys.every((key, index) => key === expected[index]) &&
|
|
199
|
+
typeof record.name === "string" &&
|
|
200
|
+
typeof record.dsnVar === "string" &&
|
|
201
|
+
(version === 2 ? record.provider === "postgres" : record.provider === undefined));
|
|
202
|
+
}
|
|
203
|
+
function isRecord(value) {
|
|
204
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
131
205
|
}
|
|
132
206
|
//# sourceMappingURL=mcp-connections-service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-connections-service.js","sourceRoot":"","sources":["../../src/application/mcp-connections-service.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"mcp-connections-service.js","sourceRoot":"","sources":["../../src/application/mcp-connections-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { isDeepStrictEqual } from "node:util";
|
|
2
1
|
import { buildMcpEntry, } from "../domain/mcp-entry.js";
|
|
2
|
+
import { containsSensitiveData } from "../domain/redaction.js";
|
|
3
3
|
import { readDsnFile } from "./dsn-reader-service.js";
|
|
4
|
+
import { classifyMcpEntry } from "./mcp-entry-classification.js";
|
|
4
5
|
import { readMcpEntry } from "./mcp-host-reader.js";
|
|
5
6
|
import { resolveScopeDir } from "./mcp-scope-common.js";
|
|
6
7
|
export function runMcpDoctor(env, paths, input) {
|
|
@@ -9,7 +10,7 @@ export function runMcpDoctor(env, paths, input) {
|
|
|
9
10
|
const reports = [];
|
|
10
11
|
for (const host of input.hosts) {
|
|
11
12
|
for (const connection of input.connections) {
|
|
12
|
-
reports.push(buildReport(env, host, connection, scopeDir, dsn, input.scope));
|
|
13
|
+
reports.push(buildReport(env, host, connection, scopeDir, dsn, input.scope, input.namespace));
|
|
13
14
|
}
|
|
14
15
|
}
|
|
15
16
|
const summary = {
|
|
@@ -18,12 +19,20 @@ export function runMcpDoctor(env, paths, input) {
|
|
|
18
19
|
dsn_mismatch: reports.filter((r) => r.status === "dsn-mismatch").length,
|
|
19
20
|
missing_dsn: reports.filter((r) => r.status === "missing-dsn").length,
|
|
20
21
|
extra: reports.filter((r) => r.status === "extra-entry").length,
|
|
22
|
+
legacy_entry: reports.filter((r) => r.status === "legacy-entry").length,
|
|
23
|
+
foreign_entry: reports.filter((r) => r.status === "foreign-entry").length,
|
|
24
|
+
malformed_entry: reports.filter((r) => r.status === "malformed-entry").length,
|
|
21
25
|
};
|
|
22
26
|
return { scope: input.scope, scope_dir: scopeDir, reports, summary };
|
|
23
27
|
}
|
|
24
|
-
function buildReport(env, host, connection, scopeDir, dsn, scope) {
|
|
25
|
-
const entry = buildMcpEntry(connection.name, connection.dsnVar
|
|
28
|
+
function buildReport(env, host, connection, scopeDir, dsn, scope, namespace) {
|
|
29
|
+
const entry = buildMcpEntry(connection.name, connection.dsnVar, {
|
|
30
|
+
host,
|
|
31
|
+
scope,
|
|
32
|
+
...(namespace === undefined ? {} : { namespace }),
|
|
33
|
+
});
|
|
26
34
|
const snapshot = readMcpEntry(host, scopeDir, entry.name, scope);
|
|
35
|
+
const classification = classifyMcpEntry(host, snapshot, entry, connection);
|
|
27
36
|
const dsnKey = connection.dsnVar;
|
|
28
37
|
const dsnPresent = Boolean(env.get(dsnKey)) || Boolean(dsn.values[dsnKey]);
|
|
29
38
|
const dsnInfo = {
|
|
@@ -32,67 +41,102 @@ function buildReport(env, host, connection, scopeDir, dsn, scope) {
|
|
|
32
41
|
key: dsnKey,
|
|
33
42
|
present: dsnPresent,
|
|
34
43
|
};
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
const mcp = {
|
|
45
|
+
name: entry.name,
|
|
46
|
+
present: snapshot.exists || Boolean(snapshot.present),
|
|
47
|
+
matches: classification.state === "current",
|
|
48
|
+
};
|
|
49
|
+
const launchMode = scope === "workspace" ? "path-dependent" : "absolute";
|
|
50
|
+
const base = {
|
|
51
|
+
host,
|
|
52
|
+
instance: connection.name,
|
|
53
|
+
scope,
|
|
54
|
+
target: snapshot.target,
|
|
55
|
+
dsn: dsnInfo,
|
|
56
|
+
mcp,
|
|
57
|
+
entry_state: classification.state,
|
|
58
|
+
launch_mode: launchMode,
|
|
59
|
+
};
|
|
60
|
+
const entryDecision = entryStateDecision(classification.state, dsnPresent, entry.name, connection.name, snapshot.target, hasEmbeddedCredential(snapshot));
|
|
61
|
+
if (entryDecision !== undefined)
|
|
62
|
+
return { ...base, ...entryDecision };
|
|
50
63
|
if (!dsnPresent) {
|
|
51
64
|
return {
|
|
52
|
-
|
|
53
|
-
instance: connection.name,
|
|
54
|
-
scope,
|
|
55
|
-
target: snapshot.target,
|
|
56
|
-
dsn: dsnInfo,
|
|
57
|
-
mcp: { name: entry.name, present: true, matches },
|
|
65
|
+
...base,
|
|
58
66
|
status: "dsn-mismatch",
|
|
59
67
|
detail: `MCP '${entry.name}' registrado pero ${dsnKey} no está en ${dsn.path}`,
|
|
60
68
|
};
|
|
61
69
|
}
|
|
62
|
-
|
|
70
|
+
const detail = launchDetail(launchMode, host);
|
|
71
|
+
return {
|
|
72
|
+
...base,
|
|
73
|
+
status: "ok",
|
|
74
|
+
...(detail === undefined ? {} : { detail }),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function entryStateDecision(state, dsnPresent, entryName, instance, target, embeddedCredential) {
|
|
78
|
+
if (state === "current")
|
|
79
|
+
return undefined;
|
|
80
|
+
if (state === "missing") {
|
|
63
81
|
return {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
dsn: dsnInfo,
|
|
69
|
-
mcp: { name: entry.name, present: true, matches: false },
|
|
70
|
-
status: "extra-entry",
|
|
71
|
-
detail: `Entrada '${entry.name}' difiere del shape esperado (command/args/env)`,
|
|
82
|
+
status: dsnPresent ? "missing-mcp" : "missing-dsn",
|
|
83
|
+
detail: dsnPresent
|
|
84
|
+
? `Falta entrada MCP '${entryName}' en ${target}`
|
|
85
|
+
: `Ni DSN ni MCP registrados para ${instance}`,
|
|
72
86
|
};
|
|
73
87
|
}
|
|
74
88
|
return {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
scope,
|
|
78
|
-
target: snapshot.target,
|
|
79
|
-
dsn: dsnInfo,
|
|
80
|
-
mcp: { name: entry.name, present: true, matches: true },
|
|
81
|
-
status: "ok",
|
|
82
|
-
...(host === "warp"
|
|
83
|
-
? {
|
|
84
|
-
detail: "Recordá activar 'File-based MCP Servers' en Warp Settings para que Warp lo spawnee.",
|
|
85
|
-
}
|
|
86
|
-
: {}),
|
|
89
|
+
status: entryStateStatus(state),
|
|
90
|
+
detail: entryStateDetail(state, entryName, embeddedCredential),
|
|
87
91
|
};
|
|
88
92
|
}
|
|
89
|
-
function
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
93
|
+
function entryStateStatus(state) {
|
|
94
|
+
switch (state) {
|
|
95
|
+
case "malformed":
|
|
96
|
+
return "malformed-entry";
|
|
97
|
+
case "foreign":
|
|
98
|
+
return "foreign-entry";
|
|
99
|
+
case "known-legacy":
|
|
100
|
+
return "legacy-entry";
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function entryStateDetail(state, entryName, embeddedCredential) {
|
|
104
|
+
switch (state) {
|
|
105
|
+
case "malformed":
|
|
106
|
+
return embeddedCredential
|
|
107
|
+
? `${malformedEntryDetail(entryName)}; parece contener una credencial embebida; retirala y rotá esa credencial.`
|
|
108
|
+
: malformedEntryDetail(entryName);
|
|
109
|
+
case "foreign":
|
|
110
|
+
return embeddedCredential
|
|
111
|
+
? `La entrada '${entryName}' no coincide con una forma publicada por Workline y parece contener una credencial embebida; retirala y rotá esa credencial.`
|
|
112
|
+
: `La entrada '${entryName}' no coincide con una forma publicada por Workline`;
|
|
113
|
+
case "known-legacy":
|
|
114
|
+
return embeddedCredential
|
|
115
|
+
? `La entrada '${entryName}' usa un descriptor histórico de Workline y parece contener una credencial embebida; retirala y rotá esa credencial.`
|
|
116
|
+
: `La entrada '${entryName}' usa un descriptor histórico de Workline`;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function malformedEntryDetail(entryName) {
|
|
120
|
+
return `La entrada '${entryName}' no puede interpretarse de forma segura`;
|
|
121
|
+
}
|
|
122
|
+
/** Never return a value from a host entry; this only drives a safe remediation hint. */
|
|
123
|
+
function hasEmbeddedCredential(snapshot) {
|
|
124
|
+
return containsSensitiveData({
|
|
125
|
+
...(snapshot.command === undefined ? {} : { command: snapshot.command }),
|
|
126
|
+
...(snapshot.args === undefined ? {} : { args: snapshot.args }),
|
|
127
|
+
...(snapshot.env === undefined ? {} : { env: snapshot.env }),
|
|
128
|
+
...(snapshot.raw === undefined ? {} : { raw: snapshot.raw }),
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
function launchDetail(launchMode, host) {
|
|
132
|
+
const detail = [
|
|
133
|
+
...(launchMode === "path-dependent"
|
|
134
|
+
? ["Descriptor portable dependiente de PATH; la garantía absoluta aplica a user scope/TUI."]
|
|
135
|
+
: []),
|
|
136
|
+
...(host === "warp"
|
|
137
|
+
? ["Recordá activar 'File-based MCP Servers' en Warp Settings para que Warp lo spawnee."]
|
|
138
|
+
: []),
|
|
139
|
+
].join(" ");
|
|
140
|
+
return detail.length === 0 ? undefined : detail;
|
|
97
141
|
}
|
|
98
142
|
//# sourceMappingURL=mcp-doctor-service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-doctor-service.js","sourceRoot":"","sources":["../../src/application/mcp-doctor-service.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"mcp-doctor-service.js","sourceRoot":"","sources":["../../src/application/mcp-doctor-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { isDeepStrictEqual } from "node:util";
|
|
2
|
+
import { knownLegacyMcpEntries, mcpEntryShapeForHost, previousReliableMcpEntry, } from "../domain/mcp-entry.js";
|
|
3
|
+
import { WORKLINE_MCP_ENTRY_NAME, worklineMcpEntry } from "../domain/workline-mcp-entry.js";
|
|
4
|
+
export function classifyMcpEntry(host, snapshot, current, connection) {
|
|
5
|
+
const primary = classifySnapshot(host, snapshot, current, connection);
|
|
6
|
+
if (host === "claude" && snapshot.legacy_location && primary.state === "current") {
|
|
7
|
+
// A current descriptor in the old location is safe to move, but it must
|
|
8
|
+
// not be reported as fully current because Claude may still load it.
|
|
9
|
+
return { state: "known-legacy", legacy: current };
|
|
10
|
+
}
|
|
11
|
+
if (snapshot.secondary === undefined || primary.state !== "current")
|
|
12
|
+
return primary;
|
|
13
|
+
const secondary = classifySnapshot(host, snapshot.secondary, current, connection);
|
|
14
|
+
if (secondary.state === "missing")
|
|
15
|
+
return primary;
|
|
16
|
+
if (secondary.state === "current")
|
|
17
|
+
return { state: "known-legacy", legacy: current };
|
|
18
|
+
return secondary;
|
|
19
|
+
}
|
|
20
|
+
function classifySnapshot(host, snapshot, current, connection) {
|
|
21
|
+
if (!snapshot.exists) {
|
|
22
|
+
if (!snapshot.present)
|
|
23
|
+
return { state: "missing" };
|
|
24
|
+
// Readers retain a raw same-named scalar so it remains a foreign entry,
|
|
25
|
+
// whereas an unparseable container has no raw shape and is malformed.
|
|
26
|
+
return { state: snapshot.raw === undefined ? "malformed" : "foreign" };
|
|
27
|
+
}
|
|
28
|
+
if (snapshot.malformed ||
|
|
29
|
+
snapshot.raw === undefined ||
|
|
30
|
+
snapshot.command === undefined ||
|
|
31
|
+
snapshot.args === undefined) {
|
|
32
|
+
return { state: "malformed" };
|
|
33
|
+
}
|
|
34
|
+
if (isDeepStrictEqual(snapshot.raw, mcpEntryShapeForHost(host, current))) {
|
|
35
|
+
return { state: "current" };
|
|
36
|
+
}
|
|
37
|
+
const previous = previousReliableMcpEntry(current);
|
|
38
|
+
if (previous !== undefined &&
|
|
39
|
+
isDeepStrictEqual(snapshot.raw, mcpEntryShapeForHost(host, previous))) {
|
|
40
|
+
return { state: "known-legacy", legacy: previous };
|
|
41
|
+
}
|
|
42
|
+
const legacy = knownLegacyMcpEntries(connection.name, connection.dsnVar).find((entry) => isDeepStrictEqual(snapshot.raw, mcpEntryShapeForHost(host, entry)));
|
|
43
|
+
if (legacy !== undefined)
|
|
44
|
+
return { state: "known-legacy", legacy };
|
|
45
|
+
// Before database MCP used the connection name, surface installation wrote a
|
|
46
|
+
// single elicitation server called `agent-workflow`. A database connection
|
|
47
|
+
// with that valid name must not be rejected or overwrite it implicitly: its
|
|
48
|
+
// exact historic shape is migratable only through the explicit migration
|
|
49
|
+
// flow. Every other same-named shape remains foreign.
|
|
50
|
+
const elicitation = legacyElicitationEntry(host, current);
|
|
51
|
+
if (elicitation !== undefined &&
|
|
52
|
+
isDeepStrictEqual(snapshot.raw, mcpEntryShapeForHost(host, elicitation))) {
|
|
53
|
+
return { state: "known-legacy", legacy: elicitation };
|
|
54
|
+
}
|
|
55
|
+
return { state: "foreign" };
|
|
56
|
+
}
|
|
57
|
+
function legacyElicitationEntry(host, current) {
|
|
58
|
+
return current.name === WORKLINE_MCP_ENTRY_NAME ? worklineMcpEntry(host) : undefined;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=mcp-entry-classification.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-entry-classification.js","sourceRoot":"","sources":["../../src/application/mcp-entry-classification.ts"],"names":[],"mappings":"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"}
|