From 6ff7ddc690ef3a8e75330d7e38833a776ba4b7ba Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 15 Jan 2026 08:22:22 +0000 Subject: [PATCH 1/3] Initial plan From 9215dea560539ed76ffa7207dbbe7a95603b40ae Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 15 Jan 2026 08:28:52 +0000 Subject: [PATCH 2/3] Add README.md files for all crates and update version numbers Co-authored-by: bkataru <14833123+bkataru@users.noreply.github.com> --- crates/thulp-adapter/README.md | 164 ++++++++++++++++++++++ crates/thulp-browser/README.md | 161 ++++++++++++++++++++++ crates/thulp-cli/README.md | 179 ++++++++++++++++++++++++ crates/thulp-core/README.md | 204 +++++++++++++++++++++++++++ crates/thulp-guidance/README.md | 157 +++++++++++++++++++++ crates/thulp-mcp/README.md | 6 +- crates/thulp-registry/README.md | 235 ++++++++++++++++++++++++++++++++ 7 files changed, 1103 insertions(+), 3 deletions(-) create mode 100644 crates/thulp-adapter/README.md create mode 100644 crates/thulp-browser/README.md create mode 100644 crates/thulp-cli/README.md create mode 100644 crates/thulp-core/README.md create mode 100644 crates/thulp-guidance/README.md create mode 100644 crates/thulp-registry/README.md diff --git a/crates/thulp-adapter/README.md b/crates/thulp-adapter/README.md new file mode 100644 index 0000000..0297a7e --- /dev/null +++ b/crates/thulp-adapter/README.md @@ -0,0 +1,164 @@ +# thulp-adapter + +Adapter for converting external tool definitions to Thulp format. + +## Overview + +This crate provides functionality to convert OpenAPI v2/v3 specifications into Thulp tool definitions. It enables automatic generation of tool adapters from existing API specifications, making it easy to integrate external services with AI agents. + +## Features + +- Parse OpenAPI v2 and v3 specifications (JSON and YAML) +- Convert API endpoints into Thulp tool definitions +- Extract authentication requirements +- Generate adapter configuration files +- Support for path, query, and body parameters + +## Installation + +Add to your `Cargo.toml`: + +```toml +[dependencies] +thulp-adapter = "0.2" +``` + +## Usage + +### Basic Conversion + +```rust +use thulp_adapter::AdapterGenerator; +use serde_json::Value; + +// Load an OpenAPI specification +let spec: Value = serde_json::from_str(r#"{ + "openapi": "3.0.0", + "info": {"title": "Test API", "version": "1.0.0"}, + "paths": { + "/users": { + "get": { + "operationId": "listUsers", + "summary": "List all users", + "responses": { + "200": { + "description": "A list of users" + } + } + } + } + } +}"#).unwrap(); + +// Create an adapter generator +let generator = AdapterGenerator::new(spec, Some("test-api".to_string())); + +// Generate tool definitions +let tools = generator.generate_tools().unwrap(); +println!("Generated {} tools", tools.len()); +``` + +### Loading from URL + +```rust +use thulp_adapter::AdapterGenerator; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let generator = AdapterGenerator::from_url( + "https://api.example.com/openapi.json", + Some("example-api".to_string()) + ).await?; + + let tools = generator.generate_tools()?; + Ok(()) +} +``` + +### Extract Authentication Configuration + +```rust +use thulp_adapter::AdapterGenerator; +use serde_json::json; + +let spec = json!({ + "openapi": "3.0.0", + "info": {"title": "Test API", "version": "1.0.0"}, + "components": { + "securitySchemes": { + "ApiKeyAuth": { + "type": "apiKey", + "in": "header", + "name": "X-API-Key" + } + } + }, + "paths": {} +}); + +let generator = AdapterGenerator::new(spec, Some("test-api".to_string())); +let auth_configs = generator.extract_auth_config(); +``` + +### Generate Configuration File + +```rust +use thulp_adapter::AdapterGenerator; +use serde_json::json; + +let spec = json!({ + "openapi": "3.0.0", + "info": {"title": "API", "version": "1.0.0"}, + "paths": { + "/items": { + "get": { + "operationId": "listItems", + "summary": "List items" + } + } + } +}); + +let generator = AdapterGenerator::new(spec, Some("items-api".to_string())); +let yaml_config = generator.generate_config()?; +``` + +## Parameter Type Mapping + +The adapter automatically maps OpenAPI types to Thulp parameter types: + +| OpenAPI Type | Thulp ParameterType | +|--------------|---------------------| +| `string` | `ParameterType::String` | +| `integer` | `ParameterType::Integer` | +| `number` | `ParameterType::Number` | +| `boolean` | `ParameterType::Boolean` | +| `array` | `ParameterType::Array` | +| `object` | `ParameterType::Object` | + +## CLI Usage + +Use the Thulp CLI to convert OpenAPI specifications: + +```bash +# Convert OpenAPI spec to tool definitions +thulp convert openapi spec.yaml --output tools.yaml + +# Show conversion examples +thulp convert examples +``` + +## Testing + +```bash +cargo test -p thulp-adapter +``` + +## License + +Licensed under either of: + +- Apache License, Version 2.0 ([LICENSE-APACHE](../../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) +- MIT license ([LICENSE-MIT](../../LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. diff --git a/crates/thulp-browser/README.md b/crates/thulp-browser/README.md new file mode 100644 index 0000000..f2f457c --- /dev/null +++ b/crates/thulp-browser/README.md @@ -0,0 +1,161 @@ +# thulp-browser + +Browser automation and web scraping utilities for Thulp. + +## Overview + +This crate provides tools for web page fetching, HTML content extraction, and browser automation. It supports basic HTTP fetching out of the box and optional Chrome DevTools Protocol (CDP) integration for full browser automation. + +## Features + +- **Web Page Fetching**: Simple async HTTP client for fetching web pages +- **HTML Content Extraction**: Extract text content and page titles from HTML +- **CDP Support**: Optional Chrome DevTools Protocol integration for advanced browser automation +- **Page Metadata**: Access page URL, status code, title, and content +- **Async Design**: Built on tokio and reqwest for efficient async operations + +## Installation + +Add to your `Cargo.toml`: + +```toml +[dependencies] +thulp-browser = "0.2" +``` + +For CDP browser automation support: + +```toml +[dependencies] +thulp-browser = { version = "0.2", features = ["cdp"] } +``` + +## Usage + +### Basic Web Fetching + +```rust +use thulp_browser::WebClient; + +#[tokio::main] +async fn main() -> Result<(), thulp_browser::BrowserError> { + let client = WebClient::new(); + let page = client.fetch("https://example.com").await?; + + println!("URL: {}", page.url); + println!("Status: {}", page.status); + println!("Title: {:?}", page.title); + println!("Content length: {} bytes", page.len()); + + // Extract text content (HTML tags stripped) + println!("Text: {}", page.text()); + + Ok(()) +} +``` + +### Working with Page Content + +```rust +use thulp_browser::{Page, WebClient}; + +#[tokio::main] +async fn main() -> Result<(), thulp_browser::BrowserError> { + let client = WebClient::new(); + let page = client.fetch("https://example.com").await?; + + // Check if fetch was successful + if page.status == 200 { + // Access raw HTML + println!("HTML: {}", page.html); + + // Get text without HTML tags + let text = page.text(); + + // Check page title + if let Some(title) = &page.title { + println!("Page title: {}", title); + } + } + + Ok(()) +} +``` + +### CDP Browser Automation (requires `cdp` feature) + +```rust +use thulp_browser::cdp::{Browser, BrowserConfig}; + +#[tokio::main] +async fn main() -> Result<(), thulp_browser::BrowserError> { + // Configure browser (headless mode) + let config = BrowserConfig::new().headless(true); + + // Launch browser + let browser = Browser::launch(config).await?; + + // Create a new page + let page = browser.new_page().await?; + + // Navigate to URL + page.navigate("https://example.com").await?; + + // Take a screenshot + let screenshot = page.screenshot().await?; + + // Evaluate JavaScript + let result = page.evaluate("document.title").await?; + + Ok(()) +} +``` + +## Page Structure + +The `Page` struct contains: + +- **url**: The URL of the fetched page +- **html**: Raw HTML content +- **title**: Extracted page title (if found) +- **status**: HTTP status code + +## Error Types + +The crate provides detailed error types for different failure scenarios: + +- `BrowserError::Http`: HTTP request failures +- `BrowserError::Parse`: HTML parsing errors +- `BrowserError::InvalidUrl`: Invalid URL format +- `BrowserError::CdpConnection`: CDP connection failures +- `BrowserError::CdpProtocol`: CDP protocol errors +- `BrowserError::BrowserLaunch`: Browser launch failures +- `BrowserError::Navigation`: Page navigation failures +- `BrowserError::JavaScriptEval`: JavaScript evaluation failures +- `BrowserError::Screenshot`: Screenshot capture failures +- `BrowserError::Timeout`: Operation timeout + +## Feature Flags + +| Flag | Description | +|------|-------------| +| `cdp` | Enable Chrome DevTools Protocol support | + +## Testing + +```bash +# Run tests +cargo test -p thulp-browser + +# Run tests with CDP feature +cargo test -p thulp-browser --features cdp +``` + +## License + +Licensed under either of: + +- Apache License, Version 2.0 ([LICENSE-APACHE](../../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) +- MIT license ([LICENSE-MIT](../../LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. diff --git a/crates/thulp-cli/README.md b/crates/thulp-cli/README.md new file mode 100644 index 0000000..8cbb7b0 --- /dev/null +++ b/crates/thulp-cli/README.md @@ -0,0 +1,179 @@ +# thulp-cli + +Command-line interface for the Thulp execution context engineering platform. + +## Overview + +This crate provides a full-featured CLI for interacting with Thulp tools, MCP servers, and OpenAPI adapters. It supports multiple output formats (text, JSON) and shell completion generation. + +## Features + +- **Tool Management**: List, show, and validate tool definitions +- **MCP Integration**: Connect to MCP servers via STDIO or HTTP +- **OpenAPI Conversion**: Convert OpenAPI specs to tool definitions +- **Multiple Output Formats**: Human-readable text or JSON output +- **Shell Completions**: Generate completions for Bash, Zsh, Fish, PowerShell, and Elvish +- **Demo Mode**: Interactive demonstration of core functionality + +## Installation + +Install from crates.io: + +```bash +cargo install thulp-cli +``` + +Or build from source: + +```bash +cargo build --release -p thulp-cli +``` + +With MCP support: + +```bash +cargo install thulp-cli --features mcp +``` + +## Usage + +### List Tools + +```bash +# Human-readable output +thulp tools list + +# JSON output +thulp tools list --output json +``` + +### Show Tool Details + +```bash +thulp tools show read_file +thulp tools show read_file --output json +``` + +### Validate Tool Arguments + +```bash +# Validate with JSON arguments +thulp tools validate read_file --args '{"path": "/etc/hosts"}' + +# JSON output for scripting +thulp tools validate read_file --args '{}' --output json +``` + +### MCP Server Connection (requires `mcp` feature) + +```bash +# Connect via HTTP +thulp mcp connect-http myserver http://localhost:8080 + +# Connect via STDIO +thulp mcp connect-stdio myserver /path/to/mcp-server -- --verbose + +# List tools from MCP server +thulp mcp list + +# Call MCP tool +thulp mcp call search --args '{"query": "test"}' + +# Check connection status +thulp mcp status +``` + +### OpenAPI Conversion + +```bash +# Convert OpenAPI spec to tool definitions +thulp convert openapi spec.yaml +thulp convert openapi spec.json --output tools.yaml + +# Show conversion examples +thulp convert examples +``` + +### Generate Shell Completions + +```bash +# Bash +thulp completions bash > ~/.local/share/bash-completion/completions/thulp + +# Zsh +thulp completions zsh > ~/.zfunc/_thulp + +# Fish +thulp completions fish > ~/.config/fish/completions/thulp.fish + +# PowerShell +thulp completions powershell >> $PROFILE + +# Output to directory +thulp completions bash --dir ~/.local/share/bash-completion/completions +``` + +### Run Demo + +```bash +# Interactive demo +thulp demo + +# JSON output for testing +thulp demo --output json +``` + +### Validate Configuration + +```bash +thulp validate config.yaml +``` + +## Output Formats + +The CLI supports three output formats: + +| Format | Flag | Description | +|--------|------|-------------| +| Text | `--output text` | Human-readable output (default) | +| JSON | `--output json` | Pretty-printed JSON | +| JSON Compact | `--output json-compact` | Single-line JSON | + +## Commands + +| Command | Description | +|---------|-------------| +| `tools list` | List all available tools | +| `tools show ` | Show details of a specific tool | +| `tools validate ` | Validate tool arguments | +| `mcp connect-http` | Connect to MCP server via HTTP | +| `mcp connect-stdio` | Connect to MCP server via STDIO | +| `mcp list` | List tools from MCP server | +| `mcp call` | Call a tool on the MCP server | +| `mcp status` | Show connection status | +| `convert openapi` | Convert OpenAPI spec to tools | +| `convert examples` | Show conversion examples | +| `demo` | Run interactive demo | +| `validate` | Validate configuration files | +| `completions` | Generate shell completions | + +## Feature Flags + +| Flag | Description | +|------|-------------| +| `mcp` | Enable MCP server integration | + +## Testing + +```bash +cargo test -p thulp-cli +``` + +## License + +Licensed under either of: + +- Apache License, Version 2.0 ([LICENSE-APACHE](../../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) +- MIT license ([LICENSE-MIT](../../LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. diff --git a/crates/thulp-core/README.md b/crates/thulp-core/README.md new file mode 100644 index 0000000..e7f3681 --- /dev/null +++ b/crates/thulp-core/README.md @@ -0,0 +1,204 @@ +# thulp-core + +Core types, traits, and error definitions for the Thulp execution context platform. + +## Overview + +This crate provides the foundational abstractions for defining, validating, and executing tools in AI agent environments. It includes type-safe parameter definitions, tool metadata, and extensible traits for implementing custom tool providers and transports. + +## Features + +- **Type-Safe Parameters**: Compile-time and runtime validation of tool parameters +- **Builder Pattern**: Ergonomic API for constructing tool definitions +- **JSON Serialization**: Full serde support for all types +- **MCP Integration**: Parse MCP JSON Schema to Thulp parameter definitions +- **Async Support**: Built on tokio for efficient async execution + +## Installation + +Add to your `Cargo.toml`: + +```toml +[dependencies] +thulp-core = "0.2" +``` + +## Core Types + +- `ToolDefinition`: Describes an available tool with its parameters and metadata +- `ToolCall`: Represents a request to execute a specific tool with arguments +- `ToolResult`: The result of a tool execution (success or failure) +- `Parameter`: Defines a tool parameter with type information and validation rules +- `ParameterType`: Strongly-typed parameter types (String, Integer, Number, Boolean, Array, Object) + +## MCP Types + +- `Resource`: MCP resource definition with URI, name, and metadata +- `ResourceContents`: Content of a read resource (text or blob) +- `Prompt`: MCP prompt definition with arguments +- `PromptMessage`: Message in a rendered prompt + +## Traits + +- `Tool`: Trait for implementing executable tools +- `Transport`: Trait for implementing tool transport layers (MCP, HTTP, gRPC) + +## Usage + +### Defining a Tool + +```rust +use thulp_core::{ToolDefinition, Parameter, ParameterType}; + +let tool = ToolDefinition::builder("read_file") + .description("Read contents of a file") + .parameter( + Parameter::builder("path") + .param_type(ParameterType::String) + .required(true) + .description("Path to the file to read") + .build() + ) + .parameter( + Parameter::builder("encoding") + .param_type(ParameterType::String) + .default(serde_json::Value::String("utf-8".to_string())) + .description("File encoding") + .build() + ) + .build(); + +assert_eq!(tool.name, "read_file"); +assert_eq!(tool.parameters.len(), 2); +``` + +### Validating Tool Arguments + +```rust +use thulp_core::{ToolDefinition, Parameter, ParameterType}; +use serde_json::json; + +let tool = ToolDefinition::builder("add") + .description("Add two numbers") + .parameter( + Parameter::builder("a") + .param_type(ParameterType::Number) + .required(true) + .build() + ) + .parameter( + Parameter::builder("b") + .param_type(ParameterType::Number) + .required(true) + .build() + ) + .build(); + +// Valid arguments +let args = json!({"a": 5.0, "b": 3.0}); +assert!(tool.validate_args(&args).is_ok()); + +// Invalid - missing required parameter +let args = json!({"a": 5.0}); +assert!(tool.validate_args(&args).is_err()); +``` + +### Creating Tool Calls + +```rust +use thulp_core::ToolCall; +use serde_json::json; + +let call = ToolCall::builder("search") + .arg("query", json!("rust programming")) + .arg("max_results", json!(10)) + .build(); + +assert_eq!(call.tool, "search"); +``` + +### Parsing MCP JSON Schema + +```rust +use thulp_core::ToolDefinition; +use serde_json::json; + +let schema = json!({ + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "User name" + }, + "age": { + "type": "integer", + "description": "User age" + } + }, + "required": ["name"] +}); + +let params = ToolDefinition::parse_mcp_input_schema(&schema).unwrap(); +assert_eq!(params.len(), 2); +``` + +### Working with MCP Resources + +```rust +use thulp_core::{Resource, ResourceContents}; + +let resource = Resource::builder("file:///docs/readme.md", "readme.md") + .title("Project README") + .mime_type("text/markdown") + .description("Main project documentation") + .build(); + +let contents = ResourceContents::text("file:///docs/readme.md", "# Project\n..."); +``` + +## Error Handling + +All fallible operations return `Result`, where `Error` provides detailed error information: + +```rust +use thulp_core::{ToolDefinition, Error, Parameter, ParameterType}; +use serde_json::json; + +let tool = ToolDefinition::builder("test") + .parameter( + Parameter::builder("required_param") + .param_type(ParameterType::String) + .required(true) + .build() + ) + .build(); + +match tool.validate_args(&json!({})) { + Ok(_) => println!("Valid!"), + Err(Error::MissingParameter(name)) => { + eprintln!("Missing required parameter: {}", name); + } + Err(e) => eprintln!("Other error: {}", e), +} +``` + +## Testing + +```bash +cargo test -p thulp-core +``` + +## Benchmarking + +```bash +cargo bench -p thulp-core --bench tool_benchmarks +``` + +## License + +Licensed under either of: + +- Apache License, Version 2.0 ([LICENSE-APACHE](../../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) +- MIT license ([LICENSE-MIT](../../LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. diff --git a/crates/thulp-guidance/README.md b/crates/thulp-guidance/README.md new file mode 100644 index 0000000..8b4e807 --- /dev/null +++ b/crates/thulp-guidance/README.md @@ -0,0 +1,157 @@ +# thulp-guidance + +LLM guidance and prompt template system for Thulp. + +## Overview + +This crate provides utilities for creating, managing, and rendering prompt templates for AI agent interactions. It supports variable substitution, default values, and a template registry for organizing prompts. + +## Features + +- **Prompt Templates**: Define templates with `{{variable}}` placeholders +- **Variable Substitution**: Replace placeholders with runtime values +- **Default Values**: Set fallback values for template variables +- **Template Registry**: Organize and manage multiple templates +- **JSON Serialization**: Full serde support for templates + +## Installation + +Add to your `Cargo.toml`: + +```toml +[dependencies] +thulp-guidance = "0.2" +``` + +## Usage + +### Creating a Prompt Template + +```rust +use thulp_guidance::PromptTemplate; + +let template = PromptTemplate::new( + "greeting", + "Hello {{name}}! Welcome to {{place}}." +); +``` + +### Rendering with Variables + +```rust +use thulp_guidance::PromptTemplate; +use std::collections::HashMap; + +let template = PromptTemplate::new("greeting", "Hello {{name}}!"); + +let mut vars = HashMap::new(); +vars.insert("name".to_string(), "World".to_string()); + +let result = template.render(&vars).unwrap(); +assert_eq!(result, "Hello World!"); +``` + +### Using Default Values + +```rust +use thulp_guidance::PromptTemplate; +use std::collections::HashMap; + +let template = PromptTemplate::new("greeting", "Hello {{name}}!") + .with_default("name", "Guest"); + +// Renders with default value +let result = template.render(&HashMap::new()).unwrap(); +assert_eq!(result, "Hello Guest!"); + +// Override default with provided value +let mut vars = HashMap::new(); +vars.insert("name".to_string(), "Alice".to_string()); +let result = template.render(&vars).unwrap(); +assert_eq!(result, "Hello Alice!"); +``` + +### Template Registry + +```rust +use thulp_guidance::{PromptTemplate, TemplateRegistry}; +use std::collections::HashMap; + +let mut registry = TemplateRegistry::new(); + +// Register templates +registry.register(PromptTemplate::new("greeting", "Hello {{name}}!")); +registry.register(PromptTemplate::new("farewell", "Goodbye {{name}}!")); + +// List all templates +let names = registry.list(); +println!("Available templates: {:?}", names); + +// Render by name +let mut vars = HashMap::new(); +vars.insert("name".to_string(), "World".to_string()); + +let greeting = registry.render("greeting", &vars).unwrap(); +assert_eq!(greeting, "Hello World!"); +``` + +### Complex Templates + +```rust +use thulp_guidance::PromptTemplate; +use std::collections::HashMap; + +let template = PromptTemplate::new( + "code_review", + r#"Please review the following {{language}} code: + +```{{language}} +{{code}} +``` + +Focus on: {{focus_areas}} + +Provide feedback on code quality, potential bugs, and improvements."# +) +.with_default("focus_areas", "readability and performance"); + +let mut vars = HashMap::new(); +vars.insert("language".to_string(), "rust".to_string()); +vars.insert("code".to_string(), "fn main() { println!(\"Hello\"); }".to_string()); + +let prompt = template.render(&vars).unwrap(); +``` + +## Error Handling + +The crate provides specific error types: + +- `GuidanceError::Template`: Template rendering errors +- `GuidanceError::VariableNotFound`: Missing template or variable +- `GuidanceError::InvalidFormat`: Format validation errors + +```rust +use thulp_guidance::{PromptTemplate, GuidanceError}; +use std::collections::HashMap; + +let template = PromptTemplate::new("test", "Hello {{name}}!"); + +// Missing variable returns error +let result = template.render(&HashMap::new()); +assert!(result.is_err()); +``` + +## Testing + +```bash +cargo test -p thulp-guidance +``` + +## License + +Licensed under either of: + +- Apache License, Version 2.0 ([LICENSE-APACHE](../../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) +- MIT license ([LICENSE-MIT](../../LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. diff --git a/crates/thulp-mcp/README.md b/crates/thulp-mcp/README.md index 5acd064..7ec09da 100644 --- a/crates/thulp-mcp/README.md +++ b/crates/thulp-mcp/README.md @@ -19,14 +19,14 @@ Add to your `Cargo.toml`: ```toml [dependencies] -thulp-mcp = "0.1" +thulp-mcp = "0.2" ``` For Ares server support: ```toml [dependencies] -thulp-mcp = { version = "0.1", features = ["ares"] } +thulp-mcp = { version = "0.2", features = ["ares"] } ``` ## Usage @@ -352,7 +352,7 @@ Enables integration with the Ares MCP server implementation: ```toml [dependencies] -thulp-mcp = { version = "0.1", features = ["ares"] } +thulp-mcp = { version = "0.2", features = ["ares"] } ``` This feature: diff --git a/crates/thulp-registry/README.md b/crates/thulp-registry/README.md new file mode 100644 index 0000000..3a30d0a --- /dev/null +++ b/crates/thulp-registry/README.md @@ -0,0 +1,235 @@ +# thulp-registry + +Async thread-safe tool registry for Thulp. + +## Overview + +This crate provides a registry for managing tool definitions with support for dynamic registration, tagging, and discovery. The registry is designed for concurrent access in async environments. + +## Features + +- **Dynamic Registration**: Register and unregister tools at runtime +- **Thread-Safe**: Concurrent access via `RwLock` for safe multi-threaded use +- **Tool Discovery**: Find tools by name or tag +- **Tagging System**: Organize tools with custom tags +- **Batch Operations**: Register multiple tools at once +- **Async Design**: Built on tokio for async operations + +## Installation + +Add to your `Cargo.toml`: + +```toml +[dependencies] +thulp-registry = "0.2" +``` + +## Usage + +### Creating a Registry + +```rust +use thulp_registry::ToolRegistry; + +let registry = ToolRegistry::new(); +``` + +### Registering Tools + +```rust +use thulp_registry::ToolRegistry; +use thulp_core::{ToolDefinition, Parameter, ParameterType}; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let registry = ToolRegistry::new(); + + // Create a tool definition + let tool = ToolDefinition::builder("read_file") + .description("Read file contents") + .parameter( + Parameter::builder("path") + .param_type(ParameterType::String) + .required(true) + .build() + ) + .build(); + + // Register the tool + registry.register(tool).await?; + + // Check if registered + assert!(registry.contains("read_file").await); + + Ok(()) +} +``` + +### Registering Multiple Tools + +```rust +use thulp_registry::ToolRegistry; +use thulp_core::{ToolDefinition, Parameter, ParameterType}; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let registry = ToolRegistry::new(); + + let tools = vec![ + ToolDefinition::builder("read_file") + .description("Read file") + .build(), + ToolDefinition::builder("write_file") + .description("Write file") + .build(), + ToolDefinition::builder("delete_file") + .description("Delete file") + .build(), + ]; + + registry.register_many(tools).await?; + + assert_eq!(registry.count().await, 3); + + Ok(()) +} +``` + +### Retrieving Tools + +```rust +use thulp_registry::ToolRegistry; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let registry = ToolRegistry::new(); + // ... register tools ... + + // Get specific tool + if let Some(tool) = registry.get("read_file").await? { + println!("Found tool: {}", tool.name); + } + + // List all tools + let tools = registry.list().await?; + for tool in tools { + println!("Tool: {}", tool.name); + } + + Ok(()) +} +``` + +### Tagging Tools + +```rust +use thulp_registry::ToolRegistry; +use thulp_core::ToolDefinition; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let registry = ToolRegistry::new(); + + // Register tools + registry.register(ToolDefinition::builder("read_file").build()).await?; + registry.register(ToolDefinition::builder("write_file").build()).await?; + registry.register(ToolDefinition::builder("http_get").build()).await?; + + // Tag tools by category + registry.tag("read_file", "filesystem").await?; + registry.tag("write_file", "filesystem").await?; + registry.tag("http_get", "network").await?; + + // Find tools by tag + let fs_tools = registry.find_by_tag("filesystem").await?; + assert_eq!(fs_tools.len(), 2); + + let net_tools = registry.find_by_tag("network").await?; + assert_eq!(net_tools.len(), 1); + + Ok(()) +} +``` + +### Unregistering Tools + +```rust +use thulp_registry::ToolRegistry; +use thulp_core::ToolDefinition; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let registry = ToolRegistry::new(); + + registry.register(ToolDefinition::builder("temp_tool").build()).await?; + assert!(registry.contains("temp_tool").await); + + // Remove the tool + let removed = registry.unregister("temp_tool").await?; + assert!(removed.is_some()); + assert!(!registry.contains("temp_tool").await); + + Ok(()) +} +``` + +### Clearing the Registry + +```rust +use thulp_registry::ToolRegistry; + +#[tokio::main] +async fn main() { + let registry = ToolRegistry::new(); + // ... register tools ... + + // Clear all tools + registry.clear().await; + assert_eq!(registry.count().await, 0); +} +``` + +## Thread Safety + +The registry uses `tokio::sync::RwLock` internally, allowing multiple readers or a single writer at any time. All operations are safe to use from multiple async tasks concurrently. + +```rust +use thulp_registry::ToolRegistry; +use std::sync::Arc; + +#[tokio::main] +async fn main() { + let registry = Arc::new(ToolRegistry::new()); + + // Spawn multiple tasks that access the registry + let handles: Vec<_> = (0..10) + .map(|i| { + let reg = registry.clone(); + tokio::spawn(async move { + // Safe concurrent access + let count = reg.count().await; + println!("Task {} sees {} tools", i, count); + }) + }) + .collect(); + + for handle in handles { + handle.await.unwrap(); + } +} +``` + +## Testing + +```bash +cargo test -p thulp-registry +``` + +## License + +Licensed under either of: + +- Apache License, Version 2.0 ([LICENSE-APACHE](../../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) +- MIT license ([LICENSE-MIT](../../LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. From da6123439833d08c8eea2472a36c1728143fe4cc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 15 Jan 2026 08:58:37 +0000 Subject: [PATCH 3/3] Fix CLI README: use positional arguments instead of --args flag Co-authored-by: bkataru <14833123+bkataru@users.noreply.github.com> --- crates/thulp-cli/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/thulp-cli/README.md b/crates/thulp-cli/README.md index 8cbb7b0..310c2ce 100644 --- a/crates/thulp-cli/README.md +++ b/crates/thulp-cli/README.md @@ -57,11 +57,11 @@ thulp tools show read_file --output json ### Validate Tool Arguments ```bash -# Validate with JSON arguments -thulp tools validate read_file --args '{"path": "/etc/hosts"}' +# Validate with JSON arguments (positional argument) +thulp tools validate read_file '{"path": "/etc/hosts"}' # JSON output for scripting -thulp tools validate read_file --args '{}' --output json +thulp tools validate read_file '{}' --output json ``` ### MCP Server Connection (requires `mcp` feature) @@ -77,7 +77,7 @@ thulp mcp connect-stdio myserver /path/to/mcp-server -- --verbose thulp mcp list # Call MCP tool -thulp mcp call search --args '{"query": "test"}' +thulp mcp call search '{"query": "test"}' # Check connection status thulp mcp status