Skip to content

Commit 1840f28

Browse files
authored
Merge pull request #14 from universal-tool-calling-protocol/dev
v1.1
2 parents a4af55f + 069a277 commit 1840f28

22 files changed

+405
-22
lines changed

packages/cli/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@utcp/cli",
3-
"version": "1.0.12",
3+
"version": "1.1.0",
44
"description": "CLI utilities for UTCP",
55
"main": "dist/index.cjs",
66
"module": "dist/index.js",
@@ -43,7 +43,7 @@
4343
}
4444
},
4545
"dependencies": {
46-
"@utcp/sdk": "^1.0.15"
46+
"@utcp/sdk": "^1.1.0"
4747
},
4848
"devDependencies": {
4949
"bun-types": "latest",

packages/cli/src/cli_call_template.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ export interface CliCallTemplate extends CallTemplate {
162162
env_vars?: Record<string, string> | null;
163163
working_dir?: string | null;
164164
auth?: undefined;
165+
allowed_communication_protocols?: string[];
165166
}
166167

167168
/**
@@ -174,6 +175,7 @@ export const CliCallTemplateSchema: z.ZodType<CliCallTemplate> = z.object({
174175
env_vars: z.record(z.string(), z.string()).nullable().optional().describe('Environment variables to set when executing the commands'),
175176
working_dir: z.string().nullable().optional().describe('Working directory for command execution'),
176177
auth: z.undefined().optional(),
178+
allowed_communication_protocols: z.array(z.string()).optional().describe('Optional list of allowed communication protocol types for tools within this manual.'),
177179
}).strict() as z.ZodType<CliCallTemplate>;
178180

179181
/**
@@ -200,6 +202,7 @@ export class CliCallTemplateSerializer extends Serializer<CliCallTemplate> {
200202
env_vars: obj.env_vars,
201203
working_dir: obj.working_dir,
202204
auth: obj.auth,
205+
allowed_communication_protocols: obj.allowed_communication_protocols,
203206
};
204207
}
205208

packages/cli/src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,8 @@ export function register(override: boolean = false): void {
1313
CommunicationProtocol.communicationProtocols['cli'] = new CliCommunicationProtocol();
1414
}
1515

16+
// Automatically register CLI plugins on import
17+
register();
18+
1619
export * from './cli_call_template';
1720
export * from './cli_communication_protocol';

packages/code-mode/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@utcp/code-mode",
3-
"version": "1.0.5",
3+
"version": "1.1.0",
44
"description": "Code execution mode for UTCP - enables executing TypeScript code chains with tool access",
55
"main": "dist/index.cjs",
66
"module": "dist/index.js",
@@ -40,7 +40,7 @@
4040
}
4141
},
4242
"dependencies": {
43-
"@utcp/sdk": "^1.0.17"
43+
"@utcp/sdk": "^1.1.0"
4444
},
4545
"devDependencies": {
4646
"@types/node": "^20.0.0",

packages/core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@utcp/sdk",
3-
"version": "1.0.17",
3+
"version": "1.1.0",
44
"description": "Universal Tool Calling Protocol SDK",
55
"main": "dist/index.cjs",
66
"module": "dist/index.js",

packages/core/src/client/utcp_client.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,26 @@ export class UtcpClient implements IUtcpClient {
138138
const result = await protocol.registerManual(this, processedCallTemplate);
139139

140140
if (result.success) {
141+
// Determine allowed protocols: use explicit list if provided, otherwise default to manual's own protocol
142+
const allowedProtocols = (processedCallTemplate.allowed_communication_protocols?.length)
143+
? processedCallTemplate.allowed_communication_protocols
144+
: [processedCallTemplate.call_template_type];
145+
146+
// Filter tools based on allowed protocols and prefix names
147+
const filteredTools = [];
141148
for (const tool of result.manual.tools) {
149+
const toolProtocol = tool.tool_call_template.call_template_type;
150+
if (!allowedProtocols.includes(toolProtocol)) {
151+
console.warn(`Tool '${tool.name}' uses communication protocol '${toolProtocol}' which is not in allowed protocols [${allowedProtocols.map(p => `'${p}'`).join(', ')}] for manual '${manualCallTemplate.name}'. Tool will not be registered.`);
152+
continue;
153+
}
142154
if (!tool.name.startsWith(`${processedCallTemplate.name}.`)) {
143155
tool.name = `${processedCallTemplate.name}.${tool.name}`;
144156
}
157+
filteredTools.push(tool);
145158
}
159+
result.manual.tools = filteredTools;
160+
146161
await this.config.tool_repository.saveManual(processedCallTemplate, result.manual);
147162
console.log(`Successfully registered manual '${manualCallTemplate.name}' with ${result.manual.tools.length} tools.`);
148163
} else {
@@ -224,6 +239,16 @@ export class UtcpClient implements IUtcpClient {
224239
throw new Error(`Could not find manual call template for manual '${manualName}'.`);
225240
}
226241

242+
// Validate protocol is allowed
243+
const toolProtocol = tool.tool_call_template.call_template_type;
244+
const allowedProtocols = (manualCallTemplate.allowed_communication_protocols?.length)
245+
? manualCallTemplate.allowed_communication_protocols
246+
: [manualCallTemplate.call_template_type];
247+
248+
if (!allowedProtocols.includes(toolProtocol)) {
249+
throw new Error(`Tool '${toolName}' uses communication protocol '${toolProtocol}' which is not allowed by manual '${manualName}'. Allowed protocols: [${allowedProtocols.map(p => `'${p}'`).join(', ')}]`);
250+
}
251+
227252
const processedToolCallTemplate = await this.substituteCallTemplateVariables(tool.tool_call_template, manualName);
228253

229254
const protocol = this._registeredCommProtocols.get(processedToolCallTemplate.call_template_type);
@@ -263,6 +288,16 @@ export class UtcpClient implements IUtcpClient {
263288
throw new Error(`Could not find manual call template for manual '${manualName}'.`);
264289
}
265290

291+
// Validate protocol is allowed
292+
const toolProtocol = tool.tool_call_template.call_template_type;
293+
const allowedProtocols = (manualCallTemplate.allowed_communication_protocols?.length)
294+
? manualCallTemplate.allowed_communication_protocols
295+
: [manualCallTemplate.call_template_type];
296+
297+
if (!allowedProtocols.includes(toolProtocol)) {
298+
throw new Error(`Tool '${toolName}' uses communication protocol '${toolProtocol}' which is not allowed by manual '${manualName}'. Allowed protocols: [${allowedProtocols.map(p => `'${p}'`).join(', ')}]`);
299+
}
300+
266301
const processedToolCallTemplate = await this.substituteCallTemplateVariables(tool.tool_call_template, manualName);
267302

268303
const protocol = this._registeredCommProtocols.get(processedToolCallTemplate.call_template_type);

packages/core/src/data/call_template.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,18 @@ export interface CallTemplate {
2323
*/
2424
auth?: Auth;
2525

26+
/**
27+
* Optional list of allowed communication protocol types for tools within this manual.
28+
*
29+
* Behavior:
30+
* - If undefined, null, or empty array → defaults to only allowing the manual's own call_template_type
31+
* - If set to a non-empty array → only those protocol types are allowed
32+
*
33+
* This provides secure-by-default behavior where a manual can only register/call tools
34+
* that use its own protocol unless explicitly configured otherwise.
35+
*/
36+
allowed_communication_protocols?: string[];
37+
2638
[key: string]: any;
2739
}
2840

packages/direct-call/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@utcp/direct-call",
3-
"version": "1.0.12",
3+
"version": "1.1.0",
44
"description": "Direct callable functions plugin for UTCP",
55
"main": "dist/index.cjs",
66
"module": "dist/index.js",
@@ -44,7 +44,7 @@
4444
}
4545
},
4646
"dependencies": {
47-
"@utcp/sdk": "^1.0.15"
47+
"@utcp/sdk": "^1.1.0"
4848
},
4949
"devDependencies": {
5050
"bun-types": "latest",

packages/direct-call/src/direct_call_template.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export interface DirectCallTemplate extends CallTemplate {
1717
call_template_type: 'direct-call';
1818
callable_name: string;
1919
auth?: undefined;
20+
allowed_communication_protocols?: string[];
2021
}
2122

2223
/**
@@ -27,6 +28,7 @@ export const DirectCallTemplateSchema: z.ZodType<DirectCallTemplate> = z.object(
2728
call_template_type: z.literal('direct-call'),
2829
callable_name: z.string().describe('The name of the callable function to invoke.'),
2930
auth: z.undefined().optional(),
31+
allowed_communication_protocols: z.array(z.string()).optional().describe('Optional list of allowed communication protocol types for tools within this manual.'),
3032
}).strict() as z.ZodType<DirectCallTemplate>;
3133

3234
/**
@@ -42,6 +44,7 @@ export class DirectCallTemplateSerializer extends Serializer<DirectCallTemplate>
4244
call_template_type: obj.call_template_type,
4345
callable_name: obj.callable_name,
4446
auth: obj.auth,
47+
allowed_communication_protocols: obj.allowed_communication_protocols,
4548
};
4649
}
4750

packages/dotenv-loader/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@utcp/dotenv-loader",
3-
"version": "1.0.1",
3+
"version": "1.1.0",
44
"description": "DotEnv Variable Loader plugin for UTCP",
55
"main": "dist/index.cjs",
66
"module": "dist/index.js",
@@ -44,7 +44,7 @@
4444
"zod": "^3.23.8"
4545
},
4646
"peerDependencies": {
47-
"@utcp/sdk": "^1.0.15"
47+
"@utcp/sdk": "^1.1.0"
4848
},
4949
"devDependencies": {
5050
"bun-types": "latest",

0 commit comments

Comments
 (0)