@synapsor/runner 0.1.0 → 0.1.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.
- package/CHANGELOG.md +38 -0
- package/README.md +750 -245
- package/dist/cli.d.ts.map +1 -1
- package/dist/runner.mjs +1621 -163
- package/docs/README.md +85 -47
- package/docs/conformance.md +91 -0
- package/docs/migrating-to-synapsor-spec.md +191 -0
- package/docs/production.md +289 -0
- package/docs/release-notes.md +32 -0
- package/examples/app-owned-writeback/command-handler.mjs +0 -0
- package/examples/claude-desktop-postgres/Makefile +6 -0
- package/examples/claude-desktop-postgres/README.md +40 -0
- package/examples/cursor-postgres/Makefile +6 -0
- package/examples/cursor-postgres/README.md +30 -0
- package/examples/mcp-postgres-billing-app-handler/scripts/run-demo.sh +0 -0
- package/examples/mysql-refund-agent/Makefile +4 -0
- package/examples/mysql-refund-agent/README.md +36 -0
- package/examples/openai-agents-http/Makefile +6 -0
- package/examples/openai-agents-http/README.md +14 -0
- package/examples/openai-agents-stdio/Makefile +6 -0
- package/examples/openai-agents-stdio/README.md +14 -0
- package/examples/raw-sql-vs-synapsor/Makefile +11 -0
- package/examples/raw-sql-vs-synapsor/README.md +41 -0
- package/examples/reference-support-billing-app/scripts/run-demo.sh +0 -0
- package/examples/support-billing-agent/Makefile +19 -0
- package/examples/support-billing-agent/README.md +89 -0
- package/examples/support-billing-agent/app/README.md +13 -0
- package/examples/support-billing-agent/db/schema.sql +91 -0
- package/examples/support-billing-agent/db/seed.sql +43 -0
- package/examples/support-billing-agent/docker-compose.yml +13 -0
- package/examples/support-billing-agent/scripts/run-demo.sh +15 -0
- package/examples/support-billing-agent/synapsor.runner.json +233 -0
- package/package.json +27 -10
package/README.md
CHANGED
|
@@ -1,11 +1,32 @@
|
|
|
1
1
|
# Synapsor Runner
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@synapsor/runner)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
[](https://github.com/synapsor-ai/synapsor-runner/actions/workflows/ci.yml)
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
or
|
|
7
|
+
Stop giving AI agents `execute_sql()`. Give them reviewed business actions.
|
|
8
|
+
|
|
9
|
+
Synapsor Runner is an Open-source MCP safety layer for Postgres and MySQL. It
|
|
10
|
+
sits between Claude, Cursor, OpenAI Agents SDK, or another MCP client and your
|
|
11
|
+
database so the model can inspect scoped data and propose changes without
|
|
12
|
+
receiving raw SQL, write credentials, approval tools, or commit authority.
|
|
13
|
+
|
|
14
|
+
```text
|
|
15
|
+
Without Synapsor:
|
|
16
|
+
agent -> execute_sql("UPDATE invoices SET late_fee_cents = 0 ...")
|
|
17
|
+
# raw write path, model-controlled scope, easy tenant mistake
|
|
18
|
+
|
|
19
|
+
With Synapsor Runner:
|
|
20
|
+
agent -> billing.propose_late_fee_waiver(invoice_id, reason)
|
|
21
|
+
# proposal only
|
|
22
|
+
human approves -> guarded writeback applies exactly one change
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Try the no-database quick demo:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx @synapsor/runner demo --quick
|
|
29
|
+
```
|
|
9
30
|
|
|
10
31
|
## The Five-Line Model
|
|
11
32
|
|
|
@@ -15,60 +36,6 @@ It can suggest: saved proposals with evidence and exact diffs.
|
|
|
15
36
|
It cannot commit: approval and writeback happen outside the model-facing tool.
|
|
16
37
|
After writeback, Runner keeps receipts and replay so you can inspect what happened.
|
|
17
38
|
|
|
18
|
-
## Four Terms
|
|
19
|
-
|
|
20
|
-
- Capability: a tool you define in config, such as `billing.inspect_invoice`
|
|
21
|
-
or `billing.propose_late_fee_waiver`. The agent only sees capabilities.
|
|
22
|
-
- Proposal: the agent's suggested database-backed change. It is saved, not
|
|
23
|
-
applied.
|
|
24
|
-
- Writeback: the moment an approved proposal actually changes the database.
|
|
25
|
-
- Executor: your app's writeback handler for anything richer than a guarded
|
|
26
|
-
one-row update.
|
|
27
|
-
|
|
28
|
-
You install only `@synapsor/runner`. There is no separate handler package to
|
|
29
|
-
install. A handler is your app's endpoint or script for rich approved writes;
|
|
30
|
-
Runner includes templates and examples to help you build one.
|
|
31
|
-
|
|
32
|
-
## Who Does What
|
|
33
|
-
|
|
34
|
-
You write the config: sources, trusted context, capabilities, visible fields,
|
|
35
|
-
proposal fields, and guards. For rich writes, you also write a small handler.
|
|
36
|
-
|
|
37
|
-
Synapsor Runner serves the MCP tools, stores evidence/proposals/receipts,
|
|
38
|
-
enforces tenant, column, version, and idempotency guards, routes writeback, and
|
|
39
|
-
keeps the replay log. You do not rebuild the safety loop yourself.
|
|
40
|
-
|
|
41
|
-
## The Writeback Rule
|
|
42
|
-
|
|
43
|
-
One-row update to an existing row: Runner can do guarded direct writeback.
|
|
44
|
-
Anything else, such as inserting a row, touching two tables, or emitting an
|
|
45
|
-
event: your app-owned executor does it after approval.
|
|
46
|
-
|
|
47
|
-
## How An External Handler Works
|
|
48
|
-
|
|
49
|
-
Some changes are too rich for Runner's one-row writeback: insert a credit row,
|
|
50
|
-
touch two tables, or emit an event. For those, you run a small endpoint. The
|
|
51
|
-
flow is:
|
|
52
|
-
|
|
53
|
-
```text
|
|
54
|
-
agent proposes
|
|
55
|
-
-> human approves outside MCP
|
|
56
|
-
-> Runner POSTs the approved change to your endpoint
|
|
57
|
-
-> your code writes it in its own transaction and returns a receipt
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
The model never touches this code. You are the last line of defense: Runner
|
|
61
|
-
hands you the tenant, expected row version, and idempotency key, and your
|
|
62
|
-
handler must re-check all three. Skipping those checks reintroduces
|
|
63
|
-
cross-tenant writes, lost updates, or duplicate writes. Start from
|
|
64
|
-
`synapsor-runner handler template ...` instead of hand-rolling the safety checks.
|
|
65
|
-
|
|
66
|
-
## Deliberate Limits
|
|
67
|
-
|
|
68
|
-
Runner does not expose raw SQL, write credentials, approval tools, or commit
|
|
69
|
-
tools to the model. Direct Runner writeback does not do generic `INSERT`,
|
|
70
|
-
`DELETE`, `UPSERT`, DDL, or multi-row SQL. Those are app-owned executor jobs.
|
|
71
|
-
|
|
72
39
|
```text
|
|
73
40
|
AI agent or MCP client
|
|
74
41
|
(Claude, Cursor, OpenAI Agents SDK, LangGraph)
|
|
@@ -97,23 +64,13 @@ Your database stays the source of truth. Synapsor Runner owns the
|
|
|
97
64
|
model-facing boundary: what the agent can read, what it can propose, what
|
|
98
65
|
evidence is saved, and what can later be reviewed or replayed.
|
|
99
66
|
|
|
100
|
-
## What Runner Does
|
|
101
|
-
|
|
102
|
-
When an agent uses Runner:
|
|
103
|
-
|
|
104
|
-
- the model gets reviewed capabilities, not raw database authority;
|
|
105
|
-
- reads produce evidence handles and query audit;
|
|
106
|
-
- writes become proposals, not direct mutations;
|
|
107
|
-
- approval and writeback happen outside the model-facing MCP surface;
|
|
108
|
-
- replay shows what the agent saw, proposed, and what was applied or blocked.
|
|
109
|
-
|
|
110
67
|
## Start Here
|
|
111
68
|
|
|
112
69
|
Run the guided quick demo first. It does not require Docker, a database, a
|
|
113
70
|
config file, an MCP client, or a Synapsor Cloud account.
|
|
114
71
|
|
|
115
72
|
```bash
|
|
116
|
-
npx
|
|
73
|
+
npx @synapsor/runner demo --quick
|
|
117
74
|
```
|
|
118
75
|
|
|
119
76
|
In a terminal, it walks through the safety model step by step. In CI, piped
|
|
@@ -125,44 +82,189 @@ It does not prove database connectivity. It shows the proposal, evidence, and
|
|
|
125
82
|
replay flow without giving the runner a database URL.
|
|
126
83
|
|
|
127
84
|
```bash
|
|
128
|
-
npx
|
|
85
|
+
npx @synapsor/runner demo inspect
|
|
129
86
|
```
|
|
130
87
|
|
|
131
|
-
|
|
132
|
-
`--json` for complete machine-readable records.
|
|
133
|
-
|
|
134
|
-
Useful quick-demo modes:
|
|
88
|
+
Then choose one path:
|
|
135
89
|
|
|
136
|
-
```
|
|
137
|
-
synapsor-runner demo
|
|
138
|
-
synapsor-runner
|
|
139
|
-
synapsor-runner demo --quick --details
|
|
140
|
-
synapsor-runner demo inspect --npx
|
|
90
|
+
```text
|
|
91
|
+
Full disposable proof -> npx -y -p @synapsor/runner synapsor-runner demo
|
|
92
|
+
Inspect MCP risk -> npx -y -p @synapsor/runner synapsor-runner audit --example dangerous-db-mcp
|
|
141
93
|
```
|
|
142
94
|
|
|
143
|
-
|
|
95
|
+
## Why Not Just Build This Yourself?
|
|
96
|
+
|
|
97
|
+
You can build the outline in an afternoon:
|
|
144
98
|
|
|
145
99
|
```text
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
100
|
+
model calls a function
|
|
101
|
+
-> app stores a pending change
|
|
102
|
+
-> human approves
|
|
103
|
+
-> app runs SQL
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
That is useful, but it is not the safety layer. The repeated hard parts are
|
|
107
|
+
tenant scope, no raw SQL exposure, evidence, query audit, exact diffs,
|
|
108
|
+
approval outside the model-facing tool surface, idempotency, stale-row conflict
|
|
109
|
+
checks, affected-row checks, receipts, and replay.
|
|
110
|
+
|
|
111
|
+
Synapsor Runner gives you those pieces as a local runtime:
|
|
112
|
+
|
|
113
|
+
- reviewed semantic capabilities instead of `execute_sql`;
|
|
114
|
+
- trusted tenant/principal/object bindings from your server-side context;
|
|
115
|
+
- scoped reads with evidence handles and query audit;
|
|
116
|
+
- saved proposals with exact before/after changes;
|
|
117
|
+
- approval and writeback commands that are not exposed to the model;
|
|
118
|
+
- guarded direct writeback for one-row updates;
|
|
119
|
+
- app-owned executors for richer writes;
|
|
120
|
+
- idempotency receipts and replay so you can inspect what happened later.
|
|
121
|
+
|
|
122
|
+
If all you need is restricted reads, a read-only database user and safe views
|
|
123
|
+
are a good start. Use Runner when you need the agent-facing boundary around
|
|
124
|
+
those reads, or when database-backed actions must become proposals before any
|
|
125
|
+
durable write happens.
|
|
126
|
+
|
|
127
|
+
## Connect Your Postgres Or MySQL
|
|
128
|
+
|
|
129
|
+
Use a staging or disposable database first:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
export DATABASE_URL="postgres://readonly:...@localhost:5432/app"
|
|
133
|
+
npx -y -p @synapsor/runner synapsor-runner start --from-env DATABASE_URL
|
|
149
134
|
```
|
|
150
135
|
|
|
151
|
-
|
|
152
|
-
or another MCP client:
|
|
136
|
+
The first-run path is:
|
|
153
137
|
|
|
154
138
|
```text
|
|
155
|
-
1.
|
|
139
|
+
1. Inspect schema and generate a reviewed config with start/init/onboard.
|
|
156
140
|
2. Run tools preview to confirm no raw SQL or write credentials are exposed.
|
|
157
141
|
3. Run smoke call against one generated inspect tool.
|
|
158
|
-
4.
|
|
142
|
+
4. Start review mode with up --serve or mcp serve.
|
|
143
|
+
5. Inspect, propose, approve, apply, and replay from the local ledger.
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Useful commands after setup:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
synapsor-runner tools preview --config ./synapsor.runner.json --store ./.synapsor/local.db
|
|
150
|
+
synapsor-runner smoke call --config ./synapsor.runner.json --store ./.synapsor/local.db
|
|
151
|
+
synapsor-runner up --serve --config ./synapsor.runner.json --store ./.synapsor/local.db
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
If you already have a canonical `synapsor.contract.json` from the DSL, Cloud,
|
|
155
|
+
or the C++ exporter, keep it as the source of truth and reference it from local
|
|
156
|
+
runner wiring:
|
|
157
|
+
|
|
158
|
+
```json
|
|
159
|
+
{
|
|
160
|
+
"version": 1,
|
|
161
|
+
"mode": "review",
|
|
162
|
+
"contracts": ["./synapsor.contract.json"],
|
|
163
|
+
"sources": {
|
|
164
|
+
"local_postgres": {
|
|
165
|
+
"engine": "postgres",
|
|
166
|
+
"read_url_env": "DATABASE_URL"
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
"storage": {
|
|
170
|
+
"sqlite_path": "./.synapsor/local.db"
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Preview the model-facing tool surface before connecting an MCP client:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
synapsor-runner contract validate ./synapsor.contract.json
|
|
179
|
+
synapsor-runner tools preview --config ./synapsor.runner.json --store ./.synapsor/local.db
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## What Runner Does
|
|
183
|
+
|
|
184
|
+
When an agent uses Runner:
|
|
185
|
+
|
|
186
|
+
- the model gets reviewed capabilities, not raw database authority;
|
|
187
|
+
- reads produce evidence handles and query audit;
|
|
188
|
+
- writes become proposals, not direct mutations;
|
|
189
|
+
- approval and writeback happen outside the model-facing MCP surface;
|
|
190
|
+
- replay shows what the agent saw, proposed, and what was applied or blocked.
|
|
191
|
+
|
|
192
|
+
## Four Terms
|
|
193
|
+
|
|
194
|
+
- Capability: a tool you define in config, such as `billing.inspect_invoice`
|
|
195
|
+
or `billing.propose_late_fee_waiver`. The agent only sees capabilities.
|
|
196
|
+
- Proposal: the agent's suggested database-backed change. It is saved, not
|
|
197
|
+
applied.
|
|
198
|
+
- Writeback: the moment an approved proposal actually changes the database.
|
|
199
|
+
- Executor: your app's writeback handler for anything richer than a guarded
|
|
200
|
+
one-row update.
|
|
201
|
+
|
|
202
|
+
You install only `@synapsor/runner`. There is no separate handler package to
|
|
203
|
+
install. A handler is your app's endpoint or script for rich approved writes;
|
|
204
|
+
Runner includes templates and examples to help you build one.
|
|
205
|
+
|
|
206
|
+
## Who Does What
|
|
207
|
+
|
|
208
|
+
You write the config: sources, trusted context, capabilities, visible fields,
|
|
209
|
+
proposal fields, and guards. For rich writes, you also write a small handler.
|
|
210
|
+
|
|
211
|
+
Synapsor Runner serves the MCP tools, stores evidence/proposals/receipts,
|
|
212
|
+
enforces tenant, column, version, and idempotency guards, routes writeback, and
|
|
213
|
+
keeps the replay log. You do not rebuild the safety loop yourself.
|
|
214
|
+
|
|
215
|
+
## The Writeback Rule
|
|
216
|
+
|
|
217
|
+
One-row update to an existing row: Runner can do guarded direct writeback.
|
|
218
|
+
Anything else, such as inserting a row, touching two tables, or emitting an
|
|
219
|
+
event: your app-owned executor does it after approval.
|
|
220
|
+
|
|
221
|
+
## How An External Handler Works
|
|
222
|
+
|
|
223
|
+
Some changes are too rich for Runner's one-row writeback: insert a credit row,
|
|
224
|
+
touch two tables, or emit an event. For those, you run a small endpoint. The
|
|
225
|
+
flow is:
|
|
226
|
+
|
|
227
|
+
```text
|
|
228
|
+
agent proposes
|
|
229
|
+
-> human approves outside MCP
|
|
230
|
+
-> Runner POSTs the approved change to your endpoint
|
|
231
|
+
-> your code writes it in its own transaction and returns a receipt
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
The model never touches this code. You are the last line of defense: Runner
|
|
235
|
+
hands you the tenant, expected row version, and idempotency key, and your
|
|
236
|
+
handler must re-check all three. Skipping those checks reintroduces
|
|
237
|
+
cross-tenant writes, lost updates, or duplicate writes. Start from
|
|
238
|
+
`synapsor-runner handler template ...` instead of hand-rolling the safety checks.
|
|
239
|
+
|
|
240
|
+
## Deliberate Limits
|
|
241
|
+
|
|
242
|
+
Runner does not expose raw SQL, write credentials, approval tools, or commit
|
|
243
|
+
tools to the model. Direct Runner writeback does not do generic `INSERT`,
|
|
244
|
+
`DELETE`, `UPSERT`, DDL, or multi-row SQL. Those are app-owned executor jobs.
|
|
245
|
+
|
|
246
|
+
## Command Name
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
npm install -g @synapsor/runner
|
|
250
|
+
synapsor-runner demo --quick
|
|
159
251
|
```
|
|
160
252
|
|
|
161
253
|
`synapsor-runner` is the public command for this OSS runner. `synapsor` is
|
|
162
|
-
reserved for the Synapsor Cloud CLI.
|
|
254
|
+
reserved for the Synapsor Cloud CLI. If you install the package globally, you
|
|
255
|
+
can drop the `npx -y -p @synapsor/runner` prefix.
|
|
256
|
+
|
|
257
|
+
Contributor note: during development, test local changes with
|
|
258
|
+
`./bin/synapsor-runner ...` or a packed tarball. `npx -p @synapsor/runner ...`
|
|
259
|
+
only tests the currently published package, not unpublished local source
|
|
260
|
+
changes.
|
|
163
261
|
|
|
164
262
|
Authoring reference:
|
|
165
263
|
|
|
264
|
+
- [Migrating To `@synapsor/spec`](docs/migrating-to-synapsor-spec.md):
|
|
265
|
+
split portable contract semantics from local runner wiring.
|
|
266
|
+
- [Conformance Fixtures](docs/conformance.md): how the shared fixture suite
|
|
267
|
+
keeps Runner and Cloud/C++ contract semantics from drifting.
|
|
166
268
|
- [Capability Authoring](docs/capability-authoring.md): read/proposal tools,
|
|
167
269
|
model-facing descriptions, result envelope v2, trusted context, and writeback
|
|
168
270
|
guards.
|
|
@@ -171,7 +273,7 @@ Authoring reference:
|
|
|
171
273
|
- [JSON Schema](schemas/synapsor.runner.schema.json): editor validation for
|
|
172
274
|
`synapsor.runner.json`.
|
|
173
275
|
|
|
174
|
-
##
|
|
276
|
+
## Operational Details
|
|
175
277
|
|
|
176
278
|
These are current alpha requirements, not hidden behavior:
|
|
177
279
|
|
|
@@ -206,12 +308,64 @@ These are current alpha requirements, not hidden behavior:
|
|
|
206
308
|
`synapsor-runner doctor --config synapsor.runner.json --check-handlers` to
|
|
207
309
|
check handler env vars and network reachability without applying a proposal.
|
|
208
310
|
|
|
311
|
+
## Run The Full Disposable Demo
|
|
312
|
+
|
|
313
|
+
The full demo requires Docker. It starts a disposable local Postgres-backed app
|
|
314
|
+
and proves the proposal-first write path:
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
npx -y -p @synapsor/runner synapsor-runner demo
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
After the demo prints its generated config and store path, run the happy path it
|
|
321
|
+
prints. The shape is:
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
synapsor-runner propose billing.propose_late_fee_waiver --sample
|
|
325
|
+
synapsor-runner proposals show latest
|
|
326
|
+
synapsor-runner proposals approve latest --yes
|
|
327
|
+
synapsor-runner apply latest
|
|
328
|
+
synapsor-runner replay show latest
|
|
329
|
+
synapsor-runner replay show latest --details
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
What you should see:
|
|
333
|
+
|
|
334
|
+
```text
|
|
335
|
+
Agent called:
|
|
336
|
+
billing.propose_late_fee_waiver
|
|
337
|
+
|
|
338
|
+
Proposal created:
|
|
339
|
+
invoice.late_fee_cents
|
|
340
|
+
5500 -> 0
|
|
341
|
+
|
|
342
|
+
Source DB changed:
|
|
343
|
+
no
|
|
344
|
+
|
|
345
|
+
Approval:
|
|
346
|
+
required outside MCP
|
|
347
|
+
|
|
348
|
+
After approval:
|
|
349
|
+
guarded writeback applied
|
|
350
|
+
|
|
351
|
+
Replay:
|
|
352
|
+
saved
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
That is the core point: the model can ask for a database-backed business
|
|
356
|
+
change, but durable state changes only after reviewed approval and guarded
|
|
357
|
+
writeback.
|
|
358
|
+
|
|
209
359
|
## Connect Your Own Staging Database
|
|
210
360
|
|
|
211
|
-
|
|
361
|
+
Use this after the quick demo makes sense. Start with staging, a disposable
|
|
362
|
+
database, or a least-privilege view. Do not start with your most sensitive
|
|
363
|
+
production database.
|
|
364
|
+
|
|
365
|
+
Put the read-only connection string in an environment variable:
|
|
212
366
|
|
|
213
367
|
```bash
|
|
214
|
-
export DATABASE_URL="postgresql://readonly_user:password@
|
|
368
|
+
export DATABASE_URL="postgresql://readonly_user:password@host:5432/app?sslmode=require"
|
|
215
369
|
```
|
|
216
370
|
|
|
217
371
|
For disposable dev RDS fixtures only, use `sslmode=no-verify` if your local
|
|
@@ -238,20 +392,6 @@ call immediately and stores the evidence/query audit in the local ledger. If
|
|
|
238
392
|
those env vars are missing, it prints the exact command to run after you set
|
|
239
393
|
them from `.env.example`.
|
|
240
394
|
|
|
241
|
-
The end-to-end shape is:
|
|
242
|
-
|
|
243
|
-
```text
|
|
244
|
-
1. Put your read-only DB URL in DATABASE_URL.
|
|
245
|
-
2. Run start --from-env DATABASE_URL.
|
|
246
|
-
3. Choose one table/view and the safe fields agents may see.
|
|
247
|
-
4. Preview the generated capabilities.
|
|
248
|
-
5. Serve them over MCP to Claude, Cursor, OpenAI Agents SDK, or your app.
|
|
249
|
-
6. For writes, approve a proposal outside MCP before writeback.
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
The generated config is just the safety contract. A small reviewed version
|
|
253
|
-
looks like this:
|
|
254
|
-
|
|
255
395
|
Bring the generated review-mode workspace up with one command:
|
|
256
396
|
|
|
257
397
|
```bash
|
|
@@ -301,6 +441,20 @@ so `config validate` does not warn that direct SQL writeback is disabled.
|
|
|
301
441
|
You can also pass `--answers ./answers.json --yes` for a fully declarative
|
|
302
442
|
setup file.
|
|
303
443
|
|
|
444
|
+
The end-to-end shape is:
|
|
445
|
+
|
|
446
|
+
```text
|
|
447
|
+
1. Put your read-only DB URL in DATABASE_URL.
|
|
448
|
+
2. Run start --from-env DATABASE_URL.
|
|
449
|
+
3. Choose one table/view and the safe fields agents may see.
|
|
450
|
+
4. Preview the generated capabilities.
|
|
451
|
+
5. Serve them over MCP to Claude, Cursor, OpenAI Agents SDK, or your app.
|
|
452
|
+
6. For writes, approve a proposal outside MCP before writeback.
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
The generated config is just the safety contract. A small reviewed version
|
|
456
|
+
looks like this:
|
|
457
|
+
|
|
304
458
|
```json
|
|
305
459
|
{
|
|
306
460
|
"version": 1,
|
|
@@ -371,6 +525,17 @@ The agent sees `billing.inspect_invoice` and
|
|
|
371
525
|
`billing.propose_late_fee_waiver`. It does not see the database URL, writer
|
|
372
526
|
credential, raw SQL, approval command, or commit command.
|
|
373
527
|
|
|
528
|
+
Prefer the step-by-step commands if you want to inspect each stage manually:
|
|
529
|
+
|
|
530
|
+
```bash
|
|
531
|
+
npx -y -p @synapsor/runner synapsor-runner inspect \
|
|
532
|
+
--engine auto \
|
|
533
|
+
--from-env DATABASE_URL \
|
|
534
|
+
--schema public
|
|
535
|
+
|
|
536
|
+
npx -y -p @synapsor/runner synapsor-runner init --wizard --from-env DATABASE_URL --mode read_only
|
|
537
|
+
```
|
|
538
|
+
|
|
374
539
|
The wizard creates this local flow:
|
|
375
540
|
|
|
376
541
|
```text
|
|
@@ -380,45 +545,55 @@ trusted context -> capability -> MCP tool
|
|
|
380
545
|
It asks which table/view backs the context, which tenant/scope column and
|
|
381
546
|
backend session env vars are trusted, which fields are visible, and what
|
|
382
547
|
semantic capability name to expose. Before writing files, it shows a final
|
|
383
|
-
preview and lets you revise visible fields or capability names.
|
|
548
|
+
preview and lets you revise visible fields or capability names. It writes
|
|
549
|
+
`synapsor.runner.json`, `.env.example`, and MCP client snippets. It does not put
|
|
550
|
+
your database URL in the MCP client config.
|
|
551
|
+
|
|
552
|
+
Preview the tools:
|
|
384
553
|
|
|
385
554
|
```bash
|
|
386
|
-
npx -y -p @synapsor/runner synapsor-runner
|
|
387
|
-
--
|
|
388
|
-
--
|
|
389
|
-
--from-env DATABASE_URL \
|
|
390
|
-
--schema public \
|
|
391
|
-
--mode read_only
|
|
555
|
+
npx -y -p @synapsor/runner synapsor-runner tools preview \
|
|
556
|
+
--config ./synapsor.runner.json \
|
|
557
|
+
--store ./.synapsor/local.db
|
|
392
558
|
```
|
|
393
559
|
|
|
394
|
-
|
|
560
|
+
Call one generated tool locally before wiring an MCP client:
|
|
395
561
|
|
|
396
562
|
```bash
|
|
397
|
-
npx -y -p @synapsor/runner synapsor-runner
|
|
563
|
+
npx -y -p @synapsor/runner synapsor-runner smoke call \
|
|
564
|
+
<generated.inspect_tool_name> \
|
|
565
|
+
--input ./.synapsor/smoke-input.json \
|
|
398
566
|
--config ./synapsor.runner.json \
|
|
399
567
|
--store ./.synapsor/local.db
|
|
568
|
+
```
|
|
400
569
|
|
|
570
|
+
`smoke call` uses the same runtime as MCP, records evidence/query audit or a
|
|
571
|
+
proposal in the local store, and then prints the evidence/proposal/replay
|
|
572
|
+
commands to inspect what happened. If you skipped the optional smoke input in
|
|
573
|
+
the wizard, pass one real row id instead:
|
|
574
|
+
|
|
575
|
+
```bash
|
|
401
576
|
npx -y -p @synapsor/runner synapsor-runner smoke call \
|
|
402
577
|
<generated.inspect_tool_name> \
|
|
403
|
-
--
|
|
578
|
+
--json '{"<lookup_arg>":"<real_id>"}' \
|
|
404
579
|
--config ./synapsor.runner.json \
|
|
405
580
|
--store ./.synapsor/local.db
|
|
581
|
+
```
|
|
406
582
|
|
|
583
|
+
Serve the semantic MCP tools locally:
|
|
584
|
+
|
|
585
|
+
```bash
|
|
407
586
|
npx -y -p @synapsor/runner synapsor-runner mcp serve \
|
|
408
587
|
--config ./synapsor.runner.json \
|
|
409
588
|
--store ./.synapsor/local.db
|
|
410
589
|
```
|
|
411
590
|
|
|
412
|
-
|
|
413
|
-
proposal in the local store, and prints the evidence/proposal/replay commands
|
|
414
|
-
to inspect what happened. If you skipped the optional smoke input in the
|
|
415
|
-
wizard, pass `--json '{"<lookup_arg>":"<real_id>"}'` instead.
|
|
416
|
-
|
|
417
|
-
## Two Ways To Run MCP
|
|
591
|
+
## Three Ways To Run MCP
|
|
418
592
|
|
|
419
593
|
Use stdio when the MCP client runs locally and can launch Synapsor Runner. Use
|
|
420
|
-
HTTP when
|
|
421
|
-
|
|
594
|
+
Streamable HTTP when a standard HTTP MCP client connects to a long-running
|
|
595
|
+
Runner process. Use the JSON-RPC bridge only when you want simple POST calls
|
|
596
|
+
from your own app/server wrapper.
|
|
422
597
|
|
|
423
598
|
Local MCP clients:
|
|
424
599
|
|
|
@@ -460,7 +635,8 @@ synapsor-runner up --serve \
|
|
|
460
635
|
--alias-mode openai
|
|
461
636
|
```
|
|
462
637
|
|
|
463
|
-
|
|
638
|
+
The same Streamable HTTP server can also be started through the unified serve
|
|
639
|
+
command:
|
|
464
640
|
|
|
465
641
|
```bash
|
|
466
642
|
synapsor-runner mcp serve \
|
|
@@ -500,86 +676,61 @@ examples/openai-agents-stdio/
|
|
|
500
676
|
examples/openai-agents-http/
|
|
501
677
|
```
|
|
502
678
|
|
|
503
|
-
|
|
504
|
-
guarded writeback with a separate trusted write credential.
|
|
505
|
-
|
|
506
|
-
## Sanity Check The Agent Connection
|
|
679
|
+
Detailed setup: [docs/openai-agents-sdk.md](docs/openai-agents-sdk.md).
|
|
507
680
|
|
|
508
|
-
|
|
681
|
+
Use `--mode review` only when you are ready to create proposal tools and test
|
|
682
|
+
guarded writeback. Review mode needs an approved write path and a separate
|
|
683
|
+
trusted write credential; the model-facing read URL should stay least
|
|
684
|
+
privilege.
|
|
509
685
|
|
|
510
|
-
|
|
511
|
-
synapsor-runner tools preview --config ./synapsor.runner.json --store ./.synapsor/local.db
|
|
512
|
-
```
|
|
686
|
+
## Audit Your MCP Database Tools
|
|
513
687
|
|
|
514
|
-
|
|
688
|
+
`synapsor-runner audit` is a static MCP/database risk review. It is useful even before
|
|
689
|
+
you adopt the full runner.
|
|
515
690
|
|
|
516
691
|
```bash
|
|
517
|
-
synapsor-runner
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
692
|
+
synapsor-runner audit --example dangerous-db-mcp
|
|
693
|
+
synapsor-runner audit --example dangerous-db-mcp --format markdown
|
|
694
|
+
synapsor-runner audit ./synapsor.runner.json
|
|
695
|
+
synapsor-runner audit --mcp-config ./claude_desktop_config.json
|
|
696
|
+
synapsor-runner audit --stdio "node ./my-db-mcp-server.js"
|
|
521
697
|
```
|
|
522
698
|
|
|
523
|
-
|
|
699
|
+
The built-in example runs without cloning this repository or downloading an
|
|
700
|
+
examples file. File-based audits still work when you have your own exported MCP
|
|
701
|
+
tool manifest.
|
|
524
702
|
|
|
525
|
-
|
|
526
|
-
Use the Synapsor Runner MCP tool to inspect invoice INV-3001.
|
|
527
|
-
Do not answer from memory.
|
|
528
|
-
Return the tool name called, the evidence handle, and whether raw SQL was available.
|
|
529
|
-
```
|
|
530
|
-
|
|
531
|
-
Expected result: the agent calls a semantic tool, returns an evidence handle or
|
|
532
|
-
local ledger reference, and says raw SQL/write/approval tools were not
|
|
533
|
-
available. If it gives generic advice or unrelated prose without a tool call,
|
|
534
|
-
Runner is not connected yet.
|
|
535
|
-
|
|
536
|
-
The disposable reference app includes proposal-first write examples for:
|
|
537
|
-
|
|
538
|
-
- `billing.propose_late_fee_waiver`
|
|
539
|
-
- `support.propose_plan_credit`
|
|
540
|
-
- `orders.propose_status_change`
|
|
541
|
-
|
|
542
|
-
Each tool creates evidence, a before/after diff, and a proposal. The source
|
|
543
|
-
database remains unchanged until approval outside MCP and guarded writeback.
|
|
544
|
-
|
|
545
|
-
For a longer local session, you can install the package globally:
|
|
546
|
-
|
|
547
|
-
```bash
|
|
548
|
-
npm install -g @synapsor/runner
|
|
549
|
-
```
|
|
703
|
+
It looks for patterns such as:
|
|
550
704
|
|
|
551
|
-
|
|
705
|
+
- arbitrary SQL tools;
|
|
706
|
+
- broad database write tools;
|
|
707
|
+
- model-facing approval/commit tools;
|
|
708
|
+
- missing tenant/principal context;
|
|
709
|
+
- dangerous tool names;
|
|
710
|
+
- unclear parameter schemas;
|
|
711
|
+
- mutation tools without proposal/approval.
|
|
552
712
|
|
|
553
|
-
|
|
554
|
-
binary, `synapsor.runner.json` schema version `1`, result envelope v2, stdio
|
|
555
|
-
MCP, Streamable HTTP MCP, MCP client snippets, proposal/approval/writeback
|
|
556
|
-
inspection commands, direct SQL writeback contract, and app-owned executor
|
|
557
|
-
contract compatible through the `0.1.x` line unless a release note marks a
|
|
558
|
-
deprecation first.
|
|
559
|
-
|
|
560
|
-
Stable does not mean production SLA, hosted Cloud features, compliance
|
|
561
|
-
certification, physical Postgres/MySQL branching, generic SQL writeback, or
|
|
562
|
-
support for undocumented local SQLite internals.
|
|
563
|
-
|
|
564
|
-
## Runtime Flow
|
|
565
|
-
|
|
566
|
-
The local runner keeps the model-facing tool call separate from approval and
|
|
567
|
-
writeback:
|
|
713
|
+
Example finding:
|
|
568
714
|
|
|
569
715
|
```text
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
716
|
+
Risk: high
|
|
717
|
+
|
|
718
|
+
Found:
|
|
719
|
+
- execute_sql appears to expose arbitrary database access.
|
|
720
|
+
- approve_refund appears to let the model approve a durable write.
|
|
721
|
+
- update_customer appears to mutate state without a proposal boundary.
|
|
722
|
+
- No trusted tenant/principal context was detected.
|
|
723
|
+
|
|
724
|
+
Suggested safer shape:
|
|
725
|
+
- billing.inspect_invoice
|
|
726
|
+
- billing.propose_late_fee_waiver
|
|
727
|
+
- approval outside MCP
|
|
728
|
+
- guarded writeback after approval
|
|
729
|
+
|
|
730
|
+
Note:
|
|
731
|
+
This is a static risk review, not a security guarantee.
|
|
578
732
|
```
|
|
579
733
|
|
|
580
|
-
Your Postgres/MySQL database remains the source of truth. The runner stores
|
|
581
|
-
local proposals, evidence, receipts, and replay data in a local SQLite store.
|
|
582
|
-
|
|
583
734
|
## Why Not Just Use A Read-Only Database User?
|
|
584
735
|
|
|
585
736
|
You should use one.
|
|
@@ -606,47 +757,30 @@ Use Synapsor Runner when you also want the agent-facing layer: semantic tools,
|
|
|
606
757
|
trusted context, evidence handles, query audit, local inspection, and
|
|
607
758
|
proposal-first writes.
|
|
608
759
|
|
|
609
|
-
##
|
|
610
|
-
|
|
611
|
-
Run the included MCP efficiency fixture:
|
|
760
|
+
## Find Evidence And Replay
|
|
612
761
|
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
```
|
|
762
|
+
The commands in this section require this checkout or an alpha package that
|
|
763
|
+
includes the local-ledger CLI surface.
|
|
616
764
|
|
|
617
|
-
|
|
765
|
+
Synapsor Runner writes a local evidence/replay ledger to SQLite. Use it to
|
|
766
|
+
answer questions such as:
|
|
618
767
|
|
|
619
768
|
```text
|
|
620
|
-
|
|
621
|
-
exposed tools: 4
|
|
622
|
-
scripted tool calls: 5
|
|
623
|
-
raw SQL exposed: yes
|
|
624
|
-
approval separated: no
|
|
625
|
-
stale-row conflict checked: no
|
|
626
|
-
|
|
627
|
-
Synapsor Runner semantic path:
|
|
628
|
-
exposed tools: 2
|
|
629
|
-
scripted tool calls: 2
|
|
630
|
-
raw SQL exposed: no
|
|
631
|
-
approval separated: yes
|
|
632
|
-
stale-row conflict checked: yes
|
|
769
|
+
What did the agent see and do for invoice INV-3001?
|
|
633
770
|
```
|
|
634
771
|
|
|
635
|
-
|
|
636
|
-
not a model billing tokenizer and not a universal token-savings claim.
|
|
637
|
-
|
|
638
|
-
## Find Evidence And Replay
|
|
639
|
-
|
|
640
|
-
The commands in this section require this checkout or an alpha package that
|
|
641
|
-
includes the local-ledger CLI surface.
|
|
642
|
-
|
|
643
|
-
The runner stores a local SQLite evidence/replay ledger. Search it without
|
|
644
|
-
relying on `latest`:
|
|
772
|
+
Search the local activity ledger:
|
|
645
773
|
|
|
646
774
|
```bash
|
|
647
775
|
synapsor-runner activity search --tenant acme --object invoice:INV-3001
|
|
776
|
+
synapsor-runner activity search --capability billing.propose_late_fee_waiver --from 2026-06-01 --to 2026-06-23
|
|
648
777
|
synapsor-runner events tail --store ./.synapsor/local.db
|
|
649
778
|
synapsor-runner events webhook --url http://127.0.0.1:8788/synapsor/events --kind proposal_created --store ./.synapsor/local.db
|
|
779
|
+
```
|
|
780
|
+
|
|
781
|
+
Inspect the linked records:
|
|
782
|
+
|
|
783
|
+
```bash
|
|
650
784
|
synapsor-runner proposals list --tenant acme --object invoice:INV-3001 --status approved
|
|
651
785
|
synapsor-runner evidence show ev_...
|
|
652
786
|
synapsor-runner query-audit list --evidence ev_...
|
|
@@ -656,16 +790,17 @@ synapsor-runner replay show --proposal wrp_...
|
|
|
656
790
|
synapsor-runner replay show --replay replay_wrp_...
|
|
657
791
|
```
|
|
658
792
|
|
|
659
|
-
|
|
793
|
+
The default views answer what happened, whether the source DB changed, the
|
|
794
|
+
current status, and the next command to run. Add `--details` when you need
|
|
660
795
|
target URIs, primary keys, proposal hash/version, conflict guards, query
|
|
661
|
-
fingerprints, event timestamps,
|
|
796
|
+
fingerprints, event timestamps, or receipt internals.
|
|
662
797
|
|
|
663
|
-
Export
|
|
798
|
+
Export replay or evidence for review:
|
|
664
799
|
|
|
665
800
|
```bash
|
|
666
|
-
synapsor-runner evidence export ev_... --format markdown --output evidence.md
|
|
667
801
|
synapsor-runner replay export --proposal wrp_... --format json --output replay.json
|
|
668
802
|
synapsor-runner replay export --proposal wrp_... --format markdown --output replay.md
|
|
803
|
+
synapsor-runner evidence export ev_... --format markdown --output evidence.md
|
|
669
804
|
```
|
|
670
805
|
|
|
671
806
|
Create a redacted local diagnostic report:
|
|
@@ -690,16 +825,171 @@ synapsor-runner store reset --store ./.synapsor/local.db --yes
|
|
|
690
825
|
bridges, or app-local notifications. It POSTs one redacted local event envelope
|
|
691
826
|
per lifecycle event; it is not a hosted central ledger.
|
|
692
827
|
|
|
693
|
-
This is local indexed search for local/dev/staging usage. It is not
|
|
694
|
-
|
|
695
|
-
retention.
|
|
828
|
+
This is local indexed search for local/dev/staging usage. It is not a hosted
|
|
829
|
+
central ledger, not RBAC/SSO, not cross-runner search, and not compliance
|
|
830
|
+
retention. Synapsor Cloud is the upgrade path for central searchable audit,
|
|
831
|
+
team governance, retention, and production operations.
|
|
832
|
+
|
|
833
|
+
## Connect Claude, Cursor, Or Another MCP Client
|
|
834
|
+
|
|
835
|
+
Generate a local MCP client snippet:
|
|
836
|
+
|
|
837
|
+
```bash
|
|
838
|
+
synapsor-runner mcp config --config ./synapsor.runner.json --store ./.synapsor/local.db
|
|
839
|
+
```
|
|
840
|
+
|
|
841
|
+
Use a specific client shape when needed:
|
|
842
|
+
|
|
843
|
+
```bash
|
|
844
|
+
synapsor-runner mcp config cursor --config ./synapsor.runner.json --store ./.synapsor/local.db
|
|
845
|
+
synapsor-runner mcp config vscode --config ./synapsor.runner.json --store ./.synapsor/local.db
|
|
846
|
+
synapsor-runner mcp config generic --config ./synapsor.runner.json --store ./.synapsor/local.db
|
|
847
|
+
synapsor-runner mcp client-config --client openai-agents --config ./synapsor.runner.json --store ./.synapsor/local.db
|
|
848
|
+
```
|
|
849
|
+
|
|
850
|
+
The generated config references the local runner command. It does not include:
|
|
851
|
+
|
|
852
|
+
- database URL;
|
|
853
|
+
- database password;
|
|
854
|
+
- write credentials;
|
|
855
|
+
- approval tools;
|
|
856
|
+
- commit/apply tools.
|
|
857
|
+
|
|
858
|
+
## Sanity Check The Agent Connection
|
|
859
|
+
|
|
860
|
+
After you connect Claude, Cursor, OpenAI Agents SDK, or another MCP client, run
|
|
861
|
+
one tiny tool-call test before asking the agent to solve a real task.
|
|
862
|
+
|
|
863
|
+
First preview the tools Runner will expose:
|
|
864
|
+
|
|
865
|
+
```bash
|
|
866
|
+
synapsor-runner tools preview --config ./synapsor.runner.json --store ./.synapsor/local.db
|
|
867
|
+
```
|
|
868
|
+
|
|
869
|
+
For OpenAI-facing clients, preview the model-visible aliases:
|
|
870
|
+
|
|
871
|
+
```bash
|
|
872
|
+
synapsor-runner tools preview \
|
|
873
|
+
--config ./synapsor.runner.json \
|
|
874
|
+
--store ./.synapsor/local.db \
|
|
875
|
+
--alias-mode openai
|
|
876
|
+
```
|
|
877
|
+
|
|
878
|
+
Example:
|
|
879
|
+
|
|
880
|
+
```text
|
|
881
|
+
Exposed to MCP:
|
|
882
|
+
- billing__inspect_invoice -> billing.inspect_invoice
|
|
883
|
+
```
|
|
884
|
+
|
|
885
|
+
Then ask the agent:
|
|
886
|
+
|
|
887
|
+
```text
|
|
888
|
+
Use the Synapsor Runner MCP tool to inspect invoice INV-3001.
|
|
889
|
+
Do not answer from memory.
|
|
890
|
+
Return the tool name called, the evidence handle, and whether raw SQL was available.
|
|
891
|
+
```
|
|
892
|
+
|
|
893
|
+
For your own database, replace `invoice INV-3001` with one real object ID and
|
|
894
|
+
the semantic tool name from `tools preview`.
|
|
895
|
+
|
|
896
|
+
Expected result:
|
|
897
|
+
|
|
898
|
+
- the agent calls a Synapsor Runner tool such as `billing.inspect_invoice`;
|
|
899
|
+
- the response includes an evidence handle or local ledger reference;
|
|
900
|
+
- the agent says raw SQL/write/approval tools were not available.
|
|
901
|
+
|
|
902
|
+
If the agent gives generic advice, a freeform summary, or unrelated planning
|
|
903
|
+
text without a tool call or evidence handle, Runner is not in the loop yet. Fix
|
|
904
|
+
the MCP client config, restart the client, confirm trusted context environment
|
|
905
|
+
variables are set, and rerun `synapsor-runner tools preview`.
|
|
906
|
+
|
|
907
|
+
## What The Model Gets
|
|
908
|
+
|
|
909
|
+
The model gets reviewed semantic capabilities from `synapsor.runner.json`, for
|
|
910
|
+
example:
|
|
911
|
+
|
|
912
|
+
```text
|
|
913
|
+
billing.inspect_invoice
|
|
914
|
+
billing.propose_late_fee_waiver
|
|
915
|
+
support.inspect_ticket
|
|
916
|
+
support.propose_plan_credit
|
|
917
|
+
orders.inspect_order
|
|
918
|
+
orders.propose_status_change
|
|
919
|
+
```
|
|
920
|
+
|
|
921
|
+
These are business tools with trusted scope, visible fields, evidence rules,
|
|
922
|
+
proposal boundaries, and writeback guards.
|
|
923
|
+
|
|
924
|
+
## Fixture Benchmark
|
|
925
|
+
|
|
926
|
+
Run the included MCP efficiency fixture:
|
|
927
|
+
|
|
928
|
+
```bash
|
|
929
|
+
synapsor-runner benchmark mcp-efficiency
|
|
930
|
+
```
|
|
931
|
+
|
|
932
|
+
Current fixture result for the late-fee-waiver workflow:
|
|
933
|
+
|
|
934
|
+
```text
|
|
935
|
+
Generic database MCP reference:
|
|
936
|
+
exposed tools: 4
|
|
937
|
+
scripted tool calls: 5
|
|
938
|
+
raw SQL exposed: yes
|
|
939
|
+
approval separated: no
|
|
940
|
+
stale-row conflict checked: no
|
|
941
|
+
|
|
942
|
+
Synapsor Runner semantic path:
|
|
943
|
+
exposed tools: 2
|
|
944
|
+
scripted tool calls: 2
|
|
945
|
+
raw SQL exposed: no
|
|
946
|
+
approval separated: yes
|
|
947
|
+
stale-row conflict checked: yes
|
|
948
|
+
```
|
|
949
|
+
|
|
950
|
+
The fixture tokenizer is deterministic and repeatable for this repo. It is not
|
|
951
|
+
a model billing tokenizer and not a universal token-savings claim.
|
|
952
|
+
|
|
953
|
+
## Safe Write Examples
|
|
954
|
+
|
|
955
|
+
The disposable reference app includes three proposal-first write shapes:
|
|
956
|
+
|
|
957
|
+
- `billing.propose_late_fee_waiver`: waive a late fee after evidence and review.
|
|
958
|
+
- `support.propose_plan_credit`: propose a bounded customer credit for a support case.
|
|
959
|
+
- `orders.propose_status_change`: move an order through an allowlisted status transition.
|
|
960
|
+
|
|
961
|
+
Each tool creates evidence, a before/after diff, and a local proposal. The
|
|
962
|
+
source database is unchanged until approval outside MCP and guarded writeback.
|
|
963
|
+
|
|
964
|
+
## What The Model Never Gets
|
|
965
|
+
|
|
966
|
+
Synapsor Runner does not expose:
|
|
967
|
+
|
|
968
|
+
```text
|
|
969
|
+
execute_sql
|
|
970
|
+
raw_sql
|
|
971
|
+
query_database
|
|
972
|
+
database URLs
|
|
973
|
+
write credentials
|
|
974
|
+
approval tools
|
|
975
|
+
commit/apply tools
|
|
976
|
+
arbitrary table names
|
|
977
|
+
arbitrary column names
|
|
978
|
+
model-controlled tenant authority
|
|
979
|
+
direct write access
|
|
980
|
+
```
|
|
981
|
+
|
|
982
|
+
Approval and writeback stay outside the model-facing MCP tool surface.
|
|
696
983
|
|
|
697
984
|
## App-Owned Writeback
|
|
698
985
|
|
|
699
|
-
|
|
700
|
-
your application service already owns business writes,
|
|
701
|
-
`http_handler` or `command_handler` executor.
|
|
702
|
-
|
|
986
|
+
Direct guarded DB writeback is useful for local/staging demos and simple
|
|
987
|
+
single-row updates. If your application service already owns business writes,
|
|
988
|
+
configure an `http_handler` or `command_handler` executor instead.
|
|
989
|
+
|
|
990
|
+
The flow stays the same: model-facing MCP creates a proposal, approval happens
|
|
991
|
+
outside MCP, Synapsor Runner sends an approved job to your app handler, and the
|
|
992
|
+
handler returns an applied/conflict/failed receipt for replay.
|
|
703
993
|
|
|
704
994
|
> **Important:** your app handler owns the final business write. Runner creates
|
|
705
995
|
> the proposal and calls your handler only after approval, but your handler must
|
|
@@ -708,10 +998,17 @@ MCP, and the handler returns an applied/conflict/failed receipt for replay.
|
|
|
708
998
|
> error receipts. If you skip those checks, you can reintroduce cross-tenant
|
|
709
999
|
> writes, lost updates, or duplicate writes. Keep handler credentials out of MCP.
|
|
710
1000
|
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
1001
|
+
Details: [docs/writeback-executors.md](docs/writeback-executors.md). Starter
|
|
1002
|
+
handlers live in [examples/app-owned-writeback](examples/app-owned-writeback).
|
|
1003
|
+
The runner npm package includes handler templates and the
|
|
1004
|
+
`examples/mcp-postgres-billing-app-handler/synapsor-handler.mjs` bundled helper
|
|
1005
|
+
shim. These show bearer/HMAC auth, tenant scope, expected-version guards,
|
|
1006
|
+
idempotency, transaction rollback, and safe receipts around your business
|
|
1007
|
+
effect. There is no separate handler package to install.
|
|
1008
|
+
The full Postgres billing example in
|
|
1009
|
+
[examples/mcp-postgres-billing-app-handler](examples/mcp-postgres-billing-app-handler)
|
|
1010
|
+
shows `billing.propose_account_credit` creating a proposal first, then inserting
|
|
1011
|
+
an `account_credits` row through an app-owned HTTP handler after approval.
|
|
715
1012
|
You can also generate a starter handler directly:
|
|
716
1013
|
|
|
717
1014
|
```bash
|
|
@@ -726,16 +1023,224 @@ needs permission for that receipt table or an administrator must pre-create and
|
|
|
726
1023
|
grant it. Use app-owned handlers when you do not want Runner creating receipt
|
|
727
1024
|
tables in your application schema.
|
|
728
1025
|
|
|
729
|
-
##
|
|
1026
|
+
## Safety Model
|
|
1027
|
+
|
|
1028
|
+
```text
|
|
1029
|
+
MCP client
|
|
1030
|
+
-> Synapsor Runner
|
|
1031
|
+
-> semantic capability
|
|
1032
|
+
-> trusted tenant/principal context
|
|
1033
|
+
-> scoped DB read
|
|
1034
|
+
-> evidence-backed proposal
|
|
1035
|
+
-> approval outside MCP
|
|
1036
|
+
-> guarded writeback
|
|
1037
|
+
-> receipt and replay
|
|
1038
|
+
```
|
|
1039
|
+
|
|
1040
|
+
Current boundaries:
|
|
1041
|
+
|
|
1042
|
+
- no generic SQL tools;
|
|
1043
|
+
- no model-facing approval or apply tools;
|
|
1044
|
+
- tenant/principal scoping is enforced;
|
|
1045
|
+
- allowed columns are enforced;
|
|
1046
|
+
- primary-key targeting is required;
|
|
1047
|
+
- conflict/version guards are available;
|
|
1048
|
+
- idempotency keys are used;
|
|
1049
|
+
- affected row count is checked;
|
|
1050
|
+
- direct DB writeback is limited to guarded single-row `UPDATE`.
|
|
1051
|
+
|
|
1052
|
+
## Safety Checks It Catches
|
|
1053
|
+
|
|
1054
|
+
After the happy path, use the demo and tests to inspect failure cases:
|
|
1055
|
+
|
|
1056
|
+
- stale-row conflict;
|
|
1057
|
+
- missing tenant context;
|
|
1058
|
+
- disallowed write column;
|
|
1059
|
+
- model-facing commit or approval tool;
|
|
1060
|
+
- arbitrary SQL tool.
|
|
1061
|
+
|
|
1062
|
+
The important stale-row case:
|
|
1063
|
+
|
|
1064
|
+
```text
|
|
1065
|
+
The row changed after the agent saw it.
|
|
1066
|
+
Result: conflict
|
|
1067
|
+
Source DB changed by Synapsor: no
|
|
1068
|
+
```
|
|
1069
|
+
|
|
1070
|
+
Conflict handling is a safety check, not the first demo payoff.
|
|
1071
|
+
|
|
1072
|
+
## Local Features
|
|
1073
|
+
|
|
1074
|
+
| Feature | Runner version |
|
|
1075
|
+
| --- | --- |
|
|
1076
|
+
| Context bindings | Trusted tenant/principal from env, static dev config, HTTP claims, or cloud session |
|
|
1077
|
+
| Capabilities | Local semantic MCP tools from `synapsor.runner.json` |
|
|
1078
|
+
| Evidence | Local evidence bundles and query audit records |
|
|
1079
|
+
| Proposals | Local before/after change sets |
|
|
1080
|
+
| Approval | Local CLI/UI approval outside MCP |
|
|
1081
|
+
| Writeback | Guarded single-row `UPDATE` for Postgres/MySQL |
|
|
1082
|
+
| Replay | Local replay of proposal, evidence, events, receipts, and query audit |
|
|
1083
|
+
| MCP audit | Static risk review for MCP database tools |
|
|
1084
|
+
|
|
1085
|
+
The runner intentionally does not include full Synapsor Cloud/DBMS features such
|
|
1086
|
+
as workflow DAGs, native branches, time travel, settlement policies, governed
|
|
1087
|
+
memory, RBAC/SSO, hosted evidence ledger, managed runners, CDC, or C++ DBMS
|
|
1088
|
+
internals.
|
|
1089
|
+
|
|
1090
|
+
## Local Runner Vs Synapsor Cloud
|
|
1091
|
+
|
|
1092
|
+
| Need | Synapsor Runner | Synapsor Cloud |
|
|
1093
|
+
| --- | --- | --- |
|
|
1094
|
+
| Local MCP server | Yes | Managed |
|
|
1095
|
+
| Local trusted context bindings | Yes | Org/session integrated |
|
|
1096
|
+
| Local semantic capabilities | Yes | Hosted registry + versioning |
|
|
1097
|
+
| Local evidence/proposal/replay | Yes | Central searchable ledger |
|
|
1098
|
+
| Local approval | CLI/UI | Multi-user approvals |
|
|
1099
|
+
| Writeback | Guarded single-row `UPDATE` | Managed production orchestration |
|
|
1100
|
+
| MCP risk audit | Static/local | Continuous/org-wide |
|
|
1101
|
+
| RBAC/SSO | No | Yes |
|
|
1102
|
+
| Policy packs | No/basic | Yes |
|
|
1103
|
+
| Workflow builder | No | Yes |
|
|
1104
|
+
| Native branches/time travel | No | Yes |
|
|
1105
|
+
| Settlement policies | No | Yes |
|
|
1106
|
+
| Compliance exports | No | Yes |
|
|
1107
|
+
| Production support/SLA | No | Yes |
|
|
1108
|
+
|
|
1109
|
+
The runner is useful by itself for local/staging safety. Synapsor Cloud is for
|
|
1110
|
+
teams, production governance, central audit, managed runners, enterprise
|
|
1111
|
+
controls, and proprietary Synapsor platform features.
|
|
1112
|
+
|
|
1113
|
+
## Current Limitations
|
|
1114
|
+
|
|
1115
|
+
Supported in the current alpha:
|
|
1116
|
+
|
|
1117
|
+
- stdio MCP server;
|
|
1118
|
+
- authenticated HTTP MCP server for app/server deployments;
|
|
1119
|
+
- Postgres/MySQL inspection;
|
|
1120
|
+
- semantic read tools;
|
|
1121
|
+
- evidence-backed proposals;
|
|
1122
|
+
- local approval outside MCP;
|
|
1123
|
+
- guarded single-row `UPDATE`;
|
|
1124
|
+
- local SQLite evidence/proposal/replay store;
|
|
1125
|
+
- tenant, primary-key, allowed-column, idempotency, and conflict guards;
|
|
1126
|
+
- static MCP risk audit.
|
|
1127
|
+
|
|
1128
|
+
Not supported:
|
|
1129
|
+
|
|
1130
|
+
- raw `execute_sql`;
|
|
1131
|
+
- model-generated SQL;
|
|
1132
|
+
- DDL;
|
|
1133
|
+
- INSERT;
|
|
1134
|
+
- DELETE;
|
|
1135
|
+
- UPSERT;
|
|
1136
|
+
- multi-row writes;
|
|
1137
|
+
- stored procedures;
|
|
1138
|
+
- physical branching of external Postgres/MySQL;
|
|
1139
|
+
- full Synapsor workflow DAG execution;
|
|
1140
|
+
- `CREATE AGENT WORKFLOW`;
|
|
1141
|
+
- Synapsor SQL generation;
|
|
1142
|
+
- auto-merge or settlement-policy semantics;
|
|
1143
|
+
- model-callable approval or commit tools;
|
|
1144
|
+
- general prompt-injection prevention;
|
|
1145
|
+
- production SLA or compliance certification.
|
|
1146
|
+
|
|
1147
|
+
Complete limits: [docs/limitations.md](docs/limitations.md).
|
|
1148
|
+
|
|
1149
|
+
Security boundary: [docs/security-boundary.md](docs/security-boundary.md).
|
|
1150
|
+
|
|
1151
|
+
Single-node production-candidate runbook:
|
|
1152
|
+
[docs/production.md](docs/production.md).
|
|
1153
|
+
|
|
1154
|
+
Release notes and stable-tag policy:
|
|
1155
|
+
[docs/release-notes.md](docs/release-notes.md).
|
|
1156
|
+
|
|
1157
|
+
## Stable Compatibility Promise
|
|
1158
|
+
|
|
1159
|
+
Starting with `0.1.0`, Synapsor Runner keeps the following surfaces compatible
|
|
1160
|
+
through the `0.1.x` line unless a release note explicitly marks a deprecation
|
|
1161
|
+
first:
|
|
1162
|
+
|
|
1163
|
+
- the `synapsor-runner` binary name and README quickstart commands;
|
|
1164
|
+
- `synapsor.runner.json` schema version `1` for documented fields;
|
|
1165
|
+
- result envelope v2 for new configs, with the documented v1 opt-out;
|
|
1166
|
+
- stdio MCP and Streamable HTTP MCP command surfaces;
|
|
1167
|
+
- generated MCP client snippets for documented clients;
|
|
1168
|
+
- proposal, approval, guarded writeback, receipt, evidence, query-audit, and
|
|
1169
|
+
replay inspection commands;
|
|
1170
|
+
- direct SQL writeback and app-owned executor contracts documented in this
|
|
1171
|
+
README and `docs/writeback-executors.md`.
|
|
1172
|
+
|
|
1173
|
+
Stable does not mean production SLA, hosted Cloud features, compliance
|
|
1174
|
+
certification, physical Postgres/MySQL branching, generic SQL writeback, or
|
|
1175
|
+
support for undocumented local SQLite internals. Those limits remain explicit
|
|
1176
|
+
in [docs/limitations.md](docs/limitations.md).
|
|
1177
|
+
|
|
1178
|
+
## License
|
|
1179
|
+
|
|
1180
|
+
Synapsor Runner is open source under the Apache License 2.0 (`Apache-2.0`).
|
|
1181
|
+
|
|
1182
|
+
Apache-2.0 applies to this runner repo. It does not grant rights to the
|
|
1183
|
+
Synapsor name, logo, hosted cloud service, or proprietary Synapsor platform
|
|
1184
|
+
features. See [docs/licensing.md](docs/licensing.md) and
|
|
1185
|
+
[TRADEMARKS.md](TRADEMARKS.md).
|
|
1186
|
+
|
|
1187
|
+
Synapsor Cloud, hosted governance, managed runners, advanced policy/workflow
|
|
1188
|
+
engines, enterprise controls, and native Synapsor DBMS/C++ internals remain
|
|
1189
|
+
proprietary.
|
|
1190
|
+
|
|
1191
|
+
## Developer And Contributor Commands
|
|
1192
|
+
|
|
1193
|
+
Public docs use `synapsor-runner`. During source-checkout development, if the
|
|
1194
|
+
global binary is not linked yet, use `./bin/synapsor-runner ...` or
|
|
1195
|
+
`corepack pnpm runner ...`.
|
|
1196
|
+
|
|
1197
|
+
Helper scripts are wrappers and development conveniences, not the main product
|
|
1198
|
+
interface:
|
|
1199
|
+
|
|
1200
|
+
```bash
|
|
1201
|
+
./scripts/try-synapsor.sh
|
|
1202
|
+
./scripts/demo-docker.sh
|
|
1203
|
+
./scripts/open-demo-ui.sh
|
|
1204
|
+
./scripts/use-your-db.sh
|
|
1205
|
+
./scripts/mcp-config.sh
|
|
1206
|
+
```
|
|
1207
|
+
|
|
1208
|
+
Contributor checks:
|
|
1209
|
+
|
|
1210
|
+
```bash
|
|
1211
|
+
corepack pnpm install
|
|
1212
|
+
./scripts/verify-release-gate.sh
|
|
1213
|
+
```
|
|
1214
|
+
|
|
1215
|
+
After a manual alpha publish, verify the public npm package:
|
|
1216
|
+
|
|
1217
|
+
```bash
|
|
1218
|
+
VERIFY_PUBLISHED_ALPHA=1 ./scripts/verify-release-gate.sh 0.1.0-alpha.17
|
|
1219
|
+
```
|
|
1220
|
+
|
|
1221
|
+
After a manual stable publish/promotion, verify `latest`:
|
|
1222
|
+
|
|
1223
|
+
```bash
|
|
1224
|
+
./scripts/verify-published-stable.sh 0.1.0
|
|
1225
|
+
```
|
|
1226
|
+
|
|
1227
|
+
## Repository Map
|
|
730
1228
|
|
|
731
|
-
|
|
732
|
-
|
|
1229
|
+
- `apps/runner`: CLI entrypoint and local UI.
|
|
1230
|
+
- `packages/mcp-server`: stdio/HTTP MCP server and configured tool runtime.
|
|
1231
|
+
- `packages/schema-inspector`: Postgres/MySQL metadata inspection and config generation.
|
|
1232
|
+
- `packages/proposal-store`: local SQLite evidence/proposal/replay store.
|
|
1233
|
+
- `packages/postgres`, `packages/mysql`: guarded writeback adapters.
|
|
1234
|
+
- `packages/worker-core`: shared runner orchestration.
|
|
1235
|
+
- `recipes`: optional starter contracts.
|
|
1236
|
+
- `examples`: disposable local demos and reference app.
|
|
1237
|
+
- `docs`: focused setup, MCP, security, troubleshooting, and limitation docs.
|
|
733
1238
|
|
|
734
|
-
##
|
|
1239
|
+
## Community
|
|
735
1240
|
|
|
736
|
-
|
|
737
|
-
Synapsor DBMS, not a physical branch engine for Postgres/MySQL, and not a
|
|
738
|
-
general MCP security platform.
|
|
1241
|
+
Synapsor Runner is maintained by Synapsor.
|
|
739
1242
|
|
|
740
|
-
|
|
741
|
-
|
|
1243
|
+
- Website: https://synapsor.ai
|
|
1244
|
+
- Docs: https://synapsor.ai/docs
|
|
1245
|
+
- License: Apache License 2.0 (`Apache-2.0`)
|
|
1246
|
+
- Issues: use GitHub Issues
|