@lionchat/mcp-server 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +313 -0
- package/dist/client.d.ts +27 -0
- package/dist/client.js +264 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.js +57 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/tools.d.ts +4 -0
- package/dist/tools.js +280 -0
- package/dist/tools.js.map +1 -0
- package/dist/utils.d.ts +12 -0
- package/dist/utils.js +80 -0
- package/dist/utils.js.map +1 -0
- package/endpoints.json +12655 -0
- package/package.json +32 -0
package/dist/config.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// AIDEV-NOTE: Config module for LionChat MCP server
|
|
2
|
+
// Reads configuration from CLI args (--key=value) and env vars, CLI takes priority
|
|
3
|
+
// AIDEV-NOTE: Parse CLI args from process.argv looking for --key=value and --flag patterns
|
|
4
|
+
function getCliArg(name) {
|
|
5
|
+
const prefix = `--${name}=`;
|
|
6
|
+
for (const arg of process.argv) {
|
|
7
|
+
if (arg.startsWith(prefix)) {
|
|
8
|
+
return arg.slice(prefix.length);
|
|
9
|
+
}
|
|
10
|
+
// AIDEV-NOTE: Boolean flag support (--flag without =value)
|
|
11
|
+
if (arg === `--${name}`) {
|
|
12
|
+
return 'true';
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
// AIDEV-NOTE: Categories come as comma-separated string, parse into array or null
|
|
18
|
+
function parseCategories(raw) {
|
|
19
|
+
if (!raw || raw.trim() === '') {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
return raw
|
|
23
|
+
.split(',')
|
|
24
|
+
.map((c) => c.trim())
|
|
25
|
+
.filter((c) => c.length > 0);
|
|
26
|
+
}
|
|
27
|
+
// AIDEV-NOTE: Priority: CLI args > env vars > defaults
|
|
28
|
+
export function loadConfig() {
|
|
29
|
+
const apiToken = getCliArg('token') ?? process.env.LIONCHAT_API_TOKEN ?? undefined;
|
|
30
|
+
const accountId = getCliArg('account') ?? process.env.LIONCHAT_ACCOUNT_ID ?? undefined;
|
|
31
|
+
const baseUrl = getCliArg('base-url') ??
|
|
32
|
+
process.env.LIONCHAT_BASE_URL ??
|
|
33
|
+
'https://app.lionchat.com.br';
|
|
34
|
+
const categoriesRaw = getCliArg('categories') ?? process.env.LIONCHAT_CATEGORIES ?? undefined;
|
|
35
|
+
const includePublicApiRaw = getCliArg('include-public-api') ??
|
|
36
|
+
process.env.LIONCHAT_INCLUDE_PUBLIC_API ??
|
|
37
|
+
undefined;
|
|
38
|
+
// AIDEV-NOTE: Validate required fields with actionable error messages
|
|
39
|
+
if (!apiToken) {
|
|
40
|
+
throw new Error('Error: LIONCHAT_API_TOKEN is required.\n' +
|
|
41
|
+
'Set it as an environment variable or pass --token=YOUR_TOKEN\n' +
|
|
42
|
+
'Get your token at: Login > Profile Settings');
|
|
43
|
+
}
|
|
44
|
+
if (!accountId) {
|
|
45
|
+
throw new Error('Error: LIONCHAT_ACCOUNT_ID is required.\n' +
|
|
46
|
+
'Set it as an environment variable or pass --account=YOUR_ACCOUNT_ID\n' +
|
|
47
|
+
'Find your account ID at: Login > Settings > Account');
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
apiToken,
|
|
51
|
+
accountId,
|
|
52
|
+
baseUrl,
|
|
53
|
+
categories: parseCategories(categoriesRaw),
|
|
54
|
+
includePublicApi: includePublicApiRaw === 'true' || includePublicApiRaw === '1',
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,mFAAmF;AAUnF,2FAA2F;AAC3F,SAAS,SAAS,CAAC,IAAY;IAC7B,MAAM,MAAM,GAAG,KAAK,IAAI,GAAG,CAAC;IAC5B,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QAC/B,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,OAAO,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAClC,CAAC;QACD,2DAA2D;QAC3D,IAAI,GAAG,KAAK,KAAK,IAAI,EAAE,EAAE,CAAC;YACxB,OAAO,MAAM,CAAC;QAChB,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,kFAAkF;AAClF,SAAS,eAAe,CAAC,GAAuB;IAC9C,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,GAAG;SACP,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACjC,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,UAAU;IACxB,MAAM,QAAQ,GACZ,SAAS,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,SAAS,CAAC;IAEpE,MAAM,SAAS,GACb,SAAS,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,SAAS,CAAC;IAEvE,MAAM,OAAO,GACX,SAAS,CAAC,UAAU,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,iBAAiB;QAC7B,6BAA6B,CAAC;IAEhC,MAAM,aAAa,GACjB,SAAS,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,SAAS,CAAC;IAE1E,MAAM,mBAAmB,GACvB,SAAS,CAAC,oBAAoB,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,2BAA2B;QACvC,SAAS,CAAC;IAEZ,sEAAsE;IACtE,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CACb,0CAA0C;YACxC,gEAAgE;YAChE,6CAA6C,CAChD,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,2CAA2C;YACzC,uEAAuE;YACvE,qDAAqD,CACxD,CAAC;IACJ,CAAC;IAED,OAAO;QACL,QAAQ;QACR,SAAS;QACT,OAAO;QACP,UAAU,EAAE,eAAe,CAAC,aAAa,CAAC;QAC1C,gBAAgB,EACd,mBAAmB,KAAK,MAAM,IAAI,mBAAmB,KAAK,GAAG;KAChE,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { readFileSync } from 'fs';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
import { dirname, resolve } from 'path';
|
|
7
|
+
import { loadConfig } from './config.js';
|
|
8
|
+
import { LionChatClient } from './client.js';
|
|
9
|
+
import { registerTools } from './tools.js';
|
|
10
|
+
// AIDEV-NOTE: Read version from package.json to avoid hardcoding in multiple places
|
|
11
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
const pkg = JSON.parse(readFileSync(resolve(__dirname, '..', 'package.json'), 'utf-8'));
|
|
13
|
+
const VERSION = pkg.version;
|
|
14
|
+
async function main() {
|
|
15
|
+
try {
|
|
16
|
+
// AIDEV-NOTE: Load configuration from env vars (LIONCHAT_BASE_URL, LIONCHAT_API_TOKEN, etc.)
|
|
17
|
+
const config = loadConfig();
|
|
18
|
+
// AIDEV-NOTE: Warn if base URL is not HTTPS (token would be sent in cleartext)
|
|
19
|
+
if (!config.baseUrl.startsWith('https://') &&
|
|
20
|
+
!config.baseUrl.includes('localhost') &&
|
|
21
|
+
!config.baseUrl.includes('127.0.0.1')) {
|
|
22
|
+
console.error('WARNING: Base URL is not HTTPS. API token may be transmitted in cleartext.');
|
|
23
|
+
}
|
|
24
|
+
// AIDEV-NOTE: Create MCP server instance with name and version from package.json
|
|
25
|
+
const server = new McpServer({
|
|
26
|
+
name: 'lionchat-mcp-server',
|
|
27
|
+
version: VERSION,
|
|
28
|
+
});
|
|
29
|
+
// AIDEV-NOTE: Create HTTP client that wraps fetch calls to LionChat API
|
|
30
|
+
const client = new LionChatClient(config);
|
|
31
|
+
// AIDEV-NOTE: Register tools from endpoints.json, filtered by config.categories if set
|
|
32
|
+
const toolCount = registerTools(server, config, client);
|
|
33
|
+
// AIDEV-NOTE: Use stderr for logs — stdout is reserved for MCP JSON-RPC protocol
|
|
34
|
+
console.error(`LionChat MCP Server v${VERSION}`);
|
|
35
|
+
console.error(`Base URL: ${config.baseUrl}`);
|
|
36
|
+
console.error(`Account: ${config.accountId}`);
|
|
37
|
+
console.error(`Tools registered: ${toolCount}`);
|
|
38
|
+
if (config.categories) {
|
|
39
|
+
console.error(`Categories filter: ${config.categories.join(', ')}`);
|
|
40
|
+
}
|
|
41
|
+
// AIDEV-NOTE: Connect via stdio transport (stdin/stdout JSON-RPC)
|
|
42
|
+
const transport = new StdioServerTransport();
|
|
43
|
+
await server.connect(transport);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
main();
|
|
51
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,oFAAoF;AACpF,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AACxF,MAAM,OAAO,GAAW,GAAG,CAAC,OAAO,CAAC;AAEpC,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,6FAA6F;QAC7F,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;QAE5B,+EAA+E;QAC/E,IACE,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC;YACtC,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;YACrC,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,EACrC,CAAC;YACD,OAAO,CAAC,KAAK,CAAC,4EAA4E,CAAC,CAAC;QAC9F,CAAC;QAED,iFAAiF;QACjF,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;YAC3B,IAAI,EAAE,qBAAqB;YAC3B,OAAO,EAAE,OAAO;SACjB,CAAC,CAAC;QAEH,wEAAwE;QACxE,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;QAE1C,uFAAuF;QACvF,MAAM,SAAS,GAAG,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QAExD,iFAAiF;QACjF,OAAO,CAAC,KAAK,CAAC,wBAAwB,OAAO,EAAE,CAAC,CAAC;QACjD,OAAO,CAAC,KAAK,CAAC,aAAa,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7C,OAAO,CAAC,KAAK,CAAC,YAAY,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;QAC9C,OAAO,CAAC,KAAK,CAAC,qBAAqB,SAAS,EAAE,CAAC,CAAC;QAChD,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YACtB,OAAO,CAAC,KAAK,CAAC,sBAAsB,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACtE,CAAC;QAED,kEAAkE;QAClE,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACtE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
|
package/dist/tools.d.ts
ADDED
package/dist/tools.js
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
// AIDEV-NOTE: Tool registration module for LionChat MCP server
|
|
2
|
+
// Reads endpoints.json and registers each endpoint as an MCP tool with Zod schemas
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { substitutePath, buildQueryString, formatResponse, separateParams, } from './utils.js';
|
|
5
|
+
import { readFileSync } from 'fs';
|
|
6
|
+
import { resolve, dirname } from 'path';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
// AIDEV-NOTE: Map HTTP method to tool annotations for MCP client hinting
|
|
9
|
+
function getToolAnnotations(method) {
|
|
10
|
+
switch (method.toUpperCase()) {
|
|
11
|
+
case 'GET':
|
|
12
|
+
return { readOnlyHint: true, destructiveHint: false, idempotentHint: true };
|
|
13
|
+
case 'POST':
|
|
14
|
+
return { readOnlyHint: false, destructiveHint: false, idempotentHint: false };
|
|
15
|
+
case 'PATCH':
|
|
16
|
+
case 'PUT':
|
|
17
|
+
return { readOnlyHint: false, destructiveHint: false, idempotentHint: true };
|
|
18
|
+
case 'DELETE':
|
|
19
|
+
return { readOnlyHint: false, destructiveHint: true, idempotentHint: true };
|
|
20
|
+
default:
|
|
21
|
+
return { readOnlyHint: false, destructiveHint: false, idempotentHint: false };
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// AIDEV-NOTE: Normalize category names to URL-safe slugs (lowercase, underscores, no accents)
|
|
25
|
+
// AIDEV-NOTE: Category slug map — Portuguese category names to English slugs.
|
|
26
|
+
// Used for --categories filter matching. Slugs match the tool ID prefix pattern.
|
|
27
|
+
const CATEGORY_SLUG_MAP = {
|
|
28
|
+
'conta': 'account',
|
|
29
|
+
'respostas rapidas': 'canned_responses',
|
|
30
|
+
'contatos': 'contacts',
|
|
31
|
+
'conversas': 'conversations',
|
|
32
|
+
'caixas de entrada': 'inboxes',
|
|
33
|
+
'mensagens': 'messages',
|
|
34
|
+
'times': 'teams',
|
|
35
|
+
'labels': 'labels',
|
|
36
|
+
'filtros personalizados': 'custom_filters',
|
|
37
|
+
'macros': 'macros',
|
|
38
|
+
'busca': 'search',
|
|
39
|
+
'notificacoes': 'notifications',
|
|
40
|
+
'anuncios': 'announcements',
|
|
41
|
+
'empresas': 'companies',
|
|
42
|
+
'ofertas': 'offers',
|
|
43
|
+
'upload': 'upload',
|
|
44
|
+
'agenda / tarefas': 'tasks',
|
|
45
|
+
'variaveis da conta': 'account_variables',
|
|
46
|
+
'mensagens agendadas': 'scheduled_messages',
|
|
47
|
+
'funis': 'funnels',
|
|
48
|
+
'itens': 'kanban_items',
|
|
49
|
+
'operacoes em massa': 'kanban_bulk',
|
|
50
|
+
'agentes (kanban)': 'kanban_agents',
|
|
51
|
+
'checklist': 'kanban_checklist',
|
|
52
|
+
'notas': 'kanban_notes',
|
|
53
|
+
'contatos (cliente)': 'public_contacts',
|
|
54
|
+
'conversas (cliente)': 'public_conversations',
|
|
55
|
+
'mensagens (cliente)': 'public_messages',
|
|
56
|
+
'pesquisa csat': 'public_csat',
|
|
57
|
+
'sessoes': 'flow_sessions',
|
|
58
|
+
'tipos de evento': 'booking_event_types',
|
|
59
|
+
'publica': 'public_booking',
|
|
60
|
+
'chamadas': 'voip_calls',
|
|
61
|
+
'flows': 'flows',
|
|
62
|
+
'assistentes': 'captain_assistants',
|
|
63
|
+
'base de conhecimento': 'captain_documents',
|
|
64
|
+
'regras de automacao': 'automation_rules',
|
|
65
|
+
'roles personalizados': 'custom_roles',
|
|
66
|
+
'politicas de capacidade': 'capacity_policies',
|
|
67
|
+
'sla': 'sla',
|
|
68
|
+
'acesso de suporte': 'support_access',
|
|
69
|
+
'dashboard apps': 'dashboard_apps',
|
|
70
|
+
'grupos whatsapp': 'waha_groups',
|
|
71
|
+
'templates whatsapp': 'whatsapp_templates',
|
|
72
|
+
'csat template': 'csat_template',
|
|
73
|
+
'migracao de inbox': 'inbox_migration',
|
|
74
|
+
'google calendar': 'google_calendar',
|
|
75
|
+
'politicas de atribuicao': 'assignment_policies',
|
|
76
|
+
'webhooks': 'webhooks',
|
|
77
|
+
'integracoes e-commerce': 'ecommerce_webhooks',
|
|
78
|
+
'meta lead ads': 'meta_lead',
|
|
79
|
+
'config kanban': 'kanban_config',
|
|
80
|
+
'kanban v2': 'kanban_v2',
|
|
81
|
+
'portais': 'portals',
|
|
82
|
+
'config de notificacao': 'notification_settings',
|
|
83
|
+
'relatorios': 'reports',
|
|
84
|
+
'prompts salvos': 'copilot_prompts',
|
|
85
|
+
'membros de inbox': 'inbox_members',
|
|
86
|
+
'disponibilidade': 'agent_availability',
|
|
87
|
+
'csat': 'csat',
|
|
88
|
+
'atributos personalizados': 'custom_attributes',
|
|
89
|
+
'agentes': 'agents',
|
|
90
|
+
};
|
|
91
|
+
function slugify(text) {
|
|
92
|
+
const normalized = text
|
|
93
|
+
.normalize('NFD')
|
|
94
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
95
|
+
.toLowerCase()
|
|
96
|
+
.trim();
|
|
97
|
+
return CATEGORY_SLUG_MAP[normalized] || normalized.replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, '');
|
|
98
|
+
}
|
|
99
|
+
// AIDEV-NOTE: Map endpoint param type strings to Zod schema types
|
|
100
|
+
function paramTypeToZod(param) {
|
|
101
|
+
let schema;
|
|
102
|
+
switch (param.type) {
|
|
103
|
+
case 'integer':
|
|
104
|
+
schema = z.number().int();
|
|
105
|
+
break;
|
|
106
|
+
case 'number':
|
|
107
|
+
schema = z.number();
|
|
108
|
+
break;
|
|
109
|
+
case 'boolean':
|
|
110
|
+
schema = z.boolean();
|
|
111
|
+
break;
|
|
112
|
+
case 'object':
|
|
113
|
+
schema = z.record(z.unknown());
|
|
114
|
+
break;
|
|
115
|
+
case 'array':
|
|
116
|
+
schema = z.array(z.unknown());
|
|
117
|
+
break;
|
|
118
|
+
case 'file':
|
|
119
|
+
schema = z
|
|
120
|
+
.string()
|
|
121
|
+
.describe('File path or URL — file upload not supported in MCP v1');
|
|
122
|
+
break;
|
|
123
|
+
case 'string':
|
|
124
|
+
default:
|
|
125
|
+
schema = z.string();
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
// AIDEV-NOTE: Add param description unless already set (file type sets its own)
|
|
129
|
+
if (param.type !== 'file' && param.description) {
|
|
130
|
+
schema = schema.describe(param.description);
|
|
131
|
+
}
|
|
132
|
+
if (!param.required) {
|
|
133
|
+
schema = schema.optional();
|
|
134
|
+
}
|
|
135
|
+
return schema;
|
|
136
|
+
}
|
|
137
|
+
// AIDEV-NOTE: Build Zod object schema from endpoint params, skipping account_id (auto-injected)
|
|
138
|
+
function buildZodSchema(params) {
|
|
139
|
+
const shape = {};
|
|
140
|
+
for (const param of params) {
|
|
141
|
+
// AIDEV-NOTE: account_id is auto-injected from config, never exposed to MCP client
|
|
142
|
+
if (param.name === 'account_id') {
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
shape[param.name] = paramTypeToZod(param);
|
|
146
|
+
}
|
|
147
|
+
return z.object(shape);
|
|
148
|
+
}
|
|
149
|
+
// AIDEV-NOTE: Check if endpoint has any file-type params (unsupported in MCP v1)
|
|
150
|
+
function hasFileParam(params) {
|
|
151
|
+
return params.some((p) => p.type === 'file');
|
|
152
|
+
}
|
|
153
|
+
// AIDEV-NOTE: Register a single API endpoint as an MCP tool
|
|
154
|
+
function registerSingleTool(server, config, client, endpoint) {
|
|
155
|
+
const schema = buildZodSchema(endpoint.params);
|
|
156
|
+
const annotations = getToolAnnotations(endpoint.method);
|
|
157
|
+
const hasFile = hasFileParam(endpoint.params);
|
|
158
|
+
// AIDEV-NOTE: Prepend file upload warning to description when endpoint needs file params
|
|
159
|
+
let description = `[${endpoint.method.toUpperCase()}] ${endpoint.description}`;
|
|
160
|
+
if (hasFile) {
|
|
161
|
+
description =
|
|
162
|
+
'⚠️ This endpoint requires file upload which is not yet supported via MCP.\n\n' +
|
|
163
|
+
description;
|
|
164
|
+
}
|
|
165
|
+
server.tool(endpoint.id, description, schema.shape, annotations, async (params) => {
|
|
166
|
+
try {
|
|
167
|
+
// AIDEV-NOTE: Block execution if file param was actually provided
|
|
168
|
+
if (hasFile) {
|
|
169
|
+
const fileParams = endpoint.params.filter((p) => p.type === 'file');
|
|
170
|
+
for (const fp of fileParams) {
|
|
171
|
+
if (params[fp.name] !== undefined && params[fp.name] !== null) {
|
|
172
|
+
return {
|
|
173
|
+
content: [
|
|
174
|
+
{
|
|
175
|
+
type: 'text',
|
|
176
|
+
text: 'File upload is not supported via MCP. Use the LionChat web interface or direct API calls.',
|
|
177
|
+
},
|
|
178
|
+
],
|
|
179
|
+
isError: true,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
const { pathParams, queryParams, bodyParams } = separateParams(params, endpoint.params);
|
|
185
|
+
const path = substitutePath(endpoint.path, config.accountId, pathParams);
|
|
186
|
+
const queryStr = buildQueryString(queryParams);
|
|
187
|
+
const fullPath = queryStr ? `${path}${queryStr}` : path;
|
|
188
|
+
const result = await client.request({
|
|
189
|
+
method: endpoint.method,
|
|
190
|
+
path: fullPath,
|
|
191
|
+
body: Object.keys(bodyParams).length > 0 ? bodyParams : undefined,
|
|
192
|
+
});
|
|
193
|
+
return {
|
|
194
|
+
content: [{ type: 'text', text: formatResponse(result) }],
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
catch (err) {
|
|
198
|
+
// AIDEV-NOTE: Return actionable error messages from LionChatApiError to the LLM
|
|
199
|
+
// instead of letting MCP SDK swallow them into generic protocol errors
|
|
200
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
201
|
+
return {
|
|
202
|
+
content: [{ type: 'text', text: message }],
|
|
203
|
+
isError: true,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
// AIDEV-NOTE: Meta tool — tests connectivity by calling GET /api/v1/profile
|
|
209
|
+
function registerPingTool(server, config, client) {
|
|
210
|
+
server.tool('lionchat_ping', 'Test connectivity to the LionChat API. Returns your user profile if the token is valid.', {}, { readOnlyHint: true, destructiveHint: false, idempotentHint: true }, async () => {
|
|
211
|
+
try {
|
|
212
|
+
const result = await client.request({
|
|
213
|
+
method: 'GET',
|
|
214
|
+
path: '/api/v1/profile',
|
|
215
|
+
});
|
|
216
|
+
return {
|
|
217
|
+
content: [{ type: 'text', text: formatResponse(result) }],
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
catch (err) {
|
|
221
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
222
|
+
return {
|
|
223
|
+
content: [{ type: 'text', text: message }],
|
|
224
|
+
isError: true,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
// AIDEV-NOTE: Meta tool — lists all available categories with tool counts (no API call)
|
|
230
|
+
function registerListCategoriesTool(server, allEndpoints) {
|
|
231
|
+
// AIDEV-NOTE: Pre-compute category counts at registration time (static data)
|
|
232
|
+
const categoryCounts = new Map();
|
|
233
|
+
for (const ep of allEndpoints) {
|
|
234
|
+
const slug = slugify(ep.category);
|
|
235
|
+
categoryCounts.set(slug, (categoryCounts.get(slug) ?? 0) + 1);
|
|
236
|
+
}
|
|
237
|
+
const categoryList = Array.from(categoryCounts.entries())
|
|
238
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
239
|
+
.map(([slug, count]) => `${slug}: ${count} tools`)
|
|
240
|
+
.join('\n');
|
|
241
|
+
server.tool('lionchat_list_categories', 'List all available API categories and how many tools each has. Use category slugs with the --categories config flag to filter tools.', {}, { readOnlyHint: true, destructiveHint: false, idempotentHint: true }, async () => {
|
|
242
|
+
return {
|
|
243
|
+
content: [{ type: 'text', text: categoryList }],
|
|
244
|
+
};
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
// AIDEV-NOTE: Main entry point — reads endpoints.json, filters, and registers all tools + meta tools
|
|
248
|
+
export function registerTools(server, config, client) {
|
|
249
|
+
// AIDEV-NOTE: Resolve endpoints.json relative to compiled dist/ directory (one level up)
|
|
250
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
251
|
+
const endpointsPath = resolve(__dirname, '..', 'endpoints.json');
|
|
252
|
+
let endpoints;
|
|
253
|
+
try {
|
|
254
|
+
endpoints = JSON.parse(readFileSync(endpointsPath, 'utf-8'));
|
|
255
|
+
}
|
|
256
|
+
catch (err) {
|
|
257
|
+
throw new Error(`Failed to load endpoints.json from ${endpointsPath}. ` +
|
|
258
|
+
`Reinstall with: npm install @lionchat/mcp-server\n` +
|
|
259
|
+
`Original error: ${err instanceof Error ? err.message : String(err)}`);
|
|
260
|
+
}
|
|
261
|
+
let filtered = endpoints;
|
|
262
|
+
// AIDEV-NOTE: Filter by category slugs if configured via --categories or env var
|
|
263
|
+
if (config.categories) {
|
|
264
|
+
const allowedSlugs = new Set(config.categories.map(slugify));
|
|
265
|
+
filtered = endpoints.filter((e) => allowedSlugs.has(slugify(e.category)));
|
|
266
|
+
}
|
|
267
|
+
// AIDEV-NOTE: Exclude public API endpoints unless explicitly opted in
|
|
268
|
+
if (!config.includePublicApi) {
|
|
269
|
+
filtered = filtered.filter((e) => !e.id.startsWith('lionchat_public_'));
|
|
270
|
+
}
|
|
271
|
+
// AIDEV-NOTE: Register each filtered endpoint as an MCP tool
|
|
272
|
+
for (const endpoint of filtered) {
|
|
273
|
+
registerSingleTool(server, config, client, endpoint);
|
|
274
|
+
}
|
|
275
|
+
// AIDEV-NOTE: Always register meta tools regardless of category filters
|
|
276
|
+
registerPingTool(server, config, client);
|
|
277
|
+
registerListCategoriesTool(server, endpoints);
|
|
278
|
+
return filtered.length + 2; // +2 for ping and list_categories
|
|
279
|
+
}
|
|
280
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,mFAAmF;AAEnF,OAAO,EAAE,CAAC,EAAc,MAAM,KAAK,CAAC;AAIpC,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,cAAc,GACf,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AA4BpC,yEAAyE;AACzE,SAAS,kBAAkB,CAAC,MAAc;IACxC,QAAQ,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC;QAC7B,KAAK,KAAK;YACR,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC;QAC9E,KAAK,MAAM;YACT,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC;QAChF,KAAK,OAAO,CAAC;QACb,KAAK,KAAK;YACR,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC;QAC/E,KAAK,QAAQ;YACX,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC;QAC9E;YACE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC;IAClF,CAAC;AACH,CAAC;AAED,8FAA8F;AAC9F,8EAA8E;AAC9E,iFAAiF;AACjF,MAAM,iBAAiB,GAA2B;IAChD,OAAO,EAAE,SAAS;IAClB,mBAAmB,EAAE,kBAAkB;IACvC,UAAU,EAAE,UAAU;IACtB,WAAW,EAAE,eAAe;IAC5B,mBAAmB,EAAE,SAAS;IAC9B,WAAW,EAAE,UAAU;IACvB,OAAO,EAAE,OAAO;IAChB,QAAQ,EAAE,QAAQ;IAClB,wBAAwB,EAAE,gBAAgB;IAC1C,QAAQ,EAAE,QAAQ;IAClB,OAAO,EAAE,QAAQ;IACjB,cAAc,EAAE,eAAe;IAC/B,UAAU,EAAE,eAAe;IAC3B,UAAU,EAAE,WAAW;IACvB,SAAS,EAAE,QAAQ;IACnB,QAAQ,EAAE,QAAQ;IAClB,kBAAkB,EAAE,OAAO;IAC3B,oBAAoB,EAAE,mBAAmB;IACzC,qBAAqB,EAAE,oBAAoB;IAC3C,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,cAAc;IACvB,oBAAoB,EAAE,aAAa;IACnC,kBAAkB,EAAE,eAAe;IACnC,WAAW,EAAE,kBAAkB;IAC/B,OAAO,EAAE,cAAc;IACvB,oBAAoB,EAAE,iBAAiB;IACvC,qBAAqB,EAAE,sBAAsB;IAC7C,qBAAqB,EAAE,iBAAiB;IACxC,eAAe,EAAE,aAAa;IAC9B,SAAS,EAAE,eAAe;IAC1B,iBAAiB,EAAE,qBAAqB;IACxC,SAAS,EAAE,gBAAgB;IAC3B,UAAU,EAAE,YAAY;IACxB,OAAO,EAAE,OAAO;IAChB,aAAa,EAAE,oBAAoB;IACnC,sBAAsB,EAAE,mBAAmB;IAC3C,qBAAqB,EAAE,kBAAkB;IACzC,sBAAsB,EAAE,cAAc;IACtC,yBAAyB,EAAE,mBAAmB;IAC9C,KAAK,EAAE,KAAK;IACZ,mBAAmB,EAAE,gBAAgB;IACrC,gBAAgB,EAAE,gBAAgB;IAClC,iBAAiB,EAAE,aAAa;IAChC,oBAAoB,EAAE,oBAAoB;IAC1C,eAAe,EAAE,eAAe;IAChC,mBAAmB,EAAE,iBAAiB;IACtC,iBAAiB,EAAE,iBAAiB;IACpC,yBAAyB,EAAE,qBAAqB;IAChD,UAAU,EAAE,UAAU;IACtB,wBAAwB,EAAE,oBAAoB;IAC9C,eAAe,EAAE,WAAW;IAC5B,eAAe,EAAE,eAAe;IAChC,WAAW,EAAE,WAAW;IACxB,SAAS,EAAE,SAAS;IACpB,uBAAuB,EAAE,uBAAuB;IAChD,YAAY,EAAE,SAAS;IACvB,gBAAgB,EAAE,iBAAiB;IACnC,kBAAkB,EAAE,eAAe;IACnC,iBAAiB,EAAE,oBAAoB;IACvC,MAAM,EAAE,MAAM;IACd,0BAA0B,EAAE,mBAAmB;IAC/C,SAAS,EAAE,QAAQ;CACpB,CAAC;AAEF,SAAS,OAAO,CAAC,IAAY;IAC3B,MAAM,UAAU,GAAG,IAAI;SACpB,SAAS,CAAC,KAAK,CAAC;SAChB,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;SAC/B,WAAW,EAAE;SACb,IAAI,EAAE,CAAC;IACV,OAAO,iBAAiB,CAAC,UAAU,CAAC,IAAI,UAAU,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AACzG,CAAC;AAED,kEAAkE;AAClE,SAAS,cAAc,CAAC,KAAoB;IAC1C,IAAI,MAAkB,CAAC;IAEvB,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,SAAS;YACZ,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC;YAC1B,MAAM;QACR,KAAK,QAAQ;YACX,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC;YACpB,MAAM;QACR,KAAK,SAAS;YACZ,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;YACrB,MAAM;QACR,KAAK,QAAQ;YACX,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;YAC/B,MAAM;QACR,KAAK,OAAO;YACV,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;YAC9B,MAAM;QACR,KAAK,MAAM;YACT,MAAM,GAAG,CAAC;iBACP,MAAM,EAAE;iBACR,QAAQ,CACP,wDAAwD,CACzD,CAAC;YACJ,MAAM;QACR,KAAK,QAAQ,CAAC;QACd;YACE,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC;YACpB,MAAM;IACV,CAAC;IAED,gFAAgF;IAChF,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QAC/C,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAC9C,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;QACpB,MAAM,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC7B,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,gGAAgG;AAChG,SAAS,cAAc,CACrB,MAAuB;IAEvB,MAAM,KAAK,GAA+B,EAAE,CAAC;IAE7C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,mFAAmF;QACnF,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAChC,SAAS;QACX,CAAC;QACD,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IAC5C,CAAC;IAED,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACzB,CAAC;AAED,iFAAiF;AACjF,SAAS,YAAY,CAAC,MAAuB;IAC3C,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;AAC/C,CAAC;AAED,4DAA4D;AAC5D,SAAS,kBAAkB,CACzB,MAAiB,EACjB,MAAc,EACd,MAAsB,EACtB,QAAqB;IAErB,MAAM,MAAM,GAAG,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,WAAW,GAAG,kBAAkB,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACxD,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAE9C,yFAAyF;IACzF,IAAI,WAAW,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,QAAQ,CAAC,WAAW,EAAE,CAAC;IAC/E,IAAI,OAAO,EAAE,CAAC;QACZ,WAAW;YACT,+EAA+E;gBAC/E,WAAW,CAAC;IAChB,CAAC;IAED,MAAM,CAAC,IAAI,CACT,QAAQ,CAAC,EAAE,EACX,WAAW,EACX,MAAM,CAAC,KAAK,EACZ,WAAW,EACX,KAAK,EAAE,MAA+B,EAAE,EAAE;QACxC,IAAI,CAAC;YACH,kEAAkE;YAClE,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;gBACpE,KAAK,MAAM,EAAE,IAAI,UAAU,EAAE,CAAC;oBAC5B,IAAI,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,SAAS,IAAI,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;wBAC9D,OAAO;4BACL,OAAO,EAAE;gCACP;oCACE,IAAI,EAAE,MAAe;oCACrB,IAAI,EAAE,2FAA2F;iCAClG;6BACF;4BACD,OAAO,EAAE,IAAI;yBACd,CAAC;oBACJ,CAAC;gBACH,CAAC;YACH,CAAC;YAED,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,cAAc,CAC5D,MAAM,EACN,QAAQ,CAAC,MAAM,CAChB,CAAC;YAEF,MAAM,IAAI,GAAG,cAAc,CACzB,QAAQ,CAAC,IAAI,EACb,MAAM,CAAC,SAAS,EAChB,UAAU,CACX,CAAC;YACF,MAAM,QAAQ,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;YAC/C,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;YAExD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC;gBAClC,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;aAClE,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;aACnE,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,gFAAgF;YAChF,uEAAuE;YACvE,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;gBACnD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC;AAED,4EAA4E;AAC5E,SAAS,gBAAgB,CACvB,MAAiB,EACjB,MAAc,EACd,MAAsB;IAEtB,MAAM,CAAC,IAAI,CACT,eAAe,EACf,yFAAyF,EACzF,EAAE,EACF,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,EACpE,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC;gBAClC,MAAM,EAAE,KAAK;gBACb,IAAI,EAAE,iBAAiB;aACxB,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;aACnE,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;gBACnD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC;AAED,wFAAwF;AACxF,SAAS,0BAA0B,CACjC,MAAiB,EACjB,YAA2B;IAE3B,6EAA6E;IAC7E,MAAM,cAAc,GAAG,IAAI,GAAG,EAAkB,CAAC;IACjD,KAAK,MAAM,EAAE,IAAI,YAAY,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;QAClC,cAAc,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAChE,CAAC;IAED,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC;SACtD,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;SACtC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,KAAK,KAAK,QAAQ,CAAC;SACjD,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,CAAC,IAAI,CACT,0BAA0B,EAC1B,sIAAsI,EACtI,EAAE,EACF,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,EACpE,KAAK,IAAI,EAAE;QACT,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;SACzD,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC;AAED,qGAAqG;AACrG,MAAM,UAAU,aAAa,CAC3B,MAAiB,EACjB,MAAc,EACd,MAAsB;IAEtB,yFAAyF;IACzF,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1D,MAAM,aAAa,GAAG,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,gBAAgB,CAAC,CAAC;IACjE,IAAI,SAAwB,CAAC;IAC7B,IAAI,CAAC;QACH,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC;IAC/D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,sCAAsC,aAAa,IAAI;YACvD,oDAAoD;YACpD,mBAAmB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CACtE,CAAC;IACJ,CAAC;IAED,IAAI,QAAQ,GAAG,SAAS,CAAC;IAEzB,iFAAiF;IACjF,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACtB,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;QAC7D,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC5E,CAAC;IAED,sEAAsE;IACtE,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;QAC7B,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC,CAAC;IAC1E,CAAC;IAED,6DAA6D;IAC7D,KAAK,MAAM,QAAQ,IAAI,QAAQ,EAAE,CAAC;QAChC,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IACvD,CAAC;IAED,wEAAwE;IACxE,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,0BAA0B,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAE9C,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,kCAAkC;AAChE,CAAC"}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface SeparatedParams {
|
|
2
|
+
pathParams: Record<string, unknown>;
|
|
3
|
+
queryParams: Record<string, string>;
|
|
4
|
+
bodyParams: Record<string, unknown>;
|
|
5
|
+
}
|
|
6
|
+
export declare function substitutePath(pathTemplate: string, accountId: string, params: Record<string, unknown>): string;
|
|
7
|
+
export declare function buildQueryString(params: Record<string, unknown>): string;
|
|
8
|
+
export declare function formatResponse(data: unknown): string;
|
|
9
|
+
export declare function separateParams(input: Record<string, unknown>, paramDefs: Array<{
|
|
10
|
+
name: string;
|
|
11
|
+
location: string;
|
|
12
|
+
}>): SeparatedParams;
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// AIDEV-NOTE: Utility module for LionChat MCP server
|
|
2
|
+
// Path substitution, query string building, param separation, and response formatting
|
|
3
|
+
// AIDEV-NOTE: Replace {account_id} and other {param} placeholders in URL path templates
|
|
4
|
+
export function substitutePath(pathTemplate, accountId, params) {
|
|
5
|
+
let result = pathTemplate.replace('{account_id}', accountId);
|
|
6
|
+
for (const [key, value] of Object.entries(params)) {
|
|
7
|
+
result = result.replace(`{${key}}`, String(value));
|
|
8
|
+
}
|
|
9
|
+
// AIDEV-NOTE: Catch any unsubstituted placeholders — caller forgot a required param
|
|
10
|
+
const missing = result.match(/\{(\w+)\}/);
|
|
11
|
+
if (missing) {
|
|
12
|
+
throw new Error(`Missing required path parameter: ${missing[0]}`);
|
|
13
|
+
}
|
|
14
|
+
return result;
|
|
15
|
+
}
|
|
16
|
+
// AIDEV-NOTE: Convert params object to URL query string, skipping nulls and handling arrays
|
|
17
|
+
export function buildQueryString(params) {
|
|
18
|
+
const parts = [];
|
|
19
|
+
for (const [key, value] of Object.entries(params)) {
|
|
20
|
+
if (value === null || value === undefined) {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (Array.isArray(value)) {
|
|
24
|
+
// AIDEV-NOTE: Arrays expand to repeated keys: key=val1&key=val2
|
|
25
|
+
for (const item of value) {
|
|
26
|
+
if (item !== null && item !== undefined) {
|
|
27
|
+
parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(item))}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return parts.length > 0 ? `?${parts.join('&')}` : '';
|
|
36
|
+
}
|
|
37
|
+
// AIDEV-NOTE: Format API response data for MCP client consumption
|
|
38
|
+
// Truncates at 50k chars to avoid overwhelming the LLM context
|
|
39
|
+
const MAX_RESPONSE_LENGTH = 50000;
|
|
40
|
+
export function formatResponse(data) {
|
|
41
|
+
const text = typeof data === 'string' ? data : JSON.stringify(data, null, 2);
|
|
42
|
+
if (text.length > MAX_RESPONSE_LENGTH) {
|
|
43
|
+
return (text.slice(0, MAX_RESPONSE_LENGTH) +
|
|
44
|
+
'\n\n[Response truncated at 50,000 characters. Use pagination parameters (page, limit) to fetch smaller result sets.]');
|
|
45
|
+
}
|
|
46
|
+
return text;
|
|
47
|
+
}
|
|
48
|
+
// AIDEV-NOTE: Route each input param to path/query/body based on endpoint parameter definitions
|
|
49
|
+
export function separateParams(input, paramDefs) {
|
|
50
|
+
const pathParams = {};
|
|
51
|
+
const queryParams = {};
|
|
52
|
+
const bodyParams = {};
|
|
53
|
+
// AIDEV-NOTE: Build a lookup map for O(1) location resolution per param
|
|
54
|
+
const locationMap = new Map();
|
|
55
|
+
for (const def of paramDefs) {
|
|
56
|
+
locationMap.set(def.name, def.location);
|
|
57
|
+
}
|
|
58
|
+
for (const [key, value] of Object.entries(input)) {
|
|
59
|
+
const location = locationMap.get(key);
|
|
60
|
+
switch (location) {
|
|
61
|
+
case 'path':
|
|
62
|
+
pathParams[key] = value;
|
|
63
|
+
break;
|
|
64
|
+
case 'query':
|
|
65
|
+
if (value !== null && value !== undefined) {
|
|
66
|
+
queryParams[key] = String(value);
|
|
67
|
+
}
|
|
68
|
+
break;
|
|
69
|
+
case 'body':
|
|
70
|
+
bodyParams[key] = value;
|
|
71
|
+
break;
|
|
72
|
+
default:
|
|
73
|
+
// AIDEV-NOTE: Params not in definitions go to body (catch-all for nested/extra fields)
|
|
74
|
+
bodyParams[key] = value;
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return { pathParams, queryParams, bodyParams };
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
|