chuk-tool-processor 0.13__tar.gz → 0.15__tar.gz

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 (92) hide show
  1. chuk_tool_processor-0.15/PKG-INFO +533 -0
  2. chuk_tool_processor-0.15/README.md +501 -0
  3. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/pyproject.toml +1 -1
  4. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/__init__.py +51 -2
  5. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/core/__init__.py +16 -0
  6. chuk_tool_processor-0.15/src/chuk_tool_processor/core/context.py +439 -0
  7. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/core/processor.py +94 -12
  8. chuk_tool_processor-0.15/src/chuk_tool_processor/execution/__init__.py +23 -0
  9. chuk_tool_processor-0.15/src/chuk_tool_processor/execution/bulkhead.py +520 -0
  10. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/execution/strategies/inprocess_strategy.py +51 -15
  11. chuk_tool_processor-0.15/src/chuk_tool_processor/mcp/__init__.py +93 -0
  12. chuk_tool_processor-0.15/src/chuk_tool_processor/mcp/middleware.py +490 -0
  13. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/mcp/stream_manager.py +104 -3
  14. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/mcp/transport/http_streamable_transport.py +0 -1
  15. chuk_tool_processor-0.15/src/chuk_tool_processor/models/return_order.py +19 -0
  16. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/models/tool_result.py +2 -0
  17. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/registry/__init__.py +2 -1
  18. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/registry/decorators.py +39 -12
  19. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/registry/provider.py +68 -0
  20. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/registry/providers/memory.py +21 -3
  21. chuk_tool_processor-0.15/src/chuk_tool_processor/scheduling/__init__.py +48 -0
  22. chuk_tool_processor-0.15/src/chuk_tool_processor/scheduling/greedy_dag.py +473 -0
  23. chuk_tool_processor-0.15/src/chuk_tool_processor/scheduling/policy.py +66 -0
  24. chuk_tool_processor-0.15/src/chuk_tool_processor/scheduling/types.py +220 -0
  25. chuk_tool_processor-0.15/src/chuk_tool_processor.egg-info/PKG-INFO +533 -0
  26. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor.egg-info/SOURCES.txt +12 -1
  27. chuk_tool_processor-0.15/tests/test_bulkhead.py +498 -0
  28. chuk_tool_processor-0.15/tests/test_execution_context.py +354 -0
  29. chuk_tool_processor-0.15/tests/test_scoped_registry.py +245 -0
  30. chuk_tool_processor-0.13/PKG-INFO +0 -2727
  31. chuk_tool_processor-0.13/README.md +0 -2695
  32. chuk_tool_processor-0.13/src/chuk_tool_processor/execution/__init__.py +0 -6
  33. chuk_tool_processor-0.13/src/chuk_tool_processor/mcp/__init__.py +0 -34
  34. chuk_tool_processor-0.13/src/chuk_tool_processor.egg-info/PKG-INFO +0 -2727
  35. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/setup.cfg +0 -0
  36. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/core/exceptions.py +0 -0
  37. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/execution/code_sandbox.py +0 -0
  38. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/execution/strategies/__init__.py +0 -0
  39. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/execution/strategies/subprocess_strategy.py +0 -0
  40. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/execution/tool_executor.py +0 -0
  41. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/execution/wrappers/__init__.py +0 -0
  42. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/execution/wrappers/caching.py +0 -0
  43. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/execution/wrappers/circuit_breaker.py +0 -0
  44. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/execution/wrappers/rate_limiting.py +0 -0
  45. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/execution/wrappers/retry.py +0 -0
  46. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/logging/__init__.py +0 -0
  47. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/logging/context.py +0 -0
  48. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/logging/formatter.py +0 -0
  49. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/logging/helpers.py +0 -0
  50. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/logging/metrics.py +0 -0
  51. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/mcp/mcp_tool.py +0 -0
  52. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/mcp/models.py +0 -0
  53. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/mcp/register_mcp_tools.py +0 -0
  54. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/mcp/setup_mcp_http_streamable.py +0 -0
  55. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/mcp/setup_mcp_sse.py +0 -0
  56. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/mcp/setup_mcp_stdio.py +0 -0
  57. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/mcp/transport/__init__.py +0 -0
  58. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/mcp/transport/base_transport.py +0 -0
  59. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/mcp/transport/models.py +0 -0
  60. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/mcp/transport/sse_transport.py +0 -0
  61. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/mcp/transport/stdio_transport.py +0 -0
  62. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/models/__init__.py +0 -0
  63. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/models/execution_strategy.py +0 -0
  64. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/models/streaming_tool.py +0 -0
  65. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/models/tool_call.py +0 -0
  66. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/models/tool_export_mixin.py +0 -0
  67. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/models/tool_spec.py +0 -0
  68. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/models/validated_tool.py +0 -0
  69. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/observability/__init__.py +0 -0
  70. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/observability/metrics.py +0 -0
  71. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/observability/setup.py +0 -0
  72. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/observability/tracing.py +0 -0
  73. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/plugins/__init__.py +0 -0
  74. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/plugins/discovery.py +0 -0
  75. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/plugins/parsers/__init__.py +0 -0
  76. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/plugins/parsers/base.py +0 -0
  77. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/plugins/parsers/function_call_tool.py +0 -0
  78. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/plugins/parsers/json_tool.py +0 -0
  79. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/plugins/parsers/openai_tool.py +0 -0
  80. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/plugins/parsers/xml_tool.py +0 -0
  81. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/py.typed +0 -0
  82. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/registry/auto_register.py +0 -0
  83. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/registry/interface.py +0 -0
  84. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/registry/metadata.py +0 -0
  85. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/registry/providers/__init__.py +0 -0
  86. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/registry/tool_export.py +0 -0
  87. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/utils/__init__.py +0 -0
  88. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/utils/fast_json.py +0 -0
  89. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor/utils/validation.py +0 -0
  90. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor.egg-info/dependency_links.txt +0 -0
  91. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor.egg-info/requires.txt +0 -0
  92. {chuk_tool_processor-0.13 → chuk_tool_processor-0.15}/src/chuk_tool_processor.egg-info/top_level.txt +0 -0
@@ -0,0 +1,533 @@
1
+ Metadata-Version: 2.4
2
+ Name: chuk-tool-processor
3
+ Version: 0.15
4
+ Summary: Async-native framework for registering, discovering, and executing tools referenced in LLM responses
5
+ Author-email: CHUK Team <chrishayuk@somejunkmailbox.com>
6
+ Maintainer-email: CHUK Team <chrishayuk@somejunkmailbox.com>
7
+ License: MIT
8
+ Keywords: llm,tools,async,ai,openai,mcp,model-context-protocol,tool-calling,function-calling
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
19
+ Classifier: Framework :: AsyncIO
20
+ Classifier: Typing :: Typed
21
+ Requires-Python: >=3.11
22
+ Description-Content-Type: text/markdown
23
+ Requires-Dist: chuk-mcp>=0.9
24
+ Requires-Dist: dotenv>=0.9.9
25
+ Requires-Dist: psutil>=7.0.0
26
+ Requires-Dist: pydantic>=2.11.3
27
+ Requires-Dist: uuid>=1.30
28
+ Provides-Extra: fast-json
29
+ Requires-Dist: orjson<4,>=3.10.0; extra == "fast-json"
30
+ Provides-Extra: full
31
+ Requires-Dist: orjson<4,>=3.10.0; extra == "full"
32
+
33
+ # CHUK Tool Processor — A Tool Execution Runtime for AI Systems
34
+
35
+ [![PyPI](https://img.shields.io/pypi/v/chuk-tool-processor.svg)](https://pypi.org/project/chuk-tool-processor/)
36
+ [![Python](https://img.shields.io/pypi/pyversions/chuk-tool-processor.svg)](https://pypi.org/project/chuk-tool-processor/)
37
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
38
+ [![Type Checked](https://img.shields.io/badge/type%20checked-PEP%20561-blue.svg)](https://www.python.org/dev/peps/pep-0561/)
39
+ [![Wheels](https://img.shields.io/badge/wheels-macOS%20%7C%20Linux%20%7C%20Windows-blue.svg)](https://pypi.org/project/chuk-tool-processor/)
40
+ [![OpenTelemetry](https://img.shields.io/badge/observability-OpenTelemetry%20%7C%20Prometheus-blue.svg)](docs/OBSERVABILITY.md)
41
+
42
+ **Reliable tool execution for LLMs — timeouts, retries, caching, rate limits, circuit breakers, and MCP integration — in one composable layer.**
43
+
44
+ ---
45
+
46
+ ## The Missing Runtime Layer
47
+
48
+ LLMs are good at *deciding which tools to call*. The hard part is **executing** those tools reliably.
49
+
50
+ **CHUK Tool Processor** is a **tool execution runtime** — it doesn't plan workflows or decide which tools to call. It executes tool calls reliably, under constraints, as directed by higher-level planners (your agent, LangChain, LlamaIndex, or a custom orchestrator).
51
+
52
+ **What it does:**
53
+ - Parses tool calls from any model (Anthropic XML, OpenAI `tool_calls`, JSON)
54
+ - Executes them with **timeouts, retries, caching, rate limits, circuit breaker, observability**
55
+ - Runs tools locally, in **isolated subprocesses**, or **remote via MCP**
56
+
57
+ Works with OpenAI, Anthropic, local models (Ollama/MLX/vLLM), and any framework.
58
+
59
+ ---
60
+
61
+ ## Architecture
62
+
63
+ ```
64
+ LLM Output
65
+
66
+ CHUK Tool Processor
67
+
68
+ ┌──────────────┬────────────────────┐
69
+ │ Local Tools │ Remote Tools (MCP) │
70
+ └──────────────┴────────────────────┘
71
+ ```
72
+
73
+ **How it works internally:**
74
+
75
+ ```
76
+ LLM Output
77
+
78
+ Parsers (XML / OpenAI / JSON)
79
+
80
+ ┌─────────────────────────────┐
81
+ │ Execution Middleware │
82
+ │ (Applied in this order) │
83
+ │ • Cache │
84
+ │ • Rate Limit │
85
+ │ • Retry (with backoff) │
86
+ │ • Circuit Breaker │
87
+ │ • Bulkhead │
88
+ └─────────────────────────────┘
89
+
90
+ Execution Strategy
91
+ ┌──────────────────────┐
92
+ │ • InProcess │ ← Fast, trusted
93
+ │ • Isolated/Subprocess│ ← Safe, untrusted
94
+ │ • Remote via MCP │ ← Distributed
95
+ └──────────────────────┘
96
+ ```
97
+
98
+ ---
99
+
100
+ ## Quick Start
101
+
102
+ ### Installation
103
+
104
+ ```bash
105
+ pip install chuk-tool-processor
106
+
107
+ # Or with uv (recommended)
108
+ uv pip install chuk-tool-processor
109
+ ```
110
+
111
+ ### 60-Second Example
112
+
113
+ ```python
114
+ import asyncio
115
+ from chuk_tool_processor import ToolProcessor, create_registry
116
+
117
+ class Calculator:
118
+ async def execute(self, operation: str, a: float, b: float) -> dict:
119
+ ops = {"add": a + b, "multiply": a * b, "subtract": a - b}
120
+ return {"result": ops.get(operation, 0)}
121
+
122
+ async def main():
123
+ registry = create_registry()
124
+ await registry.register_tool(Calculator, name="math.calculator") # Dotted name → namespace="math"
125
+
126
+ async with ToolProcessor(registry=registry, enable_caching=True, enable_retries=True) as p:
127
+ # Works with OpenAI, Anthropic, or JSON formats
128
+ result = await p.process('<tool name="math.calculator" args=\'{"operation": "multiply", "a": 15, "b": 23}\'/>')
129
+ print(result[0].result) # {'result': 345}
130
+
131
+ asyncio.run(main())
132
+ ```
133
+
134
+ **That's it.** You now have production-ready tool execution with timeouts, retries, and caching.
135
+
136
+ ### Dotted Names for Namespacing
137
+
138
+ Dotted names are auto-parsed into namespace and tool name:
139
+
140
+ ```python
141
+ # These are equivalent:
142
+ await registry.register_tool(FetchUser, name="web.fetch_user") # Auto-parsed
143
+ await registry.register_tool(FetchUser, name="fetch_user", namespace="web") # Explicit
144
+
145
+ # Call using the full dotted name
146
+ result = await processor.process([{"tool": "web.fetch_user", "arguments": {"user_id": "123"}}])
147
+ ```
148
+
149
+ ### Works with Any LLM Format
150
+
151
+ ```python
152
+ # Anthropic XML format
153
+ anthropic_output = '<tool name="search" args=\'{"query": "Python"}\'/>'
154
+
155
+ # OpenAI tool_calls format
156
+ openai_output = {
157
+ "tool_calls": [{
158
+ "type": "function",
159
+ "function": {"name": "search", "arguments": '{"query": "Python"}'}
160
+ }]
161
+ }
162
+
163
+ # Direct JSON
164
+ json_output = [{"tool": "search", "arguments": {"query": "Python"}}]
165
+
166
+ # All work identically
167
+ results = await processor.process(anthropic_output)
168
+ results = await processor.process(openai_output)
169
+ results = await processor.process(json_output)
170
+ ```
171
+
172
+ ---
173
+
174
+ ## Key Features
175
+
176
+ ### Production Reliability
177
+
178
+ | Feature | Description |
179
+ |---------|-------------|
180
+ | **Timeouts** | Every tool execution has proper timeout handling |
181
+ | **Retries** | Automatic retry with exponential backoff and jitter |
182
+ | **Rate Limiting** | Global and per-tool rate limits with sliding windows |
183
+ | **Caching** | Result caching with TTL and SHA256-based idempotency keys |
184
+ | **Circuit Breakers** | Prevent cascading failures with automatic recovery |
185
+
186
+ ### Multi-Tenant & Isolation
187
+
188
+ | Feature | Description |
189
+ |---------|-------------|
190
+ | **Bulkheads** | Per-tool/namespace concurrency limits to prevent resource starvation |
191
+ | **Pattern Bulkheads** | Glob patterns like `"db.*": 3` for grouped concurrency limits |
192
+ | **Scoped Registries** | Isolated registries for multi-tenant apps and testing |
193
+ | **ExecutionContext** | Request-scoped metadata propagation (user, tenant, tracing, deadlines) |
194
+ | **Isolated Strategy** | Subprocess execution for untrusted code (zero crash blast radius) |
195
+
196
+ ### Advanced Scheduling
197
+
198
+ | Feature | Description |
199
+ |---------|-------------|
200
+ | **Return Order** | Choose completion order (fast first) or submission order (deterministic) |
201
+ | **SchedulerPolicy** | DAG-based scheduling with dependencies, deadlines, pool limits |
202
+ | **GreedyDagScheduler** | Built-in scheduler with topological sort and deadline-aware skipping |
203
+
204
+ ### Integration & Observability
205
+
206
+ | Feature | Description |
207
+ |---------|-------------|
208
+ | **Multi-Format Parsing** | XML (Anthropic), OpenAI `tool_calls`, JSON — all work automatically |
209
+ | **MCP Integration** | Connect to remote tools via HTTP Streamable, STDIO, SSE |
210
+ | **OpenTelemetry** | Distributed tracing with automatic span creation |
211
+ | **Prometheus** | Metrics for error rates, latency, cache hits, circuit breaker state |
212
+ | **Type Safety** | PEP 561 compliant with full mypy support |
213
+
214
+ ---
215
+
216
+ ## Production Configuration
217
+
218
+ ```python
219
+ async with ToolProcessor(
220
+ # Execution settings
221
+ default_timeout=30.0,
222
+ max_concurrency=20,
223
+
224
+ # Reliability features
225
+ enable_caching=True,
226
+ cache_ttl=600,
227
+ enable_rate_limiting=True,
228
+ global_rate_limit=100,
229
+ tool_rate_limits={"expensive_api": (5, 60)}, # 5 req/min
230
+ enable_retries=True,
231
+ max_retries=3,
232
+ enable_circuit_breaker=True,
233
+ circuit_breaker_threshold=5,
234
+
235
+ # Multi-tenant isolation
236
+ enable_bulkhead=True,
237
+ bulkhead_config=BulkheadConfig(
238
+ default_limit=10,
239
+ tool_limits={"slow_api": 2},
240
+ patterns={"db.*": 3, "mcp.notion.*": 2}, # Pattern-based limits
241
+ ),
242
+ ) as processor:
243
+ # Execute with request context
244
+ ctx = ExecutionContext(
245
+ request_id="req-123",
246
+ user_id="user-456",
247
+ tenant_id="acme-corp",
248
+ )
249
+ results = await processor.process(llm_output, context=ctx)
250
+ ```
251
+
252
+ ---
253
+
254
+ ## Return Order & Scheduling
255
+
256
+ Control how results are returned and plan complex execution graphs:
257
+
258
+ ```python
259
+ from chuk_tool_processor import ToolProcessor, ReturnOrder
260
+
261
+ async with ToolProcessor() as processor:
262
+ # Results return as tools complete (fast tools first) - default
263
+ results = await processor.process(calls, return_order="completion")
264
+
265
+ # Results return in submission order (deterministic)
266
+ results = await processor.process(calls, return_order="submission")
267
+ ```
268
+
269
+ ### DAG Scheduling with Dependencies
270
+
271
+ ```python
272
+ from chuk_tool_processor import (
273
+ GreedyDagScheduler,
274
+ SchedulingConstraints,
275
+ ToolCallSpec,
276
+ ToolMetadata,
277
+ )
278
+
279
+ scheduler = GreedyDagScheduler()
280
+
281
+ # Define calls with dependencies
282
+ calls = [
283
+ ToolCallSpec(call_id="fetch", tool_name="api.fetch",
284
+ metadata=ToolMetadata(pool="web", est_ms=300)),
285
+ ToolCallSpec(call_id="transform", tool_name="compute.transform",
286
+ depends_on=("fetch",)),
287
+ ToolCallSpec(call_id="store", tool_name="db.write",
288
+ depends_on=("transform",)),
289
+ ]
290
+
291
+ # Plan execution with constraints
292
+ constraints = SchedulingConstraints(
293
+ deadline_ms=5000,
294
+ pool_limits={"web": 2, "db": 1},
295
+ )
296
+ plan = scheduler.plan(calls, constraints)
297
+
298
+ # plan.stages: (('fetch',), ('transform',), ('store',))
299
+ # plan.skip: () or low-priority calls that would miss deadline
300
+ ```
301
+
302
+ ---
303
+
304
+ ## MCP Integration
305
+
306
+ Connect to remote tool servers using the [Model Context Protocol](https://modelcontextprotocol.io):
307
+
308
+ ```python
309
+ from chuk_tool_processor.mcp import setup_mcp_http_streamable
310
+
311
+ # Cloud services (Notion, etc.)
312
+ processor, manager = await setup_mcp_http_streamable(
313
+ servers=[{
314
+ "name": "notion",
315
+ "url": "https://mcp.notion.com/mcp",
316
+ "headers": {"Authorization": f"Bearer {token}"}
317
+ }],
318
+ namespace="notion",
319
+ enable_caching=True,
320
+ enable_retries=True
321
+ )
322
+
323
+ # Use remote tools
324
+ results = await processor.process(
325
+ '<tool name="notion.search_pages" args=\'{"query": "docs"}\'/>'
326
+ )
327
+ ```
328
+
329
+ **Transport Options:**
330
+
331
+ | Transport | Use Case | Example |
332
+ |-----------|----------|---------|
333
+ | **HTTP Streamable** | Cloud SaaS with OAuth | Notion, custom APIs |
334
+ | **STDIO** | Local tools, databases | SQLite, file systems |
335
+ | **SSE** | Legacy MCP servers | Atlassian |
336
+
337
+ See [MCP_INTEGRATION.md](docs/MCP_INTEGRATION.md) for complete examples with OAuth token refresh.
338
+
339
+ ### MCP Middleware Stack
340
+
341
+ For production deployments, wrap MCP connections with resilience middleware:
342
+
343
+ ```python
344
+ from chuk_tool_processor.mcp.middleware import (
345
+ MiddlewareConfig,
346
+ MiddlewareStack,
347
+ RetrySettings,
348
+ CircuitBreakerSettings,
349
+ RateLimitSettings,
350
+ )
351
+
352
+ # Configure middleware layers
353
+ config = MiddlewareConfig(
354
+ retry=RetrySettings(max_retries=3, base_delay=1.0),
355
+ circuit_breaker=CircuitBreakerSettings(failure_threshold=5),
356
+ rate_limiting=RateLimitSettings(enabled=True, global_limit=100),
357
+ )
358
+
359
+ # Wrap StreamManager with middleware
360
+ middleware = MiddlewareStack(stream_manager, config=config)
361
+
362
+ # Execute with automatic retry, circuit breaking, and rate limiting
363
+ result = await middleware.call_tool("notion.search", {"query": "docs"})
364
+ ```
365
+
366
+ ---
367
+
368
+ ## Observability
369
+
370
+ One-line setup for production monitoring:
371
+
372
+ ```python
373
+ from chuk_tool_processor.observability import setup_observability
374
+
375
+ setup_observability(
376
+ service_name="my-tool-service",
377
+ enable_tracing=True, # → OpenTelemetry traces
378
+ enable_metrics=True, # → Prometheus metrics at :9090/metrics
379
+ metrics_port=9090
380
+ )
381
+ # Every tool execution is now automatically traced and metered
382
+ ```
383
+
384
+ **What you get:**
385
+ - Distributed traces (Jaeger, Zipkin, any OTLP collector)
386
+ - Prometheus metrics (error rate, latency P50/P95/P99, cache hit rate)
387
+ - Circuit breaker state monitoring
388
+ - Zero code changes to your tools
389
+
390
+ See [OBSERVABILITY.md](docs/OBSERVABILITY.md) for complete setup guide.
391
+
392
+ ---
393
+
394
+ ## Documentation
395
+
396
+ | Document | Description |
397
+ |----------|-------------|
398
+ | [**GETTING_STARTED.md**](docs/GETTING_STARTED.md) | Creating tools, using the processor, ValidatedTool, StreamingTool |
399
+ | [**CORE_CONCEPTS.md**](docs/CORE_CONCEPTS.md) | Registry, strategies, wrappers, parsers, MCP overview |
400
+ | [**PRODUCTION_PATTERNS.md**](docs/PRODUCTION_PATTERNS.md) | Bulkheads, scoped registries, ExecutionContext, parallel execution |
401
+ | [**MCP_INTEGRATION.md**](docs/MCP_INTEGRATION.md) | HTTP Streamable, STDIO, SSE, OAuth, Middleware Stack |
402
+ | [**ADVANCED_TOPICS.md**](docs/ADVANCED_TOPICS.md) | Deferred loading, code sandbox, isolated strategy, testing |
403
+ | [**CONFIGURATION.md**](docs/CONFIGURATION.md) | All config options and environment variables |
404
+ | [**OBSERVABILITY.md**](docs/OBSERVABILITY.md) | OpenTelemetry, Prometheus, metrics reference |
405
+ | [**ERRORS.md**](docs/ERRORS.md) | Error codes and handling patterns |
406
+
407
+ ---
408
+
409
+ ## Examples
410
+
411
+ ```bash
412
+ # Getting started
413
+ python examples/01_getting_started/hello_tool.py
414
+
415
+ # Hero demo: 8 tools, 5-second deadline, 3 pools (DAG + bulkheads + context)
416
+ python examples/02_production_features/hero_runtime_demo.py
417
+
418
+ # Production patterns (bulkheads, context, scoped registries)
419
+ python examples/02_production_features/production_patterns_demo.py
420
+
421
+ # Runtime features (return order, pattern bulkheads, scheduling)
422
+ python examples/02_production_features/runtime_features_demo.py
423
+
424
+ # Observability demo
425
+ python examples/02_production_features/observability_demo.py
426
+
427
+ # MCP integration
428
+ python examples/04_mcp_integration/stdio_echo.py
429
+ python examples/04_mcp_integration/notion_oauth.py
430
+ python examples/04_mcp_integration/middleware_demo.py
431
+ ```
432
+
433
+ See [examples/](examples/) for 20+ working examples.
434
+
435
+ ---
436
+
437
+ ## Compatibility
438
+
439
+ | Component | Supported |
440
+ |-----------|-----------|
441
+ | **Python** | 3.11, 3.12, 3.13 |
442
+ | **Platforms** | macOS, Linux, Windows |
443
+ | **LLM Providers** | OpenAI, Anthropic, Local models (Ollama, MLX, vLLM) |
444
+ | **MCP Transports** | HTTP Streamable, STDIO, SSE |
445
+ | **MCP Spec** | 2025-11-25, 2025-06-18, 2025-03-26 |
446
+
447
+ ---
448
+
449
+ ## Installation Options
450
+
451
+ ```bash
452
+ # Core package
453
+ pip install chuk-tool-processor
454
+
455
+ # With observability (OpenTelemetry + Prometheus)
456
+ pip install chuk-tool-processor[observability]
457
+
458
+ # With MCP support
459
+ pip install chuk-tool-processor[mcp]
460
+
461
+ # With fast JSON (2-3x faster with orjson)
462
+ pip install chuk-tool-processor[fast-json]
463
+
464
+ # All extras
465
+ pip install chuk-tool-processor[all]
466
+ ```
467
+
468
+ ---
469
+
470
+ ## When to Use This
471
+
472
+ **Use CHUK Tool Processor when:**
473
+ - Your LLM calls tools or APIs
474
+ - You need retries, timeouts, caching, or rate limits
475
+ - You need to run untrusted tools safely
476
+ - Your tools are local or remote (MCP)
477
+ - You need multi-tenant isolation
478
+ - You want production-grade observability
479
+
480
+ **Don't use this if:**
481
+ - You want an agent framework (this is the execution runtime, not the agent)
482
+ - You want conversation flow/memory orchestration
483
+ - You need a planner to decide *which* tools to call
484
+
485
+ ### The Seam: Runtime vs Planner
486
+
487
+ CHUK Tool Processor deliberately does not plan workflows or decide which tools to call. It executes tool calls reliably, under constraints, as directed by higher-level planners.
488
+
489
+ ```
490
+ ┌─────────────────────────────────────────────────────┐
491
+ │ Your Agent / LangChain / LlamaIndex / Custom │ ← Decides WHICH tools
492
+ └─────────────────────────────────────────────────────┘
493
+
494
+ ┌─────────────────────────────────────────────────────┐
495
+ │ CHUK Tool Processor │ ← Executes tools RELIABLY
496
+ │ (timeouts, retries, caching, rate limits, etc.) │
497
+ └─────────────────────────────────────────────────────┘
498
+
499
+ ┌─────────────────────────────────────────────────────┐
500
+ │ Local Tools / MCP Servers │ ← Does the actual work
501
+ └─────────────────────────────────────────────────────┘
502
+ ```
503
+
504
+ This separation means you can swap planners without changing execution infrastructure, and vice versa.
505
+
506
+ ---
507
+
508
+ ## Contributing
509
+
510
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and guidelines.
511
+
512
+ ```bash
513
+ # Development setup
514
+ git clone https://github.com/chrishayuk/chuk-tool-processor.git
515
+ cd chuk-tool-processor
516
+ uv pip install -e ".[dev]"
517
+
518
+ # Run tests
519
+ make check
520
+ ```
521
+
522
+ ---
523
+
524
+ ## License
525
+
526
+ MIT License - see [LICENSE](LICENSE) for details.
527
+
528
+ ---
529
+
530
+ ## Related Projects
531
+
532
+ - [chuk-mcp](https://github.com/chrishayuk/chuk-mcp) - Low-level MCP protocol client
533
+ - [Model Context Protocol](https://modelcontextprotocol.io) - MCP specification