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
166 lines
6.5 KiB
TypeScript
166 lines
6.5 KiB
TypeScript
/**
|
|
* LysnrAI MCP tools — lysnrai.transcripts.*, lysnrai.stt.*, lysnrai.sessions.*,
|
|
* lysnrai.orgs.*, lysnrai.apiTokens.*
|
|
*
|
|
* Backed by: lysnrai-backend (port 4015).
|
|
* All tools require admin role.
|
|
*/
|
|
|
|
import { z } from 'zod';
|
|
import { registerTool } from '../tools/registry.js';
|
|
import { config } from '../../lib/config.js';
|
|
import {
|
|
lysnraiTranscriptsList,
|
|
lysnraiTranscriptGet,
|
|
lysnraiTranscriptRunExtraction,
|
|
lysnraiSttGetBackendStatus,
|
|
lysnraiSessionGet,
|
|
lysnraiSessionsList,
|
|
lysnraiOrgsList,
|
|
lysnraiOrgGet,
|
|
lysnraiApiTokensList,
|
|
} from '../../lib/lysnrai-client.js';
|
|
import type { McpToolRequest } from '../tools/types.js';
|
|
|
|
const tokenOf = (req: McpToolRequest) => req.headers.authorization?.slice(7);
|
|
|
|
// ── lysnrai.transcripts.get ───────────────────────────────────────────────
|
|
|
|
registerTool({
|
|
name: 'lysnrai.transcripts.get',
|
|
description:
|
|
'Get a single transcript by ID, including extractions[] and extractionMetadata if extraction has run. Requires admin role.',
|
|
requiredRole: 'admin',
|
|
inputSchema: z.object({
|
|
transcriptId: z.string().min(1).describe('Transcript ID'),
|
|
}),
|
|
async execute(args, req) {
|
|
return lysnraiTranscriptGet(args.transcriptId, { token: tokenOf(req), requestId: req.id });
|
|
},
|
|
});
|
|
|
|
// ── lysnrai.transcripts.list ──────────────────────────────────────────────
|
|
|
|
registerTool({
|
|
name: 'lysnrai.transcripts.list',
|
|
description: 'List dictation transcripts for the authenticated user. Requires admin role.',
|
|
requiredRole: 'admin',
|
|
inputSchema: z.object({
|
|
limit: z.coerce.number().min(1).max(config.QUERY_MAX_LIMIT).default(config.QUERY_DEFAULT_LIMIT),
|
|
offset: z.coerce.number().min(0).default(0),
|
|
}),
|
|
async execute(args, req) {
|
|
return lysnraiTranscriptsList(args, { token: tokenOf(req), requestId: req.id });
|
|
},
|
|
});
|
|
|
|
// ── lysnrai.transcripts.runExtraction ────────────────────────────────────
|
|
|
|
registerTool({
|
|
name: 'lysnrai.transcripts.runExtraction',
|
|
description:
|
|
'Run extraction-service enrichment on a transcript — populates extractions[] and extractedAt. Best-effort: returns partial if extraction-service is unavailable. Requires admin role.',
|
|
requiredRole: 'admin',
|
|
inputSchema: z.object({
|
|
transcriptId: z.string().min(1).describe('Transcript ID (trx_... prefix)'),
|
|
}),
|
|
async execute(args, req) {
|
|
return lysnraiTranscriptRunExtraction(args.transcriptId, {
|
|
token: tokenOf(req),
|
|
requestId: req.id,
|
|
});
|
|
},
|
|
});
|
|
|
|
// ── lysnrai.stt.getBackendStatus ──────────────────────────────────────────
|
|
|
|
registerTool({
|
|
name: 'lysnrai.stt.getBackendStatus',
|
|
description:
|
|
'Report which speech-to-text backend is active: azure (Azure Speech SDK) or whisper (local Whisper model). Useful for ops health checks. Requires admin role.',
|
|
requiredRole: 'admin',
|
|
inputSchema: z.object({}),
|
|
async execute(_args, req) {
|
|
return lysnraiSttGetBackendStatus({ token: tokenOf(req), requestId: req.id });
|
|
},
|
|
});
|
|
|
|
// ── 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({
|
|
name: 'lysnrai.sessions.list',
|
|
description: 'List dictation sessions for the authenticated user. Requires admin role.',
|
|
requiredRole: 'admin',
|
|
inputSchema: z.object({
|
|
status: z
|
|
.enum(['active', 'composed', 'archived'])
|
|
.optional()
|
|
.describe('Filter by session status'),
|
|
limit: z.coerce.number().min(1).max(config.QUERY_MAX_LIMIT).default(config.QUERY_DEFAULT_LIMIT),
|
|
offset: z.coerce.number().min(0).default(0),
|
|
}),
|
|
async execute(args, req) {
|
|
return lysnraiSessionsList(args, { token: tokenOf(req), requestId: req.id });
|
|
},
|
|
});
|
|
|
|
// ── lysnrai.orgs.list ─────────────────────────────────────────────────────
|
|
|
|
registerTool({
|
|
name: 'lysnrai.orgs.list',
|
|
description: 'List organisations for the authenticated user. Requires admin role.',
|
|
requiredRole: 'admin',
|
|
inputSchema: z.object({
|
|
limit: z.coerce.number().min(1).max(config.QUERY_MAX_LIMIT).default(config.QUERY_DEFAULT_LIMIT),
|
|
offset: z.coerce.number().min(0).default(0),
|
|
}),
|
|
async execute(args, req) {
|
|
return lysnraiOrgsList(args, { token: tokenOf(req), requestId: req.id });
|
|
},
|
|
});
|
|
|
|
// ── lysnrai.orgs.get ─────────────────────────────────────────────────────
|
|
|
|
registerTool({
|
|
name: 'lysnrai.orgs.get',
|
|
description:
|
|
'Get a single organisation by ID including member count, vocabulary, and shared instructions. Requires admin role.',
|
|
requiredRole: 'admin',
|
|
inputSchema: z.object({
|
|
orgId: z.string().min(1).describe('Organisation ID'),
|
|
}),
|
|
async execute(args, req) {
|
|
return lysnraiOrgGet(args.orgId, { token: tokenOf(req), requestId: req.id });
|
|
},
|
|
});
|
|
|
|
// ── lysnrai.apiTokens.list ────────────────────────────────────────────────
|
|
|
|
registerTool({
|
|
name: 'lysnrai.apiTokens.list',
|
|
description: 'List API tokens for the authenticated user. Requires admin role.',
|
|
requiredRole: 'admin',
|
|
inputSchema: z.object({
|
|
limit: z.coerce.number().min(1).max(config.QUERY_MAX_LIMIT).default(config.QUERY_DEFAULT_LIMIT),
|
|
offset: z.coerce.number().min(0).default(0),
|
|
}),
|
|
async execute(args, req) {
|
|
return lysnraiApiTokensList(args, { token: tokenOf(req), requestId: req.id });
|
|
},
|
|
});
|