@gala-chain/launchpad-mcp-server 5.0.1-beta.1 → 5.0.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/MCP_TEST_ANALYSIS.md
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/generated/version.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAO,MAAM,kBAAkB,
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/generated/version.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAO,MAAM,kBAAkB,UAAU,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/generated/version.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEU,QAAA,kBAAkB,GAAG,
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/generated/version.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEU,QAAA,kBAAkB,GAAG,OAAO,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gala-chain/launchpad-mcp-server",
|
|
3
|
-
"version": "5.0.1
|
|
3
|
+
"version": "5.0.1",
|
|
4
4
|
"description": "MCP server for Gala Launchpad - 128 tools (pool management, event watchers, GSwap DEX trading, price history, token creation, wallet management, DEX pool discovery, liquidity positions, token locks/burns, locked token queries, composite pool data, cross-chain bridging, wrap/unwrap, key derivation) supporting optional wallet (read-only and full-access modes). Production-grade AI agent integration for Claude Desktop with comprehensive validation and 80%+ test coverage",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -18,11 +18,13 @@
|
|
|
18
18
|
"test:integration:coverage": "jest --config jest.integration.config.js --coverage",
|
|
19
19
|
"test:prompts": "npm run build && node src/scripts/test-all-prompts.ts",
|
|
20
20
|
"test:all": "npm run test && npm run test:integration && npm run test:prompts",
|
|
21
|
+
"validate:mcp-tests": "tsx scripts/validate-mcp-test-analysis.ts",
|
|
22
|
+
"prerelease": "npm run validate:mcp-tests && npm run test && npm run typecheck",
|
|
21
23
|
"typecheck": "tsc --noEmit",
|
|
22
24
|
"lint": "eslint src --ext .ts",
|
|
23
25
|
"lint:check": "eslint src --ext .ts",
|
|
24
26
|
"lint:fix": "eslint src --ext .ts --fix",
|
|
25
|
-
"prepublishOnly": "npm run build"
|
|
27
|
+
"prepublishOnly": "npm run validate:mcp-tests && npm run build"
|
|
26
28
|
},
|
|
27
29
|
"keywords": [
|
|
28
30
|
"mcp",
|
|
@@ -73,7 +75,7 @@
|
|
|
73
75
|
"dependencies": {
|
|
74
76
|
"@gala-chain/api": "^2.4.3",
|
|
75
77
|
"@gala-chain/connect": "^2.4.3",
|
|
76
|
-
"@gala-chain/launchpad-sdk": "5.0.1
|
|
78
|
+
"@gala-chain/launchpad-sdk": "5.0.1",
|
|
77
79
|
"@humanwhocodes/config-array": "^0.13.0",
|
|
78
80
|
"@modelcontextprotocol/sdk": "^0.5.0",
|
|
79
81
|
"axios": "^1.12.2",
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* MCP Test Analysis Validator
|
|
4
|
+
*
|
|
5
|
+
* This script parses MCP_TEST_ANALYSIS.md and FAILS if:
|
|
6
|
+
* 1. Any tools are marked as BUG or FAIL
|
|
7
|
+
* 2. The summary counts don't match the detailed tables
|
|
8
|
+
* 3. Pass rate is not 100% (excluding CONFIG-REQUIRED)
|
|
9
|
+
*
|
|
10
|
+
* Run this BEFORE any release to ensure no known bugs are shipped.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* npm run validate:mcp-tests
|
|
14
|
+
* npx tsx scripts/validate-mcp-test-analysis.ts
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import * as fs from 'fs';
|
|
18
|
+
import * as path from 'path';
|
|
19
|
+
|
|
20
|
+
interface CategoryStats {
|
|
21
|
+
name: string;
|
|
22
|
+
total: number;
|
|
23
|
+
pass: number;
|
|
24
|
+
fail: number;
|
|
25
|
+
skip: number;
|
|
26
|
+
bug: number;
|
|
27
|
+
configRequired: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface ValidationResult {
|
|
31
|
+
success: boolean;
|
|
32
|
+
errors: string[];
|
|
33
|
+
warnings: string[];
|
|
34
|
+
stats: {
|
|
35
|
+
totalTools: number;
|
|
36
|
+
totalPass: number;
|
|
37
|
+
totalFail: number;
|
|
38
|
+
totalBug: number;
|
|
39
|
+
totalSkip: number;
|
|
40
|
+
totalConfigRequired: number;
|
|
41
|
+
passRate: number;
|
|
42
|
+
};
|
|
43
|
+
categories: CategoryStats[];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function parseMarkdownFile(filePath: string): string {
|
|
47
|
+
if (!fs.existsSync(filePath)) {
|
|
48
|
+
throw new Error(`MCP_TEST_ANALYSIS.md not found at: ${filePath}`);
|
|
49
|
+
}
|
|
50
|
+
return fs.readFileSync(filePath, 'utf-8');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function extractSummaryTable(content: string): CategoryStats[] {
|
|
54
|
+
const categories: CategoryStats[] = [];
|
|
55
|
+
|
|
56
|
+
// Find the summary table
|
|
57
|
+
const summaryMatch = content.match(/\| Category \| Total \| Pass \| Fail \| Skip \| Config-Required \|[\s\S]*?\n\n/);
|
|
58
|
+
if (!summaryMatch) {
|
|
59
|
+
throw new Error('Could not find summary table in MCP_TEST_ANALYSIS.md');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const tableLines = summaryMatch[0].split('\n').filter(line => line.startsWith('|') && !line.includes('---'));
|
|
63
|
+
|
|
64
|
+
for (const line of tableLines) {
|
|
65
|
+
// Skip header row
|
|
66
|
+
if (line.includes('Category') || line.includes('TOTAL')) continue;
|
|
67
|
+
|
|
68
|
+
const cells = line.split('|').map(c => c.trim()).filter(Boolean);
|
|
69
|
+
if (cells.length >= 6) {
|
|
70
|
+
categories.push({
|
|
71
|
+
name: cells[0],
|
|
72
|
+
total: parseInt(cells[1], 10) || 0,
|
|
73
|
+
pass: parseInt(cells[2], 10) || 0,
|
|
74
|
+
fail: parseInt(cells[3], 10) || 0,
|
|
75
|
+
skip: parseInt(cells[4], 10) || 0,
|
|
76
|
+
bug: 0, // Not in summary table, check details
|
|
77
|
+
configRequired: parseInt(cells[5], 10) || 0,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return categories;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function countBugsInContent(content: string): number {
|
|
86
|
+
// Count explicit BUG markers in tool status column (| BUG | or | **BUG** |)
|
|
87
|
+
// Must be a standalone cell, not part of narrative text
|
|
88
|
+
const bugMatches = content.match(/\|\s*\*\*BUG\*\*\s*\||\|\s*BUG\s*\|/g);
|
|
89
|
+
return bugMatches ? bugMatches.length : 0;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function countFailsInContent(content: string): number {
|
|
93
|
+
// Count explicit FAIL markers in tool status column (| FAIL | or | **FAIL** |)
|
|
94
|
+
// Must be a standalone cell, not part of narrative text
|
|
95
|
+
const failMatches = content.match(/\|\s*\*\*FAIL\*\*\s*\||\|\s*FAIL\s*\|/g);
|
|
96
|
+
return failMatches ? failMatches.length : 0;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function countSkipsInContent(content: string): number {
|
|
100
|
+
// Count explicit SKIP markers in tool status column (| SKIP | or | **SKIP** |)
|
|
101
|
+
// Must be a standalone cell, not part of narrative text
|
|
102
|
+
const skipMatches = content.match(/\|\s*\*\*SKIP\*\*\s*\||\|\s*SKIP\s*\|/g);
|
|
103
|
+
return skipMatches ? skipMatches.length : 0;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function checkSectionHeaders(content: string): string[] {
|
|
107
|
+
const errors: string[] = [];
|
|
108
|
+
|
|
109
|
+
// Check for sections that mention BUG counts in headers
|
|
110
|
+
const sectionHeaders = content.match(/## [A-Z]+ \(\d+ tools?\).*(?:BUG|FAIL)/gi);
|
|
111
|
+
if (sectionHeaders) {
|
|
112
|
+
for (const header of sectionHeaders) {
|
|
113
|
+
errors.push(`Section header indicates bugs: "${header}"`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return errors;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function validateMcpTestAnalysis(): ValidationResult {
|
|
121
|
+
const filePath = path.join(__dirname, '..', 'MCP_TEST_ANALYSIS.md');
|
|
122
|
+
const content = parseMarkdownFile(filePath);
|
|
123
|
+
|
|
124
|
+
const errors: string[] = [];
|
|
125
|
+
const warnings: string[] = [];
|
|
126
|
+
|
|
127
|
+
// Parse summary table
|
|
128
|
+
const categories = extractSummaryTable(content);
|
|
129
|
+
|
|
130
|
+
// Count bugs and fails in detail sections
|
|
131
|
+
const totalBugsInContent = countBugsInContent(content);
|
|
132
|
+
const totalFailsInContent = countFailsInContent(content);
|
|
133
|
+
const totalSkipsInContent = countSkipsInContent(content);
|
|
134
|
+
|
|
135
|
+
// Check section headers for bug indicators
|
|
136
|
+
const headerErrors = checkSectionHeaders(content);
|
|
137
|
+
errors.push(...headerErrors);
|
|
138
|
+
|
|
139
|
+
// Calculate totals from summary table
|
|
140
|
+
const stats = {
|
|
141
|
+
totalTools: categories.reduce((sum, c) => sum + c.total, 0),
|
|
142
|
+
totalPass: categories.reduce((sum, c) => sum + c.pass, 0),
|
|
143
|
+
totalFail: categories.reduce((sum, c) => sum + c.fail, 0) + totalFailsInContent,
|
|
144
|
+
totalBug: totalBugsInContent,
|
|
145
|
+
totalSkip: categories.reduce((sum, c) => sum + c.skip, 0) + totalSkipsInContent,
|
|
146
|
+
totalConfigRequired: categories.reduce((sum, c) => sum + c.configRequired, 0),
|
|
147
|
+
passRate: 0,
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
// Calculate pass rate (excluding config-required)
|
|
151
|
+
const testableTools = stats.totalTools - stats.totalConfigRequired;
|
|
152
|
+
stats.passRate = testableTools > 0 ? (stats.totalPass / testableTools) * 100 : 0;
|
|
153
|
+
|
|
154
|
+
// CRITICAL VALIDATION: No bugs allowed!
|
|
155
|
+
if (stats.totalBug > 0) {
|
|
156
|
+
errors.push(`RELEASE BLOCKER: ${stats.totalBug} tool(s) marked as BUG - fix before release!`);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// CRITICAL VALIDATION: No fails allowed!
|
|
160
|
+
if (stats.totalFail > 0) {
|
|
161
|
+
errors.push(`RELEASE BLOCKER: ${stats.totalFail} tool(s) marked as FAIL - fix before release!`);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// WARNING: Skips should be documented
|
|
165
|
+
if (stats.totalSkip > 0) {
|
|
166
|
+
warnings.push(`${stats.totalSkip} tool(s) marked as SKIP - ensure these are intentionally skipped`);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// CRITICAL VALIDATION: Pass rate must be 100%
|
|
170
|
+
if (stats.passRate < 100 && testableTools > 0) {
|
|
171
|
+
errors.push(`RELEASE BLOCKER: Pass rate is ${stats.passRate.toFixed(1)}%, must be 100%`);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Check for inconsistencies between summary and content
|
|
175
|
+
const contentPassCount = (content.match(/\|\s*PASS\s*\|/gi) || []).length;
|
|
176
|
+
if (Math.abs(contentPassCount - stats.totalPass) > 5) { // Allow some tolerance for PASS in notes
|
|
177
|
+
warnings.push(`Potential inconsistency: Summary shows ${stats.totalPass} PASS, content has ~${contentPassCount} PASS markers`);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return {
|
|
181
|
+
success: errors.length === 0,
|
|
182
|
+
errors,
|
|
183
|
+
warnings,
|
|
184
|
+
stats,
|
|
185
|
+
categories,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Main execution
|
|
190
|
+
function main(): void {
|
|
191
|
+
console.log('');
|
|
192
|
+
console.log('========================================');
|
|
193
|
+
console.log(' MCP Test Analysis Validator');
|
|
194
|
+
console.log(' Release Gate Check');
|
|
195
|
+
console.log('========================================');
|
|
196
|
+
console.log('');
|
|
197
|
+
|
|
198
|
+
try {
|
|
199
|
+
const result = validateMcpTestAnalysis();
|
|
200
|
+
|
|
201
|
+
// Print stats
|
|
202
|
+
console.log('Summary:');
|
|
203
|
+
console.log(` Total Tools: ${result.stats.totalTools}`);
|
|
204
|
+
console.log(` Pass: ${result.stats.totalPass}`);
|
|
205
|
+
console.log(` Fail: ${result.stats.totalFail}`);
|
|
206
|
+
console.log(` Bug: ${result.stats.totalBug}`);
|
|
207
|
+
console.log(` Skip: ${result.stats.totalSkip}`);
|
|
208
|
+
console.log(` Config-Required: ${result.stats.totalConfigRequired}`);
|
|
209
|
+
console.log(` Pass Rate: ${result.stats.passRate.toFixed(1)}%`);
|
|
210
|
+
console.log('');
|
|
211
|
+
|
|
212
|
+
// Print warnings
|
|
213
|
+
if (result.warnings.length > 0) {
|
|
214
|
+
console.log('Warnings:');
|
|
215
|
+
for (const warning of result.warnings) {
|
|
216
|
+
console.log(` - ${warning}`);
|
|
217
|
+
}
|
|
218
|
+
console.log('');
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Print errors
|
|
222
|
+
if (result.errors.length > 0) {
|
|
223
|
+
console.log('ERRORS (RELEASE BLOCKED):');
|
|
224
|
+
for (const error of result.errors) {
|
|
225
|
+
console.log(` - ${error}`);
|
|
226
|
+
}
|
|
227
|
+
console.log('');
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Final result
|
|
231
|
+
if (result.success) {
|
|
232
|
+
console.log('========================================');
|
|
233
|
+
console.log(' VALIDATION PASSED');
|
|
234
|
+
console.log(' No known bugs - safe to release!');
|
|
235
|
+
console.log('========================================');
|
|
236
|
+
process.exit(0);
|
|
237
|
+
} else {
|
|
238
|
+
console.log('========================================');
|
|
239
|
+
console.log(' VALIDATION FAILED');
|
|
240
|
+
console.log(' DO NOT RELEASE WITH KNOWN BUGS!');
|
|
241
|
+
console.log('========================================');
|
|
242
|
+
process.exit(1);
|
|
243
|
+
}
|
|
244
|
+
} catch (error) {
|
|
245
|
+
console.error('Validation error:', error);
|
|
246
|
+
process.exit(1);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
main();
|