adaptive-memory-multi-model-router 2.16.0 → 2.16.2

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 (248) hide show
  1. package/.github/workflows/adapters-ci.yml +142 -0
  2. package/.github/workflows/auto-submit-sitemap.yml +41 -0
  3. package/.github/workflows/ci.yml +2 -5
  4. package/.github/workflows/mcp-pypi-publish.yml +34 -0
  5. package/.github/workflows/pypi-publish.yml +146 -0
  6. package/.github/workflows/tmlpd-publish.yml +23 -0
  7. package/README.md +245 -148
  8. package/RELEASE_v2.16.0.md +149 -0
  9. package/TECHNICAL_README.md +253 -0
  10. package/adapters/README.md +36 -0
  11. package/adapters/__init__.py +25 -0
  12. package/adapters/a3m_adapter/__init__.py +51 -0
  13. package/adapters/a3m_adapter/adapter/__init__.py +22 -0
  14. package/adapters/a3m_adapter/adapter/autogen.py +169 -0
  15. package/adapters/a3m_adapter/adapter/config.py +100 -0
  16. package/adapters/a3m_adapter/adapter/haystack.py +197 -0
  17. package/adapters/a3m_adapter/adapter/langchain.py +155 -0
  18. package/adapters/a3m_adapter/adapter/langgraph.py +196 -0
  19. package/adapters/a3m_adapter/adapter/llamaindex.py +162 -0
  20. package/adapters/a3m_adapter/adapter/pinecone.py +217 -0
  21. package/adapters/a3m_adapter/adapter/vercel.py +188 -0
  22. package/adapters/a3m_adapter/tests/__init__.py +1 -0
  23. package/adapters/a3m_adapter/tests/test_adapters.py +118 -0
  24. package/adapters/a3m_adapter/tests/test_integration.py +80 -0
  25. package/adapters/requirements-dev.txt +6 -0
  26. package/adapters/requirements.txt +4 -0
  27. package/adapters/setup.py +23 -0
  28. package/demo.py +251 -0
  29. package/discoverability-diagnosis.md +280 -0
  30. package/dist/analytics/costAnalytics.d.ts.map +1 -1
  31. package/dist/benchmark/reproducible.d.ts.map +1 -1
  32. package/dist/cache/semanticCache.d.ts.map +1 -1
  33. package/dist/cli/setupWizard.d.ts +257 -50
  34. package/dist/cli/setupWizard.d.ts.map +1 -1
  35. package/dist/cli/setupWizard.js +419 -109
  36. package/dist/cli/setupWizard.js.map +1 -1
  37. package/dist/cli/tui.d.ts +6 -0
  38. package/dist/cli/tui.js +96 -67
  39. package/dist/cli/tui.js.map +1 -0
  40. package/dist/cli.js +9 -0
  41. package/dist/cost/budgetEnforcer.d.ts.map +1 -1
  42. package/dist/cost/costTracker.d.ts.map +1 -1
  43. package/dist/ensemble/multiRoundDialog.d.ts.map +1 -1
  44. package/dist/ensemble/shapleyValue.d.ts.map +1 -1
  45. package/dist/ensemble.d.ts +1 -1
  46. package/dist/ensemble.js +141 -0
  47. package/dist/integrations/langchainAdapter.d.ts.map +1 -1
  48. package/dist/integrations/langchainAdapter.js +3 -3
  49. package/dist/integrations/langchainAdapter.js.map +1 -1
  50. package/dist/integrations/oauth.d.ts.map +1 -1
  51. package/dist/integrations/scienceAdapter.d.ts.map +1 -1
  52. package/dist/memory/autoFetch.d.ts.map +1 -1
  53. package/dist/memory/hybridMemory.d.ts.map +1 -1
  54. package/dist/memory/memoryTree.d.ts.map +1 -1
  55. package/dist/memory/obsidianVault.d.ts.map +1 -1
  56. package/dist/memory/reasoningBank.d.ts.map +1 -1
  57. package/dist/observability/metrics.d.ts.map +1 -1
  58. package/dist/observability/tracer.d.ts.map +1 -1
  59. package/dist/providers/providerConfig.d.ts.map +1 -1
  60. package/dist/providers/providerConfig.js +32 -17
  61. package/dist/providers/providerConfig.js.map +1 -1
  62. package/dist/routing/advancedRouter.d.ts.map +1 -1
  63. package/dist/routing/advancedRouter.js +106 -14
  64. package/dist/routing/advancedRouter.js.map +1 -1
  65. package/dist/routing/providerHealth.d.ts.map +1 -1
  66. package/dist/routing/providerRetry.d.ts.map +1 -1
  67. package/dist/routing/shadowSampler.d.ts.map +1 -0
  68. package/dist/routing/shadowSampler.js.map +1 -1
  69. package/dist/security/guardrails.d.ts.map +1 -1
  70. package/dist/server/handlers/chatHandler.d.ts.map +1 -1
  71. package/dist/server/handlers/completionsHandler.d.ts.map +1 -1
  72. package/dist/server/handlers/embeddingsHandler.d.ts.map +1 -1
  73. package/dist/server/handlers/healthHandler.d.ts.map +1 -1
  74. package/dist/server/handlers/metricsHandler.d.ts.map +1 -1
  75. package/dist/server/handlers/modelsHandler.d.ts.map +1 -1
  76. package/dist/server/metrics.d.ts.map +1 -1
  77. package/dist/server/proxyServer.d.ts.map +1 -1
  78. package/dist/server/router.d.ts.map +1 -1
  79. package/dist/server/state.d.ts.map +1 -1
  80. package/dist/skills/__tests__/skill_manager.test.js +5 -265
  81. package/dist/skills/__tests__/skill_manager.test.js.map +1 -1
  82. package/dist/utils/tokenUtils.d.ts.map +1 -1
  83. package/docker-compose.yml +84 -60
  84. package/docs/ARTICLE_Biology_Inspired_Routing.md +208 -0
  85. package/docs/ARTICLE_Master.md +78 -0
  86. package/docs/ARTICLE_Master_CN.md +78 -0
  87. package/docs/ARTICLE_OpenRouter_Stripe.md +140 -0
  88. package/docs/DEVPTO_ARTICLE.md +84 -0
  89. package/docs/HUMAN_STYLE_GUIDE.md +75 -0
  90. package/docs/IMPRINT_PLAN.md +88 -0
  91. package/docs/OPENROUTER_ALTERNATIVE.md +184 -0
  92. package/docs/SOCIAL_CAMPAIGN.md +316 -0
  93. package/docs/anthropic.html +45 -0
  94. package/docs/best-llm-routers-2025.html +157 -0
  95. package/docs/cerebras.html +43 -0
  96. package/docs/cli-cheatsheet.md +286 -212
  97. package/docs/comparison.md +2 -2
  98. package/docs/deepseek.html +44 -0
  99. package/docs/google.html +47 -0
  100. package/docs/groq.html +44 -0
  101. package/docs/llms-full.txt +360 -138
  102. package/docs/llms.txt +70 -71
  103. package/docs/mistral.html +43 -0
  104. package/docs/ollama.html +50 -0
  105. package/docs/openai.html +57 -0
  106. package/docs/sitemap.xml +69 -57
  107. package/docs-site/blog/best-llm-routers-2025.html +157 -0
  108. package/docs-site/index.html +68 -9
  109. package/docs-site/providers/anthropic.html +45 -0
  110. package/docs-site/providers/cerebras.html +43 -0
  111. package/docs-site/providers/deepseek.html +44 -0
  112. package/docs-site/providers/google.html +47 -0
  113. package/docs-site/providers/groq.html +44 -0
  114. package/docs-site/providers/index.html +41 -0
  115. package/docs-site/providers/mistral.html +43 -0
  116. package/docs-site/providers/ollama.html +50 -0
  117. package/docs-site/providers/openai.html +57 -0
  118. package/docs-site/sitemap.xml +69 -0
  119. package/llms.txt +70 -62
  120. package/package.json +44 -182
  121. package/packages/agentkit-adapter/LICENSE +21 -0
  122. package/packages/agentkit-adapter/README.md +126 -0
  123. package/packages/agentkit-adapter/examples/agentkit-example.ts +139 -0
  124. package/packages/agentkit-adapter/package.json +57 -0
  125. package/packages/agentkit-adapter/src/adapter.ts +381 -0
  126. package/packages/agentkit-adapter/src/index.ts +36 -0
  127. package/packages/agentkit-adapter/src/types.ts +105 -0
  128. package/packages/agentkit-adapter/src/util.ts +13 -0
  129. package/packages/agentkit-adapter/tsconfig.json +22 -0
  130. package/prometheus.yml +8 -0
  131. package/python/README.md +35 -81
  132. package/python/a3m/__init__.py +32 -3
  133. package/python/a3m/adapters/__init__.py +21 -0
  134. package/python/a3m/adapters/langchain.py +190 -0
  135. package/python/a3m/adapters/llamaindex.py +249 -0
  136. package/python/a3m/adapters/qdrant.py +240 -0
  137. package/python/a3m/adapters/weaviate.py +263 -0
  138. package/python/a3m/client.py +5 -0
  139. package/python/build_verify.sh +32 -0
  140. package/python/mcp-server/README.md +172 -0
  141. package/python/mcp-server/a3m_mcp/__init__.py +25 -0
  142. package/python/mcp-server/a3m_mcp/__main__.py +15 -0
  143. package/python/mcp-server/a3m_mcp/server.py +205 -0
  144. package/python/mcp-server/pyproject.toml +24 -0
  145. package/python/pyproject.toml +60 -6
  146. package/python/setup.py +3 -28
  147. package/scripts/submit-sitemap.sh +52 -0
  148. package/src/__types__/registry.d.ts +14 -0
  149. package/src/cli/setupWizard.ts +443 -112
  150. package/src/cli/tui.ts +159 -0
  151. package/src/ensemble.ts +154 -1
  152. package/src/integrations/langchainAdapter.ts +2 -2
  153. package/src/providers/providerConfig.ts +32 -17
  154. package/src/providers/registry.js +27 -0
  155. package/src/routing/advancedRouter.ts +99 -14
  156. package/src/routing/shadowSampler.ts +1 -1
  157. package/test-install/package.json +12 -0
  158. package/tests/tsconfig.json +0 -1
  159. package/tmlpd-pi-extension/README.md +105 -44
  160. package/tmlpd-pi-extension/docs/demo.svg +33 -0
  161. package/tmlpd-pi-extension/package.json +35 -106
  162. package/tmlpd-pi-extension/src/tokenOptimization/contextStratifier.ts +163 -0
  163. package/tmlpd-pi-extension/src/tokenOptimization/fetchOnceLocal.ts +136 -0
  164. package/tmlpd-pi-extension/src/tokenOptimization/index.ts +197 -0
  165. package/tmlpd-pi-extension/src/tokenOptimization/interAgentCompression.ts +157 -0
  166. package/tmlpd-pi-extension/src/tokenOptimization/schemaContract.ts +101 -0
  167. package/tmlpd-pi-extension/src/tokenOptimization/semanticCache.ts +248 -0
  168. package/tmlpd-pi-extension/src/tokenOptimization/tokenAwareFallback.ts +192 -0
  169. package/tmlpd-pi-extension/test/verify.js +21 -0
  170. package/tsconfig.build.json +3 -2
  171. package/packages/a3m-vercel-ai/dist/a3m-language-model.d.ts +0 -12
  172. package/packages/a3m-vercel-ai/dist/a3m-language-model.d.ts.map +0 -1
  173. package/packages/a3m-vercel-ai/dist/a3m-language-model.js +0 -289
  174. package/packages/a3m-vercel-ai/dist/a3m-language-model.js.map +0 -1
  175. package/packages/a3m-vercel-ai/dist/index.d.ts +0 -82
  176. package/packages/a3m-vercel-ai/dist/index.d.ts.map +0 -1
  177. package/packages/a3m-vercel-ai/dist/index.js +0 -79
  178. package/packages/a3m-vercel-ai/dist/index.js.map +0 -1
  179. package/packages/a3m-vercel-ai/dist/types.d.ts +0 -97
  180. package/packages/a3m-vercel-ai/dist/types.d.ts.map +0 -1
  181. package/packages/a3m-vercel-ai/dist/types.js +0 -5
  182. package/packages/a3m-vercel-ai/dist/types.js.map +0 -1
  183. package/src/skills/__tests__/skill_manager.test.ts +0 -328
  184. package/tmlpd-pi-extension/dist/cache/prefixCache.d.ts +0 -114
  185. package/tmlpd-pi-extension/dist/cache/prefixCache.d.ts.map +0 -1
  186. package/tmlpd-pi-extension/dist/cache/prefixCache.js +0 -285
  187. package/tmlpd-pi-extension/dist/cache/prefixCache.js.map +0 -1
  188. package/tmlpd-pi-extension/dist/cache/responseCache.d.ts +0 -58
  189. package/tmlpd-pi-extension/dist/cache/responseCache.d.ts.map +0 -1
  190. package/tmlpd-pi-extension/dist/cache/responseCache.js +0 -153
  191. package/tmlpd-pi-extension/dist/cache/responseCache.js.map +0 -1
  192. package/tmlpd-pi-extension/dist/cli.js +0 -59
  193. package/tmlpd-pi-extension/dist/cost/costTracker.d.ts +0 -95
  194. package/tmlpd-pi-extension/dist/cost/costTracker.d.ts.map +0 -1
  195. package/tmlpd-pi-extension/dist/cost/costTracker.js +0 -240
  196. package/tmlpd-pi-extension/dist/cost/costTracker.js.map +0 -1
  197. package/tmlpd-pi-extension/dist/index.d.ts +0 -723
  198. package/tmlpd-pi-extension/dist/index.d.ts.map +0 -1
  199. package/tmlpd-pi-extension/dist/index.js +0 -239
  200. package/tmlpd-pi-extension/dist/index.js.map +0 -1
  201. package/tmlpd-pi-extension/dist/memory/episodicMemory.d.ts +0 -82
  202. package/tmlpd-pi-extension/dist/memory/episodicMemory.d.ts.map +0 -1
  203. package/tmlpd-pi-extension/dist/memory/episodicMemory.js +0 -145
  204. package/tmlpd-pi-extension/dist/memory/episodicMemory.js.map +0 -1
  205. package/tmlpd-pi-extension/dist/orchestration/haloOrchestrator.d.ts +0 -102
  206. package/tmlpd-pi-extension/dist/orchestration/haloOrchestrator.d.ts.map +0 -1
  207. package/tmlpd-pi-extension/dist/orchestration/haloOrchestrator.js +0 -207
  208. package/tmlpd-pi-extension/dist/orchestration/haloOrchestrator.js.map +0 -1
  209. package/tmlpd-pi-extension/dist/orchestration/mctsWorkflow.d.ts +0 -85
  210. package/tmlpd-pi-extension/dist/orchestration/mctsWorkflow.d.ts.map +0 -1
  211. package/tmlpd-pi-extension/dist/orchestration/mctsWorkflow.js +0 -210
  212. package/tmlpd-pi-extension/dist/orchestration/mctsWorkflow.js.map +0 -1
  213. package/tmlpd-pi-extension/dist/providers/localProvider.d.ts +0 -102
  214. package/tmlpd-pi-extension/dist/providers/localProvider.d.ts.map +0 -1
  215. package/tmlpd-pi-extension/dist/providers/localProvider.js +0 -338
  216. package/tmlpd-pi-extension/dist/providers/localProvider.js.map +0 -1
  217. package/tmlpd-pi-extension/dist/providers/registry.d.ts +0 -55
  218. package/tmlpd-pi-extension/dist/providers/registry.d.ts.map +0 -1
  219. package/tmlpd-pi-extension/dist/providers/registry.js +0 -138
  220. package/tmlpd-pi-extension/dist/providers/registry.js.map +0 -1
  221. package/tmlpd-pi-extension/dist/routing/advancedRouter.d.ts +0 -68
  222. package/tmlpd-pi-extension/dist/routing/advancedRouter.d.ts.map +0 -1
  223. package/tmlpd-pi-extension/dist/routing/advancedRouter.js +0 -332
  224. package/tmlpd-pi-extension/dist/routing/advancedRouter.js.map +0 -1
  225. package/tmlpd-pi-extension/dist/tools/tmlpdTools.d.ts +0 -101
  226. package/tmlpd-pi-extension/dist/tools/tmlpdTools.d.ts.map +0 -1
  227. package/tmlpd-pi-extension/dist/tools/tmlpdTools.js +0 -368
  228. package/tmlpd-pi-extension/dist/tools/tmlpdTools.js.map +0 -1
  229. package/tmlpd-pi-extension/dist/utils/batchProcessor.d.ts +0 -96
  230. package/tmlpd-pi-extension/dist/utils/batchProcessor.d.ts.map +0 -1
  231. package/tmlpd-pi-extension/dist/utils/batchProcessor.js +0 -170
  232. package/tmlpd-pi-extension/dist/utils/batchProcessor.js.map +0 -1
  233. package/tmlpd-pi-extension/dist/utils/compression.d.ts +0 -61
  234. package/tmlpd-pi-extension/dist/utils/compression.d.ts.map +0 -1
  235. package/tmlpd-pi-extension/dist/utils/compression.js +0 -281
  236. package/tmlpd-pi-extension/dist/utils/compression.js.map +0 -1
  237. package/tmlpd-pi-extension/dist/utils/reliability.d.ts +0 -74
  238. package/tmlpd-pi-extension/dist/utils/reliability.d.ts.map +0 -1
  239. package/tmlpd-pi-extension/dist/utils/reliability.js +0 -177
  240. package/tmlpd-pi-extension/dist/utils/reliability.js.map +0 -1
  241. package/tmlpd-pi-extension/dist/utils/speculativeDecoding.d.ts +0 -117
  242. package/tmlpd-pi-extension/dist/utils/speculativeDecoding.d.ts.map +0 -1
  243. package/tmlpd-pi-extension/dist/utils/speculativeDecoding.js +0 -246
  244. package/tmlpd-pi-extension/dist/utils/speculativeDecoding.js.map +0 -1
  245. package/tmlpd-pi-extension/dist/utils/tokenUtils.d.ts +0 -50
  246. package/tmlpd-pi-extension/dist/utils/tokenUtils.d.ts.map +0 -1
  247. package/tmlpd-pi-extension/dist/utils/tokenUtils.js +0 -124
  248. package/tmlpd-pi-extension/dist/utils/tokenUtils.js.map +0 -1
@@ -0,0 +1,172 @@
1
+ # A3M Router MCP Server (Python)
2
+
3
+ [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) server for [A3M Router](https://github.com/Das-rebel/a3m-router) — parallel multi-LLM execution for AI agents.
4
+
5
+ Allows any MCP-compatible AI agent (Claude Desktop, Cursor, Windsurf, Codex, n8n, etc.) to use A3M's intelligent routing and ensemble execution directly from Python.
6
+
7
+ ## Tools
8
+
9
+ | Tool | Description |
10
+ |------|-------------|
11
+ | `a3m_route` | Route a query to the optimal LLM provider — returns model, tier, cost, reasoning |
12
+ | `a3m_ensemble` | Execute a query across multiple providers in parallel and merge results |
13
+ | `a3m_classify` | Classify query type (fast/creative/deep/code) and get provider recommendations |
14
+ | `a3m_providers` | List all configured providers with cost and availability |
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ # From source
20
+ cd python/mcp-server
21
+ pip install -e .
22
+
23
+ # Or install the package directly (when published)
24
+ pip install a3m-mcp-server
25
+ ```
26
+
27
+ ## Configuration
28
+
29
+ Set environment variables:
30
+
31
+ ```bash
32
+ # Required: A3M Router URL (must be running)
33
+ export A3M_BASE_URL=http://localhost:8787
34
+
35
+ # Optional
36
+ export A3M_API_KEY=not-needed # default
37
+ export A3M_TIMEOUT=30.0
38
+ ```
39
+
40
+ ## Start A3M Router
41
+
42
+ ```bash
43
+ # Node.js way
44
+ npx a3m-router serve
45
+
46
+ # Python way
47
+ pip install a3m-router
48
+ a3m-router serve
49
+ ```
50
+
51
+ ## Usage
52
+
53
+ ### Claude Desktop
54
+
55
+ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
56
+
57
+ ```json
58
+ {
59
+ "mcpServers": {
60
+ "a3m-router": {
61
+ "command": "python",
62
+ "args": ["-m", "a3m_mcp"],
63
+ "env": {
64
+ "A3M_BASE_URL": "http://localhost:8787"
65
+ }
66
+ }
67
+ }
68
+ }
69
+ ```
70
+
71
+ ### Cursor
72
+
73
+ Settings → Features → MCP Servers → Add:
74
+
75
+ ```
76
+ Name: A3M Router
77
+ Command: python
78
+ Arguments: -m a3m_mcp
79
+ ```
80
+
81
+ ### n8n MCP Trigger
82
+
83
+ Add MCP Trigger node with:
84
+
85
+ ```json
86
+ {
87
+ "server": "a3m-router",
88
+ "command": "python",
89
+ "args": ["-m", "a3m_mcp"]
90
+ }
91
+ ```
92
+
93
+ ### Direct stdio (pipe JSON-RPC)
94
+
95
+ ```bash
96
+ # List tools
97
+ echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | python -m a3m_mcp
98
+
99
+ # Call a3m_route
100
+ echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"a3m_route","arguments":{"query":"Write a Python quicksort"}}}' | python -m a3m_mcp
101
+ ```
102
+
103
+ ## Examples
104
+
105
+ ### Route a query
106
+
107
+ ```python
108
+ # a3m_route tool
109
+ Input: {"query": "Write a Python function to sort a list"}
110
+ Output:
111
+ {
112
+ "model": "groq/llama-3.3-70b-versatile",
113
+ "tier": "cheap",
114
+ "cost": 0.000012,
115
+ "reasoning": "Code query detected, routing to fast coding provider",
116
+ "classification": "code"
117
+ }
118
+ ```
119
+
120
+ ### Ensemble execution
121
+
122
+ ```python
123
+ # a3m_ensemble tool
124
+ Input: {"query": "Explain quantum computing in 3 sentences", "providers": ["groq", "google", "cerebras"]}
125
+ Output:
126
+ {
127
+ "query": "Explain quantum computing in 3 sentences",
128
+ "parallel_responses": [
129
+ {"provider": "groq", "content": "Quantum computing is..."},
130
+ {"provider": "google", "content": "At its core, quantum..."},
131
+ {"provider": "cerebras", "content": "Quantum computing leverages..."}
132
+ ],
133
+ "best_answer": "Quantum computing is...",
134
+ "stats": {"total_providers": 3, "successful": 3, "failed": 0}
135
+ }
136
+ ```
137
+
138
+ ## Architecture
139
+
140
+ ```
141
+ ┌──────────────────────────────────────────────────────┐
142
+ │ MCP Client (Claude, Cursor, Codex, n8n) │
143
+ └──────────────────────┬───────────────────────────────┘
144
+ │ MCP Protocol (stdio)
145
+ ┌──────────────────────▼───────────────────────────────┐
146
+ │ A3M Router MCP Server (Python) │
147
+ │ │
148
+ │ a3m_route a3m_ensemble a3m_classify a3m_providers │
149
+ └──────────────────────┬───────────────────────────────┘
150
+ │ HTTP API
151
+ ┌──────────────────────▼───────────────────────────────┐
152
+ │ A3M Router (a3m-router serve) │
153
+ │ │
154
+ │ routeQuery() parallelEnsemble() providers │
155
+ └───────┬────────────┬────────────┬─────────────────────┘
156
+ │ │ │
157
+ ┌────▼───┐ ┌────▼───┐ ┌────▼───┐
158
+ │ Groq │ │ Google │ │Cerebras│ ...
159
+ └────────┘ └────────┘ └────────┘
160
+ ```
161
+
162
+ ## Testing
163
+
164
+ ```bash
165
+ cd python/mcp-server
166
+ pip install -e ".[dev]"
167
+ pytest
168
+ ```
169
+
170
+ ## License
171
+
172
+ MIT
@@ -0,0 +1,25 @@
1
+ """
2
+ A3M Router MCP Server
3
+
4
+ MCP (Model Context Protocol) server for A3M Router.
5
+ Provides intelligent LLM routing and ensemble execution as MCP tools.
6
+ """
7
+
8
+ __version__ = "1.0.0"
9
+
10
+ # Try to import MCP components
11
+ HAS_MCP = False
12
+ SERVER_NAME = "a3m-router"
13
+
14
+ try:
15
+ from mcp.server.lowlevel import Server
16
+ from mcp import Tool
17
+ HAS_MCP = True
18
+ except ImportError:
19
+ pass
20
+
21
+ # Import main if available
22
+ try:
23
+ from .server import main
24
+ except ImportError:
25
+ main = None
@@ -0,0 +1,15 @@
1
+ """Entry point: python -m a3m_mcp"""
2
+ import sys
3
+ import os
4
+
5
+ # Add parent directory to path so a3m_mcp can find sibling packages
6
+ sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
7
+
8
+ from .server import main, HAS_MCP
9
+
10
+ if __name__ == "__main__":
11
+ if not HAS_MCP:
12
+ print("ERROR: mcp package required. Install with: pip install mcp", file=sys.stderr)
13
+ sys.exit(1)
14
+ import asyncio
15
+ asyncio.run(main())
@@ -0,0 +1,205 @@
1
+ """
2
+ A3M Router MCP Server - MCP Protocol Server for A3M Router
3
+
4
+ MCP 2.0.0 compatible server that provides A3M Router functionality
5
+ as MCP tools for AI agents.
6
+ """
7
+
8
+ import os
9
+ import asyncio
10
+ import json
11
+ from typing import Optional, List, Any
12
+
13
+ try:
14
+ from mcp.server.lowlevel import Server
15
+ from mcp import Tool, ListToolsResult
16
+ from mcp.types import CallToolResult, TextContent
17
+ from mcp.server.stdio import stdio_server
18
+ HAS_MCP = True
19
+ except ImportError:
20
+ HAS_MCP = False
21
+ print("WARNING: mcp package not installed. Run: pip install mcp", flush=True)
22
+
23
+ # A3M Router client
24
+ try:
25
+ import a3m
26
+ A3MRouter = a3m.A3MRouter
27
+ except ImportError:
28
+ A3MRouter = None
29
+
30
+
31
+ SERVER_NAME = "a3m-router"
32
+ SERVER_VERSION = "1.0.0"
33
+
34
+ _router: Optional["A3MRouter"] = None
35
+
36
+
37
+ def get_router() -> "A3MRouter":
38
+ """Get or create A3MRouter instance."""
39
+ global _router
40
+ if _router is None:
41
+ base_url = os.environ.get("A3M_BASE_URL", "http://localhost:8787")
42
+ api_key = os.environ.get("A3M_API_KEY", "")
43
+ _router = A3MRouter(base_url=base_url, api_key=api_key)
44
+ return _router
45
+
46
+
47
+ # Tool definitions
48
+ TOOLS = [
49
+ Tool(
50
+ name="a3m_route",
51
+ title="Route Query",
52
+ description="Route a query to the optimal LLM provider using A3M's adaptive routing. Returns model selection, tier, estimated cost, and reasoning.",
53
+ inputSchema={
54
+ "type": "object",
55
+ "properties": {
56
+ "query": {
57
+ "type": "string",
58
+ "description": "The user query to route (e.g. 'Write Python code to sort a list')",
59
+ },
60
+ "provider": {
61
+ "type": "string",
62
+ "description": "Optional: Force a specific provider (e.g. 'groq', 'google')",
63
+ },
64
+ },
65
+ "required": ["query"],
66
+ },
67
+ ),
68
+ Tool(
69
+ name="a3m_chat",
70
+ title="Chat with A3M",
71
+ description="Send a chat message through A3M Router's adaptive routing.",
72
+ inputSchema={
73
+ "type": "object",
74
+ "properties": {
75
+ "query": {
76
+ "type": "string",
77
+ "description": "The user query",
78
+ },
79
+ },
80
+ "required": ["query"],
81
+ },
82
+ ),
83
+ Tool(
84
+ name="a3m_cost_report",
85
+ title="Cost Report",
86
+ description="Get cost analytics across all providers.",
87
+ inputSchema={
88
+ "type": "object",
89
+ "properties": {},
90
+ },
91
+ ),
92
+ Tool(
93
+ name="a3m_models",
94
+ title="List Models",
95
+ description="List all available models with cost/latency info.",
96
+ inputSchema={
97
+ "type": "object",
98
+ "properties": {},
99
+ },
100
+ ),
101
+ ]
102
+
103
+
104
+ class A3MServer:
105
+ """A3M Router MCP Server with tool handlers."""
106
+
107
+ def __init__(self):
108
+ pass
109
+
110
+ async def handle_list_tools(self, request_context=None) -> ListToolsResult:
111
+ """Handle tools/list request."""
112
+ return ListToolsResult(
113
+ tools=[
114
+ {
115
+ "name": t.name,
116
+ "description": t.description,
117
+ "inputSchema": t.inputSchema,
118
+ }
119
+ for t in TOOLS
120
+ ]
121
+ )
122
+
123
+ async def handle_call_tool(self, request_context, name: str, arguments: dict) -> CallToolResult:
124
+ """Handle tools/call request."""
125
+ try:
126
+ if name == "a3m_route":
127
+ router = get_router()
128
+ query = arguments.get("query")
129
+ provider = arguments.get("provider")
130
+
131
+ result = router.route(query, provider=provider)
132
+ return CallToolResult(
133
+ content=[TextContent(type="text", text=json.dumps(result, indent=2))]
134
+ )
135
+
136
+ elif name == "a3m_chat":
137
+ router = get_router()
138
+ query = arguments.get("query")
139
+
140
+ result = router.chat(query)
141
+ return CallToolResult(
142
+ content=[TextContent(type="text", text=str(result))]
143
+ )
144
+
145
+ elif name == "a3m_cost_report":
146
+ router = get_router()
147
+ report = router.cost_report()
148
+ return CallToolResult(
149
+ content=[TextContent(type="text", text=json.dumps(report, indent=2))]
150
+ )
151
+
152
+ elif name == "a3m_models":
153
+ router = get_router()
154
+ models = router.models()
155
+ return CallToolResult(
156
+ content=[TextContent(type="text", text=json.dumps(models, indent=2))]
157
+ )
158
+
159
+ else:
160
+ return CallToolResult(
161
+ content=[TextContent(type="text", text=f"Unknown tool: {name}")],
162
+ isError=True,
163
+ )
164
+
165
+ except Exception as e:
166
+ return CallToolResult(
167
+ content=[TextContent(type="text", text=f"Error: {str(e)}")],
168
+ isError=True,
169
+ )
170
+
171
+
172
+ if HAS_MCP:
173
+ # Create server with handlers
174
+ a3m_server = A3MServer()
175
+
176
+ server = Server(
177
+ SERVER_NAME,
178
+ version=SERVER_VERSION,
179
+ on_list_tools=a3m_server.handle_list_tools,
180
+ on_call_tool=a3m_server.handle_call_tool,
181
+ )
182
+
183
+
184
+ async def main():
185
+ """Main entry point for MCP server."""
186
+ if not HAS_MCP:
187
+ print("ERROR: mcp package not installed", flush=True)
188
+ return
189
+
190
+ print(f"Starting {SERVER_NAME} MCP Server v{SERVER_VERSION}", flush=True)
191
+
192
+ async with stdio_server() as (read_stream, write_stream):
193
+ await server.run(
194
+ read_stream,
195
+ write_stream,
196
+ server.create_initialization_options(),
197
+ )
198
+
199
+
200
+ if __name__ == "__main__":
201
+ if HAS_MCP:
202
+ asyncio.run(main())
203
+ else:
204
+ print("ERROR: mcp package required", flush=True)
205
+ print("Run: pip install mcp", flush=True)
@@ -0,0 +1,24 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "a3m-mcp-server"
7
+ version = "1.0.0"
8
+ description = "MCP server for A3M Router — parallel multi-LLM execution for AI agents"
9
+ readme = "README.md"
10
+ license = {text = "MIT"}
11
+ requires-python = ">=3.10"
12
+ dependencies = [
13
+ "mcp>=1.0.0",
14
+ "httpx>=0.24.0",
15
+ ]
16
+
17
+ [project.optional-dependencies]
18
+ dev = ["pytest>=7.4.0", "pytest-asyncio>=0.21.0", "black>=23.0.0"]
19
+
20
+ [project.urls]
21
+ Homepage = "https://github.com/Das-rebel/a3m-router"
22
+
23
+ [tool.setuptools.packages.find]
24
+ where = ["."]
@@ -1,23 +1,77 @@
1
1
  [build-system]
2
- requires = ["setuptools>=64", "wheel"]
3
- build-backend = "setuptools.backends._legacy:_Backend"
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "a3m-router"
7
- version = "2.1.0"
8
- description = "Python SDK for A3M Router intelligent LLM routing with 99.5% accuracy"
7
+ version = "2.16.2"
8
+ description = "Auto-selects cheapest capable LLM from 47+ providers 70-95% cost savings"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
11
11
  requires-python = ">=3.8"
12
12
  dependencies = ["httpx>=0.24.0"]
13
- keywords = ["llm", "routing", "openai", "proxy", "ai-gateway", "routellm", "litellm"]
13
+
14
+ keywords = [
15
+ "llm",
16
+ "routing",
17
+ "openai",
18
+ "proxy",
19
+ "ai-gateway",
20
+ "routellm",
21
+ "litellm",
22
+ "multi-llm",
23
+ "model-selection",
24
+ "cost-optimization",
25
+ "langchain",
26
+ "llamaindex",
27
+ "rag",
28
+ "vector-search",
29
+ "embeddings",
30
+ "parallel",
31
+ "ensemble",
32
+ "router",
33
+ ]
34
+
14
35
  classifiers = [
15
36
  "Development Status :: 4 - Beta",
16
37
  "Intended Audience :: Developers",
17
38
  "License :: OSI Approved :: MIT License",
39
+ "Operating System :: OS Independent",
18
40
  "Programming Language :: Python :: 3",
41
+ "Programming Language :: Python :: 3.8",
42
+ "Programming Language :: Python :: 3.9",
43
+ "Programming Language :: Python :: 3.10",
44
+ "Programming Language :: Python :: 3.11",
45
+ "Programming Language :: Python :: 3.12",
19
46
  "Topic :: Software Development :: Libraries :: Python Modules",
47
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
20
48
  ]
21
49
 
50
+ [project.optional-dependencies]
51
+ langchain = ["langchain>=0.1.0"]
52
+ llamaindex = ["llamaindex>=0.9.0"]
53
+ qdrant = ["qdrant-client>=1.7.0"]
54
+ weaviate = ["weaviate-client>=4.0.0"]
55
+ adapters = [
56
+ "langchain>=0.1.0",
57
+ "llamaindex>=0.9.0",
58
+ "qdrant-client>=1.7.0",
59
+ "weaviate-client>=4.0.0",
60
+ ]
61
+ dev = ["pytest>=7.4.0", "pytest-asyncio>=0.21.0", "black>=23.0.0"]
62
+
22
63
  [project.urls]
23
- Homepage = "https://github.com/Das-rebel/a3m-router"
64
+ Homepage = "https://github.com/Das-rebel/a3m-router#a3m-router"
65
+ Documentation = "https://github.com/Das-rebel/a3m-router#readme"
66
+ Repository = "https://github.com/Das-rebel/a3m-router"
67
+ Changelog = "https://github.com/Das-rebel/a3m-router/releases"
68
+ "NPM Package" = "https://www.npmjs.com/package/adaptive-memory-multi-model-router"
69
+ "PyPI Package" = "https://pypi.org/project/a3m-router/"
70
+ "GitHub Stars" = "https://github.com/Das-rebel/a3m-router/stargazers"
71
+
72
+ [tool.setuptools.packages.find]
73
+ where = ["."]
74
+ include = ["a3m*"]
75
+
76
+ [tool.black]
77
+ line-length = 100
package/python/setup.py CHANGED
@@ -1,28 +1,3 @@
1
- {
2
- "name": "tmlpd-python",
3
- "version": "1.1.0",
4
- "description": "Python bindings for tmlpd-pi - Parallel Multi-LLM Processing with TypeScript compatibility",
5
- "main": "tmlpd.py",
6
- "keywords": [
7
- "tmlpd",
8
- "python",
9
- "bindings",
10
- "parallel",
11
- "multi-llm",
12
- "llm",
13
- "openai",
14
- "anthropic",
15
- "google",
16
- "groq",
17
- "cerebras",
18
- "langchain",
19
- "agent",
20
- "orchestration"
21
- ],
22
- "author": "Subho Das",
23
- "license": "MIT",
24
- "python_requires": ">=3.8",
25
- "dependencies": {},
26
- "devDependencies": {},
27
- "readme": "See python/examples.py for usage"
28
- }
1
+ from setuptools import setup
2
+
3
+ setup()
@@ -0,0 +1,52 @@
1
+ #!/bin/bash
2
+ #
3
+ # A3M Router — Sitemap Submission Script
4
+ # Submits sitemap to Google, Bing, and IndexNow for faster indexing
5
+ #
6
+ set -e
7
+
8
+ SITEMAP_URL="${SITEMAP_URL:-https://a3m-router.com/sitemap.xml}"
9
+ INDEXNOW_KEY="${INDEXNOW_KEY:-}"
10
+
11
+ echo "=== A3M Router Sitemap Submission ==="
12
+ echo "Sitemap: $SITEMAP_URL"
13
+ echo ""
14
+
15
+ # ─── Google ───────────────────────────────────────────
16
+ echo "[1/3] Submitting to Google..."
17
+ GOOGLE_STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
18
+ "https://www.google.com/ping?sitemap=$SITEMAP_URL")
19
+ if [ "$GOOGLE_STATUS" = "200" ]; then
20
+ echo " ✅ Google: OK (HTTP $GOOGLE_STATUS)"
21
+ else
22
+ echo " ⚠️ Google: HTTP $GOOGLE_STATUS"
23
+ fi
24
+
25
+ # ─── Bing ─────────────────────────────────────────────
26
+ echo "[2/3] Submitting to Bing..."
27
+ BING_STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
28
+ "https://www.bing.com/ping?sitemap=$SITEMAP_URL")
29
+ if [ "$BING_STATUS" = "200" ]; then
30
+ echo " ✅ Bing: OK (HTTP $BING_STATUS)"
31
+ else
32
+ echo " ⚠️ Bing: HTTP $BING_STATUS"
33
+ fi
34
+
35
+ # ─── IndexNow ─────────────────────────────────────────
36
+ echo "[3/3] Submitting to IndexNow..."
37
+ if [ -z "$INDEXNOW_KEY" ]; then
38
+ echo " ⚠️ Skipped: INDEXNOW_KEY env var not set"
39
+ echo " To enable IndexNow: export INDEXNOW_KEY=your_key_from_indexnow.org"
40
+ else
41
+ # Get the sitemap URLs and submit each to IndexNow
42
+ curl -s "$SITEMAP_URL" | grep -oP '(?<=<loc>)[^<]+' | while read -r url; do
43
+ RESPONSE=$(curl -s -w "%{http_code}" -o /dev/null -X POST \
44
+ "https://indexnow.org/ping" \
45
+ -H "Content-Type: text/plain" \
46
+ -d "url=$url&key=$INDEXNOW_KEY")
47
+ echo " IndexNow: $url → HTTP $RESPONSE"
48
+ done
49
+ fi
50
+
51
+ echo ""
52
+ echo "=== Done ==="
@@ -0,0 +1,14 @@
1
+ declare module '@my-org/a3m-router/src/providers/registry' {
2
+ const PROVIDERS: Map<string, any>;
3
+ const registry: Map<string, any>;
4
+ export function registerProvider(name: string, config: any): void;
5
+ export function getProvider(name: string): any;
6
+ export function listProviders(): Array<[string, any]>;
7
+ export interface ProviderRegistry {
8
+ registerProvider: (name: string, config: any) => void;
9
+ getProvider: (name: string) => any;
10
+ listProviders: () => Array<[string, any]>;
11
+ }
12
+ const registryInstance: ProviderRegistry;
13
+ export default registryInstance;
14
+ }