mcp-adr-analysis-server 2.13.0 → 2.13.1
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/dist/.tsbuildinfo +1 -1
- package/dist/src/mcp-adr-analysis-server.d.ts +1 -45
- package/dist/src/mcp-adr-analysis-server.d.ts.map +1 -1
- package/dist/src/mcp-adr-analysis-server.js +11 -511
- package/dist/src/mcp-adr-analysis-server.js.map +1 -1
- package/dist/src/tools/mcp-tool-schemas.d.ts.map +1 -1
- package/dist/src/tools/mcp-tool-schemas.js +6 -143
- package/dist/src/tools/mcp-tool-schemas.js.map +1 -1
- package/dist/src/tools/tool-catalog.d.ts.map +1 -1
- package/dist/src/tools/tool-catalog.js +10 -232
- package/dist/src/tools/tool-catalog.js.map +1 -1
- package/dist/src/tools/tool-dispatch.d.ts.map +1 -1
- package/dist/src/tools/tool-dispatch.js +2 -40
- package/dist/src/tools/tool-dispatch.js.map +1 -1
- package/dist/src/tools/tool-dispatcher.d.ts +5 -6
- package/dist/src/tools/tool-dispatcher.d.ts.map +1 -1
- package/dist/src/tools/tool-dispatcher.js +7 -31
- package/dist/src/tools/tool-dispatcher.js.map +1 -1
- package/dist/src/utils/server-context-generator.d.ts.map +1 -1
- package/dist/src/utils/server-context-generator.js +0 -18
- package/dist/src/utils/server-context-generator.js.map +1 -1
- package/package.json +1 -1
|
@@ -19,7 +19,7 @@ import { getEnhancedModeDefault, getKnowledgeEnhancementDefault, } from './utils
|
|
|
19
19
|
import { StateReinforcementManager } from './utils/state-reinforcement-manager.js';
|
|
20
20
|
import { ConversationMemoryManager } from './utils/conversation-memory-manager.js';
|
|
21
21
|
import { MemoryEntityManager } from './utils/memory-entity-manager.js';
|
|
22
|
-
|
|
22
|
+
// RootManager import removed — ADR-023 (#1673)
|
|
23
23
|
import { ServerContextGenerator } from './utils/server-context-generator.js';
|
|
24
24
|
import { createNoOpContext } from './types/tool-context.js';
|
|
25
25
|
import { getToolListForMCP } from './tools/tool-dispatcher.js';
|
|
@@ -84,7 +84,7 @@ export class McpAdrAnalysisServer {
|
|
|
84
84
|
stateReinforcementManager;
|
|
85
85
|
conversationMemoryManager;
|
|
86
86
|
memoryEntityManager;
|
|
87
|
-
rootManager
|
|
87
|
+
// rootManager removed — only consumers were removed host-native handlers, ADR-023 (#1673)
|
|
88
88
|
contextGenerator;
|
|
89
89
|
constructor() {
|
|
90
90
|
// Load and validate configuration
|
|
@@ -94,8 +94,7 @@ export class McpAdrAnalysisServer {
|
|
|
94
94
|
this.stateReinforcementManager = new StateReinforcementManager(this.kgManager);
|
|
95
95
|
this.conversationMemoryManager = new ConversationMemoryManager(this.kgManager);
|
|
96
96
|
this.memoryEntityManager = new MemoryEntityManager();
|
|
97
|
-
//
|
|
98
|
-
this.rootManager = new RootManager(this.config.projectPath, this.config.adrDirectory);
|
|
97
|
+
// rootManager init removed — ADR-023 (#1673)
|
|
99
98
|
// Initialize server context generator
|
|
100
99
|
this.contextGenerator = new ServerContextGenerator();
|
|
101
100
|
// Print configuration summary
|
|
@@ -590,157 +589,7 @@ export class McpAdrAnalysisServer {
|
|
|
590
589
|
/**
|
|
591
590
|
* Tool implementations
|
|
592
591
|
*/
|
|
593
|
-
|
|
594
|
-
try {
|
|
595
|
-
const { loadAIConfig, isAIExecutionEnabled } = await import('./config/ai-config.js');
|
|
596
|
-
const config = loadAIConfig();
|
|
597
|
-
const hasApiKey = !!config.apiKey;
|
|
598
|
-
const isEnabled = isAIExecutionEnabled(config);
|
|
599
|
-
let reason = undefined;
|
|
600
|
-
if (config.executionMode !== 'ce-mcp') {
|
|
601
|
-
if (!hasApiKey) {
|
|
602
|
-
reason = 'Missing OPENROUTER_API_KEY environment variable';
|
|
603
|
-
}
|
|
604
|
-
else if (config.executionMode !== 'full') {
|
|
605
|
-
reason = `EXECUTION_MODE is '${config.executionMode}', should be 'full'`;
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
const status = {
|
|
609
|
-
isEnabled,
|
|
610
|
-
hasApiKey,
|
|
611
|
-
executionMode: config.executionMode,
|
|
612
|
-
model: config.defaultModel,
|
|
613
|
-
reason,
|
|
614
|
-
};
|
|
615
|
-
return {
|
|
616
|
-
content: [
|
|
617
|
-
{
|
|
618
|
-
type: 'text',
|
|
619
|
-
text: `# AI Execution Status Diagnostic
|
|
620
|
-
|
|
621
|
-
> **Note**: As of Phase 5, this server uses CE-MCP (Claude-Enriched MCP) mode by default.
|
|
622
|
-
> In CE-MCP mode, tools return orchestration directives that the host LLM executes directly,
|
|
623
|
-
> eliminating the need for external API calls. The configuration below applies to legacy mode only.
|
|
624
|
-
|
|
625
|
-
## Current Configuration
|
|
626
|
-
- **AI Execution Enabled**: ${status.isEnabled ? '✅ YES' : '❌ NO'}
|
|
627
|
-
- **Has API Key**: ${status.hasApiKey ? '✅ YES' : '❌ NO'}
|
|
628
|
-
- **Execution Mode**: ${status.executionMode}
|
|
629
|
-
- **AI Model**: ${status.model}
|
|
630
|
-
|
|
631
|
-
${
|
|
632
|
-
// CE-MCP is the DEFAULT mode and needs no API key. Reporting the absence of
|
|
633
|
-
// one as an "Issue Detected" -- immediately after saying no external API call
|
|
634
|
-
// is needed -- told every new user to go and buy a key they do not need.
|
|
635
|
-
// Legacy configuration is only a problem for someone who asked for it. (#1414)
|
|
636
|
-
status.executionMode === 'ce-mcp'
|
|
637
|
-
? `## ✅ Running in CE-MCP mode
|
|
638
|
-
|
|
639
|
-
No API key is required. Tools return orchestration directives that your host LLM
|
|
640
|
-
executes directly, which is why **AI Execution Enabled: NO** above is expected and
|
|
641
|
-
correct rather than a fault.
|
|
642
|
-
|
|
643
|
-
Note that only some tools currently return a directive; the rest return their
|
|
644
|
-
result directly. See ADR-014 and ADR-021.
|
|
645
|
-
|
|
646
|
-
Legacy OpenRouter execution is off by design. You only need the configuration
|
|
647
|
-
below if you deliberately want that older path.`
|
|
648
|
-
: status.reason
|
|
649
|
-
? `## ⚠️ Issue Detected
|
|
650
|
-
**Problem**: ${status.reason}
|
|
651
|
-
|
|
652
|
-
## Solution
|
|
653
|
-
${!status.hasApiKey
|
|
654
|
-
? `
|
|
655
|
-
1. Get an OpenRouter API key from https://openrouter.ai/keys
|
|
656
|
-
2. Add it to your MCP configuration:
|
|
657
|
-
\`\`\`json
|
|
658
|
-
{
|
|
659
|
-
"mcpServers": {
|
|
660
|
-
"adr-analysis": {
|
|
661
|
-
"command": "mcp-adr-analysis-server",
|
|
662
|
-
"env": {
|
|
663
|
-
"OPENROUTER_API_KEY": "your_api_key_here",
|
|
664
|
-
"EXECUTION_MODE": "full",
|
|
665
|
-
"AI_MODEL": "anthropic/claude-3-sonnet"
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
\`\`\`
|
|
671
|
-
3. Restart your MCP client (Claude Desktop, etc.)
|
|
672
|
-
`
|
|
673
|
-
: status.executionMode !== 'full'
|
|
674
|
-
? `
|
|
675
|
-
1. Update your MCP configuration to set EXECUTION_MODE to "full":
|
|
676
|
-
\`\`\`json
|
|
677
|
-
{
|
|
678
|
-
"mcpServers": {
|
|
679
|
-
"adr-analysis": {
|
|
680
|
-
"env": {
|
|
681
|
-
"EXECUTION_MODE": "full"
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
\`\`\`
|
|
687
|
-
2. Restart your MCP client
|
|
688
|
-
`
|
|
689
|
-
: ''}`
|
|
690
|
-
: `## ✅ Configuration Looks Good!
|
|
691
|
-
|
|
692
|
-
AI execution is properly configured. Tools should return actual results instead of prompts.
|
|
693
|
-
|
|
694
|
-
If you're still seeing prompts instead of results, try:
|
|
695
|
-
1. Restart your MCP client
|
|
696
|
-
2. Check your OpenRouter API key has sufficient credits
|
|
697
|
-
3. Verify network connectivity to OpenRouter.ai`}
|
|
698
|
-
|
|
699
|
-
${status.executionMode === 'ce-mcp'
|
|
700
|
-
? `## Environment Variables (CE-MCP mode)
|
|
701
|
-
No environment variables are required. CE-MCP mode is the default and works
|
|
702
|
-
without any API keys or execution-mode flags.
|
|
703
|
-
|
|
704
|
-
To switch to legacy OpenRouter execution instead, set:
|
|
705
|
-
- **OPENROUTER_API_KEY**: Your OpenRouter API key
|
|
706
|
-
- **EXECUTION_MODE**: \`full\`
|
|
707
|
-
- **AI_MODEL**: AI model to use (optional, defaults to claude-3-sonnet)`
|
|
708
|
-
: `## Environment Variables Expected
|
|
709
|
-
- **OPENROUTER_API_KEY**: Your OpenRouter API key
|
|
710
|
-
- **EXECUTION_MODE**: Set to "full" for AI execution
|
|
711
|
-
- **AI_MODEL**: AI model to use (optional, defaults to claude-3-sonnet)
|
|
712
|
-
|
|
713
|
-
## Testing
|
|
714
|
-
After fixing the configuration, try calling \`suggest_adrs\` - it should return actual ADR suggestions instead of prompts.`}
|
|
715
|
-
`,
|
|
716
|
-
},
|
|
717
|
-
],
|
|
718
|
-
};
|
|
719
|
-
}
|
|
720
|
-
catch (error) {
|
|
721
|
-
return {
|
|
722
|
-
content: [
|
|
723
|
-
{
|
|
724
|
-
type: 'text',
|
|
725
|
-
text: `# AI Execution Status Check Failed
|
|
726
|
-
|
|
727
|
-
**Error**: ${error instanceof Error ? error.message : String(error)}
|
|
728
|
-
|
|
729
|
-
This diagnostic tool checks the execution configuration. The server defaults to
|
|
730
|
-
CE-MCP mode, which requires no API key — so if you have not set any environment
|
|
731
|
-
variables, this error is unlikely to be a configuration problem.
|
|
732
|
-
|
|
733
|
-
## Manual Check (legacy OpenRouter mode only)
|
|
734
|
-
If you explicitly set EXECUTION_MODE=full, verify these environment variables:
|
|
735
|
-
- OPENROUTER_API_KEY
|
|
736
|
-
- EXECUTION_MODE=full
|
|
737
|
-
- AI_MODEL (optional)
|
|
738
|
-
`,
|
|
739
|
-
},
|
|
740
|
-
],
|
|
741
|
-
};
|
|
742
|
-
}
|
|
743
|
-
}
|
|
592
|
+
// checkAIExecutionStatus removed — host-native, ADR-023 (#1673)
|
|
744
593
|
async getWorkflowGuidance(args) {
|
|
745
594
|
const { goal, projectContext, availableAssets = [], timeframe = 'thorough_review', primaryConcerns = [], } = args;
|
|
746
595
|
try {
|
|
@@ -3718,146 +3567,11 @@ Please provide:
|
|
|
3718
3567
|
process.exit(0);
|
|
3719
3568
|
});
|
|
3720
3569
|
}
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
*/
|
|
3727
|
-
async listRoots() {
|
|
3728
|
-
const roots = this.rootManager.listRoots();
|
|
3729
|
-
const rootsList = roots
|
|
3730
|
-
.map(r => `### ${r.name}\n\n**Path**: \`${r.path}\`\n\n**Description**: ${r.description}\n`)
|
|
3731
|
-
.join('\n');
|
|
3732
|
-
return {
|
|
3733
|
-
content: [
|
|
3734
|
-
{
|
|
3735
|
-
type: 'text',
|
|
3736
|
-
text: `# Available File System Roots\n\nThese are the directories that can be accessed by this MCP server.\n\n${rootsList}\nUse these paths with \`read_directory\` and \`read_file\` tools to explore and access files.`,
|
|
3737
|
-
},
|
|
3738
|
-
],
|
|
3739
|
-
};
|
|
3740
|
-
}
|
|
3741
|
-
/**
|
|
3742
|
-
* Read directory contents (MCP best practice for autonomous file discovery)
|
|
3743
|
-
*/
|
|
3744
|
-
async readDirectory(args) {
|
|
3745
|
-
const targetPath = args.path || this.config.projectPath;
|
|
3746
|
-
try {
|
|
3747
|
-
const path = await import('path');
|
|
3748
|
-
const resolvedPath = path.resolve(targetPath);
|
|
3749
|
-
// Security check: ensure path is within accessible roots
|
|
3750
|
-
if (!this.rootManager.isPathAllowed(resolvedPath)) {
|
|
3751
|
-
const roots = this.rootManager.listRoots();
|
|
3752
|
-
const rootList = roots.map(r => ` - ${r.name}: ${r.path}`).join('\n');
|
|
3753
|
-
throw new McpAdrError(`Access denied: Path '${targetPath}' is outside accessible roots.\n\nAccessible roots:\n${rootList}\n\nUse list_roots tool for more details.`, 'ACCESS_DENIED');
|
|
3754
|
-
}
|
|
3755
|
-
const { readdir } = await import('fs/promises');
|
|
3756
|
-
const entries = await readdir(resolvedPath, { withFileTypes: true });
|
|
3757
|
-
const files = entries.filter(e => e.isFile()).map(e => `📄 ${e.name}`);
|
|
3758
|
-
const dirs = entries.filter(e => e.isDirectory()).map(e => `📁 ${e.name}/`);
|
|
3759
|
-
const root = this.rootManager.getRootForPath(resolvedPath);
|
|
3760
|
-
const relPath = this.rootManager.getRelativePathFromRoot(resolvedPath);
|
|
3761
|
-
const filesList = files.length > 0 ? files.join('\n') : '(no files)';
|
|
3762
|
-
const dirsList = dirs.length > 0 ? dirs.join('\n') : '(no directories)';
|
|
3763
|
-
return {
|
|
3764
|
-
content: [
|
|
3765
|
-
{
|
|
3766
|
-
type: 'text',
|
|
3767
|
-
text: `# Directory: ${targetPath}\n\n**Root**: ${root?.name}\n**Relative Path**: ${relPath || '/'}\n**Full Path**: \`${resolvedPath}\`\n\n## Directories (${dirs.length})\n\n${dirsList}\n\n## Files (${files.length})\n\n${filesList}`,
|
|
3768
|
-
},
|
|
3769
|
-
],
|
|
3770
|
-
};
|
|
3771
|
-
}
|
|
3772
|
-
catch (error) {
|
|
3773
|
-
throw new McpAdrError(`Failed to read directory: ${error instanceof Error ? error.message : String(error)}`, 'DIRECTORY_READ_ERROR');
|
|
3774
|
-
}
|
|
3775
|
-
}
|
|
3776
|
-
async readFile(args) {
|
|
3777
|
-
const { filePath } = args;
|
|
3778
|
-
try {
|
|
3779
|
-
const fs = await import('fs/promises');
|
|
3780
|
-
const path = await import('path');
|
|
3781
|
-
// Resolve path (handle both relative and absolute paths)
|
|
3782
|
-
const safePath = path.resolve(filePath);
|
|
3783
|
-
// Security check: ensure path is within accessible roots
|
|
3784
|
-
if (!this.rootManager.isPathAllowed(safePath)) {
|
|
3785
|
-
const roots = this.rootManager.listRoots();
|
|
3786
|
-
const rootList = roots.map(r => ` - ${r.name}: ${r.path}`).join('\n');
|
|
3787
|
-
throw new McpAdrError(`Access denied: Path '${filePath}' is outside accessible roots.\n\nAccessible roots:\n${rootList}\n\nUse list_roots tool for more details.`, 'ACCESS_DENIED');
|
|
3788
|
-
}
|
|
3789
|
-
const content = await fs.readFile(safePath, 'utf-8');
|
|
3790
|
-
return {
|
|
3791
|
-
content: [
|
|
3792
|
-
{
|
|
3793
|
-
type: 'text',
|
|
3794
|
-
text: content,
|
|
3795
|
-
},
|
|
3796
|
-
],
|
|
3797
|
-
};
|
|
3798
|
-
}
|
|
3799
|
-
catch (error) {
|
|
3800
|
-
throw new McpAdrError(`Failed to read file: ${error instanceof Error ? error.message : String(error)}`, 'FILE_READ_ERROR');
|
|
3801
|
-
}
|
|
3802
|
-
}
|
|
3803
|
-
async writeFile(args) {
|
|
3804
|
-
const { filePath, content } = args;
|
|
3805
|
-
try {
|
|
3806
|
-
const fs = await import('fs/promises');
|
|
3807
|
-
const path = await import('path');
|
|
3808
|
-
// Resolve path relative to project path for security
|
|
3809
|
-
const safePath = path.resolve(this.config.projectPath, filePath);
|
|
3810
|
-
// Security check: ensure path is within project directory
|
|
3811
|
-
if (!safePath.startsWith(this.config.projectPath)) {
|
|
3812
|
-
throw new McpAdrError('Access denied: Path is outside project directory', 'ACCESS_DENIED');
|
|
3813
|
-
}
|
|
3814
|
-
// Ensure directory exists
|
|
3815
|
-
await fs.mkdir(path.dirname(safePath), { recursive: true });
|
|
3816
|
-
// Write file
|
|
3817
|
-
await fs.writeFile(safePath, content, 'utf-8');
|
|
3818
|
-
return {
|
|
3819
|
-
content: [
|
|
3820
|
-
{
|
|
3821
|
-
type: 'text',
|
|
3822
|
-
text: `Successfully wrote to ${filePath}`,
|
|
3823
|
-
},
|
|
3824
|
-
],
|
|
3825
|
-
};
|
|
3826
|
-
}
|
|
3827
|
-
catch (error) {
|
|
3828
|
-
throw new McpAdrError(`Failed to write file: ${error instanceof Error ? error.message : String(error)}`, 'FILE_WRITE_ERROR');
|
|
3829
|
-
}
|
|
3830
|
-
}
|
|
3831
|
-
async listDirectory(args) {
|
|
3832
|
-
const { path: dirPath } = args;
|
|
3833
|
-
try {
|
|
3834
|
-
const fs = await import('fs/promises');
|
|
3835
|
-
const path = await import('path');
|
|
3836
|
-
// Resolve path relative to project path for security
|
|
3837
|
-
const safePath = path.resolve(this.config.projectPath, dirPath);
|
|
3838
|
-
// Security check: ensure path is within project directory
|
|
3839
|
-
if (!safePath.startsWith(this.config.projectPath)) {
|
|
3840
|
-
throw new McpAdrError('Access denied: Path is outside project directory', 'ACCESS_DENIED');
|
|
3841
|
-
}
|
|
3842
|
-
const entries = await fs.readdir(safePath, { withFileTypes: true });
|
|
3843
|
-
const fileList = entries.map(entry => ({
|
|
3844
|
-
name: entry.name,
|
|
3845
|
-
type: entry.isDirectory() ? 'directory' : 'file',
|
|
3846
|
-
path: path.join(dirPath, entry.name),
|
|
3847
|
-
}));
|
|
3848
|
-
return {
|
|
3849
|
-
content: [
|
|
3850
|
-
{
|
|
3851
|
-
type: 'text',
|
|
3852
|
-
text: JSON.stringify(fileList, null, 2),
|
|
3853
|
-
},
|
|
3854
|
-
],
|
|
3855
|
-
};
|
|
3856
|
-
}
|
|
3857
|
-
catch (error) {
|
|
3858
|
-
throw new McpAdrError(`Failed to list directory: ${error instanceof Error ? error.message : String(error)}`, 'DIRECTORY_LIST_ERROR');
|
|
3859
|
-
}
|
|
3860
|
-
}
|
|
3570
|
+
// listRoots removed — host-native, ADR-023 (#1673)
|
|
3571
|
+
// readDirectory removed — host-native, ADR-023 (#1673)
|
|
3572
|
+
// readFile removed — host-native, ADR-023 (#1673)
|
|
3573
|
+
// writeFile removed — host-native, ADR-023 (#1673)
|
|
3574
|
+
// listDirectory removed — host-native, ADR-023 (#1673)
|
|
3861
3575
|
async generateDeploymentGuidance(args) {
|
|
3862
3576
|
try {
|
|
3863
3577
|
const { generateDeploymentGuidance } = await import('./tools/deployment-guidance-tool.js');
|
|
@@ -4062,113 +3776,7 @@ This tool has been deprecated and replaced with memory-centric health scoring.
|
|
|
4062
3776
|
throw new McpAdrError(`Server context generation failed: ${error instanceof Error ? error.message : String(error)}`, 'SERVER_CONTEXT_ERROR');
|
|
4063
3777
|
}
|
|
4064
3778
|
}
|
|
4065
|
-
|
|
4066
|
-
* Get Current Datetime Tool
|
|
4067
|
-
* Returns the current date and time in various formats for ADR generation and timestamping
|
|
4068
|
-
*/
|
|
4069
|
-
async getCurrentDatetime(args) {
|
|
4070
|
-
const { timezone = 'UTC', format = 'all', includeTimestamp = true } = args;
|
|
4071
|
-
try {
|
|
4072
|
-
const now = new Date();
|
|
4073
|
-
// Format date for different timezones
|
|
4074
|
-
const formatOptions = {
|
|
4075
|
-
timeZone: timezone,
|
|
4076
|
-
year: 'numeric',
|
|
4077
|
-
month: '2-digit',
|
|
4078
|
-
day: '2-digit',
|
|
4079
|
-
hour: '2-digit',
|
|
4080
|
-
minute: '2-digit',
|
|
4081
|
-
second: '2-digit',
|
|
4082
|
-
hour12: false,
|
|
4083
|
-
};
|
|
4084
|
-
// Get date parts for the specified timezone
|
|
4085
|
-
const formatter = new Intl.DateTimeFormat('en-CA', {
|
|
4086
|
-
timeZone: timezone,
|
|
4087
|
-
year: 'numeric',
|
|
4088
|
-
month: '2-digit',
|
|
4089
|
-
day: '2-digit',
|
|
4090
|
-
});
|
|
4091
|
-
const parts = formatter.formatToParts(now);
|
|
4092
|
-
const year = parts.find(p => p.type === 'year')?.value || '';
|
|
4093
|
-
const month = parts.find(p => p.type === 'month')?.value || '';
|
|
4094
|
-
const day = parts.find(p => p.type === 'day')?.value || '';
|
|
4095
|
-
// ADR date format: YYYY-MM-DD
|
|
4096
|
-
const adrDate = `${year}-${month}-${day}`;
|
|
4097
|
-
// ISO 8601 format
|
|
4098
|
-
const isoDate = now.toISOString();
|
|
4099
|
-
// Human-readable format
|
|
4100
|
-
const humanFormatter = new Intl.DateTimeFormat('en-US', {
|
|
4101
|
-
...formatOptions,
|
|
4102
|
-
weekday: 'long',
|
|
4103
|
-
month: 'long',
|
|
4104
|
-
});
|
|
4105
|
-
const humanDate = humanFormatter.format(now);
|
|
4106
|
-
// Build response based on requested format
|
|
4107
|
-
let responseData = {};
|
|
4108
|
-
switch (format) {
|
|
4109
|
-
case 'iso':
|
|
4110
|
-
responseData = { iso: isoDate };
|
|
4111
|
-
break;
|
|
4112
|
-
case 'human':
|
|
4113
|
-
responseData = { human: humanDate };
|
|
4114
|
-
break;
|
|
4115
|
-
case 'adr':
|
|
4116
|
-
responseData = { adr: adrDate };
|
|
4117
|
-
break;
|
|
4118
|
-
case 'all':
|
|
4119
|
-
default:
|
|
4120
|
-
responseData = {
|
|
4121
|
-
iso: isoDate,
|
|
4122
|
-
human: humanDate,
|
|
4123
|
-
adr: adrDate,
|
|
4124
|
-
timezone: timezone,
|
|
4125
|
-
};
|
|
4126
|
-
}
|
|
4127
|
-
if (includeTimestamp) {
|
|
4128
|
-
responseData['timestamp'] = now.getTime();
|
|
4129
|
-
}
|
|
4130
|
-
const responseText = `# Current Date and Time
|
|
4131
|
-
|
|
4132
|
-
## Formats
|
|
4133
|
-
${format === 'all' || format === 'iso' ? `- **ISO 8601**: ${isoDate}` : ''}
|
|
4134
|
-
${format === 'all' || format === 'human' ? `- **Human Readable**: ${humanDate}` : ''}
|
|
4135
|
-
${format === 'all' || format === 'adr' ? `- **ADR Date (YYYY-MM-DD)**: ${adrDate}` : ''}
|
|
4136
|
-
${format === 'all' ? `- **Timezone**: ${timezone}` : ''}
|
|
4137
|
-
${includeTimestamp ? `- **Unix Timestamp (ms)**: ${now.getTime()}` : ''}
|
|
4138
|
-
|
|
4139
|
-
## Usage for ADR Generation
|
|
4140
|
-
|
|
4141
|
-
When generating ADRs, use the ADR date format (\`${adrDate}\`) in the Date field:
|
|
4142
|
-
|
|
4143
|
-
\`\`\`markdown
|
|
4144
|
-
# ADR-XXXX: [Title]
|
|
4145
|
-
|
|
4146
|
-
## Date
|
|
4147
|
-
${adrDate}
|
|
4148
|
-
|
|
4149
|
-
## Status
|
|
4150
|
-
Proposed
|
|
4151
|
-
\`\`\`
|
|
4152
|
-
|
|
4153
|
-
## Raw Data
|
|
4154
|
-
|
|
4155
|
-
\`\`\`json
|
|
4156
|
-
${JSON.stringify(responseData, null, 2)}
|
|
4157
|
-
\`\`\`
|
|
4158
|
-
`;
|
|
4159
|
-
return {
|
|
4160
|
-
content: [
|
|
4161
|
-
{
|
|
4162
|
-
type: 'text',
|
|
4163
|
-
text: responseText,
|
|
4164
|
-
},
|
|
4165
|
-
],
|
|
4166
|
-
};
|
|
4167
|
-
}
|
|
4168
|
-
catch (error) {
|
|
4169
|
-
throw new McpAdrError(`Failed to get current datetime: ${error instanceof Error ? error.message : String(error)}`, 'DATETIME_ERROR');
|
|
4170
|
-
}
|
|
4171
|
-
}
|
|
3779
|
+
// getCurrentDatetime removed — host-native, ADR-023 (#1673)
|
|
4172
3780
|
/**
|
|
4173
3781
|
* Set Project Path Tool - Dynamic Session Configuration
|
|
4174
3782
|
*
|
|
@@ -4194,8 +3802,7 @@ ${JSON.stringify(responseData, null, 2)}
|
|
|
4194
3802
|
}
|
|
4195
3803
|
// Update the server configuration
|
|
4196
3804
|
this.config.projectPath = absolutePath;
|
|
4197
|
-
//
|
|
4198
|
-
this.rootManager = new RootManager(absolutePath, this.config.adrDirectory);
|
|
3805
|
+
// rootManager re-init removed — ADR-023 (#1673)
|
|
4199
3806
|
this.logger.info(`Project path changed: ${previousPath} -> ${absolutePath}`);
|
|
4200
3807
|
const responseText = `# Project Path Updated
|
|
4201
3808
|
|
|
@@ -4227,112 +3834,5 @@ To make this permanent, set the \`PROJECT_PATH\` environment variable.
|
|
|
4227
3834
|
throw new McpAdrError(`Failed to set project path: ${error instanceof Error ? error.message : String(error)}`, 'SET_PROJECT_PATH_ERROR');
|
|
4228
3835
|
}
|
|
4229
3836
|
}
|
|
4230
|
-
/**
|
|
4231
|
-
* Load Prompt Tool - CE-MCP Phase 4 Lazy Loading
|
|
4232
|
-
*
|
|
4233
|
-
* @description Loads prompts on-demand instead of eagerly loading all prompts at startup.
|
|
4234
|
-
* This reduces token usage by ~96% (from 28K tokens to ~1K on-demand).
|
|
4235
|
-
*
|
|
4236
|
-
* @param args - Load prompt arguments
|
|
4237
|
-
* @param args.promptName - Name of the prompt to load
|
|
4238
|
-
* @param args.section - Optional section within the prompt
|
|
4239
|
-
* @param args.estimateOnly - If true, returns only token estimate
|
|
4240
|
-
* @returns Promise<CallToolResult> - Loaded prompt content or estimate
|
|
4241
|
-
*/
|
|
4242
|
-
async loadPrompt(args) {
|
|
4243
|
-
const { promptName, section, estimateOnly = false } = args;
|
|
4244
|
-
// Import the prompt catalog dynamically to enable lazy loading
|
|
4245
|
-
const { getPromptLoader, getPromptMetadata, calculateTokenSavings } = await import('./prompts/prompt-catalog.js');
|
|
4246
|
-
const metadata = getPromptMetadata(promptName);
|
|
4247
|
-
if (!metadata) {
|
|
4248
|
-
const availablePrompts = [
|
|
4249
|
-
'adr-suggestion',
|
|
4250
|
-
'deployment-analysis',
|
|
4251
|
-
'environment-analysis',
|
|
4252
|
-
'research-question',
|
|
4253
|
-
'rule-generation',
|
|
4254
|
-
'analysis',
|
|
4255
|
-
'research-integration',
|
|
4256
|
-
'validated-pattern',
|
|
4257
|
-
'security',
|
|
4258
|
-
];
|
|
4259
|
-
return {
|
|
4260
|
-
content: [
|
|
4261
|
-
{
|
|
4262
|
-
type: 'text',
|
|
4263
|
-
text: JSON.stringify({
|
|
4264
|
-
success: false,
|
|
4265
|
-
error: `Unknown prompt: ${promptName}`,
|
|
4266
|
-
availablePrompts,
|
|
4267
|
-
hint: 'Use one of the available prompt names listed above',
|
|
4268
|
-
}, null, 2),
|
|
4269
|
-
},
|
|
4270
|
-
],
|
|
4271
|
-
isError: true,
|
|
4272
|
-
};
|
|
4273
|
-
}
|
|
4274
|
-
// If estimate only, return token information without loading
|
|
4275
|
-
if (estimateOnly) {
|
|
4276
|
-
const loader = getPromptLoader();
|
|
4277
|
-
const estimatedTokens = loader.getEstimatedTokens(promptName, section);
|
|
4278
|
-
const savings = calculateTokenSavings([promptName]);
|
|
4279
|
-
return {
|
|
4280
|
-
content: [
|
|
4281
|
-
{
|
|
4282
|
-
type: 'text',
|
|
4283
|
-
text: JSON.stringify({
|
|
4284
|
-
success: true,
|
|
4285
|
-
promptName,
|
|
4286
|
-
section: section || 'full',
|
|
4287
|
-
estimatedTokens,
|
|
4288
|
-
metadata: {
|
|
4289
|
-
file: metadata.file,
|
|
4290
|
-
category: metadata.category,
|
|
4291
|
-
totalTokens: metadata.tokens,
|
|
4292
|
-
availableSections: metadata.sections,
|
|
4293
|
-
loadOnDemand: metadata.loadOnDemand,
|
|
4294
|
-
},
|
|
4295
|
-
tokenSavings: {
|
|
4296
|
-
loaded: savings.loaded,
|
|
4297
|
-
total: savings.total,
|
|
4298
|
-
saved: savings.saved,
|
|
4299
|
-
percentage: `${savings.percentage}%`,
|
|
4300
|
-
},
|
|
4301
|
-
}, null, 2),
|
|
4302
|
-
},
|
|
4303
|
-
],
|
|
4304
|
-
};
|
|
4305
|
-
}
|
|
4306
|
-
// Load the prompt content
|
|
4307
|
-
try {
|
|
4308
|
-
const loader = getPromptLoader();
|
|
4309
|
-
const content = await loader.loadPrompt(promptName, section);
|
|
4310
|
-
return {
|
|
4311
|
-
content: [
|
|
4312
|
-
{
|
|
4313
|
-
type: 'text',
|
|
4314
|
-
text: `# Loaded Prompt: ${promptName}${section ? ` (section: ${section})` : ''}
|
|
4315
|
-
|
|
4316
|
-
## Metadata
|
|
4317
|
-
- **Category**: ${metadata.category}
|
|
4318
|
-
- **Estimated Tokens**: ${metadata.tokens}
|
|
4319
|
-
- **Available Sections**: ${metadata.sections.join(', ')}
|
|
4320
|
-
|
|
4321
|
-
## Content
|
|
4322
|
-
|
|
4323
|
-
${content}
|
|
4324
|
-
|
|
4325
|
-
---
|
|
4326
|
-
|
|
4327
|
-
*Loaded on-demand via CE-MCP lazy loading system. Token savings: ~96% compared to eager loading all prompts.*
|
|
4328
|
-
`,
|
|
4329
|
-
},
|
|
4330
|
-
],
|
|
4331
|
-
};
|
|
4332
|
-
}
|
|
4333
|
-
catch (error) {
|
|
4334
|
-
throw new McpAdrError(`Failed to load prompt '${promptName}'${section ? ` section '${section}'` : ''}: ${error instanceof Error ? error.message : String(error)}`, 'PROMPT_LOAD_ERROR');
|
|
4335
|
-
}
|
|
4336
|
-
}
|
|
4337
3837
|
}
|
|
4338
3838
|
//# sourceMappingURL=mcp-adr-analysis-server.js.map
|