@abhinavyadav/bolna-mcp 1.0.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Abhinav Yadav
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,293 @@
1
+ # Bolna MCP Server
2
+
3
+ A production-ready [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that exposes the full [Bolna Voice AI](https://api.bolna.ai) platform as MCP tools. Connect any MCP-compatible AI client (Claude Desktop, Cursor, etc.) to Bolna so you can create and manage voice agents, make and monitor calls, run batch campaigns, manage knowledgebases, and handle phone numbers all through natural language.
4
+
5
+ ---
6
+
7
+ ## Prerequisites
8
+
9
+ - **Node.js 18+**
10
+ - A **Bolna API key** — sign up at [bolna.ai](https://bolna.ai) and find your key in the dashboard
11
+
12
+ ---
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ # 1. Clone or download the repository
18
+ git clone https://github.com/your-org/bolna-mcp.git
19
+ cd bolna-mcp
20
+
21
+ # 2. Install dependencies
22
+ npm install
23
+
24
+ # 3. Build the TypeScript source
25
+ npm run build
26
+ ```
27
+
28
+ The compiled server will be available at `dist/index.js`.
29
+
30
+ ---
31
+
32
+ ## MCP Client Configuration
33
+
34
+ The Bolna MCP server runs as a background process. Here is how you can add it to your favorite MCP clients:
35
+
36
+ > [!TIP]
37
+ > **How to get the absolute path to `dist/index.js` on your machine:**
38
+ >
39
+ > First, ensure you have navigated (using `cd`) into the root of the cloned `bolna-mcp` directory. Then run:
40
+ > - **macOS / Linux**: Run:
41
+ > ```bash
42
+ > echo "$(pwd)/dist/index.js"
43
+ > ```
44
+ > - **Windows (PowerShell)**: Run:
45
+ > ```powershell
46
+ > (Get-Item .).FullName + "\dist\index.js"
47
+ > ```
48
+ > - **Windows (Command Prompt)**: Run:
49
+ > ```cmd
50
+ > echo %cd%\dist\index.js
51
+ > ```
52
+ > Use the resulting path (e.g., `/Users/username/Developer/bolna-mcp/dist/index.js`) as the replacement for `/path/to/bolna-mcp/dist/index.js` in the configs below.
53
+
54
+ ### 1. Claude Desktop App
55
+ Add the following to your Claude Desktop configuration file:
56
+ - **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
57
+ - **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
58
+
59
+ ```json
60
+ {
61
+ "mcpServers": {
62
+ "bolna": {
63
+ "command": "node",
64
+ "args": ["/path/to/bolna-mcp/dist/index.js"],
65
+ "env": {
66
+ "BOLNA_API_KEY": "your_api_key_here"
67
+ }
68
+ }
69
+ }
70
+ }
71
+ ```
72
+
73
+ ### 2. Claude Code (CLI)
74
+ You can add the Bolna MCP server to Claude Code by running:
75
+ ```bash
76
+ claude mcp add node /path/to/bolna-mcp/dist/index.js --env BOLNA_API_KEY=your_api_key_here
77
+ ```
78
+ Or manually configure it in your `~/.claude.json` configuration file:
79
+ ```json
80
+ {
81
+ "mcpServers": {
82
+ "bolna": {
83
+ "command": "node",
84
+ "args": ["/path/to/bolna-mcp/dist/index.js"],
85
+ "env": {
86
+ "BOLNA_API_KEY": "your_api_key_here"
87
+ }
88
+ }
89
+ }
90
+ }
91
+ ```
92
+
93
+ ### 3. Antigravity / Codex (Antigravity CLI / IDE)
94
+ Antigravity (Codex) loads its configuration from:
95
+ - **Path**: `~/.gemini/config/mcp_config.json`
96
+
97
+ Add the server configuration under `mcpServers`:
98
+ ```json
99
+ {
100
+ "mcpServers": {
101
+ "bolna": {
102
+ "command": "node",
103
+ "args": ["/path/to/bolna-mcp/dist/index.js"],
104
+ "env": {
105
+ "BOLNA_API_KEY": "your_api_key_here"
106
+ }
107
+ }
108
+ }
109
+ }
110
+ ```
111
+
112
+ ### 4. Cursor
113
+ 1. Open Cursor and navigate to **Settings** (Gear icon in top right) -> **Features** -> **MCP**.
114
+ 2. Click **+ Add New MCP Server**.
115
+ 3. Fill out the fields:
116
+ - **Name**: `bolna`
117
+ - **Type**: `command`
118
+ - **Command**: `env BOLNA_API_KEY=your_api_key_here node /path/to/bolna-mcp/dist/index.js`
119
+
120
+ ### 5. Windsurf
121
+ Windsurf reads its configuration from:
122
+ - **Path**: `~/.codeium/windsurf/mcp_config.json`
123
+
124
+ Add the server under `mcpServers`:
125
+ ```json
126
+ {
127
+ "mcpServers": {
128
+ "bolna": {
129
+ "command": "node",
130
+ "args": ["/path/to/bolna-mcp/dist/index.js"],
131
+ "env": {
132
+ "BOLNA_API_KEY": "your_api_key_here"
133
+ }
134
+ }
135
+ }
136
+ }
137
+ ```
138
+
139
+ ### 6. VS Code (via extensions like Cline / Roo Code)
140
+ If you use Cline or Roo Code inside VS Code, they read their MCP configurations from:
141
+ - **macOS**: `~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json`
142
+ - **Windows**: `%APPDATA%\Code\User\globalStorage\saoudrizwan.claude-dev\settings\cline_mcp_settings.json`
143
+
144
+ Add the configuration block:
145
+ ```json
146
+ {
147
+ "mcpServers": {
148
+ "bolna": {
149
+ "command": "node",
150
+ "args": ["/path/to/bolna-mcp/dist/index.js"],
151
+ "env": {
152
+ "BOLNA_API_KEY": "your_api_key_here"
153
+ }
154
+ }
155
+ }
156
+ }
157
+ ```
158
+
159
+ > [!IMPORTANT]
160
+ > Make sure to replace `/path/to/bolna-mcp` with the absolute path where the repository is located on your local machine, and set your real Bolna API key.
161
+
162
+ ---
163
+
164
+ ## Available Tools
165
+
166
+ ### 🤖 Agents
167
+ | Tool | Description |
168
+ |------|-------------|
169
+ | `bolna_create_agent` | Create a new voice AI agent with system prompt and task config |
170
+ | `bolna_get_agent` | Retrieve full configuration of an agent by ID |
171
+ | `bolna_list_agents` | List all agents in your account (paginated) |
172
+ | `bolna_update_agent` | Update an existing agent's config or system prompt |
173
+ | `bolna_delete_agent` | Permanently delete an agent |
174
+
175
+ ### 📞 Calls
176
+ | Tool | Description |
177
+ |------|-------------|
178
+ | `bolna_make_call` | Initiate an outbound call with optional scheduling and retry logic |
179
+ | `bolna_stop_call` | Immediately terminate an active call |
180
+
181
+ ### 📋 Batch Campaigns
182
+ | Tool | Description |
183
+ |------|-------------|
184
+ | `bolna_create_batch` | Upload a CSV of phone numbers to create a batch campaign |
185
+ | `bolna_schedule_batch` | Schedule a batch to run at a specific datetime |
186
+ | `bolna_stop_batch` | Stop a running batch and cancel pending calls |
187
+ | `bolna_get_batch` | Get status and call counts for a batch |
188
+ | `bolna_list_batches` | List all batches for an agent (paginated) |
189
+ | `bolna_get_batch_executions` | List all call executions within a batch |
190
+
191
+ ### 📊 Call History (Executions)
192
+ | Tool | Description |
193
+ |------|-------------|
194
+ | `bolna_get_execution` | Get full call details: transcript, recording URL, telephony data |
195
+ | `bolna_list_agent_executions` | List all call executions for an agent (paginated) |
196
+
197
+ ### 📚 Knowledgebases
198
+ | Tool | Description |
199
+ |------|-------------|
200
+ | `bolna_create_knowledgebase` | Create a knowledgebase from a PDF file (base64) or a web URL |
201
+ | `bolna_list_knowledgebases` | List all knowledgebases with status and metadata |
202
+ | `bolna_delete_knowledgebase` | Delete a knowledgebase |
203
+
204
+ ### 📱 Phone Numbers
205
+ | Tool | Description |
206
+ |------|-------------|
207
+ | `bolna_search_phone_numbers` | Search available numbers by country, area code, or pattern |
208
+ | `bolna_buy_phone_number` | Purchase a phone number for your account |
209
+ | `bolna_list_phone_numbers` | List all phone numbers on your account |
210
+
211
+ ---
212
+
213
+ ## Example Claude Prompts
214
+
215
+ ### 1. Create an agent and make a test call
216
+ ```
217
+ Create a Hindi appointment booking agent for a hospital.
218
+ The agent should greet callers warmly, collect their name and preferred appointment time,
219
+ and confirm the booking. Then make a test call to +919999999999 using that agent.
220
+ ```
221
+
222
+ ### 2. Review batch call results
223
+ ```
224
+ Show me all call executions for agent <agent_id> from the last batch.
225
+ Include the transcript and recording URL for any calls that lasted more than 2 minutes.
226
+ ```
227
+
228
+ ### 3. Purchase an Indian phone number
229
+ ```
230
+ Search for available Indian phone numbers with area code 080 (Bangalore).
231
+ Show me the top 3 options with their prices, then buy the cheapest one using Twilio as the provider.
232
+ ```
233
+
234
+ ---
235
+
236
+ ## Environment Variables
237
+
238
+ | Variable | Required | Description |
239
+ |----------|----------|-------------|
240
+ | `BOLNA_API_KEY` | ✅ Yes | Your Bolna platform API key |
241
+
242
+ ---
243
+
244
+ ## Development
245
+
246
+ ```bash
247
+ # Run in development mode (no build step)
248
+ BOLNA_API_KEY=your_key npm run dev
249
+
250
+ # Build for production
251
+ npm run build
252
+
253
+ # Run built server
254
+ BOLNA_API_KEY=your_key npm start
255
+ ```
256
+
257
+ ---
258
+
259
+ ## Testing
260
+
261
+ The project ships with a Jest + ts-jest test suite located in `src/__tests__/`. Tests are entirely offline — no real API calls are made; the Bolna client is fully mocked.
262
+
263
+ ```bash
264
+ # Run all tests
265
+ BOLNA_API_KEY=any-value npm test
266
+
267
+ # Run with coverage report
268
+ BOLNA_API_KEY=any-value npm run test:coverage
269
+ ```
270
+
271
+ ### Test Coverage
272
+
273
+ | File | Statements | Branches | Functions | Lines |
274
+ |------|-----------|----------|-----------|-------|
275
+ | `client.ts` | 95% | 78% | 100% | 95% |
276
+ | `calls.ts` | 100% | 96% | 100% | 100% |
277
+ | `agents.ts` | 33% | 6% | 50% | 33% |
278
+
279
+ > **Note**: `agents.ts` coverage is intentionally lower — the test suite focuses on `list`, `get`, and `delete` endpoints (most commonly used). More tool coverage can be added to `src/__tests__/agents.test.ts`.
280
+
281
+ ### Test Files
282
+
283
+ | File | What's tested |
284
+ |------|---------------|
285
+ | `src/__tests__/calls.test.ts` | `bolna_make_call` (6 cases) + `bolna_stop_call` (2 cases) |
286
+ | `src/__tests__/agents.test.ts` | `bolna_list_agents`, `bolna_get_agent`, `bolna_delete_agent` |
287
+ | `src/__tests__/client.test.ts` | `handleAxiosError` (4 cases) + `bolnaClient` factory (3 cases) |
288
+
289
+ ---
290
+
291
+ ## License
292
+
293
+ MIT
package/dist/client.js ADDED
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: Object.getOwnPropertyDescriptor(all, name).get
9
+ });
10
+ }
11
+ _export(exports, {
12
+ get bolnaClient () {
13
+ return bolnaClient;
14
+ },
15
+ get handleAxiosError () {
16
+ return handleAxiosError;
17
+ }
18
+ });
19
+ const _axios = /*#__PURE__*/ _interop_require_default(require("axios"));
20
+ const _types = require("@modelcontextprotocol/sdk/types.js");
21
+ function _interop_require_default(obj) {
22
+ return obj && obj.__esModule ? obj : {
23
+ default: obj
24
+ };
25
+ }
26
+ const BOLNA_BASE_URL = "https://api.bolna.ai";
27
+ function createBolnaClient() {
28
+ const apiKey = process.env.BOLNA_API_KEY;
29
+ if (!apiKey) {
30
+ throw new Error("BOLNA_API_KEY environment variable is required");
31
+ }
32
+ const client = _axios.default.create({
33
+ baseURL: BOLNA_BASE_URL,
34
+ headers: {
35
+ Authorization: `Bearer ${apiKey}`,
36
+ "Content-Type": "application/json"
37
+ },
38
+ timeout: 30000
39
+ });
40
+ return client;
41
+ }
42
+ const bolnaClient = createBolnaClient();
43
+ function handleAxiosError(error, context) {
44
+ if (_axios.default.isAxiosError(error)) {
45
+ const axiosError = error;
46
+ const status = axiosError.response?.status ?? "unknown";
47
+ const data = axiosError.response?.data;
48
+ const message = data && (data.message || data.detail) || axiosError.message || "Unknown error";
49
+ throw new _types.McpError(_types.ErrorCode.InternalError, `${context} failed (HTTP ${status}): ${message}`);
50
+ }
51
+ throw new _types.McpError(_types.ErrorCode.InternalError, `${context} failed: ${String(error)}`);
52
+ }
package/dist/index.js ADDED
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ const _mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
7
+ const _stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
8
+ const _agents = require("./tools/agents.js");
9
+ const _calls = require("./tools/calls.js");
10
+ const _batches = require("./tools/batches.js");
11
+ const _executions = require("./tools/executions.js");
12
+ const _knowledgebases = require("./tools/knowledgebases.js");
13
+ const _phone_numbers = require("./tools/phone_numbers.js");
14
+ const _inbound = require("./tools/inbound.js");
15
+ const _dispositions = require("./tools/dispositions.js");
16
+ const _providers = require("./tools/providers.js");
17
+ const _sub_accounts = require("./tools/sub_accounts.js");
18
+ const _voice = require("./tools/voice.js");
19
+ const _user = require("./tools/user.js");
20
+ const _sip_trunks = require("./tools/sip_trunks.js");
21
+ const _violations = require("./tools/violations.js");
22
+ // Validate required environment variables at startup
23
+ if (!process.env.BOLNA_API_KEY) {
24
+ process.stderr.write("Error: BOLNA_API_KEY environment variable is required\n");
25
+ process.exit(1);
26
+ }
27
+ async function main() {
28
+ const server = new _mcp.McpServer({
29
+ name: "bolna-mcp",
30
+ version: "1.0.0"
31
+ });
32
+ // ── Current APIs ──────────────────────────────────────────────────────────
33
+ (0, _agents.registerAgentTools)(server); // Agent CRUD + patch + stop queued
34
+ (0, _calls.registerCallTools)(server); // Make call + stop call
35
+ (0, _batches.registerBatchTools)(server); // Batch CRUD + schedule/stop/executions
36
+ (0, _executions.registerExecutionTools)(server); // Get execution + list + raw logs
37
+ (0, _knowledgebases.registerKnowledgebaseTools)(server); // KB create/get/list/delete
38
+ (0, _phone_numbers.registerPhoneNumberTools)(server); // Search/buy/list/delete phone numbers
39
+ (0, _inbound.registerInboundTools)(server); // Set + unlink inbound agent
40
+ (0, _dispositions.registerDispositionTools)(server); // Dispositions CRUD + bulk + test
41
+ (0, _providers.registerProviderTools)(server); // Add/list/remove providers
42
+ (0, _sub_accounts.registerSubAccountTools)(server); // Sub-account CRUD + usage
43
+ (0, _voice.registerVoiceTools)(server); // List voices
44
+ (0, _user.registerUserTools)(server); // User info + add custom LLM
45
+ (0, _sip_trunks.registerSipTrunkTools)(server); // SIP trunk CRUD + numbers
46
+ (0, _violations.registerViolationTools)(server); // List + submit violations
47
+ // Use stdio transport (standard MCP pattern)
48
+ const transport = new _stdio.StdioServerTransport();
49
+ await server.connect(transport);
50
+ // Log to stderr only — stdout is reserved for MCP protocol messages
51
+ process.stderr.write("Bolna MCP Server running\n");
52
+ }
53
+ main().catch((error)=>{
54
+ process.stderr.write(`Fatal error: ${error.message}\n`);
55
+ process.exit(1);
56
+ });
@@ -0,0 +1,225 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "registerAgentTools", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return registerAgentTools;
9
+ }
10
+ });
11
+ const _zod = require("zod");
12
+ const _client = require("../client.js");
13
+ function registerAgentTools(server) {
14
+ server.tool("bolna_create_agent", "Create a new Bolna voice AI agent with full configuration and system prompt", {
15
+ agent_name: _zod.z.string().describe("Unique name for the agent"),
16
+ agent_welcome_message: _zod.z.string().optional().describe("First message the agent speaks when a call connects"),
17
+ agent_type: _zod.z.string().optional().default("other").describe('Agent type, e.g. "other"'),
18
+ webhook_url: _zod.z.string().url().nullable().optional().describe("Webhook URL to receive call events"),
19
+ hangup_after_silence: _zod.z.number().optional().default(10).describe("Seconds of silence before hanging up"),
20
+ incremental_delay: _zod.z.number().optional().default(400).describe("Delay in ms between incremental responses"),
21
+ number_of_words_for_interruption: _zod.z.number().optional().default(2).describe("Number of words the caller must speak to interrupt the agent"),
22
+ call_terminate: _zod.z.number().optional().describe("Maximum call duration in seconds"),
23
+ ambient_noise_track: _zod.z.string().optional().describe('Ambient noise track, e.g. "coffee-shop"'),
24
+ system_prompt: _zod.z.string().describe("LLM system prompt that governs agent behaviour")
25
+ }, async (args)=>{
26
+ try {
27
+ const body = {
28
+ agent_config: {
29
+ agent_name: args.agent_name,
30
+ ...args.agent_welcome_message !== undefined && {
31
+ agent_welcome_message: args.agent_welcome_message
32
+ },
33
+ ...args.agent_type !== undefined && {
34
+ agent_type: args.agent_type
35
+ },
36
+ webhook_url: args.webhook_url ?? null,
37
+ tasks: [
38
+ {
39
+ task_type: "conversation",
40
+ task_config: {
41
+ hangup_after_silence: args.hangup_after_silence ?? 10,
42
+ incremental_delay: args.incremental_delay ?? 400,
43
+ number_of_words_for_interruption: args.number_of_words_for_interruption ?? 2,
44
+ ...args.call_terminate !== undefined && {
45
+ call_terminate: args.call_terminate
46
+ },
47
+ ...args.ambient_noise_track !== undefined && {
48
+ ambient_noise_track: args.ambient_noise_track
49
+ }
50
+ }
51
+ }
52
+ ]
53
+ },
54
+ agent_prompts: {
55
+ task_1: {
56
+ system_prompt: args.system_prompt
57
+ }
58
+ }
59
+ };
60
+ const response = await _client.bolnaClient.post("/v2/agent", body);
61
+ return {
62
+ content: [
63
+ {
64
+ type: "text",
65
+ text: JSON.stringify(response.data, null, 2)
66
+ }
67
+ ]
68
+ };
69
+ } catch (error) {
70
+ (0, _client.handleAxiosError)(error, "bolna_create_agent");
71
+ }
72
+ });
73
+ server.tool("bolna_get_agent", "Retrieve the full configuration of a specific Bolna agent by its ID", {
74
+ agent_id: _zod.z.string().describe("The unique ID of the agent to retrieve")
75
+ }, async (args)=>{
76
+ try {
77
+ const response = await _client.bolnaClient.get(`/v2/agent/${args.agent_id}`);
78
+ return {
79
+ content: [
80
+ {
81
+ type: "text",
82
+ text: JSON.stringify(response.data, null, 2)
83
+ }
84
+ ]
85
+ };
86
+ } catch (error) {
87
+ (0, _client.handleAxiosError)(error, "bolna_get_agent");
88
+ }
89
+ });
90
+ server.tool("bolna_list_agents", "List all Bolna agents in your account with optional pagination", {
91
+ page_number: _zod.z.number().int().positive().optional().default(1).describe("Page number (1-indexed)"),
92
+ page_size: _zod.z.number().int().positive().optional().default(10).describe("Number of agents per page")
93
+ }, async (args)=>{
94
+ try {
95
+ const response = await _client.bolnaClient.get("/v2/agent/all", {
96
+ params: {
97
+ page_number: args.page_number ?? 1,
98
+ page_size: args.page_size ?? 10
99
+ }
100
+ });
101
+ return {
102
+ content: [
103
+ {
104
+ type: "text",
105
+ text: JSON.stringify(response.data, null, 2)
106
+ }
107
+ ]
108
+ };
109
+ } catch (error) {
110
+ (0, _client.handleAxiosError)(error, "bolna_list_agents");
111
+ }
112
+ });
113
+ server.tool("bolna_update_agent", "Update an existing Bolna agent's configuration and/or system prompt", {
114
+ agent_id: _zod.z.string().describe("The unique ID of the agent to update"),
115
+ agent_name: _zod.z.string().optional().describe("New name for the agent"),
116
+ agent_welcome_message: _zod.z.string().optional().describe("New welcome message"),
117
+ agent_type: _zod.z.string().optional().describe("Agent type"),
118
+ webhook_url: _zod.z.string().url().nullable().optional().describe("New webhook URL"),
119
+ hangup_after_silence: _zod.z.number().optional().describe("Seconds of silence before hanging up"),
120
+ incremental_delay: _zod.z.number().optional().describe("Delay in ms between incremental responses"),
121
+ number_of_words_for_interruption: _zod.z.number().optional().describe("Words to interrupt"),
122
+ call_terminate: _zod.z.number().optional().describe("Max call duration in seconds"),
123
+ ambient_noise_track: _zod.z.string().optional().describe("Ambient noise track"),
124
+ system_prompt: _zod.z.string().optional().describe("New LLM system prompt")
125
+ }, async (args)=>{
126
+ try {
127
+ const { agent_id, system_prompt, ...rest } = args;
128
+ const taskConfig = {};
129
+ if (rest.hangup_after_silence !== undefined) taskConfig.hangup_after_silence = rest.hangup_after_silence;
130
+ if (rest.incremental_delay !== undefined) taskConfig.incremental_delay = rest.incremental_delay;
131
+ if (rest.number_of_words_for_interruption !== undefined) taskConfig.number_of_words_for_interruption = rest.number_of_words_for_interruption;
132
+ if (rest.call_terminate !== undefined) taskConfig.call_terminate = rest.call_terminate;
133
+ if (rest.ambient_noise_track !== undefined) taskConfig.ambient_noise_track = rest.ambient_noise_track;
134
+ const agentConfig = {};
135
+ if (rest.agent_name !== undefined) agentConfig.agent_name = rest.agent_name;
136
+ if (rest.agent_welcome_message !== undefined) agentConfig.agent_welcome_message = rest.agent_welcome_message;
137
+ if (rest.agent_type !== undefined) agentConfig.agent_type = rest.agent_type;
138
+ if (rest.webhook_url !== undefined) agentConfig.webhook_url = rest.webhook_url;
139
+ if (Object.keys(taskConfig).length > 0) {
140
+ agentConfig.tasks = [
141
+ {
142
+ task_type: "conversation",
143
+ task_config: taskConfig
144
+ }
145
+ ];
146
+ }
147
+ const body = {};
148
+ if (Object.keys(agentConfig).length > 0) body.agent_config = agentConfig;
149
+ if (system_prompt !== undefined) {
150
+ body.agent_prompts = {
151
+ task_1: {
152
+ system_prompt
153
+ }
154
+ };
155
+ }
156
+ const response = await _client.bolnaClient.put(`/v2/agent/${agent_id}`, body);
157
+ return {
158
+ content: [
159
+ {
160
+ type: "text",
161
+ text: JSON.stringify(response.data, null, 2)
162
+ }
163
+ ]
164
+ };
165
+ } catch (error) {
166
+ (0, _client.handleAxiosError)(error, "bolna_update_agent");
167
+ }
168
+ });
169
+ server.tool("bolna_delete_agent", "Permanently delete a Bolna agent by its ID", {
170
+ agent_id: _zod.z.string().describe("The unique ID of the agent to delete")
171
+ }, async (args)=>{
172
+ try {
173
+ const response = await _client.bolnaClient.delete(`/v2/agent/${args.agent_id}`);
174
+ return {
175
+ content: [
176
+ {
177
+ type: "text",
178
+ text: JSON.stringify(response.data, null, 2) || `Agent ${args.agent_id} deleted successfully.`
179
+ }
180
+ ]
181
+ };
182
+ } catch (error) {
183
+ (0, _client.handleAxiosError)(error, "bolna_delete_agent");
184
+ }
185
+ });
186
+ server.tool("bolna_patch_agent", "Partially update specific fields of a Bolna agent (name, welcome message, webhook URL, etc.)", {
187
+ agent_id: _zod.z.string().describe("The unique ID of the agent to patch"),
188
+ agent_name: _zod.z.string().optional().describe("New agent name"),
189
+ agent_welcome_message: _zod.z.string().optional().describe("New welcome message"),
190
+ webhook_url: _zod.z.string().url().nullable().optional().describe("New webhook URL or null to remove"),
191
+ system_prompt: _zod.z.string().optional().describe("New system prompt")
192
+ }, async (args)=>{
193
+ try {
194
+ const { agent_id, ...fields } = args;
195
+ const response = await _client.bolnaClient.patch(`/v2/agent/${agent_id}`, fields);
196
+ return {
197
+ content: [
198
+ {
199
+ type: "text",
200
+ text: JSON.stringify(response.data, null, 2)
201
+ }
202
+ ]
203
+ };
204
+ } catch (error) {
205
+ (0, _client.handleAxiosError)(error, "bolna_patch_agent");
206
+ }
207
+ });
208
+ server.tool("bolna_stop_agent_queued_calls", "Stop all queued (pending) calls for a specific Bolna agent, preventing them from executing", {
209
+ agent_id: _zod.z.string().describe("The unique ID of the agent whose queued calls to cancel")
210
+ }, async (args)=>{
211
+ try {
212
+ const response = await _client.bolnaClient.post(`/v2/agent/${args.agent_id}/stop`);
213
+ return {
214
+ content: [
215
+ {
216
+ type: "text",
217
+ text: JSON.stringify(response.data, null, 2) || `All queued calls for agent ${args.agent_id} stopped.`
218
+ }
219
+ ]
220
+ };
221
+ } catch (error) {
222
+ (0, _client.handleAxiosError)(error, "bolna_stop_agent_queued_calls");
223
+ }
224
+ });
225
+ }