@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-запуска.
78 lines • 3.16 kB
JavaScript
import { ToolError } from '../lib/errors.js';
/**
* Tool: list_apps
*
* Mapping: GET /apps → apps.routes.ts:23 (требует master key, `requireMaster`).
*
* Поведение:
* - Если master-key → возвращает все apps как есть.
* - Если обычный ELS-key → 403 INSUFFICIENT_SCOPE от ELS → graceful fallback:
* отдаём `{ apps: [{ slug: '(current-app)', restricted: true }] }` с
* `_meta.warnings` и `_meta.degraded=true`. Это согласуется с принципом
* «derived from API-key context» — для обычного key пользователь и так
* работает в рамках одного app.
*
* При OAuth path: app-slug приходит из OIDC resolver (LK API) и tool
* выдаёт его без 403-fallback.
*/
export const listAppsInputShape = {};
export const listAppsToolDef = {
name: 'list_apps',
title: 'List apps available to current API-key',
description: 'List apps (tenants) accessible to the current API key. For a regular key — one app; for a master key — all active apps.',
inputShape: listAppsInputShape,
};
export async function handleListApps(_args, client) {
try {
const { data, elsRequestId } = await client.listApps();
const apps = (data?.apps ?? []).map((a) => ({
slug: a.slug,
name: a.name,
tier: a.rateLimitTier,
isActive: a.isActive,
createdAt: a.createdAt,
}));
const meta = {
elsRequestId,
cached: false,
ttlSec: 300,
redactionApplied: false,
};
return {
structuredContent: { apps, _meta: meta },
content: [{ type: 'text', text: `${apps.length} app(s) accessible.` }],
};
}
catch (err) {
if (err instanceof ToolError && err.code === 'INSUFFICIENT_SCOPE') {
// Graceful fallback: обычный ELS-key не имеет доступа к /apps,
// но всегда привязан к одному app (см. apiContext.app.slug в middleware).
const meta = {
elsRequestId: null,
cached: false,
ttlSec: 300,
redactionApplied: false,
degraded: true,
warnings: [
'API key lacks master scope; cannot enumerate apps. Returning current-app placeholder.',
],
};
return {
structuredContent: {
apps: [{ slug: '(current-app)', name: 'Current app', isActive: true, restricted: true }],
_meta: meta,
},
content: [
{
type: 'text',
text: 'Current API key is scoped to a single app. Use a master key to enumerate all apps.',
},
],
};
}
if (err instanceof ToolError)
return err.toToolResult();
throw err;
}
}
//# sourceMappingURL=listApps.js.map