matimo-core 0.1.3__tar.gz → 0.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.
- {matimo_core-0.1.3 → matimo_core-0.2.0}/.gitignore +3 -1
- matimo_core-0.2.0/LICENSE +21 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/PKG-INFO +35 -17
- {matimo_core-0.1.3 → matimo_core-0.2.0}/README.md +27 -14
- {matimo_core-0.1.3 → matimo_core-0.2.0}/pyproject.toml +7 -4
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/__init__.py +56 -6
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/approval/handler.py +74 -17
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/auth/injection.py +34 -27
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/auth/oauth2_handler.py +3 -3
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/core/loader.py +3 -2
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/core/models.py +6 -0
- matimo_core-0.2.0/src/matimo/core/response_size_guardrail.py +150 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/core/skill_content_parser.py +28 -9
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/core/skill_loader.py +1 -1
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/core/skill_registry.py +6 -5
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/decorators/__init__.py +3 -1
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/errors.py +22 -3
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/executors/function_executor.py +50 -7
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/executors/http_executor.py +51 -14
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/instance.py +467 -50
- matimo_core-0.2.0/src/matimo/integrations/_async_bridge.py +65 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/integrations/_pydantic_utils.py +50 -20
- matimo_core-0.2.0/src/matimo/integrations/agno.py +407 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/integrations/crewai.py +106 -6
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/integrations/langchain.py +17 -4
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/logging/__init__.py +8 -7
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/mcp/README.md +39 -44
- matimo_core-0.2.0/src/matimo/mcp/approval_elicitation.py +90 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/mcp/secrets/__init__.py +4 -4
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/mcp/server.py +227 -63
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/mcp/tool_converter.py +96 -8
- matimo_core-0.2.0/src/matimo/policy/audit_sink.py +179 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/policy/content_validator.py +24 -21
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/policy/default_policy.py +36 -16
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/policy/policy_loader.py +7 -2
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/policy/risk_classifier.py +33 -6
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/policy/types.py +48 -1
- matimo_core-0.2.0/src/matimo/skills/meta-tools-lifecycle/SKILL.md +306 -0
- matimo_core-0.2.0/src/matimo/skills/policy-validation/SKILL.md +233 -0
- matimo_core-0.2.0/src/matimo/skills/skill-creator/SKILL.md +439 -0
- matimo_core-0.2.0/src/matimo/skills/skills-catalog/SKILL.md +191 -0
- matimo_core-0.2.0/src/matimo/skills/tool-creation/SKILL.md +303 -0
- matimo_core-0.2.0/src/matimo/skills/tool-discovery/SKILL.md +176 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/calculator/definition.yaml +1 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/convert_to_file/definition.yaml +1 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/edit/definition.yaml +1 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/execute/definition.yaml +3 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/extract_from_file/definition.yaml +1 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/matimo_approve_tool/definition.yaml +2 -1
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/matimo_approve_tool/matimo_approve_tool.py +56 -2
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/matimo_create_skill/definition.yaml +1 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/matimo_create_skill/matimo_create_skill.py +24 -2
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/matimo_create_tool/definition.yaml +1 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/matimo_create_tool/matimo_create_tool.py +19 -5
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/matimo_get_skill/definition.yaml +1 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/matimo_get_skill/matimo_get_skill.py +3 -2
- matimo_core-0.2.0/src/matimo/tools/matimo_get_skill_content/definition.yaml +57 -0
- matimo_core-0.2.0/src/matimo/tools/matimo_get_skill_content/matimo_get_skill_content.py +63 -0
- matimo_core-0.2.0/src/matimo/tools/matimo_get_skill_sections/definition.yaml +37 -0
- matimo_core-0.2.0/src/matimo/tools/matimo_get_skill_sections/matimo_get_skill_sections.py +48 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/matimo_get_tool/definition.yaml +1 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/matimo_get_tool_status/definition.yaml +1 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/matimo_get_tool_status/matimo_get_tool_status.py +18 -3
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/matimo_list_skills/definition.yaml +1 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/matimo_list_skills/matimo_list_skills.py +13 -12
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/matimo_list_user_tools/definition.yaml +1 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/matimo_list_user_tools/matimo_list_user_tools.py +2 -1
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/matimo_reload_tools/definition.yaml +1 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/matimo_reload_tools/matimo_reload_tools.py +2 -1
- matimo_core-0.2.0/src/matimo/tools/matimo_search_skills/definition.yaml +46 -0
- matimo_core-0.2.0/src/matimo/tools/matimo_search_skills/matimo_search_skills.py +53 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/matimo_search_tools/definition.yaml +1 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/matimo_search_tools/matimo_search_tools.py +2 -1
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/matimo_validate_skill/definition.yaml +1 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/matimo_validate_tool/definition.yaml +1 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/matimo_validate_tool/matimo_validate_tool.py +15 -3
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/read/definition.yaml +1 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/search/definition.yaml +3 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/web/definition.yaml +1 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/web_scraper/definition.yaml +1 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/approval/__init__.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/auth/__init__.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/auth/oauth2_config.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/auth/oauth2_provider_loader.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/core/__init__.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/core/registry.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/core/tfidf_embedding.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/encodings/__init__.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/encodings/parameter_encoding.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/executors/__init__.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/executors/command_executor.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/integrations/__init__.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/mcp/__init__.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/mcp/secrets/types.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/policy/__init__.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/policy/approval_manifest.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/policy/integrity_tracker.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/sync.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/calculator/calculator.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/convert_to_file/convert_to_file.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/edit/edit.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/execute/execute.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/extract_from_file/extract_from_file.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/matimo_get_tool/matimo_get_tool.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/matimo_validate_skill/matimo_validate_skill.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/read/read.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/search/search.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/web/web.py +0 -0
- {matimo_core-0.1.3 → matimo_core-0.2.0}/src/matimo/tools/web_scraper/web_scraper.py +0 -0
|
@@ -58,7 +58,6 @@ temp/
|
|
|
58
58
|
|
|
59
59
|
# Personal scratch notes / working docs — not part of the shipped repo
|
|
60
60
|
.local-notes/
|
|
61
|
-
typescript/examples/mcp/matimo-tools/.matimo-approvals.json
|
|
62
61
|
typescript/examples/mcp/matimo-tools/fetch-weather/definition.yaml
|
|
63
62
|
typescript/examples/mcp/matimo-tools/npm_downloads/definition.yaml
|
|
64
63
|
typescript/examples/mcp/matimo-tools/skills/ecosystem-health/SKILL.md
|
|
@@ -68,3 +67,6 @@ typescript/packages/cli/.matimo/certs/server.crt
|
|
|
68
67
|
typescript/packages/cli/.matimo/certs/server.key
|
|
69
68
|
typescript/examples/mcp/.matimo/certs/server.crt
|
|
70
69
|
typescript/examples/mcp/.matimo/certs/server.key
|
|
70
|
+
|
|
71
|
+
# HITL approval manifests are per-machine state (HMAC-signed approvals); never commit one
|
|
72
|
+
**/.matimo-approvals.json
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ROAIQ TECHNOLOGIES PRIVATE LIMITED
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: matimo-core
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Matimo core — framework-agnostic SDK: pre-built providers, skills layer, MCP, and a policy engine you control
|
|
5
5
|
Project-URL: Homepage, https://matimo.dev
|
|
6
|
-
Project-URL: Documentation, https://matimo.dev/
|
|
6
|
+
Project-URL: Documentation, https://docs.matimo.dev/
|
|
7
7
|
Project-URL: Repository, https://github.com/tallclub/matimo
|
|
8
8
|
Project-URL: Issues, https://github.com/tallclub/matimo/issues
|
|
9
9
|
License: MIT
|
|
10
|
-
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: agentic-ai,agents,agno,ai,ai-governance,crewai,langchain,matimo,mcp,mcp-server,policy-engine,tools
|
|
11
12
|
Classifier: Development Status :: 4 - Beta
|
|
12
13
|
Classifier: Intended Audience :: Developers
|
|
13
14
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -31,7 +32,10 @@ Requires-Dist: readability-lxml>=0.8.4.1
|
|
|
31
32
|
Requires-Dist: reportlab>=4.0
|
|
32
33
|
Requires-Dist: simpleeval>=1.0
|
|
33
34
|
Requires-Dist: typing-extensions>=4.9
|
|
35
|
+
Provides-Extra: agno
|
|
36
|
+
Requires-Dist: agno>=3.0; extra == 'agno'
|
|
34
37
|
Provides-Extra: all
|
|
38
|
+
Requires-Dist: agno>=3.0; extra == 'all'
|
|
35
39
|
Requires-Dist: crewai>=0.80; extra == 'all'
|
|
36
40
|
Requires-Dist: hvac>=2.0; extra == 'all'
|
|
37
41
|
Requires-Dist: langchain-core>=0.3; extra == 'all'
|
|
@@ -42,6 +46,7 @@ Requires-Dist: boto3>=1.34; extra == 'aws'
|
|
|
42
46
|
Provides-Extra: crewai
|
|
43
47
|
Requires-Dist: crewai>=0.80; extra == 'crewai'
|
|
44
48
|
Provides-Extra: dev
|
|
49
|
+
Requires-Dist: agno>=3.0; extra == 'dev'
|
|
45
50
|
Requires-Dist: boto3>=1.34; extra == 'dev'
|
|
46
51
|
Requires-Dist: crewai>=0.80; extra == 'dev'
|
|
47
52
|
Requires-Dist: hvac>=2.0; extra == 'dev'
|
|
@@ -71,7 +76,7 @@ Description-Content-Type: text/markdown
|
|
|
71
76
|
|
|
72
77
|
[](https://pypi.org/project/matimo-core/)
|
|
73
78
|
[](https://pypi.org/project/matimo-core/)
|
|
74
|
-
[](https://matimo.dev
|
|
79
|
+
[](https://docs.matimo.dev)
|
|
75
80
|
[](https://github.com/tallclub/matimo)
|
|
76
81
|
[](https://github.com/tallclub/matimo)
|
|
77
82
|
|
|
@@ -188,7 +193,7 @@ await server.start()
|
|
|
188
193
|
### `Matimo.init()`
|
|
189
194
|
|
|
190
195
|
```python
|
|
191
|
-
from matimo import
|
|
196
|
+
from matimo import InitOptions, JsonlFileSink, Matimo
|
|
192
197
|
|
|
193
198
|
matimo = await Matimo.init(
|
|
194
199
|
tool_paths=['./tools', './agent-tools'], # or a single string
|
|
@@ -199,6 +204,7 @@ matimo = await Matimo.init(
|
|
|
199
204
|
log_level='info', # silent | error | warn | info | debug
|
|
200
205
|
log_format='json', # json | simple
|
|
201
206
|
on_event=my_event_handler,
|
|
207
|
+
audit_sink=JsonlFileSink('./logs/matimo-audit.jsonl'), # hash-chained audit log
|
|
202
208
|
on_hitl=my_approval_callback,
|
|
203
209
|
)
|
|
204
210
|
```
|
|
@@ -242,14 +248,23 @@ execution:
|
|
|
242
248
|
## Policy Engine
|
|
243
249
|
|
|
244
250
|
```python
|
|
245
|
-
from matimo import
|
|
251
|
+
from matimo import ApprovalRequest, JsonlFileSink, Matimo
|
|
246
252
|
|
|
247
|
-
|
|
253
|
+
|
|
254
|
+
async def ask_operator(request: ApprovalRequest) -> bool:
|
|
255
|
+
return input(f"Approve {request.tool_name} {request.params}? (y/n) ") == "y"
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
matimo = await Matimo.init(
|
|
259
|
+
'./tools',
|
|
248
260
|
policy_file='./policy.yaml',
|
|
249
|
-
|
|
250
|
-
)
|
|
261
|
+
on_approval=ask_operator, # calls that need approval ask here
|
|
262
|
+
audit_sink=JsonlFileSink('./matimo-audit.jsonl'), # hash-chained audit log
|
|
263
|
+
)
|
|
251
264
|
```
|
|
252
265
|
|
|
266
|
+
Calls that need approval: tools with `requires_approval: true`, HTTP `DELETE` and command tools (the 0.2.0 secure default), and calls whose `sql`/`command` argument contains a destructive keyword. With no `on_approval` they are refused.
|
|
267
|
+
|
|
253
268
|
`policy.yaml`:
|
|
254
269
|
```yaml
|
|
255
270
|
allowedDomains:
|
|
@@ -309,25 +324,28 @@ Built-in tools that let agents manage other tools at runtime:
|
|
|
309
324
|
| `matimo_list_skills` | List available skills | No |
|
|
310
325
|
| `matimo_get_skill` | Read skill content | No |
|
|
311
326
|
| `matimo_validate_skill` | Validate skill spec | No |
|
|
327
|
+
| `matimo_search_skills` | Semantically rank skills by relevance (TF-IDF) | No |
|
|
328
|
+
| `matimo_get_skill_sections` | Inventory a skill's sections and token costs | No |
|
|
329
|
+
| `matimo_get_skill_content` | Load only specific sections of a skill | No |
|
|
312
330
|
|
|
313
331
|
---
|
|
314
332
|
|
|
315
333
|
## Documentation
|
|
316
334
|
|
|
317
|
-
- [Getting Started](https://matimo.dev/
|
|
318
|
-
- [Full API Reference](https://matimo.dev/
|
|
319
|
-
- [LangChain Integration](https://matimo.dev/
|
|
320
|
-
- [CrewAI Integration](https://matimo.dev/
|
|
321
|
-
- [MCP Guide](https://matimo.dev/
|
|
322
|
-
- [Policy & Lifecycle](https://matimo.dev/
|
|
323
|
-
- [Meta-Tools Reference](https://matimo.dev/
|
|
335
|
+
- [Getting Started](https://docs.matimo.dev/getting-started/QUICK_START)
|
|
336
|
+
- [Full API Reference](https://docs.matimo.dev/api-reference/SDK)
|
|
337
|
+
- [LangChain Integration](https://docs.matimo.dev/framework-integrations/LANGCHAIN)
|
|
338
|
+
- [CrewAI Integration](https://docs.matimo.dev/framework-integrations/CREWAI)
|
|
339
|
+
- [MCP Guide](https://docs.matimo.dev/MCP)
|
|
340
|
+
- [Policy & Lifecycle](https://docs.matimo.dev/api-reference/POLICY_AND_LIFECYCLE)
|
|
341
|
+
- [Meta-Tools Reference](https://docs.matimo.dev/api-reference/META_TOOLS)
|
|
324
342
|
|
|
325
343
|
---
|
|
326
344
|
|
|
327
345
|
## Links
|
|
328
346
|
|
|
329
347
|
- **PyPI:** https://pypi.org/project/matimo-core/
|
|
330
|
-
- **Docs:** https://matimo.dev/
|
|
348
|
+
- **Docs:** https://docs.matimo.dev/
|
|
331
349
|
- **GitHub:** https://github.com/tallclub/matimo
|
|
332
350
|
- **Changelog:** https://github.com/tallclub/matimo/blob/main/docs/RELEASES.md
|
|
333
351
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
[](https://pypi.org/project/matimo-core/)
|
|
6
6
|
[](https://pypi.org/project/matimo-core/)
|
|
7
|
-
[](https://matimo.dev
|
|
7
|
+
[](https://docs.matimo.dev)
|
|
8
8
|
[](https://github.com/tallclub/matimo)
|
|
9
9
|
[](https://github.com/tallclub/matimo)
|
|
10
10
|
|
|
@@ -121,7 +121,7 @@ await server.start()
|
|
|
121
121
|
### `Matimo.init()`
|
|
122
122
|
|
|
123
123
|
```python
|
|
124
|
-
from matimo import
|
|
124
|
+
from matimo import InitOptions, JsonlFileSink, Matimo
|
|
125
125
|
|
|
126
126
|
matimo = await Matimo.init(
|
|
127
127
|
tool_paths=['./tools', './agent-tools'], # or a single string
|
|
@@ -132,6 +132,7 @@ matimo = await Matimo.init(
|
|
|
132
132
|
log_level='info', # silent | error | warn | info | debug
|
|
133
133
|
log_format='json', # json | simple
|
|
134
134
|
on_event=my_event_handler,
|
|
135
|
+
audit_sink=JsonlFileSink('./logs/matimo-audit.jsonl'), # hash-chained audit log
|
|
135
136
|
on_hitl=my_approval_callback,
|
|
136
137
|
)
|
|
137
138
|
```
|
|
@@ -175,14 +176,23 @@ execution:
|
|
|
175
176
|
## Policy Engine
|
|
176
177
|
|
|
177
178
|
```python
|
|
178
|
-
from matimo import
|
|
179
|
+
from matimo import ApprovalRequest, JsonlFileSink, Matimo
|
|
179
180
|
|
|
180
|
-
|
|
181
|
+
|
|
182
|
+
async def ask_operator(request: ApprovalRequest) -> bool:
|
|
183
|
+
return input(f"Approve {request.tool_name} {request.params}? (y/n) ") == "y"
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
matimo = await Matimo.init(
|
|
187
|
+
'./tools',
|
|
181
188
|
policy_file='./policy.yaml',
|
|
182
|
-
|
|
183
|
-
)
|
|
189
|
+
on_approval=ask_operator, # calls that need approval ask here
|
|
190
|
+
audit_sink=JsonlFileSink('./matimo-audit.jsonl'), # hash-chained audit log
|
|
191
|
+
)
|
|
184
192
|
```
|
|
185
193
|
|
|
194
|
+
Calls that need approval: tools with `requires_approval: true`, HTTP `DELETE` and command tools (the 0.2.0 secure default), and calls whose `sql`/`command` argument contains a destructive keyword. With no `on_approval` they are refused.
|
|
195
|
+
|
|
186
196
|
`policy.yaml`:
|
|
187
197
|
```yaml
|
|
188
198
|
allowedDomains:
|
|
@@ -242,25 +252,28 @@ Built-in tools that let agents manage other tools at runtime:
|
|
|
242
252
|
| `matimo_list_skills` | List available skills | No |
|
|
243
253
|
| `matimo_get_skill` | Read skill content | No |
|
|
244
254
|
| `matimo_validate_skill` | Validate skill spec | No |
|
|
255
|
+
| `matimo_search_skills` | Semantically rank skills by relevance (TF-IDF) | No |
|
|
256
|
+
| `matimo_get_skill_sections` | Inventory a skill's sections and token costs | No |
|
|
257
|
+
| `matimo_get_skill_content` | Load only specific sections of a skill | No |
|
|
245
258
|
|
|
246
259
|
---
|
|
247
260
|
|
|
248
261
|
## Documentation
|
|
249
262
|
|
|
250
|
-
- [Getting Started](https://matimo.dev/
|
|
251
|
-
- [Full API Reference](https://matimo.dev/
|
|
252
|
-
- [LangChain Integration](https://matimo.dev/
|
|
253
|
-
- [CrewAI Integration](https://matimo.dev/
|
|
254
|
-
- [MCP Guide](https://matimo.dev/
|
|
255
|
-
- [Policy & Lifecycle](https://matimo.dev/
|
|
256
|
-
- [Meta-Tools Reference](https://matimo.dev/
|
|
263
|
+
- [Getting Started](https://docs.matimo.dev/getting-started/QUICK_START)
|
|
264
|
+
- [Full API Reference](https://docs.matimo.dev/api-reference/SDK)
|
|
265
|
+
- [LangChain Integration](https://docs.matimo.dev/framework-integrations/LANGCHAIN)
|
|
266
|
+
- [CrewAI Integration](https://docs.matimo.dev/framework-integrations/CREWAI)
|
|
267
|
+
- [MCP Guide](https://docs.matimo.dev/MCP)
|
|
268
|
+
- [Policy & Lifecycle](https://docs.matimo.dev/api-reference/POLICY_AND_LIFECYCLE)
|
|
269
|
+
- [Meta-Tools Reference](https://docs.matimo.dev/api-reference/META_TOOLS)
|
|
257
270
|
|
|
258
271
|
---
|
|
259
272
|
|
|
260
273
|
## Links
|
|
261
274
|
|
|
262
275
|
- **PyPI:** https://pypi.org/project/matimo-core/
|
|
263
|
-
- **Docs:** https://matimo.dev/
|
|
276
|
+
- **Docs:** https://docs.matimo.dev/
|
|
264
277
|
- **GitHub:** https://github.com/tallclub/matimo
|
|
265
278
|
- **Changelog:** https://github.com/tallclub/matimo/blob/main/docs/RELEASES.md
|
|
266
279
|
|
|
@@ -4,12 +4,12 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "matimo-core"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.2.0"
|
|
8
8
|
description = "Matimo core — framework-agnostic SDK: pre-built providers, skills layer, MCP, and a policy engine you control"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
11
11
|
requires-python = ">=3.11"
|
|
12
|
-
keywords = ["ai", "tools", "agents", "langchain", "crewai", "mcp", "matimo", "mcp-server", "agentic-ai", "ai-governance", "policy-engine"]
|
|
12
|
+
keywords = ["ai", "tools", "agents", "langchain", "crewai", "agno", "mcp", "matimo", "mcp-server", "agentic-ai", "ai-governance", "policy-engine"]
|
|
13
13
|
classifiers = [
|
|
14
14
|
"Development Status :: 4 - Beta",
|
|
15
15
|
"Intended Audience :: Developers",
|
|
@@ -40,6 +40,7 @@ dependencies = [
|
|
|
40
40
|
[project.optional-dependencies]
|
|
41
41
|
langchain = ["langchain-core>=0.3"]
|
|
42
42
|
crewai = ["crewai>=0.80"]
|
|
43
|
+
agno = ["agno>=3.0"]
|
|
43
44
|
mcp = ["mcp>=1.28.1"]
|
|
44
45
|
vault = ["hvac>=2.0"]
|
|
45
46
|
aws = ["boto3>=1.34"]
|
|
@@ -47,6 +48,7 @@ dotenv = ["python-dotenv>=1.0"]
|
|
|
47
48
|
all = [
|
|
48
49
|
"langchain-core>=0.3",
|
|
49
50
|
"crewai>=0.80",
|
|
51
|
+
"agno>=3.0",
|
|
50
52
|
"mcp>=1.28.1",
|
|
51
53
|
"hvac>=2.0",
|
|
52
54
|
"python-dotenv>=1.0",
|
|
@@ -61,6 +63,7 @@ dev = [
|
|
|
61
63
|
"types-pyyaml>=6.0",
|
|
62
64
|
"langchain-core>=0.3",
|
|
63
65
|
"crewai>=0.80",
|
|
66
|
+
"agno>=3.0",
|
|
64
67
|
"mcp>=1.28.1",
|
|
65
68
|
"hvac>=2.0",
|
|
66
69
|
"boto3>=1.34",
|
|
@@ -69,7 +72,7 @@ dev = [
|
|
|
69
72
|
|
|
70
73
|
[project.urls]
|
|
71
74
|
Homepage = "https://matimo.dev"
|
|
72
|
-
Documentation = "https://matimo.dev/
|
|
75
|
+
Documentation = "https://docs.matimo.dev/"
|
|
73
76
|
Repository = "https://github.com/tallclub/matimo"
|
|
74
77
|
Issues = "https://github.com/tallclub/matimo/issues"
|
|
75
78
|
|
|
@@ -80,7 +83,7 @@ core = "matimo:get_core_tools_path"
|
|
|
80
83
|
packages = ["src/matimo"]
|
|
81
84
|
|
|
82
85
|
[tool.hatch.build.targets.sdist]
|
|
83
|
-
include = ["src/", "README.md", "
|
|
86
|
+
include = ["src/", "README.md", "LICENSE"]
|
|
84
87
|
|
|
85
88
|
[tool.pytest.ini_options]
|
|
86
89
|
testpaths = ["tests"]
|
|
@@ -34,6 +34,7 @@ from matimo.approval.handler import (
|
|
|
34
34
|
ApprovalCallback,
|
|
35
35
|
ApprovalHandler,
|
|
36
36
|
ApprovalRequest,
|
|
37
|
+
definition_requires_approval,
|
|
37
38
|
get_global_approval_handler,
|
|
38
39
|
set_global_approval_handler,
|
|
39
40
|
)
|
|
@@ -122,7 +123,7 @@ from matimo.errors import (
|
|
|
122
123
|
|
|
123
124
|
# Executors
|
|
124
125
|
from matimo.executors.command_executor import CommandExecutor
|
|
125
|
-
from matimo.executors.function_executor import FunctionExecutor
|
|
126
|
+
from matimo.executors.function_executor import FunctionExecutor, FunctionToolContext
|
|
126
127
|
from matimo.executors.http_executor import HttpExecutor
|
|
127
128
|
|
|
128
129
|
# Main entry point + sync API
|
|
@@ -150,12 +151,26 @@ from matimo.mcp.tool_converter import convert_parameters_to_mcp_schema
|
|
|
150
151
|
|
|
151
152
|
# Policy
|
|
152
153
|
from matimo.policy.approval_manifest import ApprovalManifest, ApprovalRecord
|
|
154
|
+
from matimo.policy.audit_sink import (
|
|
155
|
+
AUDIT_GENESIS_HASH,
|
|
156
|
+
AuditLogVerification,
|
|
157
|
+
AuditSink,
|
|
158
|
+
JsonlFileSink,
|
|
159
|
+
hash_audit_entry,
|
|
160
|
+
redact_secrets,
|
|
161
|
+
verify_audit_log,
|
|
162
|
+
)
|
|
153
163
|
from matimo.policy.content_validator import ContentViolation, validate_tool_content
|
|
154
164
|
from matimo.policy.default_policy import DefaultPolicyEngine, PolicyEngine, get_tier_for_tool
|
|
155
165
|
from matimo.policy.integrity_tracker import IntegrityAction, ToolIntegrityTracker
|
|
156
166
|
from matimo.policy.policy_loader import load_policy_from_file
|
|
157
|
-
from matimo.policy.risk_classifier import
|
|
167
|
+
from matimo.policy.risk_classifier import (
|
|
168
|
+
classify_execution_risk,
|
|
169
|
+
classify_risk,
|
|
170
|
+
meets_risk_threshold,
|
|
171
|
+
)
|
|
158
172
|
from matimo.policy.types import (
|
|
173
|
+
GovernanceMode,
|
|
159
174
|
HITLCallback,
|
|
160
175
|
HITLRequest,
|
|
161
176
|
MatimoEvent,
|
|
@@ -170,7 +185,7 @@ from matimo.policy.types import (
|
|
|
170
185
|
)
|
|
171
186
|
from matimo.sync import MatimoSync
|
|
172
187
|
|
|
173
|
-
__version__ = "0.
|
|
188
|
+
__version__ = "0.2.0"
|
|
174
189
|
|
|
175
190
|
|
|
176
191
|
def get_core_tools_path() -> str:
|
|
@@ -231,6 +246,36 @@ def convert_tools_to_crewai(
|
|
|
231
246
|
return _inner(tools, matimo_instance, credentials)
|
|
232
247
|
|
|
233
248
|
|
|
249
|
+
def convert_tools_to_agno(
|
|
250
|
+
tools: list[Any],
|
|
251
|
+
matimo_instance: Matimo,
|
|
252
|
+
credentials: dict[str, str] | None = None,
|
|
253
|
+
**kwargs: Any, # noqa: ANN401
|
|
254
|
+
) -> list[Any]:
|
|
255
|
+
"""Convert Matimo tools to Agno Function list. Requires agno.
|
|
256
|
+
|
|
257
|
+
Extra keyword arguments (context, confirm_risk_levels) are forwarded to
|
|
258
|
+
matimo.integrations.agno.convert_tools_to_agno.
|
|
259
|
+
"""
|
|
260
|
+
from matimo.integrations.agno import convert_tools_to_agno as _inner
|
|
261
|
+
return _inner(tools, matimo_instance, credentials, **kwargs)
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def MatimoTools( # noqa: N802
|
|
265
|
+
matimo_instance: Matimo,
|
|
266
|
+
tools: list[Any] | None = None,
|
|
267
|
+
**kwargs: Any, # noqa: ANN401
|
|
268
|
+
) -> Any: # noqa: ANN401
|
|
269
|
+
"""Build an Agno Toolkit exposing governed Matimo tools. Requires agno.
|
|
270
|
+
|
|
271
|
+
Named in CapWords to match Agno's <Name>Tools toolkit convention. Returns Any
|
|
272
|
+
because Toolkit comes from an optional dependency (agno). Extra keyword
|
|
273
|
+
arguments are forwarded to matimo.integrations.agno.MatimoTools.
|
|
274
|
+
"""
|
|
275
|
+
from matimo.integrations.agno import MatimoTools as _inner
|
|
276
|
+
return _inner(matimo_instance, tools, **kwargs)
|
|
277
|
+
|
|
278
|
+
|
|
234
279
|
# ---------------------------------------------------------------------------
|
|
235
280
|
# Decorators
|
|
236
281
|
# ---------------------------------------------------------------------------
|
|
@@ -272,7 +317,7 @@ __all__ = [
|
|
|
272
317
|
"ParsedSkillContent", "SemanticSearchResult",
|
|
273
318
|
"TfIdfEmbeddingProvider", "EmbeddingProvider", "cosine_similarity",
|
|
274
319
|
# Executors
|
|
275
|
-
"HttpExecutor", "CommandExecutor", "FunctionExecutor",
|
|
320
|
+
"HttpExecutor", "CommandExecutor", "FunctionExecutor", "FunctionToolContext",
|
|
276
321
|
# Auth
|
|
277
322
|
"inject_auth_parameters", "extract_parameter_placeholders",
|
|
278
323
|
"OAuth2Handler", "OAuth2ProviderLoader",
|
|
@@ -280,17 +325,20 @@ __all__ = [
|
|
|
280
325
|
# Approval
|
|
281
326
|
"ApprovalHandler", "ApprovalRequest", "ApprovalCallback",
|
|
282
327
|
"get_global_approval_handler", "set_global_approval_handler",
|
|
328
|
+
"definition_requires_approval",
|
|
283
329
|
# Encodings
|
|
284
330
|
"apply_parameter_encodings",
|
|
285
331
|
# Policy
|
|
286
332
|
"PolicyEngine", "DefaultPolicyEngine", "PolicyConfig",
|
|
287
333
|
"PolicyDecision", "PolicyAllowed", "PolicyDenied", "PolicyPendingApproval",
|
|
288
334
|
"RiskLevel", "PolicyTier",
|
|
289
|
-
"MatimoEvent", "MatimoEventHandler", "HITLCallback", "HITLRequest",
|
|
335
|
+
"MatimoEvent", "MatimoEventHandler", "GovernanceMode", "HITLCallback", "HITLRequest",
|
|
290
336
|
"ContentViolation", "validate_tool_content",
|
|
291
|
-
"classify_risk", "get_tier_for_tool",
|
|
337
|
+
"classify_risk", "classify_execution_risk", "meets_risk_threshold", "get_tier_for_tool",
|
|
292
338
|
"ToolIntegrityTracker", "IntegrityAction",
|
|
293
339
|
"ApprovalManifest", "ApprovalRecord",
|
|
340
|
+
"AuditSink", "JsonlFileSink", "AuditLogVerification", "verify_audit_log",
|
|
341
|
+
"redact_secrets", "hash_audit_entry", "AUDIT_GENESIS_HASH",
|
|
294
342
|
"load_policy_from_file",
|
|
295
343
|
# MCP
|
|
296
344
|
"MCPServer", "MCPServerOptions", "create_mcp_server",
|
|
@@ -303,6 +351,8 @@ __all__ = [
|
|
|
303
351
|
"get_skills_metadata",
|
|
304
352
|
"build_relevant_skill_prompt",
|
|
305
353
|
"convert_tools_to_crewai",
|
|
354
|
+
"convert_tools_to_agno",
|
|
355
|
+
"MatimoTools",
|
|
306
356
|
# Decorators
|
|
307
357
|
"tool", "set_global_matimo_instance", "get_global_matimo_instance",
|
|
308
358
|
# Logging
|
|
@@ -9,7 +9,11 @@ import logging
|
|
|
9
9
|
import os
|
|
10
10
|
from collections.abc import Awaitable, Callable
|
|
11
11
|
from dataclasses import dataclass
|
|
12
|
-
from typing import Any
|
|
12
|
+
from typing import TYPE_CHECKING, Any
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from matimo.core.models import ToolDefinition
|
|
16
|
+
from matimo.policy.types import GovernanceMode
|
|
13
17
|
|
|
14
18
|
logger = logging.getLogger("matimo")
|
|
15
19
|
|
|
@@ -22,6 +26,32 @@ DEFAULT_DESTRUCTIVE_KEYWORDS: list[str] = [
|
|
|
22
26
|
]
|
|
23
27
|
|
|
24
28
|
|
|
29
|
+
# Tools whose approval prompt nothing may skip: neither MATIMO_AUTO_APPROVE nor
|
|
30
|
+
# an approved pattern (not even "*"). Approving a tool is the step that lets
|
|
31
|
+
# agent-written code run, so a human must always see it.
|
|
32
|
+
# Mirrors NEVER_PRE_APPROVED_TOOLS in approval-handler.ts.
|
|
33
|
+
NEVER_PRE_APPROVED_TOOLS: frozenset[str] = frozenset({"matimo_approve_tool"})
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def definition_requires_approval(tool: ToolDefinition, mode: GovernanceMode = "secure") -> bool:
|
|
37
|
+
"""
|
|
38
|
+
Whether a tool's definition alone makes every call need approval.
|
|
39
|
+
Mirrors definitionRequiresApproval() in approval-handler.ts: an explicit
|
|
40
|
+
`requires_approval` in the YAML always wins, so a developer can opt a tool
|
|
41
|
+
out with `requires_approval: false`. When it is absent, in "secure" mode
|
|
42
|
+
HTTP DELETE and `type: command` (shell) tools need approval by default;
|
|
43
|
+
"legacy" mode has no such default.
|
|
44
|
+
"""
|
|
45
|
+
if "requires_approval" in tool.model_fields_set:
|
|
46
|
+
return tool.requires_approval
|
|
47
|
+
if mode == "legacy":
|
|
48
|
+
return False
|
|
49
|
+
execution = tool.execution
|
|
50
|
+
if execution.type == "command":
|
|
51
|
+
return True
|
|
52
|
+
return execution.type == "http" and execution.method.upper() == "DELETE"
|
|
53
|
+
|
|
54
|
+
|
|
25
55
|
@dataclass
|
|
26
56
|
class ApprovalRequest:
|
|
27
57
|
"""Represents a pending approval for a tool execution."""
|
|
@@ -58,33 +88,59 @@ class ApprovalHandler:
|
|
|
58
88
|
# Public API
|
|
59
89
|
# ------------------------------------------------------------------
|
|
60
90
|
|
|
61
|
-
def set_approval_callback(self, callback: ApprovalCallback) -> None:
|
|
62
|
-
"""Wire an async approval callback (e.g., Slack DM, CLI prompt)."""
|
|
91
|
+
def set_approval_callback(self, callback: ApprovalCallback | None) -> None:
|
|
92
|
+
"""Wire an async approval callback (e.g., Slack DM, CLI prompt), or clear it."""
|
|
63
93
|
self._callback = callback
|
|
64
94
|
|
|
65
|
-
|
|
95
|
+
def get_approval_callback(self) -> ApprovalCallback | None:
|
|
96
|
+
"""Return the current approval callback (for save/restore patterns)."""
|
|
97
|
+
return self._callback
|
|
98
|
+
|
|
99
|
+
def requires_approval(
|
|
100
|
+
self, requires_approval_in_yaml: bool | None, content: str | None = None
|
|
101
|
+
) -> bool:
|
|
66
102
|
"""
|
|
67
|
-
|
|
68
|
-
|
|
103
|
+
Whether a call needs per-call approval. Mirrors requiresApproval() in
|
|
104
|
+
approval-handler.ts: an explicit YAML `requires_approval: true` always
|
|
105
|
+
does; otherwise the supplied content (SQL, shell command, ...) is
|
|
106
|
+
scanned for destructive keywords.
|
|
69
107
|
"""
|
|
70
|
-
|
|
71
|
-
if self.auto_approve:
|
|
72
|
-
logger.debug(
|
|
73
|
-
"Auto-approving tool '%s' (MATIMO_AUTO_APPROVE=true)", request.tool_name
|
|
74
|
-
)
|
|
108
|
+
if requires_approval_in_yaml is True:
|
|
75
109
|
return True
|
|
110
|
+
if content:
|
|
111
|
+
upper = content.upper()
|
|
112
|
+
return any(kw in upper for kw in self.destructive_keywords)
|
|
113
|
+
return False
|
|
114
|
+
|
|
115
|
+
def is_pre_approved(self, tool_name: str) -> bool:
|
|
116
|
+
"""True when MATIMO_AUTO_APPROVE is on or the tool matches an approved pattern.
|
|
117
|
+
Never for NEVER_PRE_APPROVED_TOOLS."""
|
|
118
|
+
if tool_name in NEVER_PRE_APPROVED_TOOLS:
|
|
119
|
+
return False
|
|
120
|
+
return self.auto_approve or self._matches_approved_pattern(tool_name)
|
|
76
121
|
|
|
77
|
-
|
|
78
|
-
|
|
122
|
+
async def request_approval(
|
|
123
|
+
self, request: ApprovalRequest, callback: ApprovalCallback | None = None
|
|
124
|
+
) -> bool:
|
|
125
|
+
"""
|
|
126
|
+
Gate execution on approval.
|
|
127
|
+
Returns True if approved, False if denied.
|
|
128
|
+
`callback` overrides this handler's callback for this request (a Matimo
|
|
129
|
+
instance passes its own `on_approval` here).
|
|
130
|
+
"""
|
|
131
|
+
callback = callback if callback is not None else self._callback
|
|
132
|
+
# 1-2. MATIMO_AUTO_APPROVE (CI / testing) or an approved pattern —
|
|
133
|
+
# never for NEVER_PRE_APPROVED_TOOLS
|
|
134
|
+
if self.is_pre_approved(request.tool_name):
|
|
79
135
|
logger.debug(
|
|
80
|
-
"Tool '%s'
|
|
136
|
+
"Tool '%s' is pre-approved (MATIMO_AUTO_APPROVE or approved pattern)",
|
|
81
137
|
request.tool_name,
|
|
82
138
|
)
|
|
83
139
|
return True
|
|
84
140
|
|
|
85
141
|
# 3. HITL callback
|
|
86
|
-
if
|
|
87
|
-
approved = await
|
|
142
|
+
if callback is not None:
|
|
143
|
+
approved = await callback(request)
|
|
88
144
|
if not approved:
|
|
89
145
|
logger.info(
|
|
90
146
|
"Approval denied for tool '%s' by callback", request.tool_name
|
|
@@ -125,8 +181,9 @@ class ApprovalHandler:
|
|
|
125
181
|
return {p.strip() for p in raw.split(",") if p.strip()}
|
|
126
182
|
|
|
127
183
|
def _matches_approved_pattern(self, tool_name: str) -> bool:
|
|
184
|
+
# Case-insensitive on every OS, like matchesPattern() in approval-handler.ts
|
|
128
185
|
return any(
|
|
129
|
-
fnmatch.
|
|
186
|
+
fnmatch.fnmatchcase(tool_name.lower(), pattern.lower())
|
|
130
187
|
for pattern in self.approved_patterns
|
|
131
188
|
)
|
|
132
189
|
|
|
@@ -31,8 +31,8 @@ def inject_auth_parameters(
|
|
|
31
31
|
Scan all placeholders in the tool's execution config (URL, headers, body,
|
|
32
32
|
query_params). For any placeholder that looks auth-related and has no value
|
|
33
33
|
in params, attempt to resolve it from:
|
|
34
|
-
1. per-call credentials dict
|
|
35
|
-
2. process environment (MATIMO_{TOOL_NAME}_{KEY}
|
|
34
|
+
1. per-call credentials dict ({KEY}, then MATIMO_{KEY})
|
|
35
|
+
2. process environment (MATIMO_{KEY}, MATIMO_{TOOL_NAME}_{KEY}, then {KEY})
|
|
36
36
|
|
|
37
37
|
SECURITY: injected values are never logged.
|
|
38
38
|
|
|
@@ -71,21 +71,20 @@ def extract_parameter_placeholders(tool: ToolDefinition) -> set[str]:
|
|
|
71
71
|
"""
|
|
72
72
|
placeholders: set[str] = set()
|
|
73
73
|
exec_cfg = tool.execution
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
_scan_object(exec_cfg.
|
|
79
|
-
_scan_object(exec_cfg.
|
|
80
|
-
_scan_object(exec_cfg.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
for arg in exec_cfg.args or []: # type: ignore[attr-defined]
|
|
74
|
+
|
|
75
|
+
if exec_cfg.type == "http":
|
|
76
|
+
_scan_string(exec_cfg.url, placeholders)
|
|
77
|
+
_scan_object(exec_cfg.headers, placeholders)
|
|
78
|
+
_scan_object(exec_cfg.body, placeholders)
|
|
79
|
+
_scan_object(exec_cfg.query_params, placeholders)
|
|
80
|
+
_scan_object(exec_cfg.params, placeholders)
|
|
81
|
+
|
|
82
|
+
elif exec_cfg.type == "command":
|
|
83
|
+
_scan_string(exec_cfg.command, placeholders)
|
|
84
|
+
for arg in exec_cfg.args or []:
|
|
86
85
|
_scan_string(arg, placeholders)
|
|
87
86
|
|
|
88
|
-
elif
|
|
87
|
+
elif exec_cfg.type == "function":
|
|
89
88
|
# Function tools may have params passed directly — nothing to scan
|
|
90
89
|
pass
|
|
91
90
|
|
|
@@ -103,19 +102,27 @@ def _resolve_auth_value(
|
|
|
103
102
|
credentials: dict[str, str] | None,
|
|
104
103
|
) -> str | None:
|
|
105
104
|
"""
|
|
106
|
-
Try to resolve an auth placeholder in priority order
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
105
|
+
Try to resolve an auth placeholder in priority order, matching
|
|
106
|
+
injectAuthParameters() in matimo-instance.ts:
|
|
107
|
+
1. per-call credentials: {PLACEHOLDER}, then MATIMO_{PLACEHOLDER}
|
|
108
|
+
2. env MATIMO_{PLACEHOLDER}
|
|
109
|
+
3. env MATIMO_{TOOL_NAME_UPPER}_{PLACEHOLDER_UPPER} (Python-only, kept for
|
|
110
|
+
existing deployments)
|
|
111
|
+
4. env {PLACEHOLDER}
|
|
110
112
|
"""
|
|
111
|
-
if credentials
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
113
|
+
if credentials:
|
|
114
|
+
for key in (placeholder, f"MATIMO_{placeholder}"):
|
|
115
|
+
if credentials.get(key):
|
|
116
|
+
return credentials[key]
|
|
117
|
+
|
|
118
|
+
for env_key in (
|
|
119
|
+
f"MATIMO_{placeholder}",
|
|
120
|
+
# e.g. MATIMO_SLACK_SEND_CHANNEL_MESSAGE_SLACK_BOT_TOKEN
|
|
121
|
+
f"MATIMO_{tool_name.upper()}_{placeholder.upper()}",
|
|
122
|
+
):
|
|
123
|
+
val = os.environ.get(env_key)
|
|
124
|
+
if val:
|
|
125
|
+
return val
|
|
119
126
|
|
|
120
127
|
# env directly (e.g. SLACK_BOT_TOKEN)
|
|
121
128
|
return os.environ.get(placeholder)
|