@comfanion/workflow 4.36.29 → 4.36.30

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/bin/cli.js CHANGED
@@ -259,14 +259,14 @@ program
259
259
  {
260
260
  type: 'checkbox',
261
261
  name: 'mcp_servers',
262
- message: 'Select MCP servers to enable:',
262
+ message: 'Select MCP servers to enable (writes to opencode.json):',
263
263
  choices: [
264
264
  { name: 'context7 - Library docs for npm, Go, Python (recommended)', value: 'context7', checked: true },
265
+ { name: 'grep - Search code examples from GitHub', value: 'grep', checked: false },
265
266
  { name: 'sequential-thinking - Enhanced reasoning for complex tasks', value: 'sequential-thinking', checked: false },
266
267
  { name: 'playwright - Browser automation and testing', value: 'playwright', checked: false },
267
- { name: 'chrome-devtools - Chrome debugging and inspection', value: 'chrome-devtools', checked: false },
268
- { name: 'atlassian - Jira/Confluence integration', value: 'atlassian', checked: false },
269
- { name: 'github - GitHub repos, issues, PRs', value: 'github', checked: false },
268
+ { name: 'github - GitHub repos, issues, PRs (needs GITHUB_TOKEN)', value: 'github', checked: false },
269
+ { name: 'sentry - Query Sentry issues and errors (OAuth)', value: 'sentry', checked: false },
270
270
  { name: 'postgres - PostgreSQL database queries', value: 'postgres', checked: false }
271
271
  ]
272
272
  }
@@ -504,26 +504,40 @@ program
504
504
  }
505
505
  }
506
506
 
507
- // Save MCP server selections (only if user made selections)
507
+ // Save MCP server selections to opencode.json
508
508
  if (config.mcp_servers && config.mcp_servers.length > 0) {
509
- spinner.text = 'Configuring MCP servers...';
510
- const mcpEnabledPath = path.join(targetDir, 'mcp', 'enabled.yaml');
509
+ spinner.text = 'Configuring MCP servers in opencode.json...';
510
+ const opencodeJsonPath = path.join(process.cwd(), 'opencode.json');
511
511
 
512
- // Don't overwrite existing enabled.yaml if updating
513
- if (!isUpdate || !await fs.pathExists(mcpEnabledPath)) {
514
- let mcpContent = `# Enabled MCP Servers
515
- # Your personal selection of MCP servers
516
- # This file is NOT modified by updates
517
-
518
- `;
519
- for (const server of config.mcp_servers) {
520
- mcpContent += `${server}:
521
- enabled: true
522
-
523
- `;
512
+ // MCP catalog with server configs
513
+ const mcpCatalog = {
514
+ 'context7': { type: 'remote', url: 'https://mcp.context7.com/mcp' },
515
+ 'grep': { type: 'remote', url: 'https://mcp.grep.app' },
516
+ 'sentry': { type: 'remote', url: 'https://mcp.sentry.dev/mcp', oauth: {} },
517
+ 'sequential-thinking': { type: 'local', command: ['npx', '-y', '@anthropic/mcp-sequential-thinking'] },
518
+ 'playwright': { type: 'local', command: ['npx', '-y', '@anthropic/mcp-playwright'] },
519
+ 'github': { type: 'local', command: ['npx', '-y', '@anthropic/mcp-github'] },
520
+ 'postgres': { type: 'local', command: ['npx', '-y', '@anthropic/mcp-postgres'] }
521
+ };
522
+
523
+ // Read existing opencode.json or create new
524
+ let opencodeConfig = { "$schema": "https://opencode.ai/config.json" };
525
+ try {
526
+ if (await fs.pathExists(opencodeJsonPath)) {
527
+ opencodeConfig = JSON.parse(await fs.readFile(opencodeJsonPath, 'utf8'));
528
+ }
529
+ } catch {}
530
+
531
+ // Add MCP servers
532
+ if (!opencodeConfig.mcp) opencodeConfig.mcp = {};
533
+ for (const serverId of config.mcp_servers) {
534
+ if (mcpCatalog[serverId]) {
535
+ opencodeConfig.mcp[serverId] = { ...mcpCatalog[serverId], enabled: true };
524
536
  }
525
- await fs.writeFile(mcpEnabledPath, mcpContent);
526
537
  }
538
+
539
+ await fs.writeFile(opencodeJsonPath, JSON.stringify(opencodeConfig, null, 2) + '\n');
540
+ console.log(chalk.green(`✅ MCP servers added to opencode.json`));
527
541
  }
528
542
 
529
543
  // Install plugin dependencies
@@ -1235,4 +1249,239 @@ program
1235
1249
  }
1236
1250
  });
1237
1251
 
1252
+ // =============================================================================
1253
+ // MCP COMMANDS
1254
+ // =============================================================================
1255
+
1256
+ // MCP catalog with server configs
1257
+ const MCP_CATALOG = {
1258
+ 'context7': {
1259
+ name: 'Context7',
1260
+ description: 'Library docs for npm, Go, Python',
1261
+ type: 'remote',
1262
+ url: 'https://mcp.context7.com/mcp',
1263
+ recommended: true
1264
+ },
1265
+ 'grep': {
1266
+ name: 'Grep by Vercel',
1267
+ description: 'Search code examples from GitHub',
1268
+ type: 'remote',
1269
+ url: 'https://mcp.grep.app',
1270
+ recommended: false
1271
+ },
1272
+ 'sentry': {
1273
+ name: 'Sentry',
1274
+ description: 'Query Sentry issues and errors',
1275
+ type: 'remote',
1276
+ url: 'https://mcp.sentry.dev/mcp',
1277
+ oauth: {},
1278
+ recommended: false
1279
+ },
1280
+ 'sequential-thinking': {
1281
+ name: 'Sequential Thinking',
1282
+ description: 'Enhanced reasoning for complex tasks',
1283
+ type: 'local',
1284
+ command: ['npx', '-y', '@anthropic/mcp-sequential-thinking'],
1285
+ recommended: true
1286
+ },
1287
+ 'playwright': {
1288
+ name: 'Playwright',
1289
+ description: 'Browser automation and testing',
1290
+ type: 'local',
1291
+ command: ['npx', '-y', '@anthropic/mcp-playwright'],
1292
+ recommended: false
1293
+ },
1294
+ 'github': {
1295
+ name: 'GitHub',
1296
+ description: 'GitHub repos, issues, PRs',
1297
+ type: 'local',
1298
+ command: ['npx', '-y', '@anthropic/mcp-github'],
1299
+ requires_env: ['GITHUB_TOKEN'],
1300
+ recommended: false
1301
+ },
1302
+ 'gitlab': {
1303
+ name: 'GitLab',
1304
+ description: 'GitLab repos, issues, MRs',
1305
+ type: 'local',
1306
+ command: ['npx', '-y', '@anthropic/mcp-gitlab'],
1307
+ requires_env: ['GITLAB_TOKEN'],
1308
+ recommended: false
1309
+ },
1310
+ 'postgres': {
1311
+ name: 'PostgreSQL',
1312
+ description: 'Query PostgreSQL databases',
1313
+ type: 'local',
1314
+ command: ['npx', '-y', '@anthropic/mcp-postgres'],
1315
+ requires_env: ['POSTGRES_CONNECTION_STRING'],
1316
+ recommended: false
1317
+ },
1318
+ 'slack': {
1319
+ name: 'Slack',
1320
+ description: 'Slack messages and channels',
1321
+ type: 'local',
1322
+ command: ['npx', '-y', '@anthropic/mcp-slack'],
1323
+ requires_env: ['SLACK_TOKEN'],
1324
+ recommended: false
1325
+ }
1326
+ };
1327
+
1328
+ program
1329
+ .command('mcp')
1330
+ .description('Manage MCP servers in opencode.json')
1331
+ .argument('<action>', 'list | add <id> | remove <id> | install')
1332
+ .argument('[server]', 'Server ID for add/remove')
1333
+ .action(async (action, server) => {
1334
+ const opencodeJsonPath = path.join(process.cwd(), 'opencode.json');
1335
+
1336
+ if (action === 'list') {
1337
+ console.log(chalk.blue.bold('\n🔌 Available MCP Servers\n'));
1338
+
1339
+ // Show installed
1340
+ let installed = {};
1341
+ try {
1342
+ if (await fs.pathExists(opencodeJsonPath)) {
1343
+ const config = JSON.parse(await fs.readFile(opencodeJsonPath, 'utf8'));
1344
+ installed = config.mcp || {};
1345
+ }
1346
+ } catch {}
1347
+
1348
+ for (const [id, info] of Object.entries(MCP_CATALOG)) {
1349
+ const isInstalled = installed[id];
1350
+ const status = isInstalled ? chalk.green('✓') : chalk.gray('○');
1351
+ const rec = info.recommended ? chalk.yellow(' ⭐') : '';
1352
+ const type = info.type === 'remote' ? chalk.cyan('[remote]') : chalk.gray('[local]');
1353
+ console.log(` ${status} ${chalk.white(id)}${rec} ${type}`);
1354
+ console.log(chalk.gray(` ${info.description}`));
1355
+ if (info.requires_env) {
1356
+ console.log(chalk.yellow(` Requires: ${info.requires_env.join(', ')}`));
1357
+ }
1358
+ }
1359
+
1360
+ console.log(chalk.gray('\nUsage:'));
1361
+ console.log(chalk.cyan(' npx @comfanion/workflow mcp add context7'));
1362
+ console.log(chalk.cyan(' npx @comfanion/workflow mcp remove github'));
1363
+ console.log('');
1364
+
1365
+ } else if (action === 'add') {
1366
+ if (!server) {
1367
+ console.log(chalk.red('Usage: mcp add <server-id>'));
1368
+ console.log(chalk.gray('Run `mcp list` to see available servers'));
1369
+ process.exit(1);
1370
+ }
1371
+
1372
+ if (!MCP_CATALOG[server]) {
1373
+ console.log(chalk.red(`Unknown server: ${server}`));
1374
+ console.log(chalk.gray('Run `mcp list` to see available servers'));
1375
+ process.exit(1);
1376
+ }
1377
+
1378
+ const spinner = ora(`Adding ${server}...`).start();
1379
+
1380
+ // Read or create opencode.json
1381
+ let config = { "$schema": "https://opencode.ai/config.json" };
1382
+ try {
1383
+ if (await fs.pathExists(opencodeJsonPath)) {
1384
+ config = JSON.parse(await fs.readFile(opencodeJsonPath, 'utf8'));
1385
+ }
1386
+ } catch {}
1387
+
1388
+ if (!config.mcp) config.mcp = {};
1389
+
1390
+ const serverConfig = MCP_CATALOG[server];
1391
+ config.mcp[server] = {
1392
+ type: serverConfig.type,
1393
+ ...(serverConfig.type === 'remote'
1394
+ ? { url: serverConfig.url, ...(serverConfig.oauth ? { oauth: serverConfig.oauth } : {}) }
1395
+ : { command: serverConfig.command }),
1396
+ enabled: true
1397
+ };
1398
+
1399
+ await fs.writeFile(opencodeJsonPath, JSON.stringify(config, null, 2) + '\n');
1400
+ spinner.succeed(chalk.green(`Added ${server} to opencode.json`));
1401
+
1402
+ if (serverConfig.requires_env) {
1403
+ console.log(chalk.yellow(`\n⚠️ Set environment variables:`));
1404
+ for (const env of serverConfig.requires_env) {
1405
+ console.log(chalk.cyan(` export ${env}="..."`));
1406
+ }
1407
+ }
1408
+ if (serverConfig.oauth) {
1409
+ console.log(chalk.yellow(`\n⚠️ OAuth required. Run:`));
1410
+ console.log(chalk.cyan(` opencode mcp auth ${server}`));
1411
+ }
1412
+
1413
+ } else if (action === 'remove') {
1414
+ if (!server) {
1415
+ console.log(chalk.red('Usage: mcp remove <server-id>'));
1416
+ process.exit(1);
1417
+ }
1418
+
1419
+ if (!await fs.pathExists(opencodeJsonPath)) {
1420
+ console.log(chalk.yellow('No opencode.json found'));
1421
+ return;
1422
+ }
1423
+
1424
+ const spinner = ora(`Removing ${server}...`).start();
1425
+
1426
+ const config = JSON.parse(await fs.readFile(opencodeJsonPath, 'utf8'));
1427
+ if (config.mcp && config.mcp[server]) {
1428
+ delete config.mcp[server];
1429
+ await fs.writeFile(opencodeJsonPath, JSON.stringify(config, null, 2) + '\n');
1430
+ spinner.succeed(chalk.green(`Removed ${server} from opencode.json`));
1431
+ } else {
1432
+ spinner.info(chalk.yellow(`${server} not found in opencode.json`));
1433
+ }
1434
+
1435
+ } else if (action === 'install') {
1436
+ // Interactive selection
1437
+ const installed = {};
1438
+ try {
1439
+ if (await fs.pathExists(opencodeJsonPath)) {
1440
+ const config = JSON.parse(await fs.readFile(opencodeJsonPath, 'utf8'));
1441
+ Object.assign(installed, config.mcp || {});
1442
+ }
1443
+ } catch {}
1444
+
1445
+ const choices = Object.entries(MCP_CATALOG).map(([id, info]) => ({
1446
+ name: `${id} - ${info.description}${info.recommended ? ' (recommended)' : ''}`,
1447
+ value: id,
1448
+ checked: installed[id] || info.recommended
1449
+ }));
1450
+
1451
+ const { servers } = await inquirer.prompt([{
1452
+ type: 'checkbox',
1453
+ name: 'servers',
1454
+ message: 'Select MCP servers:',
1455
+ choices
1456
+ }]);
1457
+
1458
+ // Read or create opencode.json
1459
+ let config = { "$schema": "https://opencode.ai/config.json" };
1460
+ try {
1461
+ if (await fs.pathExists(opencodeJsonPath)) {
1462
+ config = JSON.parse(await fs.readFile(opencodeJsonPath, 'utf8'));
1463
+ }
1464
+ } catch {}
1465
+
1466
+ config.mcp = {};
1467
+ for (const id of servers) {
1468
+ const serverConfig = MCP_CATALOG[id];
1469
+ config.mcp[id] = {
1470
+ type: serverConfig.type,
1471
+ ...(serverConfig.type === 'remote'
1472
+ ? { url: serverConfig.url, ...(serverConfig.oauth ? { oauth: serverConfig.oauth } : {}) }
1473
+ : { command: serverConfig.command }),
1474
+ enabled: true
1475
+ };
1476
+ }
1477
+
1478
+ await fs.writeFile(opencodeJsonPath, JSON.stringify(config, null, 2) + '\n');
1479
+ console.log(chalk.green(`\n✅ Updated opencode.json with ${servers.length} MCP servers`));
1480
+
1481
+ } else {
1482
+ console.log(chalk.red(`Unknown action: ${action}`));
1483
+ console.log('Available: list, add <id>, remove <id>, install');
1484
+ }
1485
+ });
1486
+
1238
1487
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@comfanion/workflow",
3
- "version": "4.36.29",
3
+ "version": "4.36.30",
4
4
  "description": "Initialize OpenCode Workflow system for AI-assisted development with semantic code search",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "4.36.29",
3
- "buildDate": "2026-01-24T20:54:34.023Z",
2
+ "version": "4.36.30",
3
+ "buildDate": "2026-01-24T20:58:37.569Z",
4
4
  "files": [
5
5
  "config.yaml",
6
6
  "FLOW.yaml",
@@ -6,15 +6,14 @@
6
6
  #
7
7
  # Usage:
8
8
  # npx @comfanion/workflow mcp list # Show available MCP servers
9
- # npx @comfanion/workflow mcp enable # Interactive selection
10
- # npx @comfanion/workflow mcp add <id> # Add specific MCP
9
+ # npx @comfanion/workflow mcp install # Install selected to opencode.json
11
10
  #
12
- # Version: 1.0.0
11
+ # Version: 1.1.0
13
12
  # Last updated: 2026-01-24
14
13
 
15
14
  servers:
16
15
  # ==========================================================================
17
- # DOCUMENTATION & RESEARCH
16
+ # DOCUMENTATION & RESEARCH (Remote MCP)
18
17
  # ==========================================================================
19
18
 
20
19
  context7:
@@ -22,13 +21,35 @@ servers:
22
21
  description: "Library documentation for npm, Go, Python packages"
23
22
  category: documentation
24
23
  recommended: true
25
- config:
26
- command: npx
27
- args: ["-y", "@anthropic/mcp-context7"]
24
+ type: remote
25
+ url: "https://mcp.context7.com/mcp"
28
26
  tags: [docs, npm, go, python, research]
29
27
 
28
+ grep:
29
+ name: "Grep by Vercel"
30
+ description: "Search code examples from GitHub"
31
+ category: documentation
32
+ recommended: false
33
+ type: remote
34
+ url: "https://mcp.grep.app"
35
+ tags: [github, code-search, examples]
36
+
37
+ # ==========================================================================
38
+ # INTEGRATIONS (Remote MCP with OAuth)
39
+ # ==========================================================================
40
+
41
+ sentry:
42
+ name: "Sentry"
43
+ description: "Query Sentry issues, projects, and error data"
44
+ category: integrations
45
+ recommended: false
46
+ type: remote
47
+ url: "https://mcp.sentry.dev/mcp"
48
+ oauth: true
49
+ tags: [errors, monitoring, debugging]
50
+
30
51
  # ==========================================================================
31
- # THINKING & REASONING
52
+ # LOCAL MCP SERVERS
32
53
  # ==========================================================================
33
54
 
34
55
  sequential-thinking:
@@ -36,73 +57,37 @@ servers:
36
57
  description: "Enhanced reasoning for complex multi-step problems"
37
58
  category: thinking
38
59
  recommended: true
39
- config:
40
- command: npx
41
- args: ["-y", "@anthropic/mcp-sequential-thinking"]
60
+ type: local
61
+ command: ["npx", "-y", "@anthropic/mcp-sequential-thinking"]
42
62
  tags: [reasoning, planning, complex-tasks]
43
63
 
44
- # ==========================================================================
45
- # BROWSER & UI
46
- # ==========================================================================
47
-
48
64
  playwright:
49
65
  name: "Playwright"
50
66
  description: "Browser automation, testing, and web scraping"
51
67
  category: browser
52
68
  recommended: false
53
- config:
54
- command: npx
55
- args: ["-y", "@anthropic/mcp-playwright"]
69
+ type: local
70
+ command: ["npx", "-y", "@anthropic/mcp-playwright"]
56
71
  tags: [browser, testing, automation, scraping]
57
72
 
58
- chrome-devtools:
59
- name: "Chrome DevTools"
60
- description: "Chrome debugging, performance analysis, DOM inspection"
61
- category: browser
62
- recommended: false
63
- config:
64
- command: npx
65
- args: ["-y", "chrome-devtools-mcp@latest"]
66
- tags: [chrome, debugging, devtools]
67
-
68
73
  puppeteer:
69
74
  name: "Puppeteer"
70
75
  description: "Headless Chrome automation"
71
76
  category: browser
72
77
  recommended: false
73
- config:
74
- command: npx
75
- args: ["-y", "@anthropic/mcp-puppeteer"]
78
+ type: local
79
+ command: ["npx", "-y", "@anthropic/mcp-puppeteer"]
76
80
  tags: [chrome, headless, automation]
77
81
 
78
- # ==========================================================================
79
- # INTEGRATIONS
80
- # ==========================================================================
81
-
82
- atlassian:
83
- name: "Atlassian (Jira/Confluence)"
84
- description: "Jira issues, Confluence pages integration"
85
- category: integrations
86
- recommended: false
87
- requires_env:
88
- - ATLASSIAN_EMAIL
89
- - ATLASSIAN_API_TOKEN
90
- - ATLASSIAN_URL
91
- config:
92
- command: npx
93
- args: ["-y", "@anthropic/mcp-atlassian"]
94
- tags: [jira, confluence, tickets, docs]
95
-
96
82
  github:
97
83
  name: "GitHub"
98
84
  description: "GitHub repos, issues, PRs, actions"
99
85
  category: integrations
100
86
  recommended: false
87
+ type: local
88
+ command: ["npx", "-y", "@anthropic/mcp-github"]
101
89
  requires_env:
102
90
  - GITHUB_TOKEN
103
- config:
104
- command: npx
105
- args: ["-y", "@anthropic/mcp-github"]
106
91
  tags: [github, git, issues, prs]
107
92
 
108
93
  gitlab:
@@ -110,11 +95,10 @@ servers:
110
95
  description: "GitLab repos, issues, MRs, pipelines"
111
96
  category: integrations
112
97
  recommended: false
98
+ type: local
99
+ command: ["npx", "-y", "@anthropic/mcp-gitlab"]
113
100
  requires_env:
114
101
  - GITLAB_TOKEN
115
- config:
116
- command: npx
117
- args: ["-y", "@anthropic/mcp-gitlab"]
118
102
  tags: [gitlab, git, issues, mrs]
119
103
 
120
104
  slack:
@@ -122,27 +106,21 @@ servers:
122
106
  description: "Slack messages, channels, search"
123
107
  category: integrations
124
108
  recommended: false
109
+ type: local
110
+ command: ["npx", "-y", "@anthropic/mcp-slack"]
125
111
  requires_env:
126
112
  - SLACK_TOKEN
127
- config:
128
- command: npx
129
- args: ["-y", "@anthropic/mcp-slack"]
130
113
  tags: [slack, messaging, communication]
131
114
 
132
- # ==========================================================================
133
- # DATA & STORAGE
134
- # ==========================================================================
135
-
136
115
  postgres:
137
116
  name: "PostgreSQL"
138
117
  description: "Query PostgreSQL databases"
139
118
  category: database
140
119
  recommended: false
120
+ type: local
121
+ command: ["npx", "-y", "@anthropic/mcp-postgres"]
141
122
  requires_env:
142
123
  - POSTGRES_CONNECTION_STRING
143
- config:
144
- command: npx
145
- args: ["-y", "@anthropic/mcp-postgres"]
146
124
  tags: [database, sql, postgres]
147
125
 
148
126
  sqlite:
@@ -150,9 +128,8 @@ servers:
150
128
  description: "Query SQLite databases"
151
129
  category: database
152
130
  recommended: false
153
- config:
154
- command: npx
155
- args: ["-y", "@anthropic/mcp-sqlite"]
131
+ type: local
132
+ command: ["npx", "-y", "@anthropic/mcp-sqlite"]
156
133
  tags: [database, sql, sqlite]
157
134
 
158
135
  redis:
@@ -160,51 +137,30 @@ servers:
160
137
  description: "Redis key-value operations"
161
138
  category: database
162
139
  recommended: false
140
+ type: local
141
+ command: ["npx", "-y", "@anthropic/mcp-redis"]
163
142
  requires_env:
164
143
  - REDIS_URL
165
- config:
166
- command: npx
167
- args: ["-y", "@anthropic/mcp-redis"]
168
144
  tags: [database, cache, redis]
169
145
 
170
- # ==========================================================================
171
- # FILE & SYSTEM
172
- # ==========================================================================
173
-
174
146
  filesystem:
175
147
  name: "Filesystem"
176
148
  description: "Advanced file operations (usually built-in)"
177
149
  category: system
178
150
  recommended: false
179
- config:
180
- command: npx
181
- args: ["-y", "@anthropic/mcp-filesystem"]
151
+ type: local
152
+ command: ["npx", "-y", "@anthropic/mcp-filesystem"]
182
153
  tags: [files, filesystem]
183
154
 
184
- # ==========================================================================
185
- # API & WEB
186
- # ==========================================================================
187
-
188
155
  fetch:
189
156
  name: "Fetch"
190
157
  description: "HTTP requests to external APIs (usually built-in)"
191
158
  category: api
192
159
  recommended: false
193
- config:
194
- command: npx
195
- args: ["-y", "@anthropic/mcp-fetch"]
160
+ type: local
161
+ command: ["npx", "-y", "@anthropic/mcp-fetch"]
196
162
  tags: [http, api, fetch]
197
163
 
198
- openapi:
199
- name: "OpenAPI"
200
- description: "Interact with APIs via OpenAPI specs"
201
- category: api
202
- recommended: false
203
- config:
204
- command: npx
205
- args: ["-y", "@anthropic/mcp-openapi"]
206
- tags: [api, openapi, swagger]
207
-
208
164
  # Categories for UI grouping
209
165
  categories:
210
166
  documentation: