Skip to content

Commit 264c310

Browse files
committed
Fix a lot of issues
1 parent c5328aa commit 264c310

38 files changed

+1014
-433
lines changed

README.md

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ UTCP offers a unified framework for integrating disparate tools and services, ma
1414
* **Automatic Plugin Registration**: The official plugins are automatically discovered and registered when you import the core client—no manual setup required. For other plugins, you will need to register them manually.
1515
* **Scalability**: Designed to handle a large number of tools and providers without compromising performance.
1616
* **Extensibility**: A pluggable architecture allows developers to easily add new communication protocols, tool storage mechanisms, and search strategies without modifying the core library.
17-
* **Interoperability**: With a growing ecosystem of protocol plugins—including HTTP, MCP, Text, and CLI—UTCP can integrate with almost any existing service or infrastructure.
17+
* **Interoperability**: With a growing ecosystem of protocol plugins—including HTTP, MCP, Text, File, and CLI—UTCP can integrate with almost any existing service or infrastructure.
1818
* **Type Safety**: Built on well-defined TypeScript interfaces and runtime validation powered by Zod, making it robust and developer-friendly.
1919
* **Secure Variable Management**: Namespace-isolated variables prevent leakage between manuals, with support for environment variables and .env files.
2020

@@ -28,10 +28,13 @@ Install UTCP packages from npm:
2828

2929
```bash
3030
# Install core SDK and desired protocol plugins
31-
npm install @utcp/sdk @utcp/http @utcp/mcp @utcp/text
31+
npm install @utcp/sdk @utcp/http @utcp/mcp @utcp/text @utcp/file
32+
33+
# Optional: Add dotenv variable loader for Node.js
34+
npm install @utcp/dotenv-loader
3235

3336
# Or using bun
34-
bun add @utcp/sdk @utcp/http @utcp/mcp @utcp/text
37+
bun add @utcp/sdk @utcp/http @utcp/mcp @utcp/text @utcp/file
3538
```
3639

3740
### For Development
@@ -98,13 +101,13 @@ main().catch(console.error);
98101
import { UtcpClient } from '@utcp/sdk';
99102
import { HttpCallTemplateSerializer } from '@utcp/http';
100103
import { McpCallTemplateSerializer } from '@utcp/mcp';
101-
import { TextCallTemplateSerializer } from '@utcp/text';
104+
import { FileCallTemplateSerializer } from '@utcp/file';
102105

103106
async function main() {
104107
// Create serializers for each protocol
105108
const httpSerializer = new HttpCallTemplateSerializer();
106109
const mcpSerializer = new McpCallTemplateSerializer();
107-
const textSerializer = new TextCallTemplateSerializer();
110+
const fileSerializer = new FileCallTemplateSerializer();
108111

109112
// Validate and create call templates
110113
const httpTemplate = httpSerializer.validateDict({
@@ -132,9 +135,9 @@ async function main() {
132135
}
133136
});
134137

135-
const textTemplate = textSerializer.validateDict({
138+
const fileTemplate = fileSerializer.validateDict({
136139
name: 'local_tools',
137-
call_template_type: 'text',
140+
call_template_type: 'file',
138141
file_path: './config/tools.json'
139142
});
140143

@@ -152,7 +155,7 @@ async function main() {
152155
manual_call_templates: [
153156
httpTemplate, // HTTP API
154157
mcpTemplate, // MCP Server
155-
textTemplate // Local file-based tools
158+
fileTemplate // Local file-based tools
156159
]
157160
});
158161

@@ -383,15 +386,34 @@ const mcpTemplate = serializer.validateDict({
383386

384387
### Text Protocol
385388

386-
Load tools from local JSON/YAML files or OpenAPI specs:
389+
Handle direct text/string content (browser-compatible):
387390

388391
```typescript
389392
import { TextCallTemplateSerializer } from '@utcp/text';
390393

391394
const serializer = new TextCallTemplateSerializer();
392395
const textTemplate = serializer.validateDict({
393-
name: 'local_tools',
396+
name: 'inline_tools',
394397
call_template_type: 'text',
398+
content: JSON.stringify({
399+
tools: [
400+
// UTCP manual or OpenAPI spec as string
401+
]
402+
})
403+
});
404+
```
405+
406+
### File Protocol
407+
408+
Load tools from local JSON/YAML files or OpenAPI specs (Node.js only):
409+
410+
```typescript
411+
import { FileCallTemplateSerializer } from '@utcp/file';
412+
413+
const serializer = new FileCallTemplateSerializer();
414+
const fileTemplate = serializer.validateDict({
415+
name: 'local_tools',
416+
call_template_type: 'file',
395417
file_path: './config/tools.json'
396418
// Supports: .json, .yaml, .yml, OpenAPI specs
397419
});
@@ -425,7 +447,10 @@ typescript-utcp/
425447
│ ├── core/ # Core SDK with UtcpClient and interfaces
426448
│ ├── http/ # HTTP protocol plugin
427449
│ ├── mcp/ # MCP protocol plugin
428-
│ ├── text/ # Text/file protocol plugin
450+
│ ├── text/ # Text/string content protocol plugin (browser-compatible)
451+
│ ├── file/ # File system protocol plugin (Node.js only)
452+
│ ├── dotenv-loader/ # DotEnv variable loader plugin (Node.js only)
453+
│ ├── direct-call/ # Direct call protocol plugin
429454
│ └── cli/ # CLI protocol plugin
430455
├── tests/ # End-to-end integration tests
431456
└── README.md
@@ -435,7 +460,10 @@ Each package is independently published to npm:
435460
- `@utcp/sdk` - Core SDK library (required)
436461
- `@utcp/http` - HTTP protocol support
437462
- `@utcp/mcp` - MCP protocol support
438-
- `@utcp/text` - File-based tools
463+
- `@utcp/text` - Direct text/string content (browser-compatible)
464+
- `@utcp/file` - File system operations (Node.js only)
465+
- `@utcp/dotenv-loader` - DotEnv variable loader (Node.js only)
466+
- `@utcp/direct-call` - Direct function call protocol
439467
- `@utcp/cli` - Command-line tools
440468

441469
## Development & Testing

bun.lock

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,38 @@
5151
"typescript": "^5.0.0",
5252
},
5353
},
54+
"packages/dotenv-loader": {
55+
"name": "@utcp/dotenv-loader",
56+
"version": "1.0.0",
57+
"dependencies": {
58+
"dotenv": "^17.2.1",
59+
"zod": "^3.23.8",
60+
},
61+
"devDependencies": {
62+
"bun-types": "latest",
63+
"typescript": "^5.0.0",
64+
},
65+
"peerDependencies": {
66+
"@utcp/sdk": "^1.0.8",
67+
},
68+
},
69+
"packages/file": {
70+
"name": "@utcp/file",
71+
"version": "1.0.0",
72+
"dependencies": {
73+
"@utcp/http": "^1.0.7",
74+
"@utcp/sdk": "^1.0.8",
75+
"js-yaml": "^4.1.0",
76+
},
77+
"devDependencies": {
78+
"@types/bun": "latest",
79+
"bun-types": "latest",
80+
"typescript": "^5.0.0",
81+
},
82+
},
5483
"packages/http": {
5584
"name": "@utcp/http",
56-
"version": "1.0.6",
85+
"version": "1.0.8",
5786
"dependencies": {
5887
"@utcp/sdk": "^1.0.6",
5988
"axios": "^1.11.0",
@@ -82,14 +111,13 @@
82111
},
83112
"packages/text": {
84113
"name": "@utcp/text",
85-
"version": "1.0.8",
114+
"version": "1.0.11",
86115
"dependencies": {
87-
"@utcp/http": "^1.0.6",
116+
"@utcp/http": "^1.0.8",
88117
"@utcp/sdk": "^1.0.8",
89118
"js-yaml": "^4.1.0",
90119
},
91120
"devDependencies": {
92-
"@types/bun": "latest",
93121
"bun-types": "latest",
94122
"typescript": "^5.0.0",
95123
},
@@ -231,6 +259,10 @@
231259

232260
"@utcp/direct-call": ["@utcp/direct-call@workspace:packages/direct-call"],
233261

262+
"@utcp/dotenv-loader": ["@utcp/dotenv-loader@workspace:packages/dotenv-loader"],
263+
264+
"@utcp/file": ["@utcp/file@workspace:packages/file"],
265+
234266
"@utcp/http": ["@utcp/http@workspace:packages/http"],
235267

236268
"@utcp/mcp": ["@utcp/mcp@workspace:packages/mcp"],
@@ -593,6 +625,10 @@
593625

594626
"@utcp/direct-call/bun-types": ["bun-types@1.3.0", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-u8X0thhx+yJ0KmkxuEo9HAtdfgCBaM/aI9K90VQcQioAmkVp3SG3FkwWGibUFz3WdXAdcsqOcbU40lK7tbHdkQ=="],
595627

628+
"@utcp/dotenv-loader/bun-types": ["bun-types@1.3.1", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-NMrcy7smratanWJ2mMXdpatalovtxVggkj11bScuWuiOoXTiKIu2eVS1/7qbyI/4yHedtsn175n4Sm4JcdHLXw=="],
629+
630+
"@utcp/file/bun-types": ["bun-types@1.3.1", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-NMrcy7smratanWJ2mMXdpatalovtxVggkj11bScuWuiOoXTiKIu2eVS1/7qbyI/4yHedtsn175n4Sm4JcdHLXw=="],
631+
596632
"@utcp/http/bun-types": ["bun-types@1.3.1", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-NMrcy7smratanWJ2mMXdpatalovtxVggkj11bScuWuiOoXTiKIu2eVS1/7qbyI/4yHedtsn175n4Sm4JcdHLXw=="],
597633

598634
"@utcp/mcp/bun-types": ["bun-types@1.3.0", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-u8X0thhx+yJ0KmkxuEo9HAtdfgCBaM/aI9K90VQcQioAmkVp3SG3FkwWGibUFz3WdXAdcsqOcbU40lK7tbHdkQ=="],

package.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@
1818
},
1919
"scripts": {
2020
"clean": "rm -rf packages/*/dist || rmdir /s /q packages\\*\\dist || true",
21-
"build": "bun run build:core && bun run build:http && bun run build:mcp && bun run build:text && bun run build:cli && bun run build:direct-call",
21+
"build": "bun run build:core && bun run build:http && bun run build:mcp && bun run build:text && bun run build:file && bun run build:cli && bun run build:direct-call && bun run build:dotenv-loader",
2222
"build:core": "cd packages/core && bun run build",
2323
"build:http": "cd packages/http && bun run build",
2424
"build:mcp": "cd packages/mcp && bun run build",
2525
"build:text": "cd packages/text && bun run build",
26+
"build:file": "cd packages/file && bun run build",
2627
"build:cli": "cd packages/cli && bun run build",
2728
"build:direct-call": "cd packages/direct-call && bun run build",
29+
"build:dotenv-loader": "cd packages/dotenv-loader && bun run build",
2830
"rebuild": "bun run clean && bun run build",
2931
"test": "bun test --config tsconfig.test.json",
3032
"version:patch": "node scripts/update-versions.js patch",
@@ -33,11 +35,13 @@
3335
"version:set": "node scripts/update-versions.js set",
3436
"publish:core": "cd packages/core && npm publish",
3537
"publish:text": "cd packages/text && npm publish",
38+
"publish:file": "cd packages/file && npm publish",
3639
"publish:http": "cd packages/http && npm publish",
3740
"publish:mcp": "cd packages/mcp && npm publish",
3841
"publish:cli": "cd packages/cli && npm publish",
3942
"publish:direct-call": "cd packages/direct-call && npm publish",
40-
"publish:all": "bun run build && bun run publish:core && bun run publish:text && bun run publish:http && bun run publish:mcp && bun run publish:cli && bun run publish:direct-call"
43+
"publish:dotenv-loader": "cd packages/dotenv-loader && npm publish",
44+
"publish:all": "bun run build && bun run publish:core && bun run publish:text && bun run publish:file && bun run publish:http && bun run publish:mcp && bun run publish:cli && bun run publish:direct-call && bun run publish:dotenv-loader"
4145
},
4246
"workspaces": [
4347
"packages/*"

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.6",
3+
"version": "1.0.11",
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.6"
46+
"@utcp/sdk": "^1.0.11"
4747
},
4848
"devDependencies": {
4949
"bun-types": "latest",

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.8",
3+
"version": "1.0.11",
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: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
// packages/core/src/client/utcp_client.ts
2-
import { promises as fs } from 'fs';
3-
import * as path from 'path';
4-
import { parse as parseDotEnv } from 'dotenv';
52
import { CallTemplate, CallTemplateSchema } from '../data/call_template';
63
import { Tool } from '../data/tool';
74
import { UtcpManualSchema } from '../data/utcp_manual';
@@ -14,6 +11,7 @@ import { ToolPostProcessor } from '../interfaces/tool_post_processor';
1411
import {
1512
UtcpClientConfig,
1613
UtcpClientConfigSchema,
14+
UtcpClientConfigSerializer,
1715
} from './utcp_client_config';
1816
import { DefaultVariableSubstitutor } from '../implementations/default_variable_substitutor';
1917
import { ensureCorePluginsInitialized } from '../plugins/plugin_loader';
@@ -60,16 +58,14 @@ export class UtcpClient implements IUtcpClient {
6058
*/
6159
public static async create(
6260
root_dir: string = process.cwd(),
63-
config: Partial<UtcpClientConfig> | string = {}
61+
config: UtcpClientConfig | null = null
6462
): Promise<UtcpClient> {
6563
// Ensure core plugins are initialized before parsing config
6664
ensureCorePluginsInitialized();
6765

6866
let loadedConfig: Partial<UtcpClientConfig>;
69-
if (typeof config === 'string') {
70-
const configPath = path.resolve(root_dir, config);
71-
const configFileContent = await fs.readFile(configPath, 'utf-8');
72-
loadedConfig = JSON.parse(configFileContent);
67+
if (config === null) {
68+
loadedConfig = new UtcpClientConfigSerializer().validateDict({});
7369
} else {
7470
loadedConfig = config;
7571
}
@@ -347,27 +343,6 @@ export class UtcpClient implements IUtcpClient {
347343
return result.data as T;
348344
}
349345

350-
/**
351-
* Loads variables from sources defined in the client configuration.
352-
*/
353-
private async loadVariables(): Promise<void> {
354-
for (const varLoader of this.config.load_variables_from || []) {
355-
const parsedLoader = varLoader;
356-
if (parsedLoader.variable_loader_type === 'dotenv') {
357-
try {
358-
const envFilePath = path.resolve(this.root_dir || process.cwd(), parsedLoader.env_file_path);
359-
const envContent = await fs.readFile(envFilePath, 'utf-8');
360-
const envVars = parseDotEnv(envContent);
361-
// Merge loaded variables, giving precedence to existing config.variables
362-
this.config.variables = { ...envVars, ...this.config.variables };
363-
console.log(`Loaded variables from .env file: ${envFilePath}`);
364-
} catch (e: any) {
365-
console.warn(`Could not load .env file from '${parsedLoader.env_file_path}': ${e.message}`);
366-
}
367-
}
368-
}
369-
}
370-
371346
/**
372347
* Closes the UTCP client and releases any resources held by its communication protocols.
373348
*/

packages/core/src/plugins/plugin_loader.ts

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,6 @@ import { BasicAuthSerializer } from '../data/auth_implementations/basic_auth';
55
import { OAuth2AuthSerializer } from '../data/auth_implementations/oauth2_auth';
66
import { setPluginInitializer } from '../interfaces/serializer';
77

8-
// Core Variable Loaders
9-
import { VariableLoaderSerializer } from '../data/variable_loader';
10-
import { DotEnvVariableLoaderSerializer } from '../data/variable_loader_implementations/dotenv_variable_loader';
11-
128
// Core Tool Repository
139
import { InMemConcurrentToolRepositorySerializer } from '../implementations/in_mem_concurrent_tool_repository';
1410
import { ConcurrentToolRepositoryConfigSerializer } from '../interfaces/concurrent_tool_repository';
@@ -34,9 +30,6 @@ function _registerCorePlugins(): void {
3430
AuthSerializer.registerAuth('basic', new BasicAuthSerializer());
3531
AuthSerializer.registerAuth('oauth2', new OAuth2AuthSerializer());
3632

37-
// Register Core Variable Loader Serializers
38-
VariableLoaderSerializer.registerVariableLoader('dotenv', new DotEnvVariableLoaderSerializer());
39-
4033
// Register Tool Repository Serializers
4134
ConcurrentToolRepositoryConfigSerializer.registerRepository('in_memory', new InMemConcurrentToolRepositorySerializer());
4235

@@ -49,7 +42,7 @@ function _registerCorePlugins(): void {
4942
}
5043

5144
/**
52-
* Attempts to auto-register optional UTCP plugins (HTTP, MCP, Text, Direct Call, CLI, etc.)
45+
* Attempts to auto-register optional UTCP plugins (HTTP, MCP, Text, File, Direct Call, CLI, DotEnv Loader, etc.)
5346
* if they are available in the project. This is a best-effort approach that
5447
* silently ignores plugins that are not installed.
5548
*/
@@ -84,6 +77,16 @@ function _tryRegisterOptionalPlugins(): void {
8477
// Text plugin not available, skip
8578
}
8679

80+
// Try to register File plugin
81+
try {
82+
const filePlugin = require('@utcp/file');
83+
if (filePlugin && typeof filePlugin.register === 'function') {
84+
filePlugin.register();
85+
}
86+
} catch (e) {
87+
// File plugin not available, skip
88+
}
89+
8790
// Try to register Direct Call plugin
8891
try {
8992
const directCallPlugin = require('@utcp/direct-call');
@@ -103,6 +106,26 @@ function _tryRegisterOptionalPlugins(): void {
103106
} catch (e) {
104107
// CLI plugin not available, skip
105108
}
109+
110+
// Try to register DotEnv Loader plugin
111+
try {
112+
const dotenvLoaderPlugin = require('@utcp/dotenv-loader');
113+
if (dotenvLoaderPlugin && typeof dotenvLoaderPlugin.register === 'function') {
114+
dotenvLoaderPlugin.register();
115+
}
116+
} catch (e) {
117+
// DotEnv Loader plugin not available, skip
118+
}
119+
120+
// Try to register String plugin
121+
try {
122+
const stringPlugin = require('@utcp/string');
123+
if (stringPlugin && typeof stringPlugin.register === 'function') {
124+
stringPlugin.register();
125+
}
126+
} catch (e) {
127+
// String plugin not available, skip
128+
}
106129
}
107130

108131
/**

0 commit comments

Comments
 (0)