@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-запуска.
83 lines • 3.3 kB
JavaScript
export class ToolError extends Error {
code;
retryAfter;
suggestedAction;
meta;
constructor(code, message, options = {}) {
super(message);
this.name = 'ToolError';
this.code = code;
if (typeof options.retryAfter === 'number')
this.retryAfter = options.retryAfter;
if (options.suggestedAction)
this.suggestedAction = options.suggestedAction;
if (options.meta)
this.meta = options.meta;
if (options.cause !== undefined) {
// Стандартный Error.cause — поддерживается Node 20+.
this.cause = options.cause;
}
}
/**
* Сериализация в MCP-tool error response.
*/
toToolResult() {
const _meta = { code: this.code };
if (typeof this.retryAfter === 'number')
_meta.retryAfter = this.retryAfter;
if (this.suggestedAction)
_meta.suggestedAction = this.suggestedAction;
if (this.meta)
Object.assign(_meta, this.meta);
return {
isError: true,
content: [{ type: 'text', text: `[${this.code}] ${this.message}` }],
structuredContent: { code: this.code, message: this.message, ...(this.meta ?? {}) },
_meta,
};
}
}
/**
* Преобразовать HTTP-статус и тело ответа ELS в ToolError.
*
* `body` приходит как уже-распарсенный JSON (или string, если parse не удался).
* `retryAfterHeader` — содержимое заголовка Retry-After (секунды).
*/
export function mapHttpToToolError(status, body, retryAfterHeader) {
const bodyAny = body;
const upstreamMessage = (typeof bodyAny?.message === 'string' && bodyAny.message) ||
(typeof bodyAny?.error === 'string' && bodyAny.error) ||
`Upstream ELS returned ${status}`;
if (status === 429) {
const retryAfter = retryAfterHeader ? Number(retryAfterHeader) : undefined;
return new ToolError('RATE_LIMITED', upstreamMessage, {
retryAfter: Number.isFinite(retryAfter) ? retryAfter : 60,
suggestedAction: 'Wait and retry after the specified number of seconds.',
});
}
if (status === 404) {
return new ToolError('NOT_FOUND', upstreamMessage);
}
if (status === 403) {
return new ToolError('INSUFFICIENT_SCOPE', upstreamMessage, {
suggestedAction: 'API-key lacks required scope. Use a key with broader access.',
});
}
if (status === 401) {
return new ToolError('INSUFFICIENT_SCOPE', `Unauthorized: ${upstreamMessage}`, {
suggestedAction: 'Check ELS_API_KEY env var.',
});
}
if (status >= 400 && status < 500) {
return new ToolError('INVALID_ARGS', upstreamMessage, { meta: { status } });
}
if (status >= 500) {
return new ToolError('UPSTREAM_UNAVAILABLE', upstreamMessage, {
retryAfter: 5,
suggestedAction: 'Upstream is temporarily unavailable; retry in a few seconds.',
meta: { status },
});
}
return new ToolError('INTERNAL', upstreamMessage, { meta: { status } });
}
//# sourceMappingURL=errors.js.map