@ace-sdk/mcp 1.0.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/README.md +60 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +590 -0
- package/dist/index.js.map +1 -0
- package/dist/services/initialization.d.ts +128 -0
- package/dist/services/initialization.d.ts.map +1 -0
- package/dist/services/initialization.js +874 -0
- package/dist/services/initialization.js.map +1 -0
- package/dist/services/language-detector.d.ts +63 -0
- package/dist/services/language-detector.d.ts.map +1 -0
- package/dist/services/language-detector.js +123 -0
- package/dist/services/language-detector.js.map +1 -0
- package/dist/tools/definitions.d.ts +13 -0
- package/dist/tools/definitions.d.ts.map +1 -0
- package/dist/tools/definitions.js +351 -0
- package/dist/tools/definitions.js.map +1 -0
- package/dist/utils/version-checker.d.ts +27 -0
- package/dist/utils/version-checker.d.ts.map +1 -0
- package/dist/utils/version-checker.js +30 -0
- package/dist/utils/version-checker.js.map +1 -0
- package/package.json +58 -0
package/README.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# @ace-sdk/mcp
|
|
2
|
+
|
|
3
|
+
MCP Server for ACE pattern learning - works with any MCP-compatible client.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@ace-sdk/mcp)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install @ace-sdk/mcp
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Features
|
|
15
|
+
|
|
16
|
+
- **15 MCP Tools**: Full ACE functionality as MCP tools
|
|
17
|
+
- **Client Agnostic**: Works with Claude Code, Cursor, Cline, VSCode Copilot, or any MCP client
|
|
18
|
+
- **Auto Learning**: Automatic pattern capture from coding sessions
|
|
19
|
+
- **Semantic Search**: Find relevant patterns while coding
|
|
20
|
+
|
|
21
|
+
## MCP Client Setup
|
|
22
|
+
|
|
23
|
+
Add to your MCP configuration (e.g., `.mcp.json`):
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"mcpServers": {
|
|
28
|
+
"ace-pattern-learning": {
|
|
29
|
+
"command": "npx",
|
|
30
|
+
"args": ["@ace-sdk/mcp"],
|
|
31
|
+
"env": {
|
|
32
|
+
"ACE_SERVER_URL": "https://ace-api.code-engine.app",
|
|
33
|
+
"ACE_API_TOKEN": "your-token",
|
|
34
|
+
"ACE_ORG_ID": "your-org",
|
|
35
|
+
"ACE_PROJECT_ID": "your-project"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Available Tools
|
|
43
|
+
|
|
44
|
+
| Tool | Description |
|
|
45
|
+
|------|-------------|
|
|
46
|
+
| `ace_get_playbook` | Fetch learned patterns |
|
|
47
|
+
| `ace_search` | Semantic search for patterns |
|
|
48
|
+
| `ace_learn` | Submit learning from execution |
|
|
49
|
+
| `ace_bootstrap` | Initialize playbook from codebase |
|
|
50
|
+
| `ace_status` | Get playbook statistics |
|
|
51
|
+
| `ace_delta` | Manual pattern management |
|
|
52
|
+
| `ace_cache_clear` | Clear local caches |
|
|
53
|
+
|
|
54
|
+
## Documentation
|
|
55
|
+
|
|
56
|
+
Full documentation: [packages/mcp/docs](./docs)
|
|
57
|
+
|
|
58
|
+
## License
|
|
59
|
+
|
|
60
|
+
MIT Š [CE.NET Team](mailto:ace@code-engine.net)
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* ACE MCP Server v1.0.0
|
|
4
|
+
*
|
|
5
|
+
* Model Context Protocol server for ACE (Agentic Context Engineering) pattern learning.
|
|
6
|
+
* Uses @ace-sdk/core for HTTP client, caching, and configuration.
|
|
7
|
+
*
|
|
8
|
+
* Server-side intelligence: Reflector + Curator run on ACE server
|
|
9
|
+
* Client responsibility: Send traces, retrieve playbooks
|
|
10
|
+
*
|
|
11
|
+
* Compatible with: Claude Code, Cursor, Cline, any MCP client
|
|
12
|
+
*
|
|
13
|
+
* @package @ace-sdk/mcp
|
|
14
|
+
*/
|
|
15
|
+
export declare const VERSION = "1.0.0";
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;GAYG;AAwBH,eAAO,MAAM,OAAO,UAAc,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,590 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* ACE MCP Server v1.0.0
|
|
4
|
+
*
|
|
5
|
+
* Model Context Protocol server for ACE (Agentic Context Engineering) pattern learning.
|
|
6
|
+
* Uses @ace-sdk/core for HTTP client, caching, and configuration.
|
|
7
|
+
*
|
|
8
|
+
* Server-side intelligence: Reflector + Curator run on ACE server
|
|
9
|
+
* Client responsibility: Send traces, retrieve playbooks
|
|
10
|
+
*
|
|
11
|
+
* Compatible with: Claude Code, Cursor, Cline, any MCP client
|
|
12
|
+
*
|
|
13
|
+
* @package @ace-sdk/mcp
|
|
14
|
+
*/
|
|
15
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
16
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
17
|
+
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
18
|
+
import { AceClient, loadConfig, THOROUGHNESS_PRESETS } from '@ace-sdk/core';
|
|
19
|
+
import { tools } from './tools/definitions.js';
|
|
20
|
+
import { InitializationService } from './services/initialization.js';
|
|
21
|
+
import { checkVersionCompatibility, MCP_VERSION } from './utils/version-checker.js';
|
|
22
|
+
// Re-export version
|
|
23
|
+
export const VERSION = MCP_VERSION;
|
|
24
|
+
// Initialize configuration
|
|
25
|
+
const config = loadConfig();
|
|
26
|
+
if (!config.serverUrl || !config.apiToken || !config.projectId) {
|
|
27
|
+
console.error('â Failed to load configuration: missing required fields');
|
|
28
|
+
console.error(' Required: serverUrl, apiToken, projectId');
|
|
29
|
+
console.error(' Run "ace-mcp" with ACE_SERVER_URL, ACE_API_TOKEN, ACE_PROJECT_ID environment variables');
|
|
30
|
+
console.error(' Or configure ~/.ace/config.json');
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
// Create AceClient from @ace-sdk/core
|
|
34
|
+
const aceClient = new AceClient(config);
|
|
35
|
+
// Create initialization service for bootstrap
|
|
36
|
+
const initializationService = new InitializationService();
|
|
37
|
+
// Check version compatibility (async, non-blocking)
|
|
38
|
+
let versionStatus = null;
|
|
39
|
+
checkVersionCompatibility().then(status => {
|
|
40
|
+
versionStatus = status;
|
|
41
|
+
}).catch(error => {
|
|
42
|
+
console.error('â ī¸ Version check failed (non-critical):', error.message);
|
|
43
|
+
});
|
|
44
|
+
// Create MCP server (NO SAMPLING - works with all MCP clients!)
|
|
45
|
+
const server = new Server({
|
|
46
|
+
name: 'ace-pattern-learning',
|
|
47
|
+
version: VERSION
|
|
48
|
+
}, {
|
|
49
|
+
capabilities: {
|
|
50
|
+
tools: {} // Just tools, no sampling required
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
// Register handlers
|
|
54
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
55
|
+
return { tools };
|
|
56
|
+
});
|
|
57
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
58
|
+
const { name, arguments: args } = request.params;
|
|
59
|
+
try {
|
|
60
|
+
switch (name) {
|
|
61
|
+
// ========================================================================
|
|
62
|
+
// Configuration Tools
|
|
63
|
+
// ========================================================================
|
|
64
|
+
case 'ace_save_config': {
|
|
65
|
+
const { serverUrl, apiToken, projectId } = args;
|
|
66
|
+
console.error('đž Saving configuration...');
|
|
67
|
+
// Save config to disk
|
|
68
|
+
const fs = await import('fs/promises');
|
|
69
|
+
const os = await import('os');
|
|
70
|
+
const path = await import('path');
|
|
71
|
+
const configDir = path.join(os.homedir(), '.ace');
|
|
72
|
+
const configPath = path.join(configDir, 'config.json');
|
|
73
|
+
await fs.mkdir(configDir, { recursive: true });
|
|
74
|
+
// Read existing config to preserve orgs section
|
|
75
|
+
let existingConfig = {};
|
|
76
|
+
try {
|
|
77
|
+
const existingContent = await fs.readFile(configPath, 'utf8');
|
|
78
|
+
existingConfig = JSON.parse(existingContent);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// File doesn't exist, start fresh
|
|
82
|
+
}
|
|
83
|
+
const newConfig = {
|
|
84
|
+
...existingConfig,
|
|
85
|
+
serverUrl,
|
|
86
|
+
apiToken,
|
|
87
|
+
projectId
|
|
88
|
+
};
|
|
89
|
+
await fs.writeFile(configPath, JSON.stringify(newConfig, null, 2), 'utf8');
|
|
90
|
+
return {
|
|
91
|
+
content: [{
|
|
92
|
+
type: 'text',
|
|
93
|
+
text: JSON.stringify({
|
|
94
|
+
success: true,
|
|
95
|
+
message: 'Configuration saved to ~/.ace/config.json',
|
|
96
|
+
config: { serverUrl, projectId }
|
|
97
|
+
}, null, 2)
|
|
98
|
+
}]
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
case 'ace_get_config': {
|
|
102
|
+
console.error('đ Fetching server configuration...');
|
|
103
|
+
const serverConfig = await aceClient.getConfig();
|
|
104
|
+
return {
|
|
105
|
+
content: [{
|
|
106
|
+
type: 'text',
|
|
107
|
+
text: JSON.stringify(serverConfig, null, 2)
|
|
108
|
+
}]
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
case 'ace_set_config': {
|
|
112
|
+
const { scope, ...updates } = args;
|
|
113
|
+
if (!scope) {
|
|
114
|
+
return {
|
|
115
|
+
content: [{
|
|
116
|
+
type: 'text',
|
|
117
|
+
text: JSON.stringify({
|
|
118
|
+
error: 'Missing required parameter',
|
|
119
|
+
message: 'The "scope" parameter is required',
|
|
120
|
+
hint: 'Use scope="project" for Claude Code CLI'
|
|
121
|
+
}, null, 2)
|
|
122
|
+
}],
|
|
123
|
+
isError: true
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
if (scope !== 'project') {
|
|
127
|
+
return {
|
|
128
|
+
content: [{
|
|
129
|
+
type: 'text',
|
|
130
|
+
text: JSON.stringify({
|
|
131
|
+
error: 'Invalid scope',
|
|
132
|
+
message: 'Claude Code CLI only supports scope="project"',
|
|
133
|
+
hint: 'Org-level config must be set via website dashboard'
|
|
134
|
+
}, null, 2)
|
|
135
|
+
}],
|
|
136
|
+
isError: true
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
console.error('âī¸ Updating server configuration...');
|
|
140
|
+
const result = await aceClient.updateConfig(updates, scope);
|
|
141
|
+
return {
|
|
142
|
+
content: [{
|
|
143
|
+
type: 'text',
|
|
144
|
+
text: `Configuration updated successfully:\n${JSON.stringify(result, null, 2)}`
|
|
145
|
+
}]
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
case 'ace_reset_config': {
|
|
149
|
+
const { scope } = args;
|
|
150
|
+
if (!scope) {
|
|
151
|
+
return {
|
|
152
|
+
content: [{
|
|
153
|
+
type: 'text',
|
|
154
|
+
text: JSON.stringify({
|
|
155
|
+
error: 'Missing required parameter',
|
|
156
|
+
message: 'The "scope" parameter is required',
|
|
157
|
+
hint: 'Use scope="project" for Claude Code CLI'
|
|
158
|
+
}, null, 2)
|
|
159
|
+
}],
|
|
160
|
+
isError: true
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
if (scope !== 'project') {
|
|
164
|
+
return {
|
|
165
|
+
content: [{
|
|
166
|
+
type: 'text',
|
|
167
|
+
text: JSON.stringify({
|
|
168
|
+
error: 'Invalid scope',
|
|
169
|
+
message: 'Claude Code CLI only supports scope="project"',
|
|
170
|
+
hint: 'Org-level config must be set via website dashboard'
|
|
171
|
+
}, null, 2)
|
|
172
|
+
}],
|
|
173
|
+
isError: true
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
console.error('đ Resetting project configuration to defaults...');
|
|
177
|
+
const result = await aceClient.resetConfig(scope);
|
|
178
|
+
return {
|
|
179
|
+
content: [{
|
|
180
|
+
type: 'text',
|
|
181
|
+
text: `Configuration reset successfully:\n${JSON.stringify(result, null, 2)}`
|
|
182
|
+
}]
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
// ========================================================================
|
|
186
|
+
// Playbook Operations
|
|
187
|
+
// ========================================================================
|
|
188
|
+
case 'ace_get_playbook': {
|
|
189
|
+
const { section, min_helpful, include_metadata } = args;
|
|
190
|
+
console.error('đ Fetching playbook from server...');
|
|
191
|
+
const response = await aceClient.getPlaybook({ include_metadata });
|
|
192
|
+
let playbook = response.playbook;
|
|
193
|
+
// Client-side filtering if requested
|
|
194
|
+
if (section) {
|
|
195
|
+
playbook = {
|
|
196
|
+
strategies_and_hard_rules: section === 'strategies_and_hard_rules' ? playbook.strategies_and_hard_rules : [],
|
|
197
|
+
useful_code_snippets: section === 'useful_code_snippets' ? playbook.useful_code_snippets : [],
|
|
198
|
+
troubleshooting_and_pitfalls: section === 'troubleshooting_and_pitfalls' ? playbook.troubleshooting_and_pitfalls : [],
|
|
199
|
+
apis_to_use: section === 'apis_to_use' ? playbook.apis_to_use : []
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
if (min_helpful !== undefined) {
|
|
203
|
+
for (const key of Object.keys(playbook)) {
|
|
204
|
+
playbook[key] = playbook[key].filter((b) => (b.helpful || 0) >= min_helpful);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
const result = { playbook };
|
|
208
|
+
if (response.metadata) {
|
|
209
|
+
result.metadata = response.metadata;
|
|
210
|
+
}
|
|
211
|
+
return {
|
|
212
|
+
content: [{
|
|
213
|
+
type: 'text',
|
|
214
|
+
text: JSON.stringify(result, null, 2)
|
|
215
|
+
}]
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
case 'ace_search': {
|
|
219
|
+
const { query, section, threshold, include_metadata } = args;
|
|
220
|
+
console.error(`đ Searching for patterns: "${query}"`);
|
|
221
|
+
// Fetch config if threshold not specified
|
|
222
|
+
let searchThreshold = threshold;
|
|
223
|
+
if (!searchThreshold) {
|
|
224
|
+
const serverConfig = await aceClient.getConfig();
|
|
225
|
+
searchThreshold = serverConfig.constitution_threshold || 0.85;
|
|
226
|
+
console.error(`đ Using dynamic threshold from config: ${searchThreshold}`);
|
|
227
|
+
}
|
|
228
|
+
const response = await aceClient.searchPatterns({
|
|
229
|
+
query,
|
|
230
|
+
section,
|
|
231
|
+
threshold: searchThreshold,
|
|
232
|
+
include_metadata
|
|
233
|
+
});
|
|
234
|
+
const result = {
|
|
235
|
+
query,
|
|
236
|
+
threshold: response.threshold,
|
|
237
|
+
results: response.similar_patterns,
|
|
238
|
+
count: response.count,
|
|
239
|
+
message: `Found ${response.count} patterns matching "${query}"`
|
|
240
|
+
};
|
|
241
|
+
if (response.metadata) {
|
|
242
|
+
result.metadata = response.metadata;
|
|
243
|
+
}
|
|
244
|
+
return {
|
|
245
|
+
content: [{
|
|
246
|
+
type: 'text',
|
|
247
|
+
text: JSON.stringify(result, null, 2)
|
|
248
|
+
}]
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
case 'ace_top_patterns': {
|
|
252
|
+
const { section, limit, min_helpful } = args;
|
|
253
|
+
console.error('â Fetching top patterns...');
|
|
254
|
+
const results = await aceClient.getTopPatterns({
|
|
255
|
+
section,
|
|
256
|
+
limit: limit || 10,
|
|
257
|
+
min_helpful: min_helpful || 0
|
|
258
|
+
});
|
|
259
|
+
return {
|
|
260
|
+
content: [{
|
|
261
|
+
type: 'text',
|
|
262
|
+
text: JSON.stringify({
|
|
263
|
+
section: section || 'all',
|
|
264
|
+
results,
|
|
265
|
+
count: results.length,
|
|
266
|
+
message: `Retrieved ${results.length} top-rated patterns`
|
|
267
|
+
}, null, 2)
|
|
268
|
+
}]
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
case 'ace_clear': {
|
|
272
|
+
const { confirm } = args;
|
|
273
|
+
if (!confirm) {
|
|
274
|
+
throw new Error('Must set confirm=true to clear playbook');
|
|
275
|
+
}
|
|
276
|
+
console.error('đī¸ Clearing playbook...');
|
|
277
|
+
await aceClient.clearPlaybook();
|
|
278
|
+
aceClient.invalidateCache();
|
|
279
|
+
return {
|
|
280
|
+
content: [{
|
|
281
|
+
type: 'text',
|
|
282
|
+
text: JSON.stringify({
|
|
283
|
+
success: true,
|
|
284
|
+
message: 'Playbook cleared successfully'
|
|
285
|
+
}, null, 2)
|
|
286
|
+
}]
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
case 'ace_batch_get': {
|
|
290
|
+
const { pattern_ids } = args;
|
|
291
|
+
if (!Array.isArray(pattern_ids) || pattern_ids.length === 0) {
|
|
292
|
+
return {
|
|
293
|
+
content: [{
|
|
294
|
+
type: 'text',
|
|
295
|
+
text: 'Error: pattern_ids must be a non-empty array'
|
|
296
|
+
}]
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
console.error(`đĻ Batch fetching ${pattern_ids.length} patterns...`);
|
|
300
|
+
const result = await aceClient.batchGetPatterns(pattern_ids);
|
|
301
|
+
return {
|
|
302
|
+
content: [{
|
|
303
|
+
type: 'text',
|
|
304
|
+
text: JSON.stringify(result, null, 2)
|
|
305
|
+
}]
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
case 'ace_delta': {
|
|
309
|
+
const { operation, bullets } = args;
|
|
310
|
+
console.error(`đ Applying delta operation: ${operation}...`);
|
|
311
|
+
for (const bullet of bullets) {
|
|
312
|
+
await aceClient.applyDelta({
|
|
313
|
+
type: operation.toUpperCase(),
|
|
314
|
+
section: bullet.section,
|
|
315
|
+
content: bullet.content,
|
|
316
|
+
bullet_id: bullet.id,
|
|
317
|
+
helpful_delta: bullet.helpful,
|
|
318
|
+
harmful_delta: bullet.harmful,
|
|
319
|
+
evidence: bullet.evidence
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
aceClient.invalidateCache();
|
|
323
|
+
return {
|
|
324
|
+
content: [{
|
|
325
|
+
type: 'text',
|
|
326
|
+
text: JSON.stringify({
|
|
327
|
+
success: true,
|
|
328
|
+
operation,
|
|
329
|
+
bullets_affected: bullets.length,
|
|
330
|
+
message: `Successfully applied ${operation} operation to ${bullets.length} bullet(s)`
|
|
331
|
+
}, null, 2)
|
|
332
|
+
}]
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
// ========================================================================
|
|
336
|
+
// Learning & Bootstrap
|
|
337
|
+
// ========================================================================
|
|
338
|
+
case 'ace_learn': {
|
|
339
|
+
const { task, trajectory, success, output, error, playbook_used } = args;
|
|
340
|
+
console.error('đ¤ Sending execution trace to server...');
|
|
341
|
+
// Convert string array to TrajectoryStep array if needed
|
|
342
|
+
const formattedTrajectory = trajectory.map((step, index) => {
|
|
343
|
+
if (typeof step === 'string') {
|
|
344
|
+
return {
|
|
345
|
+
step: index + 1,
|
|
346
|
+
action: step,
|
|
347
|
+
args: {},
|
|
348
|
+
result: 'Completed'
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
return step;
|
|
352
|
+
});
|
|
353
|
+
const trace = {
|
|
354
|
+
task,
|
|
355
|
+
trajectory: formattedTrajectory,
|
|
356
|
+
result: { success, output, error },
|
|
357
|
+
playbook_used: playbook_used || [],
|
|
358
|
+
timestamp: new Date().toISOString()
|
|
359
|
+
};
|
|
360
|
+
try {
|
|
361
|
+
const result = await aceClient.storeExecutionTrace(trace);
|
|
362
|
+
aceClient.invalidateCache();
|
|
363
|
+
console.error('â
Execution trace stored. Server is analyzing...');
|
|
364
|
+
return {
|
|
365
|
+
content: [{
|
|
366
|
+
type: 'text',
|
|
367
|
+
text: JSON.stringify({
|
|
368
|
+
success: true,
|
|
369
|
+
message: 'Execution trace stored successfully. Server-side Reflector and Curator will process asynchronously.',
|
|
370
|
+
task,
|
|
371
|
+
timestamp: trace.timestamp,
|
|
372
|
+
analysis_triggered: result.analysis_performed || false,
|
|
373
|
+
learning_statistics: result.learning_statistics
|
|
374
|
+
}, null, 2)
|
|
375
|
+
}]
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
catch (err) {
|
|
379
|
+
console.error('â Error storing trace:', err);
|
|
380
|
+
return {
|
|
381
|
+
content: [{
|
|
382
|
+
type: 'text',
|
|
383
|
+
text: JSON.stringify({
|
|
384
|
+
success: false,
|
|
385
|
+
error: err.message || 'Failed to store execution trace'
|
|
386
|
+
}, null, 2)
|
|
387
|
+
}],
|
|
388
|
+
isError: true
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
case 'ace_bootstrap': {
|
|
393
|
+
const { mode, thoroughness, repo_path, max_files, commit_limit, days_back, merge_with_existing: _mergeWithExisting } = args;
|
|
394
|
+
const thoroughnessLevel = thoroughness || 'medium';
|
|
395
|
+
const preset = THOROUGHNESS_PRESETS[thoroughnessLevel];
|
|
396
|
+
const effectiveMaxFiles = max_files ?? preset.max_files;
|
|
397
|
+
const effectiveCommitLimit = commit_limit ?? preset.commit_limit;
|
|
398
|
+
const effectiveDaysBack = days_back ?? preset.days_back;
|
|
399
|
+
const analysisMode = mode || 'hybrid';
|
|
400
|
+
const projectPath = repo_path || process.cwd();
|
|
401
|
+
console.error(`đ Bootstrapping playbook (mode: ${analysisMode}, thoroughness: ${thoroughnessLevel})...`);
|
|
402
|
+
console.error(` Files: ${effectiveMaxFiles === -1 ? 'unlimited' : effectiveMaxFiles}, Commits: ${effectiveCommitLimit}, Days: ${effectiveDaysBack}`);
|
|
403
|
+
try {
|
|
404
|
+
console.error('đ Running local codebase analysis...');
|
|
405
|
+
const playbook = await initializationService.initializeFromCodebase(projectPath, {
|
|
406
|
+
mode: analysisMode,
|
|
407
|
+
commitLimit: effectiveCommitLimit,
|
|
408
|
+
daysBack: effectiveDaysBack,
|
|
409
|
+
maxFiles: effectiveMaxFiles
|
|
410
|
+
});
|
|
411
|
+
const allBullets = [
|
|
412
|
+
...playbook.strategies_and_hard_rules,
|
|
413
|
+
...playbook.useful_code_snippets,
|
|
414
|
+
...playbook.troubleshooting_and_pitfalls,
|
|
415
|
+
...playbook.apis_to_use
|
|
416
|
+
];
|
|
417
|
+
console.error(`â
Discovered ${allBullets.length} patterns locally`);
|
|
418
|
+
if (allBullets.length === 0) {
|
|
419
|
+
console.error('â ī¸ No patterns found - playbook is empty');
|
|
420
|
+
return {
|
|
421
|
+
content: [{
|
|
422
|
+
type: 'text',
|
|
423
|
+
text: JSON.stringify({
|
|
424
|
+
success: true,
|
|
425
|
+
patternsExtracted: 0,
|
|
426
|
+
message: 'No patterns found in codebase. Try working on real tasks to build the playbook through online learning.'
|
|
427
|
+
}, null, 2)
|
|
428
|
+
}]
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
// Build code blocks for bootstrap endpoint
|
|
432
|
+
const codeBlocks = [];
|
|
433
|
+
for (const snippet of playbook.useful_code_snippets) {
|
|
434
|
+
if (snippet.evidence && snippet.evidence.length > 0) {
|
|
435
|
+
codeBlocks.push(`File: ${snippet.evidence[0]}\n\n${snippet.content}`);
|
|
436
|
+
}
|
|
437
|
+
else {
|
|
438
|
+
codeBlocks.push(snippet.content);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
for (const pattern of playbook.troubleshooting_and_pitfalls) {
|
|
442
|
+
if (pattern.content.length > 100) {
|
|
443
|
+
codeBlocks.push(pattern.content);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
for (const pattern of playbook.strategies_and_hard_rules) {
|
|
447
|
+
if (pattern.content.length > 100) {
|
|
448
|
+
codeBlocks.push(pattern.content);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
for (const pattern of playbook.apis_to_use) {
|
|
452
|
+
if (pattern.content.length > 100) {
|
|
453
|
+
codeBlocks.push(pattern.content);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
console.error(`đ¤ Sending ${codeBlocks.length} code blocks to ACE server for bootstrap...`);
|
|
457
|
+
const bootstrapResult = await aceClient.bootstrap({
|
|
458
|
+
mode: analysisMode,
|
|
459
|
+
code_blocks: codeBlocks,
|
|
460
|
+
metadata: {
|
|
461
|
+
blocks_extracted: codeBlocks.length,
|
|
462
|
+
thoroughness: thoroughness || 'medium',
|
|
463
|
+
file_extensions: []
|
|
464
|
+
}
|
|
465
|
+
});
|
|
466
|
+
aceClient.invalidateCache();
|
|
467
|
+
console.error(`â
Bootstrap complete: ${bootstrapResult.blocks_received} blocks â ${bootstrapResult.patterns_extracted} patterns (${bootstrapResult.compression_percentage}% compression)`);
|
|
468
|
+
return {
|
|
469
|
+
content: [{
|
|
470
|
+
type: 'text',
|
|
471
|
+
text: JSON.stringify({
|
|
472
|
+
success: true,
|
|
473
|
+
mode: analysisMode,
|
|
474
|
+
blocks_sent: bootstrapResult.blocks_received,
|
|
475
|
+
patterns_extracted: bootstrapResult.patterns_extracted,
|
|
476
|
+
compression_percentage: bootstrapResult.compression_percentage,
|
|
477
|
+
breakdown: bootstrapResult.by_section,
|
|
478
|
+
average_confidence: bootstrapResult.average_confidence,
|
|
479
|
+
analysis_time_seconds: bootstrapResult.analysis_time_seconds,
|
|
480
|
+
message: `Bootstrap complete! Sent ${bootstrapResult.blocks_received} code blocks â Server extracted ${bootstrapResult.patterns_extracted} unique patterns (${bootstrapResult.compression_percentage}% compression via semantic deduplication)`,
|
|
481
|
+
next_steps: 'Use /ace-patterns to view the deduplicated playbook.'
|
|
482
|
+
}, null, 2)
|
|
483
|
+
}]
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
catch (err) {
|
|
487
|
+
console.error('â Error during bootstrap:', err);
|
|
488
|
+
return {
|
|
489
|
+
content: [{
|
|
490
|
+
type: 'text',
|
|
491
|
+
text: JSON.stringify({
|
|
492
|
+
success: false,
|
|
493
|
+
error: err.message || 'Failed to bootstrap playbook',
|
|
494
|
+
stack: err.stack
|
|
495
|
+
}, null, 2)
|
|
496
|
+
}],
|
|
497
|
+
isError: true
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
// ========================================================================
|
|
502
|
+
// Utilities
|
|
503
|
+
// ========================================================================
|
|
504
|
+
case 'ace_status': {
|
|
505
|
+
console.error('đ Fetching status from server...');
|
|
506
|
+
const status = await aceClient.getAnalytics();
|
|
507
|
+
return {
|
|
508
|
+
content: [{
|
|
509
|
+
type: 'text',
|
|
510
|
+
text: JSON.stringify(status, null, 2)
|
|
511
|
+
}]
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
case 'ace_version_status': {
|
|
515
|
+
console.error('đ Checking version compatibility...');
|
|
516
|
+
if (!versionStatus) {
|
|
517
|
+
versionStatus = await checkVersionCompatibility();
|
|
518
|
+
}
|
|
519
|
+
return {
|
|
520
|
+
content: [{
|
|
521
|
+
type: 'text',
|
|
522
|
+
text: JSON.stringify(versionStatus, null, 2)
|
|
523
|
+
}]
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
case 'ace_cache_clear': {
|
|
527
|
+
const { cache_type } = args;
|
|
528
|
+
const cacheType = cache_type || 'all';
|
|
529
|
+
console.error(`đī¸ Clearing ${cacheType} cache...`);
|
|
530
|
+
if (cacheType === 'ram' || cacheType === 'all') {
|
|
531
|
+
aceClient.invalidateCache();
|
|
532
|
+
aceClient.clearConfigCache();
|
|
533
|
+
console.error('â
RAM cache cleared (playbook + config)');
|
|
534
|
+
}
|
|
535
|
+
if (cacheType === 'sqlite' || cacheType === 'all') {
|
|
536
|
+
const localCache = aceClient.getLocalCache();
|
|
537
|
+
if (localCache) {
|
|
538
|
+
localCache.clear();
|
|
539
|
+
console.error('â
SQLite cache cleared');
|
|
540
|
+
}
|
|
541
|
+
else {
|
|
542
|
+
console.error('âšī¸ SQLite cache not available (skipped)');
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
return {
|
|
546
|
+
content: [{
|
|
547
|
+
type: 'text',
|
|
548
|
+
text: JSON.stringify({
|
|
549
|
+
success: true,
|
|
550
|
+
cache_type: cacheType,
|
|
551
|
+
message: `${cacheType.toUpperCase()} cache cleared successfully`
|
|
552
|
+
}, null, 2)
|
|
553
|
+
}]
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
default:
|
|
557
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
catch (err) {
|
|
561
|
+
console.error(`â Error in ${name}:`, err);
|
|
562
|
+
return {
|
|
563
|
+
content: [{
|
|
564
|
+
type: 'text',
|
|
565
|
+
text: JSON.stringify({
|
|
566
|
+
success: false,
|
|
567
|
+
error: err.message || String(err)
|
|
568
|
+
}, null, 2)
|
|
569
|
+
}],
|
|
570
|
+
isError: true
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
});
|
|
574
|
+
// Start server
|
|
575
|
+
async function main() {
|
|
576
|
+
const transport = new StdioServerTransport();
|
|
577
|
+
await server.connect(transport);
|
|
578
|
+
console.error(`â
ACE MCP Server v${VERSION} started`);
|
|
579
|
+
console.error('đ Server:', config.serverUrl);
|
|
580
|
+
console.error('đ Project:', config.projectId);
|
|
581
|
+
if (config.orgs && Object.keys(config.orgs).length > 0) {
|
|
582
|
+
console.error('đ Multi-org:', `${Object.keys(config.orgs).length} organization(s) configured`);
|
|
583
|
+
}
|
|
584
|
+
console.error('đ Universal MCP compatibility (no sampling required)');
|
|
585
|
+
}
|
|
586
|
+
main().catch((error) => {
|
|
587
|
+
console.error('â Fatal error:', error);
|
|
588
|
+
process.exit(1);
|
|
589
|
+
});
|
|
590
|
+
//# sourceMappingURL=index.js.map
|