chuk-tool-processor 0.9.1__py3-none-any.whl → 0.9.5__py3-none-any.whl

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.
@@ -176,17 +176,24 @@ class StreamManager:
176
176
  for idx, server_name in enumerate(servers):
177
177
  try:
178
178
  if transport_type == "stdio":
179
- params = await load_config(config_file, server_name)
179
+ params, server_timeout = await load_config(config_file, server_name)
180
+ # Use per-server timeout if specified, otherwise use global default
181
+ effective_timeout = server_timeout if server_timeout is not None else default_timeout
182
+ logger.info(
183
+ f"Server '{server_name}' using timeout: {effective_timeout}s (per-server: {server_timeout}, default: {default_timeout})"
184
+ )
180
185
  # Use initialization_timeout for connection_timeout since subprocess
181
186
  # launch can take time (e.g., uvx downloading packages)
182
187
  transport: MCPBaseTransport = StdioTransport(
183
- params, connection_timeout=initialization_timeout, default_timeout=default_timeout
188
+ params, connection_timeout=initialization_timeout, default_timeout=effective_timeout
184
189
  )
185
190
  elif transport_type == "sse":
186
191
  logger.debug(
187
192
  "Using SSE transport in initialize() - consider using initialize_with_sse() instead"
188
193
  )
189
- params = await load_config(config_file, server_name)
194
+ params, server_timeout = await load_config(config_file, server_name)
195
+ # Use per-server timeout if specified, otherwise use global default
196
+ effective_timeout = server_timeout if server_timeout is not None else default_timeout
190
197
 
191
198
  if isinstance(params, dict) and "url" in params:
192
199
  sse_url = params["url"]
@@ -199,7 +206,7 @@ class StreamManager:
199
206
  logger.debug("No URL configured for SSE transport, using default: %s", sse_url)
200
207
 
201
208
  # Build SSE transport with optional headers
202
- transport_params = {"url": sse_url, "api_key": api_key, "default_timeout": default_timeout}
209
+ transport_params = {"url": sse_url, "api_key": api_key, "default_timeout": effective_timeout}
203
210
  if headers:
204
211
  transport_params["headers"] = headers
205
212
 
@@ -209,7 +216,9 @@ class StreamManager:
209
216
  logger.debug(
210
217
  "Using HTTP Streamable transport in initialize() - consider using initialize_with_http_streamable() instead"
211
218
  )
212
- params = await load_config(config_file, server_name)
219
+ params, server_timeout = await load_config(config_file, server_name)
220
+ # Use per-server timeout if specified, otherwise use global default
221
+ effective_timeout = server_timeout if server_timeout is not None else default_timeout
213
222
 
214
223
  if isinstance(params, dict) and "url" in params:
215
224
  http_url = params["url"]
@@ -227,7 +236,7 @@ class StreamManager:
227
236
  transport_params = {
228
237
  "url": http_url,
229
238
  "api_key": api_key,
230
- "default_timeout": default_timeout,
239
+ "default_timeout": effective_timeout,
231
240
  "session_id": session_id,
232
241
  }
233
242
  # Note: headers not added until HTTPStreamableTransport supports them
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chuk-tool-processor
3
- Version: 0.9.1
3
+ Version: 0.9.5
4
4
  Summary: Async-native framework for registering, discovering, and executing tools referenced in LLM responses
5
5
  Author-email: CHUK Team <chrishayuk@somejunkmailbox.com>
6
6
  Maintainer-email: CHUK Team <chrishayuk@somejunkmailbox.com>
@@ -20,7 +20,7 @@ Classifier: Framework :: AsyncIO
20
20
  Classifier: Typing :: Typed
21
21
  Requires-Python: >=3.11
22
22
  Description-Content-Type: text/markdown
23
- Requires-Dist: chuk-mcp>=0.7.1
23
+ Requires-Dist: chuk-mcp>=0.8
24
24
  Requires-Dist: dotenv>=0.9.9
25
25
  Requires-Dist: psutil>=7.0.0
26
26
  Requires-Dist: pydantic>=2.11.3
@@ -112,6 +112,25 @@ CHUK Tool Processor uses a **composable stack architecture**:
112
112
 
113
113
  Each layer is **optional** and **configurable**. Mix and match what you need.
114
114
 
115
+ ## Compatibility Matrix
116
+
117
+ | Component | Supported Versions | Notes |
118
+ |-----------|-------------------|-------|
119
+ | **Python** | 3.11, 3.12, 3.13 | Python 3.11+ required |
120
+ | **Operating Systems** | macOS, Linux, Windows | All platforms fully supported |
121
+ | **LLM Providers** | OpenAI, Anthropic, Local models | Any LLM that outputs tool calls |
122
+ | **MCP Transports** | HTTP Streamable, STDIO, SSE | All MCP 1.0 transports |
123
+ | **MCP Servers** | Notion, SQLite, Atlassian, Echo, Custom | Any MCP-compliant server |
124
+
125
+ **Tested Configurations:**
126
+ - ✅ macOS 14+ (Apple Silicon & Intel)
127
+ - ✅ Ubuntu 20.04+ / Debian 11+
128
+ - ✅ Windows 10+ (native & WSL2)
129
+ - ✅ Python 3.11.0+, 3.12.0+, 3.13.0+
130
+ - ✅ OpenAI GPT-4, GPT-4 Turbo
131
+ - ✅ Anthropic Claude 3 (Opus, Sonnet, Haiku)
132
+ - ✅ Local models (Ollama, LM Studio)
133
+
115
134
  ## Quick Start
116
135
 
117
136
  ### Installation
@@ -131,6 +150,21 @@ cd chuk-tool-processor
131
150
  uv pip install -e .
132
151
  ```
133
152
 
153
+ ## 60-Second Quick Start
154
+
155
+ **Absolutely minimal example** → See `examples/hello_tool.py`:
156
+
157
+ ```bash
158
+ python examples/hello_tool.py
159
+ ```
160
+
161
+ Single file that demonstrates:
162
+ - Registering a tool
163
+ - Parsing OpenAI & Anthropic formats
164
+ - Executing and getting results
165
+
166
+ Takes 60 seconds to understand, 3 minutes to master.
167
+
134
168
  ### 3-Minute Example
135
169
 
136
170
  Copy-paste this into a file and run it:
@@ -176,16 +210,27 @@ asyncio.run(main())
176
210
  > **Why not just use OpenAI tool calls?**
177
211
  > OpenAI's function calling is great for parsing, but you still need: parsing multiple formats (Anthropic XML, etc.), timeouts, retries, rate limits, caching, subprocess isolation, and connecting to external MCP servers. CHUK Tool Processor **is** that missing middle layer.
178
212
 
213
+ ## Documentation Quick Reference
214
+
215
+ | Document | What It Covers |
216
+ |----------|----------------|
217
+ | 📘 [CONFIGURATION.md](docs/CONFIGURATION.md) | **All config knobs & defaults**: ToolProcessor options, timeouts, retry policy, rate limits, circuit breakers, caching, environment variables |
218
+ | 🚨 [ERRORS.md](docs/ERRORS.md) | **Error taxonomy**: All error codes, exception classes, error details structure, handling patterns, retryability guide |
219
+ | 📊 [OBSERVABILITY.md](docs/OBSERVABILITY.md) | **Metrics & tracing**: OpenTelemetry setup, Prometheus metrics, spans reference, PromQL queries |
220
+ | 🔌 [examples/hello_tool.py](examples/hello_tool.py) | **60-second starter**: Single-file, copy-paste-and-run example |
221
+ | 🎯 [examples/](examples/) | **20+ working examples**: MCP integration, OAuth flows, streaming, production patterns |
222
+
179
223
  ## Choose Your Path
180
224
 
181
225
  | Your Goal | What You Need | Where to Look |
182
226
  |-----------|---------------|---------------|
183
- | ☕ **Just process LLM tool calls** | Basic tool registration + processor | [3-Minute Example](#3-minute-example) |
227
+ | ☕ **Just process LLM tool calls** | Basic tool registration + processor | [60-Second Quick Start](#60-second-quick-start) |
184
228
  | 🔌 **Connect to external tools** | MCP integration (HTTP/STDIO/SSE) | [MCP Integration](#5-mcp-integration-external-tools) |
185
- | 🛡️ **Production deployment** | Timeouts, retries, rate limits, caching | [Production Configuration](#using-the-processor) |
229
+ | 🛡️ **Production deployment** | Timeouts, retries, rate limits, caching | [CONFIGURATION.md](docs/CONFIGURATION.md) |
186
230
  | 🔒 **Run untrusted code safely** | Subprocess isolation strategy | [Subprocess Strategy](#using-subprocess-strategy) |
187
- | 📊 **Monitor and observe** | OpenTelemetry + Prometheus | [Observability](#opentelemetry--prometheus-drop-in-observability) |
231
+ | 📊 **Monitor and observe** | OpenTelemetry + Prometheus | [OBSERVABILITY.md](docs/OBSERVABILITY.md) |
188
232
  | 🌊 **Stream incremental results** | StreamingTool pattern | [StreamingTool](#streamingtool-real-time-results) |
233
+ | 🚨 **Handle errors reliably** | Error codes & taxonomy | [ERRORS.md](docs/ERRORS.md) |
189
234
 
190
235
  ### Real-World Quick Start
191
236
 
@@ -1100,24 +1145,29 @@ asyncio.run(main())
1100
1145
 
1101
1146
  #### OpenTelemetry & Prometheus (Drop-in Observability)
1102
1147
 
1103
- **Why Telemetry Matters**: In production, you need to know *what* your tools are doing, *how long* they take, *when* they fail, and *why*. CHUK Tool Processor provides **enterprise-grade telemetry** that operations teams expect—with zero manual instrumentation.
1104
-
1105
- **One function call. Full observability.**
1148
+ **3-Line Setup:**
1106
1149
 
1107
1150
  ```python
1108
1151
  from chuk_tool_processor.observability import setup_observability
1109
1152
 
1110
- # Enable everything
1111
1153
  setup_observability(
1112
1154
  service_name="my-tool-service",
1113
- enable_tracing=True, # OpenTelemetry distributed tracing
1114
- enable_metrics=True, # Prometheus metrics endpoint
1115
- metrics_port=9090 # HTTP endpoint at :9090/metrics
1155
+ enable_tracing=True, # OpenTelemetry traces
1156
+ enable_metrics=True, # Prometheus metrics at :9090/metrics
1157
+ metrics_port=9090
1116
1158
  )
1117
-
1118
- # Every tool execution is now automatically traced and metered!
1159
+ # That's it! Every tool execution is now automatically traced and metered.
1119
1160
  ```
1120
1161
 
1162
+ **What you get automatically:**
1163
+ - ✅ Distributed traces (Jaeger, Zipkin, any OTLP collector)
1164
+ - ✅ Prometheus metrics (error rate, latency P50/P95/P99, cache hit rate)
1165
+ - ✅ Circuit breaker state monitoring
1166
+ - ✅ Retry attempt tracking
1167
+ - ✅ Zero code changes to your tools
1168
+
1169
+ **Why Telemetry Matters**: In production, you need to know *what* your tools are doing, *how long* they take, *when* they fail, and *why*. CHUK Tool Processor provides **enterprise-grade telemetry** that operations teams expect—with zero manual instrumentation.
1170
+
1121
1171
  **What You Get (Automatically)**
1122
1172
 
1123
1173
  ✅ **Distributed Traces** - Understand exactly what happened in each tool call
@@ -1151,6 +1201,8 @@ pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp prom
1151
1201
  uv pip install chuk-tool-processor --group observability
1152
1202
  ```
1153
1203
 
1204
+ > **⚠️ SRE Note**: Observability packages are **optional**. If not installed, all observability calls are no-ops—your tools run normally without tracing/metrics. Zero crashes, zero warnings. Safe to deploy without observability dependencies.
1205
+
1154
1206
  **Quick Start: See Your Tools in Action**
1155
1207
 
1156
1208
  ```python
@@ -1612,10 +1664,13 @@ async def create_secure_processor():
1612
1664
  Check out the [`examples/`](examples/) directory for complete working examples:
1613
1665
 
1614
1666
  ### Getting Started
1667
+ - **60-second hello**: `examples/hello_tool.py` - Absolute minimal example (copy-paste-run)
1615
1668
  - **Quick start**: `examples/quickstart_demo.py` - Basic tool registration and execution
1616
1669
  - **Execution strategies**: `examples/execution_strategies_demo.py` - InProcess vs Subprocess
1617
1670
  - **Production wrappers**: `examples/wrappers_demo.py` - Caching, retries, rate limiting
1618
1671
  - **Streaming tools**: `examples/streaming_demo.py` - Real-time incremental results
1672
+ - **Streaming tool calls**: `examples/streaming_tool_calls_demo.py` - Handle partial tool calls from streaming LLMs
1673
+ - **Schema helper**: `examples/schema_helper_demo.py` - Auto-generate schemas from typed tools (Pydantic → OpenAI/Anthropic/MCP)
1619
1674
  - **Observability**: `examples/observability_demo.py` - OpenTelemetry + Prometheus integration
1620
1675
 
1621
1676
  ### MCP Integration (Real-World)
@@ -1696,6 +1751,54 @@ A: InProcess is faster (same process), Subprocess is safer (isolated process). U
1696
1751
  - Use directly if you need protocol-level control
1697
1752
  - Use chuk-tool-processor if you want high-level tool execution
1698
1753
 
1754
+ ## Development & Publishing
1755
+
1756
+ ### For Contributors
1757
+
1758
+ Development setup:
1759
+
1760
+ ```bash
1761
+ # Clone repository
1762
+ git clone https://github.com/chrishayuk/chuk-tool-processor.git
1763
+ cd chuk-tool-processor
1764
+
1765
+ # Install development dependencies
1766
+ uv sync --dev
1767
+
1768
+ # Run tests
1769
+ make test
1770
+
1771
+ # Run all quality checks
1772
+ make check
1773
+ ```
1774
+
1775
+ ### For Maintainers: Publishing Releases
1776
+
1777
+ The project uses **fully automated CI/CD** for releases. Publishing is as simple as:
1778
+
1779
+ ```bash
1780
+ # 1. Bump version
1781
+ make bump-patch # or bump-minor, bump-major
1782
+
1783
+ # 2. Commit version change
1784
+ git add pyproject.toml
1785
+ git commit -m "version X.Y.Z"
1786
+ git push
1787
+
1788
+ # 3. Create release (automated)
1789
+ make publish
1790
+ ```
1791
+
1792
+ This will:
1793
+ - Create and push a git tag
1794
+ - Trigger GitHub Actions to create a release with auto-generated changelog
1795
+ - Run tests across all platforms and Python versions
1796
+ - Build and publish to PyPI automatically
1797
+
1798
+ For detailed release documentation, see:
1799
+ - **[RELEASING.md](RELEASING.md)** - Complete release process guide
1800
+ - **[docs/CI-CD.md](docs/CI-CD.md)** - Full CI/CD pipeline documentation
1801
+
1699
1802
  ## Contributing & Support
1700
1803
 
1701
1804
  - **GitHub**: [chrishayuk/chuk-tool-processor](https://github.com/chrishayuk/chuk-tool-processor)
@@ -23,7 +23,7 @@ chuk_tool_processor/mcp/register_mcp_tools.py,sha256=OyHczwVnqhvBZO9g4I0T56EPMvF
23
23
  chuk_tool_processor/mcp/setup_mcp_http_streamable.py,sha256=cXZcaPDYhAZbi92dapHmhbDDnq4Ond8Kj5Igsty2sWM,6478
24
24
  chuk_tool_processor/mcp/setup_mcp_sse.py,sha256=ClGKFtSfDxKQKUcyZY4s5xAgtrTycFSbzxGetdZIM_4,5717
25
25
  chuk_tool_processor/mcp/setup_mcp_stdio.py,sha256=KxCC0BL0C6z5ZHxBzPhWZC9CKrGUACXqx1tkjru-UYI,2922
26
- chuk_tool_processor/mcp/stream_manager.py,sha256=398j65oGvMMwi_EC9qS2EPHXvGefUDJ4IR9Tkg4jaGY,34781
26
+ chuk_tool_processor/mcp/stream_manager.py,sha256=P_Rkb2j-Cq8_WRQfxtFR1Pz12w6xa8IywaDOz4zHkLs,35653
27
27
  chuk_tool_processor/mcp/transport/__init__.py,sha256=od-7f_cYv31_ioZCJu57ozA8IXywMyf-0N4HlM2J_bU,841
28
28
  chuk_tool_processor/mcp/transport/base_transport.py,sha256=rG61TlaignbVZbsqdBS38TnFzTVO666ehKEI0IUAJCM,8675
29
29
  chuk_tool_processor/mcp/transport/http_streamable_transport.py,sha256=j5Rb6vn-cclYthDRCxnn2ZOCosIWBOtDxwRsqLKitEs,27922
@@ -61,7 +61,7 @@ chuk_tool_processor/registry/providers/__init__.py,sha256=iGc_2JzlYJSBRQ6tFbX781
61
61
  chuk_tool_processor/registry/providers/memory.py,sha256=udfboAHH0gRxtnf3GsI3wMshhobJxYnCkMwKjQ_uqkw,5017
62
62
  chuk_tool_processor/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
63
  chuk_tool_processor/utils/validation.py,sha256=jHPO65sB61ynm9P6V3th4pN7j4u0SQhYR-bstj5QjnI,4175
64
- chuk_tool_processor-0.9.1.dist-info/METADATA,sha256=llfoclt8ntrU2odrZhudQkqgh3AIoYazMwON-vEbSRQ,57514
65
- chuk_tool_processor-0.9.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
66
- chuk_tool_processor-0.9.1.dist-info/top_level.txt,sha256=7lTsnuRx4cOW4U2sNJWNxl4ZTt_J1ndkjTbj3pHPY5M,20
67
- chuk_tool_processor-0.9.1.dist-info/RECORD,,
64
+ chuk_tool_processor-0.9.5.dist-info/METADATA,sha256=eUqgZU-WCkJ9880urwpanL8MTwDbvAGJNcUSMoWzWTk,61364
65
+ chuk_tool_processor-0.9.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
66
+ chuk_tool_processor-0.9.5.dist-info/top_level.txt,sha256=7lTsnuRx4cOW4U2sNJWNxl4ZTt_J1ndkjTbj3pHPY5M,20
67
+ chuk_tool_processor-0.9.5.dist-info/RECORD,,