Metadata-Version: 2.4
Name: toolcase
Version: 0.1.0
Summary: Type-safe, extensible tool framework for AI agents with monadic error handling
Author-email: GriffinCanCode <griffincancode@gmail.com>
License:                 ╔══════════════════════════════════════════════════════════════════════════════╗
                        ║                              GRIFFIN LICENSE                                 ║
                        ║                                Version 1.0                                   ║
                        ╚══════════════════════════════════════════════════════════════════════════════╝
        
                                    Copyright (c) 2026 griffin
        
                            Permission is hereby granted, free of charge, to any person 
                            obtaining a copy of this software and associated documentation 
                            files (the "Software"), to deal in the Software without 
                            restriction, including without limitation the rights to use, 
                            modify, merge, publish, distribute, sublicense, and/or sell 
                            copies of the Software, and to permit persons to whom the 
                            Software is furnished to do so, subject to the following 
                            conditions:
        
                        ┌─────────────────────────────────────────────────────────────────────────────┐
                        │                          ATTRIBUTION REQUIREMENT                            │
                        └─────────────────────────────────────────────────────────────────────────────┘
        
                            The name "Griffin" must be prominently included in any work, 
                            derivative work, documentation, or distribution that incorporates, 
                            is based upon, or is derived from the Software, regardless of 
                            the extent of such incorporation or derivation. This includes 
                            but is not limited to:
        
                                            ◆ SOURCE CODE ATTRIBUTION
                                When the Software or any portion thereof is included in 
                                another codebase, repository, or project, the name "Griffin" 
                                must appear in:
                                  • The primary documentation or README file
                                  • Source code comments identifying Griffin as a contributor
                                  • Any copyright notices or attribution sections
        
                                          ◆ BINARY DISTRIBUTION ATTRIBUTION
                                When distributing compiled versions or applications that 
                                incorporate the Software, the name "Griffin" must appear in:
                                  • Application credits or about sections
                                  • Installation documentation
                                  • End user license agreements or terms of service
        
                                           ◆ DERIVATIVE WORKS ATTRIBUTION
                                Any modification, enhancement, or derivative creation based 
                                upon the Software must include "Griffin" in:
                                  • Project naming, descriptions, or documentation
                                  • Credits or acknowledgments sections
                                  • Any public presentations or publications describing the work
        
                                            ◆ TANGENTIAL INCLUSION
                                Even when the Software is used indirectly, as a dependency, 
                                or as a minor component within a larger system, the name 
                                "Griffin" must be included in the project's attribution 
                                documentation.
        
                        ┌─────────────────────────────────────────────────────────────────────────────┐
                        │                    PATENT AND TRADEMARK RESTRICTIONS                        │
                        └─────────────────────────────────────────────────────────────────────────────┘
        
                            No person or entity may obtain patents or trademarks on any 
                            concepts, methods, algorithms, or innovations contained within 
                            or derived from the Software. This restriction applies to:
        
                                          ◇ DIRECT PATENTING PROHIBITION
                                The concepts, processes, methods, and innovations embodied 
                                in the Software are expressly placed in the public domain 
                                for the purpose of patent law and may not be patented by 
                                any party.
        
                                         ◇ DERIVATIVE CONCEPT PROTECTION
                                Any concepts or innovations that are derived from, inspired 
                                by, or substantially similar to those contained in the 
                                Software may not be patented.
        
                                            ◇ TRADEMARK RESTRICTIONS
                                The specific implementations, naming conventions, and 
                                innovative approaches contained in the Software may not be 
                                trademarked for the purpose of preventing others from using 
                                similar approaches.
        
                                                ◇ ENFORCEMENT
                                Any attempt to patent or trademark concepts covered under 
                                this license shall render this license null and void for 
                                the attempting party, and shall constitute a material breach 
                                of this agreement.
        
                        ═══════════════════════════════════════════════════════════════════════════════
        
                            The above copyright notice, this permission notice, and the 
                            attribution requirement shall be included in all copies or 
                            substantial portions of the Software.
        
                            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
                            EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
                            OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
                            NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
                            HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
                            WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
                            FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
                            OTHER DEALINGS IN THE SOFTWARE.
License-File: LICENSE
Keywords: agents,ai,langchain,llm,mcp,model-context-protocol,tools
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: Other/Proprietary License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: beartype>=0.18
Requires-Dist: httpx>=0.27
Requires-Dist: msgpack>=1.0
Requires-Dist: msgspec>=0.18
Requires-Dist: orjson>=3.9
Requires-Dist: pydantic-extra-types>=2.6
Requires-Dist: pydantic-settings>=2.2
Requires-Dist: pydantic>=2.7
Requires-Dist: stamina>=24.3
Requires-Dist: structlog>=24.1
Provides-Extra: all
Requires-Dist: fastmcp>=2.0; extra == 'all'
Requires-Dist: langchain-core>=0.2; extra == 'all'
Requires-Dist: opentelemetry-api>=1.20; extra == 'all'
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.20; extra == 'all'
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.20; extra == 'all'
Requires-Dist: opentelemetry-instrumentation-httpx>=0.42b0; extra == 'all'
Requires-Dist: opentelemetry-sdk>=1.20; extra == 'all'
Requires-Dist: pymemcache>=4.0; extra == 'all'
Requires-Dist: redis>=5.0; extra == 'all'
Requires-Dist: starlette>=0.37; extra == 'all'
Requires-Dist: uvicorn>=0.29; extra == 'all'
Provides-Extra: dev
Requires-Dist: hypothesis>=6.100; extra == 'dev'
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Provides-Extra: http
Requires-Dist: starlette>=0.37; extra == 'http'
Requires-Dist: uvicorn>=0.29; extra == 'http'
Provides-Extra: langchain
Requires-Dist: langchain-core>=0.2; extra == 'langchain'
Provides-Extra: mcp
Requires-Dist: fastmcp>=2.0; extra == 'mcp'
Provides-Extra: memcached
Requires-Dist: pymemcache>=4.0; extra == 'memcached'
Provides-Extra: otel
Requires-Dist: opentelemetry-api>=1.20; extra == 'otel'
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.20; extra == 'otel'
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.20; extra == 'otel'
Requires-Dist: opentelemetry-instrumentation-httpx>=0.42b0; extra == 'otel'
Requires-Dist: opentelemetry-sdk>=1.20; extra == 'otel'
Provides-Extra: redis
Requires-Dist: redis>=5.0; extra == 'redis'
Description-Content-Type: text/markdown

# Toolcase

Type-safe, extensible tool framework for AI agents.

## Features

- **Async-first** with sync compatibility
- **Type-safe parameters** via Pydantic generics
- **Monadic error handling** with `Result[T, E]` types
- **Multi-framework converters** (OpenAI, Anthropic, Google)
- **MCP protocol & HTTP server** for Cursor/Claude Desktop
- **Middleware pipeline** (logging, retry, timeout, rate limiting, circuit breaker)
- **Agentic primitives** (router, fallback, race, gate, escalation)
- **Structured concurrency** with TaskGroup and CancelScope
- **Distributed tracing** (OTLP, Datadog, Honeycomb, Zipkin)
- **Caching** with TTL (memory, Redis, Memcached)
- **Dependency injection** with scoped lifecycle
- **Streaming** with SSE, WebSocket, JSON Lines adapters

## Installation

```bash
pip install toolcase

# Optional integrations
pip install toolcase[mcp]        # MCP protocol (Cursor, Claude Desktop)
pip install toolcase[http]       # HTTP REST server
pip install toolcase[langchain]  # LangChain tools
pip install toolcase[redis]      # Redis cache backend
pip install toolcase[otel]       # OpenTelemetry exporters
pip install toolcase[all]        # Everything
```

## Quick Start

```python
from toolcase import tool, init_tools

@tool(description="Search the web")
async def search(query: str, limit: int = 5) -> str:
    return f"Found {limit} results for: {query}"

registry = init_tools(search)  # Registers discovery tool + your tools
result = await registry.execute("search", {"query": "python", "limit": 3})
```

### Class-Based Tools

```python
from pydantic import BaseModel, Field
from toolcase import BaseTool, ToolMetadata

class SearchParams(BaseModel):
    query: str = Field(..., description="Search query")
    limit: int = Field(default=5, ge=1, le=20)

class SearchTool(BaseTool[SearchParams]):
    metadata = ToolMetadata(name="search", description="Search the web", category="search")
    params_schema = SearchParams

    async def _async_run(self, params: SearchParams) -> str:
        return f"Found {params.limit} results for: {params.query}"
```

## Core Concepts

### Middleware Pipeline

```python
from toolcase import LoggingMiddleware, RetryMiddleware, TimeoutMiddleware

registry.use(LoggingMiddleware())
registry.use(RetryMiddleware(max_retries=3))
registry.use(TimeoutMiddleware(30.0))
```

### Monadic Error Handling

```python
from toolcase import Ok, Err, Result, try_tool_operation

def _run_result(self, params) -> Result[str, ToolError]:
    return (
        self._validate(params)
        .flat_map(lambda p: self._fetch(p))
        .map(lambda d: self._format(d))
    )

# Auto-wrap exceptions
result = try_tool_operation("my_tool", lambda: risky_call())
match result:
    case Ok(value): print(value)
    case Err(error): print(error.message)
```

See [docs/MONADIC_ERRORS.md](docs/MONADIC_ERRORS.md) for complete guide.

### Agentic Composition

```python
from toolcase import router, fallback, race, gate, Route

smart_search = router(Route(lambda p: "code" in p["query"], code_search), default=web_search)
resilient = fallback(primary_api, backup_api, cache)  # Try until success
fastest = race(api_a, api_b, timeout=5.0)             # First success wins
premium = gate(lambda ctx: ctx.get("is_premium"), expensive_tool)
```

### Multi-Framework Export

```python
from toolcase.foundation.formats import to_openai, to_anthropic, to_google

openai_tools = to_openai(registry)      # OpenAI function calling
anthropic_tools = to_anthropic(registry) # Anthropic tool_use
gemini_tools = to_google(registry)       # Google Gemini
```

### MCP & HTTP Server

```python
from toolcase.ext.mcp import serve_mcp, serve_http

serve_mcp(registry, transport="sse", port=8080)  # Cursor, Claude Desktop
serve_http(registry, port=8000)                   # REST API
```

### Dependency Injection

```python
from toolcase import Container, Scope

container = Container()
container.provide("db", lambda: Database(), Scope.SINGLETON)
container.provide("http", lambda: httpx.AsyncClient(), Scope.SCOPED)

async with container.scope() as ctx:
    db = await container.resolve("db", ctx)
```

### Batch Execution

```python
from toolcase import BatchConfig

params_list = [{"query": q} for q in ["python", "rust", "go"]]
results = await tool.batch_run(params_list, BatchConfig(concurrency=5))
print(f"Success: {results.success_rate:.0%}")
```

### Streaming

```python
from toolcase import sse_adapter

@tool(description="Stream response", streaming=True)
async def stream_search(query: str):
    for i in range(10):
        yield f"Result {i} for {query}"

async for event in sse_adapter(stream_search.stream({"query": "test"})):
    print(event)
```

### Observability

```python
from toolcase import configure_tracing, configure_logging, TracingMiddleware

configure_tracing(exporter="otlp", endpoint="http://localhost:4317")
configure_logging(level="INFO", json=True)
registry.use(TracingMiddleware())
```

### Testing

```python
from toolcase import ToolTestCase, mock_tool

class TestSearch(ToolTestCase):
    async def test_search(self):
        tool = mock_tool("search", return_value="mocked")
        result = await tool.run({"query": "test"})
        self.assert_success(result)
```

### Settings & Environment

```python
from toolcase import get_settings, load_env

load_env()  # Load .env files
settings = get_settings()
print(settings.cache.ttl, settings.retry.max_retries)
```

## CLI Help

```bash
toolcase help              # List topics
toolcase help tool         # Tool creation
toolcase help middleware   # Middleware pipeline
toolcase help agents       # Agentic patterns
toolcase help mcp          # MCP/HTTP server
toolcase help result       # Monadic errors
```

## API Reference

### Core
`BaseTool[T]` · `ToolMetadata` · `ToolCapabilities` · `@tool` · `init_tools`

### Errors
`Result[T, E]` · `Ok` · `Err` · `ErrorCode` · `ToolError` · `try_tool_operation`

### Runtime
`Middleware` · `compose` · `pipeline` · `parallel` · `streaming_pipeline`

### Agents
`router` · `fallback` · `race` · `gate` · `retry_with_escalation`

### Concurrency
`TaskGroup` · `CancelScope` · `Lock` · `Semaphore` · `run_sync`

### Observability
`configure_tracing` · `configure_logging` · `TracingMiddleware` · `Span`

### IO
`ToolCache` · `MemoryCache` · `StreamChunk` · `StreamEvent` · `BatchConfig`

## License

Griffin License - Made by GriffinCanCode

See [LICENSE](LICENSE) for full terms.
