@synapsor/runner 1.5.3 → 1.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -2
- package/README.md +20 -12
- package/dist/cli.d.ts.map +1 -1
- package/dist/runner.mjs +2332 -501
- package/dist/runtime.mjs +788 -148
- package/dist/shadow.mjs +101 -1
- package/docs/capability-authoring.md +6 -1
- package/docs/cloud-mode.md +18 -0
- package/docs/database-enforced-scope.md +8 -0
- package/docs/dsl-reference.md +45 -4
- package/docs/getting-started-own-database.md +6 -3
- package/docs/guarded-crud-writeback.md +10 -1
- package/docs/http-mcp.md +222 -207
- package/docs/limitations.md +9 -2
- package/docs/local-mode.md +5 -2
- package/docs/mcp-client-setup.md +24 -11
- package/docs/mcp-clients.md +10 -4
- package/docs/openai-agents-sdk.md +16 -2
- package/docs/production.md +72 -7
- package/docs/release-notes.md +44 -3
- package/docs/runner-bundles.md +7 -2
- package/docs/runner-config-reference.md +96 -6
- package/docs/running-a-runner-fleet.md +42 -13
- package/docs/security-boundary.md +38 -3
- package/docs/store-lifecycle.md +93 -5
- package/examples/openai-agents-http/README.md +10 -4
- package/examples/openai-agents-http/agent.py +2 -2
- package/examples/runner-fleet/Dockerfile +7 -2
- package/examples/runner-fleet/README.md +11 -7
- package/examples/runner-fleet/docker-compose.yml +4 -4
- package/examples/runner-fleet/mint-dev-token.mjs +1 -1
- package/examples/runner-fleet/start-tls-runner.sh +21 -0
- package/examples/runner-fleet/synapsor.runner.json +27 -1
- package/examples/support-plan-credit/README.md +6 -1
- package/examples/support-plan-credit/mcp-client-examples/generic-streamable-http.json +4 -1
- package/examples/support-plan-credit/mcp-client-examples/openai-agents-streamable-http.ts +4 -0
- package/examples/support-plan-credit/synapsor.contract.json +0 -3
- package/package.json +1 -1
- package/schemas/synapsor.runner.schema.json +80 -0
package/docs/http-mcp.md
CHANGED
|
@@ -1,44 +1,55 @@
|
|
|
1
1
|
# HTTP MCP
|
|
2
2
|
|
|
3
|
-
Use HTTP
|
|
4
|
-
|
|
3
|
+
Use HTTP when an application, server-side agent, container, or remote MCP client
|
|
4
|
+
connects to a long-running Synapsor Runner. Prefer stdio when one local desktop
|
|
5
|
+
client can launch Runner directly: stdio opens no network socket and needs no
|
|
6
|
+
HTTP credential, TLS setup, OAuth flow, or MCP HTTP session.
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
local agent tool can launch Synapsor Runner directly.
|
|
8
|
+
Runner provides:
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
- `mcp serve-streamable-http`: standard MCP Streamable HTTP using the official
|
|
11
|
+
MCP SDK. This is the normal HTTP endpoint.
|
|
12
|
+
- `mcp serve-http`: a legacy JSON-RPC bridge with `tools/list`, `tools/call`, and
|
|
13
|
+
`resources/read`. It has the same network-channel hardening but no standard
|
|
14
|
+
MCP session and therefore cannot use per-session `http_claims` identity.
|
|
10
15
|
|
|
11
|
-
|
|
12
|
-
when an MCP SDK/client expects `initialize`, session IDs, POST/GET/DELETE, and
|
|
13
|
-
standard HTTP MCP behavior.
|
|
14
|
-
- `mcp serve-http`: a lightweight authenticated JSON-RPC bridge for
|
|
15
|
-
`tools/list`, `tools/call`, and `resources/read`. Use this when your app wants
|
|
16
|
-
simple POST calls or an explicit wrapper around Runner tools.
|
|
16
|
+
## Authentication Concepts
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
These are separate controls:
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
| Control | Meaning |
|
|
21
|
+
| --- | --- |
|
|
22
|
+
| TLS | Encrypts the network channel and authenticates the server certificate. |
|
|
23
|
+
| mTLS | Also authenticates a client workload certificate. It supplements Bearer auth in Runner. |
|
|
24
|
+
| HTTP Bearer | The HTTP presentation scheme: `Authorization: Bearer <credential>`. It does not imply that the credential is a JWT. |
|
|
25
|
+
| Opaque endpoint token | One high-entropy service credential for loopback or an explicitly single-tenant service. It is not user or tenant identity. |
|
|
26
|
+
| Signed JWT | A short-lived identity-provider-issued access token whose signature, algorithm, issuer, audience/resource, time, scope, tenant, and principal claims Runner verifies. |
|
|
27
|
+
| MCP session ID | Routes requests to initialized MCP state. It is not authentication. |
|
|
28
|
+
| Trusted context | The tenant and principal Runner binds after authentication. Model arguments, arbitrary headers, query strings, forwarded headers, and MCP metadata are never trusted context. |
|
|
22
29
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
Runner does not issue endpoint tokens, JWTs, refresh tokens, or end-user
|
|
31
|
+
passwords. An operator generates and distributes an opaque token out of band.
|
|
32
|
+
For a shared deployment, an external identity provider or authorization server
|
|
33
|
+
issues JWT access tokens; Runner is only the protected resource that verifies
|
|
34
|
+
them.
|
|
35
|
+
|
|
36
|
+
## Deployment Profiles
|
|
30
37
|
|
|
31
|
-
|
|
32
|
-
|
|
38
|
+
### Local loopback with an opaque token
|
|
39
|
+
|
|
40
|
+
Generate at least 32 random bytes. The same environment variable must be
|
|
41
|
+
available to Runner and the authorized local client; the value is never placed
|
|
42
|
+
in config JSON or a generated client file.
|
|
33
43
|
|
|
34
44
|
```bash
|
|
45
|
+
export SYNAPSOR_RUNNER_HTTP_TOKEN="$(node -e 'process.stdout.write(require("node:crypto").randomBytes(32).toString("base64url"))')"
|
|
46
|
+
|
|
35
47
|
synapsor-runner mcp serve-streamable-http \
|
|
36
48
|
--host 127.0.0.1 \
|
|
37
49
|
--port 8766 \
|
|
38
50
|
--config ./synapsor.runner.json \
|
|
39
51
|
--store ./.synapsor/local.db \
|
|
40
|
-
--auth-token-env SYNAPSOR_RUNNER_HTTP_TOKEN
|
|
41
|
-
--alias-mode openai
|
|
52
|
+
--auth-token-env SYNAPSOR_RUNNER_HTTP_TOKEN
|
|
42
53
|
```
|
|
43
54
|
|
|
44
55
|
Equivalent unified command:
|
|
@@ -50,34 +61,57 @@ synapsor-runner mcp serve \
|
|
|
50
61
|
--port 8766 \
|
|
51
62
|
--config ./synapsor.runner.json \
|
|
52
63
|
--store ./.synapsor/local.db \
|
|
53
|
-
--auth-token-env SYNAPSOR_RUNNER_HTTP_TOKEN
|
|
54
|
-
--alias-mode openai
|
|
64
|
+
--auth-token-env SYNAPSOR_RUNNER_HTTP_TOKEN
|
|
55
65
|
```
|
|
56
66
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
the canonical Synapsor capability such as `billing.inspect_invoice`. Use
|
|
60
|
-
`--alias-mode both` only during migrations where some clients still need
|
|
61
|
-
canonical dotted names.
|
|
67
|
+
`--dev-no-auth` is accepted only for an explicit loopback development run. It
|
|
68
|
+
is refused for wildcard, private-network, and public binds.
|
|
62
69
|
|
|
63
|
-
|
|
70
|
+
### Remote single-tenant service
|
|
64
71
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
72
|
+
Declare the service and channel in Runner deployment config. This wiring is not
|
|
73
|
+
part of the portable Synapsor contract:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"http_security": {
|
|
78
|
+
"deployment": "single_tenant",
|
|
79
|
+
"channel": "trusted_tls_proxy",
|
|
80
|
+
"static_token": {
|
|
81
|
+
"active_env": "SYNAPSOR_RUNNER_HTTP_TOKEN",
|
|
82
|
+
"previous_env": "SYNAPSOR_RUNNER_HTTP_TOKEN_PREVIOUS"
|
|
83
|
+
},
|
|
84
|
+
"allowed_hosts": ["runner.internal.example"],
|
|
85
|
+
"allowed_origins": ["https://agent-console.example"]
|
|
86
|
+
}
|
|
87
|
+
}
|
|
71
88
|
```
|
|
72
89
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
90
|
+
The supported protected channels are:
|
|
91
|
+
|
|
92
|
+
1. Runner-owned TLS, selected by supplying certificate and key env references.
|
|
93
|
+
2. `trusted_tls_proxy`, where a trusted proxy terminates TLS and a firewall or
|
|
94
|
+
private network prevents direct client access to Runner.
|
|
95
|
+
3. `insecure_http_break_glass`, an authenticated but interceptable emergency
|
|
96
|
+
mode. It emits a security warning and is not appropriate for normal use.
|
|
76
97
|
|
|
77
|
-
|
|
98
|
+
A non-loopback listener with no explicit channel refuses to start before it
|
|
99
|
+
binds. Break glass never disables authentication.
|
|
78
100
|
|
|
79
|
-
|
|
80
|
-
|
|
101
|
+
Trusted TLS proxy:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
synapsor-runner mcp serve-streamable-http \
|
|
105
|
+
--host 0.0.0.0 \
|
|
106
|
+
--port 8766 \
|
|
107
|
+
--config ./synapsor.runner.json \
|
|
108
|
+
--store ./.synapsor/local.db \
|
|
109
|
+
--trusted-tls-proxy \
|
|
110
|
+
--auth-token-env SYNAPSOR_RUNNER_HTTP_TOKEN \
|
|
111
|
+
--previous-auth-token-env SYNAPSOR_RUNNER_HTTP_TOKEN_PREVIOUS
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Runner-owned TLS:
|
|
81
115
|
|
|
82
116
|
```bash
|
|
83
117
|
export SYNAPSOR_TLS_CERT_PEM="$(cat ./server.crt)"
|
|
@@ -93,7 +127,7 @@ synapsor-runner mcp serve-streamable-http \
|
|
|
93
127
|
--tls-key-env SYNAPSOR_TLS_KEY_PEM
|
|
94
128
|
```
|
|
95
129
|
|
|
96
|
-
|
|
130
|
+
For mTLS, add a protected client CA bundle:
|
|
97
131
|
|
|
98
132
|
```bash
|
|
99
133
|
export SYNAPSOR_TLS_CA_PEM="$(cat ./client-ca.crt)"
|
|
@@ -110,211 +144,192 @@ synapsor-runner mcp serve-streamable-http \
|
|
|
110
144
|
--require-client-cert
|
|
111
145
|
```
|
|
112
146
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
app-owned `http_handler` executors, terminate mTLS in your service mesh/proxy
|
|
116
|
-
or handler process and keep bearer/signature checks enabled in the handler.
|
|
147
|
+
mTLS authenticates a workload certificate in addition to the Bearer credential.
|
|
148
|
+
It does not turn a shared opaque token into per-user or per-tenant identity.
|
|
117
149
|
|
|
118
|
-
|
|
150
|
+
### Shared multi-user or multi-tenant service
|
|
119
151
|
|
|
120
|
-
|
|
121
|
-
|
|
152
|
+
Use verified signed session identity. A static endpoint token is intentionally
|
|
153
|
+
insufficient as trusted tenant/principal authority.
|
|
122
154
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
155
|
+
```json
|
|
156
|
+
{
|
|
157
|
+
"trusted_context": {
|
|
158
|
+
"provider": "http_claims",
|
|
159
|
+
"values": {
|
|
160
|
+
"tenant_id_key": "tenant_id",
|
|
161
|
+
"principal_key": "sub"
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
"session_auth": {
|
|
165
|
+
"provider": "jwt_asymmetric",
|
|
166
|
+
"algorithms": ["ES256"],
|
|
167
|
+
"jwks_url_env": "SYNAPSOR_SESSION_JWKS_URL",
|
|
168
|
+
"issuer": "https://identity.example",
|
|
169
|
+
"audience": "https://runner.example/mcp",
|
|
170
|
+
"tenant_claim": "tenant_id",
|
|
171
|
+
"principal_claim": "sub",
|
|
172
|
+
"clock_skew_seconds": 30
|
|
173
|
+
},
|
|
174
|
+
"http_security": {
|
|
175
|
+
"deployment": "shared",
|
|
176
|
+
"channel": "trusted_tls_proxy",
|
|
177
|
+
"oauth_resource": {
|
|
178
|
+
"resource": "https://runner.example/mcp",
|
|
179
|
+
"authorization_servers": ["https://identity.example"],
|
|
180
|
+
"scopes_supported": ["synapsor:mcp"],
|
|
181
|
+
"required_scopes": ["synapsor:mcp"],
|
|
182
|
+
"resource_name": "Synapsor Runner"
|
|
183
|
+
},
|
|
184
|
+
"allowed_hosts": ["runner.example"],
|
|
185
|
+
"allowed_origins": ["https://agent-console.example"]
|
|
186
|
+
}
|
|
187
|
+
}
|
|
129
188
|
```
|
|
130
189
|
|
|
131
|
-
|
|
190
|
+
The identity provider publishes the public JWKS URL stored in
|
|
191
|
+
`SYNAPSOR_SESSION_JWKS_URL`. The client obtains a short-lived access token from
|
|
192
|
+
that provider through the provider-supported OAuth/OIDC flow and sends it in the
|
|
193
|
+
Bearer header. Runner then validates, on every request including requests for an
|
|
194
|
+
existing MCP session:
|
|
132
195
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
196
|
+
- allowed `RS256` or `ES256` algorithm and signature;
|
|
197
|
+
- public `kid` selection and bounded JWKS refresh/cache behavior;
|
|
198
|
+
- exact issuer and audience/resource;
|
|
199
|
+
- expiry, not-before, and configured clock skew;
|
|
200
|
+
- configured required scopes;
|
|
201
|
+
- bounded scalar tenant and principal claims.
|
|
139
202
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
203
|
+
The audience must exactly equal `http_security.oauth_resource.resource`.
|
|
204
|
+
Unverified headers such as `X-Tenant-Id` and all `Forwarded`/`X-Forwarded-*`
|
|
205
|
+
values never become trusted identity.
|
|
143
206
|
|
|
144
|
-
|
|
145
|
-
variable name. It does not print token values or database URLs.
|
|
207
|
+
Runner exposes RFC 9728 protected-resource metadata at the current MCP path:
|
|
146
208
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
```bash
|
|
150
|
-
curl -i http://127.0.0.1:8766/healthz
|
|
151
|
-
curl -i http://127.0.0.1:8765/healthz
|
|
152
|
-
curl -i http://127.0.0.1:8766/readyz
|
|
209
|
+
```text
|
|
210
|
+
/.well-known/oauth-protected-resource/mcp
|
|
153
211
|
```
|
|
154
212
|
|
|
155
|
-
|
|
213
|
+
An unauthenticated MCP request receives a `401` Bearer challenge containing the
|
|
214
|
+
`resource_metadata` URL. A valid token missing a required scope receives `403`
|
|
215
|
+
with `insufficient_scope`. Runner does not implement a proprietary login or
|
|
216
|
+
refresh-token service.
|
|
156
217
|
|
|
157
|
-
|
|
158
|
-
{
|
|
159
|
-
"ok": true,
|
|
160
|
-
"transport": "streamable-http",
|
|
161
|
-
"tools": 1,
|
|
162
|
-
"mode": "read_only"
|
|
163
|
-
}
|
|
164
|
-
```
|
|
218
|
+
## Opaque Token Rotation
|
|
165
219
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
Unauthorized requests fail:
|
|
220
|
+
Runner accepts one active token and, only when configured, one previous token:
|
|
169
221
|
|
|
170
222
|
```bash
|
|
171
|
-
|
|
172
|
-
-H "Content-Type: application/json" \
|
|
173
|
-
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' \
|
|
174
|
-
http://127.0.0.1:8765/mcp
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
Authorized requests include the bearer token:
|
|
178
|
-
|
|
179
|
-
```bash
|
|
180
|
-
curl -i \
|
|
181
|
-
-H "Authorization: Bearer dev-local-token" \
|
|
182
|
-
-H "Content-Type: application/json" \
|
|
183
|
-
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' \
|
|
184
|
-
http://127.0.0.1:8765/mcp
|
|
223
|
+
export SYNAPSOR_RUNNER_HTTP_TOKEN="$(node -e 'process.stdout.write(require("node:crypto").randomBytes(32).toString("base64url"))')"
|
|
185
224
|
```
|
|
186
225
|
|
|
187
|
-
|
|
226
|
+
1. Move the old active value to the previous secret slot.
|
|
227
|
+
2. Have the secret manager inject that old value as
|
|
228
|
+
`SYNAPSOR_RUNNER_HTTP_TOKEN_PREVIOUS`, then put a new random value in the
|
|
229
|
+
active slot.
|
|
230
|
+
3. Restart/roll Runner instances and update authorized clients.
|
|
231
|
+
4. Remove `previous_env` and its secret after the bounded rollout window.
|
|
188
232
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
```
|
|
233
|
+
Runner never accepts an unbounded key history. Existing MCP sessions are pinned
|
|
234
|
+
to the exact credential used at initialization, so swapping active and previous
|
|
235
|
+
tokens cannot take over another session.
|
|
193
236
|
|
|
194
|
-
|
|
237
|
+
## Origin, Host, CORS, And Request Bounds
|
|
195
238
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
arbitrary table or column names
|
|
205
|
-
```
|
|
239
|
+
- Every present browser `Origin` must exactly match `allowed_origins`; otherwise
|
|
240
|
+
Runner returns `403`. Native MCP clients may omit `Origin`.
|
|
241
|
+
- Wildcard CORS and the `null` origin are rejected.
|
|
242
|
+
- Every request `Host` must match `allowed_hosts` (or the safe loopback default).
|
|
243
|
+
This is independent of tenant identity and limits DNS-rebinding-style access.
|
|
244
|
+
- Forwarded host and identity headers are never trusted automatically.
|
|
245
|
+
- Request body, header, connection, request-time, session-count, and idle-session
|
|
246
|
+
limits have bounded defaults and can be tightened under `http_security.limits`.
|
|
206
247
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
"
|
|
219
|
-
"arguments": { "invoice_id": "INV-3001" }
|
|
248
|
+
```json
|
|
249
|
+
{
|
|
250
|
+
"http_security": {
|
|
251
|
+
"limits": {
|
|
252
|
+
"max_request_bytes": 65536,
|
|
253
|
+
"max_header_bytes": 8192,
|
|
254
|
+
"max_sessions": 500,
|
|
255
|
+
"session_idle_timeout_seconds": 300,
|
|
256
|
+
"request_timeout_ms": 15000,
|
|
257
|
+
"headers_timeout_ms": 5000,
|
|
258
|
+
"keep_alive_timeout_ms": 5000,
|
|
259
|
+
"max_connections": 1000
|
|
220
260
|
}
|
|
221
|
-
}
|
|
222
|
-
|
|
261
|
+
}
|
|
262
|
+
}
|
|
223
263
|
```
|
|
224
264
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
265
|
+
Session and connection limits are per Runner process. Capability rate limits and
|
|
266
|
+
ledger state become fleet-wide only when the shared PostgreSQL runtime store is
|
|
267
|
+
configured.
|
|
228
268
|
|
|
229
|
-
##
|
|
269
|
+
## Health, Readiness, And Metrics
|
|
230
270
|
|
|
231
|
-
|
|
271
|
+
`/healthz` is unauthenticated and intentionally minimal:
|
|
232
272
|
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
-
|
|
238
|
-
|
|
239
|
-
"id": 3,
|
|
240
|
-
"method": "resources/read",
|
|
241
|
-
"params": { "uri": "synapsor://evidence/ev_..." }
|
|
242
|
-
}' \
|
|
243
|
-
http://127.0.0.1:8765/mcp
|
|
273
|
+
```json
|
|
274
|
+
{
|
|
275
|
+
"ok": true,
|
|
276
|
+
"status": "live",
|
|
277
|
+
"transport": "streamable-http"
|
|
278
|
+
}
|
|
244
279
|
```
|
|
245
280
|
|
|
246
|
-
|
|
281
|
+
`/readyz` reports bounded dependency status codes without credentials or raw
|
|
282
|
+
infrastructure errors. `/metrics` is disabled unless separately configured and
|
|
283
|
+
uses its own authorization; the MCP endpoint credential does not implicitly
|
|
284
|
+
grant metrics access.
|
|
247
285
|
|
|
248
|
-
|
|
249
|
-
development, allow one explicit origin:
|
|
286
|
+
## Legacy JSON-RPC Bridge
|
|
250
287
|
|
|
251
288
|
```bash
|
|
252
289
|
synapsor-runner mcp serve-http \
|
|
290
|
+
--host 127.0.0.1 \
|
|
291
|
+
--port 8765 \
|
|
253
292
|
--config ./synapsor.runner.json \
|
|
254
293
|
--store ./.synapsor/local.db \
|
|
255
|
-
--
|
|
294
|
+
--auth-token-env SYNAPSOR_RUNNER_HTTP_TOKEN
|
|
256
295
|
```
|
|
257
296
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
297
|
+
The bridge has equivalent remote channel, TLS/mTLS, static-token rotation,
|
|
298
|
+
Origin/Host, and request-bound enforcement. It rejects `http_claims` because it
|
|
299
|
+
does not implement standard MCP sessions. Use Streamable HTTP for a shared
|
|
300
|
+
identity deployment and for standard MCP SDK clients.
|
|
261
301
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
If you explicitly bind to all interfaces:
|
|
302
|
+
An authorized bridge request references the environment value at runtime:
|
|
265
303
|
|
|
266
304
|
```bash
|
|
267
|
-
|
|
305
|
+
curl -i \
|
|
306
|
+
-H "Authorization: Bearer ${SYNAPSOR_RUNNER_HTTP_TOKEN}" \
|
|
307
|
+
-H "Content-Type: application/json" \
|
|
308
|
+
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' \
|
|
309
|
+
http://127.0.0.1:8765/mcp
|
|
268
310
|
```
|
|
269
311
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
- keep bearer auth enabled;
|
|
273
|
-
- use TLS or a trusted reverse proxy;
|
|
274
|
-
- prefer private networking;
|
|
275
|
-
- add rate limits and request-size limits at the edge;
|
|
276
|
-
- do not log request bodies by default;
|
|
277
|
-
- rotate the bearer token if it is exposed.
|
|
278
|
-
|
|
279
|
-
`--dev-no-auth` is accepted only on `localhost` or `127.0.0.1`. It fails closed
|
|
280
|
-
with `--host 0.0.0.0`.
|
|
312
|
+
## Diagnose Before Serving
|
|
281
313
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
```text
|
|
289
|
-
tenant_id
|
|
290
|
-
principal
|
|
291
|
-
principal_id
|
|
292
|
-
project_id
|
|
293
|
-
source_id
|
|
294
|
-
allowed_columns
|
|
295
|
-
approval_identity
|
|
314
|
+
```bash
|
|
315
|
+
synapsor-runner doctor \
|
|
316
|
+
--config ./synapsor.runner.json \
|
|
317
|
+
--transport streamable-http \
|
|
318
|
+
--host 127.0.0.1 \
|
|
319
|
+
--auth-token-env SYNAPSOR_RUNNER_HTTP_TOKEN
|
|
296
320
|
```
|
|
297
321
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
See:
|
|
305
|
-
|
|
306
|
-
```text
|
|
307
|
-
examples/openai-agents-http/
|
|
308
|
-
examples/openai-agents-stdio/
|
|
309
|
-
```
|
|
322
|
+
For a remote proxy deployment add `--host 0.0.0.0 --trusted-tls-proxy`; for
|
|
323
|
+
Runner-owned TLS add the same TLS env-name flags used at startup. Doctor reports
|
|
324
|
+
the transport, bind scope, channel, auth/identity mode, issuer/audience/resource,
|
|
325
|
+
key readiness, token strength/rotation, Origin/Host policy, limits, rate-limit
|
|
326
|
+
scope, and database isolation assurance without printing credential values.
|
|
310
327
|
|
|
311
|
-
|
|
312
|
-
is available. The stdio example launches Runner as a child process. The HTTP
|
|
313
|
-
example connects to `synapsor-runner mcp serve-streamable-http` through
|
|
314
|
-
`MCPServerStreamableHttp`. Use the JSON-RPC bridge only when you intentionally
|
|
315
|
-
want a small app-owned wrapper instead of standard HTTP MCP.
|
|
328
|
+
## Model-Facing Boundary
|
|
316
329
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
330
|
+
HTTP transport does not change authority. MCP clients receive reviewed semantic
|
|
331
|
+
capabilities, never raw SQL, database credentials, endpoint credentials,
|
|
332
|
+
approval/apply/reconcile/revert tools, token minting, or token refresh. Keep
|
|
333
|
+
least-privilege DB roles and PostgreSQL RLS or tenant-bound credentials under
|
|
334
|
+
Runner where practical; transport authentication does not replace database or
|
|
335
|
+
operator authorization.
|
package/docs/limitations.md
CHANGED
|
@@ -41,7 +41,9 @@ enterprise SLA.
|
|
|
41
41
|
- Primary-key guard.
|
|
42
42
|
- Tenant guard.
|
|
43
43
|
- Allowed-column validation.
|
|
44
|
-
-
|
|
44
|
+
- Exact version-column conflict guards, plus an explicit legacy
|
|
45
|
+
`CONFLICT GUARD WEAK ROW HASH ACKNOWLEDGED` escape hatch for ordinary
|
|
46
|
+
single-row source-DB UPDATE only.
|
|
45
47
|
- Idempotency receipts.
|
|
46
48
|
- Named local trusted contexts for capability configs.
|
|
47
49
|
- Capability recipes that generate reviewed starter configs.
|
|
@@ -134,7 +136,12 @@ Do not describe external approval as merge.
|
|
|
134
136
|
|
|
135
137
|
## Weak Conflict Guards
|
|
136
138
|
|
|
137
|
-
A version/timestamp column is the preferred conflict guard.
|
|
139
|
+
A version/timestamp column is the preferred conflict guard. UPDATE authoring
|
|
140
|
+
fails if no guard is declared. A weak row-hash guard can be selected only with
|
|
141
|
+
the reviewer-visible `CONFLICT GUARD WEAK ROW HASH ACKNOWLEDGED` clause for a
|
|
142
|
+
narrow ordinary single-row source-DB UPDATE. It hashes the captured projection,
|
|
143
|
+
may miss concurrent changes outside that projection, and must not be presented
|
|
144
|
+
as equivalent to a durable version column.
|
|
138
145
|
|
|
139
146
|
Runner-ledger UPDATE and DELETE require an exact guard; UPDATE must advance it
|
|
140
147
|
inside the source transaction. INSERT requires a reviewed source-unique dedup
|
package/docs/local-mode.md
CHANGED
|
@@ -85,7 +85,7 @@ Use Streamable HTTP when your app/server agent connects through a standard HTTP
|
|
|
85
85
|
MCP client:
|
|
86
86
|
|
|
87
87
|
```bash
|
|
88
|
-
export SYNAPSOR_RUNNER_HTTP_TOKEN="
|
|
88
|
+
export SYNAPSOR_RUNNER_HTTP_TOKEN="$(node -e 'process.stdout.write(require("node:crypto").randomBytes(32).toString("base64url"))')"
|
|
89
89
|
|
|
90
90
|
npx -y -p @synapsor/runner synapsor-runner mcp serve-streamable-http \
|
|
91
91
|
--config ./synapsor.runner.json \
|
|
@@ -94,7 +94,10 @@ npx -y -p @synapsor/runner synapsor-runner mcp serve-streamable-http \
|
|
|
94
94
|
```
|
|
95
95
|
|
|
96
96
|
Streamable HTTP defaults to `127.0.0.1:8766`, requires bearer auth by default,
|
|
97
|
-
and
|
|
97
|
+
and uses an opaque endpoint token only as shared service access, not user or
|
|
98
|
+
tenant identity. Non-loopback serving requires direct TLS, an explicitly
|
|
99
|
+
trusted TLS proxy, or authenticated emergency break glass; shared deployments
|
|
100
|
+
require verified signed claims.
|
|
98
101
|
Use `synapsor-runner mcp serve-http` only when you explicitly want the smaller
|
|
99
102
|
JSON-RPC bridge. Details: [HTTP MCP](http-mcp.md).
|
|
100
103
|
|
package/docs/mcp-client-setup.md
CHANGED
|
@@ -49,10 +49,13 @@ developer path. Streamable HTTP implements MCP initialize/session behavior over
|
|
|
49
49
|
an authenticated `/mcp` endpoint. The JSON-RPC bridge is intentionally smaller
|
|
50
50
|
and does not implement MCP initialize/session behavior.
|
|
51
51
|
|
|
52
|
-
HTTP requires
|
|
52
|
+
HTTP requires Bearer authentication by default. `Bearer` is the HTTP
|
|
53
|
+
presentation scheme; for this loopback example it carries one opaque random
|
|
54
|
+
endpoint token, not a user identity or JWT. The operator generates it and
|
|
55
|
+
provisions the same environment value to Runner and the authorized client:
|
|
53
56
|
|
|
54
57
|
```bash
|
|
55
|
-
export SYNAPSOR_RUNNER_HTTP_TOKEN="
|
|
58
|
+
export SYNAPSOR_RUNNER_HTTP_TOKEN="$(node -e 'process.stdout.write(require("node:crypto").randomBytes(32).toString("base64url"))')"
|
|
56
59
|
|
|
57
60
|
npx -y -p @synapsor/runner synapsor-runner mcp serve-streamable-http \
|
|
58
61
|
--config ./synapsor.runner.json \
|
|
@@ -88,8 +91,10 @@ npx -y -p @synapsor/runner synapsor-runner tools preview \
|
|
|
88
91
|
--alias-mode openai
|
|
89
92
|
```
|
|
90
93
|
|
|
91
|
-
|
|
92
|
-
|
|
94
|
+
Do not distribute one opaque token to unrelated users or tenants. A
|
|
95
|
+
non-loopback service also needs direct TLS or an explicitly trusted TLS proxy;
|
|
96
|
+
a shared service uses short-lived signed JWTs issued by your identity provider,
|
|
97
|
+
with tenant/principal bound from verified claims. Details: [HTTP MCP](http-mcp.md).
|
|
93
98
|
|
|
94
99
|
## Generate A Client Snippet
|
|
95
100
|
|
|
@@ -142,8 +147,10 @@ npx -y -p @synapsor/runner synapsor-runner mcp configure \
|
|
|
142
147
|
When the destination already exists, Synapsor Runner creates a timestamped
|
|
143
148
|
backup before writing. Noninteractive scripts must add `--yes`.
|
|
144
149
|
|
|
145
|
-
The command writes only
|
|
146
|
-
|
|
150
|
+
The command writes only command arguments and, for HTTP clients, credential
|
|
151
|
+
environment references plus external authorization metadata. It never writes
|
|
152
|
+
database URLs, passwords, token values, client secrets, or refresh tokens into
|
|
153
|
+
the generated client config.
|
|
147
154
|
|
|
148
155
|
No separate Apps flag is required. A compatible host discovers
|
|
149
156
|
`ui://synapsor/proposal-review.html` from proposal-tool metadata. The app can
|
|
@@ -165,8 +172,6 @@ the current `latest` release.
|
|
|
165
172
|
For standard app/server HTTP MCP mode:
|
|
166
173
|
|
|
167
174
|
```bash
|
|
168
|
-
export SYNAPSOR_RUNNER_HTTP_TOKEN="dev-local-token"
|
|
169
|
-
|
|
170
175
|
npx -y -p @synapsor/runner synapsor-runner mcp serve-streamable-http \
|
|
171
176
|
--config ./examples/mcp-postgres-billing/synapsor.runner.json \
|
|
172
177
|
--store ./.synapsor/local.db \
|
|
@@ -174,6 +179,8 @@ npx -y -p @synapsor/runner synapsor-runner mcp serve-streamable-http \
|
|
|
174
179
|
```
|
|
175
180
|
|
|
176
181
|
For the smaller JSON-RPC bridge, use `synapsor-runner mcp serve-http` instead.
|
|
182
|
+
The bridge is not standard Streamable HTTP and cannot provide claim-bound MCP
|
|
183
|
+
sessions, so do not use it for a shared identity deployment.
|
|
177
184
|
|
|
178
185
|
## Generic stdio Client
|
|
179
186
|
|
|
@@ -195,9 +202,9 @@ For the smaller JSON-RPC bridge, use `synapsor-runner mcp serve-http` instead.
|
|
|
195
202
|
"./.synapsor/local.db"
|
|
196
203
|
],
|
|
197
204
|
"env": {
|
|
198
|
-
"BILLING_POSTGRES_READ_URL": "
|
|
199
|
-
"SYNAPSOR_TENANT_ID": "
|
|
200
|
-
"SYNAPSOR_PRINCIPAL": "
|
|
205
|
+
"BILLING_POSTGRES_READ_URL": "${BILLING_POSTGRES_READ_URL}",
|
|
206
|
+
"SYNAPSOR_TENANT_ID": "${SYNAPSOR_TENANT_ID}",
|
|
207
|
+
"SYNAPSOR_PRINCIPAL": "${SYNAPSOR_PRINCIPAL}"
|
|
201
208
|
}
|
|
202
209
|
}
|
|
203
210
|
}
|
|
@@ -265,6 +272,12 @@ examples/mcp-client-configs/vscode.json
|
|
|
265
272
|
|
|
266
273
|
Each example uses the same stdio command/args/env structure. Replace the placeholder environment variables in your client settings or shell environment.
|
|
267
274
|
|
|
275
|
+
These checked-in desktop examples use stdio, which is the recommended local
|
|
276
|
+
path for Claude Desktop, Cursor, and VS Code. The OpenAI Agents SDK recipe is
|
|
277
|
+
syntax-checked, and the HTTP endpoint is interoperability-tested with the
|
|
278
|
+
official MCP TypeScript client; repository CI does not claim to exercise an
|
|
279
|
+
identity-provider login inside every third-party host.
|
|
280
|
+
|
|
268
281
|
Do not add a write database URL to the MCP server environment unless you are intentionally running a local review/writeback demo. For normal read/proposal tool calls, use the read URL and trusted context values only.
|
|
269
282
|
|
|
270
283
|
Before documenting a client UI as officially tested, verify:
|