@utcp/http 1.0.0 → 1.0.2

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.
Files changed (2) hide show
  1. package/README.md +617 -71
  2. package/package.json +2 -3
package/README.md CHANGED
@@ -1,96 +1,642 @@
1
- # @utcp/http: HTTP Communication Protocol Plugin for UTCP
1
+ # @utcp/http
2
2
 
3
- The `@utcp/http` package provides the HTTP communication protocol implementation for the Universal Tool Calling Protocol (UTCP) client. It enables the `UtcpClient` to interact with RESTful HTTP/HTTPS APIs, supporting various authentication methods, URL path parameters, and automatic tool discovery from UTCP Manuals or OpenAPI specifications.
3
+ HTTP-Based Communication Protocols for UTCP
4
+
5
+ ## Overview
6
+
7
+ The `@utcp/http` package provides comprehensive HTTP-based protocol support for the Universal Tool Calling Protocol (UTCP). It includes **three distinct protocols**:
8
+
9
+ 1. **HTTP** - Standard RESTful HTTP/HTTPS requests
10
+ 2. **Streamable HTTP** - HTTP with chunked transfer encoding for streaming large responses
11
+ 3. **SSE** - Server-Sent Events for real-time event streaming
12
+
13
+ All protocols support multiple authentication methods, URL path parameters, custom headers, and automatic OpenAPI specification conversion.
4
14
 
5
15
  ## Features
6
16
 
7
- * **HTTP `CallTemplate`**: Defines the specific configuration for HTTP-based tools (`HttpCallTemplate`), including HTTP method, URL, content type, authentication, and headers.
8
- * **`HttpCommunicationProtocol`**: Implements the `CommunicationProtocol` interface for HTTP interactions:
9
- * **Tool Discovery**: Automatically registers tools from remote UTCP Manuals or OpenAPI (v2/v3) specifications (JSON/YAML).
10
- * **Tool Execution**: Handles `GET`, `POST`, `PUT`, `DELETE`, `PATCH` requests with:
11
- * URL path parameter substitution (`{param_name}`).
12
- * Query parameter handling.
13
- * Request body mapping (`body_field`).
14
- * Custom header fields.
15
- * **Authentication Support**: Integrates `ApiKeyAuth` (header, query, cookie), `BasicAuth`, and `OAuth2Auth` (client credentials flow with token caching and refresh).
16
- * **Security**: Enforces HTTPS or localhost connections for discovery and tool calls to prevent Man-in-the-Middle (MITM) attacks.
17
- * **`OpenApiConverter`**: A utility for parsing OpenAPI specifications and transforming them into UTCP `Tool` definitions that leverage `HttpCallTemplate`.
17
+ ### 1. HTTP CallTemplate
18
+
19
+ Standard HTTP requests for RESTful APIs:
20
+
21
+ ```typescript
22
+ interface HttpCallTemplate {
23
+ name: string;
24
+ call_template_type: 'http';
25
+ http_method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';
26
+ url: string;
27
+ headers?: Record<string, string>;
28
+ body_field?: string;
29
+ content_type?: string;
30
+ timeout?: number;
31
+ auth?: ApiKeyAuth | BasicAuth | OAuth2Auth;
32
+ }
33
+ ```
34
+
35
+ ### 2. Streamable HTTP CallTemplate
36
+
37
+ HTTP streaming with chunked transfer encoding for large responses:
38
+
39
+ ```typescript
40
+ interface StreamableHttpCallTemplate {
41
+ name: string;
42
+ call_template_type: 'streamable_http';
43
+ url: string;
44
+ http_method: 'GET' | 'POST';
45
+ content_type?: string;
46
+ chunk_size?: number; // Default: 4096 bytes
47
+ timeout?: number; // Default: 60000ms
48
+ headers?: Record<string, string>;
49
+ body_field?: string;
50
+ header_fields?: string[];
51
+ auth?: ApiKeyAuth | BasicAuth | OAuth2Auth;
52
+ }
53
+ ```
54
+
55
+ ### 3. SSE CallTemplate
56
+
57
+ Server-Sent Events for real-time streaming:
58
+
59
+ ```typescript
60
+ interface SseCallTemplate {
61
+ name: string;
62
+ call_template_type: 'sse';
63
+ url: string;
64
+ event_type?: string; // Filter specific event types
65
+ reconnect?: boolean; // Auto-reconnect on disconnect
66
+ retry_timeout?: number; // Reconnection timeout (ms)
67
+ headers?: Record<string, string>;
68
+ body_field?: string;
69
+ header_fields?: string[];
70
+ auth?: ApiKeyAuth | BasicAuth | OAuth2Auth;
71
+ }
72
+ ```
73
+
74
+ ### HTTP Communication Protocol
75
+
76
+ * **Tool Discovery**: Automatically registers tools from:
77
+ * Remote UTCP Manuals
78
+ * OpenAPI 2.0 (Swagger) specifications
79
+ * OpenAPI 3.x specifications
80
+ * Both JSON and YAML formats
81
+
82
+ * **Tool Execution**:
83
+ * All HTTP methods: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS
84
+ * URL path parameter substitution: `${param_name}` or `{param_name}`
85
+ * Query parameter handling
86
+ * Request body mapping via `body_field`
87
+ * Custom headers with variable substitution
88
+
89
+ * **Authentication Support**:
90
+ * **API Key**: Header, query parameter, or cookie-based
91
+ * **Basic Auth**: Username/password authentication
92
+ * **OAuth2**: Client credentials flow with automatic token caching and refresh
93
+
94
+ * **Security**:
95
+ * Enforces HTTPS or localhost connections
96
+ * Prevents Man-in-the-Middle (MITM) attacks
97
+ * OAuth2 token caching to minimize token requests
98
+
99
+ ### OpenAPI Converter
100
+
101
+ Automatically converts OpenAPI specifications to UTCP tools:
102
+ * Parses OpenAPI 2.0 and 3.x specifications
103
+ * Generates tool definitions with proper schemas
104
+ * Extracts authentication requirements
105
+ * Creates placeholder variables for API keys
106
+
107
+ ## Protocol Comparison
108
+
109
+ ### When to Use Each Protocol
110
+
111
+ | Protocol | Use Case | Response Type | Best For |
112
+ |----------|----------|---------------|----------|
113
+ | **HTTP** | Standard RESTful APIs | Complete response | Most APIs, CRUD operations, single requests |
114
+ | **Streamable HTTP** | Large data downloads | Chunked streaming | Large files, datasets, progressive data |
115
+ | **SSE** | Real-time updates | Event stream | Live updates, notifications, real-time feeds |
116
+
117
+ ### Key Differences
118
+
119
+ **HTTP**
120
+ - ✅ Simple request-response model
121
+ - ✅ Complete data in single response
122
+ - ✅ All HTTP methods supported
123
+ - ❌ Not suitable for large responses
124
+ - ❌ No real-time updates
125
+
126
+ **Streamable HTTP**
127
+ - ✅ Efficient for large responses
128
+ - ✅ Progressive data processing
129
+ - ✅ Reduced memory usage
130
+ - ⚠️ Only GET/POST methods
131
+ - ❌ No bidirectional communication
132
+
133
+ **SSE**
134
+ - ✅ Real-time event streaming
135
+ - ✅ Automatic reconnection
136
+ - ✅ Event type filtering
137
+ - ✅ Server push updates
138
+ - ❌ Unidirectional (server → client only)
18
139
 
19
140
  ## Installation
20
141
 
21
142
  ```bash
22
- bun add @utcp/http @utcp/core axios js-yaml
143
+ npm install @utcp/http @utcp/sdk
144
+
145
+ # Or with bun
146
+ bun add @utcp/http @utcp/sdk
23
147
  ```
24
148
 
25
- Note: `@utcp/core` is a peer dependency, and `axios` and `js-yaml` are direct dependencies required for HTTP communication and OpenAPI parsing.
149
+ **Dependencies:**
150
+ - `@utcp/sdk` - Core UTCP SDK (peer dependency)
151
+ - `axios` - HTTP client
152
+ - `js-yaml` - YAML parsing for OpenAPI specs
26
153
 
27
- ## Usage
154
+ ## Quick Start
28
155
 
29
- To use the HTTP plugin, you must register its capabilities with the core `UtcpClient` at application startup. This is typically done by calling the `registerHttpPlugin()` function exported from `@utcp/http`.
156
+ ### Automatic Registration
30
157
 
31
- ```typescript
32
- // From your application's entry point
158
+ All three HTTP-based protocols (`http`, `streamable_http`, `sse`) are **automatically registered** when you import the UtcpClient. No manual setup required!
33
159
 
34
- import { UtcpClient } from '@utcp/core/client/utcp_client';
35
- import { UtcpClientConfigSchema } from '@utcp/core/client/utcp_client_config';
36
- import { registerHttpPlugin } from '@utcp/http'; // Import the registration function
160
+ ### Basic HTTP Usage
37
161
 
38
- // --- IMPORTANT: Register the HTTP plugin once at the start of your application ---
39
- registerHttpPlugin();
40
- // -------------------------------------------------------------------------------
162
+ ```typescript
163
+ import { UtcpClient } from '@utcp/sdk';
164
+ import { HttpCallTemplateSerializer } from '@utcp/http';
41
165
 
42
166
  async function main() {
43
- const client = await UtcpClient.create(
44
- UtcpClientConfigSchema.parse({
45
- // Define variables for substitution in call templates (e.g., for API keys)
46
- variables: {
47
- OPENLIBRARY_API_KEY_1: 'your-openlibrary-key' // Example for OpenAPI-derived template
48
- },
49
- // Manually define HTTP call templates in the config to be registered at startup
50
- manual_call_templates: [
51
- {
52
- name: 'openlibrary_api',
53
- call_template_type: 'http',
54
- url: 'https://openlibrary.org/static/openapi.json', // URL pointing to an OpenAPI spec
55
- http_method: 'GET'
56
- // Auth fields would be auto-generated by OpenApiConverter, but variables must be supplied
57
- }
58
- ],
59
- // Or load variables from .env files
60
- load_variables_from: [
61
- { type: 'dotenv', env_file_path: './.env' }
62
- ]
63
- })
64
- );
65
-
66
- console.log('HTTP Plugin active. Searching for tools...');
67
-
68
- // Search for tools (e.g., from the OpenLibrary API)
69
- const bookSearchTools = await client.searchTools('search for books by author');
70
- console.log('Found OpenLibrary tools:', bookSearchTools.map(t => t.name));
71
-
72
- // Example: Call a tool (e.g., 'openlibrary_api.read_search_authors_json_search_authors_json_get')
73
- if (bookSearchTools.length > 0) {
74
- try {
75
- const toolToCall = bookSearchTools.find(t => t.name.includes('search_authors'));
76
- if (toolToCall) {
77
- console.log(`Calling tool: ${toolToCall.name}`);
78
- const result = await client.callTool(toolToCall.name, { q: 'J. K. Rowling' });
79
- console.log('Tool call result:', result);
80
- } else {
81
- console.warn('No author search tool found for example call.');
82
- }
83
- } catch (error) {
84
- console.error('Error calling HTTP tool:', error);
167
+ const serializer = new HttpCallTemplateSerializer();
168
+ const weatherTemplate = serializer.validateDict({
169
+ name: 'weather_api',
170
+ call_template_type: 'http',
171
+ http_method: 'GET',
172
+ url: 'https://api.weatherapi.com/v1/current.json',
173
+ headers: {
174
+ 'X-API-Key': '${API_KEY}'
85
175
  }
176
+ });
177
+
178
+ const client = await UtcpClient.create(process.cwd(), {
179
+ variables: {
180
+ // Namespaced variables for security
181
+ 'weather__api_API_KEY': process.env.WEATHER_API_KEY || ''
182
+ },
183
+ manual_call_templates: [weatherTemplate]
184
+ });
185
+
186
+ // Call the API
187
+ const weather = await client.callTool('weather_api.get_current', {
188
+ q: 'London'
189
+ });
190
+
191
+ console.log('Weather:', weather);
192
+ await client.close();
193
+ }
194
+ ```
195
+
196
+ ### With OpenAPI Specification
197
+
198
+ Automatically discover tools from an OpenAPI spec:
199
+
200
+ ```typescript
201
+ import { UtcpClient } from '@utcp/sdk';
202
+ import { HttpCallTemplateSerializer } from '@utcp/http';
203
+
204
+ const serializer = new HttpCallTemplateSerializer();
205
+ const petstoreTemplate = serializer.validateDict({
206
+ name: 'petstore_api',
207
+ call_template_type: 'http',
208
+ http_method: 'GET',
209
+ url: 'https://petstore.swagger.io/v2/swagger.json',
210
+ // Tools will be auto-discovered from the OpenAPI spec
211
+ });
212
+
213
+ const client = await UtcpClient.create(process.cwd(), {
214
+ manual_call_templates: [petstoreTemplate]
215
+ });
216
+
217
+ // Search for discovered tools
218
+ const tools = await client.searchTools('pet');
219
+ console.log('Available tools:', tools.map(t => t.name));
220
+
221
+ // Call a discovered tool
222
+ const pets = await client.callTool('petstore_api.findPetsByStatus', {
223
+ status: 'available'
224
+ });
225
+ ```
226
+
227
+ ### Streamable HTTP Usage
228
+
229
+ Stream large responses using chunked transfer encoding:
230
+
231
+ ```typescript
232
+ import { UtcpClient } from '@utcp/sdk';
233
+ import { StreamableHttpCallTemplateSerializer } from '@utcp/http';
234
+
235
+ const serializer = new StreamableHttpCallTemplateSerializer();
236
+ const streamTemplate = serializer.validateDict({
237
+ name: 'large_data_api',
238
+ call_template_type: 'streamable_http',
239
+ http_method: 'GET',
240
+ url: 'https://api.example.com/large-dataset',
241
+ chunk_size: 8192, // 8KB chunks
242
+ timeout: 120000, // 2 minutes
243
+ headers: {
244
+ 'Accept': 'application/octet-stream'
245
+ }
246
+ });
247
+
248
+ const client = await UtcpClient.create(process.cwd(), {
249
+ manual_call_templates: [streamTemplate]
250
+ });
251
+
252
+ // Stream the response
253
+ const stream = await client.callToolStreaming('large_data_api.get_dataset', {
254
+ filter: 'recent'
255
+ });
256
+
257
+ for await (const chunk of stream) {
258
+ console.log('Received chunk:', chunk.length, 'bytes');
259
+ // Process chunk...
260
+ }
261
+ ```
262
+
263
+ ### SSE (Server-Sent Events) Usage
264
+
265
+ Real-time event streaming from servers:
266
+
267
+ ```typescript
268
+ import { UtcpClient } from '@utcp/sdk';
269
+ import { SseCallTemplateSerializer } from '@utcp/http';
270
+
271
+ const serializer = new SseCallTemplateSerializer();
272
+ const sseTemplate = serializer.validateDict({
273
+ name: 'events_api',
274
+ call_template_type: 'sse',
275
+ url: 'https://api.example.com/events',
276
+ event_type: 'notification', // Filter to specific event type
277
+ reconnect: true, // Auto-reconnect on disconnect
278
+ retry_timeout: 5000, // Retry after 5 seconds
279
+ headers: {
280
+ 'Authorization': 'Bearer ${API_KEY}'
281
+ }
282
+ });
283
+
284
+ const client = await UtcpClient.create(process.cwd(), {
285
+ variables: {
286
+ 'events__api_API_KEY': process.env.SSE_API_KEY || ''
287
+ },
288
+ manual_call_templates: [sseTemplate]
289
+ });
290
+
291
+ // Stream real-time events
292
+ const eventStream = await client.callToolStreaming('events_api.stream_events', {
293
+ channel: 'updates'
294
+ });
295
+
296
+ for await (const event of eventStream) {
297
+ console.log('Event received:', event);
298
+ // Handle event...
299
+ }
300
+ ```
301
+
302
+ ### Authentication Examples
303
+
304
+ #### API Key Authentication
305
+
306
+ ```typescript
307
+ import { HttpCallTemplateSerializer } from '@utcp/http';
308
+
309
+ const serializer = new HttpCallTemplateSerializer();
310
+ const callTemplate = serializer.validateDict({
311
+ name: 'api_with_key',
312
+ call_template_type: 'http',
313
+ http_method: 'GET',
314
+ url: 'https://api.example.com/data',
315
+ auth: {
316
+ auth_type: 'api_key',
317
+ var_name: 'X-API-Key',
318
+ api_key_value: '${API_KEY}',
319
+ in: 'header' // or 'query' or 'cookie'
320
+ }
321
+ });
322
+ ```
323
+
324
+ #### Basic Authentication
325
+
326
+ ```typescript
327
+ const serializer = new HttpCallTemplateSerializer();
328
+ const callTemplate = serializer.validateDict({
329
+ name: 'api_with_basic',
330
+ call_template_type: 'http',
331
+ http_method: 'GET',
332
+ url: 'https://api.example.com/data',
333
+ auth: {
334
+ auth_type: 'basic',
335
+ username: '${USERNAME}',
336
+ password: '${PASSWORD}'
337
+ }
338
+ });
339
+ ```
340
+
341
+ #### OAuth2 Client Credentials
342
+
343
+ ```typescript
344
+ const serializer = new HttpCallTemplateSerializer();
345
+ const callTemplate = serializer.validateDict({
346
+ name: 'api_with_oauth',
347
+ call_template_type: 'http',
348
+ http_method: 'GET',
349
+ url: 'https://api.example.com/data',
350
+ auth: {
351
+ auth_type: 'oauth2',
352
+ token_url: 'https://auth.example.com/oauth/token',
353
+ client_id: '${CLIENT_ID}',
354
+ client_secret: '${CLIENT_SECRET}',
355
+ scope: 'read write'
356
+ }
357
+ });
358
+ ```
359
+
360
+ ### Path Parameters
361
+
362
+ Use `${param}` or `{param}` syntax for path parameters:
363
+
364
+ ```typescript
365
+ const serializer = new HttpCallTemplateSerializer();
366
+ const callTemplate = serializer.validateDict({
367
+ name: 'github_api',
368
+ call_template_type: 'http',
369
+ http_method: 'GET',
370
+ url: 'https://api.github.com/users/${username}',
371
+ });
372
+
373
+ // Call with arguments
374
+ await client.callTool('github_api.get_user', {
375
+ username: 'octocat'
376
+ });
377
+ // Resolves to: https://api.github.com/users/octocat
378
+ ```
379
+
380
+ ### Request Body
381
+
382
+ For POST/PUT/PATCH requests, use `body_field`:
383
+
384
+ ```typescript
385
+ const serializer = new HttpCallTemplateSerializer();
386
+ const callTemplate = serializer.validateDict({
387
+ name: 'create_resource',
388
+ call_template_type: 'http',
389
+ http_method: 'POST',
390
+ url: 'https://api.example.com/resources',
391
+ body_field: 'data',
392
+ content_type: 'application/json',
393
+ headers: {
394
+ 'Content-Type': 'application/json'
395
+ }
396
+ });
397
+
398
+ // Call with body
399
+ await client.callTool('create_resource.post', {
400
+ data: {
401
+ name: 'My Resource',
402
+ value: 42
403
+ }
404
+ });
405
+ ```
406
+
407
+ ## Use Case Examples
408
+
409
+ ### HTTP: GitHub API Integration
410
+
411
+ ```typescript
412
+ const serializer = new HttpCallTemplateSerializer();
413
+ const githubTemplate = serializer.validateDict({
414
+ name: 'github_api',
415
+ call_template_type: 'http',
416
+ http_method: 'GET',
417
+ url: 'https://api.github.com/repos/${owner}/${repo}/issues',
418
+ headers: { 'Authorization': 'Bearer ${TOKEN}' }
419
+ });
420
+
421
+ const client = await UtcpClient.create(process.cwd(), {
422
+ variables: { 'github__api_TOKEN': process.env.GITHUB_TOKEN || '' },
423
+ manual_call_templates: [githubTemplate]
424
+ });
425
+
426
+ const issues = await client.callTool('github_api.get_issues', {
427
+ owner: 'utcp', repo: 'typescript-utcp'
428
+ });
429
+ ```
430
+
431
+ ### Streamable HTTP: Large File Download
432
+
433
+ ```typescript
434
+ const serializer = new StreamableHttpCallTemplateSerializer();
435
+ const cdnTemplate = serializer.validateDict({
436
+ name: 'cdn',
437
+ call_template_type: 'streamable_http',
438
+ http_method: 'GET',
439
+ url: 'https://cdn.example.com/large-file.zip',
440
+ chunk_size: 16384
441
+ });
442
+
443
+ const client = await UtcpClient.create(process.cwd(), {
444
+ manual_call_templates: [cdnTemplate]
445
+ });
446
+
447
+ const stream = await client.callToolStreaming('cdn.download', {});
448
+ for await (const chunk of stream) {
449
+ // Write chunk to file or process incrementally
450
+ fs.appendFileSync('output.zip', chunk);
451
+ }
452
+ ```
453
+
454
+ ### SSE: Stock Price Updates
455
+
456
+ ```typescript
457
+ const serializer = new SseCallTemplateSerializer();
458
+ const stockTemplate = serializer.validateDict({
459
+ name: 'stock_api',
460
+ call_template_type: 'sse',
461
+ url: 'https://api.stocks.com/stream',
462
+ event_type: 'price_update',
463
+ reconnect: true
464
+ });
465
+
466
+ const client = await UtcpClient.create(process.cwd(), {
467
+ manual_call_templates: [stockTemplate]
468
+ });
469
+
470
+ const priceStream = await client.callToolStreaming('stock_api.watch', {
471
+ symbol: 'AAPL'
472
+ });
473
+
474
+ for await (const update of priceStream) {
475
+ console.log('Price update:', update.price, 'at', update.timestamp);
476
+ }
477
+ ```
478
+
479
+ ## Advanced Features
480
+
481
+ ### Custom Headers with Variables
482
+
483
+ ```typescript
484
+ const serializer = new HttpCallTemplateSerializer();
485
+ const callTemplate = serializer.validateDict({
486
+ name: 'custom_api',
487
+ call_template_type: 'http',
488
+ http_method: 'GET',
489
+ url: 'https://api.example.com/data',
490
+ headers: {
491
+ 'Authorization': 'Bearer ${TOKEN}',
492
+ 'X-Request-ID': '${REQUEST_ID}',
493
+ 'User-Agent': 'UTCP-Client/1.0'
86
494
  }
495
+ });
496
+ ```
87
497
 
88
- await client.close(); // Clean up HTTP client sessions, OAuth tokens, etc.
498
+ ### Timeout Configuration
499
+
500
+ ```typescript
501
+ const serializer = new HttpCallTemplateSerializer();
502
+ const callTemplate = serializer.validateDict({
503
+ name: 'slow_api',
504
+ call_template_type: 'http',
505
+ http_method: 'GET',
506
+ url: 'https://api.example.com/slow-endpoint',
507
+ timeout: 60000 // 60 seconds
508
+ });
509
+ ```
510
+
511
+ ### Variable Namespacing
512
+
513
+ All variables are automatically namespaced by manual name for security:
514
+
515
+ ```typescript
516
+ const client = await UtcpClient.create(process.cwd(), {
517
+ variables: {
518
+ // For manual "github_api", variables must be prefixed
519
+ 'github__api_TOKEN': 'github-token-123',
520
+ 'gitlab__api_TOKEN': 'gitlab-token-456'
521
+ },
522
+ manual_call_templates: [
523
+ {
524
+ name: 'github_api',
525
+ // ...
526
+ headers: {
527
+ // Resolves to "github__api_TOKEN"
528
+ 'Authorization': 'Bearer ${TOKEN}'
529
+ }
530
+ }
531
+ ]
532
+ });
533
+ ```
534
+
535
+ ## OpenAPI Conversion
536
+
537
+ The `OpenApiConverter` automatically:
538
+
539
+ 1. **Parses OpenAPI specs** (2.0 and 3.x)
540
+ 2. **Extracts endpoints** as individual tools
541
+ 3. **Generates schemas** for inputs and outputs
542
+ 4. **Detects authentication** requirements
543
+ 5. **Creates placeholder variables** for API keys
544
+
545
+ ```typescript
546
+ import { OpenApiConverter } from '@utcp/http';
547
+
548
+ const converter = new OpenApiConverter('https://api.example.com/openapi.json');
549
+ const manual = await converter.convert();
550
+
551
+ console.log('Discovered tools:', manual.tools.length);
552
+ ```
553
+
554
+ ## Security Features
555
+
556
+ ### HTTPS Enforcement
557
+
558
+ The HTTP protocol enforces HTTPS or localhost connections by default to prevent MITM attacks:
559
+
560
+ ```typescript
561
+ // ✅ Allowed
562
+ 'https://api.example.com'
563
+ 'http://localhost:8080'
564
+ 'http://127.0.0.1:3000'
565
+
566
+ // ❌ Rejected
567
+ 'http://api.example.com' // Non-localhost HTTP
568
+ ```
569
+
570
+ ### OAuth2 Token Caching
571
+
572
+ OAuth2 tokens are automatically cached by `client_id` to minimize token requests:
573
+
574
+ - Tokens are cached until expiration
575
+ - Automatic refresh when expired
576
+ - Tries both body and auth header methods
577
+
578
+ ## Error Handling
579
+
580
+ ```typescript
581
+ try {
582
+ const result = await client.callTool('api_manual.endpoint', args);
583
+ } catch (error) {
584
+ if (error.message.includes('401')) {
585
+ console.error('Authentication failed');
586
+ } else if (error.message.includes('404')) {
587
+ console.error('Endpoint not found');
588
+ } else {
589
+ console.error('Request failed:', error);
590
+ }
89
591
  }
592
+ ```
90
593
 
91
- main().catch(console.error);
594
+ ## TypeScript Support
595
+
596
+ Full TypeScript support with exported types for all three protocols:
597
+
598
+ ```typescript
599
+ import {
600
+ // HTTP Protocol
601
+ HttpCallTemplate,
602
+ HttpCommunicationProtocol,
603
+
604
+ // Streamable HTTP Protocol
605
+ StreamableHttpCallTemplate,
606
+ StreamableHttpCommunicationProtocol,
607
+
608
+ // SSE Protocol
609
+ SseCallTemplate,
610
+ SseCommunicationProtocol,
611
+
612
+ // OpenAPI Converter
613
+ OpenApiConverter,
614
+
615
+ // Authentication Types
616
+ ApiKeyAuth,
617
+ BasicAuth,
618
+ OAuth2Auth
619
+ } from '@utcp/http';
92
620
  ```
93
621
 
94
- ## Development
622
+ ## Testing
623
+
624
+ ```bash
625
+ # Run HTTP protocol tests
626
+ bun test packages/http/tests/
627
+ ```
628
+
629
+ ## Related Packages
630
+
631
+ - `@utcp/sdk` - Core UTCP SDK
632
+ - `@utcp/mcp` - MCP protocol support
633
+ - `@utcp/text` - File-based tools
634
+ - `@utcp/cli` - Command-line tools
635
+
636
+ ## Contributing
637
+
638
+ See the root repository for contribution guidelines.
639
+
640
+ ## License
95
641
 
96
- Refer to the root `README.md` for monorepo development and testing instructions.
642
+ Mozilla Public License Version 2.0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@utcp/http",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "HTTP utilities for UTCP",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -36,12 +36,11 @@
36
36
  "exports": {
37
37
  ".": {
38
38
  "import": "./dist/index.js",
39
- "require": "./dist/index.js",
40
39
  "types": "./dist/index.d.ts"
41
40
  }
42
41
  },
43
42
  "dependencies": {
44
- "@utcp/sdk": "^1.0.0",
43
+ "@utcp/sdk": "^1.0.2",
45
44
  "axios": "^1.11.0",
46
45
  "js-yaml": "^4.1.0"
47
46
  },