UNPKG

@inso_web/els-mcp

Version:

MCP-сервер поверх INSO Error Logs Service. Read-only tools (search, analytics, fingerprinting, correlations) для подключения Claude Desktop/Code и ChatGPT к логам ошибок. Streamable HTTP transport + stdio для npx-запуска.

91 lines 3.37 kB
import { z } from 'zod'; import { ToolError } from '../lib/errors.js'; import { encodeCursor, decodeCursor } from '../lib/cursor.js'; import { applyResponseFormat } from '../lib/responseFormat.js'; /** * Tool: errors_in_session (composite) * * Wrapper над search_logs с фиксированным sessionId, sortBy=receivedAt asc. * Используется когда саппорту дали session-ID — нужно посмотреть всю * хронологию ошибок этого пользователя. * * Cursor — passthrough из search_logs (offset-based transitional wrapper). */ export const errorsInSessionInputShape = { sessionId: z.string().min(1).max(128), from: z.string().optional(), to: z.string().optional(), limit: z.number().int().min(1).max(200).default(20), cursor: z.string().nullable().optional(), // eslint-disable-next-line camelcase response_format: z.enum(['compact', 'full', 'summary']).default('compact'), }; export const errorsInSessionToolDef = { name: 'errors_in_session', title: 'All errors in a user session', description: 'Return chronologically-ordered errors for a single session/user. Use when support gives you a session-ID and asks "what happened in this session?".', inputShape: errorsInSessionInputShape, }; function filtersFromArgs(args) { return { sessionId: args.sessionId, from: args.from, to: args.to, }; } export async function handleErrorsInSession(args, client) { try { const filters = filtersFromArgs(args); let page = 1; if (args.cursor && args.cursor.length > 0) { const decoded = decodeCursor(args.cursor, filters); page = decoded.page ?? 1; } const params = { page, limit: args.limit, sortBy: 'receivedAt', sortOrder: 'asc', sessionId: args.sessionId, from: args.from, to: args.to, }; const { data, elsRequestId } = await client.searchLogs(params); const raw = data; const { items: formattedItems, truncated } = applyResponseFormat(raw.items ?? [], args.response_format); const hasMore = raw.page * raw.limit < raw.total; let nextCursor = null; if (hasMore && raw.items.length > 0) { const lastItem = raw.items[raw.items.length - 1]; nextCursor = encodeCursor({ receivedAt: lastItem.receivedAt, id: lastItem.id }, filters, raw.page + 1, raw.limit); } const meta = { elsRequestId, cached: false, ttlSec: 30, redactionApplied: false, truncated, }; return { structuredContent: { sessionId: args.sessionId, total: raw.total, items: formattedItems, nextCursor, _meta: meta, }, content: [ { type: 'text', text: `Session ${args.sessionId}: ${raw.total} error(s) total, returning ${formattedItems.length}.`, }, ], }; } catch (err) { if (err instanceof ToolError) return err.toToolResult(); throw err; } } //# sourceMappingURL=errorsInSession.js.map