fix(mcp-server): audit fixes — 3 bugs + 2 new tools

Bug fixes:
- lysnrai: add lysnrai.sessions.get tool (GET /sessions/:id existed but had no MCP surface)
- nomgap: add nomgap.autophagyConfidence tool (POST /fasting/autophagy-confidence had no tool)
- chronomind: fix syncStatus description 'paused' -> 'pending' (wrong field name)

New client functions: lysnraiSessionGet, nomgapAutophagyConfidence (with typed interfaces)

Root bug fixed in learning_voice_ai_agent commit 42aa931:
GET /transcripts/:id was missing from backend — lysnrai.transcripts.get was always 404-ing
This commit is contained in:
saravanakumardb1 2026-03-05 14:05:03 -08:00
parent a08ca9d3ee
commit f70001de74
5 changed files with 108 additions and 1 deletions

View File

@ -111,6 +111,13 @@ export interface SessionDoc {
updatedAt: string;
}
export function lysnraiSessionGet(
sessionId: string,
opts: LysnraiClientOptions
): Promise<SessionDoc> {
return lysnraiFetch(`/sessions/${sessionId}`, { method: 'GET' }, opts);
}
export function lysnraiSessionsList(
params: { limit?: number; offset?: number; status?: string },
opts: LysnraiClientOptions

View File

@ -101,6 +101,42 @@ export function nomgapBodyStagesList(
return nomgapFetch('/fasting/stages', { method: 'GET' }, opts);
}
// ── Autophagy confidence ──────────────────────────────────────────────────
export interface AutophagyConfidenceInput {
durationHours: number;
activityLevel: 'sedentary' | 'light' | 'moderate' | 'active' | 'very_active';
lastMealCarbs?: number;
sleepHours?: number;
completionHistory?: { totalFasts: number; completionRate: number };
hrvData?: { restingHR?: number; hrv?: number };
}
export interface AutophagyConfidenceResult {
confidence: number;
label: 'unlikely' | 'possible' | 'likely' | 'very_likely' | 'near_certain';
breakdown: {
duration: number;
meal: number;
activity: number;
sleep: number;
history: number;
hrv: number;
};
currentStage: string;
}
export function nomgapAutophagyConfidence(
input: AutophagyConfidenceInput,
opts: Pick<NomGapClientOptions, 'requestId'>
): Promise<AutophagyConfidenceResult> {
return nomgapFetch(
'/fasting/autophagy-confidence',
{ method: 'POST', body: JSON.stringify(input) },
opts
);
}
// ── Push triggers ──────────────────────────────────────────────────────────
export type PushTriggerType =

View File

@ -109,7 +109,7 @@ registerTool({
registerTool({
name: 'chronomind.syncStatus',
description:
'Instant sync health check: total timers, active count, paused count, unsynced count, and last sync timestamp. Requires admin role.',
'Instant sync health check: total timers, active count, pending count, unsynced count, and last sync timestamp. Requires admin role.',
requiredRole: 'admin',
inputSchema: z.object({}),
async execute(_args, req) {

View File

@ -14,6 +14,7 @@ import {
lysnraiTranscriptGet,
lysnraiTranscriptRunExtraction,
lysnraiSttGetBackendStatus,
lysnraiSessionGet,
lysnraiSessionsList,
lysnraiOrgsList,
lysnraiOrgGet,
@ -84,6 +85,21 @@ registerTool({
},
});
// ── lysnrai.sessions.get ──────────────────────────────────────────────────
registerTool({
name: 'lysnrai.sessions.get',
description:
'Get a single dictation session by ID including its entries[], composedText, compositionHistory, and status. Requires admin role.',
requiredRole: 'admin',
inputSchema: z.object({
sessionId: z.string().min(1).describe('Session ID (ses_… prefix)'),
}),
async execute(args, req) {
return lysnraiSessionGet(args.sessionId, { token: tokenOf(req), requestId: req.id });
},
});
// ── lysnrai.sessions.list ─────────────────────────────────────────────────
registerTool({

View File

@ -14,6 +14,7 @@ import {
nomgapFastingGetWeeklyStats,
nomgapProtocolsList,
nomgapBodyStagesList,
nomgapAutophagyConfidence,
nomgapPushFire,
nomgapPushGetStats,
nomgapPushGetPending,
@ -158,6 +159,53 @@ registerTool({
},
});
// ── nomgap.autophagyConfidence ─────────────────────────────────────────────────
registerTool({
name: 'nomgap.autophagyConfidence',
description: [
'Calculate a personalised autophagy confidence score (0100) given fasting duration and biometrics.',
'Weights: duration 40%, last-meal carbs 20%, activity 15%, sleep 10%, completion history 10%, HRV 5%.',
'Returns: confidence (0100), label (unlikely/possible/likely/very_likely/near_certain), breakdown, currentStage.',
'Public endpoint — no auth required on backend.',
].join(' '),
requiredRole: 'admin',
inputSchema: z.object({
durationHours: z.coerce.number().min(0).describe('Hours elapsed since the fast started'),
activityLevel: z
.enum(['sedentary', 'light', 'moderate', 'active', 'very_active'])
.describe('Physical activity level during the fast'),
lastMealCarbs: z.coerce
.number()
.min(0)
.optional()
.describe('Grams of carbs in the last meal before the fast'),
sleepHours: z.coerce
.number()
.min(0)
.max(24)
.optional()
.describe('Hours of sleep the previous night'),
completionHistory: z
.object({
totalFasts: z.coerce.number().min(0),
completionRate: z.coerce.number().min(0).max(1),
})
.optional()
.describe('Historical fasting stats (improves scoring accuracy)'),
hrvData: z
.object({
restingHR: z.coerce.number().min(0).optional(),
hrv: z.coerce.number().min(0).optional(),
})
.optional()
.describe('Heart rate variability data from wearable'),
}),
async execute(args, req) {
return nomgapAutophagyConfidence(args, { requestId: req.id });
},
});
// ── nomgap.push.pending ───────────────────────────────────────────────────
registerTool({