@synapsor/runner 0.1.0-alpha.1 → 0.1.0-alpha.11
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/README.md +426 -19
- package/TRADEMARKS.md +23 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +20 -8723
- package/dist/runner.mjs +12958 -0
- package/docs/README.md +53 -0
- package/docs/app-owned-executors.md +21 -0
- package/docs/cloud-mode.md +24 -0
- package/docs/current-scope.md +24 -0
- package/docs/dependency-license-inventory.md +35 -0
- package/docs/getting-started-own-database.md +460 -0
- package/docs/http-mcp.md +276 -0
- package/docs/licensing.md +36 -0
- package/docs/limitations.md +95 -0
- package/docs/local-mode.md +351 -0
- package/docs/mcp-audit.md +152 -0
- package/docs/mcp-client-setup.md +270 -0
- package/docs/openai-agents-sdk.md +57 -0
- package/docs/recipes.md +61 -0
- package/docs/release-notes.md +158 -0
- package/docs/security-boundary.md +94 -0
- package/docs/troubleshooting-first-run.md +248 -0
- package/docs/use-your-own-database.md +18 -0
- package/docs/writeback-executors.md +220 -0
- package/examples/app-owned-writeback/README.md +120 -0
- package/examples/app-owned-writeback/business-actions.md +221 -0
- package/examples/app-owned-writeback/command-handler.mjs +46 -0
- package/examples/app-owned-writeback/node-fastify-handler.mjs +55 -0
- package/examples/app-owned-writeback/python-fastapi-handler.py +57 -0
- package/examples/dangerous-mcp-tools.json +88 -0
- package/examples/mcp-postgres-billing-app-handler/README.md +82 -0
- package/examples/mcp-postgres-billing-app-handler/app-handler.mjs +197 -0
- package/examples/mcp-postgres-billing-app-handler/docker-compose.yml +13 -0
- package/examples/mcp-postgres-billing-app-handler/schema.sql +59 -0
- package/examples/mcp-postgres-billing-app-handler/scripts/run-demo.sh +99 -0
- package/examples/mcp-postgres-billing-app-handler/seed.sql +39 -0
- package/examples/mcp-postgres-billing-app-handler/synapsor.runner.json +157 -0
- package/examples/openai-agents-http/README.md +64 -0
- package/examples/openai-agents-http/agent.py +54 -0
- package/examples/openai-agents-http/requirements.txt +1 -0
- package/examples/openai-agents-stdio/README.md +66 -0
- package/examples/openai-agents-stdio/agent.py +72 -0
- package/examples/openai-agents-stdio/requirements.txt +1 -0
- package/examples/reference-support-billing-app/README.md +137 -0
- package/examples/reference-support-billing-app/docker-compose.yml +13 -0
- package/examples/reference-support-billing-app/mcp-client.generic.json +11 -0
- package/examples/reference-support-billing-app/schema.sql +68 -0
- package/examples/reference-support-billing-app/scripts/run-demo.sh +7 -0
- package/examples/reference-support-billing-app/seed.sql +33 -0
- package/examples/reference-support-billing-app/synapsor.runner.json +241 -0
- package/fixtures/benchmark/mcp-efficiency.json +53 -0
- package/fixtures/benchmark/mcp-efficiency.txt +25 -0
- package/fixtures/protocol/MANIFEST.json +54 -0
- package/fixtures/protocol/change-set.late-fee-waiver.v1.json +72 -0
- package/fixtures/protocol/execution-receipt.applied.v1.json +14 -0
- package/fixtures/protocol/execution-receipt.conflict.v1.json +15 -0
- package/fixtures/protocol/runner-registration.v1.json +22 -0
- package/fixtures/protocol/writeback-job.late-fee-waiver.v1.json +44 -0
- package/package.json +14 -4
- package/recipes/accounts.trial_extension.json +42 -0
- package/recipes/billing.late_fee_waiver.json +46 -0
- package/recipes/credits.account_credit.json +45 -0
- package/recipes/orders.refund_review.json +57 -0
- package/recipes/support.ticket_resolution.json +51 -0
- package/dist/bin.cjs +0 -13
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
# Local mode
|
|
2
|
+
|
|
3
|
+
Local mode runs Synapsor Runner inside the developer or customer environment. No Synapsor Cloud account is required for local review flows.
|
|
4
|
+
|
|
5
|
+
Command model:
|
|
6
|
+
|
|
7
|
+
- `./scripts/demo-docker.sh` runs the no-install Docker demo.
|
|
8
|
+
- `synapsor <command>` is the public CLI surface.
|
|
9
|
+
- From a source checkout, use `./bin/synapsor-runner <command>` if the global binary is
|
|
10
|
+
not linked yet.
|
|
11
|
+
|
|
12
|
+
`synapsor-runner demo --quick` creates a fixture ledger for learning and CLI
|
|
13
|
+
verification. In a terminal it walks through the safety model step by step; in
|
|
14
|
+
CI or piped output it prints a short summary and exits without waiting for
|
|
15
|
+
Enter. It does not read or write external Postgres/MySQL. Local mode with
|
|
16
|
+
`synapsor-runner mcp serve`, `synapsor-runner demo`, or an own generated config is the real
|
|
17
|
+
Postgres/MySQL path. Use `synapsor-runner demo inspect` to print the follow-up
|
|
18
|
+
commands for the quick-demo fixture.
|
|
19
|
+
|
|
20
|
+
Current local-mode foundation:
|
|
21
|
+
|
|
22
|
+
- strict JSON capability config validation in `packages/config`;
|
|
23
|
+
- local SQLite proposal/event/evidence/query-audit/writeback/replay store in `packages/proposal-store`;
|
|
24
|
+
- local proposal review CLI in `apps/runner`;
|
|
25
|
+
- local localhost proposal review UI through `synapsor-runner ui`;
|
|
26
|
+
- static MCP database risk review with `synapsor-runner audit`;
|
|
27
|
+
- local stdio MCP server with semantic read/proposal tools;
|
|
28
|
+
- authenticated HTTP MCP server for app/server agents;
|
|
29
|
+
- MCP resource reads for `synapsor://proposals/*`, `synapsor://evidence/*`, and `synapsor://replay/*`;
|
|
30
|
+
- local approved proposal to `synapsor.writeback-job.v1` job generation;
|
|
31
|
+
- guarded Postgres/MySQL writeback adapters for approved structured jobs.
|
|
32
|
+
|
|
33
|
+
Still pending:
|
|
34
|
+
|
|
35
|
+
The alpha package requires Node >= 22.5.0 because the local evidence/replay
|
|
36
|
+
ledger uses Node's `node:sqlite` runtime. The published package declares that
|
|
37
|
+
engine requirement and the CLI exits early with a clear message on older Node
|
|
38
|
+
versions. The Docker-backed demo remains the recommended path when you do not
|
|
39
|
+
want to change your host Node version.
|
|
40
|
+
|
|
41
|
+
## Initialize a config
|
|
42
|
+
|
|
43
|
+
Create a starter config without putting credentials in the file:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner init --engine postgres --mode review
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
For MySQL:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner init --engine mysql --mode review --output synapsor.mysql.runner.json
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The generated config uses environment-variable names for read/write URLs and trusted context. Edit the table, column, and capability names before serving tools.
|
|
56
|
+
|
|
57
|
+
Do not include credential-bearing columns in reviewed visible fields or
|
|
58
|
+
evidence. The local store rejects obvious database URLs, bearer tokens, runner
|
|
59
|
+
tokens, private-key blocks, and secret-like field names before they can be
|
|
60
|
+
persisted into proposals, evidence, query audit, runner state, or replay.
|
|
61
|
+
|
|
62
|
+
For a reviewed own-database setup generated from explicit selections, use:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner init --spec onboarding-selection.json --non-interactive
|
|
66
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner doctor --config synapsor.runner.json
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`doctor --config` checks config validation, required environment variables,
|
|
70
|
+
read/write credential separation, metadata visibility for configured targets,
|
|
71
|
+
and the semantic MCP tool boundary without printing credential values.
|
|
72
|
+
|
|
73
|
+
## Stdio Vs HTTP MCP
|
|
74
|
+
|
|
75
|
+
Use stdio for local MCP clients that launch Synapsor Runner:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner mcp serve \
|
|
79
|
+
--config ./synapsor.runner.json \
|
|
80
|
+
--store ./.synapsor/local.db
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Use Streamable HTTP when your app/server agent connects through a standard HTTP
|
|
84
|
+
MCP client:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
export SYNAPSOR_RUNNER_HTTP_TOKEN="dev-local-token"
|
|
88
|
+
|
|
89
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner mcp serve-streamable-http \
|
|
90
|
+
--config ./synapsor.runner.json \
|
|
91
|
+
--store ./.synapsor/local.db \
|
|
92
|
+
--auth-token-env SYNAPSOR_RUNNER_HTTP_TOKEN
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Streamable HTTP defaults to `127.0.0.1:8766`, requires bearer auth by default,
|
|
96
|
+
and should run behind private networking/TLS before production-like exposure.
|
|
97
|
+
Use `synapsor-runner mcp serve-http` only when you explicitly want the smaller
|
|
98
|
+
JSON-RPC bridge. Details: [HTTP MCP](http-mcp.md).
|
|
99
|
+
|
|
100
|
+
## Local safety modes
|
|
101
|
+
|
|
102
|
+
The local runner modes are intentionally narrow:
|
|
103
|
+
|
|
104
|
+
- `read_only`: exposes read tools only; proposal tools fail closed.
|
|
105
|
+
- `shadow`: lets proposal tools create local proposals, evidence, query audit, and replay records, but approval and writeback-job creation are disabled.
|
|
106
|
+
- `review`: lets proposal tools create local proposals, then a human/operator can approve and create a guarded writeback job.
|
|
107
|
+
- `cloud`: delegates reviewed tools to Synapsor Cloud through a runner token.
|
|
108
|
+
|
|
109
|
+
Use `shadow` when you want to test the shape of proposals without any path to mutate the source database. Use `review` only when you are ready to exercise the trusted writeback worker.
|
|
110
|
+
|
|
111
|
+
## Store path
|
|
112
|
+
|
|
113
|
+
Commands use `--store` or `SYNAPSOR_LOCAL_STORE`.
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
export SYNAPSOR_LOCAL_STORE="./.synapsor/local.db"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
If neither is set, the CLI uses:
|
|
120
|
+
|
|
121
|
+
```text
|
|
122
|
+
./.synapsor/local.db
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Proposal review
|
|
126
|
+
|
|
127
|
+
List proposals:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner proposals list --store ./.synapsor/local.db
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Show a proposal:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner proposals show wrp_123 --store ./.synapsor/local.db
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Approve:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner proposals approve wrp_123 \
|
|
143
|
+
--store ./.synapsor/local.db \
|
|
144
|
+
--actor local_reviewer \
|
|
145
|
+
--yes
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Before approval, the CLI prints the reviewer-critical proposal details: trusted principal, tenant, target row, primary key, required role, proposal hash/version, allowed columns, conflict guard, evidence bundle/query fingerprint, writeback boundary, source mutation state, and exact before/after diff. Interactive approval still requires typing `yes`; noninteractive scripts must pass `--yes`.
|
|
149
|
+
|
|
150
|
+
Create a guarded writeback job from an approved proposal:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner proposals writeback-job wrp_123 \
|
|
154
|
+
--store ./.synapsor/local.db \
|
|
155
|
+
--project local \
|
|
156
|
+
--runner local_runner \
|
|
157
|
+
--output job.json
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
The generated job uses the public `synapsor.writeback-job.v1` protocol and can be applied by the guarded worker:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
export SYNAPSOR_DATABASE_WRITE_URL="postgresql://writer:<password>@localhost:5432/app"
|
|
164
|
+
SYNAPSOR_ENGINE=postgres \
|
|
165
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner apply --job job.json --config synapsor.runner.json --store ./.synapsor/local.db
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
When `--config` is passed, direct SQL writeback reads the writer connection from
|
|
169
|
+
the source `write_url_env` in that config. `SYNAPSOR_DATABASE_URL` is only a
|
|
170
|
+
legacy fallback for direct worker flows without a local runner config.
|
|
171
|
+
|
|
172
|
+
Passing `--store` records the terminal `synapsor.execution-receipt.v1` locally. Replay then links the proposal, approval, writeback job, applied/conflict/failed receipt, evidence, and query audit.
|
|
173
|
+
|
|
174
|
+
Reject:
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner proposals reject wrp_123 \
|
|
178
|
+
--store ./.synapsor/local.db \
|
|
179
|
+
--reason "policy evidence is incomplete" \
|
|
180
|
+
--yes
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
`approve` and `reject` require either interactive confirmation or explicit `--yes`.
|
|
184
|
+
|
|
185
|
+
Approval records the approver against the exact proposal hash/version. The proposal patch is immutable after creation.
|
|
186
|
+
|
|
187
|
+
Shadow-mode proposals are inspectable through `proposals show` and `replay show`, but `proposals approve` and `proposals writeback-job` reject them. Shadow mode never mutates Postgres/MySQL.
|
|
188
|
+
|
|
189
|
+
## Browser review UI
|
|
190
|
+
|
|
191
|
+
Start a localhost-only review UI:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner ui --config synapsor.runner.json --store ./.synapsor/local.db
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
The UI shows setup summary, semantic tools, proposal states, exact diffs,
|
|
198
|
+
evidence, approval state, receipts, and replay. It binds to `127.0.0.1` by
|
|
199
|
+
default, uses a per-run local session token, and requires CSRF protection for
|
|
200
|
+
approve/reject actions.
|
|
201
|
+
|
|
202
|
+
The UI does not expose raw SQL, database URLs, password values, MCP approval
|
|
203
|
+
tools, MCP commit tools, or controls that widen configured tables/columns.
|
|
204
|
+
|
|
205
|
+
## Replay
|
|
206
|
+
|
|
207
|
+
Show replay:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner replay show wrp_123 --store ./.synapsor/local.db
|
|
211
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner replay show --proposal wrp_123 --store ./.synapsor/local.db
|
|
212
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner replay show --replay replay_wrp_123 --store ./.synapsor/local.db
|
|
213
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner replay show --evidence ev_123 --store ./.synapsor/local.db
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Export replay:
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner replay export wrp_123 \
|
|
220
|
+
--store ./.synapsor/local.db \
|
|
221
|
+
--output replay.json
|
|
222
|
+
|
|
223
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner replay export --proposal wrp_123 \
|
|
224
|
+
--format markdown \
|
|
225
|
+
--store ./.synapsor/local.db \
|
|
226
|
+
--output replay.md
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Replay records include proposal metadata, before/after diff, events, writeback receipts, evidence summaries, and query audit rows currently stored for the proposal.
|
|
230
|
+
Human output is concise by default. Use `--details` for reviewer metadata or
|
|
231
|
+
`--json` for complete machine-readable records.
|
|
232
|
+
|
|
233
|
+
## Local evidence, query audit, and receipts
|
|
234
|
+
|
|
235
|
+
The local SQLite store is also searchable without relying on `latest`:
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
synapsor-runner activity search \
|
|
239
|
+
--tenant acme \
|
|
240
|
+
--object invoice:INV-3001 \
|
|
241
|
+
--store ./.synapsor/local.db
|
|
242
|
+
|
|
243
|
+
synapsor-runner evidence list \
|
|
244
|
+
--tenant acme \
|
|
245
|
+
--capability billing.inspect_invoice \
|
|
246
|
+
--source app_postgres \
|
|
247
|
+
--table invoices \
|
|
248
|
+
--store ./.synapsor/local.db
|
|
249
|
+
|
|
250
|
+
synapsor-runner evidence show ev_123 --store ./.synapsor/local.db
|
|
251
|
+
synapsor-runner query-audit list --evidence ev_123 --store ./.synapsor/local.db
|
|
252
|
+
synapsor-runner receipts list --proposal wrp_123 --store ./.synapsor/local.db
|
|
253
|
+
synapsor-runner receipts show <receipt_id> --store ./.synapsor/local.db
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Default inspection output is intentionally short. Add `--details` when you need
|
|
257
|
+
target URIs, primary keys, proposal hash/version, conflict guards, query
|
|
258
|
+
fingerprints, event timestamps, or receipt internals.
|
|
259
|
+
|
|
260
|
+
Read-only MCP tools record evidence bundles and query-audit rows and return an
|
|
261
|
+
evidence handle. Use `evidence show`, `evidence list`, and `query-audit list`
|
|
262
|
+
to inspect those captured rows and fingerprints later without rerunning the
|
|
263
|
+
external database read.
|
|
264
|
+
|
|
265
|
+
This is local indexed search over the runner's SQLite ledger. It is not
|
|
266
|
+
external Postgres/MySQL time travel, not native branching, and not a hosted
|
|
267
|
+
cross-runner audit ledger.
|
|
268
|
+
|
|
269
|
+
## Local store maintenance
|
|
270
|
+
|
|
271
|
+
The local ledger is a developer/staging SQLite file. You can inspect, compact,
|
|
272
|
+
or prune it without touching your source Postgres/MySQL database:
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
synapsor-runner store stats --store ./.synapsor/local.db
|
|
276
|
+
synapsor-runner store vacuum --store ./.synapsor/local.db
|
|
277
|
+
synapsor-runner store prune --store ./.synapsor/local.db --older-than 30d --dry-run
|
|
278
|
+
synapsor-runner store prune --store ./.synapsor/local.db --older-than 30d --yes
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
`store prune` defaults to dry-run. Use `--yes` only after reviewing the row
|
|
282
|
+
counts it will remove.
|
|
283
|
+
|
|
284
|
+
## Boundary
|
|
285
|
+
|
|
286
|
+
Local mode does not expose `approve_proposal` or `commit_proposal` as model-callable MCP tools. The intended flow is:
|
|
287
|
+
|
|
288
|
+
```text
|
|
289
|
+
MCP tool call
|
|
290
|
+
-> reviewed semantic proposal
|
|
291
|
+
-> local store
|
|
292
|
+
-> human/operator approval outside the model
|
|
293
|
+
-> guarded worker writeback
|
|
294
|
+
-> terminal receipt
|
|
295
|
+
-> replay
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
The external Postgres/MySQL database is not physically branched. It remains unchanged until a trusted runner applies an approved writeback job.
|
|
299
|
+
|
|
300
|
+
## Local MCP smoke
|
|
301
|
+
|
|
302
|
+
The repository includes a one-command Docker-only local demo:
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
./scripts/demo-docker.sh
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
This path requires Docker only. It builds the runner image locally, starts disposable Postgres/MySQL fixtures, runs the stdio MCP proof, and tears down the disposable resources. No Synapsor Cloud account, API key, hosted workspace, or host Node/Corepack setup is required.
|
|
309
|
+
|
|
310
|
+
If you already have Node/Corepack installed for contributor work, the direct wrapper is also available:
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
./scripts/demo-local.sh
|
|
314
|
+
corepack pnpm demo:local
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
The Docker-only script is also available through pnpm after dependencies are installed:
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
corepack pnpm demo:docker
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
The contributor script checks Docker/Corepack, installs dependencies if needed, starts disposable Postgres/MySQL containers, and runs the stdio MCP proof flow.
|
|
324
|
+
|
|
325
|
+
For CI or direct verification, use:
|
|
326
|
+
|
|
327
|
+
```bash
|
|
328
|
+
corepack pnpm test:mcp-local
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
It launches the official MCP stdio client transport against `synapsor-runner mcp serve`, exercises the Postgres billing, Postgres support, and MySQL orders examples, checks that source rows are unchanged before approval, approves locally, generates versioned writeback jobs, applies them, retries idempotently, and then proves stale-row conflict:
|
|
332
|
+
|
|
333
|
+
```text
|
|
334
|
+
The business state changed after the agent saw it, so Synapsor refused to commit.
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
## Optional MCP client configs
|
|
338
|
+
|
|
339
|
+
After the Docker demo passes, developers who want to attach an MCP client can use the checked-in stdio config shapes in:
|
|
340
|
+
|
|
341
|
+
```text
|
|
342
|
+
examples/mcp-client-configs/
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
Verify those config files without launching any client UI:
|
|
346
|
+
|
|
347
|
+
```bash
|
|
348
|
+
corepack pnpm test:mcp-client-configs
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
That command starts the runner through each config shape, calls MCP `tools/list`, and verifies that the server exposes semantic tools such as `billing.inspect_invoice` and `billing.propose_late_fee_waiver` without exposing raw SQL, approval, or commit tools. It verifies the stdio contract and config shape; it does not claim that a specific client application's UI was manually tested.
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# MCP database risk review
|
|
2
|
+
|
|
3
|
+
`npx -y -p @synapsor/runner@alpha synapsor-runner audit <target>` performs a
|
|
4
|
+
static MCP database risk review over an exported tool manifest, a remote MCP
|
|
5
|
+
`tools/list` endpoint, or a stdio MCP server. The `mcp audit` subcommand is also
|
|
6
|
+
available for users who look for the command under the MCP namespace.
|
|
7
|
+
|
|
8
|
+
From a source checkout, use `./bin/synapsor-runner ...` if the global binary is not
|
|
9
|
+
linked yet.
|
|
10
|
+
|
|
11
|
+
It does not call business tools. It only inspects names, descriptions, input schemas, output schemas, annotations, and examples when those are present.
|
|
12
|
+
|
|
13
|
+
Every report includes this disclaimer:
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
This is a static risk review, not proof that an MCP server is secure.
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
MCP annotations are treated as hints, not enforcement.
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
Built-in database MCP risk example:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner audit --example dangerous-db-mcp
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
This bundled example does not require a source checkout or local examples file.
|
|
30
|
+
It audits a deliberately risky database MCP shape with `execute_sql`,
|
|
31
|
+
`run_query`, model-callable approval/update/delete tools, arbitrary
|
|
32
|
+
table/column inputs, and model-controlled tenant/principal fields.
|
|
33
|
+
|
|
34
|
+
Human-readable output:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner audit ./tools-list.json
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Remote `tools/list` endpoint with a bearer token kept in the environment:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
SYNAPSOR_MCP_AUDIT_BEARER="..." \
|
|
44
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner audit https://mcp.example.com --format json
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Remote endpoint with a custom bearer-token environment variable:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner audit https://mcp.example.com --bearer-env MCP_AUDIT_TOKEN --format json
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Stdio MCP server:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner audit 'stdio:node ./server.mjs' --timeout-ms 5000
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
JSON output:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner audit ./tools-list.json --format json
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Markdown output for issues, PRs, or security review notes:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner audit --example dangerous-db-mcp --format markdown
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
During local development, the repo-local wrapper can run the same command:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
./bin/synapsor-runner audit ./tools-list.json
|
|
75
|
+
./bin/synapsor-runner audit ./tools-list.json --format json
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Supported inputs
|
|
79
|
+
|
|
80
|
+
The audit accepts common exported shapes:
|
|
81
|
+
|
|
82
|
+
```json
|
|
83
|
+
{ "tools": [] }
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{ "result": { "tools": [] } }
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
```json
|
|
91
|
+
{ "data": { "tools": [] } }
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
It also scans nested `adapter`, `mcpServers`, and `servers` blocks when they include tool metadata.
|
|
95
|
+
|
|
96
|
+
For live targets, the audit calls only JSON-RPC `tools/list`. It does not call business tools, approval tools, commit tools, or writeback tools.
|
|
97
|
+
|
|
98
|
+
## Findings
|
|
99
|
+
|
|
100
|
+
The audit flags database-commit risks such as:
|
|
101
|
+
|
|
102
|
+
- generic `execute_sql`, `run_query`, or raw SQL tools;
|
|
103
|
+
- tools accepting arbitrary SQL, schema, table, or column identifiers;
|
|
104
|
+
- tools accepting `tenant_id`, `principal`, source ids, allowed columns, row versions, or approval identity as model input;
|
|
105
|
+
- model-callable approval, commit, apply, settle, merge, or writeback tools;
|
|
106
|
+
- write-like tools with no visible proposal, approval, or guarded-writeback boundary;
|
|
107
|
+
- missing structured output schemas;
|
|
108
|
+
- missing idempotency/request-key metadata for direct write-like tools;
|
|
109
|
+
- missing row-version/conflict-guard metadata for direct write-like tools;
|
|
110
|
+
- ambiguous read/write tool boundaries;
|
|
111
|
+
- missing business descriptions, annotations, or fixture examples.
|
|
112
|
+
|
|
113
|
+
## Recommended target shape
|
|
114
|
+
|
|
115
|
+
A safer model-facing database MCP tool should look like a reviewed semantic proposal capability:
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
{
|
|
119
|
+
"name": "billing.propose_late_fee_waiver",
|
|
120
|
+
"description": "Create an evidence-backed proposal for support lead approval before trusted writeback.",
|
|
121
|
+
"inputSchema": {
|
|
122
|
+
"type": "object",
|
|
123
|
+
"properties": {
|
|
124
|
+
"invoice_id": { "type": "string" },
|
|
125
|
+
"reason": { "type": "string" }
|
|
126
|
+
},
|
|
127
|
+
"required": ["invoice_id", "reason"]
|
|
128
|
+
},
|
|
129
|
+
"outputSchema": {
|
|
130
|
+
"type": "object",
|
|
131
|
+
"properties": {
|
|
132
|
+
"status": { "type": "string" },
|
|
133
|
+
"proposal_id": { "type": "string" },
|
|
134
|
+
"evidence_bundle_id": { "type": "string" },
|
|
135
|
+
"source_database_changed": { "type": "boolean" }
|
|
136
|
+
},
|
|
137
|
+
"required": ["status", "proposal_id", "source_database_changed"]
|
|
138
|
+
},
|
|
139
|
+
"annotations": {
|
|
140
|
+
"readOnlyHint": false,
|
|
141
|
+
"destructiveHint": false
|
|
142
|
+
},
|
|
143
|
+
"examples": [
|
|
144
|
+
{
|
|
145
|
+
"invoice_id": "INV-3001",
|
|
146
|
+
"reason": "customer requested review"
|
|
147
|
+
}
|
|
148
|
+
]
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Trusted values such as tenant, principal, source, allowed columns, approval identity, row-version guard, and database credentials must come from Synapsor/runner context, not from model-facing arguments.
|