fraim-framework 2.0.81 → 2.0.83

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.
Files changed (33) hide show
  1. package/dist/src/cli/api/get-provider-client.js +41 -0
  2. package/dist/src/cli/api/provider-client.js +107 -0
  3. package/dist/src/cli/commands/add-ide.js +144 -77
  4. package/dist/src/cli/commands/add-provider.js +223 -0
  5. package/dist/src/cli/commands/doctor.js +131 -111
  6. package/dist/src/cli/commands/init-project.js +67 -31
  7. package/dist/src/cli/commands/setup.js +247 -563
  8. package/dist/src/cli/commands/sync.js +2 -2
  9. package/dist/src/cli/commands/test-mcp.js +35 -1
  10. package/dist/src/cli/doctor/check-runner.js +199 -0
  11. package/dist/src/cli/doctor/checks/global-setup-checks.js +220 -0
  12. package/dist/src/cli/doctor/checks/ide-config-checks.js +250 -0
  13. package/dist/src/cli/doctor/checks/mcp-connectivity-checks.js +381 -0
  14. package/dist/src/cli/doctor/checks/project-setup-checks.js +282 -0
  15. package/dist/src/cli/doctor/checks/scripts-checks.js +157 -0
  16. package/dist/src/cli/doctor/checks/workflow-checks.js +247 -0
  17. package/dist/src/cli/doctor/reporters/console-reporter.js +96 -0
  18. package/dist/src/cli/doctor/reporters/json-reporter.js +11 -0
  19. package/dist/src/cli/doctor/types.js +6 -0
  20. package/dist/src/cli/fraim.js +44 -3
  21. package/dist/src/cli/mcp/ide-formats.js +243 -0
  22. package/dist/src/cli/mcp/mcp-server-builder.js +48 -0
  23. package/dist/src/cli/mcp/mcp-server-registry.js +159 -0
  24. package/dist/src/cli/mcp/types.js +3 -0
  25. package/dist/src/cli/providers/local-provider-registry.js +145 -0
  26. package/dist/src/cli/providers/provider-registry.js +230 -0
  27. package/dist/src/cli/setup/auto-mcp-setup.js +56 -118
  28. package/dist/src/cli/setup/mcp-config-generator.js +64 -321
  29. package/dist/src/cli/setup/provider-prompts.js +300 -0
  30. package/dist/src/cli/utils/remote-sync.js +22 -2
  31. package/package.json +4 -2
  32. package/dist/src/cli/commands/install.js +0 -86
  33. package/dist/src/cli/setup/token-validator.js +0 -57
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ /**
3
+ * Console reporter for FRAIM doctor command
4
+ * Formats output with colors and emojis
5
+ * Issue #144: Enhanced doctor command
6
+ */
7
+ var __importDefault = (this && this.__importDefault) || function (mod) {
8
+ return (mod && mod.__esModule) ? mod : { "default": mod };
9
+ };
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.formatConsoleOutput = formatConsoleOutput;
12
+ const chalk_1 = __importDefault(require("chalk"));
13
+ const CATEGORY_NAMES = {
14
+ globalSetup: 'Global Setup',
15
+ projectSetup: 'Project Setup',
16
+ workflows: 'Workflows',
17
+ ideConfiguration: 'IDE Configuration',
18
+ mcpConnectivity: 'MCP Server Connectivity',
19
+ scripts: 'Scripts'
20
+ };
21
+ function getStatusIcon(status) {
22
+ switch (status) {
23
+ case 'passed': return '✅';
24
+ case 'warning': return '⚠️';
25
+ case 'error': return '❌';
26
+ }
27
+ }
28
+ function formatLatency(latency) {
29
+ if (!latency)
30
+ return '';
31
+ return chalk_1.default.gray(` (${latency}ms)`);
32
+ }
33
+ function formatConsoleOutput(result, options) {
34
+ const lines = [];
35
+ // Header
36
+ lines.push(chalk_1.default.blue('🩺 FRAIM Doctor - Comprehensive Health Check\n'));
37
+ // Categories
38
+ for (const [categoryKey, categoryResult] of Object.entries(result.categories)) {
39
+ // Skip empty categories
40
+ if (categoryResult.checks.length === 0)
41
+ continue;
42
+ const categoryName = CATEGORY_NAMES[categoryKey] || categoryKey;
43
+ lines.push(chalk_1.default.bold(`━━━ ${categoryName} ━━━`));
44
+ for (const check of categoryResult.checks) {
45
+ const icon = getStatusIcon(check.status);
46
+ const latency = formatLatency(check.latency);
47
+ lines.push(`${icon} ${check.message}${latency}`);
48
+ // Show details in verbose mode
49
+ if (options.verbose && check.details) {
50
+ for (const [key, value] of Object.entries(check.details)) {
51
+ lines.push(chalk_1.default.gray(` ${key}: ${value}`));
52
+ }
53
+ }
54
+ // Show suggestions for warnings and errors
55
+ if (check.suggestion) {
56
+ lines.push(chalk_1.default.blue(` 💡 ${check.suggestion}`));
57
+ if (check.command) {
58
+ lines.push(chalk_1.default.gray(` Run: ${check.command}`));
59
+ }
60
+ }
61
+ }
62
+ lines.push(''); // Empty line between categories
63
+ }
64
+ // Summary
65
+ lines.push(chalk_1.default.bold('━━━ Summary ━━━'));
66
+ lines.push(`${chalk_1.default.green('✅')} ${result.summary.passed} checks passed`);
67
+ if (result.summary.warnings > 0) {
68
+ lines.push(`${chalk_1.default.yellow('⚠️')} ${result.summary.warnings} warnings`);
69
+ }
70
+ if (result.summary.errors > 0) {
71
+ lines.push(`${chalk_1.default.red('❌')} ${result.summary.errors} errors`);
72
+ }
73
+ lines.push('');
74
+ // Final message
75
+ if (result.summary.errors === 0 && result.summary.warnings === 0) {
76
+ lines.push(chalk_1.default.green('✨ Everything looks great! Your FRAIM setup is healthy.'));
77
+ }
78
+ else if (result.summary.errors === 0) {
79
+ lines.push(chalk_1.default.yellow('⚠️ Some warnings found. See suggestions below.'));
80
+ }
81
+ else {
82
+ lines.push(chalk_1.default.red('❌ Issues found. See suggestions below.'));
83
+ }
84
+ // Suggestions
85
+ if (result.suggestions && result.suggestions.length > 0) {
86
+ lines.push('');
87
+ lines.push(chalk_1.default.blue('💡 Suggested fixes:'));
88
+ for (const suggestion of result.suggestions.slice(0, 5)) { // Show top 5
89
+ lines.push(chalk_1.default.blue(` ${suggestion.priority}. ${suggestion.message}`));
90
+ if (suggestion.command) {
91
+ lines.push(chalk_1.default.gray(` Run: ${suggestion.command}`));
92
+ }
93
+ }
94
+ }
95
+ return lines.join('\n');
96
+ }
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ /**
3
+ * JSON reporter for FRAIM doctor command
4
+ * Formats output as JSON for automation
5
+ * Issue #144: Enhanced doctor command
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.formatJsonOutput = formatJsonOutput;
9
+ function formatJsonOutput(result) {
10
+ return JSON.stringify(result, null, 2);
11
+ }
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ /**
3
+ * Type definitions for the FRAIM doctor command
4
+ * Issue #144: Enhanced doctor command
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,5 +1,38 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
3
36
  var __importDefault = (this && this.__importDefault) || function (mod) {
4
37
  return (mod && mod.__esModule) ? mod : { "default": mod };
5
38
  };
@@ -12,9 +45,9 @@ const setup_1 = require("./commands/setup");
12
45
  const init_project_1 = require("./commands/init-project");
13
46
  const test_mcp_1 = require("./commands/test-mcp");
14
47
  const add_ide_1 = require("./commands/add-ide");
48
+ const add_provider_1 = require("./commands/add-provider");
15
49
  const override_1 = require("./commands/override");
16
50
  const list_overridable_1 = require("./commands/list-overridable");
17
- const install_1 = require("./commands/install");
18
51
  const fs_1 = __importDefault(require("fs"));
19
52
  const path_1 = __importDefault(require("path"));
20
53
  const program = new commander_1.Command();
@@ -49,7 +82,15 @@ program.addCommand(setup_1.setupCommand);
49
82
  program.addCommand(init_project_1.initProjectCommand);
50
83
  program.addCommand(test_mcp_1.testMCPCommand);
51
84
  program.addCommand(add_ide_1.addIDECommand);
85
+ program.addCommand(add_provider_1.addProviderCommand);
52
86
  program.addCommand(override_1.overrideCommand);
53
87
  program.addCommand(list_overridable_1.listOverridableCommand);
54
- program.addCommand(install_1.installCommand);
55
- program.parse(process.argv);
88
+ // Wait for async command initialization before parsing
89
+ (async () => {
90
+ // Import the initialization promise from setup command
91
+ const { setupCommandInitialization } = await Promise.resolve().then(() => __importStar(require('./commands/setup')));
92
+ if (setupCommandInitialization) {
93
+ await setupCommandInitialization;
94
+ }
95
+ program.parse(process.argv);
96
+ })();
@@ -0,0 +1,243 @@
1
+ "use strict";
2
+ // IDE Format Adapters - transform logical server structure to IDE-specific formats
3
+ // Uses the centralized registry to determine server types
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.IDE_FORMATS = exports.CodexFormat = exports.WindsurfFormat = exports.ClaudeCodeFormat = exports.ClaudeFormat = exports.VSCodeFormat = exports.KiroFormat = exports.StandardFormat = void 0;
6
+ exports.getIDEFormat = getIDEFormat;
7
+ const mcp_server_registry_1 = require("./mcp-server-registry");
8
+ const provider_registry_1 = require("../providers/provider-registry");
9
+ // Standard format (Cursor, Kiro, Antigravity, etc.)
10
+ class StandardFormat {
11
+ constructor() {
12
+ this.name = 'standard';
13
+ }
14
+ transform(servers) {
15
+ const mcpServers = {};
16
+ for (const [key, server] of servers) {
17
+ if (server.url) {
18
+ // HTTP server - use serverUrl for standard format
19
+ mcpServers[key] = {
20
+ serverUrl: server.url,
21
+ headers: server.headers
22
+ };
23
+ }
24
+ else {
25
+ // stdio server
26
+ mcpServers[key] = {
27
+ command: server.command,
28
+ ...(server.args && { args: server.args }),
29
+ ...(server.env && { env: server.env })
30
+ };
31
+ }
32
+ }
33
+ return { mcpServers };
34
+ }
35
+ }
36
+ exports.StandardFormat = StandardFormat;
37
+ // Kiro format (also used by Cursor)
38
+ class KiroFormat {
39
+ constructor() {
40
+ this.name = 'kiro';
41
+ }
42
+ transform(servers) {
43
+ const mcpServers = {};
44
+ for (const [key, server] of servers) {
45
+ if (server.url) {
46
+ // HTTP server - use url (not serverUrl)
47
+ mcpServers[key] = {
48
+ url: server.url,
49
+ headers: server.headers
50
+ };
51
+ }
52
+ else {
53
+ // stdio server
54
+ mcpServers[key] = {
55
+ command: server.command,
56
+ ...(server.args && { args: server.args }),
57
+ ...(server.env && { env: server.env })
58
+ };
59
+ }
60
+ }
61
+ return { mcpServers };
62
+ }
63
+ }
64
+ exports.KiroFormat = KiroFormat;
65
+ // VSCode format
66
+ class VSCodeFormat {
67
+ constructor() {
68
+ this.name = 'vscode';
69
+ }
70
+ transform(servers) {
71
+ const vscodeServers = {};
72
+ for (const [key, server] of servers) {
73
+ if (server.url) {
74
+ // HTTP server
75
+ vscodeServers[key] = {
76
+ type: 'http',
77
+ url: server.url,
78
+ headers: server.headers
79
+ };
80
+ }
81
+ else {
82
+ // stdio server
83
+ vscodeServers[key] = {
84
+ type: 'stdio',
85
+ command: server.command,
86
+ ...(server.args && { args: server.args }),
87
+ ...(server.env && { env: server.env })
88
+ };
89
+ }
90
+ }
91
+ return { servers: vscodeServers };
92
+ }
93
+ }
94
+ exports.VSCodeFormat = VSCodeFormat;
95
+ // Claude Desktop format (excludes provider servers - Issue #132)
96
+ class ClaudeFormat {
97
+ constructor() {
98
+ this.name = 'claude';
99
+ }
100
+ async transform(servers) {
101
+ const mcpServers = {};
102
+ for (const [key, server] of servers) {
103
+ // Skip all provider servers - they break Claude Desktop
104
+ // See: https://github.com/mathursrus/FRAIM/issues/132
105
+ if (await (0, mcp_server_registry_1.isProviderServer)(key)) {
106
+ continue;
107
+ }
108
+ // Only include base servers (git, playwright, fraim)
109
+ mcpServers[key] = {
110
+ command: server.command,
111
+ ...(server.args && { args: server.args }),
112
+ ...(server.env && { env: server.env })
113
+ };
114
+ }
115
+ return { mcpServers };
116
+ }
117
+ }
118
+ exports.ClaudeFormat = ClaudeFormat;
119
+ // Claude Code format (supports HTTP servers with VSCode-style format)
120
+ class ClaudeCodeFormat {
121
+ constructor() {
122
+ this.name = 'claude-code';
123
+ }
124
+ transform(servers) {
125
+ const mcpServers = {};
126
+ for (const [key, server] of servers) {
127
+ if (server.url) {
128
+ // HTTP server - use VSCode-style format
129
+ mcpServers[key] = {
130
+ type: 'http',
131
+ url: server.url,
132
+ headers: server.headers
133
+ };
134
+ }
135
+ else {
136
+ // stdio server
137
+ mcpServers[key] = {
138
+ command: server.command,
139
+ ...(server.args && { args: server.args }),
140
+ ...(server.env && { env: server.env })
141
+ };
142
+ }
143
+ }
144
+ return { mcpServers };
145
+ }
146
+ }
147
+ exports.ClaudeCodeFormat = ClaudeCodeFormat;
148
+ // Windsurf format (uses server-fetch wrapper for HTTP servers)
149
+ class WindsurfFormat {
150
+ constructor() {
151
+ this.name = 'windsurf';
152
+ }
153
+ async transform(servers) {
154
+ const mcpServers = {};
155
+ for (const [key, server] of servers) {
156
+ if (server.url) {
157
+ // HTTP server - wrap with server-fetch
158
+ const provider = await (0, provider_registry_1.getProvider)(key);
159
+ const tokenEnvVar = provider?.id ? `${provider.id.toUpperCase()}_TOKEN` : undefined;
160
+ if (tokenEnvVar && server.headers?.Authorization) {
161
+ const token = server.headers.Authorization.replace('Bearer ', '');
162
+ mcpServers[key] = {
163
+ command: 'npx',
164
+ args: ['-y', '@modelcontextprotocol/server-fetch', server.url],
165
+ env: {
166
+ [tokenEnvVar]: token
167
+ }
168
+ };
169
+ }
170
+ }
171
+ else {
172
+ // stdio server
173
+ mcpServers[key] = {
174
+ command: server.command,
175
+ ...(server.args && { args: server.args }),
176
+ ...(server.env && { env: server.env })
177
+ };
178
+ }
179
+ }
180
+ return { mcpServers };
181
+ }
182
+ }
183
+ exports.WindsurfFormat = WindsurfFormat;
184
+ // Codex format (TOML)
185
+ class CodexFormat {
186
+ constructor() {
187
+ this.name = 'codex';
188
+ }
189
+ transform(servers) {
190
+ const sections = [];
191
+ for (const [key, server] of servers) {
192
+ if (server.url) {
193
+ // HTTP server
194
+ const token = server.headers?.Authorization?.replace('Bearer ', '') || '';
195
+ const escapedToken = this.escapeToml(token);
196
+ const escapedUrl = this.escapeToml(server.url);
197
+ sections.push(`[mcp_servers.${key}]`);
198
+ sections.push(`url = "${escapedUrl}"`);
199
+ sections.push(`http_headers = { Authorization = "Bearer ${escapedToken}" }`);
200
+ sections.push('');
201
+ }
202
+ else {
203
+ // stdio server
204
+ sections.push(`[mcp_servers.${key}]`);
205
+ sections.push(`command = "${this.escapeToml(server.command || '')}"`);
206
+ if (server.args && server.args.length > 0) {
207
+ const argsStr = server.args.map(arg => `"${this.escapeToml(arg)}"`).join(', ');
208
+ sections.push(`args = [${argsStr}]`);
209
+ }
210
+ if (server.env) {
211
+ sections.push('');
212
+ sections.push(`[mcp_servers.${key}.env]`);
213
+ for (const [envKey, envValue] of Object.entries(server.env)) {
214
+ sections.push(`${envKey} = "${this.escapeToml(envValue)}"`);
215
+ }
216
+ }
217
+ sections.push('');
218
+ }
219
+ }
220
+ return sections.join('\n');
221
+ }
222
+ escapeToml(value) {
223
+ return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
224
+ }
225
+ }
226
+ exports.CodexFormat = CodexFormat;
227
+ // Format registry
228
+ exports.IDE_FORMATS = {
229
+ standard: new StandardFormat(),
230
+ kiro: new KiroFormat(),
231
+ vscode: new VSCodeFormat(),
232
+ claude: new ClaudeFormat(),
233
+ 'claude-code': new ClaudeCodeFormat(),
234
+ windsurf: new WindsurfFormat(),
235
+ codex: new CodexFormat()
236
+ };
237
+ function getIDEFormat(configType) {
238
+ const format = exports.IDE_FORMATS[configType];
239
+ if (!format) {
240
+ throw new Error(`Unsupported IDE format: ${configType}`);
241
+ }
242
+ return format;
243
+ }
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ // MCP Server Builder - builds logical server structure (format-agnostic)
3
+ // Uses the centralized registry for all server definitions
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.MCPServerBuilder = void 0;
6
+ const mcp_server_registry_1 = require("./mcp-server-registry");
7
+ class MCPServerBuilder {
8
+ constructor() {
9
+ this.servers = new Map();
10
+ }
11
+ addBaseServers(fraimKey) {
12
+ const baseServers = (0, mcp_server_registry_1.buildAllBaseServers)(fraimKey);
13
+ for (const [id, server] of baseServers) {
14
+ this.servers.set(id, server);
15
+ }
16
+ return this;
17
+ }
18
+ async addProvider(providerId, token, config) {
19
+ try {
20
+ const server = await (0, mcp_server_registry_1.buildProviderMCPServer)(providerId, token, config);
21
+ this.servers.set(providerId, server);
22
+ }
23
+ catch (error) {
24
+ // Always warn user when MCP server can't be built
25
+ // Common case: Jira without baseUrl/email config
26
+ const errorMessage = error instanceof Error ? error.message : String(error);
27
+ console.warn(`⚠️ Skipping ${providerId} MCP server: ${errorMessage}`);
28
+ }
29
+ return this;
30
+ }
31
+ // Legacy methods for backward compatibility - delegate to addProvider
32
+ async addGitHub(token) {
33
+ return await this.addProvider('github', token);
34
+ }
35
+ async addGitLab(token) {
36
+ return await this.addProvider('gitlab', token);
37
+ }
38
+ async addJira(token, config) {
39
+ return await this.addProvider('jira', token, config);
40
+ }
41
+ getServers() {
42
+ return new Map(this.servers);
43
+ }
44
+ toObject() {
45
+ return Object.fromEntries(this.servers);
46
+ }
47
+ }
48
+ exports.MCPServerBuilder = MCPServerBuilder;
@@ -0,0 +1,159 @@
1
+ "use strict";
2
+ // MCP Server Registry - Builds MCP servers from provider definitions
3
+ // This file NO LONGER contains hardcoded server configurations
4
+ // All provider MCP server configs come from the provider registry (server or local fallback)
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.BASE_MCP_SERVERS = void 0;
7
+ exports.buildProviderMCPServer = buildProviderMCPServer;
8
+ exports.getBaseMCPServer = getBaseMCPServer;
9
+ exports.getProviderMCPServerIds = getProviderMCPServerIds;
10
+ exports.getAllMCPServerIds = getAllMCPServerIds;
11
+ exports.isProviderServer = isProviderServer;
12
+ exports.isHTTPServer = isHTTPServer;
13
+ exports.buildAllBaseServers = buildAllBaseServers;
14
+ const provider_registry_1 = require("../providers/provider-registry");
15
+ exports.BASE_MCP_SERVERS = [
16
+ {
17
+ id: 'git',
18
+ name: 'Git',
19
+ description: 'Git repository operations (commit, branch, merge, etc.)',
20
+ buildServer: () => ({
21
+ command: 'npx',
22
+ args: ['-y', '@cyanheads/git-mcp-server']
23
+ })
24
+ },
25
+ {
26
+ id: 'playwright',
27
+ name: 'Playwright',
28
+ description: 'Browser automation and testing',
29
+ buildServer: () => ({
30
+ command: 'npx',
31
+ args: ['-y', '@playwright/mcp']
32
+ })
33
+ },
34
+ {
35
+ id: 'fraim',
36
+ name: 'FRAIM',
37
+ description: 'FRAIM workflow orchestration and mentoring',
38
+ buildServer: (fraimKey) => ({
39
+ command: 'fraim-mcp',
40
+ env: {
41
+ FRAIM_API_KEY: fraimKey,
42
+ FRAIM_REMOTE_URL: 'https://fraim.wellnessatwork.me'
43
+ }
44
+ })
45
+ }
46
+ ];
47
+ // ============================================================================
48
+ // PROVIDER MCP SERVER BUILDER (uses provider registry)
49
+ // ============================================================================
50
+ /**
51
+ * Build an MCP server for a provider using its definition from the registry
52
+ */
53
+ async function buildProviderMCPServer(providerId, token, config) {
54
+ // Get provider definition from registry (server or local fallback)
55
+ const provider = await (0, provider_registry_1.getProvider)(providerId);
56
+ if (!provider) {
57
+ throw new Error(`Unknown provider: ${providerId}`);
58
+ }
59
+ if (!provider.mcpServer) {
60
+ throw new Error(`Provider ${providerId} does not have an MCP server configuration`);
61
+ }
62
+ const mcpConfig = provider.mcpServer;
63
+ // Validate config if provider requires additional config
64
+ if (provider.hasAdditionalConfig) {
65
+ const validation = await (0, provider_registry_1.validateProviderConfig)(providerId, config || {});
66
+ if (!validation.valid) {
67
+ throw new Error(`${provider.displayName} requires additional configuration: ${validation.missing.join(', ')}`);
68
+ }
69
+ }
70
+ // Build MCP server based on type
71
+ if (mcpConfig.type === 'http') {
72
+ return buildHTTPServer(mcpConfig, token);
73
+ }
74
+ else {
75
+ return buildStdioServer(mcpConfig, token, config);
76
+ }
77
+ }
78
+ /**
79
+ * Build an HTTP MCP server
80
+ */
81
+ function buildHTTPServer(mcpConfig, token) {
82
+ if (!mcpConfig.url) {
83
+ throw new Error('HTTP MCP server requires url');
84
+ }
85
+ const authHeader = mcpConfig.authHeaderTemplate?.replace('{token}', token) || `Bearer ${token}`;
86
+ return {
87
+ url: mcpConfig.url,
88
+ headers: {
89
+ Authorization: authHeader
90
+ }
91
+ };
92
+ }
93
+ /**
94
+ * Build a stdio MCP server
95
+ */
96
+ function buildStdioServer(mcpConfig, token, config) {
97
+ if (!mcpConfig.command) {
98
+ throw new Error('Stdio MCP server requires command');
99
+ }
100
+ // Build environment variables from template
101
+ const env = {};
102
+ if (mcpConfig.envTemplate) {
103
+ for (const [key, template] of Object.entries(mcpConfig.envTemplate)) {
104
+ let value = template;
105
+ // Replace {token} placeholder
106
+ value = value.replace('{token}', token);
107
+ // Replace {config.key} placeholders
108
+ if (config) {
109
+ for (const [configKey, configValue] of Object.entries(config)) {
110
+ value = value.replace(`{config.${configKey}}`, String(configValue));
111
+ }
112
+ }
113
+ // Handle URL normalization for Jira
114
+ if (key === 'JIRA_URL' && value && !value.startsWith('http')) {
115
+ value = `https://${value}`;
116
+ }
117
+ env[key] = value;
118
+ }
119
+ }
120
+ return {
121
+ command: mcpConfig.command,
122
+ args: mcpConfig.args || [],
123
+ env
124
+ };
125
+ }
126
+ // ============================================================================
127
+ // REGISTRY LOOKUP FUNCTIONS
128
+ // ============================================================================
129
+ function getBaseMCPServer(id) {
130
+ return exports.BASE_MCP_SERVERS.find(server => server.id === id);
131
+ }
132
+ async function getProviderMCPServerIds() {
133
+ // This would need to fetch all providers and filter those with MCP servers
134
+ // For now, return empty array - this function is not critical
135
+ return [];
136
+ }
137
+ function getAllMCPServerIds() {
138
+ // Return only base server IDs
139
+ // Provider server IDs are dynamic and come from the registry
140
+ return exports.BASE_MCP_SERVERS.map(s => s.id);
141
+ }
142
+ async function isProviderServer(serverId) {
143
+ const provider = await (0, provider_registry_1.getProvider)(serverId);
144
+ return provider !== undefined && provider.mcpServer !== undefined;
145
+ }
146
+ async function isHTTPServer(serverId) {
147
+ const provider = await (0, provider_registry_1.getProvider)(serverId);
148
+ return provider?.mcpServer?.type === 'http';
149
+ }
150
+ // ============================================================================
151
+ // BUILDER HELPERS
152
+ // ============================================================================
153
+ function buildAllBaseServers(fraimKey) {
154
+ const servers = new Map();
155
+ for (const def of exports.BASE_MCP_SERVERS) {
156
+ servers.set(def.id, def.buildServer(fraimKey));
157
+ }
158
+ return servers;
159
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ // Shared types for MCP configuration
3
+ Object.defineProperty(exports, "__esModule", { value: true });