@grunnverk/kodrdriv 1.3.0
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/.claude/settings.local.json +12 -0
- package/.cursor/rules/no-local-dependencies.md +6 -0
- package/.gitignore~ +23 -0
- package/.kodrdriv-example-branch-targeting.yaml +71 -0
- package/BUG_TREE_PUBLISH_CONFIG_DIR.md +79 -0
- package/LICENSE +190 -0
- package/README.md +218 -0
- package/dist/application.js +228 -0
- package/dist/application.js.map +1 -0
- package/dist/arguments.js +1307 -0
- package/dist/arguments.js.map +1 -0
- package/dist/constants.js +255 -0
- package/dist/constants.js.map +1 -0
- package/dist/logging.js +176 -0
- package/dist/logging.js.map +1 -0
- package/dist/main.js +24 -0
- package/dist/main.js.map +1 -0
- package/dist/mcp/prompts/check_development.md +169 -0
- package/dist/mcp/prompts/dependency_update.md +62 -0
- package/dist/mcp/prompts/fix_and_commit.md +53 -0
- package/dist/mcp/prompts/publish.md +100 -0
- package/dist/mcp/prompts/tree_fix_and_commit.md +102 -0
- package/dist/mcp/prompts/tree_publish.md +118 -0
- package/dist/mcp-server.js +15601 -0
- package/dist/mcp-server.js.map +7 -0
- package/dist/types.js +303 -0
- package/dist/types.js.map +1 -0
- package/guide/ai-system.md +522 -0
- package/guide/architecture.md +349 -0
- package/guide/commands.md +383 -0
- package/guide/configuration.md +516 -0
- package/guide/debugging.md +587 -0
- package/guide/development.md +632 -0
- package/guide/index.md +224 -0
- package/guide/integration.md +510 -0
- package/guide/monorepo.md +533 -0
- package/guide/quickstart.md +249 -0
- package/guide/testing.md +463 -0
- package/guide/tree-operations.md +621 -0
- package/guide/usage.md +578 -0
- package/input/250509-kodrdriv-library-rules.m4a +0 -0
- package/package.json +105 -0
- package/packages/components/package.json +7 -0
- package/packages/tools/package.json +7 -0
- package/packages/utils/package.json +7 -0
- package/processed/250705-kodrdriv-confirm-editor-for-commit-and-release.m4a +0 -0
- package/processed/250705-kodrdriv-confirm-flag-release.m4a +0 -0
- package/processed/250705-kodrdriv-context-for-review.m4a +0 -0
- package/processed/250705-kodrdriv-feedback-on-publish-pipeline.m4a +0 -0
- package/processed/250705-kodrdriv-intelligent-eslint-style.m4a +0 -0
- package/processed/250705-kodrdriv-make-review-less-strict.m4a +0 -0
- package/processed/250705-kodrdriv-multilevel-transcription.m4a +0 -0
- package/processed/250705-kodrdriv-opinionated-review.m4a +0 -0
- package/processed/250705-kodrdriv-publish-next-version.m4a +0 -0
- package/processed/250705-kodrdriv-release-branches-and-milestones.m4a +0 -0
- package/processed/250705-kodrdriv-scope-check-fix-or-ignore.m4a +0 -0
- package/processed/250705-kodrdriv-scope-checker.m4a +0 -0
- package/processed/250705-kodrdriv-specify-a-release-note-for-publish.m4a +0 -0
- package/scripts/build-mcp.js +111 -0
- package/scripts/pre-commit-hook.sh +52 -0
- package/scripts/test-get-version-tool.js +102 -0
- package/scripts/test-mcp-compliance.js +254 -0
- package/scripts/update-test-log-assertions.js +73 -0
- package/temp-dist/arguments.js +817 -0
- package/temp-dist/constants.js +202 -0
- package/temp-dist/logging.js +130 -0
- package/temp-dist/types.js +112 -0
- package/temp-dist/util/stdin.js +132 -0
- package/temp-dist/util/storage.js +149 -0
- package/temp-dist/util/validation.js +110 -0
- package/test-external-unlink/package.json +16 -0
- package/test-externals/package.json +8 -0
- package/test-increment.js +0 -0
- package/test-multiline/cli/package.json +8 -0
- package/test-multiline/core/package.json +5 -0
- package/test-multiline/mobile/package.json +8 -0
- package/test-multiline/web/package.json +8 -0
- package/test-project/package-lock.json +21 -0
- package/test-project/package.json +1 -0
- package/test-review-flow.sh +15 -0
- package/test-sort-files/alpha.md +3 -0
- package/test-sort-files/middle.txt +3 -0
- package/test-sort-files/zebra.txt +3 -0
- package/test_output.txt +161 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Build MCP Server
|
|
4
|
+
* Simple build script to compile the MCP server separately from main build
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { build } from 'esbuild';
|
|
8
|
+
import { resolve, dirname } from 'path';
|
|
9
|
+
import { fileURLToPath } from 'url';
|
|
10
|
+
import { readFileSync, writeFileSync, chmodSync } from 'fs';
|
|
11
|
+
import { execSync } from 'child_process';
|
|
12
|
+
import os from 'os';
|
|
13
|
+
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __dirname = dirname(__filename);
|
|
16
|
+
const root = resolve(__dirname, '..');
|
|
17
|
+
|
|
18
|
+
// Capture git info
|
|
19
|
+
let gitInfo = {
|
|
20
|
+
branch: '',
|
|
21
|
+
commit: '',
|
|
22
|
+
tags: '',
|
|
23
|
+
commitDate: '',
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
gitInfo = {
|
|
28
|
+
branch: execSync('git rev-parse --abbrev-ref HEAD').toString().trim(),
|
|
29
|
+
commit: execSync('git rev-parse --short HEAD').toString().trim(),
|
|
30
|
+
tags: '',
|
|
31
|
+
commitDate: execSync('git log -1 --format=%cd --date=iso').toString().trim(),
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
gitInfo.tags = execSync('git tag --points-at HEAD | paste -sd "," -').toString().trim();
|
|
36
|
+
} catch {
|
|
37
|
+
gitInfo.tags = '';
|
|
38
|
+
}
|
|
39
|
+
} catch {
|
|
40
|
+
console.log('No git repository, using placeholder values');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Capture build metadata
|
|
44
|
+
const buildInfo = {
|
|
45
|
+
hostname: os.hostname(),
|
|
46
|
+
timestamp: new Date().toISOString(),
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// Get package version
|
|
50
|
+
const packageJson = JSON.parse(readFileSync(resolve(root, 'package.json'), 'utf-8'));
|
|
51
|
+
const version = packageJson.version;
|
|
52
|
+
|
|
53
|
+
async function buildMCPServer() {
|
|
54
|
+
try {
|
|
55
|
+
console.log('Building MCP server...');
|
|
56
|
+
|
|
57
|
+
await build({
|
|
58
|
+
entryPoints: [resolve(root, 'src/mcp/server.ts')],
|
|
59
|
+
bundle: true,
|
|
60
|
+
platform: 'node',
|
|
61
|
+
target: 'esnext',
|
|
62
|
+
format: 'esm',
|
|
63
|
+
outfile: resolve(root, 'dist/mcp-server.js'),
|
|
64
|
+
external: [
|
|
65
|
+
'@modelcontextprotocol/*',
|
|
66
|
+
'@grunnverk/*',
|
|
67
|
+
'@theunwalked/*',
|
|
68
|
+
'@riotprompt/*',
|
|
69
|
+
// Winston and its dependencies use dynamic requires that don't work when bundled
|
|
70
|
+
// These must be external dependencies, not bundled
|
|
71
|
+
'winston',
|
|
72
|
+
'winston/*',
|
|
73
|
+
'logform',
|
|
74
|
+
'logform/*',
|
|
75
|
+
'@colors/colors',
|
|
76
|
+
'@colors/safe',
|
|
77
|
+
],
|
|
78
|
+
sourcemap: true,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// Add shebang and replace placeholders
|
|
82
|
+
const outputPath = resolve(root, 'dist/mcp-server.js');
|
|
83
|
+
let content = readFileSync(outputPath, 'utf-8');
|
|
84
|
+
|
|
85
|
+
// Replace placeholders
|
|
86
|
+
content = content.replace(/__VERSION__/g, version);
|
|
87
|
+
content = content.replace(/__GIT_BRANCH__/g, gitInfo.branch);
|
|
88
|
+
content = content.replace(/__GIT_COMMIT__/g, gitInfo.commit);
|
|
89
|
+
content = content.replace(/__GIT_TAGS__/g, gitInfo.tags === '' ? '' : `T:${gitInfo.tags}`);
|
|
90
|
+
content = content.replace(/__GIT_COMMIT_DATE__/g, gitInfo.commitDate);
|
|
91
|
+
content = content.replace(/__SYSTEM_INFO__/g, `${process.platform} ${process.arch} ${process.version}`);
|
|
92
|
+
content = content.replace(/__BUILD_HOSTNAME__/g, buildInfo.hostname);
|
|
93
|
+
content = content.replace(/__BUILD_TIMESTAMP__/g, buildInfo.timestamp);
|
|
94
|
+
|
|
95
|
+
if (!content.startsWith('#!')) {
|
|
96
|
+
content = `#!/usr/bin/env node\n${content}`;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
writeFileSync(outputPath, content);
|
|
100
|
+
|
|
101
|
+
// Make executable
|
|
102
|
+
chmodSync(outputPath, 0o755);
|
|
103
|
+
|
|
104
|
+
console.log('✓ MCP server built successfully');
|
|
105
|
+
} catch (error) {
|
|
106
|
+
console.error('✗ MCP server build failed:', error);
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
buildMCPServer();
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# KodrDriv Pre-commit Hook
|
|
4
|
+
# Prevents committing package.json files that contain file: dependencies
|
|
5
|
+
#
|
|
6
|
+
# To install this hook:
|
|
7
|
+
# 1. Copy this file to .git/hooks/pre-commit
|
|
8
|
+
# 2. Make it executable: chmod +x .git/hooks/pre-commit
|
|
9
|
+
#
|
|
10
|
+
# Or run: npm run install-hooks (if you add this script to package.json)
|
|
11
|
+
|
|
12
|
+
echo "🔍 Checking for file: dependencies in staged package.json files..."
|
|
13
|
+
|
|
14
|
+
# Find all staged package.json files
|
|
15
|
+
staged_package_files=$(git diff --cached --name-only | grep "package\.json$")
|
|
16
|
+
|
|
17
|
+
if [ -z "$staged_package_files" ]; then
|
|
18
|
+
echo "✅ No package.json files staged for commit"
|
|
19
|
+
exit 0
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
found_file_deps=false
|
|
23
|
+
|
|
24
|
+
# Check each staged package.json file for file: dependencies
|
|
25
|
+
for file in $staged_package_files; do
|
|
26
|
+
if [ -f "$file" ]; then
|
|
27
|
+
# Look for "file:" dependencies in the staged version
|
|
28
|
+
if git show :$file | grep -q '"file:'; then
|
|
29
|
+
echo "❌ Found file: dependencies in $file:"
|
|
30
|
+
git show :$file | grep '"file:' | sed 's/^/ /'
|
|
31
|
+
found_file_deps=true
|
|
32
|
+
fi
|
|
33
|
+
fi
|
|
34
|
+
done
|
|
35
|
+
|
|
36
|
+
if $found_file_deps; then
|
|
37
|
+
echo ""
|
|
38
|
+
echo "🚫 COMMIT BLOCKED: Cannot commit package.json files with file: dependencies"
|
|
39
|
+
echo ""
|
|
40
|
+
echo "💡 To fix this:"
|
|
41
|
+
echo " 1. Run 'kodrdriv unlink' to restore registry versions"
|
|
42
|
+
echo " 2. Commit your changes"
|
|
43
|
+
echo " 3. Run 'kodrdriv link' again for local development"
|
|
44
|
+
echo ""
|
|
45
|
+
echo " Or to commit anyway (not recommended):"
|
|
46
|
+
echo " git commit --no-verify"
|
|
47
|
+
echo ""
|
|
48
|
+
exit 1
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
echo "✅ No file: dependencies found in staged package.json files"
|
|
52
|
+
exit 0
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Test get_version MCP tool
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { spawn } from 'child_process';
|
|
7
|
+
import { resolve } from 'path';
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
9
|
+
import { dirname } from 'path';
|
|
10
|
+
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
+
const __dirname = dirname(__filename);
|
|
13
|
+
|
|
14
|
+
const SERVER_PATH = resolve(__dirname, '../dist/mcp-server.js');
|
|
15
|
+
const TIMEOUT_MS = 5000;
|
|
16
|
+
|
|
17
|
+
console.log('🔍 Testing get_version tool...\n');
|
|
18
|
+
|
|
19
|
+
function sendMCPRequest(server, method, params = {}) {
|
|
20
|
+
return new Promise((resolve, reject) => {
|
|
21
|
+
const id = Math.floor(Math.random() * 1000000);
|
|
22
|
+
const request = {
|
|
23
|
+
jsonrpc: '2.0',
|
|
24
|
+
id,
|
|
25
|
+
method,
|
|
26
|
+
params,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
let response = '';
|
|
30
|
+
const timeout = setTimeout(() => {
|
|
31
|
+
reject(new Error('Request timeout'));
|
|
32
|
+
}, TIMEOUT_MS);
|
|
33
|
+
|
|
34
|
+
server.stdout.on('data', (data) => {
|
|
35
|
+
response += data.toString();
|
|
36
|
+
try {
|
|
37
|
+
const parsed = JSON.parse(response);
|
|
38
|
+
if (parsed.id === id) {
|
|
39
|
+
clearTimeout(timeout);
|
|
40
|
+
resolve(parsed);
|
|
41
|
+
}
|
|
42
|
+
} catch (e) {
|
|
43
|
+
// Still accumulating response
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
server.stdin.write(JSON.stringify(request) + '\n');
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function testGetVersionTool() {
|
|
52
|
+
const server = spawn('node', [SERVER_PATH], {
|
|
53
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
// Initialize
|
|
58
|
+
await sendMCPRequest(server, 'initialize', {
|
|
59
|
+
protocolVersion: '2024-11-05',
|
|
60
|
+
capabilities: {},
|
|
61
|
+
clientInfo: { name: 'test', version: '1.0.0' },
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Call get_version tool
|
|
65
|
+
const response = await sendMCPRequest(server, 'tools/call', {
|
|
66
|
+
name: 'kodrdriv_get_version',
|
|
67
|
+
arguments: {},
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
if (response.result && response.result.content) {
|
|
71
|
+
const content = response.result.content[0];
|
|
72
|
+
console.log('✅ get_version tool executed successfully\n');
|
|
73
|
+
console.log('Response:');
|
|
74
|
+
console.log(content.text);
|
|
75
|
+
console.log('\n');
|
|
76
|
+
|
|
77
|
+
// Parse and display structured data
|
|
78
|
+
try {
|
|
79
|
+
const data = JSON.parse(content.text);
|
|
80
|
+
console.log('Parsed data:');
|
|
81
|
+
console.log(' Version:', data.version);
|
|
82
|
+
console.log(' Build Hostname:', data.buildHostname);
|
|
83
|
+
console.log(' Build Timestamp:', data.buildTimestamp);
|
|
84
|
+
} catch (e) {
|
|
85
|
+
// Response might be text format
|
|
86
|
+
}
|
|
87
|
+
} else {
|
|
88
|
+
throw new Error('Invalid response from get_version tool');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
server.kill();
|
|
92
|
+
return true;
|
|
93
|
+
} catch (error) {
|
|
94
|
+
server.kill();
|
|
95
|
+
console.log(`❌ Test failed: ${error.message}\n`);
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
testGetVersionTool().then(success => {
|
|
101
|
+
process.exit(success ? 0 : 1);
|
|
102
|
+
});
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* MCP Compliance Test
|
|
4
|
+
*
|
|
5
|
+
* Validates that kodrdriv MCP server follows MCP specification.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { spawn } from 'child_process';
|
|
9
|
+
import { resolve } from 'path';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
import { dirname } from 'path';
|
|
12
|
+
|
|
13
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
+
const __dirname = dirname(__filename);
|
|
15
|
+
|
|
16
|
+
// Test configuration
|
|
17
|
+
const SERVER_PATH = resolve(__dirname, '../dist/mcp-server.js');
|
|
18
|
+
const TIMEOUT_MS = 5000;
|
|
19
|
+
|
|
20
|
+
console.log('🔍 Testing MCP Compliance for KodrDriv...\n');
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Helper to send JSON-RPC request to MCP server
|
|
24
|
+
*/
|
|
25
|
+
function sendMCPRequest(server, method, params = {}) {
|
|
26
|
+
return new Promise((resolve, reject) => {
|
|
27
|
+
const id = Math.floor(Math.random() * 1000000);
|
|
28
|
+
const request = {
|
|
29
|
+
jsonrpc: '2.0',
|
|
30
|
+
id,
|
|
31
|
+
method,
|
|
32
|
+
params,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
let response = '';
|
|
36
|
+
const timeout = setTimeout(() => {
|
|
37
|
+
reject(new Error('Request timeout'));
|
|
38
|
+
}, TIMEOUT_MS);
|
|
39
|
+
|
|
40
|
+
server.stdout.on('data', (data) => {
|
|
41
|
+
response += data.toString();
|
|
42
|
+
try {
|
|
43
|
+
const parsed = JSON.parse(response);
|
|
44
|
+
if (parsed.id === id) {
|
|
45
|
+
clearTimeout(timeout);
|
|
46
|
+
resolve(parsed);
|
|
47
|
+
}
|
|
48
|
+
} catch (e) {
|
|
49
|
+
// Still accumulating response
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
server.stdin.write(JSON.stringify(request) + '\n');
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Test 1: Server starts and initializes
|
|
58
|
+
async function testServerInitialization() {
|
|
59
|
+
console.log('Test 1: Server Initialization...');
|
|
60
|
+
|
|
61
|
+
const server = spawn('node', [SERVER_PATH], {
|
|
62
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
const response = await sendMCPRequest(server, 'initialize', {
|
|
67
|
+
protocolVersion: '2024-11-05',
|
|
68
|
+
capabilities: {},
|
|
69
|
+
clientInfo: {
|
|
70
|
+
name: 'test-client',
|
|
71
|
+
version: '1.0.0',
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
if (response.result && response.result.protocolVersion) {
|
|
76
|
+
console.log(' ✅ Server initializes correctly');
|
|
77
|
+
console.log(` Protocol: ${response.result.protocolVersion}`);
|
|
78
|
+
console.log(` Server: ${response.result.serverInfo?.name || 'unknown'}\n`);
|
|
79
|
+
} else {
|
|
80
|
+
throw new Error('Invalid initialization response');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
server.kill();
|
|
84
|
+
return true;
|
|
85
|
+
} catch (error) {
|
|
86
|
+
server.kill();
|
|
87
|
+
console.log(` ⚠️ Initialization test skipped: ${error.message}\n`);
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Test 2: Server advertises capabilities
|
|
93
|
+
async function testCapabilities() {
|
|
94
|
+
console.log('Test 2: Capabilities Advertisement...');
|
|
95
|
+
|
|
96
|
+
const server = spawn('node', [SERVER_PATH], {
|
|
97
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
const initResponse = await sendMCPRequest(server, 'initialize', {
|
|
102
|
+
protocolVersion: '2024-11-05',
|
|
103
|
+
capabilities: {},
|
|
104
|
+
clientInfo: { name: 'test', version: '1.0.0' },
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
const caps = initResponse.result?.capabilities;
|
|
108
|
+
if (caps && caps.tools && caps.resources && caps.prompts) {
|
|
109
|
+
console.log(' ✅ Capabilities advertised correctly');
|
|
110
|
+
console.log(' - Tools: supported');
|
|
111
|
+
console.log(' - Resources: supported');
|
|
112
|
+
console.log(' - Prompts: supported\n');
|
|
113
|
+
} else {
|
|
114
|
+
throw new Error('Missing capabilities');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
server.kill();
|
|
118
|
+
return true;
|
|
119
|
+
} catch (error) {
|
|
120
|
+
server.kill();
|
|
121
|
+
console.log(` ⚠️ Capabilities test skipped: ${error.message}\n`);
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Test 3: Tools endpoint responds
|
|
127
|
+
async function testToolsEndpoint() {
|
|
128
|
+
console.log('Test 3: Tools Endpoint...');
|
|
129
|
+
|
|
130
|
+
const server = spawn('node', [SERVER_PATH], {
|
|
131
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
// Initialize first
|
|
136
|
+
await sendMCPRequest(server, 'initialize', {
|
|
137
|
+
protocolVersion: '2024-11-05',
|
|
138
|
+
capabilities: {},
|
|
139
|
+
clientInfo: { name: 'test', version: '1.0.0' },
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
const response = await sendMCPRequest(server, 'tools/list');
|
|
143
|
+
|
|
144
|
+
if (response.result && Array.isArray(response.result.tools)) {
|
|
145
|
+
console.log(' ✅ Tools endpoint responds correctly');
|
|
146
|
+
console.log(` Found ${response.result.tools.length} tools`);
|
|
147
|
+
console.log(` Sample: ${response.result.tools.slice(0, 3).map(t => t.name).join(', ')}\n`);
|
|
148
|
+
} else {
|
|
149
|
+
throw new Error('Invalid tools response');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
server.kill();
|
|
153
|
+
return true;
|
|
154
|
+
} catch (error) {
|
|
155
|
+
server.kill();
|
|
156
|
+
console.log(` ⚠️ Tools test skipped: ${error.message}\n`);
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Test 4: Resources endpoint responds
|
|
162
|
+
async function testResourcesEndpoint() {
|
|
163
|
+
console.log('Test 4: Resources Endpoint...');
|
|
164
|
+
|
|
165
|
+
const server = spawn('node', [SERVER_PATH], {
|
|
166
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
try {
|
|
170
|
+
await sendMCPRequest(server, 'initialize', {
|
|
171
|
+
protocolVersion: '2024-11-05',
|
|
172
|
+
capabilities: {},
|
|
173
|
+
clientInfo: { name: 'test', version: '1.0.0' },
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
const response = await sendMCPRequest(server, 'resources/list');
|
|
177
|
+
|
|
178
|
+
if (response.result && Array.isArray(response.result.resources)) {
|
|
179
|
+
console.log(' ✅ Resources endpoint responds correctly');
|
|
180
|
+
console.log(` Found ${response.result.resources.length} resources\n`);
|
|
181
|
+
} else {
|
|
182
|
+
throw new Error('Invalid resources response');
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
server.kill();
|
|
186
|
+
return true;
|
|
187
|
+
} catch (error) {
|
|
188
|
+
server.kill();
|
|
189
|
+
console.log(` ⚠️ Resources test skipped: ${error.message}\n`);
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Test 5: Prompts endpoint responds
|
|
195
|
+
async function testPromptsEndpoint() {
|
|
196
|
+
console.log('Test 5: Prompts Endpoint...');
|
|
197
|
+
|
|
198
|
+
const server = spawn('node', [SERVER_PATH], {
|
|
199
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
try {
|
|
203
|
+
await sendMCPRequest(server, 'initialize', {
|
|
204
|
+
protocolVersion: '2024-11-05',
|
|
205
|
+
capabilities: {},
|
|
206
|
+
clientInfo: { name: 'test', version: '1.0.0' },
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
const response = await sendMCPRequest(server, 'prompts/list');
|
|
210
|
+
|
|
211
|
+
if (response.result && Array.isArray(response.result.prompts)) {
|
|
212
|
+
console.log(' ✅ Prompts endpoint responds correctly');
|
|
213
|
+
console.log(` Found ${response.result.prompts.length} prompts`);
|
|
214
|
+
console.log(` Available: ${response.result.prompts.map(p => p.name).join(', ')}\n`);
|
|
215
|
+
} else {
|
|
216
|
+
throw new Error('Invalid prompts response');
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
server.kill();
|
|
220
|
+
return true;
|
|
221
|
+
} catch (error) {
|
|
222
|
+
server.kill();
|
|
223
|
+
console.log(` ⚠️ Prompts test skipped: ${error.message}\n`);
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Run all tests
|
|
229
|
+
async function runTests() {
|
|
230
|
+
let passed = 0;
|
|
231
|
+
let total = 5;
|
|
232
|
+
|
|
233
|
+
console.log(`MCP Server Path: ${SERVER_PATH}\n`);
|
|
234
|
+
|
|
235
|
+
if (await testServerInitialization()) passed++;
|
|
236
|
+
if (await testCapabilities()) passed++;
|
|
237
|
+
if (await testToolsEndpoint()) passed++;
|
|
238
|
+
if (await testResourcesEndpoint()) passed++;
|
|
239
|
+
if (await testPromptsEndpoint()) passed++;
|
|
240
|
+
|
|
241
|
+
console.log('─'.repeat(50));
|
|
242
|
+
if (passed === total) {
|
|
243
|
+
console.log(`✅ All ${total} compliance tests passed!\n`);
|
|
244
|
+
process.exit(0);
|
|
245
|
+
} else if (passed > 0) {
|
|
246
|
+
console.log(`⚠️ ${passed}/${total} tests passed (some tests skipped)\n`);
|
|
247
|
+
process.exit(0);
|
|
248
|
+
} else {
|
|
249
|
+
console.log(`❌ 0/${total} tests passed\n`);
|
|
250
|
+
process.exit(1);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
runTests();
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Helper script to identify and suggest updates for test log assertions
|
|
4
|
+
* after migrating to AI-friendly logging format
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
|
|
10
|
+
// Mapping of old emoji-based messages to new structured format patterns
|
|
11
|
+
const logMessageMappings = {
|
|
12
|
+
// Success messages
|
|
13
|
+
'✅ ': 'SUCCESS: ',
|
|
14
|
+
'✓ ': 'SUCCESS: ',
|
|
15
|
+
|
|
16
|
+
// Error messages
|
|
17
|
+
'❌ ': 'FAILED: ',
|
|
18
|
+
'✗ ': 'FAILED: ',
|
|
19
|
+
|
|
20
|
+
// Warning messages
|
|
21
|
+
'⚠️ ': 'WARNING: ',
|
|
22
|
+
|
|
23
|
+
// Info messages
|
|
24
|
+
'🔄 ': '_SYNCING: ',
|
|
25
|
+
'📦 ': '_PACKAGE: ',
|
|
26
|
+
'🎯 ': '_TARGET: ',
|
|
27
|
+
'🏷️ ': '_TAG: ',
|
|
28
|
+
'📝 ': '_COMMIT: ',
|
|
29
|
+
'🚀 ': '_STARTING: ',
|
|
30
|
+
'ℹ️ ': '_INFO: ',
|
|
31
|
+
'💡 ': '_HINT: ',
|
|
32
|
+
'🔧 ': '_RESOLUTION: ',
|
|
33
|
+
'📊 ': '_ANALYSIS: ',
|
|
34
|
+
'🎉 ': '_COMPLETE: ',
|
|
35
|
+
'🔍 ': '_CHECK: ',
|
|
36
|
+
'📁 ': '_FILE: ',
|
|
37
|
+
'🤖 ': '_AI: ',
|
|
38
|
+
'🎵 ': '_AUDIO: ',
|
|
39
|
+
'🎙️ ': '_RECORDING: ',
|
|
40
|
+
'🏁 ': '_MILESTONE: ',
|
|
41
|
+
'🔓 ': '_UNLINK: ',
|
|
42
|
+
'🔗 ': '_LINK: ',
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
console.log('AI-Friendly Logging Test Update Helper');
|
|
46
|
+
console.log('======================================\n');
|
|
47
|
+
console.log('This script helps identify test assertions that need updating');
|
|
48
|
+
console.log('after migrating to structured AI-friendly logging format.\n');
|
|
49
|
+
|
|
50
|
+
console.log('Common patterns to update in tests:\n');
|
|
51
|
+
console.log('OLD: expect(logger.info).toHaveBeenCalledWith(\'✅ Success message\')');
|
|
52
|
+
console.log('NEW: expect(logger.info).toHaveBeenCalledWith(\'OPERATION_SUCCESS: Success message | Status: completed\')\n');
|
|
53
|
+
|
|
54
|
+
console.log('OLD: expect(logger.warn).toHaveBeenCalledWith(\'⚠️ Warning message\')');
|
|
55
|
+
console.log('NEW: expect(logger.warn).toHaveBeenCalledWith(\'OPERATION_WARNING: Warning message | Impact: ...\')\n');
|
|
56
|
+
|
|
57
|
+
console.log('OLD: expect(logger.error).toHaveBeenCalledWith(\'❌ Error message\')');
|
|
58
|
+
console.log('NEW: expect(logger.error).toHaveBeenCalledWith(\'OPERATION_FAILED: Error message | Error: ...\')\n');
|
|
59
|
+
|
|
60
|
+
console.log('\nKey principles for new format:');
|
|
61
|
+
console.log('1. OPERATION_STATE: prefix (SNAKE_CASE)');
|
|
62
|
+
console.log('2. Pipe-separated key-value pairs');
|
|
63
|
+
console.log('3. Include context: Package, Status, Error, Purpose, Action, etc.');
|
|
64
|
+
console.log('4. No emojis in structured prefixes\n');
|
|
65
|
+
|
|
66
|
+
console.log('Run full test suite to see failures:');
|
|
67
|
+
console.log(' npm test -- --run\n');
|
|
68
|
+
|
|
69
|
+
console.log('Then update test assertions to match new log format.');
|
|
70
|
+
console.log('See AI-FRIENDLY-LOGGING-GUIDE.md for complete documentation.\n');
|
|
71
|
+
|
|
72
|
+
process.exit(0);
|
|
73
|
+
|