@enfyra/mcp-server 0.1.69 → 0.1.71
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 +1 -1
- package/dist/lib/config-local-adapters.d.ts +18 -0
- package/dist/lib/config-local-adapters.js +271 -0
- package/dist/lib/config-local-adapters.js.map +1 -0
- package/dist/lib/config-local-contracts.d.ts +28 -0
- package/dist/lib/config-local-contracts.js +200 -0
- package/dist/lib/config-local-contracts.js.map +1 -0
- package/dist/lib/config-local-prompts.d.ts +10 -0
- package/dist/lib/config-local-prompts.js +185 -0
- package/dist/lib/config-local-prompts.js.map +1 -0
- package/dist/lib/config-local-types.d.ts +23 -0
- package/dist/lib/config-local-types.js +2 -0
- package/dist/lib/config-local-types.js.map +1 -0
- package/dist/lib/config-local.js +3 -649
- package/dist/lib/config-local.js.map +1 -1
- package/dist/lib/discovery-tools.d.ts +4 -0
- package/dist/lib/discovery-tools.js +546 -0
- package/dist/lib/discovery-tools.js.map +1 -0
- package/dist/lib/dynamic-repository-builder.d.ts +1 -1
- package/dist/lib/dynamic-script-context-contract.d.ts +100 -0
- package/dist/lib/dynamic-script-context-contract.js +163 -0
- package/dist/lib/dynamic-script-context-contract.js.map +1 -0
- package/dist/lib/enfyra-mcp-server.d.ts +3 -0
- package/dist/lib/enfyra-mcp-server.js +79 -0
- package/dist/lib/enfyra-mcp-server.js.map +1 -0
- package/dist/lib/enfyra-tool-logic.d.ts +7 -0
- package/dist/lib/enfyra-tool-logic.js +8 -0
- package/dist/lib/enfyra-tool-logic.js.map +1 -0
- package/dist/lib/enfyra-tool-types.d.ts +27 -0
- package/dist/lib/enfyra-tool-types.js +2 -0
- package/dist/lib/enfyra-tool-types.js.map +1 -0
- package/dist/lib/extension-api-builders.d.ts +17 -0
- package/dist/lib/extension-api-builders.js +235 -0
- package/dist/lib/extension-api-builders.js.map +1 -0
- package/dist/lib/extension-component-builders.d.ts +87 -0
- package/dist/lib/extension-component-builders.js +623 -0
- package/dist/lib/extension-component-builders.js.map +1 -0
- package/dist/lib/extension-contract-review.d.ts +26 -0
- package/dist/lib/extension-contract-review.js +187 -0
- package/dist/lib/extension-contract-review.js.map +1 -0
- package/dist/lib/extension-theme-contract.d.ts +63 -0
- package/dist/lib/extension-theme-contract.js +417 -0
- package/dist/lib/extension-theme-contract.js.map +1 -0
- package/dist/lib/identity-tools.d.ts +4 -0
- package/dist/lib/identity-tools.js +46 -0
- package/dist/lib/identity-tools.js.map +1 -0
- package/dist/lib/log-tools.d.ts +4 -0
- package/dist/lib/log-tools.js +65 -0
- package/dist/lib/log-tools.js.map +1 -0
- package/dist/lib/mcp-example-connect.d.ts +9 -0
- package/dist/lib/mcp-example-connect.js +442 -0
- package/dist/lib/mcp-example-connect.js.map +1 -0
- package/dist/lib/mcp-example-extensions.d.ts +9 -0
- package/dist/lib/mcp-example-extensions.js +729 -0
- package/dist/lib/mcp-example-extensions.js.map +1 -0
- package/dist/lib/mcp-example-files.d.ts +9 -0
- package/dist/lib/mcp-example-files.js +51 -0
- package/dist/lib/mcp-example-files.js.map +1 -0
- package/dist/lib/mcp-example-flows.d.ts +9 -0
- package/dist/lib/mcp-example-flows.js +76 -0
- package/dist/lib/mcp-example-flows.js.map +1 -0
- package/dist/lib/mcp-example-graphql.d.ts +9 -0
- package/dist/lib/mcp-example-graphql.js +57 -0
- package/dist/lib/mcp-example-graphql.js.map +1 -0
- package/dist/lib/mcp-example-handlers-hooks.d.ts +9 -0
- package/dist/lib/mcp-example-handlers-hooks.js +328 -0
- package/dist/lib/mcp-example-handlers-hooks.js.map +1 -0
- package/dist/lib/mcp-example-oauth-setup.d.ts +9 -0
- package/dist/lib/mcp-example-oauth-setup.js +41 -0
- package/dist/lib/mcp-example-oauth-setup.js.map +1 -0
- package/dist/lib/mcp-example-permissions-rls.d.ts +9 -0
- package/dist/lib/mcp-example-permissions-rls.js +210 -0
- package/dist/lib/mcp-example-permissions-rls.js.map +1 -0
- package/dist/lib/mcp-example-queries-deep.d.ts +9 -0
- package/dist/lib/mcp-example-queries-deep.js +220 -0
- package/dist/lib/mcp-example-queries-deep.js.map +1 -0
- package/dist/lib/mcp-example-schema-relations.d.ts +9 -0
- package/dist/lib/mcp-example-schema-relations.js +148 -0
- package/dist/lib/mcp-example-schema-relations.js.map +1 -0
- package/dist/lib/mcp-example-websocket.d.ts +9 -0
- package/dist/lib/mcp-example-websocket.js +103 -0
- package/dist/lib/mcp-example-websocket.js.map +1 -0
- package/dist/lib/mcp-examples.d.ts +5 -5
- package/dist/lib/mcp-examples.js +22 -2394
- package/dist/lib/mcp-examples.js.map +1 -1
- package/dist/lib/method-tools.d.ts +4 -0
- package/dist/lib/method-tools.js +217 -0
- package/dist/lib/method-tools.js.map +1 -0
- package/dist/lib/package-tools.d.ts +4 -0
- package/dist/lib/package-tools.js +98 -0
- package/dist/lib/package-tools.js.map +1 -0
- package/dist/lib/platform-data-operations.d.ts +24 -0
- package/dist/lib/platform-data-operations.js +71 -0
- package/dist/lib/platform-data-operations.js.map +1 -0
- package/dist/lib/platform-endpoint-workflow.d.ts +42 -0
- package/dist/lib/platform-endpoint-workflow.js +382 -0
- package/dist/lib/platform-endpoint-workflow.js.map +1 -0
- package/dist/lib/platform-extension-source.d.ts +487 -0
- package/dist/lib/platform-extension-source.js +524 -0
- package/dist/lib/platform-extension-source.js.map +1 -0
- package/dist/lib/platform-extension-tools.d.ts +1 -0
- package/dist/lib/platform-extension-tools.js +416 -0
- package/dist/lib/platform-extension-tools.js.map +1 -0
- package/dist/lib/platform-extension-ui.d.ts +4 -0
- package/dist/lib/platform-extension-ui.js +5 -0
- package/dist/lib/platform-extension-ui.js.map +1 -0
- package/dist/lib/platform-extension-workflow.d.ts +54 -0
- package/dist/lib/platform-extension-workflow.js +194 -0
- package/dist/lib/platform-extension-workflow.js.map +1 -0
- package/dist/lib/platform-flow-operations.d.ts +554 -0
- package/dist/lib/platform-flow-operations.js +317 -0
- package/dist/lib/platform-flow-operations.js.map +1 -0
- package/dist/lib/platform-flow-tools.d.ts +1 -0
- package/dist/lib/platform-flow-tools.js +248 -0
- package/dist/lib/platform-flow-tools.js.map +1 -0
- package/dist/lib/platform-operation-logic.d.ts +10 -0
- package/dist/lib/platform-operation-logic.js +11 -0
- package/dist/lib/platform-operation-logic.js.map +1 -0
- package/dist/lib/platform-operation-tools.d.ts +1 -324
- package/dist/lib/platform-operation-tools.js +13 -4620
- package/dist/lib/platform-operation-tools.js.map +1 -1
- package/dist/lib/platform-operation-types.d.ts +46 -0
- package/dist/lib/platform-operation-types.js +2 -0
- package/dist/lib/platform-operation-types.js.map +1 -0
- package/dist/lib/platform-policy-tools.d.ts +1 -0
- package/dist/lib/platform-policy-tools.js +248 -0
- package/dist/lib/platform-policy-tools.js.map +1 -0
- package/dist/lib/platform-resource-operations.d.ts +124 -0
- package/dist/lib/platform-resource-operations.js +109 -0
- package/dist/lib/platform-resource-operations.js.map +1 -0
- package/dist/lib/platform-resource-tools.d.ts +1 -0
- package/dist/lib/platform-resource-tools.js +70 -0
- package/dist/lib/platform-resource-tools.js.map +1 -0
- package/dist/lib/platform-route-operations.d.ts +222 -0
- package/dist/lib/platform-route-operations.js +290 -0
- package/dist/lib/platform-route-operations.js.map +1 -0
- package/dist/lib/platform-route-tools.d.ts +1 -0
- package/dist/lib/platform-route-tools.js +307 -0
- package/dist/lib/platform-route-tools.js.map +1 -0
- package/dist/lib/platform-shared-operations.d.ts +7 -0
- package/dist/lib/platform-shared-operations.js +4 -0
- package/dist/lib/platform-shared-operations.js.map +1 -0
- package/dist/lib/platform-websocket-tools.d.ts +1 -0
- package/dist/lib/platform-websocket-tools.js +70 -0
- package/dist/lib/platform-websocket-tools.js.map +1 -0
- package/dist/lib/record-tools.d.ts +4 -0
- package/dist/lib/record-tools.js +418 -0
- package/dist/lib/record-tools.js.map +1 -0
- package/dist/lib/required-knowledge.d.ts +1 -1
- package/dist/lib/required-knowledge.js +3 -2
- package/dist/lib/required-knowledge.js.map +1 -1
- package/dist/lib/route-access-tools.d.ts +4 -0
- package/dist/lib/route-access-tools.js +172 -0
- package/dist/lib/route-access-tools.js.map +1 -0
- package/dist/lib/route-definition-tools.d.ts +4 -0
- package/dist/lib/route-definition-tools.js +285 -0
- package/dist/lib/route-definition-tools.js.map +1 -0
- package/dist/lib/route-inspection-tools.d.ts +4 -0
- package/dist/lib/route-inspection-tools.js +319 -0
- package/dist/lib/route-inspection-tools.js.map +1 -0
- package/dist/lib/route-tools.d.ts +1 -0
- package/dist/lib/route-tools.js +9 -0
- package/dist/lib/route-tools.js.map +1 -0
- package/dist/lib/runtime-zone-registry.d.ts +27 -0
- package/dist/lib/runtime-zone-registry.js +81 -0
- package/dist/lib/runtime-zone-registry.js.map +1 -0
- package/dist/lib/runtime-zone-search.d.ts +303 -0
- package/dist/lib/runtime-zone-search.js +596 -0
- package/dist/lib/runtime-zone-search.js.map +1 -0
- package/dist/lib/runtime-zone-tools.d.ts +2 -307
- package/dist/lib/runtime-zone-tools.js +2 -674
- package/dist/lib/runtime-zone-tools.js.map +1 -1
- package/dist/lib/schema-column-tools.d.ts +3 -0
- package/dist/lib/schema-column-tools.js +80 -0
- package/dist/lib/schema-column-tools.js.map +1 -0
- package/dist/lib/schema-mutation-coordinator.d.ts +28 -0
- package/dist/lib/schema-mutation-coordinator.js +154 -0
- package/dist/lib/schema-mutation-coordinator.js.map +1 -0
- package/dist/lib/schema-relation-contracts.d.ts +39 -0
- package/dist/lib/schema-relation-contracts.js +160 -0
- package/dist/lib/schema-relation-contracts.js.map +1 -0
- package/dist/lib/schema-relation-tools.d.ts +3 -0
- package/dist/lib/schema-relation-tools.js +61 -0
- package/dist/lib/schema-relation-tools.js.map +1 -0
- package/dist/lib/schema-table-contracts.d.ts +28 -0
- package/dist/lib/schema-table-contracts.js +263 -0
- package/dist/lib/schema-table-contracts.js.map +1 -0
- package/dist/lib/schema-table-tools.d.ts +3 -0
- package/dist/lib/schema-table-tools.js +297 -0
- package/dist/lib/schema-table-tools.js.map +1 -0
- package/dist/lib/schema-tool-operations.d.ts +150 -0
- package/dist/lib/schema-tool-operations.js +468 -0
- package/dist/lib/schema-tool-operations.js.map +1 -0
- package/dist/lib/schema-tool-types.d.ts +38 -0
- package/dist/lib/schema-tool-types.js +2 -0
- package/dist/lib/schema-tool-types.js.map +1 -0
- package/dist/lib/schema-verification.d.ts +14 -0
- package/dist/lib/schema-verification.js +105 -0
- package/dist/lib/schema-verification.js.map +1 -0
- package/dist/lib/script-tools.d.ts +4 -0
- package/dist/lib/script-tools.js +127 -0
- package/dist/lib/script-tools.js.map +1 -0
- package/dist/lib/system-tools.d.ts +4 -0
- package/dist/lib/system-tools.js +41 -0
- package/dist/lib/system-tools.js.map +1 -0
- package/dist/lib/table-tool-logic.d.ts +5 -0
- package/dist/lib/table-tool-logic.js +6 -0
- package/dist/lib/table-tool-logic.js.map +1 -0
- package/dist/lib/table-tools.d.ts +1 -84
- package/dist/lib/table-tools.js +7 -1522
- package/dist/lib/table-tools.js.map +1 -1
- package/dist/lib/tool-catalog.d.ts +2 -1
- package/dist/lib/tool-catalog.js +23 -2
- package/dist/lib/tool-catalog.js.map +1 -1
- package/dist/lib/tool-metadata-operations.d.ts +27 -0
- package/dist/lib/tool-metadata-operations.js +93 -0
- package/dist/lib/tool-metadata-operations.js.map +1 -0
- package/dist/lib/tool-permission-profile.d.ts +37 -0
- package/dist/lib/tool-permission-profile.js +106 -0
- package/dist/lib/tool-permission-profile.js.map +1 -0
- package/dist/lib/tool-record-operations.d.ts +102 -0
- package/dist/lib/tool-record-operations.js +260 -0
- package/dist/lib/tool-record-operations.js.map +1 -0
- package/dist/lib/tool-route-inspection.d.ts +47 -0
- package/dist/lib/tool-route-inspection.js +168 -0
- package/dist/lib/tool-route-inspection.js.map +1 -0
- package/dist/lib/tool-routing.d.ts +3 -417
- package/dist/lib/tool-routing.js +3 -1038
- package/dist/lib/tool-routing.js.map +1 -1
- package/dist/lib/tool-runtime-config.d.ts +33 -0
- package/dist/lib/tool-runtime-config.js +237 -0
- package/dist/lib/tool-runtime-config.js.map +1 -0
- package/dist/lib/tool-script-operations.d.ts +34 -0
- package/dist/lib/tool-script-operations.js +153 -0
- package/dist/lib/tool-script-operations.js.map +1 -0
- package/dist/lib/workflow-definitions.d.ts +366 -0
- package/dist/lib/workflow-definitions.js +703 -0
- package/dist/lib/workflow-definitions.js.map +1 -0
- package/dist/lib/workflow-planner.d.ts +45 -0
- package/dist/lib/workflow-planner.js +338 -0
- package/dist/lib/workflow-planner.js.map +1 -0
- package/dist/lib/workflow-types.d.ts +39 -0
- package/dist/lib/workflow-types.js +2 -0
- package/dist/lib/workflow-types.js.map +1 -0
- package/dist/mcp-server-entry.d.ts +0 -3
- package/dist/mcp-server-entry.js +2 -3249
- package/dist/mcp-server-entry.js.map +1 -1
- package/package.json +1 -1
package/dist/lib/config-local.js
CHANGED
|
@@ -1,653 +1,7 @@
|
|
|
1
|
-
import { appendFile, chmod, readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
2
|
-
import { execFile as execFileCallback } from 'node:child_process';
|
|
3
|
-
import { createInterface } from 'node:readline/promises';
|
|
4
|
-
import { emitKeypressEvents } from 'node:readline';
|
|
5
1
|
import { stdin as input, stdout as output, cwd } from 'node:process';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
const MCP_PACKAGE_SPEC = '@enfyra/mcp-server@latest';
|
|
10
|
-
const PRIVATE_FILE_MODE = 0o600;
|
|
11
|
-
const execFile = promisify(execFileCallback);
|
|
12
|
-
const forceColor = process.env.FORCE_COLOR != null && process.env.FORCE_COLOR !== '0';
|
|
13
|
-
const canStyle = forceColor || (output.isTTY && process.env.NO_COLOR == null);
|
|
14
|
-
const style = {
|
|
15
|
-
bold: (value) => canStyle ? `\x1B[1m${value}\x1B[22m` : value,
|
|
16
|
-
dim: (value) => canStyle ? `\x1B[2m${value}\x1B[22m` : value,
|
|
17
|
-
cyan: (value) => canStyle ? `\x1B[36m${value}\x1B[39m` : value,
|
|
18
|
-
green: (value) => canStyle ? `\x1B[32m${value}\x1B[39m` : value,
|
|
19
|
-
magenta: (value) => canStyle ? `\x1B[35m${value}\x1B[39m` : value,
|
|
20
|
-
blue: (value) => canStyle ? `\x1B[34m${value}\x1B[39m` : value,
|
|
21
|
-
yellow: (value) => canStyle ? `\x1B[33m${value}\x1B[39m` : value,
|
|
22
|
-
underline: (value) => canStyle ? `\x1B[4m${value}\x1B[24m` : value,
|
|
23
|
-
inverse: (value) => canStyle ? `\x1B[7m${value}\x1B[27m` : value,
|
|
24
|
-
};
|
|
25
|
-
const clients = {
|
|
26
|
-
codex: {
|
|
27
|
-
label: 'Codex',
|
|
28
|
-
path: './.codex/config.toml',
|
|
29
|
-
color: style.green,
|
|
30
|
-
},
|
|
31
|
-
claude: {
|
|
32
|
-
label: 'Claude Code',
|
|
33
|
-
path: './.mcp.json',
|
|
34
|
-
color: style.magenta,
|
|
35
|
-
},
|
|
36
|
-
cursor: {
|
|
37
|
-
label: 'Cursor',
|
|
38
|
-
path: './.cursor/mcp.json',
|
|
39
|
-
color: style.cyan,
|
|
40
|
-
},
|
|
41
|
-
vscode: {
|
|
42
|
-
label: 'VS Code / Copilot',
|
|
43
|
-
path: './.vscode/mcp.json',
|
|
44
|
-
color: style.blue,
|
|
45
|
-
},
|
|
46
|
-
antigravity: {
|
|
47
|
-
label: 'Antigravity',
|
|
48
|
-
path: './.agents/mcp_config.json',
|
|
49
|
-
color: style.yellow,
|
|
50
|
-
},
|
|
51
|
-
};
|
|
52
|
-
async function writePrivateFile(path, content) {
|
|
53
|
-
await writeFile(path, content, { encoding: 'utf8', mode: PRIVATE_FILE_MODE });
|
|
54
|
-
await chmod(path, PRIVATE_FILE_MODE);
|
|
55
|
-
}
|
|
56
|
-
async function ensureProjectConfigIgnored(root, paths) {
|
|
57
|
-
const gitignorePath = join(root, '.gitignore');
|
|
58
|
-
let gitignore = '';
|
|
59
|
-
try {
|
|
60
|
-
gitignore = await readFile(gitignorePath, 'utf8');
|
|
61
|
-
}
|
|
62
|
-
catch (error) {
|
|
63
|
-
if (error.code !== 'ENOENT')
|
|
64
|
-
throw error;
|
|
65
|
-
}
|
|
66
|
-
const existing = new Set(gitignore.split(/\r?\n/).map((line) => line.trim()).filter(Boolean));
|
|
67
|
-
const entries = paths
|
|
68
|
-
.map((path) => relative(root, path).split('\\').join('/'))
|
|
69
|
-
.filter((path) => path && !existing.has(path));
|
|
70
|
-
if (!entries.length)
|
|
71
|
-
return;
|
|
72
|
-
const prefix = gitignore && !gitignore.endsWith('\n') ? '\n' : '';
|
|
73
|
-
await appendFile(gitignorePath, `${prefix}${entries.join('\n')}\n`, {
|
|
74
|
-
encoding: 'utf8',
|
|
75
|
-
mode: PRIVATE_FILE_MODE,
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
async function assertProjectConfigUntracked(root, paths) {
|
|
79
|
-
const entries = paths
|
|
80
|
-
.map((path) => relative(root, path).split('\\').join('/'))
|
|
81
|
-
.filter(Boolean);
|
|
82
|
-
if (!entries.length)
|
|
83
|
-
return;
|
|
84
|
-
try {
|
|
85
|
-
const { stdout } = await execFile('git', [
|
|
86
|
-
'-C',
|
|
87
|
-
root,
|
|
88
|
-
'ls-files',
|
|
89
|
-
'--',
|
|
90
|
-
...entries,
|
|
91
|
-
]);
|
|
92
|
-
const tracked = stdout.trim().split(/\r?\n/).filter(Boolean);
|
|
93
|
-
if (tracked.length) {
|
|
94
|
-
throw new Error(`Refusing to write tracked MCP config files: ${tracked.join(', ')}. Remove them from Git tracking before storing a token.`);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
catch (error) {
|
|
98
|
-
if (error?.code === 128)
|
|
99
|
-
return;
|
|
100
|
-
throw error;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
function statusIcon(kind) {
|
|
104
|
-
if (kind === 'success')
|
|
105
|
-
return canStyle ? style.green('✓') : 'Done';
|
|
106
|
-
if (kind === 'warn')
|
|
107
|
-
return canStyle ? style.yellow('!') : 'Warning';
|
|
108
|
-
return canStyle ? style.cyan('•') : '-';
|
|
109
|
-
}
|
|
110
|
-
function isCancelError(error) {
|
|
111
|
-
const item = error;
|
|
112
|
-
return item?.code === 'ABORT_ERR' || (item?.message || '') === 'Cancelled';
|
|
113
|
-
}
|
|
114
|
-
function exitCancelled() {
|
|
115
|
-
console.log('\nCancelled.');
|
|
116
|
-
process.exit(130);
|
|
117
|
-
}
|
|
118
|
-
function printHelp() {
|
|
119
|
-
console.log(`${style.bold('Enfyra MCP config')}
|
|
120
|
-
${style.dim('Write project-local MCP client config for Enfyra.')}
|
|
121
|
-
|
|
122
|
-
${style.bold('Usage')}
|
|
123
|
-
npx @enfyra/mcp-server@latest config [options]
|
|
124
|
-
|
|
125
|
-
${style.bold('Supported clients')}
|
|
126
|
-
Codex ./.codex/config.toml
|
|
127
|
-
Claude Code ./.mcp.json
|
|
128
|
-
Cursor ./.cursor/mcp.json
|
|
129
|
-
VS Code ./.vscode/mcp.json
|
|
130
|
-
Antigravity ./.agents/mcp_config.json
|
|
131
|
-
|
|
132
|
-
${style.bold('Options')}
|
|
133
|
-
--app-url <url> Enfyra app/admin URL, for example https://demo.enfyra.io
|
|
134
|
-
--api-token, -t <secret> ENFYRA_API_TOKEN
|
|
135
|
-
--reconfig Always choose target again in interactive mode and replace the old enfyra config for that target
|
|
136
|
-
--yes Non-interactive: no prompts (CI / scripts); use CLI, env, existing file, then defaults
|
|
137
|
-
|
|
138
|
-
${style.bold('Client selection')}
|
|
139
|
-
Non-interactive default is all supported clients. In a TTY with no target flags, choose with ↑/↓.
|
|
140
|
-
|
|
141
|
-
--claude-code, --claude, --claude-only Only ./.mcp.json (Claude Code project scope)
|
|
142
|
-
--cursor, --cursor-only Only ./.cursor/mcp.json (Cursor)
|
|
143
|
-
--codex, --codex-only Only ./.codex/config.toml (Codex project scope)
|
|
144
|
-
--vscode, --copilot, --vscode-only Only ./.vscode/mcp.json (VS Code / Copilot)
|
|
145
|
-
--antigravity, --antigravity-only Only ./.agents/mcp_config.json (Antigravity)
|
|
146
|
-
Passing multiple target flags writes each selected target.
|
|
147
|
-
|
|
148
|
-
-h, --help Show this help
|
|
149
|
-
|
|
150
|
-
${style.bold('Interactive mode')}
|
|
151
|
-
Choose Codex, Claude Code, Cursor, VS Code, Antigravity, or all clients; then enter ENFYRA_APP_URL and ENFYRA_API_TOKEN.
|
|
152
|
-
Existing Enfyra config and environment variables are used as defaults. Re-run anytime to update.
|
|
153
|
-
|
|
154
|
-
${style.bold('Examples')}
|
|
155
|
-
npx @enfyra/mcp-server@latest config
|
|
156
|
-
npx @enfyra/mcp-server@latest config --yes
|
|
157
|
-
npx @enfyra/mcp-server@latest config --codex --cursor
|
|
158
|
-
npx @enfyra/mcp-server@latest config --vscode
|
|
159
|
-
npx @enfyra/mcp-server@latest config --antigravity
|
|
160
|
-
npx @enfyra/mcp-server@latest config --claude-code
|
|
161
|
-
npx @enfyra/mcp-server@latest config --reconfig
|
|
162
|
-
npx @enfyra/mcp-server@latest config --app-url http://localhost:3000 -t 'efy_pat_...'
|
|
163
|
-
ENFYRA_APP_URL=https://demo.enfyra.io ENFYRA_API_TOKEN=efy_pat_... npx @enfyra/mcp-server@latest config --yes
|
|
164
|
-
`);
|
|
165
|
-
}
|
|
166
|
-
function parseArgs(argv) {
|
|
167
|
-
const out = {
|
|
168
|
-
appUrl: undefined,
|
|
169
|
-
apiToken: undefined,
|
|
170
|
-
claude: true,
|
|
171
|
-
cursor: true,
|
|
172
|
-
codex: true,
|
|
173
|
-
help: false,
|
|
174
|
-
yes: false,
|
|
175
|
-
reconfig: false,
|
|
176
|
-
vscode: true,
|
|
177
|
-
antigravity: true,
|
|
178
|
-
targetExplicit: false,
|
|
179
|
-
};
|
|
180
|
-
let pickClaude = false;
|
|
181
|
-
let pickCursor = false;
|
|
182
|
-
let pickCodex = false;
|
|
183
|
-
let pickVscode = false;
|
|
184
|
-
let pickAntigravity = false;
|
|
185
|
-
for (let i = 0; i < argv.length; i += 1) {
|
|
186
|
-
const a = argv[i];
|
|
187
|
-
const next = () => {
|
|
188
|
-
const v = argv[i + 1];
|
|
189
|
-
if (v == null)
|
|
190
|
-
throw new Error(`Missing value after ${a}`);
|
|
191
|
-
i += 1;
|
|
192
|
-
return v;
|
|
193
|
-
};
|
|
194
|
-
if (a === '--help' || a === '-h')
|
|
195
|
-
out.help = true;
|
|
196
|
-
else if (a === 'help')
|
|
197
|
-
out.help = true;
|
|
198
|
-
else if (a === '--yes')
|
|
199
|
-
out.yes = true;
|
|
200
|
-
else if (a === '--reconfig')
|
|
201
|
-
out.reconfig = true;
|
|
202
|
-
else if (a === '--app-url')
|
|
203
|
-
out.appUrl = next();
|
|
204
|
-
else if (a === '--api-url' || a === '-a') {
|
|
205
|
-
throw new Error(`${a} is no longer supported for setup; use --app-url instead`);
|
|
206
|
-
}
|
|
207
|
-
else if (a === '--api-token' || a === '-t')
|
|
208
|
-
out.apiToken = next();
|
|
209
|
-
else if (a === '--email' || a === '-e' || a === '--password' || a === '-p') {
|
|
210
|
-
throw new Error(`${a} is no longer supported; use --api-token instead`);
|
|
211
|
-
}
|
|
212
|
-
else if (a === '--claude-only' || a === '--claude-code' || a === '--claude')
|
|
213
|
-
pickClaude = true;
|
|
214
|
-
else if (a === '--cursor-only' || a === '--cursor')
|
|
215
|
-
pickCursor = true;
|
|
216
|
-
else if (a === '--codex-only' || a === '--codex')
|
|
217
|
-
pickCodex = true;
|
|
218
|
-
else if (a === '--vscode-only' || a === '--vscode' || a === '--copilot')
|
|
219
|
-
pickVscode = true;
|
|
220
|
-
else if (a === '--antigravity-only' || a === '--antigravity')
|
|
221
|
-
pickAntigravity = true;
|
|
222
|
-
else
|
|
223
|
-
throw new Error(`Unknown argument: ${a}`);
|
|
224
|
-
}
|
|
225
|
-
out.targetExplicit = pickClaude || pickCursor || pickCodex || pickVscode || pickAntigravity;
|
|
226
|
-
if (out.targetExplicit) {
|
|
227
|
-
out.claude = pickClaude;
|
|
228
|
-
out.cursor = pickCursor;
|
|
229
|
-
out.codex = pickCodex;
|
|
230
|
-
out.vscode = pickVscode;
|
|
231
|
-
out.antigravity = pickAntigravity;
|
|
232
|
-
}
|
|
233
|
-
return out;
|
|
234
|
-
}
|
|
235
|
-
function buildServerEntry(apiUrl, apiToken) {
|
|
236
|
-
return {
|
|
237
|
-
command: 'npx',
|
|
238
|
-
args: ['-y', MCP_PACKAGE_SPEC],
|
|
239
|
-
env: {
|
|
240
|
-
ENFYRA_API_URL: apiUrl,
|
|
241
|
-
ENFYRA_API_TOKEN: apiToken,
|
|
242
|
-
},
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
function normalizeAppUrl(appUrl) {
|
|
246
|
-
const raw = String(appUrl || '').trim().replace(/\/+$/, '');
|
|
247
|
-
if (!raw)
|
|
248
|
-
return '';
|
|
249
|
-
return raw.replace(/\/(?:api|enfyra)$/i, '') || raw;
|
|
250
|
-
}
|
|
251
|
-
function deriveApiUrlFromAppUrl(appUrl) {
|
|
252
|
-
const normalized = normalizeAppUrl(appUrl);
|
|
253
|
-
return normalized ? `${normalized}/api` : 'http://localhost:3000/api';
|
|
254
|
-
}
|
|
255
|
-
function deriveAppUrlFromApiUrl(apiUrl) {
|
|
256
|
-
return normalizeAppUrl(apiUrl);
|
|
257
|
-
}
|
|
258
|
-
function deriveMeUrl(appUrl) {
|
|
259
|
-
const normalized = normalizeAppUrl(appUrl);
|
|
260
|
-
return normalized ? `${normalized}/me` : '/me';
|
|
261
|
-
}
|
|
262
|
-
function resolveDefaultAppUrl(opts, existing) {
|
|
263
|
-
const appCandidate = opts.appUrl ?? process.env.ENFYRA_APP_URL;
|
|
264
|
-
if (appCandidate)
|
|
265
|
-
return normalizeAppUrl(appCandidate);
|
|
266
|
-
const apiCandidate = process.env.ENFYRA_API_URL ?? existing.apiUrl;
|
|
267
|
-
if (apiCandidate)
|
|
268
|
-
return deriveAppUrlFromApiUrl(apiCandidate);
|
|
269
|
-
return 'http://localhost:3000';
|
|
270
|
-
}
|
|
271
|
-
async function mergeMcpFile(absPath, serverEntry) {
|
|
272
|
-
let data = { mcpServers: {} };
|
|
273
|
-
try {
|
|
274
|
-
const raw = await readFile(absPath, 'utf8');
|
|
275
|
-
const parsed = JSON.parse(raw);
|
|
276
|
-
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
277
|
-
data = { ...parsed, mcpServers: parsed.mcpServers && typeof parsed.mcpServers === 'object' ? { ...parsed.mcpServers } : {} };
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
catch (e) {
|
|
281
|
-
if (e.code !== 'ENOENT')
|
|
282
|
-
throw e;
|
|
283
|
-
}
|
|
284
|
-
data.mcpServers = { ...data.mcpServers, [SERVER_KEY]: serverEntry };
|
|
285
|
-
const dir = dirname(absPath);
|
|
286
|
-
await mkdir(dir, { recursive: true });
|
|
287
|
-
await writePrivateFile(absPath, `${JSON.stringify(data, null, 2)}\n`);
|
|
288
|
-
}
|
|
289
|
-
async function mergeVscodeMcpFile(absPath, serverEntry) {
|
|
290
|
-
let data = { servers: {} };
|
|
291
|
-
try {
|
|
292
|
-
const raw = await readFile(absPath, 'utf8');
|
|
293
|
-
const parsed = JSON.parse(raw);
|
|
294
|
-
if (parsed && typeof parsed === 'object') {
|
|
295
|
-
data = {
|
|
296
|
-
...parsed,
|
|
297
|
-
servers: parsed.servers && typeof parsed.servers === 'object' ? { ...parsed.servers } : {},
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
catch (e) {
|
|
302
|
-
if (e.code !== 'ENOENT')
|
|
303
|
-
throw e;
|
|
304
|
-
}
|
|
305
|
-
data.servers = {
|
|
306
|
-
...data.servers,
|
|
307
|
-
[SERVER_KEY]: {
|
|
308
|
-
type: 'stdio',
|
|
309
|
-
...serverEntry,
|
|
310
|
-
},
|
|
311
|
-
};
|
|
312
|
-
await mkdir(dirname(absPath), { recursive: true });
|
|
313
|
-
await writePrivateFile(absPath, `${JSON.stringify(data, null, 2)}\n`);
|
|
314
|
-
}
|
|
315
|
-
function tomlString(value) {
|
|
316
|
-
return JSON.stringify(String(value ?? ''));
|
|
317
|
-
}
|
|
318
|
-
function buildCodexTomlBlock(apiUrl, apiToken) {
|
|
319
|
-
return [
|
|
320
|
-
'[mcp_servers.enfyra]',
|
|
321
|
-
'command = "npx"',
|
|
322
|
-
`args = ["-y", "${MCP_PACKAGE_SPEC}"]`,
|
|
323
|
-
'',
|
|
324
|
-
'[mcp_servers.enfyra.env]',
|
|
325
|
-
`ENFYRA_API_URL = ${tomlString(apiUrl)}`,
|
|
326
|
-
`ENFYRA_API_TOKEN = ${tomlString(apiToken)}`,
|
|
327
|
-
'',
|
|
328
|
-
].join('\n');
|
|
329
|
-
}
|
|
330
|
-
async function mergeCodexConfig(absPath, apiUrl, apiToken) {
|
|
331
|
-
let raw = '';
|
|
332
|
-
try {
|
|
333
|
-
raw = await readFile(absPath, 'utf8');
|
|
334
|
-
}
|
|
335
|
-
catch (e) {
|
|
336
|
-
if (e.code !== 'ENOENT')
|
|
337
|
-
throw e;
|
|
338
|
-
}
|
|
339
|
-
const kept = [];
|
|
340
|
-
let skip = false;
|
|
341
|
-
for (const line of raw.split(/\r?\n/)) {
|
|
342
|
-
const header = line.match(/^\s*\[([^\]]+)\]\s*$/);
|
|
343
|
-
if (header) {
|
|
344
|
-
const section = header[1].trim();
|
|
345
|
-
skip = section === 'mcp_servers.enfyra' || section.startsWith('mcp_servers.enfyra.');
|
|
346
|
-
}
|
|
347
|
-
if (!skip)
|
|
348
|
-
kept.push(line);
|
|
349
|
-
}
|
|
350
|
-
const prefix = kept.join('\n').trimEnd();
|
|
351
|
-
const next = prefix ? `${prefix}\n\n${buildCodexTomlBlock(apiUrl, apiToken)}` : buildCodexTomlBlock(apiUrl, apiToken);
|
|
352
|
-
await mkdir(dirname(absPath), { recursive: true });
|
|
353
|
-
await writePrivateFile(absPath, next);
|
|
354
|
-
}
|
|
355
|
-
function parseTomlString(value) {
|
|
356
|
-
const trimmed = String(value || '').trim();
|
|
357
|
-
if (!trimmed)
|
|
358
|
-
return '';
|
|
359
|
-
try {
|
|
360
|
-
return JSON.parse(trimmed);
|
|
361
|
-
}
|
|
362
|
-
catch {
|
|
363
|
-
return trimmed.replace(/^['"]|['"]$/g, '');
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
async function readCodexEnfyraEnv(absPath) {
|
|
367
|
-
try {
|
|
368
|
-
const raw = await readFile(absPath, 'utf8');
|
|
369
|
-
const values = { apiUrl: '', apiToken: '' };
|
|
370
|
-
let inEnv = false;
|
|
371
|
-
for (const line of raw.split(/\r?\n/)) {
|
|
372
|
-
const header = line.match(/^\s*\[([^\]]+)\]\s*$/);
|
|
373
|
-
if (header) {
|
|
374
|
-
inEnv = header[1].trim() === 'mcp_servers.enfyra.env';
|
|
375
|
-
continue;
|
|
376
|
-
}
|
|
377
|
-
if (!inEnv)
|
|
378
|
-
continue;
|
|
379
|
-
const pair = line.match(/^\s*([A-Z0-9_]+)\s*=\s*(.+?)\s*$/);
|
|
380
|
-
if (!pair)
|
|
381
|
-
continue;
|
|
382
|
-
const key = pair[1];
|
|
383
|
-
const value = parseTomlString(pair[2]);
|
|
384
|
-
if (key === 'ENFYRA_API_URL')
|
|
385
|
-
values.apiUrl = value;
|
|
386
|
-
if (key === 'ENFYRA_API_TOKEN')
|
|
387
|
-
values.apiToken = value;
|
|
388
|
-
}
|
|
389
|
-
if (values.apiUrl || values.apiToken)
|
|
390
|
-
return values;
|
|
391
|
-
}
|
|
392
|
-
catch {
|
|
393
|
-
/* */
|
|
394
|
-
}
|
|
395
|
-
return null;
|
|
396
|
-
}
|
|
397
|
-
function getCodexConfigPath(root) {
|
|
398
|
-
return join(root, '.codex', 'config.toml');
|
|
399
|
-
}
|
|
400
|
-
function getClaudeConfigPath(root) {
|
|
401
|
-
return join(root, '.mcp.json');
|
|
402
|
-
}
|
|
403
|
-
function getCursorConfigPath(root) {
|
|
404
|
-
return join(root, '.cursor', 'mcp.json');
|
|
405
|
-
}
|
|
406
|
-
function getVscodeConfigPath(root) {
|
|
407
|
-
return join(root, '.vscode', 'mcp.json');
|
|
408
|
-
}
|
|
409
|
-
function getAntigravityConfigPath(root) {
|
|
410
|
-
return join(root, '.agents', 'mcp_config.json');
|
|
411
|
-
}
|
|
412
|
-
function getClientPath(client, root) {
|
|
413
|
-
if (client === 'claude')
|
|
414
|
-
return getClaudeConfigPath(root);
|
|
415
|
-
if (client === 'cursor')
|
|
416
|
-
return getCursorConfigPath(root);
|
|
417
|
-
if (client === 'codex')
|
|
418
|
-
return getCodexConfigPath(root);
|
|
419
|
-
if (client === 'vscode')
|
|
420
|
-
return getVscodeConfigPath(root);
|
|
421
|
-
if (client === 'antigravity')
|
|
422
|
-
return getAntigravityConfigPath(root);
|
|
423
|
-
throw new Error(`Unknown MCP client: ${client}`);
|
|
424
|
-
}
|
|
425
|
-
async function readMcpServerEnv(absPath, serverRootKey) {
|
|
426
|
-
try {
|
|
427
|
-
const raw = await readFile(absPath, 'utf8');
|
|
428
|
-
const j = JSON.parse(raw);
|
|
429
|
-
const e = j?.[serverRootKey]?.[SERVER_KEY]?.env;
|
|
430
|
-
if (e && typeof e === 'object' && (e.ENFYRA_API_URL || e.ENFYRA_API_TOKEN)) {
|
|
431
|
-
return {
|
|
432
|
-
apiUrl: typeof e.ENFYRA_API_URL === 'string' ? e.ENFYRA_API_URL : '',
|
|
433
|
-
apiToken: typeof e.ENFYRA_API_TOKEN === 'string' ? e.ENFYRA_API_TOKEN : '',
|
|
434
|
-
};
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
catch {
|
|
438
|
-
/* */
|
|
439
|
-
}
|
|
440
|
-
return null;
|
|
441
|
-
}
|
|
442
|
-
async function loadExistingEnfyraEnv(root, readClaude, readCursor, readCodex, readVscode, readAntigravity) {
|
|
443
|
-
const paths = [];
|
|
444
|
-
if (readClaude)
|
|
445
|
-
paths.push({ path: getClaudeConfigPath(root), rootKey: 'mcpServers' });
|
|
446
|
-
if (readCursor)
|
|
447
|
-
paths.push({ path: getCursorConfigPath(root), rootKey: 'mcpServers' });
|
|
448
|
-
if (!readClaude && readCursor)
|
|
449
|
-
paths.push({ path: getClaudeConfigPath(root), rootKey: 'mcpServers' });
|
|
450
|
-
if (readVscode)
|
|
451
|
-
paths.push({ path: getVscodeConfigPath(root), rootKey: 'servers' });
|
|
452
|
-
if (readAntigravity)
|
|
453
|
-
paths.push({ path: getAntigravityConfigPath(root), rootKey: 'mcpServers' });
|
|
454
|
-
const seen = new Set();
|
|
455
|
-
for (const entry of paths) {
|
|
456
|
-
const key = `${entry.rootKey}:${entry.path}`;
|
|
457
|
-
if (seen.has(key))
|
|
458
|
-
continue;
|
|
459
|
-
seen.add(key);
|
|
460
|
-
const env = await readMcpServerEnv(entry.path, entry.rootKey);
|
|
461
|
-
if (env)
|
|
462
|
-
return env;
|
|
463
|
-
}
|
|
464
|
-
if (readCodex) {
|
|
465
|
-
const codex = await readCodexEnfyraEnv(getCodexConfigPath(root));
|
|
466
|
-
if (codex)
|
|
467
|
-
return codex;
|
|
468
|
-
}
|
|
469
|
-
return { apiUrl: '', apiToken: '' };
|
|
470
|
-
}
|
|
471
|
-
async function promptTargetChoice() {
|
|
472
|
-
const choices = [
|
|
473
|
-
{
|
|
474
|
-
client: 'codex',
|
|
475
|
-
value: { claude: false, cursor: false, codex: true, vscode: false, antigravity: false },
|
|
476
|
-
},
|
|
477
|
-
{
|
|
478
|
-
client: 'claude',
|
|
479
|
-
value: { claude: true, cursor: false, codex: false, vscode: false, antigravity: false },
|
|
480
|
-
},
|
|
481
|
-
{
|
|
482
|
-
client: 'cursor',
|
|
483
|
-
value: { claude: false, cursor: true, codex: false, vscode: false, antigravity: false },
|
|
484
|
-
},
|
|
485
|
-
{
|
|
486
|
-
client: 'vscode',
|
|
487
|
-
value: { claude: false, cursor: false, codex: false, vscode: true, antigravity: false },
|
|
488
|
-
},
|
|
489
|
-
{
|
|
490
|
-
client: 'antigravity',
|
|
491
|
-
value: { claude: false, cursor: false, codex: false, vscode: false, antigravity: true },
|
|
492
|
-
},
|
|
493
|
-
{
|
|
494
|
-
client: 'all',
|
|
495
|
-
value: { claude: true, cursor: true, codex: true, vscode: true, antigravity: true },
|
|
496
|
-
},
|
|
497
|
-
];
|
|
498
|
-
if (input.setRawMode && output.isTTY) {
|
|
499
|
-
return promptTargetSelect(choices, 5);
|
|
500
|
-
}
|
|
501
|
-
const rl = createInterface({ input, output });
|
|
502
|
-
const line = (await rl.question('Where should Enfyra MCP config be written?\n'
|
|
503
|
-
+ ' [1] Codex ./.codex/config.toml\n'
|
|
504
|
-
+ ' [2] Claude Code ./.mcp.json\n'
|
|
505
|
-
+ ' [3] Cursor ./.cursor/mcp.json\n'
|
|
506
|
-
+ ' [4] VS Code ./.vscode/mcp.json\n'
|
|
507
|
-
+ ' [5] Antigravity ./.agents/mcp_config.json\n'
|
|
508
|
-
+ ' [6] All [default]\n'
|
|
509
|
-
+ 'Choice [6]: ')).trim().toLowerCase();
|
|
510
|
-
await rl.close();
|
|
511
|
-
if (line === '' || line === '6' || line === 'all' || line === 'a') {
|
|
512
|
-
return { claude: true, cursor: true, codex: true, vscode: true, antigravity: true };
|
|
513
|
-
}
|
|
514
|
-
if (line === '1' || line === 'codex' || line === 'x') {
|
|
515
|
-
return { claude: false, cursor: false, codex: true, vscode: false, antigravity: false };
|
|
516
|
-
}
|
|
517
|
-
if (line === '2' || line === 'claude' || line === 'claude-code') {
|
|
518
|
-
return { claude: true, cursor: false, codex: false, vscode: false, antigravity: false };
|
|
519
|
-
}
|
|
520
|
-
if (line === '3' || line === 'cursor' || line === 'u') {
|
|
521
|
-
return { claude: false, cursor: true, codex: false, vscode: false, antigravity: false };
|
|
522
|
-
}
|
|
523
|
-
if (line === '4' || line === 'vscode' || line === 'vs-code' || line === 'copilot') {
|
|
524
|
-
return { claude: false, cursor: false, codex: false, vscode: true, antigravity: false };
|
|
525
|
-
}
|
|
526
|
-
if (line === '5' || line === 'antigravity') {
|
|
527
|
-
return { claude: false, cursor: false, codex: false, vscode: false, antigravity: true };
|
|
528
|
-
}
|
|
529
|
-
return { claude: true, cursor: true, codex: true, vscode: true, antigravity: true };
|
|
530
|
-
}
|
|
531
|
-
async function promptTargetSelect(choices, initialIndex = 0) {
|
|
532
|
-
let selected = Math.max(0, Math.min(initialIndex, choices.length - 1));
|
|
533
|
-
let renderedLines = 0;
|
|
534
|
-
const formatChoice = (choice, active) => {
|
|
535
|
-
const indicator = active ? style.cyan('◆') : style.dim('◇');
|
|
536
|
-
const accent = active ? style.cyan('│') : style.dim('│');
|
|
537
|
-
if (choice.client === 'all') {
|
|
538
|
-
const label = active ? style.bold(style.underline('All supported clients')) : 'All supported clients';
|
|
539
|
-
const paddedLabel = label + ' '.repeat(22 - 'All supported clients'.length);
|
|
540
|
-
const hint = active ? style.cyan('Codex + Claude Code + Cursor + VS Code + Antigravity') : style.dim('Codex + Claude Code + Cursor + VS Code + Antigravity');
|
|
541
|
-
return `${accent} ${indicator} ${paddedLabel} ${hint}`;
|
|
542
|
-
}
|
|
543
|
-
const meta = clients[choice.client];
|
|
544
|
-
const label = active ? style.bold(meta.color(meta.label)) : meta.color(meta.label);
|
|
545
|
-
const paddedLabel = label + ' '.repeat(Math.max(1, 22 - meta.label.length));
|
|
546
|
-
const path = active ? style.cyan(meta.path) : style.dim(meta.path);
|
|
547
|
-
return `${accent} ${indicator} ${paddedLabel} ${path}`;
|
|
548
|
-
};
|
|
549
|
-
const render = () => {
|
|
550
|
-
if (renderedLines > 0) {
|
|
551
|
-
output.write(`\x1B[${renderedLines}A\x1B[0J`);
|
|
552
|
-
}
|
|
553
|
-
const lines = [
|
|
554
|
-
`${style.cyan('◆')} ${style.bold('Enfyra MCP setup')}`,
|
|
555
|
-
`${style.dim('│')} ${style.dim('Choose where to write the project config.')}`,
|
|
556
|
-
style.dim('│'),
|
|
557
|
-
...choices.map((choice, index) => formatChoice(choice, index === selected)),
|
|
558
|
-
style.dim('│'),
|
|
559
|
-
style.dim('Choose one client config, or write all supported project configs.'),
|
|
560
|
-
`${style.dim('└')} ${style.dim('Use ↑/↓ to move, Enter to select, Ctrl+C to cancel.')}`,
|
|
561
|
-
];
|
|
562
|
-
renderedLines = lines.length;
|
|
563
|
-
output.write(`${lines.join('\n')}\n`);
|
|
564
|
-
};
|
|
565
|
-
return new Promise((resolve, reject) => {
|
|
566
|
-
const wasRaw = input.isRaw;
|
|
567
|
-
const cleanup = () => {
|
|
568
|
-
input.off('keypress', onKeypress);
|
|
569
|
-
if (!wasRaw)
|
|
570
|
-
input.setRawMode(false);
|
|
571
|
-
output.write('\x1B[?25h');
|
|
572
|
-
};
|
|
573
|
-
const finish = () => {
|
|
574
|
-
cleanup();
|
|
575
|
-
resolve(choices[selected].value);
|
|
576
|
-
};
|
|
577
|
-
const onKeypress = (_str, key = {}) => {
|
|
578
|
-
if (key.ctrl && key.name === 'c') {
|
|
579
|
-
cleanup();
|
|
580
|
-
output.write('\n');
|
|
581
|
-
reject(new Error('Cancelled'));
|
|
582
|
-
return;
|
|
583
|
-
}
|
|
584
|
-
if (key.name === 'up') {
|
|
585
|
-
selected = selected <= 0 ? choices.length - 1 : selected - 1;
|
|
586
|
-
render();
|
|
587
|
-
return;
|
|
588
|
-
}
|
|
589
|
-
if (key.name === 'down') {
|
|
590
|
-
selected = selected >= choices.length - 1 ? 0 : selected + 1;
|
|
591
|
-
render();
|
|
592
|
-
return;
|
|
593
|
-
}
|
|
594
|
-
if (key.name === 'return' || key.name === 'enter') {
|
|
595
|
-
finish();
|
|
596
|
-
}
|
|
597
|
-
};
|
|
598
|
-
emitKeypressEvents(input);
|
|
599
|
-
input.setRawMode(true);
|
|
600
|
-
input.resume();
|
|
601
|
-
output.write('\x1B[?25l');
|
|
602
|
-
input.on('keypress', onKeypress);
|
|
603
|
-
render();
|
|
604
|
-
});
|
|
605
|
-
}
|
|
606
|
-
async function promptConfig(opts, existing) {
|
|
607
|
-
let appUrl = opts.appUrl ? normalizeAppUrl(opts.appUrl) : '';
|
|
608
|
-
let apiToken = opts.apiToken;
|
|
609
|
-
if (appUrl && apiToken !== undefined) {
|
|
610
|
-
return { apiUrl: deriveApiUrlFromAppUrl(appUrl), apiToken };
|
|
611
|
-
}
|
|
612
|
-
const rl = createInterface({ input, output });
|
|
613
|
-
const q = async (msg) => {
|
|
614
|
-
try {
|
|
615
|
-
return await rl.question(msg);
|
|
616
|
-
}
|
|
617
|
-
catch (error) {
|
|
618
|
-
if (isCancelError(error)) {
|
|
619
|
-
throw new Error('Cancelled');
|
|
620
|
-
}
|
|
621
|
-
throw error;
|
|
622
|
-
}
|
|
623
|
-
};
|
|
624
|
-
const defaultAppUrl = resolveDefaultAppUrl(opts, existing);
|
|
625
|
-
if (!appUrl) {
|
|
626
|
-
console.log(`${style.cyan('◆')} ${style.bold('Connect to Enfyra')}`);
|
|
627
|
-
console.log(`${style.dim('│')} Enter the Enfyra app URL.`);
|
|
628
|
-
const line = (await q(`${style.dim('└')} ENFYRA_APP_URL ${style.dim(`[${defaultAppUrl}]`)}: `)).trim();
|
|
629
|
-
appUrl = normalizeAppUrl(line || defaultAppUrl);
|
|
630
|
-
}
|
|
631
|
-
const apiUrl = deriveApiUrlFromAppUrl(appUrl);
|
|
632
|
-
const defaultApiToken = opts.apiToken ?? process.env.ENFYRA_API_TOKEN ?? existing.apiToken ?? '';
|
|
633
|
-
if (apiToken === undefined) {
|
|
634
|
-
const hint = defaultApiToken ? ' (Enter = keep current)' : '';
|
|
635
|
-
const meUrl = deriveMeUrl(appUrl);
|
|
636
|
-
console.log('');
|
|
637
|
-
console.log(`${style.cyan('◆')} ${style.bold('API token')}`);
|
|
638
|
-
console.log(`${style.dim('│')} If you do not have a token yet, create one here: ${style.cyan(meUrl)}`);
|
|
639
|
-
const line = (await q(`${style.dim('└')} ENFYRA_API_TOKEN${hint}: `)).trim();
|
|
640
|
-
apiToken = line !== '' ? line : defaultApiToken;
|
|
641
|
-
}
|
|
642
|
-
await rl.close();
|
|
643
|
-
return { apiUrl, apiToken };
|
|
644
|
-
}
|
|
645
|
-
function resolveNonInteractive(opts, existing) {
|
|
646
|
-
const appUrl = resolveDefaultAppUrl(opts, existing);
|
|
647
|
-
const apiUrl = deriveApiUrlFromAppUrl(appUrl);
|
|
648
|
-
const apiToken = opts.apiToken ?? process.env.ENFYRA_API_TOKEN ?? existing.apiToken ?? '';
|
|
649
|
-
return { apiUrl, apiToken };
|
|
650
|
-
}
|
|
2
|
+
import { clients, exitCancelled, isCancelError, parseArgs, printHelp, statusIcon, style, } from './config-local-contracts.js';
|
|
3
|
+
import { assertProjectConfigUntracked, buildServerEntry, ensureProjectConfigIgnored, getClientPath, loadExistingEnfyraEnv, mergeCodexConfig, mergeMcpFile, mergeVscodeMcpFile, } from './config-local-adapters.js';
|
|
4
|
+
import { promptConfig, promptTargetChoice, resolveNonInteractive } from './config-local-prompts.js';
|
|
651
5
|
export async function runLocalConfig(argv) {
|
|
652
6
|
const onSigint = () => exitCancelled();
|
|
653
7
|
const onUnhandledRejection = (error) => {
|