@rymi/mcp 2.2.0 → 2.4.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 +7 -3
- package/dist/index.js +210 -67
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -63,7 +63,7 @@ Run the server on your own machine — it speaks **stdio** by default and talks
|
|
|
63
63
|
}
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
-
> **Options:** `RYMI_MCP_READONLY=1` hides every mutating tool (including `create_call`, `batch_call`, `publish_agent`).
|
|
66
|
+
> **Options:** `RYMI_MCP_READONLY=1` hides every mutating tool (including `create_call`, `batch_call`, `publish_agent`). `RYMI_WORKSPACE` makes the local server act in that workspace (sent as the `Rymi-Workspace` header). On the hosted endpoint, send the `Rymi-Workspace` header on the HTTP request instead.
|
|
67
67
|
>
|
|
68
68
|
> This package speaks **stdio** only. `--transport http` was removed in 2.0.0 — use the hosted endpoint above, which the local server could never match on auth (it has no OAuth, and no per-key tool gating).
|
|
69
69
|
|
|
@@ -76,8 +76,8 @@ Run the server on your own machine — it speaks **stdio** by default and talks
|
|
|
76
76
|
<td><code>list_agents</code> · <code>get_agent</code> · <code>create_agent</code> · <code>update_agent</code> · <code>delete_agent</code> · <code>clone_agent</code> · <code>apply_agent_changes</code> · <code>generate_agent_draft</code> · <code>enrich_company</code> · <code>validate_agent_publish</code> · <code>preview_stack</code> · <code>publish_agent</code></td>
|
|
77
77
|
</tr>
|
|
78
78
|
<tr>
|
|
79
|
-
<td><b>
|
|
80
|
-
<td><code>list_agent_tools</code> · <code>add_agent_tool</code> · <code>update_agent_tool</code> · <code>remove_agent_tool</code> · <code>list_tool_secrets</code> · <code>set_tool_secret</code></td>
|
|
79
|
+
<td><b>Agent tools & secrets</b></td>
|
|
80
|
+
<td><code>set_agent_tools</code> · <code>list_agent_tools</code> · <code>add_agent_tool</code> · <code>update_agent_tool</code> · <code>remove_agent_tool</code> · <code>list_tool_secrets</code> · <code>set_tool_secret</code></td>
|
|
81
81
|
</tr>
|
|
82
82
|
<tr>
|
|
83
83
|
<td><b>Share link</b></td>
|
|
@@ -135,6 +135,10 @@ Run the server on your own machine — it speaks **stdio** by default and talks
|
|
|
135
135
|
<td><b>Billing & cost</b></td>
|
|
136
136
|
<td><code>estimate_call_cost</code> · <code>set_auto_recharge</code> · <code>set_spend_alerts</code></td>
|
|
137
137
|
</tr>
|
|
138
|
+
<tr>
|
|
139
|
+
<td><b>Workspaces</b></td>
|
|
140
|
+
<td><code>list_workspaces</code> · <code>create_workspace</code></td>
|
|
141
|
+
</tr>
|
|
138
142
|
</table>
|
|
139
143
|
|
|
140
144
|
### ⚠️ Gated tools
|
package/dist/index.js
CHANGED
|
@@ -34,6 +34,68 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
34
34
|
));
|
|
35
35
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
36
36
|
|
|
37
|
+
// ../shared-types/dist/safeUrl.js
|
|
38
|
+
var safeUrl_exports = {};
|
|
39
|
+
__export(safeUrl_exports, {
|
|
40
|
+
isSafeUrl: () => isSafeUrl
|
|
41
|
+
});
|
|
42
|
+
function unmapIpv4(v6) {
|
|
43
|
+
const dotted = /^::ffff:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/.exec(v6);
|
|
44
|
+
if (dotted)
|
|
45
|
+
return dotted[1];
|
|
46
|
+
const hex = /^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/.exec(v6);
|
|
47
|
+
if (!hex)
|
|
48
|
+
return null;
|
|
49
|
+
const high = parseInt(hex[1], 16);
|
|
50
|
+
const low = parseInt(hex[2], 16);
|
|
51
|
+
return [high >> 8, high & 255, low >> 8, low & 255].join(".");
|
|
52
|
+
}
|
|
53
|
+
function isBlockedHost(host) {
|
|
54
|
+
const bare = host.startsWith("[") && host.endsWith("]") ? host.slice(1, -1) : host;
|
|
55
|
+
if (bare === "localhost" || bare === "0.0.0.0" || bare === "::")
|
|
56
|
+
return true;
|
|
57
|
+
if (bare.endsWith(".local") || bare.endsWith(".internal") || bare.endsWith(".localhost"))
|
|
58
|
+
return true;
|
|
59
|
+
if (/^127\./.test(bare))
|
|
60
|
+
return true;
|
|
61
|
+
if (/^10\./.test(bare))
|
|
62
|
+
return true;
|
|
63
|
+
if (/^192\.168\./.test(bare))
|
|
64
|
+
return true;
|
|
65
|
+
if (/^172\.(1[6-9]|2\d|3[01])\./.test(bare))
|
|
66
|
+
return true;
|
|
67
|
+
if (/^169\.254\./.test(bare))
|
|
68
|
+
return true;
|
|
69
|
+
const v6 = bare.toLowerCase();
|
|
70
|
+
if (v6 === "::1")
|
|
71
|
+
return true;
|
|
72
|
+
if (/^f[cd][0-9a-f]{2}:/.test(v6))
|
|
73
|
+
return true;
|
|
74
|
+
if (/^fe[89ab][0-9a-f]:/.test(v6))
|
|
75
|
+
return true;
|
|
76
|
+
const mapped = unmapIpv4(v6);
|
|
77
|
+
if (mapped)
|
|
78
|
+
return isBlockedHost(mapped);
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
function isSafeUrl(raw, options = {}) {
|
|
82
|
+
const protocols = options.protocols ?? ["http:", "https:"];
|
|
83
|
+
let url;
|
|
84
|
+
try {
|
|
85
|
+
url = new URL(raw);
|
|
86
|
+
} catch {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
if (!protocols.includes(url.protocol))
|
|
90
|
+
return false;
|
|
91
|
+
return !isBlockedHost(url.hostname.toLowerCase());
|
|
92
|
+
}
|
|
93
|
+
var init_safeUrl = __esm({
|
|
94
|
+
"../shared-types/dist/safeUrl.js"() {
|
|
95
|
+
"use strict";
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
37
99
|
// ../shared-types/dist/agentTools.js
|
|
38
100
|
var agentTools_exports = {};
|
|
39
101
|
__export(agentTools_exports, {
|
|
@@ -43,9 +105,32 @@ __export(agentTools_exports, {
|
|
|
43
105
|
API_TOOL_RESERVED_FIELD_NAMES: () => API_TOOL_RESERVED_FIELD_NAMES,
|
|
44
106
|
API_TOOL_SECRET_REF_PATTERN: () => API_TOOL_SECRET_REF_PATTERN,
|
|
45
107
|
BUILTIN_TOOL_CATALOG: () => BUILTIN_TOOL_CATALOG,
|
|
108
|
+
MCP_CONNECT_TIMEOUT_MS: () => MCP_CONNECT_TIMEOUT_MS,
|
|
109
|
+
MCP_SERVER_TOOL_ID: () => MCP_SERVER_TOOL_ID,
|
|
46
110
|
SECRET_NAME_PATTERN: () => SECRET_NAME_PATTERN,
|
|
111
|
+
connectionStatus: () => connectionStatus,
|
|
112
|
+
isAgentToolEnabled: () => isAgentToolEnabled,
|
|
113
|
+
readMcpServerBinding: () => readMcpServerBinding,
|
|
47
114
|
toToolCapabilitySafeView: () => toToolCapabilitySafeView
|
|
48
115
|
});
|
|
116
|
+
function readMcpServerBinding(binding) {
|
|
117
|
+
const raw = binding?.provider_settings ?? {};
|
|
118
|
+
const url = typeof raw.url === "string" ? raw.url.trim() : "";
|
|
119
|
+
if (!isSafeUrl(url, { protocols: ["https:"] }))
|
|
120
|
+
return null;
|
|
121
|
+
const allowlist = Array.isArray(raw.allowlist) ? [...new Set(raw.allowlist.filter((t) => typeof t === "string" && t.trim() !== "").map((t) => t.trim()))].slice(0, MAX_MCP_ALLOWLIST) : [];
|
|
122
|
+
if (allowlist.length === 0)
|
|
123
|
+
return null;
|
|
124
|
+
const headers = {};
|
|
125
|
+
if (raw.headers && typeof raw.headers === "object" && !Array.isArray(raw.headers)) {
|
|
126
|
+
for (const [key, value] of Object.entries(raw.headers)) {
|
|
127
|
+
if (key.trim() && typeof value === "string")
|
|
128
|
+
headers[key.trim()] = value;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
const name = typeof raw.name === "string" && raw.name.trim() ? raw.name.trim() : new URL(url).hostname;
|
|
132
|
+
return { name, url, headers, allowlist };
|
|
133
|
+
}
|
|
49
134
|
function toToolCapabilitySafeView(state) {
|
|
50
135
|
return {
|
|
51
136
|
toolId: state.toolId,
|
|
@@ -54,10 +139,27 @@ function toToolCapabilitySafeView(state) {
|
|
|
54
139
|
sideEffect: state.sideEffect
|
|
55
140
|
};
|
|
56
141
|
}
|
|
57
|
-
|
|
142
|
+
function isAgentToolEnabled(bindings, defaultOn) {
|
|
143
|
+
if (bindings?.some((binding) => binding.enabled === true))
|
|
144
|
+
return true;
|
|
145
|
+
if (bindings?.some((binding) => binding.enabled === false))
|
|
146
|
+
return false;
|
|
147
|
+
return defaultOn;
|
|
148
|
+
}
|
|
149
|
+
function connectionStatus(row) {
|
|
150
|
+
if (row.is_active === false)
|
|
151
|
+
return "error";
|
|
152
|
+
const creds = row.credentials || {};
|
|
153
|
+
const hasRefreshToken = typeof creds.refresh_token === "string" && creds.refresh_token.trim().length > 0;
|
|
154
|
+
const expiresAt = typeof creds.expires_at === "string" ? new Date(creds.expires_at) : null;
|
|
155
|
+
const accessTokenExpired = expiresAt && !isNaN(expiresAt.getTime()) && expiresAt.getTime() < Date.now();
|
|
156
|
+
return accessTokenExpired && !hasRefreshToken ? "expired" : "connected";
|
|
157
|
+
}
|
|
158
|
+
var API_TOOL_NAME_PATTERN, SECRET_NAME_PATTERN, API_SECRETS_PROVIDER, API_TOOL_RESERVED_FIELD_NAMES, API_TOOL_AUTH_HEADER_PATTERN, API_TOOL_SECRET_REF_PATTERN, MCP_SERVER_TOOL_ID, MCP_CONNECT_TIMEOUT_MS, MAX_MCP_ALLOWLIST, BUILTIN_TOOL_CATALOG;
|
|
58
159
|
var init_agentTools = __esm({
|
|
59
160
|
"../shared-types/dist/agentTools.js"() {
|
|
60
161
|
"use strict";
|
|
162
|
+
init_safeUrl();
|
|
61
163
|
API_TOOL_NAME_PATTERN = /^[a-z][a-z0-9_]{2,40}$/;
|
|
62
164
|
SECRET_NAME_PATTERN = /^[A-Z][A-Z0-9_]{1,63}$/;
|
|
63
165
|
API_SECRETS_PROVIDER = "api_secrets";
|
|
@@ -101,6 +203,9 @@ var init_agentTools = __esm({
|
|
|
101
203
|
]);
|
|
102
204
|
API_TOOL_AUTH_HEADER_PATTERN = /^(authorization|x-api-key|api[-_]?key|.*token.*|.*secret.*)$/i;
|
|
103
205
|
API_TOOL_SECRET_REF_PATTERN = /\{\{\s*secrets\.[A-Z][A-Z0-9_]{1,63}\s*\}\}/;
|
|
206
|
+
MCP_SERVER_TOOL_ID = "mcp_server";
|
|
207
|
+
MCP_CONNECT_TIMEOUT_MS = 3e3;
|
|
208
|
+
MAX_MCP_ALLOWLIST = 50;
|
|
104
209
|
BUILTIN_TOOL_CATALOG = [
|
|
105
210
|
{
|
|
106
211
|
tool_id: "handoff_to_human",
|
|
@@ -111,6 +216,15 @@ var init_agentTools = __esm({
|
|
|
111
216
|
default_timeout_ms: 1e3,
|
|
112
217
|
requires_credential: false
|
|
113
218
|
},
|
|
219
|
+
{
|
|
220
|
+
tool_id: "schedule_callback",
|
|
221
|
+
label: "Scheduled callbacks",
|
|
222
|
+
description: "Let the agent schedule a call back to the caller at a time they choose, and place it itself at that time (Indian mobile numbers, 9 am to 9 pm IST). Needs a phone number attached to the agent or the workspace; no calendar or messaging connection is required.",
|
|
223
|
+
category: "call_control",
|
|
224
|
+
side_effect: "write",
|
|
225
|
+
default_timeout_ms: 4e3,
|
|
226
|
+
requires_credential: false
|
|
227
|
+
},
|
|
114
228
|
{
|
|
115
229
|
tool_id: "check_calendar_availability",
|
|
116
230
|
label: "Check calendar availability",
|
|
@@ -220,73 +334,20 @@ var init_agentTools = __esm({
|
|
|
220
334
|
// The endpoint lives in the binding's provider_settings and its secrets in
|
|
221
335
|
// the tenant's api_secrets row — nothing to connect in Settings → Connectors.
|
|
222
336
|
requires_credential: false
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
tool_id: "mcp_server",
|
|
340
|
+
label: "MCP server",
|
|
341
|
+
description: "Give the agent tools from your own MCP server. Only the tools you allowlist are offered; header secrets stay encrypted and are sent only to that server.",
|
|
342
|
+
category: "webhook",
|
|
343
|
+
side_effect: "write",
|
|
344
|
+
default_timeout_ms: MCP_CONNECT_TIMEOUT_MS,
|
|
345
|
+
requires_credential: false
|
|
223
346
|
}
|
|
224
347
|
];
|
|
225
348
|
}
|
|
226
349
|
});
|
|
227
350
|
|
|
228
|
-
// ../shared-types/dist/safeUrl.js
|
|
229
|
-
var safeUrl_exports = {};
|
|
230
|
-
__export(safeUrl_exports, {
|
|
231
|
-
isSafeUrl: () => isSafeUrl
|
|
232
|
-
});
|
|
233
|
-
function unmapIpv4(v6) {
|
|
234
|
-
const dotted = /^::ffff:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/.exec(v6);
|
|
235
|
-
if (dotted)
|
|
236
|
-
return dotted[1];
|
|
237
|
-
const hex = /^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/.exec(v6);
|
|
238
|
-
if (!hex)
|
|
239
|
-
return null;
|
|
240
|
-
const high = parseInt(hex[1], 16);
|
|
241
|
-
const low = parseInt(hex[2], 16);
|
|
242
|
-
return [high >> 8, high & 255, low >> 8, low & 255].join(".");
|
|
243
|
-
}
|
|
244
|
-
function isBlockedHost(host) {
|
|
245
|
-
const bare = host.startsWith("[") && host.endsWith("]") ? host.slice(1, -1) : host;
|
|
246
|
-
if (bare === "localhost" || bare === "0.0.0.0" || bare === "::")
|
|
247
|
-
return true;
|
|
248
|
-
if (bare.endsWith(".local") || bare.endsWith(".internal") || bare.endsWith(".localhost"))
|
|
249
|
-
return true;
|
|
250
|
-
if (/^127\./.test(bare))
|
|
251
|
-
return true;
|
|
252
|
-
if (/^10\./.test(bare))
|
|
253
|
-
return true;
|
|
254
|
-
if (/^192\.168\./.test(bare))
|
|
255
|
-
return true;
|
|
256
|
-
if (/^172\.(1[6-9]|2\d|3[01])\./.test(bare))
|
|
257
|
-
return true;
|
|
258
|
-
if (/^169\.254\./.test(bare))
|
|
259
|
-
return true;
|
|
260
|
-
const v6 = bare.toLowerCase();
|
|
261
|
-
if (v6 === "::1")
|
|
262
|
-
return true;
|
|
263
|
-
if (/^f[cd][0-9a-f]{2}:/.test(v6))
|
|
264
|
-
return true;
|
|
265
|
-
if (/^fe[89ab][0-9a-f]:/.test(v6))
|
|
266
|
-
return true;
|
|
267
|
-
const mapped = unmapIpv4(v6);
|
|
268
|
-
if (mapped)
|
|
269
|
-
return isBlockedHost(mapped);
|
|
270
|
-
return false;
|
|
271
|
-
}
|
|
272
|
-
function isSafeUrl(raw, options = {}) {
|
|
273
|
-
const protocols = options.protocols ?? ["http:", "https:"];
|
|
274
|
-
let url;
|
|
275
|
-
try {
|
|
276
|
-
url = new URL(raw);
|
|
277
|
-
} catch {
|
|
278
|
-
return false;
|
|
279
|
-
}
|
|
280
|
-
if (!protocols.includes(url.protocol))
|
|
281
|
-
return false;
|
|
282
|
-
return !isBlockedHost(url.hostname.toLowerCase());
|
|
283
|
-
}
|
|
284
|
-
var init_safeUrl = __esm({
|
|
285
|
-
"../shared-types/dist/safeUrl.js"() {
|
|
286
|
-
"use strict";
|
|
287
|
-
}
|
|
288
|
-
});
|
|
289
|
-
|
|
290
351
|
// ../ops-tools/dist/index.js
|
|
291
352
|
var require_dist = __commonJS({
|
|
292
353
|
"../ops-tools/dist/index.js"(exports2, module2) {
|
|
@@ -1270,7 +1331,7 @@ var require_dist = __commonJS({
|
|
|
1270
1331
|
];
|
|
1271
1332
|
var import_zod11 = require("zod");
|
|
1272
1333
|
var import_agentTools = (init_agentTools(), __toCommonJS(agentTools_exports));
|
|
1273
|
-
var
|
|
1334
|
+
var import_safeUrl2 = (init_safeUrl(), __toCommonJS(safeUrl_exports));
|
|
1274
1335
|
var DEFAULT_NAME = "call_webhook";
|
|
1275
1336
|
var METHODS = ["GET", "POST", "PUT", "PATCH"];
|
|
1276
1337
|
var FIELD_NAME = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
@@ -1308,7 +1369,7 @@ var require_dist = __commonJS({
|
|
|
1308
1369
|
const url = typeof s.url === "string" ? s.url.trim() : "";
|
|
1309
1370
|
if (!url) errors.push("url is required.");
|
|
1310
1371
|
else if (!/^https:\/\//i.test(url)) errors.push("url must be https \u2014 the request carries caller details.");
|
|
1311
|
-
else if (!(0,
|
|
1372
|
+
else if (!(0, import_safeUrl2.isSafeUrl)(url, { protocols: ["https:"] })) errors.push("url must be a valid public host; private and loopback addresses are refused at call time.");
|
|
1312
1373
|
if (!METHODS.includes(s.method)) errors.push(`method must be one of ${METHODS.join(", ")}.`);
|
|
1313
1374
|
if (!Number.isInteger(b.timeout_ms) || b.timeout_ms < 1e3 || b.timeout_ms > 1e4) errors.push("timeout_ms must be an integer from 1000 to 10000.");
|
|
1314
1375
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -1351,6 +1412,49 @@ var require_dist = __commonJS({
|
|
|
1351
1412
|
}
|
|
1352
1413
|
return found;
|
|
1353
1414
|
}
|
|
1415
|
+
var ALWAYS_ON_TOOL_IDS = ["datetime_now", "knowledge_search", "end_call", "get_caller_history", "forget_me"];
|
|
1416
|
+
var SWITCHABLE_CATALOG = import_agentTools.BUILTIN_TOOL_CATALOG.filter((t) => t.tool_id !== "call_webhook" && t.tool_id !== "mcp_server");
|
|
1417
|
+
var TOOL_GROUPS = {
|
|
1418
|
+
calendar: [
|
|
1419
|
+
"check_calendar_availability",
|
|
1420
|
+
"list_calendar_events",
|
|
1421
|
+
"create_calendar_event",
|
|
1422
|
+
"update_calendar_event",
|
|
1423
|
+
"delete_calendar_event"
|
|
1424
|
+
],
|
|
1425
|
+
tickets: ["lookup_ticket", "create_ticket"]
|
|
1426
|
+
};
|
|
1427
|
+
var SWITCHABLE_IDS = [...ALWAYS_ON_TOOL_IDS, ...SWITCHABLE_CATALOG.map((t) => t.tool_id)];
|
|
1428
|
+
function expandToolIds(requested) {
|
|
1429
|
+
const ids = /* @__PURE__ */ new Set();
|
|
1430
|
+
const unknown = [];
|
|
1431
|
+
for (const raw of requested) {
|
|
1432
|
+
const name = raw.trim();
|
|
1433
|
+
if (TOOL_GROUPS[name]) TOOL_GROUPS[name].forEach((id) => ids.add(id));
|
|
1434
|
+
else if (SWITCHABLE_IDS.includes(name)) ids.add(name);
|
|
1435
|
+
else unknown.push(name);
|
|
1436
|
+
}
|
|
1437
|
+
if (unknown.length) {
|
|
1438
|
+
throw new Error(`Unknown tool ${unknown.map((u) => `"${u}"`).join(", ")}. Use one of: ${[...Object.keys(TOOL_GROUPS), ...SWITCHABLE_IDS].join(", ")}. API tools use add/update/remove_agent_tool.`);
|
|
1439
|
+
}
|
|
1440
|
+
return [...ids];
|
|
1441
|
+
}
|
|
1442
|
+
function setToolsEnabled(tools, toolIds, enabled) {
|
|
1443
|
+
const next = tools.map((t) => toolIds.includes(t.tool_id) ? { ...t, enabled } : t);
|
|
1444
|
+
for (const toolId of toolIds) {
|
|
1445
|
+
if (next.some((t) => t.tool_id === toolId)) continue;
|
|
1446
|
+
const entry = SWITCHABLE_CATALOG.find((t) => t.tool_id === toolId);
|
|
1447
|
+
next.push({
|
|
1448
|
+
tool_id: toolId,
|
|
1449
|
+
enabled,
|
|
1450
|
+
credential_ref: null,
|
|
1451
|
+
timeout_ms: entry?.default_timeout_ms ?? 3e3,
|
|
1452
|
+
side_effect: entry?.side_effect ?? (toolId === "end_call" || toolId === "forget_me" ? "write" : "read"),
|
|
1453
|
+
provider_settings: {}
|
|
1454
|
+
});
|
|
1455
|
+
}
|
|
1456
|
+
return next;
|
|
1457
|
+
}
|
|
1354
1458
|
var addShape = { agent_id: import_zod11.z.string().describe("The agent UUID"), name: import_zod11.z.string().describe('LLM-facing tool name, e.g. "lookup_reservation". Unique per agent.'), ...settingsShape };
|
|
1355
1459
|
var updateShape = {
|
|
1356
1460
|
agent_id: import_zod11.z.string().describe("The agent UUID"),
|
|
@@ -1458,6 +1562,22 @@ var require_dist = __commonJS({
|
|
|
1458
1562
|
return { status: "removed", agent_id: agentId, name, remaining: tools.filter(isApiTool).map(bindingName), note: LIVE_NOTE };
|
|
1459
1563
|
}
|
|
1460
1564
|
}),
|
|
1565
|
+
defineTool({
|
|
1566
|
+
name: "set_agent_tools",
|
|
1567
|
+
description: `Switch built-in tools on or off for one agent: calendar (check/list/create/update/delete), lookup_customer, lookup_ticket/create_ticket, send_whatsapp_message, send_telegram_message, send_asset, handoff_to_human, schedule_callback, and the always-on ones (end_call, forget_me, knowledge_search, get_caller_history, datetime_now). Groups: "calendar" (all five calendar tools), "tickets". Connected-app tools are opt-in per agent: connecting the app for the workspace makes them available, and an agent gets one only when switched on here or in Studio; it also needs the app connected (Settings \u2192 Connectors) to work on calls. Other agents are not affected. ${LIVE_NOTE}`,
|
|
1568
|
+
scope: "agent",
|
|
1569
|
+
risk: "write",
|
|
1570
|
+
input: {
|
|
1571
|
+
agent_id: import_zod11.z.string().describe("The agent UUID"),
|
|
1572
|
+
tools: import_zod11.z.array(import_zod11.z.string()).min(1).describe('Tool ids or groups, e.g. ["calendar"] or ["send_whatsapp_message", "send_asset"].'),
|
|
1573
|
+
enabled: import_zod11.z.boolean().describe("true switches them on for this agent, false switches them off.")
|
|
1574
|
+
},
|
|
1575
|
+
run: async (client, { agent_id, tools: requested, enabled }) => {
|
|
1576
|
+
const toolIds = expandToolIds(requested);
|
|
1577
|
+
const { agentId } = await writeTools(client, agent_id, (tools) => setToolsEnabled(tools, toolIds, enabled));
|
|
1578
|
+
return { status: enabled ? "enabled" : "disabled", agent_id: agentId, tools: toolIds, note: LIVE_NOTE };
|
|
1579
|
+
}
|
|
1580
|
+
}),
|
|
1461
1581
|
defineTool({
|
|
1462
1582
|
name: "list_tool_secrets",
|
|
1463
1583
|
description: "List the workspace's API-tool secret names and the host each is pinned to. Values are never returned.",
|
|
@@ -1517,6 +1637,28 @@ var require_dist = __commonJS({
|
|
|
1517
1637
|
run: (client, { agent_id }) => client.agents.regenerateShareLink(agent_id)
|
|
1518
1638
|
})
|
|
1519
1639
|
];
|
|
1640
|
+
var import_zod13 = require("zod");
|
|
1641
|
+
var workspaceTools = [
|
|
1642
|
+
defineTool({
|
|
1643
|
+
name: "list_workspaces",
|
|
1644
|
+
description: "List the workspaces this credential can act in, marking the current one. Act in another by setting RYMI_WORKSPACE (local MCP) or the Rymi-Workspace header.",
|
|
1645
|
+
scope: "account",
|
|
1646
|
+
risk: "read",
|
|
1647
|
+
input: {},
|
|
1648
|
+
run: (client) => client.workspaces.list()
|
|
1649
|
+
}),
|
|
1650
|
+
defineTool({
|
|
1651
|
+
name: "create_workspace",
|
|
1652
|
+
description: "Create a standalone workspace you own, with its own agents, numbers, keys and balance. It gets no free monthly credit.",
|
|
1653
|
+
scope: "account",
|
|
1654
|
+
risk: "write",
|
|
1655
|
+
input: {
|
|
1656
|
+
name: import_zod13.z.string().min(1).max(80).describe("Workspace name"),
|
|
1657
|
+
operating_country: import_zod13.z.string().length(2).optional().describe('ISO-3166 alpha-2 country, e.g. "IN"')
|
|
1658
|
+
},
|
|
1659
|
+
run: (client, params) => client.workspaces.create(params)
|
|
1660
|
+
})
|
|
1661
|
+
];
|
|
1520
1662
|
var import_agentTools2 = (init_agentTools(), __toCommonJS(agentTools_exports));
|
|
1521
1663
|
var REDACTED = "[redacted]";
|
|
1522
1664
|
function redactToolSecrets(value) {
|
|
@@ -1550,7 +1692,8 @@ var require_dist = __commonJS({
|
|
|
1550
1692
|
...webhookTools,
|
|
1551
1693
|
...billingTools,
|
|
1552
1694
|
...campaignTools,
|
|
1553
|
-
...shareLinkTools
|
|
1695
|
+
...shareLinkTools,
|
|
1696
|
+
...workspaceTools
|
|
1554
1697
|
].map((t) => ({ ...t, run: async (client, params) => redactToolSecrets(await t.run(client, params)) }));
|
|
1555
1698
|
var names = /* @__PURE__ */ new Set();
|
|
1556
1699
|
for (const tool of opsToolCatalog2) {
|
|
@@ -1586,7 +1729,7 @@ function withToolErrors(handler) {
|
|
|
1586
1729
|
// package.json
|
|
1587
1730
|
var package_default = {
|
|
1588
1731
|
name: "@rymi/mcp",
|
|
1589
|
-
version: "2.
|
|
1732
|
+
version: "2.4.0",
|
|
1590
1733
|
description: "Rymi MCP server \u2014 manage AI voice agents via Model Context Protocol",
|
|
1591
1734
|
license: "MIT",
|
|
1592
1735
|
author: "Rymi AI <engineering@rymi.live>",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rymi/mcp",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "Rymi MCP server — manage AI voice agents via Model Context Protocol",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Rymi AI <engineering@rymi.live>",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@modelcontextprotocol/sdk": "^1.11.1",
|
|
47
|
-
"@rymi/node": "^2.
|
|
47
|
+
"@rymi/node": "^2.3.0",
|
|
48
48
|
"zod": "^3.23.0"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|