@synapsor/runner 0.1.10 → 0.1.12

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 (26) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.md +49 -25
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/runner.mjs +275 -20
  5. package/docs/README.md +6 -0
  6. package/docs/cloud-mode.md +18 -0
  7. package/docs/cloud-push.md +54 -0
  8. package/docs/current-scope.md +1 -1
  9. package/docs/mcp-clients.md +123 -0
  10. package/docs/release-notes.md +41 -0
  11. package/docs/runner-bundles.md +59 -0
  12. package/examples/support-plan-credit/.env.example +10 -0
  13. package/examples/support-plan-credit/README.md +107 -10
  14. package/examples/support-plan-credit/expected-output/cloud-push-response.json +9 -0
  15. package/examples/support-plan-credit/expected-output/proposal-created.json +23 -0
  16. package/examples/support-plan-credit/expected-output/receipt.json +13 -0
  17. package/examples/support-plan-credit/expected-output/replay-summary.json +13 -0
  18. package/examples/support-plan-credit/expected-output/tools-preview.txt +15 -0
  19. package/examples/support-plan-credit/mcp-client-examples/claude-desktop.json +20 -0
  20. package/examples/support-plan-credit/mcp-client-examples/cursor-global.mcp.json +20 -0
  21. package/examples/support-plan-credit/mcp-client-examples/cursor-project.mcp.json +20 -0
  22. package/examples/support-plan-credit/mcp-client-examples/generic-stdio.json +17 -0
  23. package/examples/support-plan-credit/mcp-client-examples/generic-streamable-http.json +5 -0
  24. package/examples/support-plan-credit/mcp-client-examples/openai-agents-stdio.ts +19 -0
  25. package/examples/support-plan-credit/mcp-client-examples/openai-agents-streamable-http.ts +20 -0
  26. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,41 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ### Runner Version Invocation
6
+
7
+ - Stages `@synapsor/runner@0.1.12` without changing or republishing
8
+ `@synapsor/spec@0.1.4` or `@synapsor/dsl@0.1.4`.
9
+ - Keeps `--version`, `-v`, and `version` stable when an npm/npx wrapper forwards
10
+ a duplicated `synapsor-runner` executable token.
11
+ - Reads the Runner version from bundled package metadata instead of the
12
+ invoking project's ambient `npm_package_version` value.
13
+ - Adds source-wrapper and installed-tarball checks for every supported version
14
+ form and the duplicated-token regression shape.
15
+
16
+ ## 0.1.11
17
+
18
+ ### Cloud Adoption Loop
19
+
20
+ - Publishes `@synapsor/spec@0.1.4`, `@synapsor/dsl@0.1.4`, and
21
+ `@synapsor/runner@0.1.11`.
22
+ - Adds a seven-file MCP client bundle for Claude Desktop, Cursor, OpenAI Agents
23
+ SDK, and generic stdio/Streamable HTTP clients, including OpenAI-safe tool
24
+ aliases.
25
+ - Productizes local and Cloud-generated Runner bundles with placeholder env
26
+ wiring, validation/run instructions, and no embedded credentials or rows.
27
+ - Adds a network-free adoption quickstart verifier and a real local
28
+ Runner-to-Cloud-to-ZIP-to-Runner verification path around the flagship
29
+ `support-plan-credit` contract.
30
+ - Documents the Cloud registry/version/bundle loop and avoids implying managed
31
+ runner fleets, SAML/SCIM, hosted policy enforcement, or enterprise SLA.
32
+ - Adds `SYNAPSOR_CLOUD_WORKSPACE` support and explicit Cloud push failure tests
33
+ for authorization, validation, conflict, server, and network outcomes.
34
+ - Corrects `cloud push --help` so it describes the implemented authenticated
35
+ upload path and the network-free dry-run instead of the removed pre-registry
36
+ limitation.
37
+
38
+ ## 0.1.10
39
+
5
40
  ### Policy Auto-Approval
6
41
 
7
42
  - Stages `@synapsor/spec@0.1.3`, `@synapsor/dsl@0.1.3`, and
package/README.md CHANGED
@@ -6,10 +6,11 @@
6
6
 
7
7
  Stop giving AI agents `execute_sql()`. Give them reviewed business actions.
8
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.
9
+ Synapsor Runner is an open-source, local-first MCP server that exposes reviewed semantic
10
+ capabilities over Postgres and MySQL, stages risky writes as proposals, and
11
+ keeps evidence and replay for agent actions. It sits between Claude, Cursor,
12
+ OpenAI Agents SDK, or another MCP client and your database so the model does
13
+ not receive raw SQL, write credentials, approval tools, or commit authority.
13
14
 
14
15
  ```text
15
16
  Without Synapsor:
@@ -25,9 +26,12 @@ With Synapsor Runner:
25
26
  Try the no-database quick demo:
26
27
 
27
28
  ```bash
28
- npx @synapsor/runner demo --quick
29
+ npx -y @synapsor/runner demo --quick
29
30
  ```
30
31
 
32
+ You will see semantic tools instead of raw SQL, an exact proposal rather than
33
+ an immediate write, approval/apply outside MCP, and a receipt/replay record.
34
+
31
35
  ## The Five-Line Model
32
36
 
33
37
  Your agent talks to Synapsor Runner, not directly to your database.
@@ -70,7 +74,7 @@ Run the guided quick demo first. It does not require Docker, a database, a
70
74
  config file, an MCP client, or a Synapsor Cloud account.
71
75
 
72
76
  ```bash
73
- npx @synapsor/runner demo --quick
77
+ npx -y @synapsor/runner demo --quick
74
78
  ```
75
79
 
76
80
  In a terminal, it walks through the safety model step by step. In CI, piped
@@ -82,7 +86,7 @@ It does not prove database connectivity. It shows the proposal, evidence, and
82
86
  replay flow without giving the runner a database URL.
83
87
 
84
88
  ```bash
85
- npx @synapsor/runner demo inspect
89
+ npx -y @synapsor/runner demo inspect
86
90
  ```
87
91
 
88
92
  Then choose one path:
@@ -129,6 +133,13 @@ are a good start. Use Runner when you need the agent-facing boundary around
129
133
  those reads, or when database-backed actions must become proposals before any
130
134
  durable write happens.
131
135
 
136
+ ## More Than A Tool Proxy
137
+
138
+ Synapsor is intentionally more than an MCP wrapper. The public packages include
139
+ a versioned contract, DSL compiler, schema validation, conformance fixtures,
140
+ Runner enforcement, proposal/evidence/replay artifacts, Cloud registry push,
141
+ and C++/Cloud round-trip verification.
142
+
132
143
  ## Connect Your Postgres Or MySQL
133
144
 
134
145
  Use a staging or disposable database first:
@@ -310,6 +321,16 @@ See [`docs/dsl-json-parity.md`](docs/dsl-json-parity.md) for the current
310
321
  field-by-field support matrix across JSON spec, DSL, runner enforcement,
311
322
  C++/Cloud compatibility, and Cloud push.
312
323
 
324
+ After a real push, open **Contract registry** in Synapsor Cloud to inspect the
325
+ immutable version, semantic capabilities, workflows, visible and kept-out
326
+ fields, policy references, warnings, and registry audit events. Downloading a
327
+ runner bundle returns the same normalized contract with placeholder local
328
+ wiring and ready-to-copy MCP configs.
329
+
330
+ - [Cloud push](docs/cloud-push.md)
331
+ - [Runner bundles](docs/runner-bundles.md)
332
+ - [MCP client configs](docs/mcp-clients.md)
333
+
313
334
  Your `synapsor.runner.json` supplies local wiring: database env var names,
314
335
  SQLite store path, MCP transport settings, and local debug options. The
315
336
  contract supplies the portable meaning: contexts, capabilities, evidence,
@@ -953,8 +974,9 @@ per lifecycle event; it is not a hosted central ledger.
953
974
 
954
975
  This is local indexed search for local/dev/staging usage. It is not a hosted
955
976
  central ledger, not RBAC/SSO, not cross-runner search, and not compliance
956
- retention. Synapsor Cloud is the upgrade path for central searchable audit,
957
- team governance, retention, and production operations.
977
+ retention. Synapsor Cloud adds a shared contract registry and enabled hosted
978
+ activity/evidence surfaces; confirm retention and production operations for
979
+ the specific design-partner deployment.
958
980
 
959
981
  ## Connect Claude, Cursor, Or Another MCP Client
960
982
 
@@ -1217,24 +1239,25 @@ internals.
1217
1239
 
1218
1240
  | Need | Synapsor Runner | Synapsor Cloud |
1219
1241
  | --- | --- | --- |
1220
- | Local MCP server | Yes | Managed |
1221
- | Local trusted context bindings | Yes | Org/session integrated |
1242
+ | Local MCP server | Yes | Contracts export back to Runner; a managed fleet is not claimed |
1243
+ | Local trusted context bindings | Yes | Contract bindings are registered; hosted session behavior is pilot-specific |
1222
1244
  | Local semantic capabilities | Yes | Hosted registry + versioning |
1223
1245
  | Local evidence/proposal/replay | Yes | Central searchable ledger |
1224
- | Local approval | CLI/UI | Multi-user approvals |
1225
- | Writeback | Guarded single-row `UPDATE` | Managed production orchestration |
1246
+ | Local approval | CLI/UI | Existing team approval surfaces where enabled for a pilot |
1247
+ | Writeback | Guarded single-row `UPDATE` | Cloud-linked jobs exist; managed production orchestration is not claimed |
1226
1248
  | MCP risk audit | Static/local | Continuous/org-wide |
1227
- | RBAC/SSO | No | Yes |
1228
- | Policy packs | No/basic | Yes |
1229
- | Workflow builder | No | Yes |
1249
+ | RBAC/SSO | No | RBAC where configured; SAML/SCIM are not in this beta |
1250
+ | Policy packs | Local reviewed subset | Registry preserves policies; hosted enforcement is not implied |
1251
+ | Workflow builder | No | Existing Cloud authoring surfaces; full public DAG parity is not claimed |
1230
1252
  | Native branches/time travel | No | Yes |
1231
1253
  | Settlement policies | No | Yes |
1232
- | Compliance exports | No | Yes |
1233
- | Production support/SLA | No | Yes |
1254
+ | Compliance exports | No | Audit/retention primitives exist; legal hold/certification are not claimed |
1255
+ | Production support/SLA | No | Design-partner support; no enterprise SLA is claimed |
1234
1256
 
1235
- The runner is useful by itself for local/staging safety. Synapsor Cloud is for
1236
- teams, production governance, central audit, managed runners, enterprise
1237
- controls, and proprietary Synapsor platform features.
1257
+ The runner is useful by itself for local/staging safety. Synapsor Cloud adds a
1258
+ shared contract registry, immutable versions, downloadable Runner bundles, and
1259
+ existing team activity/evidence/approval surfaces where enabled. Managed
1260
+ runners, SAML/SCIM, legal hold, and an enterprise SLA remain future work.
1238
1261
 
1239
1262
  Portable contracts can be checked locally before Cloud import:
1240
1263
 
@@ -1251,7 +1274,7 @@ synapsor-runner cloud push ./synapsor.contract.json \
1251
1274
 
1252
1275
  ## Current Limitations
1253
1276
 
1254
- Supported in the current alpha:
1277
+ Supported in the current `0.1.x` line:
1255
1278
 
1256
1279
  - stdio MCP server;
1257
1280
  - authenticated HTTP MCP server for app/server deployments;
@@ -1327,9 +1350,10 @@ Synapsor name, logo, hosted cloud service, or proprietary Synapsor platform
1327
1350
  features. See [docs/licensing.md](docs/licensing.md) and
1328
1351
  [TRADEMARKS.md](TRADEMARKS.md).
1329
1352
 
1330
- Synapsor Cloud, hosted governance, managed runners, advanced policy/workflow
1331
- engines, enterprise controls, and native Synapsor DBMS/C++ internals remain
1332
- proprietary.
1353
+ Synapsor Cloud, hosted governance, advanced policy/workflow engines, enterprise
1354
+ controls, and native Synapsor DBMS/C++ internals are outside this Apache-2.0
1355
+ repository. Managed runners and other hosted features, where offered, are
1356
+ proprietary and are not implied by the OSS package.
1333
1357
 
1334
1358
  ## Developer And Contributor Commands
1335
1359
 
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAYA,OAAO,EAAoP,KAAK,WAAW,EAA2F,MAAM,6BAA6B,CAAC;AAoB1Y,OAAO,EAA6G,KAAK,YAAY,EAAwB,MAAM,2BAA2B,CAAC;AAE/L,OAAO,EAOL,KAAK,gBAAgB,EAEtB,MAAM,mCAAmC,CAAC;AA6U3C,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAyD1D;AA+DD,KAAK,SAAS,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAE9E,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE;IACP,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;CACvC,GACL,OAAO,CAAC,MAAM,CAAC,CA2TjB;AA+tED,wBAAsB,0BAA0B,CAAC,GAAG,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAS/H"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAYA,OAAO,EAAoP,KAAK,WAAW,EAA2F,MAAM,6BAA6B,CAAC;AAoB1Y,OAAO,EAA6G,KAAK,YAAY,EAAwB,MAAM,2BAA2B,CAAC;AAE/L,OAAO,EAOL,KAAK,gBAAgB,EAEtB,MAAM,mCAAmC,CAAC;AAgV3C,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAyD1D;AAqED,KAAK,SAAS,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAE9E,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE;IACP,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;CACvC,GACL,OAAO,CAAC,MAAM,CAAC,CA2TjB;AAowED,wBAAsB,0BAA0B,CAAC,GAAG,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAS/H"}
package/dist/runner.mjs CHANGED
@@ -8436,6 +8436,191 @@ function stringOrDefault(value, fallback) {
8436
8436
  return typeof value === "string" && value.trim() ? value.trim() : fallback;
8437
8437
  }
8438
8438
 
8439
+ // apps/runner/package.json
8440
+ var package_default = {
8441
+ name: "@synapsor/runner",
8442
+ version: "0.1.12",
8443
+ description: "Stop giving AI agents execute_sql; expose reviewed Postgres/MySQL MCP actions with proposals, approval, writeback, and replay.",
8444
+ license: "Apache-2.0",
8445
+ type: "module",
8446
+ bin: {
8447
+ "synapsor-runner": "dist/cli.js"
8448
+ },
8449
+ files: [
8450
+ "dist/cli.js",
8451
+ "dist/cli.d.ts",
8452
+ "dist/cli.d.ts.map",
8453
+ "dist/local-ui.d.ts",
8454
+ "dist/local-ui.d.ts.map",
8455
+ "dist/runner.mjs",
8456
+ "docs/**/*.md",
8457
+ "examples/dangerous-mcp-tools.json",
8458
+ "examples/app-owned-writeback/**",
8459
+ "examples/claude-desktop-postgres/**",
8460
+ "examples/cursor-postgres/**",
8461
+ "examples/mcp-postgres-billing-app-handler/**",
8462
+ "examples/mysql-refund-agent/**",
8463
+ "examples/openai-agents-http/**",
8464
+ "examples/openai-agents-stdio/**",
8465
+ "examples/raw-sql-vs-synapsor/**",
8466
+ "examples/reference-support-billing-app/**",
8467
+ "examples/support-plan-credit/**",
8468
+ "examples/support-billing-agent/**",
8469
+ "fixtures/**",
8470
+ "schemas/**",
8471
+ "recipes/**/*.json",
8472
+ "README.md",
8473
+ "CHANGELOG.md",
8474
+ "LICENSE",
8475
+ "NOTICE",
8476
+ "TRADEMARKS.md"
8477
+ ],
8478
+ keywords: [
8479
+ "mcp",
8480
+ "postgres",
8481
+ "mysql",
8482
+ "ai-agents",
8483
+ "sql-safety",
8484
+ "database-safety",
8485
+ "openai-agents",
8486
+ "claude",
8487
+ "cursor",
8488
+ "writeback",
8489
+ "replay",
8490
+ "model-context-protocol"
8491
+ ],
8492
+ engines: {
8493
+ node: ">=22.5.0"
8494
+ },
8495
+ scripts: {
8496
+ build: "tsc -b && node ../../scripts/build-runner-package.mjs",
8497
+ prepack: "cd ../.. && corepack pnpm build:runner-package",
8498
+ test: "vitest run"
8499
+ },
8500
+ dependencies: {
8501
+ "@modelcontextprotocol/sdk": "1.29.0",
8502
+ mysql2: "^3.11.0",
8503
+ pg: "^8.13.0",
8504
+ zod: "^3.25.0"
8505
+ },
8506
+ devDependencies: {
8507
+ typescript: "^5.7.0",
8508
+ vitest: "^3.2.0"
8509
+ },
8510
+ homepage: "https://synapsor.ai",
8511
+ repository: {
8512
+ type: "git",
8513
+ url: "git+https://github.com/Synapsor/Synapsor-Runner.git"
8514
+ },
8515
+ bugs: {
8516
+ url: "https://synapsor.ai/contact"
8517
+ },
8518
+ publishConfig: {
8519
+ access: "public"
8520
+ }
8521
+ };
8522
+
8523
+ // packages/dsl/package.json
8524
+ var package_default2 = {
8525
+ name: "@synapsor/dsl",
8526
+ version: "0.1.4",
8527
+ description: "Preview SQL-like Synapsor authoring DSL compiler for canonical @synapsor/spec contracts.",
8528
+ license: "Apache-2.0",
8529
+ type: "module",
8530
+ main: "dist/index.js",
8531
+ types: "dist/index.d.ts",
8532
+ bin: {
8533
+ "synapsor-dsl": "dist/cli.js"
8534
+ },
8535
+ files: [
8536
+ "dist/**",
8537
+ "examples/**",
8538
+ "README.md",
8539
+ "package.json"
8540
+ ],
8541
+ scripts: {
8542
+ build: "tsc -b",
8543
+ test: "vitest run"
8544
+ },
8545
+ dependencies: {
8546
+ "@synapsor/spec": "workspace:^0.1.4"
8547
+ },
8548
+ devDependencies: {
8549
+ typescript: "^5.7.0",
8550
+ vitest: "^3.2.0"
8551
+ },
8552
+ keywords: [
8553
+ "synapsor",
8554
+ "dsl",
8555
+ "ai-agents",
8556
+ "mcp",
8557
+ "database-safety"
8558
+ ],
8559
+ engines: {
8560
+ node: ">=22.5.0"
8561
+ },
8562
+ publishConfig: {
8563
+ access: "public"
8564
+ },
8565
+ repository: {
8566
+ type: "git",
8567
+ url: "git+https://github.com/Synapsor/Synapsor-Runner.git",
8568
+ directory: "packages/dsl"
8569
+ },
8570
+ homepage: "https://github.com/Synapsor/Synapsor-Runner/tree/main/packages/dsl#readme",
8571
+ bugs: {
8572
+ url: "https://github.com/Synapsor/Synapsor-Runner/issues"
8573
+ }
8574
+ };
8575
+
8576
+ // packages/spec/package.json
8577
+ var package_default3 = {
8578
+ name: "@synapsor/spec",
8579
+ version: "0.1.4",
8580
+ description: "Canonical Synapsor contract schemas, types, validation, and conformance fixtures.",
8581
+ license: "Apache-2.0",
8582
+ type: "module",
8583
+ main: "dist/index.js",
8584
+ types: "dist/index.d.ts",
8585
+ bin: {
8586
+ "synapsor-spec": "dist/cli.js"
8587
+ },
8588
+ files: [
8589
+ "dist/**",
8590
+ "schemas/**",
8591
+ "examples/**",
8592
+ "fixtures/**",
8593
+ "README.md",
8594
+ "package.json"
8595
+ ],
8596
+ scripts: {
8597
+ build: "tsc -b",
8598
+ test: "vitest run"
8599
+ },
8600
+ keywords: [
8601
+ "synapsor",
8602
+ "ai-agents",
8603
+ "mcp",
8604
+ "database-safety",
8605
+ "contracts"
8606
+ ],
8607
+ engines: {
8608
+ node: ">=22.5.0"
8609
+ },
8610
+ publishConfig: {
8611
+ access: "public"
8612
+ },
8613
+ repository: {
8614
+ type: "git",
8615
+ url: "git+https://github.com/Synapsor/Synapsor-Runner.git",
8616
+ directory: "packages/spec"
8617
+ },
8618
+ homepage: "https://github.com/Synapsor/Synapsor-Runner/tree/main/packages/spec#readme",
8619
+ bugs: {
8620
+ url: "https://github.com/Synapsor/Synapsor-Runner/issues"
8621
+ }
8622
+ };
8623
+
8439
8624
  // apps/runner/src/cli.ts
8440
8625
  var adapters = { postgres: postgresAdapter, mysql: mysqlAdapter };
8441
8626
  var handlerReceiptStatuses = /* @__PURE__ */ new Set(["applied", "already_applied", "conflict", "failed"]);
@@ -8752,7 +8937,7 @@ var referenceDemoEnv = {
8752
8937
  SYNAPSOR_RUNNER_TOKEN: "syn_wbr_demo_local"
8753
8938
  };
8754
8939
  async function main(argv) {
8755
- const [command, ...rest] = argv;
8940
+ const [command, ...rest] = normalizeCliArgv(argv);
8756
8941
  if (!command || command === "--help" || command === "-h") {
8757
8942
  usage([]);
8758
8943
  return 0;
@@ -8818,6 +9003,11 @@ ${cliCommandName()} --help
8818
9003
  `);
8819
9004
  return 2;
8820
9005
  }
9006
+ function normalizeCliArgv(argv) {
9007
+ const [first, ...rest] = argv;
9008
+ if (first === "synapsor-runner" || first === "synapsor") return rest;
9009
+ return argv;
9010
+ }
8821
9011
  async function init(args) {
8822
9012
  const answersPath = optionalArg(args, "--answers");
8823
9013
  if (answersPath) {
@@ -10042,18 +10232,21 @@ async function contractBundle(args) {
10042
10232
  const firstSource = firstCapability?.source ?? "local_postgres";
10043
10233
  const engine = inferContractBundleEngine(contract);
10044
10234
  const readUrlEnv = engine === "mysql" ? "SYNAPSOR_DATABASE_READ_URL" : "SYNAPSOR_DATABASE_READ_URL";
10235
+ const hasProposals = contract.capabilities.some((capability) => capability.kind === "proposal");
10236
+ const sourceConfig = {
10237
+ engine,
10238
+ read_url_env: readUrlEnv,
10239
+ statement_timeout_ms: 3e3
10240
+ };
10241
+ if (hasProposals) sourceConfig.write_url_env = "SYNAPSOR_DATABASE_WRITE_URL";
10045
10242
  const runnerConfig = {
10046
10243
  version: 1,
10047
- mode: contract.capabilities.some((capability) => capability.kind === "proposal") ? "review" : "read_only",
10244
+ mode: hasProposals ? "review" : "read_only",
10048
10245
  result_format: 2,
10049
10246
  storage: { sqlite_path: "./.synapsor/local.db" },
10050
10247
  contracts: ["./synapsor.contract.json"],
10051
10248
  sources: {
10052
- [firstSource]: {
10053
- engine,
10054
- read_url_env: readUrlEnv,
10055
- statement_timeout_ms: 3e3
10056
- }
10249
+ [firstSource]: sourceConfig
10057
10250
  }
10058
10251
  };
10059
10252
  await fs3.mkdir(outDir, { recursive: true });
@@ -10064,11 +10257,9 @@ async function contractBundle(args) {
10064
10257
  `, "utf8");
10065
10258
  await fs3.writeFile(path3.join(outDir, ".env.example"), bundleEnvExample(contract, readUrlEnv, engine), "utf8");
10066
10259
  await fs3.writeFile(path3.join(outDir, "README.md"), bundleReadme(contract), "utf8");
10067
- await fs3.writeFile(path3.join(outDir, "mcp-client-examples", "generic-stdio.json"), `${JSON.stringify({
10068
- command: cliCommandName(),
10069
- args: ["mcp", "serve", "--config", "./synapsor.runner.json", "--store", "./.synapsor/local.db"]
10070
- }, null, 2)}
10071
- `, "utf8");
10260
+ for (const [name, content] of Object.entries(bundleMcpClientExamples())) {
10261
+ await fs3.writeFile(path3.join(outDir, "mcp-client-examples", name), content, "utf8");
10262
+ }
10072
10263
  process2.stdout.write(`created runner bundle: ${outDir}
10073
10264
  `);
10074
10265
  process2.stdout.write("No database URLs, write credentials, tokens, or customer rows were included.\n");
@@ -10087,6 +10278,7 @@ function bundleEnvExample(contract, readUrlEnv, engine) {
10087
10278
  "# Fill these locally. Do not commit real values.",
10088
10279
  `# Set ${readUrlEnv} to your read-only ${engine === "mysql" ? "MySQL" : "Postgres"} URL.`,
10089
10280
  `${readUrlEnv}=`,
10281
+ ...contract.capabilities.some((capability) => capability.kind === "proposal") ? ["# Optional: separate least-privilege write URL for guarded direct UPDATE writeback.", "SYNAPSOR_DATABASE_WRITE_URL="] : [],
10090
10282
  `${tenantBinding?.key ?? "SYNAPSOR_TENANT_ID"}=acme`,
10091
10283
  `${principalBinding?.key ?? "SYNAPSOR_PRINCIPAL"}=local_operator`,
10092
10284
  ""
@@ -10113,12 +10305,70 @@ function bundleReadme(contract) {
10113
10305
  "```bash",
10114
10306
  "cp .env.example .env",
10115
10307
  "# edit .env, then export the values in your shell",
10116
- `${cliCommandName()} contract validate ./synapsor.contract.json`,
10117
- `${cliCommandName()} mcp serve --config ./synapsor.runner.json --store ./.synapsor/local.db`,
10308
+ "set -a && . ./.env && set +a",
10309
+ "npx -y -p @synapsor/runner synapsor-runner contract validate ./synapsor.contract.json",
10310
+ "npx -y -p @synapsor/runner synapsor-runner config validate --config ./synapsor.runner.json",
10311
+ "npx -y -p @synapsor/runner synapsor-runner tools preview --config ./synapsor.runner.json --store ./.synapsor/local.db",
10312
+ "npx -y -p @synapsor/runner synapsor-runner mcp serve --config ./synapsor.runner.json --store ./.synapsor/local.db",
10313
+ "```",
10314
+ "",
10315
+ "Approval and apply remain outside the model-facing MCP catalog. Inspect local history with:",
10316
+ "",
10317
+ "```bash",
10318
+ "npx -y -p @synapsor/runner synapsor-runner replay show latest --store ./.synapsor/local.db",
10319
+ "npx -y -p @synapsor/runner synapsor-runner cloud push ./synapsor.contract.json --dry-run",
10118
10320
  "```",
10119
10321
  ""
10120
10322
  ].join("\n");
10121
10323
  }
10324
+ function bundleMcpClientExamples() {
10325
+ const packageArgs = ["-y", "-p", "@synapsor/runner", "synapsor-runner"];
10326
+ const stdioArgs = [...packageArgs, "mcp", "serve", "--config", "./synapsor.runner.json", "--store", "./.synapsor/local.db"];
10327
+ const server = { command: "npx", args: stdioArgs };
10328
+ const json = (value) => `${JSON.stringify(value, null, 2)}
10329
+ `;
10330
+ return {
10331
+ "claude-desktop.json": json({ mcpServers: { "synapsor-runner": server } }),
10332
+ "cursor-project.mcp.json": json({ mcpServers: { "synapsor-runner": { type: "stdio", ...server } } }),
10333
+ "cursor-global.mcp.json": json({
10334
+ mcpServers: {
10335
+ "synapsor-runner": {
10336
+ type: "stdio",
10337
+ command: "npx",
10338
+ args: [...packageArgs, "mcp", "serve", "--config", "<absolute-path-to-bundle>/synapsor.runner.json", "--store", "<absolute-path-to-bundle>/.synapsor/local.db"]
10339
+ }
10340
+ }
10341
+ }),
10342
+ "generic-stdio.json": json({ name: "synapsor-runner", transport: "stdio", ...server }),
10343
+ "generic-streamable-http.json": json({ name: "synapsor-runner", transport: "streamable-http", url: "http://127.0.0.1:8766/mcp" }),
10344
+ "openai-agents-stdio.ts": `import { Agent, MCPServerStdio, run } from "@openai/agents";
10345
+
10346
+ const synapsor = new MCPServerStdio({
10347
+ name: "Synapsor Runner",
10348
+ fullCommand: "npx -y -p @synapsor/runner synapsor-runner mcp serve --config ./synapsor.runner.json --store ./.synapsor/local.db --alias-mode openai",
10349
+ });
10350
+ await synapsor.connect();
10351
+ try {
10352
+ const agent = new Agent({ name: "Reviewed database agent", instructions: "Use only Synapsor business tools. Inspect evidence before proposing a change.", mcpServers: [synapsor] });
10353
+ console.log((await run(agent, "Inspect the customer and propose a safe next action.")).finalOutput);
10354
+ } finally {
10355
+ await synapsor.close();
10356
+ }
10357
+ `,
10358
+ "openai-agents-streamable-http.ts": `import { Agent, MCPServerStreamableHttp, run } from "@openai/agents";
10359
+
10360
+ // Start Runner separately with: synapsor-runner mcp serve --transport streamable-http --alias-mode openai --config ./synapsor.runner.json --store ./.synapsor/local.db
10361
+ const synapsor = new MCPServerStreamableHttp({ name: "Synapsor Runner", url: "http://127.0.0.1:8766/mcp" });
10362
+ await synapsor.connect();
10363
+ try {
10364
+ const agent = new Agent({ name: "Reviewed database agent", instructions: "Use only Synapsor business tools. Inspect evidence before proposing a change.", mcpServers: [synapsor] });
10365
+ console.log((await run(agent, "Inspect the customer and propose a safe next action.")).finalOutput);
10366
+ } finally {
10367
+ await synapsor.close();
10368
+ }
10369
+ `
10370
+ };
10371
+ }
10122
10372
  async function configValidate(args) {
10123
10373
  const configPath = optionalArg(args, "--config") ?? "synapsor.runner.json";
10124
10374
  const result = await validateConfigFile(configPath);
@@ -11949,7 +12199,7 @@ async function cloudPush(args) {
11949
12199
  if (!target2) throw new Error("cloud push requires <synapsor.contract.json>");
11950
12200
  const parsed = JSON.parse(await fs3.readFile(target2, "utf8"));
11951
12201
  const contract = normalizeContract(parsed);
11952
- const workspace = (optionalArg(args, "--workspace") ?? optionalArg(args, "--project") ?? process2.env.SYNAPSOR_WORKSPACE_ID ?? process2.env.SYNAPSOR_PROJECT_ID ?? "").trim();
12202
+ const workspace = (optionalArg(args, "--workspace") ?? optionalArg(args, "--project") ?? process2.env.SYNAPSOR_CLOUD_WORKSPACE ?? process2.env.SYNAPSOR_WORKSPACE_ID ?? process2.env.SYNAPSOR_PROJECT_ID ?? "").trim();
11953
12203
  const name = (optionalArg(args, "--name") ?? contract.metadata?.name ?? "").trim();
11954
12204
  const description = (optionalArg(args, "--description") ?? contract.metadata?.description ?? "").trim();
11955
12205
  const idempotencyKey = optionalArg(args, "--idempotency-key");
@@ -11962,7 +12212,9 @@ async function cloudPush(args) {
11962
12212
  description,
11963
12213
  source: "runner",
11964
12214
  source_versions: {
11965
- "@synapsor/runner": process2.env.npm_package_version ?? "unknown"
12215
+ "@synapsor/spec": package_default3.version,
12216
+ "@synapsor/dsl": package_default2.version,
12217
+ "@synapsor/runner": process2.env.npm_package_version ?? package_default.version
11966
12218
  },
11967
12219
  activate: args.includes("--activate"),
11968
12220
  idempotency_key: idempotencyKey,
@@ -11997,7 +12249,7 @@ async function cloudPush(args) {
11997
12249
  const apiUrl = (optionalArg(args, "--api-url") ?? process2.env.SYNAPSOR_CLOUD_BASE_URL ?? "").trim();
11998
12250
  const token = (optionalArg(args, "--token") ?? process2.env.SYNAPSOR_CLOUD_TOKEN ?? process2.env.SYNAPSOR_RUNNER_TOKEN ?? "").trim();
11999
12251
  if (!workspace) {
12000
- throw new Error("cloud push upload requires --workspace <project_id> or SYNAPSOR_WORKSPACE_ID/SYNAPSOR_PROJECT_ID.");
12252
+ throw new Error("cloud push upload requires --workspace <project_id> or SYNAPSOR_CLOUD_WORKSPACE/SYNAPSOR_WORKSPACE_ID/SYNAPSOR_PROJECT_ID.");
12001
12253
  }
12002
12254
  if (!apiUrl || !token) {
12003
12255
  throw new Error("cloud push upload requires --api-url plus --token/SYNAPSOR_CLOUD_TOKEN. Use --dry-run for local validation without a network call.");
@@ -16535,7 +16787,9 @@ function cliCommandName() {
16535
16787
  return "synapsor-runner";
16536
16788
  }
16537
16789
  async function runnerPackageVersion() {
16538
- if (process2.env.npm_package_version) return process2.env.npm_package_version;
16790
+ if (typeof package_default.version === "string" && package_default.version.trim()) {
16791
+ return package_default.version.trim();
16792
+ }
16539
16793
  const packageUrl = new URL("../package.json", import.meta.url);
16540
16794
  try {
16541
16795
  const parsed = JSON.parse(await fs3.readFile(packageUrl, "utf8"));
@@ -16622,8 +16876,9 @@ instead of being ignored.
16622
16876
  ${cmd} cloud push ./synapsor.contract.json --dry-run [--workspace <id>] [--name <registry-name>]
16623
16877
 
16624
16878
  cloud push validates and normalizes the contract locally, then prints the
16625
- payload summary. Upload is intentionally not reported as successful until a
16626
- real Cloud registry endpoint is wired.
16879
+ payload summary. With --dry-run it makes no network request. Without --dry-run
16880
+ it uploads to the authenticated Cloud registry and reports the stored contract,
16881
+ version, digest, and registry URL returned by the server.
16627
16882
  `,
16628
16883
  up: `Usage:
16629
16884
  ${cmd} up --config ./synapsor.runner.json --store ./.synapsor/local.db [--transport stdio|streamable-http]
package/docs/README.md CHANGED
@@ -49,6 +49,8 @@ then read the concepts once the safety boundary is visible.
49
49
 
50
50
  - [MCP Client Setup](mcp-client-setup.md): connect Claude, Cursor, VS Code, or
51
51
  another stdio MCP client.
52
+ - [MCP Client Configs](mcp-clients.md): complete Claude, Cursor, OpenAI Agents,
53
+ generic stdio, and Streamable HTTP templates.
52
54
  - `examples/claude-desktop-postgres/`: copy-paste Claude Desktop config for the
53
55
  Postgres billing fixture.
54
56
  - `examples/cursor-postgres/`: copy-paste Cursor config for the Postgres
@@ -96,6 +98,10 @@ then read the concepts once the safety boundary is visible.
96
98
  scope, database roles, receipt grants, local ledger backup, restart behavior,
97
99
  Docker/systemd shapes, TLS, and release-gate expectations.
98
100
  - [Cloud Mode](cloud-mode.md): what stays local and what Cloud-linked mode adds.
101
+ - [Cloud Push](cloud-push.md): register a validated local contract in the
102
+ versioned Cloud registry.
103
+ - [Runner Bundles](runner-bundles.md): download the same immutable contract and
104
+ its local MCP wiring from Cloud.
99
105
  - [Release Notes](release-notes.md): release history and behavior changes.
100
106
  - [Release Policy](release-policy.md): stable gates and publish verification.
101
107
  - [Licensing](licensing.md): Apache-2.0 scope, trademark boundary, and what is
@@ -6,6 +6,8 @@ guarded writeback, or replay.
6
6
 
7
7
  Cloud-linked mode is for teams that need a shared control plane:
8
8
 
9
+ - versioned canonical contract registry and server-computed digests;
10
+ - Cloud-to-local runner bundle downloads;
9
11
  - team approvals and RBAC;
10
12
  - hosted evidence/replay search;
11
13
  - runner registration and heartbeat;
@@ -17,6 +19,22 @@ The local runner still keeps database credentials in your environment. MCP
17
19
  client config snippets should contain command paths and runner arguments, not
18
20
  database URLs or write credentials.
19
21
 
22
+ Push and retrieve the portable contract without moving database credentials
23
+ into Cloud:
24
+
25
+ ```bash
26
+ synapsor-runner cloud push ./synapsor.contract.json --dry-run
27
+ synapsor-runner cloud push ./synapsor.contract.json \
28
+ --workspace "$SYNAPSOR_WORKSPACE_ID" \
29
+ --name support-plan-credit
30
+ ```
31
+
32
+ See [Cloud Push](cloud-push.md) and [Runner Bundles](runner-bundles.md).
33
+
34
+ Cloud registry storage preserves approval policies but does not, by itself,
35
+ mean hosted policy enforcement is enabled. Local Runner enforcement and hosted
36
+ Cloud approval enforcement are separate runtime boundaries.
37
+
20
38
  Run the local smoke for this mode with:
21
39
 
22
40
  ```bash