@botuyo/mcp 0.7.6 → 0.9.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/README.md CHANGED
@@ -74,7 +74,7 @@ The server resolves your JWT from `BOTUYO_TOKEN`, falling back to `~/.botuyo/cre
74
74
 
75
75
  ## Available tools
76
76
 
77
- The server exposes **42 tools**. Read tools (`list_*`, `get_*`, `export_*`, `audit_*`) need `viewer+`; write/publish tools need `developer+` (see [Roles](#roles)).
77
+ The server exposes **48 tools**. Read tools (`list_*`, `get_*`, `export_*`, `audit_*`) need `viewer+`; write/publish tools need `developer+`; channel & integration connect/configure need `admin+` (see [Roles](#roles)).
78
78
 
79
79
  > **For AI assistants / IDE agents:** every tool is self-describing — its `inputSchema` lists the exact arguments (with `required`) and its `description` states role requirements and side effects. Discover the live catalog with the MCP `tools/list` request; you never need to hardcode tool names. A typical build flow is `create_agent` → `update_agent` (identity/voice) → `upsert_stage` (conversation graph) → `update_enabled_tools` / `configure_agent_tool` (capabilities) → `publish_agent`. Use `example_agent` to see a fully documented reference config, and `audit_agent_family` to validate before publishing.
80
80
 
@@ -166,6 +166,35 @@ A **family** is one logical agent with a shared `base` config plus multiple `var
166
166
  | `list_agent_versions` | List an agent's saved version snapshots |
167
167
  | `restore_agent_version` | Roll back an agent to a previous version |
168
168
 
169
+ ### Channels
170
+
171
+ Connect messaging channels to the tenant **with their secrets**. Secrets are **write-only** — the server stores them and never returns their values; `list_channels` reports only which credential keys are set. Connect/disconnect require role **owner or admin**.
172
+
173
+ | Tool | Description |
174
+ |---|---|
175
+ | `list_channels` | List the tenant's channels + status. Never returns secret values — only `credentialsSet` (which keys are configured) |
176
+ | `connect_channel` | Connect a channel (WhatsApp, Telegram, Discord, Web, …) with its credentials. Validated against the provider API and stored server-side |
177
+ | `disconnect_channel` | Disconnect a channel by id (archives its open conversations) |
178
+
179
+ **Passing secrets safely.** `connect_channel` accepts the secret two ways:
180
+
181
+ - `credentials` — literal values, e.g. `{ "botToken": "123:ABC" }`. Simplest, but the secret passes through the conversation/LLM.
182
+ - `credentialsFromEnv` (**recommended for real secrets**) — a map of credential key → environment variable name, e.g. `{ "botToken": "MY_TG_TOKEN" }`. The MCP server reads the value from its **own** environment (set it in your MCP client config), so the secret never appears in the chat.
183
+
184
+ > Channels that require an interactive flow (WhatsApp/Instagram Embedded Signup QR/OAuth) still need [admin.botuyo.com](https://admin.botuyo.com). Channels that authenticate with a static token (Telegram, Discord, WhatsApp Cloud API with an existing token, Web) can be connected here.
185
+
186
+ ### Integrations
187
+
188
+ Install and configure the tenant's external integrations (Shopify, PaseoLibre, Google Calendar, email SMTP, …) **with their secrets**, using the same write-only secret model as channels. Configure/remove require role **owner or admin**.
189
+
190
+ | Tool | Description |
191
+ |---|---|
192
+ | `list_integrations` | List the integration catalog (available) + the tenant's installed integrations. Never returns secret values — only `configKeys` (which config keys are set) |
193
+ | `configure_integration` | Install or update an integration with its config/secret (validated against the provider, stored server-side). Accepts literal `config` or `configFromEnv` (env-var reference) |
194
+ | `remove_integration` | Uninstall an integration by id |
195
+
196
+ Same two secret modes as `connect_channel`: literal `config`, or `configFromEnv` (map config key → env var name resolved from the MCP server environment, keeping the secret out of the chat).
197
+
169
198
  ### Account
170
199
 
171
200
  | Tool | Description |
@@ -181,11 +210,13 @@ A **family** is one logical agent with a shared `base` config plus multiple `var
181
210
  | `developer` | ✅ | ✅ | ✅ |
182
211
  | `viewer` | ✅ | ❌ | ❌ |
183
212
 
213
+ > **Channels & integrations:** `connect_channel` / `disconnect_channel` / `configure_integration` / `remove_integration` additionally require **owner or admin** (a `developer` can build agents but not wire up channel/integration secrets).
214
+
184
215
  ## Channel Integrations
185
216
 
186
- Connecting channels (WhatsApp, Instagram, Telegram, Web) must be done from [admin.botuyo.com](https://admin.botuyo.com) they require interactive flows (QR scans, OAuth, etc.).
217
+ Channels that authenticate with a **static secret** — Telegram (bot token), Discord (bot token), WhatsApp Cloud API (existing access token), Web can be connected directly via the `connect_channel` tool (see [Channels](#channels)). Channels that need an **interactive flow** (WhatsApp/Instagram Embedded Signup with QR scans or OAuth consent) must still be connected from [admin.botuyo.com](https://admin.botuyo.com).
187
218
 
188
- Use `get_agent_status` to check which channels are connected. It returns a direct link to the admin panel for any missing channel.
219
+ Use `get_agent_status` to check which channels are connected (it links to the admin panel for any missing channel), or `list_channels` for the tenant-wide channel list and status.
189
220
 
190
221
  ## Build from source
191
222
 
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,93 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import { listChannelsHandler, connectChannelHandler, disconnectChannelHandler } from '../channels.js';
3
+ class MockClient {
4
+ gets = [];
5
+ posts = [];
6
+ deletes = [];
7
+ async get(path) {
8
+ this.gets.push(path);
9
+ return { success: true, data: { channels: [], total: 0 } };
10
+ }
11
+ async post(path, payload) {
12
+ this.posts.push({ path, payload });
13
+ return { success: true, data: { channelId: 'ch1', status: 'connected' } };
14
+ }
15
+ async delete(path) {
16
+ this.deletes.push(path);
17
+ return { success: true, data: { message: 'disconnected' } };
18
+ }
19
+ }
20
+ describe('listChannelsHandler', () => {
21
+ it('GETs the MCP channels namespace', async () => {
22
+ const client = new MockClient();
23
+ await listChannelsHandler(client);
24
+ expect(client.gets[0]).toBe('/api/v1/mcp/channels');
25
+ });
26
+ });
27
+ describe('connectChannelHandler', () => {
28
+ it('POSTs channelType + config + literal credentials', async () => {
29
+ const client = new MockClient();
30
+ await connectChannelHandler(client, {
31
+ channelType: 'telegram',
32
+ config: { botUsername: 'mybot' },
33
+ credentials: { botToken: 'T-123' }
34
+ });
35
+ expect(client.posts[0].path).toBe('/api/v1/mcp/channels/connect');
36
+ expect(client.posts[0].payload).toEqual({
37
+ channelType: 'telegram',
38
+ config: { botUsername: 'mybot' },
39
+ credentials: { botToken: 'T-123' }
40
+ });
41
+ });
42
+ it('throws when channelType is missing', async () => {
43
+ const client = new MockClient();
44
+ await expect(connectChannelHandler(client, {})).rejects.toThrow(/channelType/i);
45
+ });
46
+ describe('credentialsFromEnv (keeps secrets out of the chat)', () => {
47
+ afterEach(() => {
48
+ delete process.env.TEST_TG_TOKEN;
49
+ });
50
+ it('resolves the secret from the MCP server environment', async () => {
51
+ process.env.TEST_TG_TOKEN = 'secret-from-env';
52
+ const client = new MockClient();
53
+ await connectChannelHandler(client, {
54
+ channelType: 'telegram',
55
+ credentialsFromEnv: { botToken: 'TEST_TG_TOKEN' }
56
+ });
57
+ expect(client.posts[0].payload.credentials).toEqual({ botToken: 'secret-from-env' });
58
+ });
59
+ it('merges literal + env credentials', async () => {
60
+ process.env.TEST_TG_TOKEN = 'env-token';
61
+ const client = new MockClient();
62
+ await connectChannelHandler(client, {
63
+ channelType: 'whatsapp',
64
+ credentials: { appSecret: 'literal-secret' },
65
+ credentialsFromEnv: { accessToken: 'TEST_TG_TOKEN' }
66
+ });
67
+ expect(client.posts[0].payload.credentials).toEqual({
68
+ appSecret: 'literal-secret',
69
+ accessToken: 'env-token'
70
+ });
71
+ });
72
+ it('throws a helpful error when the env var is not set', async () => {
73
+ const client = new MockClient();
74
+ await expect(connectChannelHandler(client, {
75
+ channelType: 'telegram',
76
+ credentialsFromEnv: { botToken: 'DEFINITELY_UNSET_ENV_VAR_XYZ' }
77
+ })).rejects.toThrow(/DEFINITELY_UNSET_ENV_VAR_XYZ/);
78
+ expect(client.posts).toHaveLength(0);
79
+ });
80
+ });
81
+ });
82
+ describe('disconnectChannelHandler', () => {
83
+ it('DELETEs the channel by id', async () => {
84
+ const client = new MockClient();
85
+ await disconnectChannelHandler(client, { channelId: 'ch1' });
86
+ expect(client.deletes[0]).toBe('/api/v1/mcp/channels/ch1');
87
+ });
88
+ it('throws when channelId is missing', async () => {
89
+ const client = new MockClient();
90
+ await expect(disconnectChannelHandler(client, {})).rejects.toThrow(/channelId/i);
91
+ });
92
+ });
93
+ //# sourceMappingURL=channels.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channels.spec.js","sourceRoot":"","sources":["../../../src/tools/__tests__/channels.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,79 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import { listIntegrationsHandler, configureIntegrationHandler, removeIntegrationHandler } from '../integrations.js';
3
+ class MockClient {
4
+ gets = [];
5
+ posts = [];
6
+ deletes = [];
7
+ async get(path) {
8
+ this.gets.push(path);
9
+ return { success: true, data: { available: [], installed: [] } };
10
+ }
11
+ async post(path, payload) {
12
+ this.posts.push({ path, payload });
13
+ return { success: true, data: { integrationId: 'shopify', status: 'active' } };
14
+ }
15
+ async delete(path) {
16
+ this.deletes.push(path);
17
+ return { success: true };
18
+ }
19
+ }
20
+ describe('listIntegrationsHandler', () => {
21
+ it('GETs the MCP integrations namespace', async () => {
22
+ const client = new MockClient();
23
+ await listIntegrationsHandler(client);
24
+ expect(client.gets[0]).toBe('/api/v1/mcp/integrations');
25
+ });
26
+ });
27
+ describe('configureIntegrationHandler', () => {
28
+ it('POSTs integrationId + literal config', async () => {
29
+ const client = new MockClient();
30
+ await configureIntegrationHandler(client, {
31
+ integrationId: 'shopify',
32
+ config: { apiUrl: 'https://x', apiKey: 'sk-123' }
33
+ });
34
+ expect(client.posts[0].path).toBe('/api/v1/mcp/integrations/configure');
35
+ expect(client.posts[0].payload).toEqual({
36
+ integrationId: 'shopify',
37
+ config: { apiUrl: 'https://x', apiKey: 'sk-123' }
38
+ });
39
+ });
40
+ it('throws when integrationId is missing', async () => {
41
+ const client = new MockClient();
42
+ await expect(configureIntegrationHandler(client, {})).rejects.toThrow(/integrationId/i);
43
+ });
44
+ describe('configFromEnv (keeps secrets out of the chat)', () => {
45
+ afterEach(() => {
46
+ delete process.env.TEST_SHOPIFY_KEY;
47
+ });
48
+ it('resolves + merges the secret from the MCP server environment', async () => {
49
+ process.env.TEST_SHOPIFY_KEY = 'sk-from-env';
50
+ const client = new MockClient();
51
+ await configureIntegrationHandler(client, {
52
+ integrationId: 'shopify',
53
+ config: { apiUrl: 'https://x' },
54
+ configFromEnv: { apiKey: 'TEST_SHOPIFY_KEY' }
55
+ });
56
+ expect(client.posts[0].payload.config).toEqual({ apiUrl: 'https://x', apiKey: 'sk-from-env' });
57
+ });
58
+ it('throws a helpful error when the env var is not set', async () => {
59
+ const client = new MockClient();
60
+ await expect(configureIntegrationHandler(client, {
61
+ integrationId: 'shopify',
62
+ configFromEnv: { apiKey: 'DEFINITELY_UNSET_ENV_VAR_XYZ' }
63
+ })).rejects.toThrow(/DEFINITELY_UNSET_ENV_VAR_XYZ/);
64
+ expect(client.posts).toHaveLength(0);
65
+ });
66
+ });
67
+ });
68
+ describe('removeIntegrationHandler', () => {
69
+ it('DELETEs by integration id', async () => {
70
+ const client = new MockClient();
71
+ await removeIntegrationHandler(client, { integrationId: 'shopify' });
72
+ expect(client.deletes[0]).toBe('/api/v1/mcp/integrations/shopify');
73
+ });
74
+ it('throws when integrationId is missing', async () => {
75
+ const client = new MockClient();
76
+ await expect(removeIntegrationHandler(client, {})).rejects.toThrow(/integrationId/i);
77
+ });
78
+ });
79
+ //# sourceMappingURL=integrations.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrations.spec.js","sourceRoot":"","sources":["../../../src/tools/__tests__/integrations.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Channel tools — connect/list/disconnect the tenant's messaging channels.
3
+ *
4
+ * SECURITY MODEL (read before editing):
5
+ * - Channel secrets (bot tokens, access tokens, app secrets…) are WRITE-ONLY: the server
6
+ * stores them and NEVER returns their values. `list_channels` only reports which credential
7
+ * keys are set (`credentialsSet`), never the values.
8
+ * - To keep secrets OUT of the AI assistant's context, `connect_channel` supports two modes:
9
+ * 1. `credentials` — literal values (simplest; the secret travels through the chat/LLM).
10
+ * 2. `credentialsFromEnv` — a map of `{ credentialKey: ENV_VAR_NAME }`; the MCP server reads
11
+ * the value from its OWN environment (process.env) and the secret never appears in the
12
+ * conversation. PREFER this for production secrets.
13
+ * - Connecting/disconnecting requires role owner or admin (enforced server-side too).
14
+ *
15
+ * All calls go through the /api/v1/mcp/channels namespace (RULE 7).
16
+ */
17
+ import type { Tool } from '@modelcontextprotocol/sdk/types.js';
18
+ import type { BotuyoApiClient } from '../client.js';
19
+ export declare const LIST_CHANNELS_TOOL: Tool;
20
+ export declare const CONNECT_CHANNEL_TOOL: Tool;
21
+ export declare const DISCONNECT_CHANNEL_TOOL: Tool;
22
+ export declare function listChannelsHandler(client: BotuyoApiClient): Promise<unknown>;
23
+ export declare function connectChannelHandler(client: BotuyoApiClient, args: Record<string, unknown>): Promise<unknown>;
24
+ export declare function disconnectChannelHandler(client: BotuyoApiClient, args: Record<string, unknown>): Promise<unknown>;
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Channel tools — connect/list/disconnect the tenant's messaging channels.
3
+ *
4
+ * SECURITY MODEL (read before editing):
5
+ * - Channel secrets (bot tokens, access tokens, app secrets…) are WRITE-ONLY: the server
6
+ * stores them and NEVER returns their values. `list_channels` only reports which credential
7
+ * keys are set (`credentialsSet`), never the values.
8
+ * - To keep secrets OUT of the AI assistant's context, `connect_channel` supports two modes:
9
+ * 1. `credentials` — literal values (simplest; the secret travels through the chat/LLM).
10
+ * 2. `credentialsFromEnv` — a map of `{ credentialKey: ENV_VAR_NAME }`; the MCP server reads
11
+ * the value from its OWN environment (process.env) and the secret never appears in the
12
+ * conversation. PREFER this for production secrets.
13
+ * - Connecting/disconnecting requires role owner or admin (enforced server-side too).
14
+ *
15
+ * All calls go through the /api/v1/mcp/channels namespace (RULE 7).
16
+ */
17
+ const BASE = '/api/v1/mcp/channels';
18
+ export const LIST_CHANNELS_TOOL = {
19
+ name: 'list_channels',
20
+ description: 'List the tenant\'s messaging channels (WhatsApp, Telegram, Discord, Web, Instagram…) with their ' +
21
+ 'connection status. SECRETS ARE NEVER RETURNED — each channel reports only `credentialsSet` (which ' +
22
+ 'secret keys are configured), never their values. Available to any authenticated role.',
23
+ inputSchema: { type: 'object', properties: {} }
24
+ };
25
+ export const CONNECT_CHANNEL_TOOL = {
26
+ name: 'connect_channel',
27
+ description: 'Connect a messaging channel to the tenant with its secret credentials (bot token, access token, etc.). ' +
28
+ 'Requires role owner or admin. The server validates the credential against the provider API and stores ' +
29
+ 'it server-side; the secret is WRITE-ONLY and is never echoed back — DO NOT repeat the secret to the user. ' +
30
+ '\n\nTwo ways to pass the secret:\n' +
31
+ '• `credentials`: literal values, e.g. { "botToken": "123:ABC" }. Simplest, but the secret passes through ' +
32
+ 'this conversation.\n' +
33
+ '• `credentialsFromEnv` (RECOMMENDED for real secrets): a map of credential key → environment variable ' +
34
+ 'name, e.g. { "botToken": "MY_TG_TOKEN" }. The MCP server reads the value from its own environment so the ' +
35
+ 'secret NEVER appears in the chat. Set that env var in your MCP client config.\n\n' +
36
+ 'Typical per channel: telegram → credentials.botToken; whatsapp → credentials.accessToken + ' +
37
+ 'config.phoneNumberId; discord → credentials.botToken; web → no secret. Fields from both sources are merged.',
38
+ inputSchema: {
39
+ type: 'object',
40
+ properties: {
41
+ channelType: {
42
+ type: 'string',
43
+ enum: ['whatsapp', 'telegram', 'discord', 'web', 'webchat', 'instagram', 'facebook'],
44
+ description: 'Channel to connect.'
45
+ },
46
+ config: {
47
+ type: 'object',
48
+ description: 'Non-secret settings (e.g. { "phoneNumberId": "..." } for WhatsApp).',
49
+ additionalProperties: true
50
+ },
51
+ credentials: {
52
+ type: 'object',
53
+ description: 'Secret values as literals (e.g. { "botToken": "..." }). Prefer credentialsFromEnv for real secrets.',
54
+ additionalProperties: true
55
+ },
56
+ credentialsFromEnv: {
57
+ type: 'object',
58
+ description: 'Map of credential key → env var name read from the MCP server environment (keeps the secret out of the chat). ' +
59
+ 'e.g. { "botToken": "MY_TG_TOKEN" }.',
60
+ additionalProperties: { type: 'string' }
61
+ }
62
+ },
63
+ required: ['channelType']
64
+ }
65
+ };
66
+ export const DISCONNECT_CHANNEL_TOOL = {
67
+ name: 'disconnect_channel',
68
+ description: 'Disconnect a channel by its id (archives its open conversations). Use list_channels first to get the id. ' +
69
+ 'Requires role owner or admin.',
70
+ inputSchema: {
71
+ type: 'object',
72
+ properties: { channelId: { type: 'string', description: 'The channel id (from list_channels).' } },
73
+ required: ['channelId']
74
+ }
75
+ };
76
+ export async function listChannelsHandler(client) {
77
+ return client.get(BASE);
78
+ }
79
+ export async function connectChannelHandler(client, args) {
80
+ const channelType = args.channelType;
81
+ if (!channelType)
82
+ throw new Error('channelType is required');
83
+ const config = args.config || {};
84
+ const credentials = { ...(args.credentials || {}) };
85
+ // Resolve credentialsFromEnv against the MCP server's own environment so secrets stay out of the chat.
86
+ const fromEnv = args.credentialsFromEnv;
87
+ if (fromEnv) {
88
+ for (const [key, envName] of Object.entries(fromEnv)) {
89
+ const value = process.env[envName];
90
+ if (value === undefined || value === '') {
91
+ throw new Error(`Environment variable "${envName}" (for credential "${key}") is not set in the MCP server environment. ` +
92
+ `Add it to your MCP client config or use the literal "credentials" field.`);
93
+ }
94
+ credentials[key] = value;
95
+ }
96
+ }
97
+ return client.post(`${BASE}/connect`, { channelType, config, credentials });
98
+ }
99
+ export async function disconnectChannelHandler(client, args) {
100
+ const channelId = args.channelId;
101
+ if (!channelId)
102
+ throw new Error('channelId is required');
103
+ return client.delete(`${BASE}/${channelId}`);
104
+ }
105
+ //# sourceMappingURL=channels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channels.js","sourceRoot":"","sources":["../../src/tools/channels.ts"],"names":[],"mappings":"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"}
@@ -44,6 +44,8 @@ import { LIST_AGENT_VERSIONS_TOOL, listAgentVersionsHandler } from './list_agent
44
44
  import { RESTORE_AGENT_VERSION_TOOL, restoreAgentVersionHandler } from './restore_agent_version.js';
45
45
  import { LIST_AGENT_FAMILIES_TOOL, listAgentFamiliesHandler, GET_AGENT_FAMILY_TOOL, getAgentFamilyHandler, CREATE_AGENT_FAMILY_TOOL, createAgentFamilyHandler, UPDATE_FAMILY_BASE_TOOL, updateFamilyBaseHandler, ADD_FAMILY_VARIANT_TOOL, addFamilyVariantHandler, UPDATE_FAMILY_VARIANT_TOOL, updateFamilyVariantHandler, REMOVE_FAMILY_VARIANT_TOOL, removeFamilyVariantHandler, PUBLISH_AGENT_FAMILY_TOOL, publishAgentFamilyHandler, DELETE_AGENT_FAMILY_TOOL, deleteAgentFamilyHandler, EXPORT_AGENT_FAMILY_TOOL, exportAgentFamilyHandler, IMPORT_AGENT_FAMILY_TOOL, importAgentFamilyHandler } from './agent_families.js';
46
46
  import { AUDIT_AGENT_FAMILY_TOOL, auditAgentFamilyHandler } from './audit_agent_family.js';
47
+ import { LIST_CHANNELS_TOOL, listChannelsHandler, CONNECT_CHANNEL_TOOL, connectChannelHandler, DISCONNECT_CHANNEL_TOOL, disconnectChannelHandler } from './channels.js';
48
+ import { LIST_INTEGRATIONS_TOOL, listIntegrationsHandler, CONFIGURE_INTEGRATION_TOOL, configureIntegrationHandler, REMOVE_INTEGRATION_TOOL, removeIntegrationHandler } from './integrations.js';
47
49
  export const ALL_TOOLS = [
48
50
  LIST_AGENTS_TOOL,
49
51
  GET_AGENT_TOOL,
@@ -87,6 +89,12 @@ export const ALL_TOOLS = [
87
89
  EXPORT_AGENT_FAMILY_TOOL,
88
90
  IMPORT_AGENT_FAMILY_TOOL,
89
91
  AUDIT_AGENT_FAMILY_TOOL,
92
+ LIST_CHANNELS_TOOL,
93
+ CONNECT_CHANNEL_TOOL,
94
+ DISCONNECT_CHANNEL_TOOL,
95
+ LIST_INTEGRATIONS_TOOL,
96
+ CONFIGURE_INTEGRATION_TOOL,
97
+ REMOVE_INTEGRATION_TOOL,
90
98
  ];
91
99
  export const TOOL_HANDLERS = {
92
100
  list_agents: listAgentsHandler,
@@ -131,5 +139,11 @@ export const TOOL_HANDLERS = {
131
139
  export_agent_family: exportAgentFamilyHandler,
132
140
  import_agent_family: importAgentFamilyHandler,
133
141
  audit_agent_family: auditAgentFamilyHandler,
142
+ list_channels: (client) => listChannelsHandler(client),
143
+ connect_channel: connectChannelHandler,
144
+ disconnect_channel: disconnectChannelHandler,
145
+ list_integrations: (client) => listIntegrationsHandler(client),
146
+ configure_integration: configureIntegrationHandler,
147
+ remove_integration: removeIntegrationHandler,
134
148
  };
135
149
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Integration tools — install/list/remove the tenant's external integrations (Shopify, PaseoLibre,
3
+ * Google Calendar, email SMTP, etc.) with their secret config.
4
+ *
5
+ * SECURITY MODEL (same as channels):
6
+ * - Secret config values are WRITE-ONLY: the server validates + stores them and NEVER returns
7
+ * them. `list_integrations` reports only `configKeys` (which keys are set), never values.
8
+ * - `configure_integration` accepts the secret two ways:
9
+ * 1. `config` — literal values (simplest; the secret travels through the chat/LLM).
10
+ * 2. `configFromEnv` — a map of `{ configKey: ENV_VAR_NAME }`; the MCP server reads the value
11
+ * from its OWN environment so the secret never appears in the conversation. PREFER this.
12
+ * - Configure/remove require role owner or admin.
13
+ *
14
+ * All calls go through the /api/v1/mcp/integrations namespace (RULE 7).
15
+ *
16
+ * NOTE (RULE 0): these are agent/tenant integrations. Recruiting-owned config (e.g. recruiting
17
+ * email senders) is NOT managed here — that belongs to the Recruiting copiloto.
18
+ */
19
+ import type { Tool } from '@modelcontextprotocol/sdk/types.js';
20
+ import type { BotuyoApiClient } from '../client.js';
21
+ export declare const LIST_INTEGRATIONS_TOOL: Tool;
22
+ export declare const CONFIGURE_INTEGRATION_TOOL: Tool;
23
+ export declare const REMOVE_INTEGRATION_TOOL: Tool;
24
+ export declare function listIntegrationsHandler(client: BotuyoApiClient): Promise<unknown>;
25
+ export declare function configureIntegrationHandler(client: BotuyoApiClient, args: Record<string, unknown>): Promise<unknown>;
26
+ export declare function removeIntegrationHandler(client: BotuyoApiClient, args: Record<string, unknown>): Promise<unknown>;
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Integration tools — install/list/remove the tenant's external integrations (Shopify, PaseoLibre,
3
+ * Google Calendar, email SMTP, etc.) with their secret config.
4
+ *
5
+ * SECURITY MODEL (same as channels):
6
+ * - Secret config values are WRITE-ONLY: the server validates + stores them and NEVER returns
7
+ * them. `list_integrations` reports only `configKeys` (which keys are set), never values.
8
+ * - `configure_integration` accepts the secret two ways:
9
+ * 1. `config` — literal values (simplest; the secret travels through the chat/LLM).
10
+ * 2. `configFromEnv` — a map of `{ configKey: ENV_VAR_NAME }`; the MCP server reads the value
11
+ * from its OWN environment so the secret never appears in the conversation. PREFER this.
12
+ * - Configure/remove require role owner or admin.
13
+ *
14
+ * All calls go through the /api/v1/mcp/integrations namespace (RULE 7).
15
+ *
16
+ * NOTE (RULE 0): these are agent/tenant integrations. Recruiting-owned config (e.g. recruiting
17
+ * email senders) is NOT managed here — that belongs to the Recruiting copiloto.
18
+ */
19
+ const BASE = '/api/v1/mcp/integrations';
20
+ export const LIST_INTEGRATIONS_TOOL = {
21
+ name: 'list_integrations',
22
+ description: 'List the integration catalog (available) and the tenant\'s installed integrations with their ' +
23
+ 'status. SECRETS ARE NEVER RETURNED — each installed integration reports only `configKeys` ' +
24
+ '(which config keys are set), never their values. Available to any authenticated role.',
25
+ inputSchema: { type: 'object', properties: {} }
26
+ };
27
+ export const CONFIGURE_INTEGRATION_TOOL = {
28
+ name: 'configure_integration',
29
+ description: 'Install or update a tenant integration with its config/secret (API key, tokens, SMTP creds, etc.). ' +
30
+ 'Requires role owner or admin. The server validates the credentials against the provider and stores ' +
31
+ 'them; secrets are WRITE-ONLY and never echoed back — DO NOT repeat them to the user. ' +
32
+ '\n\nTwo ways to pass secret values:\n' +
33
+ '• `config`: literal values, e.g. { "apiKey": "sk-..." }. Simplest, but the secret passes through this chat.\n' +
34
+ '• `configFromEnv` (RECOMMENDED for real secrets): a map of config key → environment variable name, ' +
35
+ 'e.g. { "apiKey": "MY_SHOPIFY_KEY" }. The MCP server reads the value from its own environment so the ' +
36
+ 'secret NEVER appears in the chat. Both sources are merged. Use `list_integrations` to see available ids.',
37
+ inputSchema: {
38
+ type: 'object',
39
+ properties: {
40
+ integrationId: { type: 'string', description: 'Integration id from the catalog (e.g. "shopify", "email-smtp").' },
41
+ config: {
42
+ type: 'object',
43
+ description: 'Config/secret values as literals (e.g. { "apiUrl": "...", "apiKey": "..." }).',
44
+ additionalProperties: true
45
+ },
46
+ configFromEnv: {
47
+ type: 'object',
48
+ description: 'Map of config key → env var name read from the MCP server environment (keeps the secret out of the chat).',
49
+ additionalProperties: { type: 'string' }
50
+ }
51
+ },
52
+ required: ['integrationId']
53
+ }
54
+ };
55
+ export const REMOVE_INTEGRATION_TOOL = {
56
+ name: 'remove_integration',
57
+ description: 'Uninstall a tenant integration by its id (from list_integrations). Requires role owner or admin.',
58
+ inputSchema: {
59
+ type: 'object',
60
+ properties: { integrationId: { type: 'string', description: 'The integration id to remove.' } },
61
+ required: ['integrationId']
62
+ }
63
+ };
64
+ export async function listIntegrationsHandler(client) {
65
+ return client.get(BASE);
66
+ }
67
+ export async function configureIntegrationHandler(client, args) {
68
+ const integrationId = args.integrationId;
69
+ if (!integrationId)
70
+ throw new Error('integrationId is required');
71
+ const config = { ...(args.config || {}) };
72
+ const fromEnv = args.configFromEnv;
73
+ if (fromEnv) {
74
+ for (const [key, envName] of Object.entries(fromEnv)) {
75
+ const value = process.env[envName];
76
+ if (value === undefined || value === '') {
77
+ throw new Error(`Environment variable "${envName}" (for config "${key}") is not set in the MCP server environment. ` +
78
+ `Add it to your MCP client config or use the literal "config" field.`);
79
+ }
80
+ config[key] = value;
81
+ }
82
+ }
83
+ return client.post(`${BASE}/configure`, { integrationId, config });
84
+ }
85
+ export async function removeIntegrationHandler(client, args) {
86
+ const integrationId = args.integrationId;
87
+ if (!integrationId)
88
+ throw new Error('integrationId is required');
89
+ return client.delete(`${BASE}/${integrationId}`);
90
+ }
91
+ //# sourceMappingURL=integrations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrations.js","sourceRoot":"","sources":["../../src/tools/integrations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAKH,MAAM,IAAI,GAAG,0BAA0B,CAAA;AAEvC,MAAM,CAAC,MAAM,sBAAsB,GAAS;IAC1C,IAAI,EAAE,mBAAmB;IACzB,WAAW,EACT,+FAA+F;QAC/F,4FAA4F;QAC5F,uFAAuF;IACzF,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE;CAChD,CAAA;AAED,MAAM,CAAC,MAAM,0BAA0B,GAAS;IAC9C,IAAI,EAAE,uBAAuB;IAC7B,WAAW,EACT,qGAAqG;QACrG,qGAAqG;QACrG,uFAAuF;QACvF,uCAAuC;QACvC,+GAA+G;QAC/G,qGAAqG;QACrG,sGAAsG;QACtG,0GAA0G;IAC5G,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,aAAa,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,iEAAiE,EAAE;YACjH,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,+EAA+E;gBAC5F,oBAAoB,EAAE,IAAI;aAC3B;YACD,aAAa,EAAE;gBACb,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,2GAA2G;gBAC7G,oBAAoB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;aACzC;SACF;QACD,QAAQ,EAAE,CAAC,eAAe,CAAC;KAC5B;CACF,CAAA;AAED,MAAM,CAAC,MAAM,uBAAuB,GAAS;IAC3C,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EACT,kGAAkG;IACpG,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,+BAA+B,EAAE,EAAE;QAC/F,QAAQ,EAAE,CAAC,eAAe,CAAC;KAC5B;CACF,CAAA;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,MAAuB;IACnE,OAAO,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC/C,MAAuB,EACvB,IAA6B;IAE7B,MAAM,aAAa,GAAG,IAAI,CAAC,aAAuB,CAAA;IAClD,IAAI,CAAC,aAAa;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAA;IAEhE,MAAM,MAAM,GAA4B,EAAE,GAAG,CAAE,IAAI,CAAC,MAAkC,IAAI,EAAE,CAAC,EAAE,CAAA;IAE/F,MAAM,OAAO,GAAG,IAAI,CAAC,aAAmD,CAAA;IACxE,IAAI,OAAO,EAAE,CAAC;QACZ,KAAK,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACrD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YAClC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;gBACxC,MAAM,IAAI,KAAK,CACb,yBAAyB,OAAO,kBAAkB,GAAG,+CAA+C;oBAClG,qEAAqE,CACxE,CAAA;YACH,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;QACrB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,YAAY,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,CAAA;AACpE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,MAAuB,EACvB,IAA6B;IAE7B,MAAM,aAAa,GAAG,IAAI,CAAC,aAAuB,CAAA;IAClD,IAAI,CAAC,aAAa;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAA;IAChE,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI,IAAI,aAAa,EAAE,CAAC,CAAA;AAClD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botuyo/mcp",
3
- "version": "0.7.6",
3
+ "version": "0.9.0",
4
4
  "description": "BotUyo MCP Server — create and manage AI agents via Model Context Protocol",
5
5
  "keywords": [
6
6
  "mcp",