@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/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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
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"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { Config } from './config.js';
3
+ import { LionChatClient } from './client.js';
4
+ export declare function registerTools(server: McpServer, config: Config, client: LionChatClient): number;
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":"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"}
@@ -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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"}