@deerdesign/deertools 1.2.35 → 1.3.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/package.json +1 -1
- package/src/baselinker/mcp-server.js +45 -24
- package/src/baselinker-commands.js +1 -2
- package/src/catalog/cli-commands.js +19 -0
- package/src/catalog/mcp-server.js +178 -0
- package/src/cli.js +8 -1
- package/src/commands.js +100 -71
- package/src/deliveries/cli-commands.js +19 -0
- package/src/deliveries/mcp-server.js +164 -0
- package/src/doctor.js +1 -1
- package/src/estimate/auth.js +110 -0
- package/src/estimate/cli-commands.js +161 -0
- package/src/estimate/client.js +1787 -0
- package/src/estimate/default-templates-snapshot.json +1 -0
- package/src/estimate/domain.js +1016 -0
- package/src/estimate/mcp-server.js +592 -0
- package/src/registry.js +4 -4
- package/src/skills-hub.js +14 -2
package/package.json
CHANGED
|
@@ -117,33 +117,54 @@ async function handleMcpMessage(msg, client = null, mode = 'catalog') {
|
|
|
117
117
|
|
|
118
118
|
function runBaseLinkerMcpServer(options = {}) {
|
|
119
119
|
const { mode = 'catalog' } = options;
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
});
|
|
120
|
+
return new Promise((resolve) => {
|
|
121
|
+
let pendingCount = 0;
|
|
122
|
+
let isClosed = false;
|
|
123
|
+
let closeResolve = null;
|
|
125
124
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
125
|
+
const rl = readline.createInterface({
|
|
126
|
+
input: process.stdin,
|
|
127
|
+
output: process.stdout,
|
|
128
|
+
terminal: false
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
rl.on('line', async line => {
|
|
132
|
+
const trimmed = line.trim();
|
|
133
|
+
if (!trimmed) return;
|
|
134
|
+
pendingCount++;
|
|
135
|
+
try {
|
|
136
|
+
const msg = JSON.parse(trimmed);
|
|
137
|
+
const res = await handleMcpMessage(msg, null, mode);
|
|
138
|
+
if (res) {
|
|
139
|
+
process.stdout.write(JSON.stringify(res) + '\n');
|
|
140
|
+
}
|
|
141
|
+
} catch (err) {
|
|
142
|
+
const errRes = {
|
|
143
|
+
jsonrpc: '2.0',
|
|
144
|
+
id: null,
|
|
145
|
+
error: { code: -32700, message: 'Parse error: ' + err.message }
|
|
146
|
+
};
|
|
147
|
+
process.stdout.write(JSON.stringify(errRes) + '\n');
|
|
148
|
+
} finally {
|
|
149
|
+
pendingCount--;
|
|
150
|
+
if (isClosed && pendingCount === 0 && closeResolve) {
|
|
151
|
+
closeResolve();
|
|
152
|
+
}
|
|
134
153
|
}
|
|
135
|
-
}
|
|
136
|
-
const errRes = {
|
|
137
|
-
jsonrpc: '2.0',
|
|
138
|
-
id: null,
|
|
139
|
-
error: { code: -32700, message: 'Parse error: ' + err.message }
|
|
140
|
-
};
|
|
141
|
-
process.stdout.write(JSON.stringify(errRes) + '\n');
|
|
142
|
-
}
|
|
143
|
-
});
|
|
154
|
+
});
|
|
144
155
|
|
|
145
|
-
|
|
146
|
-
|
|
156
|
+
rl.on('close', () => {
|
|
157
|
+
isClosed = true;
|
|
158
|
+
if (pendingCount === 0) {
|
|
159
|
+
resolve();
|
|
160
|
+
} else {
|
|
161
|
+
closeResolve = resolve;
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
process.on('SIGINT', () => { rl.close(); resolve(); });
|
|
166
|
+
process.on('SIGTERM', () => { rl.close(); resolve(); });
|
|
167
|
+
});
|
|
147
168
|
}
|
|
148
169
|
|
|
149
170
|
module.exports = {
|
|
@@ -79,8 +79,7 @@ Zgodnie ze standardem architektonicznym DeerTools CLI:
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
if (sub === 'mcp') {
|
|
82
|
-
runBaseLinkerMcpServer({ mode: flags.all ? 'all' : 'catalog' });
|
|
83
|
-
return;
|
|
82
|
+
return await runBaseLinkerMcpServer({ mode: flags.all ? 'all' : 'catalog' });
|
|
84
83
|
}
|
|
85
84
|
|
|
86
85
|
if (sub === 'sync-schema') {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const { runCatalogMcpServer } = require('./mcp-server');
|
|
3
|
+
|
|
4
|
+
async function cmdCatalog(pos, flags) {
|
|
5
|
+
const sub = pos[0] || 'help';
|
|
6
|
+
|
|
7
|
+
if (sub === 'mcp') {
|
|
8
|
+
return await runCatalogMcpServer();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
console.log(`Użycie deertools catalog:
|
|
12
|
+
deertools catalog mcp - Uruchamia serwer MCP Katalogu Connect (stdio)
|
|
13
|
+
`);
|
|
14
|
+
return 0;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports = {
|
|
18
|
+
cmdCatalog
|
|
19
|
+
};
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const readline = require('readline');
|
|
3
|
+
const credentials = require('../credentials');
|
|
4
|
+
const { getProduct } = require('../registry');
|
|
5
|
+
|
|
6
|
+
const PROTOCOL_VERSION = '2024-11-05';
|
|
7
|
+
const SERVER_INFO = { name: 'deer-catalog-mcp', version: '1.3.0' };
|
|
8
|
+
|
|
9
|
+
const FALLBACK_CATALOG_TOOLS = [
|
|
10
|
+
{
|
|
11
|
+
name: 'catalog_search_products',
|
|
12
|
+
description: 'Wyszukuje produkty wykończeniowe w Katalogu Connect (~17 tys. pozycji) z filtrowaniem po pakiecie (Smart Life, Modern Life, High Life) i kategorii.',
|
|
13
|
+
inputSchema: {
|
|
14
|
+
type: 'object',
|
|
15
|
+
properties: {
|
|
16
|
+
query: { type: 'string' },
|
|
17
|
+
package: { type: 'string' },
|
|
18
|
+
category: { type: 'string' },
|
|
19
|
+
limit: { type: 'number' }
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: 'catalog_get_product',
|
|
25
|
+
description: 'Pobiera szczegóły pojedynczego produktu z Katalogu Connect po ID lub SKU.',
|
|
26
|
+
inputSchema: {
|
|
27
|
+
type: 'object',
|
|
28
|
+
properties: {
|
|
29
|
+
id: { type: 'string' },
|
|
30
|
+
sku: { type: 'string' }
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: 'catalog_list_categories',
|
|
36
|
+
description: 'Pobiera drzewo kategorii Katalogu Connect.',
|
|
37
|
+
inputSchema: { type: 'object', properties: {} }
|
|
38
|
+
}
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
function getCatalogKey() {
|
|
42
|
+
const p = getProduct('catalog');
|
|
43
|
+
const cred = credentials.getKey(p);
|
|
44
|
+
if (cred && cred.key) return cred.key;
|
|
45
|
+
if (process.env.CATALOG_API_KEY) return process.env.CATALOG_API_KEY;
|
|
46
|
+
if (process.env.DEERTOOLS_CATALOG_KEY) return process.env.DEERTOOLS_CATALOG_KEY;
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function ensureCatalogAuth() {
|
|
51
|
+
const key = getCatalogKey();
|
|
52
|
+
if (!key) {
|
|
53
|
+
throw new Error('Brak klucza API do Katalogu Connect. Zaloguj się poleceniem: deertools login catalog');
|
|
54
|
+
}
|
|
55
|
+
return key;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function forwardToCatalogMcp(req) {
|
|
59
|
+
const apiKey = ensureCatalogAuth();
|
|
60
|
+
const p = getProduct('catalog');
|
|
61
|
+
const endpoint = p.mcpEndpoint || 'https://ftzaobeixglnssemugjf.supabase.co/functions/v1/catalog-mcp';
|
|
62
|
+
|
|
63
|
+
const res = await fetch(endpoint, {
|
|
64
|
+
method: 'POST',
|
|
65
|
+
headers: {
|
|
66
|
+
'Content-Type': 'application/json',
|
|
67
|
+
'x-api-key': apiKey,
|
|
68
|
+
'Authorization': `Bearer ${apiKey}`
|
|
69
|
+
},
|
|
70
|
+
body: JSON.stringify(req)
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const text = await res.text();
|
|
74
|
+
let json = null;
|
|
75
|
+
try { json = JSON.parse(text); } catch (_) {}
|
|
76
|
+
|
|
77
|
+
if (!res.ok) {
|
|
78
|
+
const errorMsg = (json && (json.message || json.error)) || text;
|
|
79
|
+
return {
|
|
80
|
+
jsonrpc: '2.0',
|
|
81
|
+
id: req.id || null,
|
|
82
|
+
error: { code: -32000, message: `Katalog Connect MCP (${res.status}): ${errorMsg}` }
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return json !== null ? json : { jsonrpc: '2.0', id: req.id, result: { content: [{ type: 'text', text }] } };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async function handleMcpMessage(msg) {
|
|
90
|
+
if (!msg || typeof msg !== 'object') return null;
|
|
91
|
+
const { id, method } = msg;
|
|
92
|
+
|
|
93
|
+
if (method === 'initialize') {
|
|
94
|
+
return {
|
|
95
|
+
jsonrpc: '2.0',
|
|
96
|
+
id,
|
|
97
|
+
result: {
|
|
98
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
99
|
+
capabilities: { tools: {} },
|
|
100
|
+
serverInfo: SERVER_INFO
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (method === 'notifications/initialized') {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (method === 'tools/list') {
|
|
110
|
+
if (!getCatalogKey()) {
|
|
111
|
+
return { jsonrpc: '2.0', id, result: { tools: FALLBACK_CATALOG_TOOLS } };
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
const upstream = await forwardToCatalogMcp(msg);
|
|
115
|
+
if (upstream && upstream.result && Array.isArray(upstream.result.tools)) {
|
|
116
|
+
return upstream;
|
|
117
|
+
}
|
|
118
|
+
} catch (_) {}
|
|
119
|
+
return { jsonrpc: '2.0', id, result: { tools: FALLBACK_CATALOG_TOOLS } };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Forward tools/call to upstream
|
|
123
|
+
return await forwardToCatalogMcp(msg);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function runCatalogMcpServer() {
|
|
127
|
+
return new Promise((resolve) => {
|
|
128
|
+
let pendingCount = 0;
|
|
129
|
+
let isClosed = false;
|
|
130
|
+
let closeResolve = null;
|
|
131
|
+
|
|
132
|
+
const rl = readline.createInterface({
|
|
133
|
+
input: process.stdin,
|
|
134
|
+
output: process.stdout,
|
|
135
|
+
terminal: false
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
rl.on('line', async (line) => {
|
|
139
|
+
const trimmed = line.trim();
|
|
140
|
+
if (!trimmed) return;
|
|
141
|
+
pendingCount++;
|
|
142
|
+
try {
|
|
143
|
+
const msg = JSON.parse(trimmed);
|
|
144
|
+
const resp = await handleMcpMessage(msg);
|
|
145
|
+
if (resp) {
|
|
146
|
+
process.stdout.write(JSON.stringify(resp) + '\n');
|
|
147
|
+
}
|
|
148
|
+
} catch (e) {
|
|
149
|
+
process.stdout.write(JSON.stringify({
|
|
150
|
+
jsonrpc: '2.0',
|
|
151
|
+
id: null,
|
|
152
|
+
error: { code: -32700, message: `Parse error: ${e.message}` }
|
|
153
|
+
}) + '\n');
|
|
154
|
+
} finally {
|
|
155
|
+
pendingCount--;
|
|
156
|
+
if (isClosed && pendingCount === 0 && closeResolve) {
|
|
157
|
+
closeResolve();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
rl.on('close', () => {
|
|
163
|
+
isClosed = true;
|
|
164
|
+
if (pendingCount === 0) {
|
|
165
|
+
resolve();
|
|
166
|
+
} else {
|
|
167
|
+
closeResolve = resolve;
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
process.on('SIGINT', () => { rl.close(); resolve(); });
|
|
171
|
+
process.on('SIGTERM', () => { rl.close(); resolve(); });
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
module.exports = {
|
|
176
|
+
handleMcpMessage,
|
|
177
|
+
runCatalogMcpServer
|
|
178
|
+
};
|
package/src/cli.js
CHANGED
|
@@ -54,6 +54,12 @@ async function main(argv) {
|
|
|
54
54
|
baselinker: c.cmdBaseLinker,
|
|
55
55
|
rendermind: c.cmdRenderMind,
|
|
56
56
|
supplier: c.cmdSupplier,
|
|
57
|
+
estimate: c.cmdEstimate,
|
|
58
|
+
kosztorys: c.cmdEstimate,
|
|
59
|
+
catalog: c.cmdCatalog,
|
|
60
|
+
katalog: c.cmdCatalog,
|
|
61
|
+
deliveries: c.cmdDeliveries,
|
|
62
|
+
dostawy: c.cmdDeliveries,
|
|
57
63
|
update: require('./updater').cmdUpdate,
|
|
58
64
|
// Bezpiecznik architektoniczny: blokada bezpośrednich wywołań REST API z CLI
|
|
59
65
|
api: () => c.cmdBlockedDomain('api'),
|
|
@@ -72,7 +78,8 @@ async function main(argv) {
|
|
|
72
78
|
|
|
73
79
|
const cmd = pos.shift() || 'help';
|
|
74
80
|
|
|
75
|
-
const
|
|
81
|
+
const isMcp = cmd === 'mcp' || pos.includes('mcp') || pos.includes('serve');
|
|
82
|
+
const shouldCheck = !flags.json && !isMcp && cmd !== 'update' && process.env.NODE_ENV !== 'test';
|
|
76
83
|
const updatePromise = shouldCheck ? require('./updater').checkUpdate().catch(() => null) : null;
|
|
77
84
|
|
|
78
85
|
const finish = async (code = 0) => {
|
package/src/commands.js
CHANGED
|
@@ -91,17 +91,6 @@ async function cmdLogin(pos, flags) {
|
|
|
91
91
|
for (const product of products) {
|
|
92
92
|
out(`\n=== ${product.name} ===`);
|
|
93
93
|
try {
|
|
94
|
-
if (product.id === 'skills') {
|
|
95
|
-
const { loginSkillsBrowser } = require('./skills-login');
|
|
96
|
-
const entry = await loginSkillsBrowser({
|
|
97
|
-
port: flags.port ? Number(flags.port) : 0,
|
|
98
|
-
openBrowser: flags['no-open'] ? null : undefined,
|
|
99
|
-
log: out,
|
|
100
|
-
});
|
|
101
|
-
out(`✓ Zalogowano do DeerSkills Hub. Zakres: ${entry.scope}.`);
|
|
102
|
-
out(` Przegląd umiejętności: deertools skill list | Synchronizacja: deertools skill sync`);
|
|
103
|
-
continue;
|
|
104
|
-
}
|
|
105
94
|
const productScope = (product.id === 'rendermind' && !explicitRo && !flags.scope && !flags.admin)
|
|
106
95
|
? 'read write'
|
|
107
96
|
: scope;
|
|
@@ -310,29 +299,47 @@ function resolveDeertoolsBin() {
|
|
|
310
299
|
return 'deertools';
|
|
311
300
|
}
|
|
312
301
|
|
|
313
|
-
function buildMcpServersConfig(products, useFullBinPath = false) {
|
|
302
|
+
function buildMcpServersConfig(products, useFullBinPath = false, { remote = false } = {}) {
|
|
314
303
|
const servers = {};
|
|
315
304
|
const binCmd = useFullBinPath ? resolveDeertoolsBin() : 'deertools';
|
|
316
305
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
306
|
+
if (remote) {
|
|
307
|
+
// Opcjonalny tryb Remote HTTP (--remote) z nagłówkami x-api-key
|
|
308
|
+
const remoteApiKeyProducts = new Set(['estimate', 'catalog', 'deliveries', 'supplier']);
|
|
309
|
+
for (const p of products) {
|
|
310
|
+
if (remoteApiKeyProducts.has(p.id) && p.mcpEndpoint) {
|
|
311
|
+
const cred = credentials.getKey(p);
|
|
312
|
+
const key = cred ? cred.key : `${p.keyPrefix}<twój_klucz_api>`;
|
|
313
|
+
const srvKey = `deer-${p.id}`;
|
|
314
|
+
servers[srvKey] = {
|
|
315
|
+
url: p.mcpEndpoint,
|
|
316
|
+
headers: {
|
|
317
|
+
'x-api-key': key,
|
|
318
|
+
'Authorization': `Bearer ${key}`,
|
|
319
|
+
},
|
|
320
|
+
};
|
|
321
|
+
}
|
|
332
322
|
}
|
|
323
|
+
} else {
|
|
324
|
+
// Domyślny tryb Local stdio MCP dla wszystkich systemów DeerTools (działający lokalnie w imieniu użytkownika)
|
|
325
|
+
servers['deer-estimate'] = {
|
|
326
|
+
command: binCmd,
|
|
327
|
+
args: ['estimate', 'mcp'],
|
|
328
|
+
};
|
|
329
|
+
servers['deer-catalog'] = {
|
|
330
|
+
command: binCmd,
|
|
331
|
+
args: ['catalog', 'mcp'],
|
|
332
|
+
};
|
|
333
|
+
servers['deer-deliveries'] = {
|
|
334
|
+
command: binCmd,
|
|
335
|
+
args: ['deliveries', 'mcp'],
|
|
336
|
+
};
|
|
337
|
+
servers['deer-supplier'] = {
|
|
338
|
+
command: binCmd,
|
|
339
|
+
args: ['supplier', 'mcp'],
|
|
340
|
+
};
|
|
333
341
|
}
|
|
334
342
|
|
|
335
|
-
// Serwery MCP stdio (silniki z obsługą plików lokalnych CAD/Excel lub długich procesów AI)
|
|
336
343
|
servers['deer-rendermind'] = {
|
|
337
344
|
command: binCmd,
|
|
338
345
|
args: ['rendermind', 'mcp'],
|
|
@@ -349,45 +356,9 @@ function buildMcpServersConfig(products, useFullBinPath = false) {
|
|
|
349
356
|
return servers;
|
|
350
357
|
}
|
|
351
358
|
|
|
352
|
-
|
|
353
|
-
const sub = pos[0] || 'config';
|
|
354
|
-
const products = resolveProducts(pos[1]);
|
|
355
|
-
|
|
356
|
-
if (sub === 'list') {
|
|
357
|
-
const servers = buildMcpServersConfig(products, false);
|
|
358
|
-
if (flags.json) {
|
|
359
|
-
out(JSON.stringify(servers, null, 2));
|
|
360
|
-
return;
|
|
361
|
-
}
|
|
362
|
-
out('\n=== Zarejestrowane Serwery MCP Ekosystemu DeerTools ===\n');
|
|
363
|
-
for (const [name, cfg] of Object.entries(servers)) {
|
|
364
|
-
if (cfg.url) {
|
|
365
|
-
out(` • ${name.padEnd(18)} [Remote HTTP] ${cfg.url}`);
|
|
366
|
-
} else {
|
|
367
|
-
out(` • ${name.padEnd(18)} [Local stdio] ${cfg.command} ${(cfg.args || []).join(' ')}`);
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
out('\nAby zainstalować w Cursor i Antigravity: deertools mcp install\n');
|
|
371
|
-
return;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
if (sub === 'config') {
|
|
375
|
-
const servers = buildMcpServersConfig(products, false);
|
|
376
|
-
const config = { mcpServers: servers };
|
|
377
|
-
if (flags.json) {
|
|
378
|
-
out(JSON.stringify(config, null, 2));
|
|
379
|
-
} else {
|
|
380
|
-
out('\nKonfiguracja MCP dla DeerTools (Cursor IDE, Claude Desktop, Antigravity):');
|
|
381
|
-
out(JSON.stringify(config, null, 2));
|
|
382
|
-
out('\nAby zainstalować automatycznie w Cursorze i Antigravity, uruchom:');
|
|
383
|
-
out(' deertools mcp install\n');
|
|
384
|
-
}
|
|
385
|
-
return;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
function installMcpServers(customProducts = null, silent = false) {
|
|
359
|
+
function installMcpServers(customProducts = null, silent = false, { remote = false } = {}) {
|
|
389
360
|
const prods = customProducts || resolveProducts('all');
|
|
390
|
-
const servers = buildMcpServersConfig(prods, true);
|
|
361
|
+
const servers = buildMcpServersConfig(prods, true, { remote });
|
|
391
362
|
let touched = 0;
|
|
392
363
|
|
|
393
364
|
// 1. Cursor global (~/.cursor/mcp.json)
|
|
@@ -458,7 +429,24 @@ function installMcpServers(customProducts = null, silent = false) {
|
|
|
458
429
|
}
|
|
459
430
|
}
|
|
460
431
|
|
|
461
|
-
// 5.
|
|
432
|
+
// 5. Antigravity AppData (~/.gemini/antigravity/mcp_config.json)
|
|
433
|
+
const antigravityAppData = path.join(os.homedir(), '.gemini', 'antigravity', 'mcp_config.json');
|
|
434
|
+
if (fs.existsSync(path.dirname(antigravityAppData))) {
|
|
435
|
+
try {
|
|
436
|
+
let cur = { mcpServers: {} };
|
|
437
|
+
if (fs.existsSync(antigravityAppData)) {
|
|
438
|
+
try { cur = JSON.parse(fs.readFileSync(antigravityAppData, 'utf8')); } catch (_) {}
|
|
439
|
+
}
|
|
440
|
+
cur.mcpServers = Object.assign({}, cur.mcpServers, servers);
|
|
441
|
+
fs.writeFileSync(antigravityAppData, JSON.stringify(cur, null, 2));
|
|
442
|
+
if (!silent) out(`✓ Antigravity AppData: ${antigravityAppData}`);
|
|
443
|
+
touched++;
|
|
444
|
+
} catch (e) {
|
|
445
|
+
if (!silent) err(`✗ Antigravity AppData (${antigravityAppData}): ${e.message}`);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// 6. Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json)
|
|
462
450
|
const claudeDesktop = path.join(os.homedir(), 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');
|
|
463
451
|
if (fs.existsSync(path.dirname(claudeDesktop))) {
|
|
464
452
|
try {
|
|
@@ -484,7 +472,7 @@ function installMcpServers(customProducts = null, silent = false) {
|
|
|
484
472
|
}
|
|
485
473
|
}
|
|
486
474
|
|
|
487
|
-
//
|
|
475
|
+
// 7. Claude Code CLI (~/.claude.json)
|
|
488
476
|
const claudeCli = path.join(os.homedir(), '.claude.json');
|
|
489
477
|
if (fs.existsSync(claudeCli)) {
|
|
490
478
|
try {
|
|
@@ -508,7 +496,7 @@ function installMcpServers(customProducts = null, silent = false) {
|
|
|
508
496
|
}
|
|
509
497
|
}
|
|
510
498
|
|
|
511
|
-
//
|
|
499
|
+
// 8. Workspace .mcp.json (Claude Code / Cowork / Standard MCP workspace)
|
|
512
500
|
const workspaceMcp = path.join(process.cwd(), '.mcp.json');
|
|
513
501
|
try {
|
|
514
502
|
let cur = {};
|
|
@@ -535,8 +523,45 @@ function installMcpServers(customProducts = null, silent = false) {
|
|
|
535
523
|
return touched;
|
|
536
524
|
}
|
|
537
525
|
|
|
526
|
+
async function cmdMcp(pos, flags) {
|
|
527
|
+
const sub = pos[0] || 'config';
|
|
528
|
+
const products = resolveProducts(pos[1]);
|
|
529
|
+
const remote = Boolean(flags.remote);
|
|
530
|
+
|
|
531
|
+
if (sub === 'list') {
|
|
532
|
+
const servers = buildMcpServersConfig(products, false, { remote });
|
|
533
|
+
if (flags.json) {
|
|
534
|
+
out(JSON.stringify(servers, null, 2));
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
out('\n=== Zarejestrowane Serwery MCP Ekosystemu DeerTools ===\n');
|
|
538
|
+
for (const [name, cfg] of Object.entries(servers)) {
|
|
539
|
+
if (cfg.url) {
|
|
540
|
+
out(` • ${name.padEnd(18)} [Remote HTTP] ${cfg.url}`);
|
|
541
|
+
} else {
|
|
542
|
+
out(` • ${name.padEnd(18)} [Local stdio] ${cfg.command} ${(cfg.args || []).join(' ')}`);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
out('\nAby zainstalować w Cursor i Antigravity: deertools mcp install\n');
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
if (sub === 'config') {
|
|
550
|
+
const servers = buildMcpServersConfig(products, false, { remote });
|
|
551
|
+
const config = { mcpServers: servers };
|
|
552
|
+
if (flags.json) {
|
|
553
|
+
out(JSON.stringify(config, null, 2));
|
|
554
|
+
} else {
|
|
555
|
+
out('\nKonfiguracja MCP dla DeerTools (Cursor IDE, Claude Desktop, Antigravity):');
|
|
556
|
+
out(JSON.stringify(config, null, 2));
|
|
557
|
+
out('\nAby zainstalować automatycznie w Cursorze i Antigravity, uruchom:');
|
|
558
|
+
out(' deertools mcp install\n');
|
|
559
|
+
}
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
|
|
538
563
|
if (sub === 'install') {
|
|
539
|
-
const touched = installMcpServers(products, false);
|
|
564
|
+
const touched = installMcpServers(products, false, { remote });
|
|
540
565
|
if (!touched) fail('Nie znaleziono środowiska agenta do instalacji MCP.', 4);
|
|
541
566
|
out(`\nPomyślnie skonfigurowano wszystkie 7 serwerów MCP dla produktów DeerTools!`);
|
|
542
567
|
return;
|
|
@@ -647,6 +672,9 @@ const { cmdCompletion } = require('./completion');
|
|
|
647
672
|
const { cmdBaseLinker } = require('./baselinker-commands');
|
|
648
673
|
const { cmdRenderMind } = require('./rendermind/cli-commands');
|
|
649
674
|
const { cmdSupplier } = require('./supplier/cli-commands');
|
|
675
|
+
const { cmdEstimate } = require('./estimate/cli-commands');
|
|
676
|
+
const { cmdCatalog } = require('./catalog/cli-commands');
|
|
677
|
+
const { cmdDeliveries } = require('./deliveries/cli-commands');
|
|
650
678
|
|
|
651
679
|
const HELP = `
|
|
652
680
|
DeerTools CLI — Identity, MCP & Skills Hub Manager dla ekosystemu Deer Design
|
|
@@ -696,7 +724,8 @@ Zasada architektoniczna:
|
|
|
696
724
|
module.exports = {
|
|
697
725
|
cmdLogin, cmdLogout, cmdWhoami, cmdSkill, cmdMcp,
|
|
698
726
|
cmdDoctor, cmdAudit, cmdProfile, cmdCompletion,
|
|
699
|
-
cmdBaseLinker, cmdRenderMind, cmdSupplier,
|
|
727
|
+
cmdBaseLinker, cmdRenderMind, cmdSupplier, cmdEstimate,
|
|
728
|
+
cmdCatalog, cmdDeliveries,
|
|
700
729
|
cmdAgent, cmdTeam, cmdBlockedDomain,
|
|
701
730
|
HELP, parseQuery,
|
|
702
731
|
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const { runDeliveriesMcpServer } = require('./mcp-server');
|
|
3
|
+
|
|
4
|
+
async function cmdDeliveries(pos, flags) {
|
|
5
|
+
const sub = pos[0] || 'help';
|
|
6
|
+
|
|
7
|
+
if (sub === 'mcp') {
|
|
8
|
+
return await runDeliveriesMcpServer();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
console.log(`Użycie deertools deliveries:
|
|
12
|
+
deertools deliveries mcp - Uruchamia serwer MCP Dostaw (stdio)
|
|
13
|
+
`);
|
|
14
|
+
return 0;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports = {
|
|
18
|
+
cmdDeliveries
|
|
19
|
+
};
|