ucn 3.8.10 → 3.8.11
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/server.js +22 -16
- package/package.json +1 -1
package/mcp/server.js
CHANGED
|
@@ -114,12 +114,17 @@ const server = new McpServer({
|
|
|
114
114
|
// TOOL HELPERS
|
|
115
115
|
// ============================================================================
|
|
116
116
|
|
|
117
|
-
const DEFAULT_OUTPUT_CHARS = 10000; // ~2.5K tokens —
|
|
117
|
+
const DEFAULT_OUTPUT_CHARS = 10000; // ~2.5K tokens — targeted commands (about, context, smart, etc.)
|
|
118
|
+
const BROAD_OUTPUT_CHARS = 3000; // ~750 tokens — broad commands where truncated listings are useless
|
|
118
119
|
const MAX_OUTPUT_CHARS = 100000; // hard ceiling even with max_chars override
|
|
119
120
|
|
|
121
|
+
// Broad commands: output is project-wide, truncation means you need a filter, not more text
|
|
122
|
+
const BROAD_COMMANDS = new Set(['toc', 'entrypoints', 'diff_impact', 'affected_tests', 'deadcode', 'usages']);
|
|
123
|
+
|
|
120
124
|
function toolResult(text, command, maxChars) {
|
|
121
125
|
if (!text) return { content: [{ type: 'text', text: '(no output)' }] };
|
|
122
|
-
const
|
|
126
|
+
const defaultLimit = BROAD_COMMANDS.has(command) ? BROAD_OUTPUT_CHARS : DEFAULT_OUTPUT_CHARS;
|
|
127
|
+
const limit = Math.min(maxChars || defaultLimit, MAX_OUTPUT_CHARS);
|
|
123
128
|
if (text.length > limit) {
|
|
124
129
|
const fullSize = text.length;
|
|
125
130
|
const fullTokens = Math.round(fullSize / 4);
|
|
@@ -128,14 +133,15 @@ function toolResult(text, command, maxChars) {
|
|
|
128
133
|
const lastNewline = truncated.lastIndexOf('\n');
|
|
129
134
|
const cleanCut = lastNewline > limit * 0.8 ? truncated.substring(0, lastNewline) : truncated;
|
|
130
135
|
// Command-specific narrowing hints
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
136
|
+
const hints = {
|
|
137
|
+
toc: 'Use in= to scope to a subdirectory, or detailed=false for compact view.',
|
|
138
|
+
entrypoints: 'Use framework= to filter by framework, exclude= to skip patterns.',
|
|
139
|
+
diff_impact: 'Use file= to scope to specific files/directories.',
|
|
140
|
+
affected_tests: 'Use file= to scope, exclude= to skip patterns.',
|
|
141
|
+
deadcode: 'Use file= to scope, exclude= to skip patterns.',
|
|
142
|
+
usages: 'Use file= to scope to specific files.',
|
|
143
|
+
};
|
|
144
|
+
const narrow = hints[command] || 'Use file=/in=/exclude= to narrow scope.';
|
|
139
145
|
return { content: [{ type: 'text', text: cleanCut + `\n\n... OUTPUT TRUNCATED: showing ${limit} of ${fullSize} chars. Full output would be ~${fullTokens} tokens. ${narrow} Or use all=true to see everything (warning: ~${fullTokens} tokens).` }] };
|
|
140
146
|
}
|
|
141
147
|
return { content: [{ type: 'text', text }] };
|
|
@@ -285,7 +291,7 @@ server.registerTool(
|
|
|
285
291
|
class_name: z.string().optional().describe('Class name to scope method analysis (e.g. "MarketDataFetcher" for close)'),
|
|
286
292
|
limit: z.number().optional().describe('Max results to return (default: 500). Caps find, usages, search, deadcode, api, toc --detailed.'),
|
|
287
293
|
max_files: z.number().optional().describe('Max files to index (default: 10000). Use for very large codebases.'),
|
|
288
|
-
max_chars: z.number().optional().describe('Max output chars before truncation (
|
|
294
|
+
max_chars: z.number().optional().describe('Max output chars before truncation. Targeted commands (about, context, smart, etc.): 10K default. Broad commands (toc, entrypoints, deadcode, etc.): 3K default. Max: 100K. Use all=true to bypass all caps.'),
|
|
289
295
|
// Structural search flags (search command)
|
|
290
296
|
type: z.string().optional().describe('Symbol type filter for structural search: function, class, call, method, type. Triggers index-based search.'),
|
|
291
297
|
param: z.string().optional().describe('Filter by parameter name or type (structural search). E.g. "Request", "ctx".'),
|
|
@@ -308,8 +314,8 @@ server.registerTool(
|
|
|
308
314
|
// all=true bypasses both formatter caps AND char truncation (parity with CLI --all)
|
|
309
315
|
const maxChars = ep.all ? MAX_OUTPUT_CHARS : ep.maxChars;
|
|
310
316
|
|
|
311
|
-
// Wrap toolResult to auto-inject maxChars from this request
|
|
312
|
-
const tr = (text
|
|
317
|
+
// Wrap toolResult to auto-inject command + maxChars from this request
|
|
318
|
+
const tr = (text) => toolResult(text, command, maxChars);
|
|
313
319
|
|
|
314
320
|
try {
|
|
315
321
|
switch (command) {
|
|
@@ -432,7 +438,7 @@ server.registerTool(
|
|
|
432
438
|
topHint: 'Set top=N or use detailed=false for compact view.'
|
|
433
439
|
});
|
|
434
440
|
if (note) text += '\n\n' + note;
|
|
435
|
-
return tr(text
|
|
441
|
+
return tr(text);
|
|
436
442
|
}
|
|
437
443
|
|
|
438
444
|
case 'search': {
|
|
@@ -456,7 +462,7 @@ server.registerTool(
|
|
|
456
462
|
const index = getIndex(project_dir, ep);
|
|
457
463
|
const { ok, result, error } = execute(index, 'affectedTests', ep);
|
|
458
464
|
if (!ok) return tr(error);
|
|
459
|
-
return tr(output.formatAffectedTests(result, { all: ep.all })
|
|
465
|
+
return tr(output.formatAffectedTests(result, { all: ep.all }));
|
|
460
466
|
}
|
|
461
467
|
|
|
462
468
|
case 'deadcode': {
|
|
@@ -542,7 +548,7 @@ server.registerTool(
|
|
|
542
548
|
const index = getIndex(project_dir, ep);
|
|
543
549
|
const { ok, result, error } = execute(index, 'diffImpact', ep);
|
|
544
550
|
if (!ok) return tr(error); // soft error — e.g. "not a git repo"
|
|
545
|
-
return tr(output.formatDiffImpact(result, { all: ep.all })
|
|
551
|
+
return tr(output.formatDiffImpact(result, { all: ep.all }));
|
|
546
552
|
}
|
|
547
553
|
|
|
548
554
|
// ── Other ───────────────────────────────────────────────────
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ucn",
|
|
3
|
-
"version": "3.8.
|
|
3
|
+
"version": "3.8.11",
|
|
4
4
|
"mcpName": "io.github.mleoca/ucn",
|
|
5
5
|
"description": "Code intelligence toolkit for AI agents — extract functions, trace call chains, find callers, detect dead code without reading entire files. Works as MCP server, CLI, or agent skill. Supports JS/TS, Python, Go, Rust, Java.",
|
|
6
6
|
"main": "index.js",
|