@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 +21 -0
- package/README.md +293 -0
- package/dist/client.js +52 -0
- package/dist/index.js +56 -0
- package/dist/tools/agents.js +225 -0
- package/dist/tools/batches.js +192 -0
- package/dist/tools/calls.js +87 -0
- package/dist/tools/dispositions.js +234 -0
- package/dist/tools/executions.js +72 -0
- package/dist/tools/inbound.js +56 -0
- package/dist/tools/knowledgebases.js +129 -0
- package/dist/tools/phone_numbers.js +95 -0
- package/dist/tools/providers.js +67 -0
- package/dist/tools/sip_trunks.js +191 -0
- package/dist/tools/sub_accounts.js +132 -0
- package/dist/tools/user.js +55 -0
- package/dist/tools/violations.js +79 -0
- package/dist/tools/voice.js +37 -0
- package/package.json +58 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "registerBatchTools", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return registerBatchTools;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _zod = require("zod");
|
|
12
|
+
const _formdata = /*#__PURE__*/ _interop_require_default(require("form-data"));
|
|
13
|
+
const _client = require("../client.js");
|
|
14
|
+
function _interop_require_default(obj) {
|
|
15
|
+
return obj && obj.__esModule ? obj : {
|
|
16
|
+
default: obj
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function registerBatchTools(server) {
|
|
20
|
+
server.tool("bolna_create_batch", "Create a batch call campaign by uploading a CSV of phone numbers for a Bolna agent", {
|
|
21
|
+
agent_id: _zod.z.string().describe("UUID of the Bolna agent to use for batch calls"),
|
|
22
|
+
csv_content: _zod.z.string().describe('Raw CSV string with a "phone_number" column (plus optional variable columns). Example: "phone_number,name\\n+919876543210,Rahul"'),
|
|
23
|
+
csv_filename: _zod.z.string().optional().default("contacts.csv").describe("Filename to use for the uploaded CSV"),
|
|
24
|
+
from_phone_numbers: _zod.z.array(_zod.z.string()).optional().describe("List of caller IDs in E.164 format to rotate through"),
|
|
25
|
+
webhook_url: _zod.z.string().url().optional().describe("Webhook URL for batch status updates"),
|
|
26
|
+
retry_config: _zod.z.object({
|
|
27
|
+
enabled: _zod.z.boolean().optional(),
|
|
28
|
+
max_retries: _zod.z.number().int().min(1).max(3).optional(),
|
|
29
|
+
retry_on_statuses: _zod.z.array(_zod.z.enum([
|
|
30
|
+
"no-answer",
|
|
31
|
+
"busy",
|
|
32
|
+
"failed",
|
|
33
|
+
"error"
|
|
34
|
+
])).optional(),
|
|
35
|
+
retry_intervals_minutes: _zod.z.array(_zod.z.number()).optional()
|
|
36
|
+
}).optional().describe("Retry configuration for failed calls in the batch")
|
|
37
|
+
}, async (args)=>{
|
|
38
|
+
try {
|
|
39
|
+
const form = new _formdata.default();
|
|
40
|
+
form.append("agent_id", args.agent_id);
|
|
41
|
+
// Convert csv_content string to a Buffer and attach as multipart file
|
|
42
|
+
const csvBuffer = Buffer.from(args.csv_content, "utf-8");
|
|
43
|
+
form.append("file", csvBuffer, {
|
|
44
|
+
filename: args.csv_filename ?? "contacts.csv",
|
|
45
|
+
contentType: "text/csv"
|
|
46
|
+
});
|
|
47
|
+
if (args.from_phone_numbers && args.from_phone_numbers.length > 0) {
|
|
48
|
+
args.from_phone_numbers.forEach((num)=>form.append("from_phone_numbers", num));
|
|
49
|
+
}
|
|
50
|
+
if (args.webhook_url) {
|
|
51
|
+
form.append("webhook_url", args.webhook_url);
|
|
52
|
+
}
|
|
53
|
+
if (args.retry_config) {
|
|
54
|
+
form.append("retry_config", JSON.stringify(args.retry_config));
|
|
55
|
+
}
|
|
56
|
+
const response = await _client.bolnaClient.post("/batches", form, {
|
|
57
|
+
headers: {
|
|
58
|
+
...form.getHeaders()
|
|
59
|
+
}
|
|
60
|
+
});
|
|
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_batch");
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
server.tool("bolna_schedule_batch", "Schedule a previously created batch to run at a specific date and time", {
|
|
74
|
+
batch_id: _zod.z.string().describe("The batch ID to schedule"),
|
|
75
|
+
run_at: _zod.z.string().describe('ISO 8601 datetime when the batch should start, e.g. "2025-08-21T10:00:00"')
|
|
76
|
+
}, async (args)=>{
|
|
77
|
+
try {
|
|
78
|
+
const response = await _client.bolnaClient.post(`/batches/${args.batch_id}/schedule`, {
|
|
79
|
+
run_at: args.run_at
|
|
80
|
+
});
|
|
81
|
+
return {
|
|
82
|
+
content: [
|
|
83
|
+
{
|
|
84
|
+
type: "text",
|
|
85
|
+
text: JSON.stringify(response.data, null, 2)
|
|
86
|
+
}
|
|
87
|
+
]
|
|
88
|
+
};
|
|
89
|
+
} catch (error) {
|
|
90
|
+
(0, _client.handleAxiosError)(error, "bolna_schedule_batch");
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
server.tool("bolna_stop_batch", "Stop a running batch campaign and cancel all pending calls in it", {
|
|
94
|
+
batch_id: _zod.z.string().describe("The batch ID to stop")
|
|
95
|
+
}, async (args)=>{
|
|
96
|
+
try {
|
|
97
|
+
const response = await _client.bolnaClient.post(`/batches/${args.batch_id}/stop`);
|
|
98
|
+
return {
|
|
99
|
+
content: [
|
|
100
|
+
{
|
|
101
|
+
type: "text",
|
|
102
|
+
text: JSON.stringify(response.data, null, 2) || `Batch ${args.batch_id} stopped successfully.`
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
};
|
|
106
|
+
} catch (error) {
|
|
107
|
+
(0, _client.handleAxiosError)(error, "bolna_stop_batch");
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
server.tool("bolna_get_batch", "Get detailed status and call counts for a specific batch campaign", {
|
|
111
|
+
batch_id: _zod.z.string().describe("The batch ID to retrieve")
|
|
112
|
+
}, async (args)=>{
|
|
113
|
+
try {
|
|
114
|
+
const response = await _client.bolnaClient.get(`/batches/${args.batch_id}`);
|
|
115
|
+
return {
|
|
116
|
+
content: [
|
|
117
|
+
{
|
|
118
|
+
type: "text",
|
|
119
|
+
text: JSON.stringify(response.data, null, 2)
|
|
120
|
+
}
|
|
121
|
+
]
|
|
122
|
+
};
|
|
123
|
+
} catch (error) {
|
|
124
|
+
(0, _client.handleAxiosError)(error, "bolna_get_batch");
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
server.tool("bolna_list_batches", "List all batch campaigns for a given Bolna agent", {
|
|
128
|
+
agent_id: _zod.z.string().describe("The agent ID whose batches to list"),
|
|
129
|
+
page_number: _zod.z.number().int().positive().optional().default(1).describe("Page number (1-indexed)"),
|
|
130
|
+
page_size: _zod.z.number().int().positive().optional().default(10).describe("Number of batches per page")
|
|
131
|
+
}, async (args)=>{
|
|
132
|
+
try {
|
|
133
|
+
const response = await _client.bolnaClient.get(`/agent/${args.agent_id}/batches`, {
|
|
134
|
+
params: {
|
|
135
|
+
page_number: args.page_number ?? 1,
|
|
136
|
+
page_size: args.page_size ?? 10
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
return {
|
|
140
|
+
content: [
|
|
141
|
+
{
|
|
142
|
+
type: "text",
|
|
143
|
+
text: JSON.stringify(response.data, null, 2)
|
|
144
|
+
}
|
|
145
|
+
]
|
|
146
|
+
};
|
|
147
|
+
} catch (error) {
|
|
148
|
+
(0, _client.handleAxiosError)(error, "bolna_list_batches");
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
server.tool("bolna_get_batch_executions", "List all individual call executions within a batch campaign", {
|
|
152
|
+
batch_id: _zod.z.string().describe("The batch ID to retrieve executions for"),
|
|
153
|
+
page_number: _zod.z.number().int().positive().optional().default(1).describe("Page number (1-indexed)"),
|
|
154
|
+
page_size: _zod.z.number().int().positive().optional().default(10).describe("Number of executions per page")
|
|
155
|
+
}, async (args)=>{
|
|
156
|
+
try {
|
|
157
|
+
const response = await _client.bolnaClient.get(`/batches/${args.batch_id}/executions`, {
|
|
158
|
+
params: {
|
|
159
|
+
page_number: args.page_number ?? 1,
|
|
160
|
+
page_size: args.page_size ?? 10
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
return {
|
|
164
|
+
content: [
|
|
165
|
+
{
|
|
166
|
+
type: "text",
|
|
167
|
+
text: JSON.stringify(response.data, null, 2)
|
|
168
|
+
}
|
|
169
|
+
]
|
|
170
|
+
};
|
|
171
|
+
} catch (error) {
|
|
172
|
+
(0, _client.handleAxiosError)(error, "bolna_get_batch_executions");
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
server.tool("bolna_delete_batch", "Permanently delete a batch campaign by its ID", {
|
|
176
|
+
batch_id: _zod.z.string().describe("The batch ID to delete")
|
|
177
|
+
}, async (args)=>{
|
|
178
|
+
try {
|
|
179
|
+
const response = await _client.bolnaClient.delete(`/batches/${args.batch_id}`);
|
|
180
|
+
return {
|
|
181
|
+
content: [
|
|
182
|
+
{
|
|
183
|
+
type: "text",
|
|
184
|
+
text: JSON.stringify(response.data, null, 2) || `Batch ${args.batch_id} deleted successfully.`
|
|
185
|
+
}
|
|
186
|
+
]
|
|
187
|
+
};
|
|
188
|
+
} catch (error) {
|
|
189
|
+
(0, _client.handleAxiosError)(error, "bolna_delete_batch");
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "registerCallTools", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return registerCallTools;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _zod = require("zod");
|
|
12
|
+
const _client = require("../client.js");
|
|
13
|
+
function registerCallTools(server) {
|
|
14
|
+
server.tool("bolna_make_call", "Initiate an outbound voice call using a Bolna agent to a specified phone number", {
|
|
15
|
+
agent_id: _zod.z.string().uuid().describe("UUID of the Bolna agent to use for the call"),
|
|
16
|
+
recipient_phone_number: _zod.z.string().describe('Recipient phone number in E.164 format, e.g. "+919876543210"'),
|
|
17
|
+
from_phone_number: _zod.z.string().optional().describe("Caller ID in E.164 format (optional)"),
|
|
18
|
+
scheduled_at: _zod.z.string().optional().describe('ISO 8601 datetime to schedule the call, e.g. "2025-08-21T10:35:00"'),
|
|
19
|
+
user_data: _zod.z.record(_zod.z.unknown()).optional().describe("Key-value pairs for dynamic prompt variable substitution in the agent"),
|
|
20
|
+
bypass_call_guardrails: _zod.z.boolean().optional().default(false).describe("Skip call guardrails if true"),
|
|
21
|
+
retry_enabled: _zod.z.boolean().optional().describe("Enable automatic call retries"),
|
|
22
|
+
retry_max_retries: _zod.z.number().int().min(1).max(3).optional().describe("Number of retry attempts (1–3)"),
|
|
23
|
+
retry_on_statuses: _zod.z.array(_zod.z.enum([
|
|
24
|
+
"no-answer",
|
|
25
|
+
"busy",
|
|
26
|
+
"failed",
|
|
27
|
+
"error"
|
|
28
|
+
])).optional().describe("Call statuses that should trigger a retry"),
|
|
29
|
+
retry_intervals_minutes: _zod.z.array(_zod.z.number()).optional().describe("Minutes to wait before each retry attempt, e.g. [30, 60, 120]")
|
|
30
|
+
}, async (args)=>{
|
|
31
|
+
try {
|
|
32
|
+
const body = {
|
|
33
|
+
agent_id: args.agent_id,
|
|
34
|
+
recipient_phone_number: args.recipient_phone_number
|
|
35
|
+
};
|
|
36
|
+
if (args.from_phone_number !== undefined) body.from_phone_number = args.from_phone_number;
|
|
37
|
+
if (args.scheduled_at !== undefined) body.scheduled_at = args.scheduled_at;
|
|
38
|
+
if (args.user_data !== undefined) body.user_data = args.user_data;
|
|
39
|
+
if (args.bypass_call_guardrails !== undefined) body.bypass_call_guardrails = args.bypass_call_guardrails;
|
|
40
|
+
// Build retry_config only if any retry field is provided
|
|
41
|
+
if (args.retry_enabled !== undefined || args.retry_max_retries !== undefined || args.retry_on_statuses !== undefined || args.retry_intervals_minutes !== undefined) {
|
|
42
|
+
body.retry_config = {
|
|
43
|
+
...args.retry_enabled !== undefined && {
|
|
44
|
+
enabled: args.retry_enabled
|
|
45
|
+
},
|
|
46
|
+
...args.retry_max_retries !== undefined && {
|
|
47
|
+
max_retries: args.retry_max_retries
|
|
48
|
+
},
|
|
49
|
+
...args.retry_on_statuses !== undefined && {
|
|
50
|
+
retry_on_statuses: args.retry_on_statuses
|
|
51
|
+
},
|
|
52
|
+
...args.retry_intervals_minutes !== undefined && {
|
|
53
|
+
retry_intervals_minutes: args.retry_intervals_minutes
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const response = await _client.bolnaClient.post("/call", body);
|
|
58
|
+
return {
|
|
59
|
+
content: [
|
|
60
|
+
{
|
|
61
|
+
type: "text",
|
|
62
|
+
text: JSON.stringify(response.data, null, 2)
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
};
|
|
66
|
+
} catch (error) {
|
|
67
|
+
(0, _client.handleAxiosError)(error, "bolna_make_call");
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
server.tool("bolna_stop_call", "Immediately terminate an active call by its execution ID", {
|
|
71
|
+
execution_id: _zod.z.string().describe("The execution ID of the active call to stop")
|
|
72
|
+
}, async (args)=>{
|
|
73
|
+
try {
|
|
74
|
+
const response = await _client.bolnaClient.post(`/call/stop/${args.execution_id}`);
|
|
75
|
+
return {
|
|
76
|
+
content: [
|
|
77
|
+
{
|
|
78
|
+
type: "text",
|
|
79
|
+
text: JSON.stringify(response.data, null, 2) || `Call ${args.execution_id} stopped successfully.`
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
};
|
|
83
|
+
} catch (error) {
|
|
84
|
+
(0, _client.handleAxiosError)(error, "bolna_stop_call");
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "registerDispositionTools", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return registerDispositionTools;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _zod = require("zod");
|
|
12
|
+
const _client = require("../client.js");
|
|
13
|
+
// Shared schema for a single ObjectiveOption (used in create/update/bulk)
|
|
14
|
+
const objectiveOptionSchema = _zod.z.lazy(()=>_zod.z.object({
|
|
15
|
+
value: _zod.z.string().describe("Value returned when this option is selected"),
|
|
16
|
+
condition: _zod.z.string().describe("Natural-language condition describing when this option applies"),
|
|
17
|
+
sub_options: _zod.z.array(objectiveOptionSchema).optional().describe("Nested sub-options for hierarchical classifications")
|
|
18
|
+
}));
|
|
19
|
+
function registerDispositionTools(server) {
|
|
20
|
+
server.tool("bolna_create_disposition", "Create a new call extraction disposition and link it to a Bolna agent", {
|
|
21
|
+
agent_id: _zod.z.string().uuid().describe("UUID of the agent this disposition will be linked to"),
|
|
22
|
+
name: _zod.z.string().describe("Display name for the disposition"),
|
|
23
|
+
question: _zod.z.string().describe("The prompt sent to the LLM to evaluate the transcript"),
|
|
24
|
+
category: _zod.z.string().optional().default("General").describe('Category grouping for the disposition (default: "General")'),
|
|
25
|
+
system_prompt: _zod.z.string().optional().describe("Optional system context for the evaluating LLM"),
|
|
26
|
+
model: _zod.z.string().optional().default("gpt-4.1-mini").describe("LLM model to use for evaluation"),
|
|
27
|
+
is_subjective: _zod.z.boolean().optional().default(false).describe("Enable free-text response"),
|
|
28
|
+
is_objective: _zod.z.boolean().optional().default(false).describe("Enable pre-defined value selection"),
|
|
29
|
+
subjective_type: _zod.z.enum([
|
|
30
|
+
"text",
|
|
31
|
+
"timestamp",
|
|
32
|
+
"numeric",
|
|
33
|
+
"boolean",
|
|
34
|
+
"email",
|
|
35
|
+
"regex"
|
|
36
|
+
]).optional().default("text").describe("Format constraint for the free-text response"),
|
|
37
|
+
subjective_type_config: _zod.z.object({
|
|
38
|
+
pattern: _zod.z.string().describe("Regex pattern the answer must match"),
|
|
39
|
+
description: _zod.z.string().optional()
|
|
40
|
+
}).optional().describe("Required when subjective_type is 'regex'"),
|
|
41
|
+
objective_options: _zod.z.array(objectiveOptionSchema).optional().describe("Required when is_objective is true")
|
|
42
|
+
}, async (args)=>{
|
|
43
|
+
try {
|
|
44
|
+
const body = {
|
|
45
|
+
agent_id: args.agent_id,
|
|
46
|
+
name: args.name,
|
|
47
|
+
question: args.question,
|
|
48
|
+
category: args.category ?? "General",
|
|
49
|
+
model: args.model ?? "gpt-4.1-mini",
|
|
50
|
+
is_subjective: args.is_subjective ?? false,
|
|
51
|
+
is_objective: args.is_objective ?? false,
|
|
52
|
+
subjective_type: args.subjective_type ?? "text"
|
|
53
|
+
};
|
|
54
|
+
if (args.system_prompt !== undefined) body.system_prompt = args.system_prompt;
|
|
55
|
+
if (args.subjective_type_config !== undefined) body.subjective_type_config = args.subjective_type_config;
|
|
56
|
+
if (args.objective_options !== undefined) body.objective_options = args.objective_options;
|
|
57
|
+
const response = await _client.bolnaClient.post("/dispositions/", body);
|
|
58
|
+
return {
|
|
59
|
+
content: [
|
|
60
|
+
{
|
|
61
|
+
type: "text",
|
|
62
|
+
text: JSON.stringify(response.data, null, 2)
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
};
|
|
66
|
+
} catch (error) {
|
|
67
|
+
(0, _client.handleAxiosError)(error, "bolna_create_disposition");
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
server.tool("bolna_bulk_create_dispositions", "Atomically create and link multiple dispositions to an agent in a single request", {
|
|
71
|
+
agent_id: _zod.z.string().uuid().describe("UUID of the agent to link all dispositions to"),
|
|
72
|
+
dispositions: _zod.z.array(_zod.z.object({
|
|
73
|
+
name: _zod.z.string(),
|
|
74
|
+
question: _zod.z.string(),
|
|
75
|
+
category: _zod.z.string().optional(),
|
|
76
|
+
system_prompt: _zod.z.string().optional(),
|
|
77
|
+
model: _zod.z.string().optional(),
|
|
78
|
+
is_subjective: _zod.z.boolean().optional(),
|
|
79
|
+
is_objective: _zod.z.boolean().optional(),
|
|
80
|
+
subjective_type: _zod.z.enum([
|
|
81
|
+
"text",
|
|
82
|
+
"timestamp",
|
|
83
|
+
"numeric",
|
|
84
|
+
"boolean",
|
|
85
|
+
"email",
|
|
86
|
+
"regex"
|
|
87
|
+
]).optional(),
|
|
88
|
+
objective_options: _zod.z.array(objectiveOptionSchema).optional()
|
|
89
|
+
})).describe("Array of disposition objects to create")
|
|
90
|
+
}, async (args)=>{
|
|
91
|
+
try {
|
|
92
|
+
const response = await _client.bolnaClient.post("/dispositions/bulk", {
|
|
93
|
+
agent_id: args.agent_id,
|
|
94
|
+
dispositions: args.dispositions
|
|
95
|
+
});
|
|
96
|
+
return {
|
|
97
|
+
content: [
|
|
98
|
+
{
|
|
99
|
+
type: "text",
|
|
100
|
+
text: JSON.stringify(response.data, null, 2)
|
|
101
|
+
}
|
|
102
|
+
]
|
|
103
|
+
};
|
|
104
|
+
} catch (error) {
|
|
105
|
+
(0, _client.handleAxiosError)(error, "bolna_bulk_create_dispositions");
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
server.tool("bolna_get_disposition", "Retrieve a single disposition by its ID", {
|
|
109
|
+
disposition_id: _zod.z.string().describe("UUID of the disposition to retrieve"),
|
|
110
|
+
agent_id: _zod.z.string().optional().describe("Optional agent UUID to scope the lookup")
|
|
111
|
+
}, async (args)=>{
|
|
112
|
+
try {
|
|
113
|
+
const response = await _client.bolnaClient.get(`/dispositions/${args.disposition_id}`, args.agent_id ? {
|
|
114
|
+
params: {
|
|
115
|
+
agent_id: args.agent_id
|
|
116
|
+
}
|
|
117
|
+
} : {});
|
|
118
|
+
return {
|
|
119
|
+
content: [
|
|
120
|
+
{
|
|
121
|
+
type: "text",
|
|
122
|
+
text: JSON.stringify(response.data, null, 2)
|
|
123
|
+
}
|
|
124
|
+
]
|
|
125
|
+
};
|
|
126
|
+
} catch (error) {
|
|
127
|
+
(0, _client.handleAxiosError)(error, "bolna_get_disposition");
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
server.tool("bolna_list_dispositions", "List all dispositions for your account, optionally filtered by agent", {
|
|
131
|
+
agent_id: _zod.z.string().optional().describe("Optional agent UUID to filter dispositions by")
|
|
132
|
+
}, async (args)=>{
|
|
133
|
+
try {
|
|
134
|
+
const response = await _client.bolnaClient.get("/dispositions/", {
|
|
135
|
+
params: args.agent_id ? {
|
|
136
|
+
agent_id: args.agent_id
|
|
137
|
+
} : {}
|
|
138
|
+
});
|
|
139
|
+
return {
|
|
140
|
+
content: [
|
|
141
|
+
{
|
|
142
|
+
type: "text",
|
|
143
|
+
text: JSON.stringify(response.data, null, 2)
|
|
144
|
+
}
|
|
145
|
+
]
|
|
146
|
+
};
|
|
147
|
+
} catch (error) {
|
|
148
|
+
(0, _client.handleAxiosError)(error, "bolna_list_dispositions");
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
server.tool("bolna_update_disposition", "Update a disposition. When scoped to an agent, shared dispositions are copied before editing", {
|
|
152
|
+
disposition_id: _zod.z.string().describe("UUID of the disposition to update"),
|
|
153
|
+
agent_id: _zod.z.string().optional().describe("Agent UUID to scope the update (triggers copy-on-write for shared dispositions)"),
|
|
154
|
+
name: _zod.z.string().optional(),
|
|
155
|
+
question: _zod.z.string().optional(),
|
|
156
|
+
category: _zod.z.string().optional(),
|
|
157
|
+
system_prompt: _zod.z.string().optional(),
|
|
158
|
+
model: _zod.z.string().optional(),
|
|
159
|
+
is_subjective: _zod.z.boolean().optional(),
|
|
160
|
+
is_objective: _zod.z.boolean().optional(),
|
|
161
|
+
subjective_type: _zod.z.enum([
|
|
162
|
+
"text",
|
|
163
|
+
"timestamp",
|
|
164
|
+
"numeric",
|
|
165
|
+
"boolean",
|
|
166
|
+
"email",
|
|
167
|
+
"regex"
|
|
168
|
+
]).optional(),
|
|
169
|
+
objective_options: _zod.z.array(objectiveOptionSchema).optional()
|
|
170
|
+
}, async (args)=>{
|
|
171
|
+
try {
|
|
172
|
+
const { disposition_id, agent_id, ...rest } = args;
|
|
173
|
+
const params = agent_id ? {
|
|
174
|
+
agent_id
|
|
175
|
+
} : {};
|
|
176
|
+
const response = await _client.bolnaClient.put(`/dispositions/${disposition_id}`, rest, {
|
|
177
|
+
params
|
|
178
|
+
});
|
|
179
|
+
return {
|
|
180
|
+
content: [
|
|
181
|
+
{
|
|
182
|
+
type: "text",
|
|
183
|
+
text: JSON.stringify(response.data, null, 2)
|
|
184
|
+
}
|
|
185
|
+
]
|
|
186
|
+
};
|
|
187
|
+
} catch (error) {
|
|
188
|
+
(0, _client.handleAxiosError)(error, "bolna_update_disposition");
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
server.tool("bolna_delete_disposition", "Permanently delete a disposition by its ID", {
|
|
192
|
+
disposition_id: _zod.z.string().describe("UUID of the disposition to delete")
|
|
193
|
+
}, async (args)=>{
|
|
194
|
+
try {
|
|
195
|
+
const response = await _client.bolnaClient.delete(`/dispositions/${args.disposition_id}`);
|
|
196
|
+
return {
|
|
197
|
+
content: [
|
|
198
|
+
{
|
|
199
|
+
type: "text",
|
|
200
|
+
text: JSON.stringify(response.data, null, 2) || `Disposition ${args.disposition_id} deleted successfully.`
|
|
201
|
+
}
|
|
202
|
+
]
|
|
203
|
+
};
|
|
204
|
+
} catch (error) {
|
|
205
|
+
(0, _client.handleAxiosError)(error, "bolna_delete_disposition");
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
server.tool("bolna_test_dispositions", "Test all dispositions linked to an agent against a call transcript to preview extraction results", {
|
|
209
|
+
agent_id: _zod.z.string().uuid().describe("UUID of the agent whose dispositions to test"),
|
|
210
|
+
transcript: _zod.z.array(_zod.z.object({
|
|
211
|
+
role: _zod.z.enum([
|
|
212
|
+
"user",
|
|
213
|
+
"assistant"
|
|
214
|
+
]),
|
|
215
|
+
content: _zod.z.string()
|
|
216
|
+
})).describe("Conversation transcript as an array of role/content objects to evaluate")
|
|
217
|
+
}, async (args)=>{
|
|
218
|
+
try {
|
|
219
|
+
const response = await _client.bolnaClient.post(`/v2/agent/${args.agent_id}/dispositions/test`, {
|
|
220
|
+
transcript: args.transcript
|
|
221
|
+
});
|
|
222
|
+
return {
|
|
223
|
+
content: [
|
|
224
|
+
{
|
|
225
|
+
type: "text",
|
|
226
|
+
text: JSON.stringify(response.data, null, 2)
|
|
227
|
+
}
|
|
228
|
+
]
|
|
229
|
+
};
|
|
230
|
+
} catch (error) {
|
|
231
|
+
(0, _client.handleAxiosError)(error, "bolna_test_dispositions");
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "registerExecutionTools", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return registerExecutionTools;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _zod = require("zod");
|
|
12
|
+
const _client = require("../client.js");
|
|
13
|
+
function registerExecutionTools(server) {
|
|
14
|
+
server.tool("bolna_get_execution", "Retrieve full details of a call execution including transcript and recording URL", {
|
|
15
|
+
execution_id: _zod.z.string().describe("The execution ID of the call to retrieve")
|
|
16
|
+
}, async (args)=>{
|
|
17
|
+
try {
|
|
18
|
+
const response = await _client.bolnaClient.get(`/execution/${args.execution_id}`);
|
|
19
|
+
return {
|
|
20
|
+
content: [
|
|
21
|
+
{
|
|
22
|
+
type: "text",
|
|
23
|
+
text: JSON.stringify(response.data, null, 2)
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
};
|
|
27
|
+
} catch (error) {
|
|
28
|
+
(0, _client.handleAxiosError)(error, "bolna_get_execution");
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
server.tool("bolna_list_agent_executions", "List all call executions for a specific Bolna agent with pagination", {
|
|
32
|
+
agent_id: _zod.z.string().describe("The agent ID whose call history to retrieve"),
|
|
33
|
+
page_number: _zod.z.number().int().positive().optional().default(1).describe("Page number (1-indexed)"),
|
|
34
|
+
page_size: _zod.z.number().int().positive().optional().default(10).describe("Number of executions per page")
|
|
35
|
+
}, async (args)=>{
|
|
36
|
+
try {
|
|
37
|
+
const response = await _client.bolnaClient.get(`/agent/${args.agent_id}/executions`, {
|
|
38
|
+
params: {
|
|
39
|
+
page_number: args.page_number ?? 1,
|
|
40
|
+
page_size: args.page_size ?? 10
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
return {
|
|
44
|
+
content: [
|
|
45
|
+
{
|
|
46
|
+
type: "text",
|
|
47
|
+
text: JSON.stringify(response.data, null, 2)
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
};
|
|
51
|
+
} catch (error) {
|
|
52
|
+
(0, _client.handleAxiosError)(error, "bolna_list_agent_executions");
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
server.tool("bolna_get_execution_raw_logs", "Fetch raw debug logs for a call execution including LLM prompts, requests, responses, and reasoning", {
|
|
56
|
+
execution_id: _zod.z.string().describe("The execution ID whose raw logs to retrieve")
|
|
57
|
+
}, async (args)=>{
|
|
58
|
+
try {
|
|
59
|
+
const response = await _client.bolnaClient.get(`/execution/${args.execution_id}/raw-logs`);
|
|
60
|
+
return {
|
|
61
|
+
content: [
|
|
62
|
+
{
|
|
63
|
+
type: "text",
|
|
64
|
+
text: JSON.stringify(response.data, null, 2)
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
};
|
|
68
|
+
} catch (error) {
|
|
69
|
+
(0, _client.handleAxiosError)(error, "bolna_get_execution_raw_logs");
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "registerInboundTools", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return registerInboundTools;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _zod = require("zod");
|
|
12
|
+
const _client = require("../client.js");
|
|
13
|
+
function registerInboundTools(server) {
|
|
14
|
+
server.tool("bolna_set_inbound_agent", "Associate a Bolna agent with a phone number so it automatically handles inbound calls", {
|
|
15
|
+
agent_id: _zod.z.string().describe("The agent ID to assign for handling inbound calls"),
|
|
16
|
+
phone_number: _zod.z.string().describe("The phone number (E.164 or as stored in Bolna) to configure for inbound")
|
|
17
|
+
}, async (args)=>{
|
|
18
|
+
try {
|
|
19
|
+
const response = await _client.bolnaClient.post("/inbound/set-agent", {
|
|
20
|
+
agent_id: args.agent_id,
|
|
21
|
+
phone_number: args.phone_number
|
|
22
|
+
});
|
|
23
|
+
return {
|
|
24
|
+
content: [
|
|
25
|
+
{
|
|
26
|
+
type: "text",
|
|
27
|
+
text: JSON.stringify(response.data, null, 2)
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
};
|
|
31
|
+
} catch (error) {
|
|
32
|
+
(0, _client.handleAxiosError)(error, "bolna_set_inbound_agent");
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
server.tool("bolna_unlink_inbound_agent", "Remove a Bolna agent from a phone number to disable automated inbound call answering", {
|
|
36
|
+
phone_number: _zod.z.string().describe("The phone number to unlink from its current inbound agent")
|
|
37
|
+
}, async (args)=>{
|
|
38
|
+
try {
|
|
39
|
+
const response = await _client.bolnaClient.delete("/inbound/unlink", {
|
|
40
|
+
data: {
|
|
41
|
+
phone_number: args.phone_number
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
return {
|
|
45
|
+
content: [
|
|
46
|
+
{
|
|
47
|
+
type: "text",
|
|
48
|
+
text: JSON.stringify(response.data, null, 2) || `Inbound agent unlinked from ${args.phone_number} successfully.`
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
};
|
|
52
|
+
} catch (error) {
|
|
53
|
+
(0, _client.handleAxiosError)(error, "bolna_unlink_inbound_agent");
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|