@synapsor/runner 0.1.0-alpha.9 → 0.1.1

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