@newrelic/preflight 1.6.8 → 1.6.9
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/tools/analytics-tools.d.ts +10 -0
- package/dist/tools/analytics-tools.d.ts.map +1 -1
- package/dist/tools/analytics-tools.js +55 -0
- package/dist/tools/analytics-tools.js.map +1 -1
- package/dist/tools/cost-tools.d.ts +9 -0
- package/dist/tools/cost-tools.d.ts.map +1 -1
- package/dist/tools/cost-tools.js +76 -0
- package/dist/tools/cost-tools.js.map +1 -1
- package/dist/tools/cross-session-tools.d.ts +18 -0
- package/dist/tools/cross-session-tools.d.ts.map +1 -1
- package/dist/tools/cross-session-tools.js +159 -0
- package/dist/tools/cross-session-tools.js.map +1 -1
- package/dist/tools/extended-analytics-tools.d.ts +15 -0
- package/dist/tools/extended-analytics-tools.d.ts.map +1 -1
- package/dist/tools/extended-analytics-tools.js +103 -0
- package/dist/tools/extended-analytics-tools.js.map +1 -1
- package/dist/tools/session-stats.d.ts +7 -7
- package/dist/tools/session-stats.d.ts.map +1 -1
- package/dist/tools/session-stats.js +124 -837
- package/dist/tools/session-stats.js.map +1 -1
- package/dist/tools/tool-registry.d.ts +52 -0
- package/dist/tools/tool-registry.d.ts.map +1 -0
- package/dist/tools/tool-registry.js +52 -0
- package/dist/tools/tool-registry.js.map +1 -0
- package/dist/tools/workflow-tools.d.ts +8 -0
- package/dist/tools/workflow-tools.d.ts.map +1 -1
- package/dist/tools/workflow-tools.js +64 -0
- package/dist/tools/workflow-tools.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `registerTools()` — the MCP server's main tool registry.
|
|
3
|
-
* `
|
|
4
|
-
*
|
|
5
|
-
* config, install-hooks,
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* is present.
|
|
2
|
+
* `registerTools()` — the MCP server's main tool registry. Composes the
|
|
3
|
+
* per-file `registerXTools(deps)` sets from `cost-tools.ts`, `workflow-tools.ts`,
|
|
4
|
+
* `cross-session-tools.ts`, `analytics-tools.ts`, and `extended-analytics-tools.ts`
|
|
5
|
+
* with this file's own "core" tools (health, config, install-hooks, session
|
|
6
|
+
* stats/timeline, git efficiency, cost-per-tool, turn analysis) into the
|
|
7
|
+
* server's single `tools/list`/`tools/call` handler pair — each tool is only
|
|
8
|
+
* advertised when its backing tracker is present, per `tool-registry.ts`.
|
|
9
9
|
*/
|
|
10
10
|
import { ListToolsRequestSchema, CallToolRequestSchema, ErrorCode, McpError, } from '@modelcontextprotocol/sdk/types.js';
|
|
11
|
-
import { z } from 'zod';
|
|
12
11
|
import { createLogger } from '../shared/index.js';
|
|
13
12
|
import { VERSION } from '../version.js';
|
|
14
13
|
const logger = createLogger('session-stats');
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
14
|
+
import { registerCostTools } from './cost-tools.js';
|
|
15
|
+
import { registerWorkflowTools } from './workflow-tools.js';
|
|
16
|
+
import { registerCrossSessionTools } from './cross-session-tools.js';
|
|
17
|
+
import { registerAnalyticsTools } from './analytics-tools.js';
|
|
18
|
+
import { registerExtendedAnalyticsTools } from './extended-analytics-tools.js';
|
|
19
|
+
import { requireTracker, requireAvailable, buildToolSet, mergeToolSets, } from './tool-registry.js';
|
|
20
20
|
// ---------------------------------------------------------------------------
|
|
21
21
|
// Tool definitions (for tools/list)
|
|
22
22
|
// ---------------------------------------------------------------------------
|
|
@@ -239,21 +239,112 @@ export function handleGetGitEfficiency(tracker) {
|
|
|
239
239
|
};
|
|
240
240
|
}
|
|
241
241
|
// ---------------------------------------------------------------------------
|
|
242
|
-
//
|
|
242
|
+
// Core tools — no natural sibling file (health, config, install-hooks,
|
|
243
|
+
// session stats/timeline, git efficiency, cost-per-tool, turn analysis)
|
|
243
244
|
// ---------------------------------------------------------------------------
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
245
|
+
function registerCoreTools(deps) {
|
|
246
|
+
return buildToolSet([
|
|
247
|
+
{
|
|
248
|
+
definition: HEALTH_TOOL,
|
|
249
|
+
available: true,
|
|
250
|
+
handle: () => handleHealth({
|
|
251
|
+
sessionStartMs: deps.sessionStartMs,
|
|
252
|
+
developer: deps.developer,
|
|
253
|
+
sessionId: deps.sessionTracker?.getMetrics().sessionId,
|
|
254
|
+
hooksInstalledFn: deps.hooksInstalledFn,
|
|
255
|
+
}),
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
definition: INSTALL_HOOKS_TOOL,
|
|
259
|
+
available: true,
|
|
260
|
+
handle: () => handleInstallHooks(deps.headlessInstaller),
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
definition: CONFIG_TOOL,
|
|
264
|
+
available: !!deps.configSummary,
|
|
265
|
+
handle: () => {
|
|
266
|
+
const missing = requireAvailable(!!deps.configSummary, 'Config summary not available');
|
|
267
|
+
if (missing)
|
|
268
|
+
return missing;
|
|
269
|
+
return handleGetConfig(deps.configSummary);
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
definition: SESSION_STATS_TOOL,
|
|
274
|
+
available: !!deps.sessionTracker,
|
|
275
|
+
handle: () => {
|
|
276
|
+
const check = requireTracker(deps.sessionTracker, 'SessionTracker');
|
|
277
|
+
if (!check.ok)
|
|
278
|
+
return check.result;
|
|
279
|
+
const { _stats: stats } = handleGetSessionStats(check.value, deps.sessionTraceId);
|
|
280
|
+
return {
|
|
281
|
+
content: [
|
|
282
|
+
{
|
|
283
|
+
type: 'text',
|
|
284
|
+
text: JSON.stringify({
|
|
285
|
+
identity: {
|
|
286
|
+
developer: deps.developer ?? 'unknown',
|
|
287
|
+
teamId: deps.teamId ?? null,
|
|
288
|
+
projectId: deps.projectId ?? null,
|
|
289
|
+
},
|
|
290
|
+
...stats,
|
|
291
|
+
}, null, 2),
|
|
292
|
+
},
|
|
293
|
+
],
|
|
294
|
+
};
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
definition: SESSION_TIMELINE_TOOL,
|
|
299
|
+
available: !!deps.sessionTracker,
|
|
300
|
+
handle: (args) => {
|
|
301
|
+
const check = requireTracker(deps.sessionTracker, 'SessionTracker');
|
|
302
|
+
if (!check.ok)
|
|
303
|
+
return check.result;
|
|
304
|
+
const lastN = args?.last_n;
|
|
305
|
+
return handleGetSessionTimeline(check.value, typeof lastN === 'number' ? lastN : 20);
|
|
306
|
+
},
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
definition: GIT_EFFICIENCY_TOOL,
|
|
310
|
+
available: !!deps.gitEfficiencyTracker,
|
|
311
|
+
handle: () => {
|
|
312
|
+
const check = requireTracker(deps.gitEfficiencyTracker, 'GitEfficiencyTracker');
|
|
313
|
+
if (!check.ok)
|
|
314
|
+
return check.result;
|
|
315
|
+
return handleGetGitEfficiency(check.value);
|
|
316
|
+
},
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
definition: COST_PER_TOOL_TOOL,
|
|
320
|
+
available: !!deps.turnCostAttributor,
|
|
321
|
+
handle: () => {
|
|
322
|
+
const check = requireTracker(deps.turnCostAttributor, 'TurnCostAttributor');
|
|
323
|
+
if (!check.ok)
|
|
324
|
+
return check.result;
|
|
325
|
+
return {
|
|
326
|
+
content: [
|
|
327
|
+
{ type: 'text', text: JSON.stringify(check.value.getMetrics(), null, 2) },
|
|
328
|
+
],
|
|
329
|
+
};
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
definition: TURN_ANALYSIS_TOOL,
|
|
334
|
+
available: !!deps.turnTracker,
|
|
335
|
+
handle: () => {
|
|
336
|
+
const check = requireTracker(deps.turnTracker, 'TurnTracker');
|
|
337
|
+
if (!check.ok)
|
|
338
|
+
return check.result;
|
|
339
|
+
return {
|
|
340
|
+
content: [
|
|
341
|
+
{ type: 'text', text: JSON.stringify(check.value.getMetrics(), null, 2) },
|
|
342
|
+
],
|
|
343
|
+
};
|
|
344
|
+
},
|
|
345
|
+
},
|
|
346
|
+
]);
|
|
347
|
+
}
|
|
257
348
|
// ---------------------------------------------------------------------------
|
|
258
349
|
// Registration
|
|
259
350
|
// ---------------------------------------------------------------------------
|
|
@@ -302,820 +393,16 @@ export function registerPendingTools(server, options) {
|
|
|
302
393
|
});
|
|
303
394
|
}
|
|
304
395
|
export function registerTools(server, options) {
|
|
305
|
-
const {
|
|
306
|
-
// Build combined tool list
|
|
307
|
-
const tools = [HEALTH_TOOL];
|
|
308
|
-
tools.push(INSTALL_HOOKS_TOOL);
|
|
309
|
-
if (options.configSummary) {
|
|
310
|
-
tools.push(CONFIG_TOOL);
|
|
311
|
-
}
|
|
312
|
-
if (sessionTracker) {
|
|
313
|
-
tools.push(SESSION_STATS_TOOL, SESSION_TIMELINE_TOOL);
|
|
314
|
-
}
|
|
315
|
-
if (costTracker) {
|
|
316
|
-
tools.push(REPORT_TOKENS_TOOL, COST_BREAKDOWN_TOOL, PROMPT_CACHE_HEALTH_TOOL);
|
|
317
|
-
}
|
|
318
|
-
if (budgetTracker) {
|
|
319
|
-
tools.push(BUDGET_STATUS_TOOL);
|
|
320
|
-
}
|
|
321
|
-
if (costTracker && sessionStartMs !== undefined) {
|
|
322
|
-
tools.push(COST_FORECAST_TOOL);
|
|
323
|
-
}
|
|
324
|
-
if (taskDetector) {
|
|
325
|
-
tools.push(WORKFLOW_TRACE_TOOL);
|
|
326
|
-
}
|
|
327
|
-
if (antiPatternDetector && taskDetector) {
|
|
328
|
-
tools.push(ANTI_PATTERNS_TOOL);
|
|
329
|
-
}
|
|
330
|
-
if (efficiencyScorer) {
|
|
331
|
-
tools.push(EFFICIENCY_SCORE_TOOL);
|
|
332
|
-
}
|
|
333
|
-
if (feedbackCollector) {
|
|
334
|
-
tools.push(REPORT_FEEDBACK_TOOL);
|
|
335
|
-
}
|
|
336
|
-
// Cross-session tools — each registered only when its specific dependencies exist
|
|
337
|
-
if (sessionStore) {
|
|
338
|
-
tools.push(SESSION_HISTORY_TOOL, PLATFORM_COMPARISON_TOOL);
|
|
339
|
-
}
|
|
340
|
-
if (weeklySummaryGenerator) {
|
|
341
|
-
tools.push(WEEKLY_SUMMARY_TOOL);
|
|
342
|
-
}
|
|
343
|
-
if (trendAnalyzer) {
|
|
344
|
-
tools.push(TRENDS_TOOL);
|
|
345
|
-
}
|
|
346
|
-
if (collaborationProfiler) {
|
|
347
|
-
tools.push(COLLABORATION_PROFILE_TOOL);
|
|
348
|
-
}
|
|
349
|
-
if (claudeMdTracker) {
|
|
350
|
-
tools.push(CLAUDEMD_IMPACT_TOOL);
|
|
351
|
-
}
|
|
352
|
-
if (costPerOutcomeAnalyzer && taskDetector) {
|
|
353
|
-
tools.push(COST_PER_OUTCOME_TOOL);
|
|
354
|
-
}
|
|
355
|
-
if (recommendationEngine) {
|
|
356
|
-
tools.push(RECOMMENDATIONS_TOOL);
|
|
357
|
-
}
|
|
358
|
-
if (options.teamId && options.nrApiKey) {
|
|
359
|
-
tools.push(TEAM_SUMMARY_TOOL);
|
|
360
|
-
}
|
|
361
|
-
if (options.configFilePath) {
|
|
362
|
-
tools.push(SUBSCRIBE_DIGEST_TOOL, UNSUBSCRIBE_DIGEST_TOOL);
|
|
363
|
-
}
|
|
364
|
-
if (options.configFilePath && weeklySummaryGenerator) {
|
|
365
|
-
tools.push(SEND_DIGEST_TOOL);
|
|
366
|
-
}
|
|
367
|
-
if (weeklySummaryGenerator && options.developer) {
|
|
368
|
-
tools.push(PERSONAL_INSIGHTS_TOOL);
|
|
369
|
-
}
|
|
370
|
-
if (contextWindowTracker) {
|
|
371
|
-
tools.push(CONTEXT_EFFICIENCY_TOOL);
|
|
372
|
-
}
|
|
373
|
-
if (contextTracker) {
|
|
374
|
-
tools.push(CONTEXT_TRACKING_TOOL);
|
|
375
|
-
}
|
|
376
|
-
if (latencyTracker) {
|
|
377
|
-
tools.push(LATENCY_PERCENTILES_TOOL);
|
|
378
|
-
}
|
|
379
|
-
if (taskCompletionTracker) {
|
|
380
|
-
tools.push(TASK_COMPLETION_TOOL);
|
|
381
|
-
}
|
|
382
|
-
if (modelUsageTracker) {
|
|
383
|
-
tools.push(MODEL_USAGE_TOOL);
|
|
384
|
-
}
|
|
385
|
-
if (retryDetector) {
|
|
386
|
-
tools.push(RETRY_ALERTS_TOOL);
|
|
387
|
-
}
|
|
388
|
-
if (contextCompositionTracker) {
|
|
389
|
-
tools.push(CONTEXT_COMPOSITION_TOOL);
|
|
390
|
-
}
|
|
391
|
-
if (latencyDecompositionTracker) {
|
|
392
|
-
tools.push(LATENCY_DECOMPOSITION_TOOL);
|
|
393
|
-
}
|
|
394
|
-
if (decisionTracker) {
|
|
395
|
-
tools.push(DECISION_TREE_TOOL);
|
|
396
|
-
}
|
|
397
|
-
if (instructionDriftTracker) {
|
|
398
|
-
tools.push(INSTRUCTION_DRIFT_TOOL);
|
|
399
|
-
}
|
|
400
|
-
if (toolSelectionScorer && options.toolCallBuffer) {
|
|
401
|
-
tools.push(TOOL_SELECTION_SCORE_TOOL);
|
|
402
|
-
}
|
|
403
|
-
if (qualityProxyTracker) {
|
|
404
|
-
tools.push(QUALITY_PROXY_TOOL);
|
|
405
|
-
}
|
|
406
|
-
if (apiFailureTracker) {
|
|
407
|
-
tools.push(API_FAILURES_TOOL);
|
|
408
|
-
}
|
|
409
|
-
if (gitEfficiencyTracker) {
|
|
410
|
-
tools.push(GIT_EFFICIENCY_TOOL);
|
|
411
|
-
}
|
|
412
|
-
if (turnCostAttributor) {
|
|
413
|
-
tools.push(COST_PER_TOOL_TOOL);
|
|
414
|
-
}
|
|
415
|
-
if (turnTracker) {
|
|
416
|
-
tools.push(TURN_ANALYSIS_TOOL);
|
|
417
|
-
}
|
|
396
|
+
const { tools, handlers } = mergeToolSets(registerCoreTools(options), registerCostTools(options), registerWorkflowTools(options), registerCrossSessionTools(options), registerAnalyticsTools(options), registerExtendedAnalyticsTools(options));
|
|
418
397
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools }));
|
|
419
398
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
420
399
|
const { name, arguments: args } = request.params;
|
|
400
|
+
const handler = handlers[name];
|
|
401
|
+
if (!handler) {
|
|
402
|
+
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
|
|
403
|
+
}
|
|
421
404
|
try {
|
|
422
|
-
|
|
423
|
-
case 'nr_observe_health': {
|
|
424
|
-
return handleHealth({
|
|
425
|
-
sessionStartMs,
|
|
426
|
-
developer: options.developer,
|
|
427
|
-
sessionId: sessionTracker?.getMetrics().sessionId,
|
|
428
|
-
hooksInstalledFn: options.hooksInstalledFn,
|
|
429
|
-
});
|
|
430
|
-
}
|
|
431
|
-
case 'nr_observe_install_hooks': {
|
|
432
|
-
return handleInstallHooks(options.headlessInstaller);
|
|
433
|
-
}
|
|
434
|
-
case 'nr_observe_get_config': {
|
|
435
|
-
if (!options.configSummary) {
|
|
436
|
-
return {
|
|
437
|
-
content: [
|
|
438
|
-
{
|
|
439
|
-
type: 'text',
|
|
440
|
-
text: JSON.stringify({ error: 'Config summary not available' }),
|
|
441
|
-
},
|
|
442
|
-
],
|
|
443
|
-
isError: true,
|
|
444
|
-
};
|
|
445
|
-
}
|
|
446
|
-
return handleGetConfig(options.configSummary);
|
|
447
|
-
}
|
|
448
|
-
case 'nr_observe_get_session_stats': {
|
|
449
|
-
if (!sessionTracker) {
|
|
450
|
-
return {
|
|
451
|
-
content: [
|
|
452
|
-
{
|
|
453
|
-
type: 'text',
|
|
454
|
-
text: JSON.stringify({ error: 'SessionTracker not available' }),
|
|
455
|
-
},
|
|
456
|
-
],
|
|
457
|
-
isError: true,
|
|
458
|
-
};
|
|
459
|
-
}
|
|
460
|
-
const result = handleGetSessionStats(sessionTracker, sessionTraceId);
|
|
461
|
-
// Use the raw stats object directly to avoid a JSON parse/stringify round-trip.
|
|
462
|
-
const stats = result._stats;
|
|
463
|
-
return {
|
|
464
|
-
content: [
|
|
465
|
-
{
|
|
466
|
-
type: 'text',
|
|
467
|
-
text: JSON.stringify({
|
|
468
|
-
identity: {
|
|
469
|
-
developer: options.developer ?? 'unknown',
|
|
470
|
-
teamId: options.teamId ?? null,
|
|
471
|
-
projectId: options.projectId ?? null,
|
|
472
|
-
},
|
|
473
|
-
...stats,
|
|
474
|
-
}, null, 2),
|
|
475
|
-
},
|
|
476
|
-
],
|
|
477
|
-
};
|
|
478
|
-
}
|
|
479
|
-
case 'nr_observe_get_session_timeline': {
|
|
480
|
-
if (!sessionTracker) {
|
|
481
|
-
return {
|
|
482
|
-
content: [
|
|
483
|
-
{
|
|
484
|
-
type: 'text',
|
|
485
|
-
text: JSON.stringify({ error: 'SessionTracker not available' }),
|
|
486
|
-
},
|
|
487
|
-
],
|
|
488
|
-
isError: true,
|
|
489
|
-
};
|
|
490
|
-
}
|
|
491
|
-
const lastN = args?.last_n;
|
|
492
|
-
return handleGetSessionTimeline(sessionTracker, typeof lastN === 'number' ? lastN : 20);
|
|
493
|
-
}
|
|
494
|
-
case 'nr_observe_report_tokens': {
|
|
495
|
-
if (!costTracker) {
|
|
496
|
-
return {
|
|
497
|
-
content: [
|
|
498
|
-
{
|
|
499
|
-
type: 'text',
|
|
500
|
-
text: JSON.stringify({ error: 'CostTracker not available' }),
|
|
501
|
-
},
|
|
502
|
-
],
|
|
503
|
-
isError: true,
|
|
504
|
-
};
|
|
505
|
-
}
|
|
506
|
-
try {
|
|
507
|
-
const tokenReport = TokenReportSchema.parse(args);
|
|
508
|
-
return handleReportTokens(costTracker, tokenReport, modelUsageTracker);
|
|
509
|
-
}
|
|
510
|
-
catch (err) {
|
|
511
|
-
const message = err instanceof z.ZodError
|
|
512
|
-
? err.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join('; ')
|
|
513
|
-
: String(err);
|
|
514
|
-
return {
|
|
515
|
-
content: [
|
|
516
|
-
{
|
|
517
|
-
type: 'text',
|
|
518
|
-
text: JSON.stringify({ error: `Invalid token report: ${message}` }),
|
|
519
|
-
},
|
|
520
|
-
],
|
|
521
|
-
isError: true,
|
|
522
|
-
};
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
case 'nr_observe_get_cost_breakdown': {
|
|
526
|
-
if (!costTracker) {
|
|
527
|
-
return {
|
|
528
|
-
content: [
|
|
529
|
-
{
|
|
530
|
-
type: 'text',
|
|
531
|
-
text: JSON.stringify({ error: 'CostTracker not available' }),
|
|
532
|
-
},
|
|
533
|
-
],
|
|
534
|
-
isError: true,
|
|
535
|
-
};
|
|
536
|
-
}
|
|
537
|
-
return handleGetCostBreakdown(costTracker, taskDetector);
|
|
538
|
-
}
|
|
539
|
-
case 'nr_observe_get_prompt_cache_health': {
|
|
540
|
-
if (!costTracker) {
|
|
541
|
-
return {
|
|
542
|
-
content: [
|
|
543
|
-
{
|
|
544
|
-
type: 'text',
|
|
545
|
-
text: JSON.stringify({ error: 'CostTracker not available' }),
|
|
546
|
-
},
|
|
547
|
-
],
|
|
548
|
-
isError: true,
|
|
549
|
-
};
|
|
550
|
-
}
|
|
551
|
-
return handleGetPromptCacheHealth(costTracker);
|
|
552
|
-
}
|
|
553
|
-
case 'nr_observe_get_budget_status': {
|
|
554
|
-
if (!budgetTracker) {
|
|
555
|
-
return {
|
|
556
|
-
content: [
|
|
557
|
-
{
|
|
558
|
-
type: 'text',
|
|
559
|
-
text: JSON.stringify({ error: 'BudgetTracker not available' }),
|
|
560
|
-
},
|
|
561
|
-
],
|
|
562
|
-
isError: true,
|
|
563
|
-
};
|
|
564
|
-
}
|
|
565
|
-
return handleGetBudgetStatus(budgetTracker);
|
|
566
|
-
}
|
|
567
|
-
case 'nr_observe_get_cost_forecast': {
|
|
568
|
-
if (!costTracker || sessionStartMs === undefined) {
|
|
569
|
-
return {
|
|
570
|
-
content: [
|
|
571
|
-
{
|
|
572
|
-
type: 'text',
|
|
573
|
-
text: JSON.stringify({ error: 'CostTracker or sessionStartMs not available' }),
|
|
574
|
-
},
|
|
575
|
-
],
|
|
576
|
-
isError: true,
|
|
577
|
-
};
|
|
578
|
-
}
|
|
579
|
-
return handleGetCostForecast(costTracker, sessionStartMs);
|
|
580
|
-
}
|
|
581
|
-
case 'nr_observe_get_workflow_trace': {
|
|
582
|
-
if (!taskDetector) {
|
|
583
|
-
return {
|
|
584
|
-
content: [
|
|
585
|
-
{
|
|
586
|
-
type: 'text',
|
|
587
|
-
text: JSON.stringify({ error: 'TaskDetector not available' }),
|
|
588
|
-
},
|
|
589
|
-
],
|
|
590
|
-
isError: true,
|
|
591
|
-
};
|
|
592
|
-
}
|
|
593
|
-
const taskId = args?.task_id;
|
|
594
|
-
return handleGetWorkflowTrace(taskDetector, antiPatternDetector, efficiencyScorer, taskId);
|
|
595
|
-
}
|
|
596
|
-
case 'nr_observe_get_anti_patterns': {
|
|
597
|
-
if (!antiPatternDetector || !taskDetector) {
|
|
598
|
-
return {
|
|
599
|
-
content: [
|
|
600
|
-
{
|
|
601
|
-
type: 'text',
|
|
602
|
-
text: JSON.stringify({
|
|
603
|
-
error: 'AntiPatternDetector or TaskDetector not available',
|
|
604
|
-
}),
|
|
605
|
-
},
|
|
606
|
-
],
|
|
607
|
-
isError: true,
|
|
608
|
-
};
|
|
609
|
-
}
|
|
610
|
-
return handleGetAntiPatterns(taskDetector, antiPatternDetector);
|
|
611
|
-
}
|
|
612
|
-
case 'nr_observe_get_efficiency_score': {
|
|
613
|
-
if (!efficiencyScorer) {
|
|
614
|
-
return {
|
|
615
|
-
content: [
|
|
616
|
-
{
|
|
617
|
-
type: 'text',
|
|
618
|
-
text: JSON.stringify({ error: 'EfficiencyScorer not available' }),
|
|
619
|
-
},
|
|
620
|
-
],
|
|
621
|
-
isError: true,
|
|
622
|
-
};
|
|
623
|
-
}
|
|
624
|
-
return handleGetEfficiencyScore(efficiencyScorer, taskDetector, antiPatternDetector);
|
|
625
|
-
}
|
|
626
|
-
case 'nr_observe_report_feedback': {
|
|
627
|
-
if (!feedbackCollector) {
|
|
628
|
-
return {
|
|
629
|
-
content: [
|
|
630
|
-
{
|
|
631
|
-
type: 'text',
|
|
632
|
-
text: JSON.stringify({ error: 'FeedbackCollector not available' }),
|
|
633
|
-
},
|
|
634
|
-
],
|
|
635
|
-
isError: true,
|
|
636
|
-
};
|
|
637
|
-
}
|
|
638
|
-
try {
|
|
639
|
-
const feedbackArgs = FeedbackSchema.parse(args);
|
|
640
|
-
return handleReportFeedback(feedbackCollector, feedbackArgs);
|
|
641
|
-
}
|
|
642
|
-
catch (err) {
|
|
643
|
-
const message = err instanceof z.ZodError
|
|
644
|
-
? err.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join('; ')
|
|
645
|
-
: String(err);
|
|
646
|
-
return {
|
|
647
|
-
content: [
|
|
648
|
-
{
|
|
649
|
-
type: 'text',
|
|
650
|
-
text: JSON.stringify({ error: `Invalid feedback: ${message}` }),
|
|
651
|
-
},
|
|
652
|
-
],
|
|
653
|
-
isError: true,
|
|
654
|
-
};
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
case 'nr_observe_get_session_history': {
|
|
658
|
-
if (!sessionStore) {
|
|
659
|
-
return {
|
|
660
|
-
content: [
|
|
661
|
-
{
|
|
662
|
-
type: 'text',
|
|
663
|
-
text: JSON.stringify({ error: 'SessionStore not available' }),
|
|
664
|
-
},
|
|
665
|
-
],
|
|
666
|
-
isError: true,
|
|
667
|
-
};
|
|
668
|
-
}
|
|
669
|
-
const historyArgs = args ?? {};
|
|
670
|
-
return handleGetSessionHistory(sessionStore, {
|
|
671
|
-
since: historyArgs.since,
|
|
672
|
-
developer: historyArgs.developer,
|
|
673
|
-
limit: historyArgs.limit,
|
|
674
|
-
});
|
|
675
|
-
}
|
|
676
|
-
case 'nr_observe_get_weekly_summary': {
|
|
677
|
-
if (!weeklySummaryGenerator) {
|
|
678
|
-
return {
|
|
679
|
-
content: [
|
|
680
|
-
{
|
|
681
|
-
type: 'text',
|
|
682
|
-
text: JSON.stringify({ error: 'WeeklySummaryGenerator not available' }),
|
|
683
|
-
},
|
|
684
|
-
],
|
|
685
|
-
isError: true,
|
|
686
|
-
};
|
|
687
|
-
}
|
|
688
|
-
const weekArgs = args ?? {};
|
|
689
|
-
return handleGetWeeklySummary(weeklySummaryGenerator, {
|
|
690
|
-
week: weekArgs.week,
|
|
691
|
-
});
|
|
692
|
-
}
|
|
693
|
-
case 'nr_observe_get_trends': {
|
|
694
|
-
if (!trendAnalyzer) {
|
|
695
|
-
return {
|
|
696
|
-
content: [
|
|
697
|
-
{
|
|
698
|
-
type: 'text',
|
|
699
|
-
text: JSON.stringify({ error: 'TrendAnalyzer not available' }),
|
|
700
|
-
},
|
|
701
|
-
],
|
|
702
|
-
isError: true,
|
|
703
|
-
};
|
|
704
|
-
}
|
|
705
|
-
const trendArgs = args ?? {};
|
|
706
|
-
return handleGetTrends(trendAnalyzer, {
|
|
707
|
-
metric: trendArgs.metric,
|
|
708
|
-
developer: trendArgs.developer,
|
|
709
|
-
weeks: trendArgs.weeks,
|
|
710
|
-
});
|
|
711
|
-
}
|
|
712
|
-
case 'nr_observe_get_collaboration_profile': {
|
|
713
|
-
if (!collaborationProfiler) {
|
|
714
|
-
return {
|
|
715
|
-
content: [
|
|
716
|
-
{
|
|
717
|
-
type: 'text',
|
|
718
|
-
text: JSON.stringify({ error: 'CollaborationProfiler not available' }),
|
|
719
|
-
},
|
|
720
|
-
],
|
|
721
|
-
isError: true,
|
|
722
|
-
};
|
|
723
|
-
}
|
|
724
|
-
const profileArgs = args ?? {};
|
|
725
|
-
return handleGetCollaborationProfile(collaborationProfiler, {
|
|
726
|
-
developer: profileArgs.developer,
|
|
727
|
-
});
|
|
728
|
-
}
|
|
729
|
-
case 'nr_observe_get_claudemd_impact': {
|
|
730
|
-
if (!claudeMdTracker) {
|
|
731
|
-
return {
|
|
732
|
-
content: [
|
|
733
|
-
{
|
|
734
|
-
type: 'text',
|
|
735
|
-
text: JSON.stringify({ error: 'ClaudeMdTracker not available' }),
|
|
736
|
-
},
|
|
737
|
-
],
|
|
738
|
-
isError: true,
|
|
739
|
-
};
|
|
740
|
-
}
|
|
741
|
-
return handleGetClaudeMdImpact(claudeMdTracker);
|
|
742
|
-
}
|
|
743
|
-
case 'nr_observe_get_cost_per_outcome': {
|
|
744
|
-
if (!costPerOutcomeAnalyzer || !taskDetector) {
|
|
745
|
-
return {
|
|
746
|
-
content: [
|
|
747
|
-
{
|
|
748
|
-
type: 'text',
|
|
749
|
-
text: JSON.stringify({
|
|
750
|
-
error: 'CostPerOutcomeAnalyzer or TaskDetector not available',
|
|
751
|
-
}),
|
|
752
|
-
},
|
|
753
|
-
],
|
|
754
|
-
isError: true,
|
|
755
|
-
};
|
|
756
|
-
}
|
|
757
|
-
const costArgs = args ?? {};
|
|
758
|
-
return handleGetCostPerOutcome(costPerOutcomeAnalyzer, taskDetector, {
|
|
759
|
-
since: costArgs.since,
|
|
760
|
-
});
|
|
761
|
-
}
|
|
762
|
-
case 'nr_observe_get_recommendations': {
|
|
763
|
-
if (!recommendationEngine) {
|
|
764
|
-
return {
|
|
765
|
-
content: [
|
|
766
|
-
{
|
|
767
|
-
type: 'text',
|
|
768
|
-
text: JSON.stringify({ error: 'RecommendationEngine not available' }),
|
|
769
|
-
},
|
|
770
|
-
],
|
|
771
|
-
isError: true,
|
|
772
|
-
};
|
|
773
|
-
}
|
|
774
|
-
const recArgs = args ?? {};
|
|
775
|
-
return handleGetRecommendations(recommendationEngine, {
|
|
776
|
-
developer: recArgs.developer,
|
|
777
|
-
topN: recArgs.topN,
|
|
778
|
-
});
|
|
779
|
-
}
|
|
780
|
-
case 'nr_observe_get_platform_comparison': {
|
|
781
|
-
if (!sessionStore) {
|
|
782
|
-
return {
|
|
783
|
-
content: [
|
|
784
|
-
{
|
|
785
|
-
type: 'text',
|
|
786
|
-
text: JSON.stringify({ error: 'SessionStore not available' }),
|
|
787
|
-
},
|
|
788
|
-
],
|
|
789
|
-
isError: true,
|
|
790
|
-
};
|
|
791
|
-
}
|
|
792
|
-
const pcArgs = args ?? {};
|
|
793
|
-
return handleGetPlatformComparison(sessionStore, {
|
|
794
|
-
metric: pcArgs.metric,
|
|
795
|
-
weeks: pcArgs.weeks,
|
|
796
|
-
});
|
|
797
|
-
}
|
|
798
|
-
case 'nr_observe_get_team_summary': {
|
|
799
|
-
if (!options.teamId || !options.nrApiKey) {
|
|
800
|
-
return {
|
|
801
|
-
content: [
|
|
802
|
-
{
|
|
803
|
-
type: 'text',
|
|
804
|
-
text: JSON.stringify({ error: 'teamId or nrApiKey not configured' }),
|
|
805
|
-
},
|
|
806
|
-
],
|
|
807
|
-
isError: true,
|
|
808
|
-
};
|
|
809
|
-
}
|
|
810
|
-
const summaryArgs = args ?? {};
|
|
811
|
-
return handleGetTeamSummary({
|
|
812
|
-
teamId: options.teamId,
|
|
813
|
-
accountId: options.accountId ?? '',
|
|
814
|
-
nrApiKey: options.nrApiKey,
|
|
815
|
-
collectorHost: options.collectorHost,
|
|
816
|
-
since: summaryArgs.since,
|
|
817
|
-
});
|
|
818
|
-
}
|
|
819
|
-
case 'nr_observe_subscribe_digest': {
|
|
820
|
-
if (!options.configFilePath) {
|
|
821
|
-
return {
|
|
822
|
-
content: [
|
|
823
|
-
{
|
|
824
|
-
type: 'text',
|
|
825
|
-
text: JSON.stringify({ error: 'configFilePath not available' }),
|
|
826
|
-
},
|
|
827
|
-
],
|
|
828
|
-
isError: true,
|
|
829
|
-
};
|
|
830
|
-
}
|
|
831
|
-
const digestArgs = args ?? {};
|
|
832
|
-
return handleSubscribeDigest(typeof digestArgs.webhookUrl === 'string' ? digestArgs.webhookUrl : '', options.configFilePath);
|
|
833
|
-
}
|
|
834
|
-
case 'nr_observe_unsubscribe_digest': {
|
|
835
|
-
if (!options.configFilePath) {
|
|
836
|
-
return {
|
|
837
|
-
content: [
|
|
838
|
-
{
|
|
839
|
-
type: 'text',
|
|
840
|
-
text: JSON.stringify({ error: 'configFilePath not available' }),
|
|
841
|
-
},
|
|
842
|
-
],
|
|
843
|
-
isError: true,
|
|
844
|
-
};
|
|
845
|
-
}
|
|
846
|
-
return handleUnsubscribeDigest(options.configFilePath);
|
|
847
|
-
}
|
|
848
|
-
case 'nr_observe_send_digest': {
|
|
849
|
-
if (!options.configFilePath || !weeklySummaryGenerator) {
|
|
850
|
-
return {
|
|
851
|
-
content: [
|
|
852
|
-
{
|
|
853
|
-
type: 'text',
|
|
854
|
-
text: JSON.stringify({
|
|
855
|
-
error: 'configFilePath or WeeklySummaryGenerator not available',
|
|
856
|
-
}),
|
|
857
|
-
},
|
|
858
|
-
],
|
|
859
|
-
isError: true,
|
|
860
|
-
};
|
|
861
|
-
}
|
|
862
|
-
return handleSendDigest(weeklySummaryGenerator, options.configFilePath);
|
|
863
|
-
}
|
|
864
|
-
case 'nr_observe_get_personal_insights': {
|
|
865
|
-
if (!weeklySummaryGenerator || !options.developer) {
|
|
866
|
-
return {
|
|
867
|
-
content: [
|
|
868
|
-
{
|
|
869
|
-
type: 'text',
|
|
870
|
-
text: JSON.stringify({
|
|
871
|
-
error: 'WeeklySummaryGenerator or developer not available',
|
|
872
|
-
}),
|
|
873
|
-
},
|
|
874
|
-
],
|
|
875
|
-
isError: true,
|
|
876
|
-
};
|
|
877
|
-
}
|
|
878
|
-
return handleGetPersonalInsights(weeklySummaryGenerator, options.developer);
|
|
879
|
-
}
|
|
880
|
-
case 'nr_observe_get_context_efficiency': {
|
|
881
|
-
if (!contextWindowTracker) {
|
|
882
|
-
return {
|
|
883
|
-
content: [
|
|
884
|
-
{
|
|
885
|
-
type: 'text',
|
|
886
|
-
text: JSON.stringify({ error: 'ContextWindowTracker not available' }),
|
|
887
|
-
},
|
|
888
|
-
],
|
|
889
|
-
isError: true,
|
|
890
|
-
};
|
|
891
|
-
}
|
|
892
|
-
return handleGetContextEfficiency(contextWindowTracker);
|
|
893
|
-
}
|
|
894
|
-
case 'nr_observe_get_context_tracking': {
|
|
895
|
-
if (!contextTracker) {
|
|
896
|
-
return {
|
|
897
|
-
content: [
|
|
898
|
-
{
|
|
899
|
-
type: 'text',
|
|
900
|
-
text: JSON.stringify({ error: 'ContextTracker not available' }),
|
|
901
|
-
},
|
|
902
|
-
],
|
|
903
|
-
isError: true,
|
|
904
|
-
};
|
|
905
|
-
}
|
|
906
|
-
return handleGetContextTracking(contextTracker);
|
|
907
|
-
}
|
|
908
|
-
case 'nr_observe_get_latency_percentiles': {
|
|
909
|
-
if (!latencyTracker) {
|
|
910
|
-
return {
|
|
911
|
-
content: [
|
|
912
|
-
{
|
|
913
|
-
type: 'text',
|
|
914
|
-
text: JSON.stringify({ error: 'LatencyTracker not available' }),
|
|
915
|
-
},
|
|
916
|
-
],
|
|
917
|
-
isError: true,
|
|
918
|
-
};
|
|
919
|
-
}
|
|
920
|
-
return handleGetLatencyPercentiles(latencyTracker);
|
|
921
|
-
}
|
|
922
|
-
case 'nr_observe_get_task_completion_rate': {
|
|
923
|
-
if (!taskCompletionTracker) {
|
|
924
|
-
return {
|
|
925
|
-
content: [
|
|
926
|
-
{
|
|
927
|
-
type: 'text',
|
|
928
|
-
text: JSON.stringify({ error: 'TaskCompletionTracker not available' }),
|
|
929
|
-
},
|
|
930
|
-
],
|
|
931
|
-
isError: true,
|
|
932
|
-
};
|
|
933
|
-
}
|
|
934
|
-
return handleGetTaskCompletionRate(taskCompletionTracker, taskDetector);
|
|
935
|
-
}
|
|
936
|
-
case 'nr_observe_get_model_usage': {
|
|
937
|
-
if (!modelUsageTracker) {
|
|
938
|
-
return {
|
|
939
|
-
content: [
|
|
940
|
-
{
|
|
941
|
-
type: 'text',
|
|
942
|
-
text: JSON.stringify({ error: 'ModelUsageTracker not available' }),
|
|
943
|
-
},
|
|
944
|
-
],
|
|
945
|
-
isError: true,
|
|
946
|
-
};
|
|
947
|
-
}
|
|
948
|
-
return handleGetModelUsage(modelUsageTracker);
|
|
949
|
-
}
|
|
950
|
-
case 'nr_observe_get_retry_alerts': {
|
|
951
|
-
if (!retryDetector) {
|
|
952
|
-
return {
|
|
953
|
-
content: [
|
|
954
|
-
{
|
|
955
|
-
type: 'text',
|
|
956
|
-
text: JSON.stringify({ error: 'RetryDetector not available' }),
|
|
957
|
-
},
|
|
958
|
-
],
|
|
959
|
-
isError: true,
|
|
960
|
-
};
|
|
961
|
-
}
|
|
962
|
-
return handleGetRetryAlerts(retryDetector);
|
|
963
|
-
}
|
|
964
|
-
case 'nr_observe_get_context_composition': {
|
|
965
|
-
if (!contextCompositionTracker) {
|
|
966
|
-
return {
|
|
967
|
-
content: [
|
|
968
|
-
{
|
|
969
|
-
type: 'text',
|
|
970
|
-
text: JSON.stringify({ error: 'ContextCompositionTracker not available' }),
|
|
971
|
-
},
|
|
972
|
-
],
|
|
973
|
-
isError: true,
|
|
974
|
-
};
|
|
975
|
-
}
|
|
976
|
-
return handleGetContextComposition(contextCompositionTracker);
|
|
977
|
-
}
|
|
978
|
-
case 'nr_observe_get_latency_decomposition': {
|
|
979
|
-
if (!latencyDecompositionTracker) {
|
|
980
|
-
return {
|
|
981
|
-
content: [
|
|
982
|
-
{
|
|
983
|
-
type: 'text',
|
|
984
|
-
text: JSON.stringify({
|
|
985
|
-
error: 'nr_observe_get_latency_decomposition is not currently functional',
|
|
986
|
-
note: "Preflight cannot observe a true LLM-API-vs-tool-execution split in either stdio or proxy mode -- see the comment above the tracker's instantiation in index.ts for the full explanation. This tool is intentionally not registered in tools/list.",
|
|
987
|
-
}),
|
|
988
|
-
},
|
|
989
|
-
],
|
|
990
|
-
isError: true,
|
|
991
|
-
};
|
|
992
|
-
}
|
|
993
|
-
return handleGetLatencyDecomposition(latencyDecompositionTracker);
|
|
994
|
-
}
|
|
995
|
-
case 'nr_observe_get_decision_tree': {
|
|
996
|
-
if (!decisionTracker) {
|
|
997
|
-
return {
|
|
998
|
-
content: [
|
|
999
|
-
{
|
|
1000
|
-
type: 'text',
|
|
1001
|
-
text: JSON.stringify({ error: 'DecisionTracker not available' }),
|
|
1002
|
-
},
|
|
1003
|
-
],
|
|
1004
|
-
isError: true,
|
|
1005
|
-
};
|
|
1006
|
-
}
|
|
1007
|
-
const dtArgs = args ?? {};
|
|
1008
|
-
return handleGetDecisionTree(decisionTracker, dtArgs.post_mortem === true);
|
|
1009
|
-
}
|
|
1010
|
-
case 'nr_observe_get_instruction_drift': {
|
|
1011
|
-
if (!instructionDriftTracker) {
|
|
1012
|
-
return {
|
|
1013
|
-
content: [
|
|
1014
|
-
{
|
|
1015
|
-
type: 'text',
|
|
1016
|
-
text: JSON.stringify({ error: 'InstructionDriftTracker not available' }),
|
|
1017
|
-
},
|
|
1018
|
-
],
|
|
1019
|
-
isError: true,
|
|
1020
|
-
};
|
|
1021
|
-
}
|
|
1022
|
-
return handleGetInstructionDrift(instructionDriftTracker);
|
|
1023
|
-
}
|
|
1024
|
-
case 'nr_observe_get_tool_selection_score': {
|
|
1025
|
-
if (!toolSelectionScorer || !options.toolCallBuffer) {
|
|
1026
|
-
return {
|
|
1027
|
-
content: [
|
|
1028
|
-
{
|
|
1029
|
-
type: 'text',
|
|
1030
|
-
text: JSON.stringify({
|
|
1031
|
-
error: 'ToolSelectionScorer or toolCallBuffer not available',
|
|
1032
|
-
}),
|
|
1033
|
-
},
|
|
1034
|
-
],
|
|
1035
|
-
isError: true,
|
|
1036
|
-
};
|
|
1037
|
-
}
|
|
1038
|
-
return handleGetToolSelectionScore(toolSelectionScorer, options.toolCallBuffer.getRecords());
|
|
1039
|
-
}
|
|
1040
|
-
case 'nr_observe_get_quality_proxy': {
|
|
1041
|
-
if (!qualityProxyTracker) {
|
|
1042
|
-
return {
|
|
1043
|
-
content: [
|
|
1044
|
-
{
|
|
1045
|
-
type: 'text',
|
|
1046
|
-
text: JSON.stringify({ error: 'QualityProxyTracker not available' }),
|
|
1047
|
-
},
|
|
1048
|
-
],
|
|
1049
|
-
isError: true,
|
|
1050
|
-
};
|
|
1051
|
-
}
|
|
1052
|
-
return handleGetQualityProxy(qualityProxyTracker);
|
|
1053
|
-
}
|
|
1054
|
-
case 'nr_observe_get_api_failures': {
|
|
1055
|
-
if (!apiFailureTracker) {
|
|
1056
|
-
return {
|
|
1057
|
-
content: [
|
|
1058
|
-
{
|
|
1059
|
-
type: 'text',
|
|
1060
|
-
text: JSON.stringify({ error: 'ApiFailureTracker not available' }),
|
|
1061
|
-
},
|
|
1062
|
-
],
|
|
1063
|
-
isError: true,
|
|
1064
|
-
};
|
|
1065
|
-
}
|
|
1066
|
-
return handleGetApiFailures(apiFailureTracker);
|
|
1067
|
-
}
|
|
1068
|
-
case 'nr_observe_get_cost_per_tool': {
|
|
1069
|
-
if (!turnCostAttributor) {
|
|
1070
|
-
return {
|
|
1071
|
-
content: [
|
|
1072
|
-
{
|
|
1073
|
-
type: 'text',
|
|
1074
|
-
text: JSON.stringify({ error: 'TurnCostAttributor not available' }),
|
|
1075
|
-
},
|
|
1076
|
-
],
|
|
1077
|
-
isError: true,
|
|
1078
|
-
};
|
|
1079
|
-
}
|
|
1080
|
-
const costMetrics = turnCostAttributor.getMetrics();
|
|
1081
|
-
return {
|
|
1082
|
-
content: [{ type: 'text', text: JSON.stringify(costMetrics, null, 2) }],
|
|
1083
|
-
};
|
|
1084
|
-
}
|
|
1085
|
-
case 'nr_observe_get_turn_analysis': {
|
|
1086
|
-
if (!turnTracker) {
|
|
1087
|
-
return {
|
|
1088
|
-
content: [
|
|
1089
|
-
{
|
|
1090
|
-
type: 'text',
|
|
1091
|
-
text: JSON.stringify({ error: 'TurnTracker not available' }),
|
|
1092
|
-
},
|
|
1093
|
-
],
|
|
1094
|
-
isError: true,
|
|
1095
|
-
};
|
|
1096
|
-
}
|
|
1097
|
-
const turnMetrics = turnTracker.getMetrics();
|
|
1098
|
-
return {
|
|
1099
|
-
content: [{ type: 'text', text: JSON.stringify(turnMetrics, null, 2) }],
|
|
1100
|
-
};
|
|
1101
|
-
}
|
|
1102
|
-
case 'nr_observe_get_git_efficiency': {
|
|
1103
|
-
if (!gitEfficiencyTracker) {
|
|
1104
|
-
return {
|
|
1105
|
-
content: [
|
|
1106
|
-
{
|
|
1107
|
-
type: 'text',
|
|
1108
|
-
text: JSON.stringify({ error: 'GitEfficiencyTracker not available' }),
|
|
1109
|
-
},
|
|
1110
|
-
],
|
|
1111
|
-
isError: true,
|
|
1112
|
-
};
|
|
1113
|
-
}
|
|
1114
|
-
return handleGetGitEfficiency(gitEfficiencyTracker);
|
|
1115
|
-
}
|
|
1116
|
-
default:
|
|
1117
|
-
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
|
|
1118
|
-
}
|
|
405
|
+
return await handler(args);
|
|
1119
406
|
}
|
|
1120
407
|
catch (err) {
|
|
1121
408
|
if (err instanceof McpError)
|