PyStreamMCP 2.1.0__tar.gz → 3.2.0__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 (87) hide show
  1. pystreammcp-3.2.0/LICENSE +22 -0
  2. pystreammcp-3.2.0/PKG-INFO +231 -0
  3. pystreammcp-3.2.0/README.md +167 -0
  4. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/pyproject.toml +11 -3
  5. pystreammcp-3.2.0/python/PyStreamMCP.egg-info/PKG-INFO +231 -0
  6. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/PyStreamMCP.egg-info/SOURCES.txt +3 -0
  7. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/PyStreamMCP.egg-info/requires.txt +5 -0
  8. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/__init__.py +10 -2
  9. pystreammcp-3.2.0/python/pystreammcp/_mcp_connector.py +796 -0
  10. pystreammcp-3.2.0/python/pystreammcp/_mcp_tools.py +766 -0
  11. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/adapters.py +18 -5
  12. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/agent.py +63 -17
  13. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/api.py +36 -13
  14. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/cli.py +46 -14
  15. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/cli_daemon.py +17 -11
  16. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/cli_dashboard.py +28 -9
  17. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/context.py +5 -0
  18. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/decomposition.py +13 -3
  19. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/discovery.py +6 -3
  20. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/integrations/crewai.py +18 -6
  21. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/integrations/haystack.py +25 -8
  22. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/integrations/langchain.py +60 -23
  23. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/integrations/langsmith.py +17 -7
  24. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/integrations/llamaindex.py +117 -23
  25. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/integrations/pydantic_ai.py +18 -6
  26. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/integrations/semantic_kernel.py +25 -8
  27. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/mcp_server.py +8 -1
  28. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/ml/relevance.py +29 -12
  29. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/ml/tagging.py +155 -53
  30. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/ml.py +11 -3
  31. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/multi_agent.py +1 -2
  32. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/observability/metrics.py +41 -21
  33. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/okf_core.py +32 -17
  34. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/okf_discovery.py +70 -40
  35. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/okf_query_planner.py +29 -13
  36. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/optimization/advanced.py +34 -23
  37. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/optimization/decomposition.py +6 -1
  38. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/optimization.py +8 -1
  39. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/orchestration/airflow.py +7 -5
  40. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/orchestration/nocode_rpa.py +14 -7
  41. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/qa/validator.py +56 -33
  42. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/quality.py +72 -43
  43. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/query.py +44 -11
  44. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/server.py +129 -29
  45. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/webhook_handlers.py +44 -24
  46. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/webhook_router.py +43 -19
  47. pystreammcp-3.2.0/setup.py +18 -0
  48. pystreammcp-3.2.0/tests/test_mcp_connector_discovery.py +283 -0
  49. pystreammcp-3.2.0/tests/test_mcp_tools_handler.py +184 -0
  50. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/tests/test_sprint1_foundation.py +18 -0
  51. pystreammcp-3.2.0/tests/test_webhook_hmac_auth.py +168 -0
  52. pystreammcp-2.1.0/LICENSE +0 -21
  53. pystreammcp-2.1.0/PKG-INFO +0 -130
  54. pystreammcp-2.1.0/README.md +0 -64
  55. pystreammcp-2.1.0/python/PyStreamMCP.egg-info/PKG-INFO +0 -130
  56. pystreammcp-2.1.0/python/pystreammcp/_mcp_connector.py +0 -142
  57. pystreammcp-2.1.0/python/pystreammcp/_mcp_tools.py +0 -727
  58. pystreammcp-2.1.0/setup.py +0 -28
  59. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/MANIFEST.in +0 -0
  60. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/PyStreamMCP.egg-info/dependency_links.txt +0 -0
  61. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/PyStreamMCP.egg-info/top_level.txt +0 -0
  62. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/integrations/__init__.py +0 -0
  63. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/ml/__init__.py +0 -0
  64. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/observability/__init__.py +0 -0
  65. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/optimization/__init__.py +0 -0
  66. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/orchestration/__init__.py +0 -0
  67. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/orchestration/temporal.py +0 -0
  68. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/qa/__init__.py +0 -0
  69. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/scripts/__init__.py +0 -0
  70. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/scripts/post_install.py +0 -0
  71. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/python/pystreammcp/streaming.py +0 -0
  72. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/setup.cfg +0 -0
  73. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/tests/test_integration_phase2.py +0 -0
  74. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/tests/test_langchain_integration.py +0 -0
  75. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/tests/test_llamaindex_integration.py +0 -0
  76. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/tests/test_okf_core.py +0 -0
  77. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/tests/test_okf_discovery.py +0 -0
  78. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/tests/test_okf_query_planner.py +0 -0
  79. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/tests/test_phase3_advanced.py +0 -0
  80. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/tests/test_phase3_items12.py +0 -0
  81. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/tests/test_phase3_items345.py +0 -0
  82. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/tests/test_sprint2_langchain.py +0 -0
  83. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/tests/test_sprint3_rag_frameworks.py +0 -0
  84. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/tests/test_sprint4_agent_frameworks.py +0 -0
  85. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/tests/test_sprint5_orchestration.py +0 -0
  86. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/tests/test_statguardian_integration.py +0 -0
  87. {pystreammcp-2.1.0 → pystreammcp-3.2.0}/tests/test_webhook_router.py +0 -0
@@ -0,0 +1,22 @@
1
+ Proprietary License — Free to use with explicit attribution
2
+
3
+ Copyright © 2026 Georgi Mammen Mullassery
4
+
5
+ Permission is granted to any person obtaining a copy of this software to use,
6
+ copy, modify, and distribute this software and its documentation, provided that:
7
+
8
+ 1. The above copyright notice and this permission notice appear in all copies
9
+ or substantial portions of the software.
10
+
11
+ 2. Explicit attribution to the original author (Georgi Mammen Mullassery) is
12
+ provided in any project documentation and significant code comments where
13
+ this software is used.
14
+
15
+ 3. The software is provided "AS IS" without warranty of any kind, express or
16
+ implied, including but not limited to the warranties of merchantability,
17
+ fitness for a particular purpose, or non-infringement.
18
+
19
+ 4. In no event shall the author be liable for any claim, damages, or other
20
+ liability arising from the use of this software.
21
+
22
+ For more information, visit: https://github.com/Mullassery
@@ -0,0 +1,231 @@
1
+ Metadata-Version: 2.4
2
+ Name: PyStreamMCP
3
+ Version: 3.2.0
4
+ Summary: Intelligent MCP orchestration hub - Intent understanding, capability matching, tool ranking with cohesive foundation
5
+ Author-email: Georgi Mammen Mullassery <mullassery@gmail.com>
6
+ License: Proprietary License — Free to use with explicit attribution
7
+ Project-URL: Repository, https://github.com/Mullassery/PyStreamMCP
8
+ Project-URL: Issues, https://github.com/Mullassery/PyStreamMCP/issues
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: Other/Proprietary License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Requires-Python: >=3.9
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: pydantic>=2.0
22
+ Requires-Dist: python-frontmatter>=1.0.0
23
+ Requires-Dist: click>=8.0
24
+ Requires-Dist: rich>=13.0
25
+ Requires-Dist: httpx>=0.24.0
26
+ Requires-Dist: toml>=0.10; python_version < "3.11"
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest>=7.0; extra == "dev"
29
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
30
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
31
+ Provides-Extra: api
32
+ Requires-Dist: fastapi>=0.104.0; extra == "api"
33
+ Requires-Dist: uvicorn[standard]>=0.24.0; extra == "api"
34
+ Requires-Dist: pydantic-settings>=2.0; extra == "api"
35
+ Requires-Dist: flask>=2.3.0; extra == "api"
36
+ Provides-Extra: mcp
37
+ Requires-Dist: mcp>=0.1.0; extra == "mcp"
38
+ Provides-Extra: langchain
39
+ Requires-Dist: langchain>=0.1.0; extra == "langchain"
40
+ Provides-Extra: llamaindex
41
+ Requires-Dist: llama-index>=0.9.0; extra == "llamaindex"
42
+ Provides-Extra: semantic-kernel
43
+ Requires-Dist: semantic-kernel>=0.4.0; extra == "semantic-kernel"
44
+ Provides-Extra: crewai
45
+ Requires-Dist: crewai>=0.1.0; extra == "crewai"
46
+ Provides-Extra: pydantic-ai
47
+ Requires-Dist: pydantic-ai>=0.1.0; extra == "pydantic-ai"
48
+ Provides-Extra: haystack
49
+ Requires-Dist: haystack-ai>=2.0.0; extra == "haystack"
50
+ Provides-Extra: temporal
51
+ Requires-Dist: temporalio>=1.0.0; extra == "temporal"
52
+ Provides-Extra: airflow
53
+ Requires-Dist: apache-airflow>=2.7.0; extra == "airflow"
54
+ Provides-Extra: all-integrations
55
+ Requires-Dist: langchain>=0.1.0; extra == "all-integrations"
56
+ Requires-Dist: llama-index>=0.9.0; extra == "all-integrations"
57
+ Requires-Dist: semantic-kernel>=0.4.0; extra == "all-integrations"
58
+ Requires-Dist: crewai>=0.1.0; extra == "all-integrations"
59
+ Requires-Dist: pydantic-ai>=0.1.0; extra == "all-integrations"
60
+ Requires-Dist: haystack-ai>=2.0.0; extra == "all-integrations"
61
+ Requires-Dist: temporalio>=1.0.0; extra == "all-integrations"
62
+ Requires-Dist: apache-airflow>=2.7.0; extra == "all-integrations"
63
+ Dynamic: license-file
64
+
65
+ # PyStreamMCP
66
+
67
+ [![CI](https://github.com/Mullassery/PyStreamMCP/actions/workflows/ci.yml/badge.svg)](https://github.com/Mullassery/PyStreamMCP/actions/workflows/ci.yml)
68
+
69
+ An AI-agent intelligence layer: query planning, context discovery, and
70
+ token-cost optimization, exposed both as a Python SDK and as an MCP
71
+ (Model Context Protocol) tool server, plus a small event-driven
72
+ orchestration/federation layer for coordinating multiple MCP endpoints.
73
+
74
+ Pure Python — `pip install` just works, no Rust toolchain or compiler
75
+ required.
76
+
77
+ ## Install
78
+
79
+ ```bash
80
+ pip install PyStreamMCP
81
+ ```
82
+
83
+ Optional extras, install what you actually need:
84
+
85
+ ```bash
86
+ pip install "PyStreamMCP[api]" # FastAPI + Flask HTTP servers
87
+ pip install "PyStreamMCP[mcp]" # MCP protocol client library
88
+ pip install "PyStreamMCP[langchain]" # LangChain adapter
89
+ pip install "PyStreamMCP[llamaindex]" # LlamaIndex adapter
90
+ pip install "PyStreamMCP[semantic-kernel]" # Semantic Kernel adapter
91
+ pip install "PyStreamMCP[all-integrations]" # every framework adapter
92
+ ```
93
+
94
+ Requires Python 3.9+.
95
+
96
+ ## Quick start
97
+
98
+ ```python
99
+ from pystreammcp import Agent
100
+
101
+ agent = Agent(
102
+ agent_id="recommendation_engine",
103
+ name="Product Recommendation Engine",
104
+ optimization_strategy="token_efficient", # or "balanced" / "quality_first"
105
+ max_tokens=1000,
106
+ )
107
+
108
+ result = agent.query("What are the top 10 customers by lifetime value?")
109
+
110
+ print(f"Baseline tokens: {result.baseline_tokens}")
111
+ print(f"Optimized tokens: {result.optimized_tokens}")
112
+ print(f"Reduction: {result.cost_reduction_percent:.1f}%")
113
+ ```
114
+
115
+ Token counts are estimated from the actual query text (a standard
116
+ ~4-characters-per-token heuristic) and the reduction percentage is
117
+ computed from the selected `optimization_strategy` — not a fixed number
118
+ returned regardless of input. See [`examples/basic_usage.py`](examples/basic_usage.py)
119
+ for a full runnable walkthrough, including framework adapters for
120
+ LangChain, LlamaIndex, CrewAI, Semantic Kernel, PydanticAI, and Haystack
121
+ under [`pystreammcp.integrations`](python/pystreammcp/integrations/).
122
+
123
+ ## MCP orchestration & federation
124
+
125
+ `Orchestrator` (`pystreammcp.Orchestrator`) discovers and routes across
126
+ other MCP-enabled projects you configure in `pystreammcp.toml`:
127
+
128
+ ```toml
129
+ [federation]
130
+ endpoints = [
131
+ "http://localhost:8765/mcp",
132
+ "http://localhost:8766/mcp",
133
+ ]
134
+ ```
135
+
136
+ ```python
137
+ from pystreammcp import Orchestrator
138
+
139
+ orch = Orchestrator() # reads ./pystreammcp.toml
140
+ result = orch.discover_mcp_projects()
141
+ # {"projects": [{"project_name": ..., "endpoint": ..., "status": "healthy"|"unavailable", ...}], "total": N}
142
+ ```
143
+
144
+ This actually probes each configured endpoint's real `tools/list` MCP
145
+ method — with nothing configured, or nothing reachable, it honestly
146
+ reports zero/unavailable projects rather than a fixed fixture list.
147
+ `Orchestrator` also does lexical tool-relevance ranking
148
+ (`rank_tools_by_relevance`) and capability matching
149
+ (`detect_compatible_projects`) against whatever it actually discovers.
150
+
151
+ To expose these (plus tool-routing and webhook-event handling) as MCP
152
+ tools, `PyStreamMCPHandler` (`pystreammcp._mcp_tools`) wires the MCP
153
+ tool-call surface directly to a live `Orchestrator`/`EventRouter`
154
+ instance — every handler call is backed by real, inspectable state, not
155
+ a hardcoded response.
156
+
157
+ **Honest limitations**: a few orchestration capabilities are accepted at
158
+ the API level but not fully implemented yet — cross-project federated
159
+ query *execution* and cross-database joins currently report
160
+ `"status": "not_implemented"` with an explanation, rather than fabricated
161
+ result rows, because there's no real query engine behind them yet.
162
+
163
+ ## Webhook event server
164
+
165
+ `pystreammcp.server.create_flask_app()` exposes a small REST/webhook
166
+ surface for orchestration events (agent MCPs reporting `mcp.available`,
167
+ `tool.invoked`, health updates, etc. to `POST /orchestration/webhooks/events`).
168
+
169
+ ### Webhook security (HMAC-SHA256)
170
+
171
+ Inbound events to `/orchestration/webhooks/events` must be signed:
172
+
173
+ ```bash
174
+ export PYSTREAMMCP_WEBHOOK_SECRET="a long random shared secret"
175
+ ```
176
+
177
+ Senders compute `HMAC-SHA256(secret, raw_request_body)` and send it as:
178
+
179
+ ```
180
+ X-PyStreamMCP-Signature: sha256=<hex digest>
181
+ ```
182
+
183
+ ```python
184
+ from pystreammcp.server import compute_webhook_signature
185
+ import json, requests
186
+
187
+ body = json.dumps({"event_type": "mcp.available", "data": {...}}).encode()
188
+ signature = compute_webhook_signature(secret, body)
189
+
190
+ requests.post(
191
+ "http://localhost:8000/orchestration/webhooks/events",
192
+ data=body,
193
+ headers={
194
+ "Content-Type": "application/json",
195
+ "X-PyStreamMCP-Signature": signature,
196
+ },
197
+ )
198
+ ```
199
+
200
+ Requests with a missing or invalid signature are rejected with `401`. If
201
+ `PYSTREAMMCP_WEBHOOK_SECRET` isn't set at all, the endpoint fails closed
202
+ and rejects every request with `503` — there is no "accept unsigned
203
+ events" fallback.
204
+
205
+ ### Network defaults
206
+
207
+ The HTTP/CLI servers (`pystreammcp server`, `PyStreamMCPServer`,
208
+ `PyStreamMCPAPI.run`) bind to `127.0.0.1` (localhost-only) by default.
209
+ Pass `--host 0.0.0.0` (CLI) or `host="0.0.0.0"` explicitly if you need the
210
+ server reachable from other hosts — e.g. inside a container that already
211
+ has its own network boundary.
212
+
213
+ ## Testing
214
+
215
+ ```bash
216
+ pip install -e ".[dev,api,mcp,langchain,llamaindex,semantic-kernel]"
217
+ pytest tests/ -v
218
+ ```
219
+
220
+ ## Rust workspace (not shipped)
221
+
222
+ `core/` and `python/src/lib.rs` are an in-progress Rust workspace intended
223
+ as a future performance backend. **It is not part of the published PyPI
224
+ package** — the wheel built from `pyproject.toml` is pure Python — and it
225
+ does not currently compile. Don't rely on it; it's tracked separately
226
+ from the Python package described in this README.
227
+
228
+ ## License
229
+
230
+ Proprietary License — Free to use with explicit attribution. See
231
+ [LICENSE](LICENSE).
@@ -0,0 +1,167 @@
1
+ # PyStreamMCP
2
+
3
+ [![CI](https://github.com/Mullassery/PyStreamMCP/actions/workflows/ci.yml/badge.svg)](https://github.com/Mullassery/PyStreamMCP/actions/workflows/ci.yml)
4
+
5
+ An AI-agent intelligence layer: query planning, context discovery, and
6
+ token-cost optimization, exposed both as a Python SDK and as an MCP
7
+ (Model Context Protocol) tool server, plus a small event-driven
8
+ orchestration/federation layer for coordinating multiple MCP endpoints.
9
+
10
+ Pure Python — `pip install` just works, no Rust toolchain or compiler
11
+ required.
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ pip install PyStreamMCP
17
+ ```
18
+
19
+ Optional extras, install what you actually need:
20
+
21
+ ```bash
22
+ pip install "PyStreamMCP[api]" # FastAPI + Flask HTTP servers
23
+ pip install "PyStreamMCP[mcp]" # MCP protocol client library
24
+ pip install "PyStreamMCP[langchain]" # LangChain adapter
25
+ pip install "PyStreamMCP[llamaindex]" # LlamaIndex adapter
26
+ pip install "PyStreamMCP[semantic-kernel]" # Semantic Kernel adapter
27
+ pip install "PyStreamMCP[all-integrations]" # every framework adapter
28
+ ```
29
+
30
+ Requires Python 3.9+.
31
+
32
+ ## Quick start
33
+
34
+ ```python
35
+ from pystreammcp import Agent
36
+
37
+ agent = Agent(
38
+ agent_id="recommendation_engine",
39
+ name="Product Recommendation Engine",
40
+ optimization_strategy="token_efficient", # or "balanced" / "quality_first"
41
+ max_tokens=1000,
42
+ )
43
+
44
+ result = agent.query("What are the top 10 customers by lifetime value?")
45
+
46
+ print(f"Baseline tokens: {result.baseline_tokens}")
47
+ print(f"Optimized tokens: {result.optimized_tokens}")
48
+ print(f"Reduction: {result.cost_reduction_percent:.1f}%")
49
+ ```
50
+
51
+ Token counts are estimated from the actual query text (a standard
52
+ ~4-characters-per-token heuristic) and the reduction percentage is
53
+ computed from the selected `optimization_strategy` — not a fixed number
54
+ returned regardless of input. See [`examples/basic_usage.py`](examples/basic_usage.py)
55
+ for a full runnable walkthrough, including framework adapters for
56
+ LangChain, LlamaIndex, CrewAI, Semantic Kernel, PydanticAI, and Haystack
57
+ under [`pystreammcp.integrations`](python/pystreammcp/integrations/).
58
+
59
+ ## MCP orchestration & federation
60
+
61
+ `Orchestrator` (`pystreammcp.Orchestrator`) discovers and routes across
62
+ other MCP-enabled projects you configure in `pystreammcp.toml`:
63
+
64
+ ```toml
65
+ [federation]
66
+ endpoints = [
67
+ "http://localhost:8765/mcp",
68
+ "http://localhost:8766/mcp",
69
+ ]
70
+ ```
71
+
72
+ ```python
73
+ from pystreammcp import Orchestrator
74
+
75
+ orch = Orchestrator() # reads ./pystreammcp.toml
76
+ result = orch.discover_mcp_projects()
77
+ # {"projects": [{"project_name": ..., "endpoint": ..., "status": "healthy"|"unavailable", ...}], "total": N}
78
+ ```
79
+
80
+ This actually probes each configured endpoint's real `tools/list` MCP
81
+ method — with nothing configured, or nothing reachable, it honestly
82
+ reports zero/unavailable projects rather than a fixed fixture list.
83
+ `Orchestrator` also does lexical tool-relevance ranking
84
+ (`rank_tools_by_relevance`) and capability matching
85
+ (`detect_compatible_projects`) against whatever it actually discovers.
86
+
87
+ To expose these (plus tool-routing and webhook-event handling) as MCP
88
+ tools, `PyStreamMCPHandler` (`pystreammcp._mcp_tools`) wires the MCP
89
+ tool-call surface directly to a live `Orchestrator`/`EventRouter`
90
+ instance — every handler call is backed by real, inspectable state, not
91
+ a hardcoded response.
92
+
93
+ **Honest limitations**: a few orchestration capabilities are accepted at
94
+ the API level but not fully implemented yet — cross-project federated
95
+ query *execution* and cross-database joins currently report
96
+ `"status": "not_implemented"` with an explanation, rather than fabricated
97
+ result rows, because there's no real query engine behind them yet.
98
+
99
+ ## Webhook event server
100
+
101
+ `pystreammcp.server.create_flask_app()` exposes a small REST/webhook
102
+ surface for orchestration events (agent MCPs reporting `mcp.available`,
103
+ `tool.invoked`, health updates, etc. to `POST /orchestration/webhooks/events`).
104
+
105
+ ### Webhook security (HMAC-SHA256)
106
+
107
+ Inbound events to `/orchestration/webhooks/events` must be signed:
108
+
109
+ ```bash
110
+ export PYSTREAMMCP_WEBHOOK_SECRET="a long random shared secret"
111
+ ```
112
+
113
+ Senders compute `HMAC-SHA256(secret, raw_request_body)` and send it as:
114
+
115
+ ```
116
+ X-PyStreamMCP-Signature: sha256=<hex digest>
117
+ ```
118
+
119
+ ```python
120
+ from pystreammcp.server import compute_webhook_signature
121
+ import json, requests
122
+
123
+ body = json.dumps({"event_type": "mcp.available", "data": {...}}).encode()
124
+ signature = compute_webhook_signature(secret, body)
125
+
126
+ requests.post(
127
+ "http://localhost:8000/orchestration/webhooks/events",
128
+ data=body,
129
+ headers={
130
+ "Content-Type": "application/json",
131
+ "X-PyStreamMCP-Signature": signature,
132
+ },
133
+ )
134
+ ```
135
+
136
+ Requests with a missing or invalid signature are rejected with `401`. If
137
+ `PYSTREAMMCP_WEBHOOK_SECRET` isn't set at all, the endpoint fails closed
138
+ and rejects every request with `503` — there is no "accept unsigned
139
+ events" fallback.
140
+
141
+ ### Network defaults
142
+
143
+ The HTTP/CLI servers (`pystreammcp server`, `PyStreamMCPServer`,
144
+ `PyStreamMCPAPI.run`) bind to `127.0.0.1` (localhost-only) by default.
145
+ Pass `--host 0.0.0.0` (CLI) or `host="0.0.0.0"` explicitly if you need the
146
+ server reachable from other hosts — e.g. inside a container that already
147
+ has its own network boundary.
148
+
149
+ ## Testing
150
+
151
+ ```bash
152
+ pip install -e ".[dev,api,mcp,langchain,llamaindex,semantic-kernel]"
153
+ pytest tests/ -v
154
+ ```
155
+
156
+ ## Rust workspace (not shipped)
157
+
158
+ `core/` and `python/src/lib.rs` are an in-progress Rust workspace intended
159
+ as a future performance backend. **It is not part of the published PyPI
160
+ package** — the wheel built from `pyproject.toml` is pure Python — and it
161
+ does not currently compile. Don't rely on it; it's tracked separately
162
+ from the Python package described in this README.
163
+
164
+ ## License
165
+
166
+ Proprietary License — Free to use with explicit attribution. See
167
+ [LICENSE](LICENSE).
@@ -4,13 +4,20 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "PyStreamMCP"
7
- version = "2.1.0"
7
+ version = "3.2.0"
8
8
  description = "Intelligent MCP orchestration hub - Intent understanding, capability matching, tool ranking with cohesive foundation"
9
9
  readme = "README.md"
10
- license = { text = "Proprietary" }
10
+ license = {text = "Proprietary License — Free to use with explicit attribution"}
11
11
  authors = [{ name = "Georgi Mammen Mullassery", email = "mullassery@gmail.com" }]
12
12
  requires-python = ">=3.9"
13
- dependencies = ["pydantic>=2.0", "python-frontmatter>=1.0.0", "click>=8.0", "rich>=13.0"]
13
+ dependencies = [
14
+ "pydantic>=2.0",
15
+ "python-frontmatter>=1.0.0",
16
+ "click>=8.0",
17
+ "rich>=13.0",
18
+ "httpx>=0.24.0",
19
+ "toml>=0.10; python_version < \"3.11\"",
20
+ ]
14
21
  classifiers = [
15
22
  "Development Status :: 5 - Production/Stable",
16
23
  "Intended Audience :: Developers",
@@ -39,6 +46,7 @@ api = [
39
46
  "fastapi>=0.104.0",
40
47
  "uvicorn[standard]>=0.24.0",
41
48
  "pydantic-settings>=2.0",
49
+ "flask>=2.3.0",
42
50
  ]
43
51
 
44
52
  # MCP (Model Context Protocol)
@@ -0,0 +1,231 @@
1
+ Metadata-Version: 2.4
2
+ Name: PyStreamMCP
3
+ Version: 3.2.0
4
+ Summary: Intelligent MCP orchestration hub - Intent understanding, capability matching, tool ranking with cohesive foundation
5
+ Author-email: Georgi Mammen Mullassery <mullassery@gmail.com>
6
+ License: Proprietary License — Free to use with explicit attribution
7
+ Project-URL: Repository, https://github.com/Mullassery/PyStreamMCP
8
+ Project-URL: Issues, https://github.com/Mullassery/PyStreamMCP/issues
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: Other/Proprietary License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Requires-Python: >=3.9
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: pydantic>=2.0
22
+ Requires-Dist: python-frontmatter>=1.0.0
23
+ Requires-Dist: click>=8.0
24
+ Requires-Dist: rich>=13.0
25
+ Requires-Dist: httpx>=0.24.0
26
+ Requires-Dist: toml>=0.10; python_version < "3.11"
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest>=7.0; extra == "dev"
29
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
30
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
31
+ Provides-Extra: api
32
+ Requires-Dist: fastapi>=0.104.0; extra == "api"
33
+ Requires-Dist: uvicorn[standard]>=0.24.0; extra == "api"
34
+ Requires-Dist: pydantic-settings>=2.0; extra == "api"
35
+ Requires-Dist: flask>=2.3.0; extra == "api"
36
+ Provides-Extra: mcp
37
+ Requires-Dist: mcp>=0.1.0; extra == "mcp"
38
+ Provides-Extra: langchain
39
+ Requires-Dist: langchain>=0.1.0; extra == "langchain"
40
+ Provides-Extra: llamaindex
41
+ Requires-Dist: llama-index>=0.9.0; extra == "llamaindex"
42
+ Provides-Extra: semantic-kernel
43
+ Requires-Dist: semantic-kernel>=0.4.0; extra == "semantic-kernel"
44
+ Provides-Extra: crewai
45
+ Requires-Dist: crewai>=0.1.0; extra == "crewai"
46
+ Provides-Extra: pydantic-ai
47
+ Requires-Dist: pydantic-ai>=0.1.0; extra == "pydantic-ai"
48
+ Provides-Extra: haystack
49
+ Requires-Dist: haystack-ai>=2.0.0; extra == "haystack"
50
+ Provides-Extra: temporal
51
+ Requires-Dist: temporalio>=1.0.0; extra == "temporal"
52
+ Provides-Extra: airflow
53
+ Requires-Dist: apache-airflow>=2.7.0; extra == "airflow"
54
+ Provides-Extra: all-integrations
55
+ Requires-Dist: langchain>=0.1.0; extra == "all-integrations"
56
+ Requires-Dist: llama-index>=0.9.0; extra == "all-integrations"
57
+ Requires-Dist: semantic-kernel>=0.4.0; extra == "all-integrations"
58
+ Requires-Dist: crewai>=0.1.0; extra == "all-integrations"
59
+ Requires-Dist: pydantic-ai>=0.1.0; extra == "all-integrations"
60
+ Requires-Dist: haystack-ai>=2.0.0; extra == "all-integrations"
61
+ Requires-Dist: temporalio>=1.0.0; extra == "all-integrations"
62
+ Requires-Dist: apache-airflow>=2.7.0; extra == "all-integrations"
63
+ Dynamic: license-file
64
+
65
+ # PyStreamMCP
66
+
67
+ [![CI](https://github.com/Mullassery/PyStreamMCP/actions/workflows/ci.yml/badge.svg)](https://github.com/Mullassery/PyStreamMCP/actions/workflows/ci.yml)
68
+
69
+ An AI-agent intelligence layer: query planning, context discovery, and
70
+ token-cost optimization, exposed both as a Python SDK and as an MCP
71
+ (Model Context Protocol) tool server, plus a small event-driven
72
+ orchestration/federation layer for coordinating multiple MCP endpoints.
73
+
74
+ Pure Python — `pip install` just works, no Rust toolchain or compiler
75
+ required.
76
+
77
+ ## Install
78
+
79
+ ```bash
80
+ pip install PyStreamMCP
81
+ ```
82
+
83
+ Optional extras, install what you actually need:
84
+
85
+ ```bash
86
+ pip install "PyStreamMCP[api]" # FastAPI + Flask HTTP servers
87
+ pip install "PyStreamMCP[mcp]" # MCP protocol client library
88
+ pip install "PyStreamMCP[langchain]" # LangChain adapter
89
+ pip install "PyStreamMCP[llamaindex]" # LlamaIndex adapter
90
+ pip install "PyStreamMCP[semantic-kernel]" # Semantic Kernel adapter
91
+ pip install "PyStreamMCP[all-integrations]" # every framework adapter
92
+ ```
93
+
94
+ Requires Python 3.9+.
95
+
96
+ ## Quick start
97
+
98
+ ```python
99
+ from pystreammcp import Agent
100
+
101
+ agent = Agent(
102
+ agent_id="recommendation_engine",
103
+ name="Product Recommendation Engine",
104
+ optimization_strategy="token_efficient", # or "balanced" / "quality_first"
105
+ max_tokens=1000,
106
+ )
107
+
108
+ result = agent.query("What are the top 10 customers by lifetime value?")
109
+
110
+ print(f"Baseline tokens: {result.baseline_tokens}")
111
+ print(f"Optimized tokens: {result.optimized_tokens}")
112
+ print(f"Reduction: {result.cost_reduction_percent:.1f}%")
113
+ ```
114
+
115
+ Token counts are estimated from the actual query text (a standard
116
+ ~4-characters-per-token heuristic) and the reduction percentage is
117
+ computed from the selected `optimization_strategy` — not a fixed number
118
+ returned regardless of input. See [`examples/basic_usage.py`](examples/basic_usage.py)
119
+ for a full runnable walkthrough, including framework adapters for
120
+ LangChain, LlamaIndex, CrewAI, Semantic Kernel, PydanticAI, and Haystack
121
+ under [`pystreammcp.integrations`](python/pystreammcp/integrations/).
122
+
123
+ ## MCP orchestration & federation
124
+
125
+ `Orchestrator` (`pystreammcp.Orchestrator`) discovers and routes across
126
+ other MCP-enabled projects you configure in `pystreammcp.toml`:
127
+
128
+ ```toml
129
+ [federation]
130
+ endpoints = [
131
+ "http://localhost:8765/mcp",
132
+ "http://localhost:8766/mcp",
133
+ ]
134
+ ```
135
+
136
+ ```python
137
+ from pystreammcp import Orchestrator
138
+
139
+ orch = Orchestrator() # reads ./pystreammcp.toml
140
+ result = orch.discover_mcp_projects()
141
+ # {"projects": [{"project_name": ..., "endpoint": ..., "status": "healthy"|"unavailable", ...}], "total": N}
142
+ ```
143
+
144
+ This actually probes each configured endpoint's real `tools/list` MCP
145
+ method — with nothing configured, or nothing reachable, it honestly
146
+ reports zero/unavailable projects rather than a fixed fixture list.
147
+ `Orchestrator` also does lexical tool-relevance ranking
148
+ (`rank_tools_by_relevance`) and capability matching
149
+ (`detect_compatible_projects`) against whatever it actually discovers.
150
+
151
+ To expose these (plus tool-routing and webhook-event handling) as MCP
152
+ tools, `PyStreamMCPHandler` (`pystreammcp._mcp_tools`) wires the MCP
153
+ tool-call surface directly to a live `Orchestrator`/`EventRouter`
154
+ instance — every handler call is backed by real, inspectable state, not
155
+ a hardcoded response.
156
+
157
+ **Honest limitations**: a few orchestration capabilities are accepted at
158
+ the API level but not fully implemented yet — cross-project federated
159
+ query *execution* and cross-database joins currently report
160
+ `"status": "not_implemented"` with an explanation, rather than fabricated
161
+ result rows, because there's no real query engine behind them yet.
162
+
163
+ ## Webhook event server
164
+
165
+ `pystreammcp.server.create_flask_app()` exposes a small REST/webhook
166
+ surface for orchestration events (agent MCPs reporting `mcp.available`,
167
+ `tool.invoked`, health updates, etc. to `POST /orchestration/webhooks/events`).
168
+
169
+ ### Webhook security (HMAC-SHA256)
170
+
171
+ Inbound events to `/orchestration/webhooks/events` must be signed:
172
+
173
+ ```bash
174
+ export PYSTREAMMCP_WEBHOOK_SECRET="a long random shared secret"
175
+ ```
176
+
177
+ Senders compute `HMAC-SHA256(secret, raw_request_body)` and send it as:
178
+
179
+ ```
180
+ X-PyStreamMCP-Signature: sha256=<hex digest>
181
+ ```
182
+
183
+ ```python
184
+ from pystreammcp.server import compute_webhook_signature
185
+ import json, requests
186
+
187
+ body = json.dumps({"event_type": "mcp.available", "data": {...}}).encode()
188
+ signature = compute_webhook_signature(secret, body)
189
+
190
+ requests.post(
191
+ "http://localhost:8000/orchestration/webhooks/events",
192
+ data=body,
193
+ headers={
194
+ "Content-Type": "application/json",
195
+ "X-PyStreamMCP-Signature": signature,
196
+ },
197
+ )
198
+ ```
199
+
200
+ Requests with a missing or invalid signature are rejected with `401`. If
201
+ `PYSTREAMMCP_WEBHOOK_SECRET` isn't set at all, the endpoint fails closed
202
+ and rejects every request with `503` — there is no "accept unsigned
203
+ events" fallback.
204
+
205
+ ### Network defaults
206
+
207
+ The HTTP/CLI servers (`pystreammcp server`, `PyStreamMCPServer`,
208
+ `PyStreamMCPAPI.run`) bind to `127.0.0.1` (localhost-only) by default.
209
+ Pass `--host 0.0.0.0` (CLI) or `host="0.0.0.0"` explicitly if you need the
210
+ server reachable from other hosts — e.g. inside a container that already
211
+ has its own network boundary.
212
+
213
+ ## Testing
214
+
215
+ ```bash
216
+ pip install -e ".[dev,api,mcp,langchain,llamaindex,semantic-kernel]"
217
+ pytest tests/ -v
218
+ ```
219
+
220
+ ## Rust workspace (not shipped)
221
+
222
+ `core/` and `python/src/lib.rs` are an in-progress Rust workspace intended
223
+ as a future performance backend. **It is not part of the published PyPI
224
+ package** — the wheel built from `pyproject.toml` is pure Python — and it
225
+ does not currently compile. Don't rely on it; it's tracked separately
226
+ from the Python package described in this README.
227
+
228
+ ## License
229
+
230
+ Proprietary License — Free to use with explicit attribution. See
231
+ [LICENSE](LICENSE).