@synapsor/runner 0.1.0-alpha.4 → 0.1.0-alpha.6
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 +211 -43
- package/dist/cli.d.ts.map +1 -1
- package/dist/runner.mjs +912 -90
- package/docs/README.md +32 -54
- package/docs/getting-started-own-database.md +68 -36
- package/docs/http-mcp.md +200 -0
- package/docs/local-mode.md +71 -35
- package/docs/mcp-audit.md +11 -15
- package/docs/mcp-client-setup.md +48 -9
- package/docs/recipes.md +6 -6
- package/docs/security-boundary.md +1 -1
- package/docs/troubleshooting-first-run.md +6 -6
- package/docs/writeback-executors.md +1 -1
- package/examples/openai-agents-http/README.md +55 -0
- package/examples/openai-agents-http/agent.py +90 -0
- package/examples/openai-agents-http/requirements.txt +1 -0
- package/examples/openai-agents-stdio/README.md +62 -0
- package/examples/openai-agents-stdio/agent.py +70 -0
- package/examples/openai-agents-stdio/requirements.txt +1 -0
- package/examples/reference-support-billing-app/README.md +17 -17
- package/package.json +3 -2
- package/docs/MCP_RUNNER_IMPLEMENTATION_PLAN.md +0 -187
- package/docs/architecture.md +0 -65
- package/docs/capability-config.md +0 -180
- package/docs/cloud-mode.md +0 -140
- package/docs/config-migrations.md +0 -67
- package/docs/demo-transcript.md +0 -161
- package/docs/dependency-license-inventory.md +0 -35
- package/docs/first-10-minutes.md +0 -172
- package/docs/licensing.md +0 -38
- package/docs/local-ui.md +0 -163
- package/docs/mcp-efficiency-benchmark.md +0 -84
- package/docs/open-source-feature-inventory.md +0 -254
- package/docs/operations.md +0 -38
- package/docs/own-db-20-minutes.md +0 -185
- package/docs/production-readiness.md +0 -39
- package/docs/protocol.md +0 -90
- package/docs/roadmap.md +0 -13
- package/docs/schema-inspection.md +0 -88
- package/docs/shadow-mode.md +0 -67
- package/docs/telemetry.md +0 -28
- package/docs/threat-model.md +0 -25
- package/docs/trusted-context.md +0 -70
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import json
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
import urllib.error
|
|
6
|
+
import urllib.request
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
from agents import Agent, Runner, function_tool
|
|
10
|
+
except ImportError as exc:
|
|
11
|
+
raise SystemExit(
|
|
12
|
+
"This example requires the OpenAI Agents SDK. "
|
|
13
|
+
"Install with: pip install -r requirements.txt"
|
|
14
|
+
) from exc
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def call_synapsor_http_mcp(method: str, params: dict) -> dict:
|
|
18
|
+
url = os.environ.get("SYNAPSOR_RUNNER_HTTP_URL", "http://127.0.0.1:8765/mcp")
|
|
19
|
+
token = os.environ.get("SYNAPSOR_RUNNER_HTTP_TOKEN")
|
|
20
|
+
if not token:
|
|
21
|
+
raise RuntimeError("SYNAPSOR_RUNNER_HTTP_TOKEN is not set")
|
|
22
|
+
|
|
23
|
+
payload = json.dumps({
|
|
24
|
+
"jsonrpc": "2.0",
|
|
25
|
+
"id": 1,
|
|
26
|
+
"method": method,
|
|
27
|
+
"params": params,
|
|
28
|
+
}).encode("utf-8")
|
|
29
|
+
request = urllib.request.Request(
|
|
30
|
+
url,
|
|
31
|
+
data=payload,
|
|
32
|
+
method="POST",
|
|
33
|
+
headers={
|
|
34
|
+
"authorization": f"Bearer {token}",
|
|
35
|
+
"content-type": "application/json",
|
|
36
|
+
},
|
|
37
|
+
)
|
|
38
|
+
try:
|
|
39
|
+
with urllib.request.urlopen(request, timeout=15) as response:
|
|
40
|
+
body = response.read().decode("utf-8")
|
|
41
|
+
except urllib.error.HTTPError as exc:
|
|
42
|
+
body = exc.read().decode("utf-8")
|
|
43
|
+
raise RuntimeError(f"Synapsor HTTP MCP returned HTTP {exc.code}: {body}") from exc
|
|
44
|
+
|
|
45
|
+
parsed = json.loads(body)
|
|
46
|
+
if "error" in parsed:
|
|
47
|
+
raise RuntimeError(f"Synapsor HTTP MCP error: {parsed['error']}")
|
|
48
|
+
return parsed["result"]
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@function_tool
|
|
52
|
+
def billing_inspect_invoice(invoice_id: str) -> str:
|
|
53
|
+
"""Inspect one scoped invoice through Synapsor Runner HTTP MCP."""
|
|
54
|
+
result = call_synapsor_http_mcp("tools/call", {
|
|
55
|
+
"name": "billing.inspect_invoice",
|
|
56
|
+
"arguments": {"invoice_id": invoice_id},
|
|
57
|
+
})
|
|
58
|
+
return json.dumps(result.get("structuredContent", result), indent=2)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
async def main() -> None:
|
|
62
|
+
required = ["OPENAI_API_KEY", "SYNAPSOR_RUNNER_HTTP_URL", "SYNAPSOR_RUNNER_HTTP_TOKEN"]
|
|
63
|
+
missing = [name for name in required if not os.environ.get(name)]
|
|
64
|
+
if missing:
|
|
65
|
+
raise SystemExit(f"Missing required environment variables: {', '.join(missing)}")
|
|
66
|
+
|
|
67
|
+
invoice_id = os.environ.get("SYNAPSOR_INVOICE_ID", "INV-3001")
|
|
68
|
+
agent = Agent(
|
|
69
|
+
name="Synapsor HTTP MCP demo agent",
|
|
70
|
+
instructions=(
|
|
71
|
+
"Use the billing_inspect_invoice tool to inspect scoped invoice data. "
|
|
72
|
+
"Do not claim that you can run SQL, approve proposals, or commit writes."
|
|
73
|
+
),
|
|
74
|
+
tools=[billing_inspect_invoice],
|
|
75
|
+
)
|
|
76
|
+
result = await Runner.run(
|
|
77
|
+
agent,
|
|
78
|
+
(
|
|
79
|
+
f"Inspect invoice {invoice_id} using Synapsor. "
|
|
80
|
+
"Explain what you saw and whether you have write authority."
|
|
81
|
+
),
|
|
82
|
+
)
|
|
83
|
+
print(result.final_output)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
if __name__ == "__main__":
|
|
87
|
+
try:
|
|
88
|
+
asyncio.run(main())
|
|
89
|
+
except KeyboardInterrupt:
|
|
90
|
+
sys.exit(130)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
openai-agents>=0.1.0
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# OpenAI Agents SDK + Synapsor Runner over stdio
|
|
2
|
+
|
|
3
|
+
This example shows an OpenAI Agents SDK app launching Synapsor Runner as a
|
|
4
|
+
local stdio MCP server.
|
|
5
|
+
|
|
6
|
+
Use stdio when the agent process can start the MCP server on the same machine.
|
|
7
|
+
The model sees Synapsor semantic tools such as `billing.inspect_invoice`. It
|
|
8
|
+
does not receive raw SQL, database URLs, write credentials, approval tools, or
|
|
9
|
+
commit tools.
|
|
10
|
+
|
|
11
|
+
## Prerequisites
|
|
12
|
+
|
|
13
|
+
Generate `synapsor.runner.json` first:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner demo
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
or connect your own staging database:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner init --wizard --from-env DATABASE_URL --mode read_only
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Then install the Python dependencies:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
python -m venv .venv
|
|
29
|
+
. .venv/bin/activate
|
|
30
|
+
pip install -r requirements.txt
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Run
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
export OPENAI_API_KEY="..."
|
|
37
|
+
export DATABASE_URL="<postgres-or-mysql-read-url>"
|
|
38
|
+
export SYNAPSOR_TENANT_ID="acme"
|
|
39
|
+
export SYNAPSOR_PRINCIPAL="openai_agent_demo"
|
|
40
|
+
|
|
41
|
+
python agent.py
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Optional env:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
export SYNAPSOR_CONFIG="./synapsor.runner.json"
|
|
48
|
+
export SYNAPSOR_STORE="./.synapsor/local.db"
|
|
49
|
+
export SYNAPSOR_TOOL="billing.inspect_invoice"
|
|
50
|
+
export SYNAPSOR_INVOICE_ID="INV-3001"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Expected behavior:
|
|
54
|
+
|
|
55
|
+
- the agent can inspect the scoped invoice through Synapsor;
|
|
56
|
+
- the agent cannot run SQL;
|
|
57
|
+
- the agent cannot approve or commit writes;
|
|
58
|
+
- evidence/query audit are saved in the local Runner store.
|
|
59
|
+
|
|
60
|
+
If your installed OpenAI Agents SDK does not expose `MCPServerStdio`, update the
|
|
61
|
+
SDK or use the HTTP example, which wraps Synapsor HTTP MCP with a small JSON-RPC
|
|
62
|
+
client.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
from agents import Agent, Runner
|
|
7
|
+
from agents.mcp import MCPServerStdio
|
|
8
|
+
except ImportError as exc:
|
|
9
|
+
raise SystemExit(
|
|
10
|
+
"This example requires the OpenAI Agents SDK with MCP stdio support. "
|
|
11
|
+
"Install with: pip install -r requirements.txt"
|
|
12
|
+
) from exc
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
async def main() -> None:
|
|
16
|
+
config_path = os.environ.get("SYNAPSOR_CONFIG", "./synapsor.runner.json")
|
|
17
|
+
store_path = os.environ.get("SYNAPSOR_STORE", "./.synapsor/local.db")
|
|
18
|
+
invoice_id = os.environ.get("SYNAPSOR_INVOICE_ID", "INV-3001")
|
|
19
|
+
|
|
20
|
+
required = ["OPENAI_API_KEY", "DATABASE_URL", "SYNAPSOR_TENANT_ID", "SYNAPSOR_PRINCIPAL"]
|
|
21
|
+
missing = [name for name in required if not os.environ.get(name)]
|
|
22
|
+
if missing:
|
|
23
|
+
raise SystemExit(f"Missing required environment variables: {', '.join(missing)}")
|
|
24
|
+
|
|
25
|
+
params = {
|
|
26
|
+
"command": "npx",
|
|
27
|
+
"args": [
|
|
28
|
+
"-y",
|
|
29
|
+
"-p",
|
|
30
|
+
"@synapsor/runner@alpha",
|
|
31
|
+
"synapsor",
|
|
32
|
+
"mcp",
|
|
33
|
+
"serve",
|
|
34
|
+
"--config",
|
|
35
|
+
config_path,
|
|
36
|
+
"--store",
|
|
37
|
+
store_path,
|
|
38
|
+
],
|
|
39
|
+
"env": {
|
|
40
|
+
**os.environ,
|
|
41
|
+
"DATABASE_URL": os.environ["DATABASE_URL"],
|
|
42
|
+
"SYNAPSOR_TENANT_ID": os.environ["SYNAPSOR_TENANT_ID"],
|
|
43
|
+
"SYNAPSOR_PRINCIPAL": os.environ["SYNAPSOR_PRINCIPAL"],
|
|
44
|
+
},
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async with MCPServerStdio(params=params) as mcp_server:
|
|
48
|
+
agent = Agent(
|
|
49
|
+
name="Synapsor stdio MCP demo agent",
|
|
50
|
+
instructions=(
|
|
51
|
+
"Use Synapsor MCP tools to inspect scoped database data. "
|
|
52
|
+
"Do not claim that you can run SQL, approve proposals, or commit writes."
|
|
53
|
+
),
|
|
54
|
+
mcp_servers=[mcp_server],
|
|
55
|
+
)
|
|
56
|
+
result = await Runner.run(
|
|
57
|
+
agent,
|
|
58
|
+
(
|
|
59
|
+
f"Inspect invoice {invoice_id} using Synapsor. "
|
|
60
|
+
"Explain what you saw and whether you have write authority."
|
|
61
|
+
),
|
|
62
|
+
)
|
|
63
|
+
print(result.final_output)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
if __name__ == "__main__":
|
|
67
|
+
try:
|
|
68
|
+
asyncio.run(main())
|
|
69
|
+
except KeyboardInterrupt:
|
|
70
|
+
sys.exit(130)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
openai-agents>=0.1.0
|
|
@@ -36,14 +36,14 @@ examples/reference-support-billing-app/scripts/run-demo.sh
|
|
|
36
36
|
Validate the reviewed contract:
|
|
37
37
|
|
|
38
38
|
```bash
|
|
39
|
-
npx -y -p @synapsor/runner@alpha synapsor config validate --config examples/reference-support-billing-app/synapsor.runner.json
|
|
40
|
-
npx -y -p @synapsor/runner@alpha synapsor doctor --config examples/reference-support-billing-app/synapsor.runner.json
|
|
39
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner config validate --config examples/reference-support-billing-app/synapsor.runner.json
|
|
40
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner doctor --config examples/reference-support-billing-app/synapsor.runner.json
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
Serve MCP:
|
|
44
44
|
|
|
45
45
|
```bash
|
|
46
|
-
npx -y -p @synapsor/runner@alpha synapsor mcp serve \
|
|
46
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner mcp serve \
|
|
47
47
|
--config examples/reference-support-billing-app/synapsor.runner.json \
|
|
48
48
|
--store ./tmp/reference-support-billing/local.db
|
|
49
49
|
```
|
|
@@ -65,15 +65,15 @@ The model does not receive approval tools, commit tools, write credentials, raw
|
|
|
65
65
|
|
|
66
66
|
## Safe Write Examples
|
|
67
67
|
|
|
68
|
-
After `synapsor demo` or after starting this fixture manually, try the same
|
|
68
|
+
After `synapsor-runner demo` or after starting this fixture manually, try the same
|
|
69
69
|
proposal-first loop without connecting an MCP client:
|
|
70
70
|
|
|
71
71
|
```bash
|
|
72
|
-
npx -y -p @synapsor/runner@alpha synapsor propose billing.propose_late_fee_waiver --sample
|
|
73
|
-
npx -y -p @synapsor/runner@alpha synapsor proposals show latest
|
|
74
|
-
npx -y -p @synapsor/runner@alpha synapsor proposals approve latest --yes
|
|
75
|
-
npx -y -p @synapsor/runner@alpha synapsor apply latest
|
|
76
|
-
npx -y -p @synapsor/runner@alpha synapsor replay latest
|
|
72
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner propose billing.propose_late_fee_waiver --sample
|
|
73
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner proposals show latest
|
|
74
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner proposals approve latest --yes
|
|
75
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner apply latest
|
|
76
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner replay latest
|
|
77
77
|
```
|
|
78
78
|
|
|
79
79
|
Expected safety output:
|
|
@@ -93,8 +93,8 @@ Guarded writeback applied.
|
|
|
93
93
|
Other proposal examples use the same review/apply/replay path:
|
|
94
94
|
|
|
95
95
|
```bash
|
|
96
|
-
npx -y -p @synapsor/runner@alpha synapsor propose support.propose_plan_credit --sample
|
|
97
|
-
npx -y -p @synapsor/runner@alpha synapsor propose orders.propose_status_change --sample
|
|
96
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner propose support.propose_plan_credit --sample
|
|
97
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner propose orders.propose_status_change --sample
|
|
98
98
|
```
|
|
99
99
|
|
|
100
100
|
Safety guarantees:
|
|
@@ -115,17 +115,17 @@ or production-scale runner orchestration.
|
|
|
115
115
|
After a proposal exists:
|
|
116
116
|
|
|
117
117
|
```bash
|
|
118
|
-
npx -y -p @synapsor/runner@alpha synapsor proposals list --store ./tmp/reference-support-billing/local.db
|
|
119
|
-
npx -y -p @synapsor/runner@alpha synapsor proposals approve <proposal_id> --store ./tmp/reference-support-billing/local.db --actor local_reviewer --yes
|
|
120
|
-
npx -y -p @synapsor/runner@alpha synapsor proposals writeback-job <proposal_id> --store ./tmp/reference-support-billing/local.db --output ./tmp/reference-support-billing/job.json
|
|
121
|
-
npx -y -p @synapsor/runner@alpha synapsor apply --job ./tmp/reference-support-billing/job.json --store ./tmp/reference-support-billing/local.db
|
|
122
|
-
npx -y -p @synapsor/runner@alpha synapsor replay export <proposal_id> --store ./tmp/reference-support-billing/local.db --output ./tmp/reference-support-billing/replay.json
|
|
118
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner proposals list --store ./tmp/reference-support-billing/local.db
|
|
119
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner proposals approve <proposal_id> --store ./tmp/reference-support-billing/local.db --actor local_reviewer --yes
|
|
120
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner proposals writeback-job <proposal_id> --store ./tmp/reference-support-billing/local.db --output ./tmp/reference-support-billing/job.json
|
|
121
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner apply --job ./tmp/reference-support-billing/job.json --store ./tmp/reference-support-billing/local.db
|
|
122
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner replay export <proposal_id> --store ./tmp/reference-support-billing/local.db --output ./tmp/reference-support-billing/replay.json
|
|
123
123
|
```
|
|
124
124
|
|
|
125
125
|
To inspect locally in a browser:
|
|
126
126
|
|
|
127
127
|
```bash
|
|
128
|
-
npx -y -p @synapsor/runner@alpha synapsor ui \
|
|
128
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner ui \
|
|
129
129
|
--config examples/reference-support-billing-app/synapsor.runner.json \
|
|
130
130
|
--store ./tmp/reference-support-billing/local.db
|
|
131
131
|
```
|
package/package.json
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synapsor/runner",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.6",
|
|
4
4
|
"description": "Commit-safe MCP runner for Postgres and MySQL agents",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
8
|
-
"synapsor": "dist/cli.js",
|
|
9
8
|
"synapsor-runner": "dist/cli.js"
|
|
10
9
|
},
|
|
11
10
|
"files": [
|
|
@@ -17,6 +16,8 @@
|
|
|
17
16
|
"dist/runner.mjs",
|
|
18
17
|
"docs/**/*.md",
|
|
19
18
|
"examples/dangerous-mcp-tools.json",
|
|
19
|
+
"examples/openai-agents-http/**",
|
|
20
|
+
"examples/openai-agents-stdio/**",
|
|
20
21
|
"examples/reference-support-billing-app/**",
|
|
21
22
|
"recipes/**/*.json",
|
|
22
23
|
"README.md",
|
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
# MCP runner implementation plan
|
|
2
|
-
|
|
3
|
-
Branch: `mcp-commit-safe-runtime`
|
|
4
|
-
|
|
5
|
-
This plan maps the existing open-source runner repository to the commit-safe database MCP goal. The runner is a local-first MCP and database safety runtime, not a copy of the Synapsor C++ DBMS.
|
|
6
|
-
|
|
7
|
-
## Current inventory
|
|
8
|
-
|
|
9
|
-
### Existing package structure
|
|
10
|
-
|
|
11
|
-
- `packages/protocol`
|
|
12
|
-
- Zod schemas for the current `protocol_version: "1.0"` writeback job/result shape.
|
|
13
|
-
- `packages/worker-core`
|
|
14
|
-
- Runner config, env loading, redaction, doctor checks, polling loop, job validation.
|
|
15
|
-
- `packages/control-plane-client`
|
|
16
|
-
- Runner-token HTTP client for registration, heartbeat, adapter catalog/call, claim, lease renewal, result, and doctor.
|
|
17
|
-
- `packages/postgres`
|
|
18
|
-
- Parameterized single-row Postgres update adapter, identifier validation, receipt table, idempotency, tenant guard, version conflict guard.
|
|
19
|
-
- `packages/mysql`
|
|
20
|
-
- Parameterized single-row MySQL update adapter with equivalent safety checks.
|
|
21
|
-
- `apps/runner`
|
|
22
|
-
- CLI entrypoint with `doctor`, `validate`, `apply`, and `start`.
|
|
23
|
-
- `examples/postgres-support`
|
|
24
|
-
- Local approved writeback fixture for support tickets.
|
|
25
|
-
- `examples/mysql-orders`
|
|
26
|
-
- Local approved writeback fixture for orders/refund review.
|
|
27
|
-
- `scripts/smoke-local-examples.mjs`
|
|
28
|
-
- Docker-backed local smoke for Postgres/MySQL apply, idempotent retry, stale conflict, tenant mismatch, and disallowed column behavior.
|
|
29
|
-
|
|
30
|
-
### Baseline behavior
|
|
31
|
-
|
|
32
|
-
- Existing test baseline before edits: `corepack pnpm test` passed 5 files / 13 tests.
|
|
33
|
-
- Current worker already rejects arbitrary identifiers, patch columns outside allowlist, primary/tenant patch allowlisting, and missing approval id.
|
|
34
|
-
- Current job protocol is useful but not yet the required public protocol names:
|
|
35
|
-
- existing: `protocol_version: "1.0"`
|
|
36
|
-
- required: `synapsor.change-set.v1`, `synapsor.writeback-job.v1`, `synapsor.execution-receipt.v1`, `synapsor.runner-registration.v1`
|
|
37
|
-
|
|
38
|
-
## Implementation phases
|
|
39
|
-
|
|
40
|
-
### Phase 1: shared public protocol
|
|
41
|
-
|
|
42
|
-
- Add `schemas/*.schema.json`.
|
|
43
|
-
- Add `fixtures/protocol/*.json`.
|
|
44
|
-
- Add a shared checksum manifest.
|
|
45
|
-
- Current status: `fixtures/protocol/MANIFEST.json` records the schema/fixture SHA-256 set mirrored into the main Synapsor repository as `protocol/MANIFEST.json`; protocol tests verify all listed hashes.
|
|
46
|
-
- Extend `packages/protocol` to parse:
|
|
47
|
-
- current legacy `protocol_version: "1.0"` jobs/results
|
|
48
|
-
- public `schema_version: "synapsor.writeback-job.v1"` jobs
|
|
49
|
-
- public `schema_version: "synapsor.execution-receipt.v1"` receipts
|
|
50
|
-
- public `schema_version: "synapsor.change-set.v1"` proposals
|
|
51
|
-
- public `schema_version: "synapsor.runner-registration.v1"` runner registration
|
|
52
|
-
- Normalize public writeback jobs into the existing worker shape so the current Postgres/MySQL adapters remain stable.
|
|
53
|
-
- Add tests proving protocol fixtures parse and no credentials/unrestricted SQL are present.
|
|
54
|
-
|
|
55
|
-
### Phase 2: local capability runtime and store
|
|
56
|
-
|
|
57
|
-
- Add a strict YAML/JSON config loader for semantic capabilities.
|
|
58
|
-
- Current status: JSON validator implemented in `packages/config`.
|
|
59
|
-
- Reject arbitrary SQL, model-controlled table/schema/column names, missing tenant/primary guards, and proposal capabilities without allowlisted columns.
|
|
60
|
-
- Current status: implemented in `packages/config` unit tests.
|
|
61
|
-
- Add local SQLite migrations for proposals, events, evidence, query audit, approvals, jobs, receipts, replay, and runner state.
|
|
62
|
-
- Current status: proposal/event/approval/evidence/query-audit/writeback-job/idempotency-receipt/replay/runner-state foundation implemented in `packages/proposal-store`.
|
|
63
|
-
- Add proposal immutability and approval-by-hash/version.
|
|
64
|
-
- Current status: implemented for proposal creation and approval in `packages/proposal-store`.
|
|
65
|
-
- Add approved proposal to public writeback job generation.
|
|
66
|
-
- Current status: implemented through `ProposalStore.createWritebackJobFromProposal` and `synapsor proposals writeback-job`.
|
|
67
|
-
|
|
68
|
-
### Phase 3: MCP stdio server
|
|
69
|
-
|
|
70
|
-
- Add official MCP TypeScript SDK pinned to a stable version.
|
|
71
|
-
- Current status: implemented in `packages/mcp-server` with `@modelcontextprotocol/sdk@1.29.0`.
|
|
72
|
-
- Implement stdio transport first.
|
|
73
|
-
- Current status: `corepack pnpm runner mcp serve --config ./synapsor.runner.json --store ./.synapsor/local.db`.
|
|
74
|
-
- Expose semantic tools only:
|
|
75
|
-
- `billing.inspect_invoice`
|
|
76
|
-
- `billing.propose_late_fee_waiver`
|
|
77
|
-
- `support.inspect_ticket`
|
|
78
|
-
- `support.propose_ticket_resolution`
|
|
79
|
-
- `orders.inspect_order`
|
|
80
|
-
- `orders.propose_refund_review`
|
|
81
|
-
- Do not expose `execute_sql`, generic query tools, approval tools, or commit tools to the model.
|
|
82
|
-
- Current status: enforced by config/runtime shape and covered by `packages/mcp-server/src/index.test.ts`.
|
|
83
|
-
- Add read-only resources:
|
|
84
|
-
- `synapsor://proposals/{proposal_id}`
|
|
85
|
-
- `synapsor://evidence/{evidence_bundle_id}`
|
|
86
|
-
- `synapsor://replay/{replay_id}`
|
|
87
|
-
- Current status: implemented in the local stdio server and direct runtime resource reader.
|
|
88
|
-
|
|
89
|
-
### Phase 4: local CLI approval and replay
|
|
90
|
-
|
|
91
|
-
- Add:
|
|
92
|
-
- `synapsor proposals list`
|
|
93
|
-
- `synapsor proposals show`
|
|
94
|
-
- `synapsor proposals approve`
|
|
95
|
-
- `synapsor proposals reject`
|
|
96
|
-
- `synapsor replay show`
|
|
97
|
-
- `synapsor replay export`
|
|
98
|
-
- `synapsor mcp serve`
|
|
99
|
-
- Add `synapsor mcp audit`
|
|
100
|
-
- Current status:
|
|
101
|
-
- `synapsor proposals list/show/approve/reject` implemented against `packages/proposal-store`.
|
|
102
|
-
- `synapsor replay show/export` implemented against `packages/proposal-store`.
|
|
103
|
-
- `synapsor mcp audit` implemented.
|
|
104
|
-
- `synapsor mcp serve` implemented for local stdio mode.
|
|
105
|
-
- `synapsor init`, `synapsor runner start`, `synapsor runner doctor`, and `synapsor cloud connect` implemented as CLI entrypoints for starter config, runner aliases, and Cloud token/config validation.
|
|
106
|
-
- Approval must show exact diff, evidence summary, conflict guard, tenant/object scope, source mutation state, and proposal hash/version.
|
|
107
|
-
- Current status: `proposals show` and non-JSON `proposals approve` / `proposals reject` print trusted principal, tenant, target row, primary key, required role, proposal hash/version, allowed columns, conflict guard, evidence bundle/query fingerprint/item count, writeback boundary, source-mutation state, and exact before/after diff before local approval/rejection.
|
|
108
|
-
|
|
109
|
-
### Phase 5: demos
|
|
110
|
-
|
|
111
|
-
- Add real disposable MCP demos:
|
|
112
|
-
- `examples/mcp-postgres-billing`
|
|
113
|
-
- `examples/mcp-postgres-support`
|
|
114
|
-
- `examples/mcp-mysql-orders`
|
|
115
|
-
- Each demo needs Docker Compose, schema, seed data, read/write users where practical, config, client snippets, happy path, conflict path, cleanup, and expected output.
|
|
116
|
-
- The stale-row conflict demo must show:
|
|
117
|
-
- proposal created
|
|
118
|
-
- source unchanged
|
|
119
|
-
- out-of-band row change
|
|
120
|
-
- approval
|
|
121
|
-
- guarded worker returns conflict
|
|
122
|
-
- no write applied
|
|
123
|
-
- Current status: `examples/mcp-postgres-billing` plus `corepack pnpm test:mcp-local` covers MCP stdio `tools/list`, tool calls, evidence resource read, source unchanged before approval, approval, generated `synapsor.writeback-job.v1`, guarded apply, idempotent retry, and stale-row conflict.
|
|
124
|
-
- Current status: equivalent first-class MCP example directories exist for support-ticket and MySQL orders. `corepack pnpm test:mcp-local` exercises Postgres billing, Postgres support, and MySQL orders through stdio MCP plus guarded writeback.
|
|
125
|
-
- Current status: public local entrypoint added as `./scripts/demo-docker.sh` and `corepack pnpm demo:docker`; it requires Docker only on the host, runs the TypeScript runner inside a local demo image, runs the Docker-backed stdio MCP proof, and tears down containers/volumes. The contributor path remains `./scripts/demo-local.sh` and `corepack pnpm demo:local`.
|
|
126
|
-
|
|
127
|
-
### Phase 6: Cloud-linked mode
|
|
128
|
-
|
|
129
|
-
- Add Cloud client registration/heartbeat/tool catalog/tool call/claim/lease/result support.
|
|
130
|
-
- Current status: `packages/control-plane-client` exposes runner registration, runner heartbeat, adapter tool catalog, adapter tool call, writeback claim, lease renewal through heartbeat, and receipt submission helpers with transient retry/backoff.
|
|
131
|
-
- Current status: `synapsor cloud connect --config ./synapsor.cloud.json` now verifies the scoped runner token, registers runner id/version/source/engine/capability metadata, and sends an initial heartbeat.
|
|
132
|
-
- Do not send DB credentials to Cloud.
|
|
133
|
-
- Current status: client tests assert runner registration/heartbeat payloads do not include DB URLs or obvious secrets.
|
|
134
|
-
- Current status: runner CLI tests assert `cloud connect` does not print or send runner tokens, database URLs, or credential-shaped values.
|
|
135
|
-
- Keep write credentials local.
|
|
136
|
-
- Keep local and Cloud histories separate unless explicit import is later implemented.
|
|
137
|
-
- Current status: `mode: "cloud"` delegates adapter tool catalog and tool calls through `ControlPlaneClient`. The main repository now exposes the compatible `/v1/agent/adapters/tools` and `/v1/agent/adapters/call-tool` runner-token bridge with `adapter:read` / `adapter:invoke` permissions.
|
|
138
|
-
- Current status: `corepack pnpm test:mcp-cloud-linked` exercises a hosted-compatible Cloud-linked lifecycle against a mock Cloud API and disposable Postgres billing fixture: runner-token doctor, runner registration, heartbeat, Cloud-mode MCP `tools/list`, Cloud adapter tool call, trusted session binding, source unchanged before approval, approved job claim/lease, real guarded Postgres writeback, and terminal receipt submission.
|
|
139
|
-
|
|
140
|
-
## Current next edits
|
|
141
|
-
|
|
142
|
-
- Phase 1 protocol schemas/fixtures are implemented locally and covered by protocol tests.
|
|
143
|
-
- `synapsor mcp audit <target>` is implemented as a static MCP database risk review for exported manifests/tools-list payloads.
|
|
144
|
-
- Validated capability config and the local store are wired into a real MCP stdio server/runtime.
|
|
145
|
-
- Public local demo entrypoint is implemented as `./scripts/demo-docker.sh` / `corepack pnpm demo:docker`; it requires Docker only, builds a small local runner image, starts Docker fixture databases, runs the stdio MCP proof, proves guarded writeback/stale-row conflict, and tears down disposable resources. The contributor path remains `./scripts/demo-local.sh` / `corepack pnpm demo:local` for environments that already have Node/Corepack installed.
|
|
146
|
-
- Runtime modes are enforced in the store/CLI/runtime layers: `read_only` exposes read tools only and direct proposal calls fail closed, `shadow` stores proposals/evidence/query-audit/replay but rejects approval and writeback-job creation, and `review` enables local approval plus guarded writeback.
|
|
147
|
-
- Local `apply --store` records a public `synapsor.execution-receipt.v1` into the SQLite proposal store, so replay includes applied/conflict terminal writeback receipts instead of only pre-write proposal history.
|
|
148
|
-
- Next code-only work is broader release hardening: optional localhost approval UI, main-repo Cloud/UI gaps, and live hosted Cloud E2E once a compatible Cloud workspace/adapter/token is available.
|
|
149
|
-
- Preserve existing worker behavior while adding local MCP/runtime layers.
|
|
150
|
-
- Keep the existing Docker smoke path working.
|
|
151
|
-
|
|
152
|
-
## Release blockers
|
|
153
|
-
|
|
154
|
-
- Live hosted Cloud-linked E2E still requires a compatible Synapsor Cloud workspace, adapter, and scoped runner token. A local hosted-compatible Cloud-linked smoke now covers the protocol/API lifecycle against a mock Cloud API and real disposable Postgres writeback.
|
|
155
|
-
- `packages/proposal-store` uses Node 22 `node:sqlite`. The alpha package pins Node >= 22.5.0 in `engines` and the package/source wrappers fail early with a clear message on older Node versions. Replacing this with a broader-LTS SQLite dependency remains a future compatibility option.
|
|
156
|
-
- Release docs present: `LICENSE` is Apache License 2.0, and `CONTRIBUTING.md` / `CODE_OF_CONDUCT.md` exist with project-specific safety guidance.
|
|
157
|
-
|
|
158
|
-
## Verification log
|
|
159
|
-
|
|
160
|
-
- `corepack pnpm --filter @synapsor-runner/mcp-server test` passed after read-only catalog enforcement: read-only mode now lists only inspect/read tools while direct proposal calls still return `PROPOSALS_DISABLED`.
|
|
161
|
-
- `corepack pnpm test` passed after read-only catalog enforcement: 9 test files, 48 tests.
|
|
162
|
-
- `corepack pnpm test` passed after shadow/read-only mode enforcement: 9 test files, 47 tests.
|
|
163
|
-
- `corepack pnpm test:mcp-local` passed: Postgres billing, Postgres support, and MySQL orders stdio MCP flows all completed local approval, guarded writeback, idempotent retry, and stale-row conflict proof.
|
|
164
|
-
- `corepack pnpm --filter @synapsor-runner/control-plane-client test` passed after main-repo runner adapter bridge verification: 1 test file, 3 tests.
|
|
165
|
-
- `./scripts/demo-docker.sh` passed after adding the Docker-only wrapper, temporary dependency volumes, and `host.docker.internal` fixture routing. The command required only Docker on the host, ran the TypeScript runner inside a local image, started disposable Postgres/MySQL Docker containers, exercised semantic MCP tools, verified source unchanged before approval, applied guarded writeback, retried idempotently, proved stale-row conflict, and tore down containers/volumes/local demo files.
|
|
166
|
-
- `./scripts/demo-local.sh` passed earlier as the contributor path for machines that already have Node/Corepack installed.
|
|
167
|
-
- `corepack pnpm test:mcp-local` passed after the Docker-only host-routing change and disallowed-column tamper proof. The MCP smoke now validates Postgres billing, Postgres support, and MySQL orders across semantic tool listing/calls, tenant spoof rejection, source unchanged before approval, disallowed-column job rejection, guarded writeback, idempotent retry, stale-row conflict, and replay export.
|
|
168
|
-
- `corepack pnpm test` passed after adding `demo:docker`: 9 test files, 48 tests.
|
|
169
|
-
- `corepack pnpm test` passed after the CLI init/runner/cloud command additions: 9 test files, 42 tests.
|
|
170
|
-
- `corepack pnpm --filter @synapsor-runner/protocol test` passed after adding manifest checksum verification.
|
|
171
|
-
- `corepack pnpm test:mcp-client-configs` passed for `generic-stdio.json`, `claude-desktop.json`, `cursor.json`, and `vscode.json`: each config started stdio, returned semantic billing tools, and exposed no raw SQL/approval/commit tool.
|
|
172
|
-
- `corepack pnpm test` passed after adding the MCP client config verifier script: 9 test files, 47 tests.
|
|
173
|
-
- `corepack pnpm --filter ./apps/runner test` passed after enriching local approval display: 1 test file, 4 tests.
|
|
174
|
-
- `corepack pnpm test` passed after enriching local approval display: 9 test files, 47 tests.
|
|
175
|
-
- `corepack pnpm --filter ./apps/runner test` passed after adding local `apply --store` receipt recording and replay assertions: 1 test file, 4 tests.
|
|
176
|
-
- `corepack pnpm test` passed after adding local `apply --store` receipt recording: 9 test files, 47 tests.
|
|
177
|
-
- `corepack pnpm test:mcp-local` passed after recording apply/conflict receipts into replay for Postgres billing, Postgres support, and MySQL orders.
|
|
178
|
-
- `corepack pnpm demo:local` passed after receipt/replay updates: the public one-command demo ran disposable Postgres billing, Postgres support, and MySQL orders MCP scenarios, proved guarded writeback/idempotency/stale-row conflict, and tore down containers/volumes/temp demo files.
|
|
179
|
-
- `corepack pnpm test` passed after Docker-first demo and adapter hardening updates: 9 test files, 50 tests.
|
|
180
|
-
- `corepack pnpm test:mcp-local` passed after disallowed-column tamper proof across Postgres billing, Postgres support, and MySQL orders.
|
|
181
|
-
- `./scripts/demo-docker.sh` passed as the exact Docker-only first-run path: built the local runner image, ran the stdio MCP proof inside Docker, started disposable Postgres/MySQL fixtures, proved source unchanged before approval, guarded writeback, idempotent retry, disallowed-column rejection, stale-row conflict, and teardown. No demo containers or generated `.pnpm-store` cache remain.
|
|
182
|
-
- `corepack pnpm test:mcp-cloud-linked` passed after adding the hosted-compatible Cloud-linked smoke with mock Cloud API plus real guarded Postgres writeback and terminal receipt submission.
|
|
183
|
-
- `corepack pnpm --filter ./apps/runner test` passed after wiring `cloud connect` runner registration/heartbeat: 1 test file, 5 tests.
|
|
184
|
-
- `corepack pnpm --filter @synapsor-runner/control-plane-client test` passed after the same change: 1 test file, 3 tests.
|
|
185
|
-
- `corepack pnpm test` passed after `cloud connect` registration/heartbeat docs and tests: 9 test files, 48 tests.
|
|
186
|
-
- `corepack pnpm --filter @synapsor-runner/config test`, `corepack pnpm --filter @synapsor-runner/mcp-server test`, and `corepack pnpm --filter ./apps/runner test` passed after allowing the generated Cloud config registration fields (`runner_id`, `runner_version`, `project_id`, `engines`, `capabilities`) in strict config validation.
|
|
187
|
-
- `corepack pnpm test` passed after the same strict Cloud config fix: 9 test files, 48 tests.
|
package/docs/architecture.md
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
# Architecture
|
|
2
|
-
|
|
3
|
-
Synapsor Runner is the local commit-safety loop for database MCP. It gives developers
|
|
4
|
-
the smallest useful version of Synapsor's commit-safety boundary on their own
|
|
5
|
-
machine: semantic tools, trusted context, evidence, proposals, approval,
|
|
6
|
-
guarded writeback, receipts, and replay.
|
|
7
|
-
|
|
8
|
-
It is not the Synapsor C++ DBMS, not a self-hosted Synapsor Cloud, and it does
|
|
9
|
-
not physically branch Postgres or MySQL.
|
|
10
|
-
|
|
11
|
-
The product boundary is:
|
|
12
|
-
|
|
13
|
-
```text
|
|
14
|
-
MCP connects the agent. Synapsor controls the commit.
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
The local proof should make one thing obvious:
|
|
18
|
-
|
|
19
|
-
```text
|
|
20
|
-
The agent can request a database change, but the runner commits only an
|
|
21
|
-
approved, scoped, conflict-checked job. If the row changed after the agent saw
|
|
22
|
-
it, the runner returns conflict with no write.
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
## Local mode
|
|
26
|
-
|
|
27
|
-
The target architecture for local mode is:
|
|
28
|
-
|
|
29
|
-
```text
|
|
30
|
-
MCP client
|
|
31
|
-
-> local Synapsor MCP server
|
|
32
|
-
-> reviewed capability config
|
|
33
|
-
-> trusted local context provider
|
|
34
|
-
-> read-only Postgres/MySQL connection
|
|
35
|
-
-> local evidence and exact proposal diff
|
|
36
|
-
-> local proposal/event store
|
|
37
|
-
-> CLI or localhost approval
|
|
38
|
-
-> guarded worker with separate write credential
|
|
39
|
-
-> local receipt and replay
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
Current implementation status: the guarded worker, protocol validation, Postgres/MySQL adapters, receipt table, Docker smoke fixtures, stdio MCP server, local proposal/event/evidence/query-audit store, approval CLI, writeback-job generation, replay CLI, and MCP resources are implemented in the current branch.
|
|
43
|
-
|
|
44
|
-
## Cloud-linked mode
|
|
45
|
-
|
|
46
|
-
Synapsor Cloud owns proposal, evidence, approval, replay, and job lease state. Synapsor Runner runs in the customer environment and owns the write credential, transaction, receipt table, and result callback.
|
|
47
|
-
|
|
48
|
-
```text
|
|
49
|
-
Synapsor Cloud -> approved structured job -> local runner -> Postgres/MySQL
|
|
50
|
-
^ |
|
|
51
|
-
|---------------- result/replay callback ------------|
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
The runner does not receive arbitrary SQL. It receives target schema/table, primary key, tenant guard, allowed columns, patch values, conflict guard, idempotency key, and lease expiry.
|
|
55
|
-
|
|
56
|
-
Current implementation status: the control-plane client supports runner registration, heartbeat, adapter tool catalog fetch, adapter tool calls, writeback claim, lease renewal through heartbeat, and result/receipt submission. The MCP runtime can operate in `mode: "cloud"` by delegating tool calls to the Cloud adapter APIs. A full Cloud E2E still requires a compatible Synapsor Cloud workspace, adapter, and scoped runner token.
|
|
57
|
-
|
|
58
|
-
## Execution authority split
|
|
59
|
-
|
|
60
|
-
```text
|
|
61
|
-
MCP tool call = request/proposal authority
|
|
62
|
-
Trusted runner = execution authority
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
The model-facing path can request an inspect/proposal tool. It cannot call approval or commit tools by default. The runner only applies an already-approved, scoped, conflict-checked job.
|