@meldocio/mcp-stdio-proxy 1.0.14 → 1.0.16
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 +8 -7
- package/bin/cli.js +569 -11
- package/bin/meldoc-mcp-proxy.js +8 -4
- package/lib/workspace.js +7 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -292,10 +292,12 @@ If you have multiple workspaces in Meldoc, you need to specify which one to use.
|
|
|
292
292
|
The system selects a workspace in this order:
|
|
293
293
|
|
|
294
294
|
1. **Specified in request** - if you explicitly specified `workspaceAlias` or `workspaceId`
|
|
295
|
-
2. **Project file** - if there's a
|
|
295
|
+
2. **Project file** - if there's a `meldoc.config.yml` file in the project folder (or git repository directory)
|
|
296
296
|
3. **Global setting** - if you set a default workspace
|
|
297
297
|
4. **Automatically** - if you only have one workspace, it will be selected automatically
|
|
298
298
|
|
|
299
|
+
**Note:** When MCP is used in a git project or directory (e.g., Claude Desktop terminal or any other LLM), the workspace is automatically taken from the `meldoc.config.yml` configuration file if it exists.
|
|
300
|
+
|
|
299
301
|
### Setting default workspace
|
|
300
302
|
|
|
301
303
|
If you have multiple workspaces, set one as default:
|
|
@@ -308,14 +310,13 @@ After this, Claude will automatically use this workspace.
|
|
|
308
310
|
|
|
309
311
|
### Workspace for a specific project
|
|
310
312
|
|
|
311
|
-
If you want different projects to use different workspaces, create a
|
|
313
|
+
If you want different projects to use different workspaces, create a `meldoc.config.yml` file in the project root:
|
|
312
314
|
|
|
313
315
|
```yaml
|
|
314
|
-
|
|
315
|
-
workspace: workspace-name-for-this-project
|
|
316
|
+
workspaceAlias: workspace-name-for-this-project
|
|
316
317
|
```
|
|
317
318
|
|
|
318
|
-
Now when working from this folder, the specified workspace will be used.
|
|
319
|
+
Now when working from this folder (or when MCP is used in a git repository), the specified workspace will be used.
|
|
319
320
|
|
|
320
321
|
## What can Claude do with your documentation?
|
|
321
322
|
|
|
@@ -489,9 +490,9 @@ Global settings:
|
|
|
489
490
|
|
|
490
491
|
Can be edited manually or through CLI commands.
|
|
491
492
|
|
|
492
|
-
###
|
|
493
|
+
### `meldoc.config.yml` (optional)
|
|
493
494
|
|
|
494
|
-
Project-specific settings. Create in the project root if you need to use a different workspace for this project.
|
|
495
|
+
Project-specific settings. Create in the project root if you need to use a different workspace for this project. When MCP is used in a git project or directory, the workspace is automatically taken from this configuration file if it exists.
|
|
495
496
|
|
|
496
497
|
## Requirements
|
|
497
498
|
|
package/bin/cli.js
CHANGED
|
@@ -219,7 +219,54 @@ function getClaudeDesktopConfigPath() {
|
|
|
219
219
|
}
|
|
220
220
|
|
|
221
221
|
/**
|
|
222
|
-
* Get
|
|
222
|
+
* Get Cursor config file path (project-specific)
|
|
223
|
+
*/
|
|
224
|
+
function getCursorProjectConfigPath() {
|
|
225
|
+
const cwd = process.cwd();
|
|
226
|
+
return path.join(cwd, '.cursor', 'mcp.json');
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Get Cursor global config file path
|
|
231
|
+
*/
|
|
232
|
+
function getCursorGlobalConfigPath() {
|
|
233
|
+
const homeDir = os.homedir();
|
|
234
|
+
return path.join(homeDir, '.cursor', 'mcp.json');
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Get local mcp.json path (in current directory)
|
|
239
|
+
*/
|
|
240
|
+
function getLocalMcpJsonPath() {
|
|
241
|
+
return path.join(process.cwd(), 'mcp.json');
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Get Claude Code project config path (.mcp.json)
|
|
246
|
+
*/
|
|
247
|
+
function getClaudeCodeProjectConfigPath() {
|
|
248
|
+
return path.join(process.cwd(), '.mcp.json');
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Get Claude Code user config path (~/.claude.json)
|
|
253
|
+
*/
|
|
254
|
+
function getClaudeCodeUserConfigPath() {
|
|
255
|
+
return path.join(os.homedir(), '.claude.json');
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Get Claude Code local config path (~/.claude.json in project path)
|
|
260
|
+
* Note: Local scope uses ~/.claude.json but stores project-specific paths
|
|
261
|
+
*/
|
|
262
|
+
function getClaudeCodeLocalConfigPath() {
|
|
263
|
+
// For local scope, Claude Code uses ~/.claude.json with project-specific paths
|
|
264
|
+
// This is the same file as user scope, but with different path context
|
|
265
|
+
return path.join(os.homedir(), '.claude.json');
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Get expected Meldoc MCP configuration for Claude Desktop
|
|
223
270
|
*/
|
|
224
271
|
function getExpectedMeldocConfig() {
|
|
225
272
|
return {
|
|
@@ -228,6 +275,27 @@ function getExpectedMeldocConfig() {
|
|
|
228
275
|
};
|
|
229
276
|
}
|
|
230
277
|
|
|
278
|
+
/**
|
|
279
|
+
* Get expected Meldoc MCP configuration for Cursor (stdio)
|
|
280
|
+
*/
|
|
281
|
+
function getExpectedMeldocConfigForCursor() {
|
|
282
|
+
return {
|
|
283
|
+
command: 'npx',
|
|
284
|
+
args: ['-y', '@meldocio/mcp-stdio-proxy@latest']
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Get expected Meldoc MCP configuration for Claude Code (stdio)
|
|
290
|
+
*/
|
|
291
|
+
function getExpectedMeldocConfigForClaudeCode() {
|
|
292
|
+
return {
|
|
293
|
+
type: 'stdio',
|
|
294
|
+
command: 'npx',
|
|
295
|
+
args: ['-y', '@meldocio/mcp-stdio-proxy@latest']
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
|
|
231
299
|
/**
|
|
232
300
|
* Check if two configurations are equal (deep comparison)
|
|
233
301
|
*/
|
|
@@ -240,9 +308,27 @@ function configsEqual(config1, config2) {
|
|
|
240
308
|
}
|
|
241
309
|
|
|
242
310
|
/**
|
|
243
|
-
*
|
|
311
|
+
* Merge MCP server configurations (preserve existing, add new)
|
|
312
|
+
*/
|
|
313
|
+
function mergeMcpServers(existing, newServer) {
|
|
314
|
+
const merged = { ...existing };
|
|
315
|
+
if (!merged.meldoc) {
|
|
316
|
+
merged.meldoc = newServer;
|
|
317
|
+
} else {
|
|
318
|
+
// Check if it's the same config
|
|
319
|
+
if (configsEqual(merged.meldoc, newServer)) {
|
|
320
|
+
return { merged, changed: false };
|
|
321
|
+
}
|
|
322
|
+
// Update if different
|
|
323
|
+
merged.meldoc = newServer;
|
|
324
|
+
}
|
|
325
|
+
return { merged, changed: true };
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Install for Claude Desktop
|
|
244
330
|
*/
|
|
245
|
-
function
|
|
331
|
+
function installClaudeDesktop() {
|
|
246
332
|
try {
|
|
247
333
|
logger.section('🚀 Installing Meldoc MCP for Claude Desktop');
|
|
248
334
|
console.log();
|
|
@@ -370,6 +456,447 @@ function handleInstall() {
|
|
|
370
456
|
}
|
|
371
457
|
}
|
|
372
458
|
|
|
459
|
+
/**
|
|
460
|
+
* Install for Cursor (project or global)
|
|
461
|
+
*/
|
|
462
|
+
function installCursor(isGlobal = false) {
|
|
463
|
+
try {
|
|
464
|
+
const configPath = isGlobal ? getCursorGlobalConfigPath() : getCursorProjectConfigPath();
|
|
465
|
+
const configDir = path.dirname(configPath);
|
|
466
|
+
const expectedConfig = getExpectedMeldocConfigForCursor();
|
|
467
|
+
|
|
468
|
+
logger.section(`🚀 Installing Meldoc MCP for Cursor (${isGlobal ? 'global' : 'project'})`);
|
|
469
|
+
console.log();
|
|
470
|
+
|
|
471
|
+
logger.info(`Config file location: ${logger.highlight(configPath)}`);
|
|
472
|
+
console.log();
|
|
473
|
+
|
|
474
|
+
// Read existing config or create new one
|
|
475
|
+
let config = {};
|
|
476
|
+
let configExists = false;
|
|
477
|
+
|
|
478
|
+
if (fs.existsSync(configPath)) {
|
|
479
|
+
try {
|
|
480
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
481
|
+
config = JSON.parse(content);
|
|
482
|
+
configExists = true;
|
|
483
|
+
logger.info('Found existing Cursor MCP configuration');
|
|
484
|
+
} catch (error) {
|
|
485
|
+
logger.warn(`Failed to parse existing config: ${error.message}`);
|
|
486
|
+
logger.info('Will create a new configuration file');
|
|
487
|
+
}
|
|
488
|
+
} else {
|
|
489
|
+
logger.info('Configuration file does not exist, will create it');
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// Ensure mcpServers object exists
|
|
493
|
+
if (!config.mcpServers) {
|
|
494
|
+
config.mcpServers = {};
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// Check if meldoc is already configured
|
|
498
|
+
if (config.mcpServers.meldoc) {
|
|
499
|
+
const existingConfig = config.mcpServers.meldoc;
|
|
500
|
+
const isEqual = configsEqual(existingConfig, expectedConfig);
|
|
501
|
+
|
|
502
|
+
if (isEqual) {
|
|
503
|
+
logger.success('Meldoc MCP is already configured correctly!');
|
|
504
|
+
console.log();
|
|
505
|
+
logger.info('Current configuration:');
|
|
506
|
+
console.log(' ' + logger.highlight(JSON.stringify(existingConfig, null, 2)));
|
|
507
|
+
console.log();
|
|
508
|
+
logger.info('No changes needed. Next steps:');
|
|
509
|
+
console.log(' 1. Restart Cursor (if you haven\'t already)');
|
|
510
|
+
console.log(' 2. Run: ' + logger.highlight('npx @meldocio/mcp-stdio-proxy auth login'));
|
|
511
|
+
console.log();
|
|
512
|
+
process.exit(0);
|
|
513
|
+
} else {
|
|
514
|
+
logger.warn('Meldoc MCP is already configured, but with different settings');
|
|
515
|
+
console.log();
|
|
516
|
+
logger.info('Current configuration:');
|
|
517
|
+
console.log(' ' + logger.highlight(JSON.stringify(existingConfig, null, 2)));
|
|
518
|
+
console.log();
|
|
519
|
+
logger.info('Expected configuration:');
|
|
520
|
+
console.log(' ' + logger.highlight(JSON.stringify(expectedConfig, null, 2)));
|
|
521
|
+
console.log();
|
|
522
|
+
logger.info('To update the configuration, run:');
|
|
523
|
+
console.log(' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy install cursor'));
|
|
524
|
+
console.log();
|
|
525
|
+
process.exit(0);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// Add meldoc configuration
|
|
530
|
+
config.mcpServers.meldoc = expectedConfig;
|
|
531
|
+
|
|
532
|
+
// Create directory if it doesn't exist
|
|
533
|
+
if (!fs.existsSync(configDir)) {
|
|
534
|
+
logger.info(`Creating directory: ${configDir}`);
|
|
535
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
// Write config file
|
|
539
|
+
const configContent = JSON.stringify(config, null, 2);
|
|
540
|
+
fs.writeFileSync(configPath, configContent, 'utf8');
|
|
541
|
+
|
|
542
|
+
logger.success('Configuration added successfully!');
|
|
543
|
+
console.log();
|
|
544
|
+
|
|
545
|
+
// Show what was added
|
|
546
|
+
logger.info('Added MCP server configuration:');
|
|
547
|
+
console.log(' ' + logger.highlight(JSON.stringify(config.mcpServers.meldoc, null, 2)));
|
|
548
|
+
console.log();
|
|
549
|
+
|
|
550
|
+
// Count other MCP servers
|
|
551
|
+
const otherServers = Object.keys(config.mcpServers).filter(key => key !== 'meldoc');
|
|
552
|
+
if (otherServers.length > 0) {
|
|
553
|
+
logger.info(`Found ${otherServers.length} other MCP server(s): ${otherServers.join(', ')}`);
|
|
554
|
+
console.log();
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// Next steps
|
|
558
|
+
logger.section('✅ Installation Complete!');
|
|
559
|
+
console.log();
|
|
560
|
+
logger.info('Next steps:');
|
|
561
|
+
console.log();
|
|
562
|
+
console.log(' 1. ' + logger.label('Restart Cursor'));
|
|
563
|
+
console.log(' Completely close and reopen Cursor for changes to take effect.');
|
|
564
|
+
console.log();
|
|
565
|
+
console.log(' 2. ' + logger.label('Authenticate with Meldoc'));
|
|
566
|
+
console.log(' Run: ' + logger.highlight('npx @meldocio/mcp-stdio-proxy auth login'));
|
|
567
|
+
console.log();
|
|
568
|
+
console.log(' 3. ' + logger.label('Start using Cursor with Meldoc!'));
|
|
569
|
+
console.log(' Ask Cursor to read, search, or update your documentation.');
|
|
570
|
+
console.log();
|
|
571
|
+
|
|
572
|
+
process.exit(0);
|
|
573
|
+
} catch (error) {
|
|
574
|
+
const configPath = isGlobal ? getCursorGlobalConfigPath() : getCursorProjectConfigPath();
|
|
575
|
+
logger.error(`Installation failed: ${error.message}`);
|
|
576
|
+
console.log();
|
|
577
|
+
logger.info('You can manually configure Cursor by:');
|
|
578
|
+
console.log(' 1. Opening the config file: ' + logger.highlight(configPath));
|
|
579
|
+
console.log(' 2. Adding this configuration:');
|
|
580
|
+
console.log(' ' + logger.highlight(JSON.stringify({
|
|
581
|
+
mcpServers: {
|
|
582
|
+
meldoc: getExpectedMeldocConfigForCursor()
|
|
583
|
+
}
|
|
584
|
+
}, null, 2)));
|
|
585
|
+
console.log();
|
|
586
|
+
process.exit(1);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
/**
|
|
591
|
+
* Install local mcp.json file
|
|
592
|
+
*/
|
|
593
|
+
function installLocal() {
|
|
594
|
+
try {
|
|
595
|
+
logger.section('🚀 Installing Meldoc MCP (Local mcp.json)');
|
|
596
|
+
console.log();
|
|
597
|
+
|
|
598
|
+
const configPath = getLocalMcpJsonPath();
|
|
599
|
+
const expectedConfig = getExpectedMeldocConfig();
|
|
600
|
+
|
|
601
|
+
logger.info(`Config file location: ${logger.highlight(configPath)}`);
|
|
602
|
+
console.log();
|
|
603
|
+
|
|
604
|
+
// Read existing config or create new one
|
|
605
|
+
let config = {};
|
|
606
|
+
let configExists = false;
|
|
607
|
+
|
|
608
|
+
if (fs.existsSync(configPath)) {
|
|
609
|
+
try {
|
|
610
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
611
|
+
config = JSON.parse(content);
|
|
612
|
+
configExists = true;
|
|
613
|
+
logger.info('Found existing mcp.json configuration');
|
|
614
|
+
} catch (error) {
|
|
615
|
+
logger.warn(`Failed to parse existing config: ${error.message}`);
|
|
616
|
+
logger.info('Will create a new configuration file');
|
|
617
|
+
}
|
|
618
|
+
} else {
|
|
619
|
+
logger.info('Configuration file does not exist, will create it');
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
// Ensure mcpServers object exists
|
|
623
|
+
if (!config.mcpServers) {
|
|
624
|
+
config.mcpServers = {};
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
// Check if meldoc is already configured
|
|
628
|
+
if (config.mcpServers.meldoc) {
|
|
629
|
+
const existingConfig = config.mcpServers.meldoc;
|
|
630
|
+
const isEqual = configsEqual(existingConfig, expectedConfig);
|
|
631
|
+
|
|
632
|
+
if (isEqual) {
|
|
633
|
+
logger.success('Meldoc MCP is already configured correctly!');
|
|
634
|
+
console.log();
|
|
635
|
+
logger.info('Current configuration:');
|
|
636
|
+
console.log(' ' + logger.highlight(JSON.stringify(existingConfig, null, 2)));
|
|
637
|
+
console.log();
|
|
638
|
+
logger.info('No changes needed. Next steps:');
|
|
639
|
+
console.log(' 1. Restart your MCP client (if needed)');
|
|
640
|
+
console.log(' 2. Run: ' + logger.highlight('npx @meldocio/mcp-stdio-proxy auth login'));
|
|
641
|
+
console.log();
|
|
642
|
+
process.exit(0);
|
|
643
|
+
} else {
|
|
644
|
+
logger.warn('Meldoc MCP is already configured, but with different settings');
|
|
645
|
+
console.log();
|
|
646
|
+
logger.info('Current configuration:');
|
|
647
|
+
console.log(' ' + logger.highlight(JSON.stringify(existingConfig, null, 2)));
|
|
648
|
+
console.log();
|
|
649
|
+
logger.info('Expected configuration:');
|
|
650
|
+
console.log(' ' + logger.highlight(JSON.stringify(expectedConfig, null, 2)));
|
|
651
|
+
console.log();
|
|
652
|
+
logger.info('Updating configuration...');
|
|
653
|
+
console.log();
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
// Add/update meldoc configuration
|
|
658
|
+
config.mcpServers.meldoc = expectedConfig;
|
|
659
|
+
|
|
660
|
+
// Write config file
|
|
661
|
+
const configContent = JSON.stringify(config, null, 2);
|
|
662
|
+
fs.writeFileSync(configPath, configContent, 'utf8');
|
|
663
|
+
|
|
664
|
+
logger.success('Configuration ' + (configExists && config.mcpServers.meldoc ? 'updated' : 'added') + ' successfully!');
|
|
665
|
+
console.log();
|
|
666
|
+
|
|
667
|
+
// Show what was added
|
|
668
|
+
logger.info('MCP server configuration:');
|
|
669
|
+
console.log(' ' + logger.highlight(JSON.stringify(config.mcpServers.meldoc, null, 2)));
|
|
670
|
+
console.log();
|
|
671
|
+
|
|
672
|
+
// Count other MCP servers
|
|
673
|
+
const otherServers = Object.keys(config.mcpServers).filter(key => key !== 'meldoc');
|
|
674
|
+
if (otherServers.length > 0) {
|
|
675
|
+
logger.info(`Found ${otherServers.length} other MCP server(s): ${otherServers.join(', ')}`);
|
|
676
|
+
console.log();
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
// Next steps
|
|
680
|
+
logger.section('✅ Installation Complete!');
|
|
681
|
+
console.log();
|
|
682
|
+
logger.info('Next steps:');
|
|
683
|
+
console.log();
|
|
684
|
+
console.log(' 1. ' + logger.label('Use this mcp.json with your MCP client'));
|
|
685
|
+
console.log(' This file can be imported or referenced by MCP clients that support JSON configuration.');
|
|
686
|
+
console.log();
|
|
687
|
+
console.log(' 2. ' + logger.label('Authenticate with Meldoc'));
|
|
688
|
+
console.log(' Run: ' + logger.highlight('npx @meldocio/mcp-stdio-proxy auth login'));
|
|
689
|
+
console.log();
|
|
690
|
+
|
|
691
|
+
process.exit(0);
|
|
692
|
+
} catch (error) {
|
|
693
|
+
logger.error(`Installation failed: ${error.message}`);
|
|
694
|
+
console.log();
|
|
695
|
+
logger.info('You can manually create mcp.json with this configuration:');
|
|
696
|
+
console.log(' ' + logger.highlight(JSON.stringify({
|
|
697
|
+
mcpServers: {
|
|
698
|
+
meldoc: getExpectedMeldocConfig()
|
|
699
|
+
}
|
|
700
|
+
}, null, 2)));
|
|
701
|
+
console.log();
|
|
702
|
+
process.exit(1);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
/**
|
|
707
|
+
* Install for Claude Code (project, user, or local scope)
|
|
708
|
+
*/
|
|
709
|
+
function installClaudeCode(scope = 'project') {
|
|
710
|
+
try {
|
|
711
|
+
let configPath;
|
|
712
|
+
if (scope === 'project') {
|
|
713
|
+
configPath = getClaudeCodeProjectConfigPath();
|
|
714
|
+
} else if (scope === 'user') {
|
|
715
|
+
configPath = getClaudeCodeUserConfigPath();
|
|
716
|
+
} else {
|
|
717
|
+
// local scope
|
|
718
|
+
configPath = getClaudeCodeLocalConfigPath();
|
|
719
|
+
}
|
|
720
|
+
const configDir = path.dirname(configPath);
|
|
721
|
+
const expectedConfig = getExpectedMeldocConfigForClaudeCode();
|
|
722
|
+
|
|
723
|
+
logger.section(`🚀 Installing Meldoc MCP for Claude Code (${scope} scope)`);
|
|
724
|
+
console.log();
|
|
725
|
+
|
|
726
|
+
logger.info(`Config file location: ${logger.highlight(configPath)}`);
|
|
727
|
+
console.log();
|
|
728
|
+
|
|
729
|
+
// Read existing config or create new one
|
|
730
|
+
let config = {};
|
|
731
|
+
let configExists = false;
|
|
732
|
+
|
|
733
|
+
if (fs.existsSync(configPath)) {
|
|
734
|
+
try {
|
|
735
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
736
|
+
config = JSON.parse(content);
|
|
737
|
+
configExists = true;
|
|
738
|
+
logger.info('Found existing Claude Code MCP configuration');
|
|
739
|
+
} catch (error) {
|
|
740
|
+
logger.warn(`Failed to parse existing config: ${error.message}`);
|
|
741
|
+
logger.info('Will create a new configuration file');
|
|
742
|
+
}
|
|
743
|
+
} else {
|
|
744
|
+
logger.info('Configuration file does not exist, will create it');
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
// Ensure mcpServers object exists
|
|
748
|
+
if (!config.mcpServers) {
|
|
749
|
+
config.mcpServers = {};
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
// Check if meldoc is already configured
|
|
753
|
+
if (config.mcpServers.meldoc) {
|
|
754
|
+
const existingConfig = config.mcpServers.meldoc;
|
|
755
|
+
// For Claude Code, compare type, command, and args
|
|
756
|
+
const isEqual = existingConfig.type === expectedConfig.type &&
|
|
757
|
+
existingConfig.command === expectedConfig.command &&
|
|
758
|
+
Array.isArray(existingConfig.args) &&
|
|
759
|
+
Array.isArray(expectedConfig.args) &&
|
|
760
|
+
existingConfig.args.length === expectedConfig.args.length &&
|
|
761
|
+
existingConfig.args.every((arg, i) => arg === expectedConfig.args[i]);
|
|
762
|
+
|
|
763
|
+
if (isEqual) {
|
|
764
|
+
logger.success('Meldoc MCP is already configured correctly!');
|
|
765
|
+
console.log();
|
|
766
|
+
logger.info('Current configuration:');
|
|
767
|
+
console.log(' ' + logger.highlight(JSON.stringify(existingConfig, null, 2)));
|
|
768
|
+
console.log();
|
|
769
|
+
logger.info('No changes needed. Next steps:');
|
|
770
|
+
console.log(' 1. Restart Claude Code (if you haven\'t already)');
|
|
771
|
+
console.log(' 2. Run: ' + logger.highlight('npx @meldocio/mcp-stdio-proxy auth login'));
|
|
772
|
+
console.log();
|
|
773
|
+
process.exit(0);
|
|
774
|
+
} else {
|
|
775
|
+
logger.warn('Meldoc MCP is already configured, but with different settings');
|
|
776
|
+
console.log();
|
|
777
|
+
logger.info('Current configuration:');
|
|
778
|
+
console.log(' ' + logger.highlight(JSON.stringify(existingConfig, null, 2)));
|
|
779
|
+
console.log();
|
|
780
|
+
logger.info('Expected configuration:');
|
|
781
|
+
console.log(' ' + logger.highlight(JSON.stringify(expectedConfig, null, 2)));
|
|
782
|
+
console.log();
|
|
783
|
+
logger.info('Updating configuration...');
|
|
784
|
+
console.log();
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
// Add/update meldoc configuration
|
|
789
|
+
config.mcpServers.meldoc = expectedConfig;
|
|
790
|
+
|
|
791
|
+
// Create directory if it doesn't exist (for user/local scope)
|
|
792
|
+
if (scope !== 'project' && !fs.existsSync(configDir)) {
|
|
793
|
+
logger.info(`Creating directory: ${configDir}`);
|
|
794
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
// Write config file
|
|
798
|
+
const configContent = JSON.stringify(config, null, 2);
|
|
799
|
+
fs.writeFileSync(configPath, configContent, 'utf8');
|
|
800
|
+
|
|
801
|
+
logger.success('Configuration ' + (configExists && config.mcpServers.meldoc ? 'updated' : 'added') + ' successfully!');
|
|
802
|
+
console.log();
|
|
803
|
+
|
|
804
|
+
// Show what was added
|
|
805
|
+
logger.info('MCP server configuration:');
|
|
806
|
+
console.log(' ' + logger.highlight(JSON.stringify(config.mcpServers.meldoc, null, 2)));
|
|
807
|
+
console.log();
|
|
808
|
+
|
|
809
|
+
// Count other MCP servers
|
|
810
|
+
const otherServers = Object.keys(config.mcpServers).filter(key => key !== 'meldoc');
|
|
811
|
+
if (otherServers.length > 0) {
|
|
812
|
+
logger.info(`Found ${otherServers.length} other MCP server(s): ${otherServers.join(', ')}`);
|
|
813
|
+
console.log();
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
// Next steps
|
|
817
|
+
logger.section('✅ Installation Complete!');
|
|
818
|
+
console.log();
|
|
819
|
+
logger.info('Next steps:');
|
|
820
|
+
console.log();
|
|
821
|
+
console.log(' 1. ' + logger.label('Restart Claude Code'));
|
|
822
|
+
console.log(' Completely close and reopen Claude Code for changes to take effect.');
|
|
823
|
+
console.log();
|
|
824
|
+
console.log(' 2. ' + logger.label('Authenticate with Meldoc'));
|
|
825
|
+
console.log(' Run: ' + logger.highlight('npx @meldocio/mcp-stdio-proxy auth login'));
|
|
826
|
+
console.log();
|
|
827
|
+
console.log(' 3. ' + logger.label('Start using Claude Code with Meldoc!'));
|
|
828
|
+
console.log(' Ask Claude Code to read, search, or update your documentation.');
|
|
829
|
+
console.log();
|
|
830
|
+
|
|
831
|
+
process.exit(0);
|
|
832
|
+
} catch (error) {
|
|
833
|
+
const configPath = scope === 'project' ? getClaudeCodeProjectConfigPath() : getClaudeCodeUserConfigPath();
|
|
834
|
+
logger.error(`Installation failed: ${error.message}`);
|
|
835
|
+
console.log();
|
|
836
|
+
logger.info('You can manually configure Claude Code by:');
|
|
837
|
+
console.log(' 1. Opening the config file: ' + logger.highlight(configPath));
|
|
838
|
+
console.log(' 2. Adding this configuration:');
|
|
839
|
+
console.log(' ' + logger.highlight(JSON.stringify({
|
|
840
|
+
mcpServers: {
|
|
841
|
+
meldoc: getExpectedMeldocConfigForClaudeCode()
|
|
842
|
+
}
|
|
843
|
+
}, null, 2)));
|
|
844
|
+
console.log();
|
|
845
|
+
logger.info('Or use the CLI command:');
|
|
846
|
+
console.log(' ' + logger.highlight(`claude mcp add --transport stdio meldoc -- npx -y @meldocio/mcp-stdio-proxy@latest --scope ${scope}`));
|
|
847
|
+
console.log();
|
|
848
|
+
process.exit(1);
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
/**
|
|
853
|
+
* Handle install command - automatically configure MCP client
|
|
854
|
+
*/
|
|
855
|
+
function handleInstall(consumer, isLocal) {
|
|
856
|
+
if (isLocal) {
|
|
857
|
+
installLocal();
|
|
858
|
+
return;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
const consumerLower = (consumer || 'claude-desktop').toLowerCase();
|
|
862
|
+
|
|
863
|
+
switch (consumerLower) {
|
|
864
|
+
case 'claude-desktop':
|
|
865
|
+
case 'claude':
|
|
866
|
+
installClaudeDesktop();
|
|
867
|
+
break;
|
|
868
|
+
case 'cursor':
|
|
869
|
+
installCursor(false); // Project-specific by default
|
|
870
|
+
break;
|
|
871
|
+
case 'cursor-global':
|
|
872
|
+
installCursor(true);
|
|
873
|
+
break;
|
|
874
|
+
case 'claude-code':
|
|
875
|
+
installClaudeCode('project'); // Project scope by default
|
|
876
|
+
break;
|
|
877
|
+
case 'claude-code-user':
|
|
878
|
+
installClaudeCode('user');
|
|
879
|
+
break;
|
|
880
|
+
case 'claude-code-local':
|
|
881
|
+
installClaudeCode('local');
|
|
882
|
+
break;
|
|
883
|
+
default:
|
|
884
|
+
logger.error(`Unknown consumer: ${consumer}`);
|
|
885
|
+
console.log();
|
|
886
|
+
logger.info('Supported consumers:');
|
|
887
|
+
console.log(' ' + logger.highlight('claude-desktop') + ' (or claude) - Claude Desktop');
|
|
888
|
+
console.log(' ' + logger.highlight('cursor') + ' - Cursor IDE (project-specific)');
|
|
889
|
+
console.log(' ' + logger.highlight('cursor-global') + ' - Cursor IDE (global)');
|
|
890
|
+
console.log(' ' + logger.highlight('claude-code') + ' - Claude Code (project scope)');
|
|
891
|
+
console.log(' ' + logger.highlight('claude-code-user') + ' - Claude Code (user scope)');
|
|
892
|
+
console.log(' ' + logger.highlight('claude-code-local') + ' - Claude Code (local scope)');
|
|
893
|
+
console.log();
|
|
894
|
+
logger.info('Or use ' + logger.highlight('--local') + ' flag to create local mcp.json');
|
|
895
|
+
console.log();
|
|
896
|
+
process.exit(1);
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
|
|
373
900
|
/**
|
|
374
901
|
* Handle uninstall command - remove Meldoc MCP configuration from Claude Desktop
|
|
375
902
|
*/
|
|
@@ -493,8 +1020,10 @@ function handleHelp() {
|
|
|
493
1020
|
console.log(' List all available workspaces');
|
|
494
1021
|
console.log();
|
|
495
1022
|
|
|
496
|
-
console.log(' ' + logger.highlight('install'));
|
|
497
|
-
console.log(' Automatically configure
|
|
1023
|
+
console.log(' ' + logger.highlight('install [consumer] [--local]'));
|
|
1024
|
+
console.log(' Automatically configure MCP client for Meldoc MCP');
|
|
1025
|
+
console.log(' Consumers: claude-desktop (default), cursor, cursor-global, claude-code');
|
|
1026
|
+
console.log(' Use --local flag to create local mcp.json file');
|
|
498
1027
|
console.log();
|
|
499
1028
|
|
|
500
1029
|
console.log(' ' + logger.highlight('uninstall'));
|
|
@@ -507,6 +1036,10 @@ function handleHelp() {
|
|
|
507
1036
|
|
|
508
1037
|
console.log(logger.label('Examples:'));
|
|
509
1038
|
console.log(' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy install'));
|
|
1039
|
+
console.log(' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy install claude-desktop'));
|
|
1040
|
+
console.log(' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy install cursor'));
|
|
1041
|
+
console.log(' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy install claude-code'));
|
|
1042
|
+
console.log(' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy install --local'));
|
|
510
1043
|
console.log(' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy uninstall'));
|
|
511
1044
|
console.log(' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy auth login'));
|
|
512
1045
|
console.log(' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy config set-workspace my-workspace'));
|
|
@@ -529,7 +1062,7 @@ function showUsageHints() {
|
|
|
529
1062
|
console.log(' ' + logger.highlight('config set-workspace') + ' - Set workspace alias');
|
|
530
1063
|
console.log(' ' + logger.highlight('config get-workspace') + ' - Get current workspace');
|
|
531
1064
|
console.log(' ' + logger.highlight('config list-workspaces') + ' - List workspaces');
|
|
532
|
-
console.log(' ' + logger.highlight('install') + '
|
|
1065
|
+
console.log(' ' + logger.highlight('install [consumer]') + ' - Configure MCP client');
|
|
533
1066
|
console.log(' ' + logger.highlight('uninstall') + ' - Remove configuration');
|
|
534
1067
|
console.log(' ' + logger.highlight('help') + ' - Show detailed help');
|
|
535
1068
|
console.log();
|
|
@@ -557,7 +1090,19 @@ async function main() {
|
|
|
557
1090
|
if (command === 'help' || command === '--help' || command === '-h') {
|
|
558
1091
|
handleHelp();
|
|
559
1092
|
} else if (command === 'install') {
|
|
560
|
-
|
|
1093
|
+
// Parse install arguments
|
|
1094
|
+
let consumer = null;
|
|
1095
|
+
let isLocal = false;
|
|
1096
|
+
|
|
1097
|
+
for (let i = 1; i < args.length; i++) {
|
|
1098
|
+
if (args[i] === '--local' || args[i] === '-l') {
|
|
1099
|
+
isLocal = true;
|
|
1100
|
+
} else if (!args[i].startsWith('--') && !args[i].startsWith('-')) {
|
|
1101
|
+
consumer = args[i];
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
handleInstall(consumer, isLocal);
|
|
561
1106
|
} else if (command === 'uninstall') {
|
|
562
1107
|
handleUninstall();
|
|
563
1108
|
} else if (command === 'auth') {
|
|
@@ -587,9 +1132,18 @@ async function main() {
|
|
|
587
1132
|
process.exit(1);
|
|
588
1133
|
}
|
|
589
1134
|
} else {
|
|
590
|
-
// Unknown command
|
|
591
|
-
|
|
592
|
-
|
|
1135
|
+
// Unknown command
|
|
1136
|
+
logger.error(`Unknown command: ${command}`);
|
|
1137
|
+
console.log('\n' + logger.label('Available commands:'));
|
|
1138
|
+
console.log(' ' + logger.highlight('install') + ' - Configure Claude Desktop');
|
|
1139
|
+
console.log(' ' + logger.highlight('uninstall') + ' - Remove configuration');
|
|
1140
|
+
console.log(' ' + logger.highlight('auth') + ' <cmd> - Authentication commands');
|
|
1141
|
+
console.log(' ' + logger.highlight('config') + ' <cmd> - Configuration commands');
|
|
1142
|
+
console.log(' ' + logger.highlight('help') + ' - Show help');
|
|
1143
|
+
console.log();
|
|
1144
|
+
console.log(logger.label('Run') + ' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy help') + ' ' + logger.label('for more information'));
|
|
1145
|
+
console.log();
|
|
1146
|
+
process.exit(1);
|
|
593
1147
|
}
|
|
594
1148
|
}
|
|
595
1149
|
|
|
@@ -608,5 +1162,9 @@ module.exports = {
|
|
|
608
1162
|
handleConfigGetWorkspace,
|
|
609
1163
|
handleConfigListWorkspaces,
|
|
610
1164
|
handleInstall,
|
|
611
|
-
handleUninstall
|
|
1165
|
+
handleUninstall,
|
|
1166
|
+
installClaudeDesktop,
|
|
1167
|
+
installCursor,
|
|
1168
|
+
installClaudeCode,
|
|
1169
|
+
installLocal
|
|
612
1170
|
};
|
package/bin/meldoc-mcp-proxy.js
CHANGED
|
@@ -9,11 +9,15 @@ const chalk = require('chalk');
|
|
|
9
9
|
|
|
10
10
|
// Check for CLI commands first
|
|
11
11
|
const args = process.argv.slice(2);
|
|
12
|
-
if (args.length > 0
|
|
12
|
+
if (args.length > 0) {
|
|
13
|
+
const command = args[0];
|
|
13
14
|
// Handle CLI commands - cli.js will handle and exit
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
if (command === 'auth' || command === 'config' || command === 'install' ||
|
|
16
|
+
command === 'uninstall' || command === 'help' || command === '--help' || command === '-h') {
|
|
17
|
+
require('./cli');
|
|
18
|
+
// Don't exit here - cli.js will handle process.exit() after async operations complete
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
17
21
|
}
|
|
18
22
|
|
|
19
23
|
// Get package info - try multiple paths for different installation scenarios
|
package/lib/workspace.js
CHANGED
|
@@ -4,16 +4,16 @@ const yaml = require('js-yaml');
|
|
|
4
4
|
const { getWorkspaceAlias: getConfigWorkspaceAlias } = require('./config');
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Find
|
|
7
|
+
* Find meldoc.config.yml file in current directory or parent directories
|
|
8
8
|
* @param {string} startDir - Starting directory
|
|
9
|
-
* @returns {string|null} Path to
|
|
9
|
+
* @returns {string|null} Path to meldoc.config.yml or null if not found
|
|
10
10
|
*/
|
|
11
11
|
function findRepoConfig(startDir = process.cwd()) {
|
|
12
12
|
let currentDir = path.resolve(startDir);
|
|
13
13
|
const root = path.parse(currentDir).root;
|
|
14
14
|
|
|
15
15
|
while (currentDir !== root) {
|
|
16
|
-
const configPath = path.join(currentDir, '
|
|
16
|
+
const configPath = path.join(currentDir, 'meldoc.config.yml');
|
|
17
17
|
if (fs.existsSync(configPath)) {
|
|
18
18
|
return configPath;
|
|
19
19
|
}
|
|
@@ -24,15 +24,15 @@ function findRepoConfig(startDir = process.cwd()) {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
|
-
* Read workspace alias from
|
|
28
|
-
* @param {string} configPath - Path to
|
|
27
|
+
* Read workspace alias from meldoc.config.yml
|
|
28
|
+
* @param {string} configPath - Path to meldoc.config.yml
|
|
29
29
|
* @returns {string|null} Workspace alias or null
|
|
30
30
|
*/
|
|
31
31
|
function readRepoConfig(configPath) {
|
|
32
32
|
try {
|
|
33
33
|
const content = fs.readFileSync(configPath, 'utf8');
|
|
34
34
|
const config = yaml.load(content);
|
|
35
|
-
return config?.
|
|
35
|
+
return config?.workspaceAlias || null;
|
|
36
36
|
} catch (error) {
|
|
37
37
|
return null;
|
|
38
38
|
}
|
|
@@ -41,7 +41,7 @@ function readRepoConfig(configPath) {
|
|
|
41
41
|
/**
|
|
42
42
|
* Resolve workspace alias for request
|
|
43
43
|
* Priority:
|
|
44
|
-
* 1. Repo config (
|
|
44
|
+
* 1. Repo config (meldoc.config.yml) - optional, can be skipped
|
|
45
45
|
* 2. Global config (~/.meldoc/config.json)
|
|
46
46
|
* 3. No header (let server choose automatically)
|
|
47
47
|
* @param {boolean} useRepoConfig - Whether to check repo config (optional)
|