matimo-postgres 0.1.2__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_postgres-0.1.2 → matimo_postgres-0.2.0}/.gitignore +3 -1
- matimo_postgres-0.2.0/LICENSE +21 -0
- matimo_postgres-0.2.0/PKG-INFO +126 -0
- matimo_postgres-0.2.0/README.md +110 -0
- {matimo_postgres-0.1.2 → matimo_postgres-0.2.0}/pyproject.toml +2 -2
- matimo_postgres-0.2.0/src/matimo_postgres/skills/postgres/SKILL.md +293 -0
- {matimo_postgres-0.1.2 → matimo_postgres-0.2.0}/src/matimo_postgres/tools/execute-sql/definition.yaml +1 -0
- matimo_postgres-0.1.2/PKG-INFO +0 -122
- matimo_postgres-0.1.2/README.md +0 -107
- {matimo_postgres-0.1.2 → matimo_postgres-0.2.0}/src/matimo_postgres/__init__.py +0 -0
- {matimo_postgres-0.1.2 → matimo_postgres-0.2.0}/src/matimo_postgres/tools/execute-sql/execute-sql.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.
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: matimo-postgres
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Matimo provider — PostgreSQL tools (query, insert, update, delete, execute SQL)
|
|
5
|
+
License: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Keywords: agents,ai,matimo,postgres,tools
|
|
8
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Requires-Python: >=3.11
|
|
13
|
+
Requires-Dist: asyncpg>=0.29
|
|
14
|
+
Requires-Dist: matimo-core<0.3.0,>=0.2.0
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
# matimo-postgres
|
|
18
|
+
|
|
19
|
+
> PostgreSQL tools for [Matimo](https://matimo.dev) - execute SQL queries safely with policy-gated approval.
|
|
20
|
+
|
|
21
|
+
[](https://pypi.org/project/matimo-postgres/)
|
|
22
|
+
[](https://docs.matimo.dev)
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install matimo matimo-postgres
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Available Tools (1 Tool)
|
|
35
|
+
|
|
36
|
+
| Tool | Description |
|
|
37
|
+
|------|-------------|
|
|
38
|
+
| `postgres-execute-sql` | Execute a SQL query against a PostgreSQL database |
|
|
39
|
+
|
|
40
|
+
The tool does not set `requires_approval` itself - if you want destructive operations
|
|
41
|
+
(INSERT, UPDATE, DELETE, DROP) to require human approval, gate them yourself via a
|
|
42
|
+
[policy file](https://docs.matimo.dev/api-reference/POLICY_AND_LIFECYCLE) or a custom
|
|
43
|
+
`PolicyEngine`.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Quick Start
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
import asyncio
|
|
51
|
+
from matimo import Matimo
|
|
52
|
+
from matimo_postgres import get_tools_path
|
|
53
|
+
|
|
54
|
+
async def main():
|
|
55
|
+
matimo = await Matimo.init(get_tools_path())
|
|
56
|
+
|
|
57
|
+
# Run a SELECT query
|
|
58
|
+
result = await matimo.execute('postgres-execute-sql', {
|
|
59
|
+
'sql': 'SELECT id, name FROM users LIMIT 10',
|
|
60
|
+
})
|
|
61
|
+
print(result)
|
|
62
|
+
|
|
63
|
+
asyncio.run(main())
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### With Interactive Approval (Recommended for Writes)
|
|
67
|
+
|
|
68
|
+
A query whose `sql` contains a destructive keyword (`DELETE`, `DROP`, `UPDATE`, `INSERT`, `ALTER`, `CREATE`, ...) needs approval. Provide an `on_approval` callback; without one the query is refused:
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
from matimo import ApprovalRequest
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
async def ask_user(request: ApprovalRequest) -> bool:
|
|
75
|
+
print(f"\nSQL requires approval:\n{request.params.get('sql')}")
|
|
76
|
+
return input("Run this query? [y/n]: ").strip() == "y"
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
matimo = await Matimo.init(get_tools_path(), on_approval=ask_user)
|
|
80
|
+
|
|
81
|
+
# Prompts before executing
|
|
82
|
+
await matimo.execute('postgres-execute-sql', {
|
|
83
|
+
'sql': 'DELETE FROM sessions WHERE expired_at < NOW()',
|
|
84
|
+
})
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
The keyword match is a substring of the upper-cased query, so a `SELECT created_at ...` also asks (it contains `CREATE`).
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Authentication
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
export MATIMO_POSTGRES_URL="postgresql://user:password@localhost:5432/mydb"
|
|
95
|
+
# or individual params
|
|
96
|
+
export MATIMO_POSTGRES_HOST="localhost"
|
|
97
|
+
export MATIMO_POSTGRES_PORT="5432"
|
|
98
|
+
export MATIMO_POSTGRES_DB="mydb"
|
|
99
|
+
export MATIMO_POSTGRES_USER="myuser"
|
|
100
|
+
export MATIMO_POSTGRES_PASSWORD="mypassword"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Security Notes
|
|
106
|
+
|
|
107
|
+
- All SQL queries go through Matimo's **content validator** - SSRF and injection patterns are detected
|
|
108
|
+
- The tool itself does not require approval - use a policy file if you want writes gated
|
|
109
|
+
- Use a **read-only database user** for agent workloads when possible
|
|
110
|
+
- Consider a [policy file](https://docs.matimo.dev/api-reference/POLICY_AND_LIFECYCLE) to restrict allowed SQL patterns
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Documentation
|
|
115
|
+
|
|
116
|
+
- [Approval System](https://docs.matimo.dev/api-reference/APPROVAL-SYSTEM)
|
|
117
|
+
- [Policy & Lifecycle](https://docs.matimo.dev/api-reference/POLICY_AND_LIFECYCLE)
|
|
118
|
+
- [Python Examples](https://github.com/tallclub/matimo/tree/main/python/examples/langchain/postgres)
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Links
|
|
123
|
+
|
|
124
|
+
- **PyPI:** https://pypi.org/project/matimo-postgres/
|
|
125
|
+
- **GitHub:** https://github.com/tallclub/matimo
|
|
126
|
+
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# matimo-postgres
|
|
2
|
+
|
|
3
|
+
> PostgreSQL tools for [Matimo](https://matimo.dev) - execute SQL queries safely with policy-gated approval.
|
|
4
|
+
|
|
5
|
+
[](https://pypi.org/project/matimo-postgres/)
|
|
6
|
+
[](https://docs.matimo.dev)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pip install matimo matimo-postgres
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Available Tools (1 Tool)
|
|
19
|
+
|
|
20
|
+
| Tool | Description |
|
|
21
|
+
|------|-------------|
|
|
22
|
+
| `postgres-execute-sql` | Execute a SQL query against a PostgreSQL database |
|
|
23
|
+
|
|
24
|
+
The tool does not set `requires_approval` itself - if you want destructive operations
|
|
25
|
+
(INSERT, UPDATE, DELETE, DROP) to require human approval, gate them yourself via a
|
|
26
|
+
[policy file](https://docs.matimo.dev/api-reference/POLICY_AND_LIFECYCLE) or a custom
|
|
27
|
+
`PolicyEngine`.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
import asyncio
|
|
35
|
+
from matimo import Matimo
|
|
36
|
+
from matimo_postgres import get_tools_path
|
|
37
|
+
|
|
38
|
+
async def main():
|
|
39
|
+
matimo = await Matimo.init(get_tools_path())
|
|
40
|
+
|
|
41
|
+
# Run a SELECT query
|
|
42
|
+
result = await matimo.execute('postgres-execute-sql', {
|
|
43
|
+
'sql': 'SELECT id, name FROM users LIMIT 10',
|
|
44
|
+
})
|
|
45
|
+
print(result)
|
|
46
|
+
|
|
47
|
+
asyncio.run(main())
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### With Interactive Approval (Recommended for Writes)
|
|
51
|
+
|
|
52
|
+
A query whose `sql` contains a destructive keyword (`DELETE`, `DROP`, `UPDATE`, `INSERT`, `ALTER`, `CREATE`, ...) needs approval. Provide an `on_approval` callback; without one the query is refused:
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from matimo import ApprovalRequest
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
async def ask_user(request: ApprovalRequest) -> bool:
|
|
59
|
+
print(f"\nSQL requires approval:\n{request.params.get('sql')}")
|
|
60
|
+
return input("Run this query? [y/n]: ").strip() == "y"
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
matimo = await Matimo.init(get_tools_path(), on_approval=ask_user)
|
|
64
|
+
|
|
65
|
+
# Prompts before executing
|
|
66
|
+
await matimo.execute('postgres-execute-sql', {
|
|
67
|
+
'sql': 'DELETE FROM sessions WHERE expired_at < NOW()',
|
|
68
|
+
})
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The keyword match is a substring of the upper-cased query, so a `SELECT created_at ...` also asks (it contains `CREATE`).
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Authentication
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
export MATIMO_POSTGRES_URL="postgresql://user:password@localhost:5432/mydb"
|
|
79
|
+
# or individual params
|
|
80
|
+
export MATIMO_POSTGRES_HOST="localhost"
|
|
81
|
+
export MATIMO_POSTGRES_PORT="5432"
|
|
82
|
+
export MATIMO_POSTGRES_DB="mydb"
|
|
83
|
+
export MATIMO_POSTGRES_USER="myuser"
|
|
84
|
+
export MATIMO_POSTGRES_PASSWORD="mypassword"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Security Notes
|
|
90
|
+
|
|
91
|
+
- All SQL queries go through Matimo's **content validator** - SSRF and injection patterns are detected
|
|
92
|
+
- The tool itself does not require approval - use a policy file if you want writes gated
|
|
93
|
+
- Use a **read-only database user** for agent workloads when possible
|
|
94
|
+
- Consider a [policy file](https://docs.matimo.dev/api-reference/POLICY_AND_LIFECYCLE) to restrict allowed SQL patterns
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Documentation
|
|
99
|
+
|
|
100
|
+
- [Approval System](https://docs.matimo.dev/api-reference/APPROVAL-SYSTEM)
|
|
101
|
+
- [Policy & Lifecycle](https://docs.matimo.dev/api-reference/POLICY_AND_LIFECYCLE)
|
|
102
|
+
- [Python Examples](https://github.com/tallclub/matimo/tree/main/python/examples/langchain/postgres)
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Links
|
|
107
|
+
|
|
108
|
+
- **PyPI:** https://pypi.org/project/matimo-postgres/
|
|
109
|
+
- **GitHub:** https://github.com/tallclub/matimo
|
|
110
|
+
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "matimo-postgres"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.2.0"
|
|
8
8
|
description = "Matimo provider — PostgreSQL tools (query, insert, update, delete, execute SQL)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -17,7 +17,7 @@ classifiers = [
|
|
|
17
17
|
"Programming Language :: Python :: 3.11",
|
|
18
18
|
]
|
|
19
19
|
dependencies = [
|
|
20
|
-
"matimo-core>=0.
|
|
20
|
+
"matimo-core>=0.2.0,<0.3.0",
|
|
21
21
|
"asyncpg>=0.29",
|
|
22
22
|
]
|
|
23
23
|
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: postgres
|
|
3
|
+
description: "Complete guide to all PostgreSQL tools — parameterized queries, schema navigation, data retrieval, and safe database interaction patterns."
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
license: "MIT"
|
|
6
|
+
metadata:
|
|
7
|
+
category: "Database"
|
|
8
|
+
difficulty: "intermediate"
|
|
9
|
+
apply-to: "postgres-execute-sql"
|
|
10
|
+
tags: "postgres,sql,database,queries"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# PostgreSQL
|
|
14
|
+
|
|
15
|
+
This skill teaches you how to **safely execute SQL queries** against a PostgreSQL database using Matimo tools, with emphasis on parameterized queries, schema awareness, and safe patterns.
|
|
16
|
+
|
|
17
|
+
## Tools You Will Use
|
|
18
|
+
|
|
19
|
+
| Tool | Purpose |
|
|
20
|
+
|------|---------|
|
|
21
|
+
| `postgres-execute-sql` | Execute any SQL statement against a connected Postgres database |
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Executing a Query
|
|
26
|
+
|
|
27
|
+
Use `postgres-execute-sql` to run SQL statements. The tool supports parameterized queries for safety.
|
|
28
|
+
|
|
29
|
+
### Parameters
|
|
30
|
+
|
|
31
|
+
| Parameter | Type | Description |
|
|
32
|
+
|-----------|------|-------------|
|
|
33
|
+
| `sql` | string | SQL statement to execute. Use `$1`, `$2`, etc. for parameterized values |
|
|
34
|
+
| `params` | array | Optional array of parameter values (matched by position to `$1`, `$2`, etc.) |
|
|
35
|
+
| `schema` | string | Optional schema name for table qualification |
|
|
36
|
+
|
|
37
|
+
### Critical: Always Use Parameterized Queries
|
|
38
|
+
|
|
39
|
+
**NEVER** interpolate user-provided values directly into SQL strings. Always use `$1`, `$2` placeholders.
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
// ✅ SAFE — parameterized
|
|
43
|
+
{
|
|
44
|
+
"sql": "SELECT * FROM users WHERE email = $1",
|
|
45
|
+
"params": ["user@example.com"]
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ❌ DANGEROUS — SQL injection risk
|
|
49
|
+
{
|
|
50
|
+
"sql": "SELECT * FROM users WHERE email = 'user@example.com'"
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
This prevents SQL injection attacks regardless of the input content.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Read Operations
|
|
59
|
+
|
|
60
|
+
### Select with Parameters
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"sql": "SELECT id, name, email FROM users WHERE id = $1",
|
|
65
|
+
"params": [42]
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Select with Multiple Conditions
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"sql": "SELECT * FROM orders WHERE status = $1 AND created_at > $2",
|
|
74
|
+
"params": ["pending", "2025-01-01"]
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Count Records
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"sql": "SELECT count(*) as total FROM users WHERE active = $1",
|
|
83
|
+
"params": [true]
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Pagination Pattern
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
{
|
|
91
|
+
"sql": "SELECT id, name, email FROM users ORDER BY created_at DESC LIMIT $1 OFFSET $2",
|
|
92
|
+
"params": [20, 0]
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Increment the offset by the limit for each page: `0`, `20`, `40`, `60`...
|
|
97
|
+
|
|
98
|
+
### Join Queries
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"sql": "SELECT u.name, o.total, o.status FROM users u JOIN orders o ON u.id = o.user_id WHERE o.status = $1 ORDER BY o.created_at DESC LIMIT $2",
|
|
103
|
+
"params": ["completed", 10]
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Schema Discovery
|
|
110
|
+
|
|
111
|
+
### List All Tables
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"sql": "SELECT table_name FROM information_schema.tables WHERE table_schema = $1 ORDER BY table_name",
|
|
116
|
+
"params": ["public"]
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Describe a Table
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"sql": "SELECT column_name, data_type, is_nullable, column_default FROM information_schema.columns WHERE table_name = $1 AND table_schema = $2 ORDER BY ordinal_position",
|
|
125
|
+
"params": ["users", "public"]
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### List Indexes
|
|
130
|
+
|
|
131
|
+
```json
|
|
132
|
+
{
|
|
133
|
+
"sql": "SELECT indexname, indexdef FROM pg_indexes WHERE tablename = $1",
|
|
134
|
+
"params": ["users"]
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Using Schema Parameter
|
|
139
|
+
|
|
140
|
+
When working with non-default schemas, use the `schema` parameter:
|
|
141
|
+
|
|
142
|
+
```json
|
|
143
|
+
{
|
|
144
|
+
"sql": "SELECT * FROM customers LIMIT 10",
|
|
145
|
+
"schema": "sales"
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Write Operations
|
|
152
|
+
|
|
153
|
+
### Insert a Row
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
{
|
|
157
|
+
"sql": "INSERT INTO users (name, email, role) VALUES ($1, $2, $3) RETURNING id",
|
|
158
|
+
"params": ["Alice Smith", "alice@example.com", "admin"]
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Use `RETURNING` to get the inserted row's ID without a second query.
|
|
163
|
+
|
|
164
|
+
### Update Rows
|
|
165
|
+
|
|
166
|
+
```json
|
|
167
|
+
{
|
|
168
|
+
"sql": "UPDATE users SET email = $1, updated_at = NOW() WHERE id = $2 RETURNING id, email",
|
|
169
|
+
"params": ["newemail@example.com", 42]
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Delete Rows
|
|
174
|
+
|
|
175
|
+
```json
|
|
176
|
+
{
|
|
177
|
+
"sql": "DELETE FROM sessions WHERE expires_at < NOW() RETURNING id",
|
|
178
|
+
"params": []
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Upsert (Insert or Update)
|
|
183
|
+
|
|
184
|
+
```json
|
|
185
|
+
{
|
|
186
|
+
"sql": "INSERT INTO settings (key, value) VALUES ($1, $2) ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value RETURNING key, value",
|
|
187
|
+
"params": ["theme", "dark"]
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Understanding the Response
|
|
194
|
+
|
|
195
|
+
Every query returns:
|
|
196
|
+
|
|
197
|
+
```json
|
|
198
|
+
{
|
|
199
|
+
"rows": [
|
|
200
|
+
{ "id": 1, "name": "Alice", "email": "alice@example.com" },
|
|
201
|
+
{ "id": 2, "name": "Bob", "email": "bob@example.com" }
|
|
202
|
+
],
|
|
203
|
+
"rowCount": 2
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
- **`rows`**: Array of result objects (empty for non-SELECT statements)
|
|
208
|
+
- **`rowCount`**: Number of rows affected (for INSERT/UPDATE/DELETE) or returned (for SELECT)
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Common Workflows
|
|
213
|
+
|
|
214
|
+
### Workflow: Data Exploration
|
|
215
|
+
|
|
216
|
+
1. **List tables:** Query `information_schema.tables` to see what's available
|
|
217
|
+
2. **Describe schema:** Query `information_schema.columns` for table structure
|
|
218
|
+
3. **Sample data:** `SELECT * FROM {table} LIMIT 10` to understand content
|
|
219
|
+
4. **Targeted queries:** Build specific queries based on discovered schema
|
|
220
|
+
|
|
221
|
+
### Workflow: Reporting
|
|
222
|
+
|
|
223
|
+
1. **Aggregate data:** Use `GROUP BY`, `COUNT`, `SUM`, `AVG`
|
|
224
|
+
2. **Date ranges:** Filter with parameterized date values
|
|
225
|
+
3. **Multiple queries:** Chain queries to build multi-dimensional reports
|
|
226
|
+
|
|
227
|
+
```json
|
|
228
|
+
{
|
|
229
|
+
"sql": "SELECT status, count(*) as count, sum(total) as revenue FROM orders WHERE created_at >= $1 GROUP BY status ORDER BY count DESC",
|
|
230
|
+
"params": ["2025-01-01"]
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Workflow: Safe Bulk Operations
|
|
235
|
+
|
|
236
|
+
Always use transactions for multi-step writes:
|
|
237
|
+
|
|
238
|
+
```json
|
|
239
|
+
{
|
|
240
|
+
"sql": "BEGIN; UPDATE accounts SET balance = balance - $1 WHERE id = $2; UPDATE accounts SET balance = balance + $1 WHERE id = $3; COMMIT;",
|
|
241
|
+
"params": [100.00, 1, 2]
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Best Practices
|
|
248
|
+
|
|
249
|
+
1. **Always parameterize.** Every dynamic value should use `$1`, `$2`, etc. — no exceptions.
|
|
250
|
+
2. **Use LIMIT.** Always add `LIMIT` to SELECT queries to prevent fetching millions of rows.
|
|
251
|
+
3. **Use RETURNING.** On INSERT/UPDATE/DELETE, use `RETURNING` to avoid a second SELECT.
|
|
252
|
+
4. **Check rowCount.** Verify the expected number of rows were affected before proceeding.
|
|
253
|
+
5. **Use specific columns.** Avoid `SELECT *` in production — name the columns you need.
|
|
254
|
+
6. **Schema-qualify tables.** Use the `schema` parameter or `schema.table` syntax for clarity.
|
|
255
|
+
7. **Timeout awareness.** Queries timeout after 30 seconds — optimize or paginate large queries.
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## Error Handling
|
|
260
|
+
|
|
261
|
+
| Error | Cause | Resolution |
|
|
262
|
+
|-------|-------|------------|
|
|
263
|
+
| `ECONNREFUSED` | Database not reachable | Check `MATIMO_POSTGRES_URL` or host/port env vars |
|
|
264
|
+
| `password authentication failed` | Bad credentials | Verify `MATIMO_POSTGRES_PASSWORD` env var |
|
|
265
|
+
| `relation "X" does not exist` | Table not found | Check table name and schema |
|
|
266
|
+
| `column "X" does not exist` | Wrong column name | Query `information_schema.columns` to verify |
|
|
267
|
+
| `syntax error at or near` | Invalid SQL | Check query syntax — use a SQL validator |
|
|
268
|
+
| `query timeout` | Query too slow | Add indexes, use LIMIT, or optimize the query |
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## Authentication
|
|
273
|
+
|
|
274
|
+
PostgreSQL connection supports two modes:
|
|
275
|
+
|
|
276
|
+
### Option 1: Connection String (Recommended)
|
|
277
|
+
|
|
278
|
+
Set `MATIMO_POSTGRES_URL`:
|
|
279
|
+
```
|
|
280
|
+
postgresql://user:password@host:5432/dbname?sslmode=require
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Option 2: Separate Environment Variables
|
|
284
|
+
|
|
285
|
+
| Env Var | Description |
|
|
286
|
+
|---------|-------------|
|
|
287
|
+
| `MATIMO_POSTGRES_HOST` | Database hostname |
|
|
288
|
+
| `MATIMO_POSTGRES_PORT` | Port (default: 5432) |
|
|
289
|
+
| `MATIMO_POSTGRES_USER` | Username |
|
|
290
|
+
| `MATIMO_POSTGRES_PASSWORD` | Password |
|
|
291
|
+
| `MATIMO_POSTGRES_DB` | Database name |
|
|
292
|
+
|
|
293
|
+
**Never log or expose connection credentials.**
|
matimo_postgres-0.1.2/PKG-INFO
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: matimo-postgres
|
|
3
|
-
Version: 0.1.2
|
|
4
|
-
Summary: Matimo provider — PostgreSQL tools (query, insert, update, delete, execute SQL)
|
|
5
|
-
License: MIT
|
|
6
|
-
Keywords: agents,ai,matimo,postgres,tools
|
|
7
|
-
Classifier: Development Status :: 4 - Beta
|
|
8
|
-
Classifier: Intended Audience :: Developers
|
|
9
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
11
|
-
Requires-Python: >=3.11
|
|
12
|
-
Requires-Dist: asyncpg>=0.29
|
|
13
|
-
Requires-Dist: matimo-core<0.2.0,>=0.1.0
|
|
14
|
-
Description-Content-Type: text/markdown
|
|
15
|
-
|
|
16
|
-
# matimo-postgres
|
|
17
|
-
|
|
18
|
-
> PostgreSQL tools for [Matimo](https://matimo.dev) — execute SQL queries safely with policy-gated approval.
|
|
19
|
-
|
|
20
|
-
[](https://pypi.org/project/matimo-postgres/)
|
|
21
|
-
[](https://matimo.dev/docs)
|
|
22
|
-
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
## Installation
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
pip install matimo matimo-postgres
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
---
|
|
32
|
-
|
|
33
|
-
## Available Tools (1 Tool)
|
|
34
|
-
|
|
35
|
-
| Tool | Description |
|
|
36
|
-
|------|-------------|
|
|
37
|
-
| `execute-sql` | Execute a SQL query against a PostgreSQL database |
|
|
38
|
-
|
|
39
|
-
The `execute-sql` tool is marked `requires_approval: true` — destructive operations (INSERT, UPDATE, DELETE, DROP) trigger HITL approval by default.
|
|
40
|
-
|
|
41
|
-
---
|
|
42
|
-
|
|
43
|
-
## Quick Start
|
|
44
|
-
|
|
45
|
-
```python
|
|
46
|
-
import asyncio
|
|
47
|
-
from matimo import Matimo, InitOptions
|
|
48
|
-
from matimo_postgres import get_tools_path
|
|
49
|
-
|
|
50
|
-
async def main():
|
|
51
|
-
# Auto-approve for read-only usage (CI/CD)
|
|
52
|
-
matimo = await Matimo.init(
|
|
53
|
-
get_tools_path(),
|
|
54
|
-
InitOptions(on_hitl=lambda req: {'approved': True, 'reason': 'auto'}),
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
# Run a SELECT query
|
|
58
|
-
result = await matimo.execute('execute-sql', {
|
|
59
|
-
'query': 'SELECT id, name FROM users LIMIT 10',
|
|
60
|
-
})
|
|
61
|
-
print(result)
|
|
62
|
-
|
|
63
|
-
asyncio.run(main())
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
### With Interactive Approval (Recommended for Writes)
|
|
67
|
-
|
|
68
|
-
```python
|
|
69
|
-
async def ask_user(request) -> dict:
|
|
70
|
-
print(f"\nSQL requires approval:\n{request.params.get('query')}")
|
|
71
|
-
answer = input("Run this query? [y/n]: ").strip()
|
|
72
|
-
return {'approved': answer == 'y', 'reason': 'user reviewed'}
|
|
73
|
-
|
|
74
|
-
matimo = await Matimo.init(
|
|
75
|
-
get_tools_path(),
|
|
76
|
-
InitOptions(on_hitl=ask_user),
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
# This will prompt before executing
|
|
80
|
-
await matimo.execute('execute-sql', {
|
|
81
|
-
'query': 'DELETE FROM sessions WHERE expired_at < NOW()',
|
|
82
|
-
})
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
---
|
|
86
|
-
|
|
87
|
-
## Authentication
|
|
88
|
-
|
|
89
|
-
```bash
|
|
90
|
-
export DATABASE_URL="postgresql://user:password@localhost:5432/mydb"
|
|
91
|
-
# or individual params
|
|
92
|
-
export POSTGRES_HOST="localhost"
|
|
93
|
-
export POSTGRES_PORT="5432"
|
|
94
|
-
export POSTGRES_DB="mydb"
|
|
95
|
-
export POSTGRES_USER="myuser"
|
|
96
|
-
export POSTGRES_PASSWORD="mypassword"
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
---
|
|
100
|
-
|
|
101
|
-
## Security Notes
|
|
102
|
-
|
|
103
|
-
- All SQL queries go through Matimo's **content validator** — SSRF and injection patterns are detected
|
|
104
|
-
- The tool has `requires_approval: true` — writes trigger approval by default
|
|
105
|
-
- Use a **read-only database user** for agent workloads when possible
|
|
106
|
-
- Consider a [policy file](https://matimo.dev/docs/api-reference/POLICY_AND_LIFECYCLE) to restrict allowed SQL patterns
|
|
107
|
-
|
|
108
|
-
---
|
|
109
|
-
|
|
110
|
-
## Documentation
|
|
111
|
-
|
|
112
|
-
- [Approval System](https://matimo.dev/docs/api-reference/APPROVAL-SYSTEM)
|
|
113
|
-
- [Policy & Lifecycle](https://matimo.dev/docs/api-reference/POLICY_AND_LIFECYCLE)
|
|
114
|
-
- [Python Examples](https://github.com/tallclub/matimo/tree/main/python/examples/langchain/postgres)
|
|
115
|
-
|
|
116
|
-
---
|
|
117
|
-
|
|
118
|
-
## Links
|
|
119
|
-
|
|
120
|
-
- **PyPI:** https://pypi.org/project/matimo-postgres/
|
|
121
|
-
- **GitHub:** https://github.com/tallclub/matimo
|
|
122
|
-
|
matimo_postgres-0.1.2/README.md
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
# matimo-postgres
|
|
2
|
-
|
|
3
|
-
> PostgreSQL tools for [Matimo](https://matimo.dev) — execute SQL queries safely with policy-gated approval.
|
|
4
|
-
|
|
5
|
-
[](https://pypi.org/project/matimo-postgres/)
|
|
6
|
-
[](https://matimo.dev/docs)
|
|
7
|
-
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
## Installation
|
|
11
|
-
|
|
12
|
-
```bash
|
|
13
|
-
pip install matimo matimo-postgres
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## Available Tools (1 Tool)
|
|
19
|
-
|
|
20
|
-
| Tool | Description |
|
|
21
|
-
|------|-------------|
|
|
22
|
-
| `execute-sql` | Execute a SQL query against a PostgreSQL database |
|
|
23
|
-
|
|
24
|
-
The `execute-sql` tool is marked `requires_approval: true` — destructive operations (INSERT, UPDATE, DELETE, DROP) trigger HITL approval by default.
|
|
25
|
-
|
|
26
|
-
---
|
|
27
|
-
|
|
28
|
-
## Quick Start
|
|
29
|
-
|
|
30
|
-
```python
|
|
31
|
-
import asyncio
|
|
32
|
-
from matimo import Matimo, InitOptions
|
|
33
|
-
from matimo_postgres import get_tools_path
|
|
34
|
-
|
|
35
|
-
async def main():
|
|
36
|
-
# Auto-approve for read-only usage (CI/CD)
|
|
37
|
-
matimo = await Matimo.init(
|
|
38
|
-
get_tools_path(),
|
|
39
|
-
InitOptions(on_hitl=lambda req: {'approved': True, 'reason': 'auto'}),
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
# Run a SELECT query
|
|
43
|
-
result = await matimo.execute('execute-sql', {
|
|
44
|
-
'query': 'SELECT id, name FROM users LIMIT 10',
|
|
45
|
-
})
|
|
46
|
-
print(result)
|
|
47
|
-
|
|
48
|
-
asyncio.run(main())
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
### With Interactive Approval (Recommended for Writes)
|
|
52
|
-
|
|
53
|
-
```python
|
|
54
|
-
async def ask_user(request) -> dict:
|
|
55
|
-
print(f"\nSQL requires approval:\n{request.params.get('query')}")
|
|
56
|
-
answer = input("Run this query? [y/n]: ").strip()
|
|
57
|
-
return {'approved': answer == 'y', 'reason': 'user reviewed'}
|
|
58
|
-
|
|
59
|
-
matimo = await Matimo.init(
|
|
60
|
-
get_tools_path(),
|
|
61
|
-
InitOptions(on_hitl=ask_user),
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
# This will prompt before executing
|
|
65
|
-
await matimo.execute('execute-sql', {
|
|
66
|
-
'query': 'DELETE FROM sessions WHERE expired_at < NOW()',
|
|
67
|
-
})
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
---
|
|
71
|
-
|
|
72
|
-
## Authentication
|
|
73
|
-
|
|
74
|
-
```bash
|
|
75
|
-
export DATABASE_URL="postgresql://user:password@localhost:5432/mydb"
|
|
76
|
-
# or individual params
|
|
77
|
-
export POSTGRES_HOST="localhost"
|
|
78
|
-
export POSTGRES_PORT="5432"
|
|
79
|
-
export POSTGRES_DB="mydb"
|
|
80
|
-
export POSTGRES_USER="myuser"
|
|
81
|
-
export POSTGRES_PASSWORD="mypassword"
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
---
|
|
85
|
-
|
|
86
|
-
## Security Notes
|
|
87
|
-
|
|
88
|
-
- All SQL queries go through Matimo's **content validator** — SSRF and injection patterns are detected
|
|
89
|
-
- The tool has `requires_approval: true` — writes trigger approval by default
|
|
90
|
-
- Use a **read-only database user** for agent workloads when possible
|
|
91
|
-
- Consider a [policy file](https://matimo.dev/docs/api-reference/POLICY_AND_LIFECYCLE) to restrict allowed SQL patterns
|
|
92
|
-
|
|
93
|
-
---
|
|
94
|
-
|
|
95
|
-
## Documentation
|
|
96
|
-
|
|
97
|
-
- [Approval System](https://matimo.dev/docs/api-reference/APPROVAL-SYSTEM)
|
|
98
|
-
- [Policy & Lifecycle](https://matimo.dev/docs/api-reference/POLICY_AND_LIFECYCLE)
|
|
99
|
-
- [Python Examples](https://github.com/tallclub/matimo/tree/main/python/examples/langchain/postgres)
|
|
100
|
-
|
|
101
|
-
---
|
|
102
|
-
|
|
103
|
-
## Links
|
|
104
|
-
|
|
105
|
-
- **PyPI:** https://pypi.org/project/matimo-postgres/
|
|
106
|
-
- **GitHub:** https://github.com/tallclub/matimo
|
|
107
|
-
|
|
File without changes
|
{matimo_postgres-0.1.2 → matimo_postgres-0.2.0}/src/matimo_postgres/tools/execute-sql/execute-sql.py
RENAMED
|
File without changes
|