@synapsor/runner 1.5.0 → 1.5.3
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 +92 -3
- package/README.md +96 -109
- package/dist/authoring.d.ts +23 -0
- package/dist/authoring.d.ts.map +1 -0
- package/dist/authoring.mjs +1318 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +4 -5
- package/dist/local-ui.d.ts +14 -0
- package/dist/local-ui.d.ts.map +1 -1
- package/dist/runner.mjs +10845 -5598
- package/dist/runtime.mjs +29 -1
- package/dist/shadow.d.ts +36 -0
- package/dist/shadow.d.ts.map +1 -0
- package/dist/shadow.mjs +5262 -0
- package/docs/README.md +25 -2
- package/docs/alternatives.md +122 -0
- package/docs/capability-authoring.md +43 -0
- package/docs/client-recipes.md +218 -0
- package/docs/contract-testing.md +9 -7
- package/docs/cursor-plugin.md +78 -0
- package/docs/effect-regression.md +39 -2
- package/docs/fresh-developer-usability.md +110 -0
- package/docs/getting-started-own-database.md +96 -2
- package/docs/host-compatibility.md +59 -0
- package/docs/local-mode.md +6 -5
- package/docs/mcp-audit.md +166 -2
- package/docs/mcp-client-setup.md +4 -0
- package/docs/mcp-clients.md +33 -4
- package/docs/oss-vs-cloud.md +3 -0
- package/docs/release-notes.md +90 -4
- package/docs/security-boundary.md +20 -5
- package/docs/shadow-studies.md +47 -4
- package/docs/troubleshooting-first-run.md +46 -0
- package/examples/support-billing-agent/README.md +18 -0
- package/examples/support-billing-agent/app/README.md +6 -0
- package/examples/support-billing-agent/app/contract.ts +28 -0
- package/examples/support-billing-agent/app/effect-adapter.mjs +23 -0
- package/examples/support-billing-agent/app/record-shadow-outcomes.mjs +44 -0
- package/examples/support-billing-agent/scripts/run-evaluation.sh +6 -5
- package/examples/support-plan-credit/README.md +48 -2
- package/examples/support-plan-credit/mcp-client-examples/README.md +23 -0
- package/examples/support-plan-credit/mcp-client-examples/claude-code.sh +34 -0
- package/examples/support-plan-credit/mcp-client-examples/codex.config.toml +24 -0
- package/examples/support-plan-credit/mcp-client-examples/generic-stdio.mjs +35 -0
- package/examples/support-plan-credit/mcp-client-examples/generic-streamable-http.mjs +31 -0
- package/examples/support-plan-credit/mcp-client-examples/google-adk.py +40 -0
- package/examples/support-plan-credit/mcp-client-examples/langchain.mjs +29 -0
- package/examples/support-plan-credit/mcp-client-examples/llamaindex.py +36 -0
- package/examples/support-plan-credit/mcp-client-examples/openai-agents-stdio.ts +1 -1
- package/examples/support-plan-credit/mcp-client-examples/openai-agents-streamable-http.ts +1 -1
- package/examples/support-plan-credit/mcp-client-examples/vscode.mcp.json +20 -0
- package/examples/support-plan-credit/synapsor/actions/support.propose_plan_credit.contract-tests.generated.json +221 -0
- package/examples/support-plan-credit/synapsor/actions/support.propose_plan_credit.ts +34 -0
- package/fixtures/mcp-audit/README.md +14 -0
- package/fixtures/mcp-audit/cursor-bypass-config.json +38 -0
- package/fixtures/mcp-audit/dangerous-tools-list.json +33 -0
- package/fixtures/mcp-audit/reviewed-proposal-tools-list.json +60 -0
- package/package.json +18 -3
- package/schemas/mcp-audit-report.schema.json +100 -1
- package/schemas/synapsor.contract-tests.schema.json +1 -1
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
2
|
+
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
3
|
+
|
|
4
|
+
const token = process.env.SYNAPSOR_RUNNER_HTTP_TOKEN;
|
|
5
|
+
if (!token) throw new Error("set SYNAPSOR_RUNNER_HTTP_TOKEN in the launching environment");
|
|
6
|
+
|
|
7
|
+
const transport = new StreamableHTTPClientTransport(new URL("http://127.0.0.1:8766/mcp"), {
|
|
8
|
+
requestInit: { headers: { Authorization: `Bearer ${token}` } },
|
|
9
|
+
});
|
|
10
|
+
const client = new Client({ name: "synapsor-generic-http", version: "1.0.0" });
|
|
11
|
+
|
|
12
|
+
await client.connect(transport);
|
|
13
|
+
try {
|
|
14
|
+
const listed = await client.listTools();
|
|
15
|
+
const names = listed.tools.map((tool) => tool.name);
|
|
16
|
+
const forbidden = names.filter((name) => /sql|approve|apply|commit|activate|revert/i.test(name));
|
|
17
|
+
if (forbidden.length) throw new Error(`unsafe model-facing tools: ${forbidden.join(", ")}`);
|
|
18
|
+
|
|
19
|
+
const result = await client.callTool({
|
|
20
|
+
name: "support.propose_plan_credit",
|
|
21
|
+
arguments: {
|
|
22
|
+
customer_id: "CUS-3001",
|
|
23
|
+
credit_cents: 2500,
|
|
24
|
+
reason: "SLA outage ticket SUP-481",
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
console.log(JSON.stringify(result, null, 2));
|
|
28
|
+
console.error("Proposal only. Review and apply outside the model-facing MCP client.");
|
|
29
|
+
} finally {
|
|
30
|
+
await client.close();
|
|
31
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from google.adk.agents import LlmAgent
|
|
4
|
+
from google.adk.tools.mcp_tool import McpToolset
|
|
5
|
+
from google.adk.tools.mcp_tool.mcp_session_manager import StdioConnectionParams
|
|
6
|
+
from mcp import StdioServerParameters
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
root_agent = LlmAgent(
|
|
10
|
+
model=os.environ["GOOGLE_ADK_MODEL"],
|
|
11
|
+
name="synapsor_support_agent",
|
|
12
|
+
instruction=(
|
|
13
|
+
"List your Synapsor tools. Call support.propose_plan_credit with "
|
|
14
|
+
"customer_id CUS-3001, credit_cents 2500, and reason "
|
|
15
|
+
"'SLA outage ticket SUP-481'. Confirm source_database_changed is false "
|
|
16
|
+
"and stop for human review outside the model-facing agent."
|
|
17
|
+
),
|
|
18
|
+
tools=[
|
|
19
|
+
McpToolset(
|
|
20
|
+
connection_params=StdioConnectionParams(
|
|
21
|
+
server_params=StdioServerParameters(
|
|
22
|
+
command="npx",
|
|
23
|
+
args=[
|
|
24
|
+
"-y", "-p", "@synapsor/runner", "synapsor-runner",
|
|
25
|
+
"mcp", "serve", "--config",
|
|
26
|
+
"./examples/support-plan-credit/synapsor.runner.json",
|
|
27
|
+
"--store", "./tmp/support-plan-credit/local.db",
|
|
28
|
+
],
|
|
29
|
+
)
|
|
30
|
+
),
|
|
31
|
+
tool_filter=[
|
|
32
|
+
"support.inspect_customer",
|
|
33
|
+
"support.propose_plan_credit",
|
|
34
|
+
],
|
|
35
|
+
)
|
|
36
|
+
],
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
# Run root_agent with your normal ADK runner. Approval, apply, commit,
|
|
40
|
+
# activation, and revert are intentionally not MCP tools.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { MultiServerMCPClient } from "@langchain/mcp-adapters";
|
|
2
|
+
|
|
3
|
+
const client = new MultiServerMCPClient({
|
|
4
|
+
synapsor: {
|
|
5
|
+
transport: "stdio",
|
|
6
|
+
command: "npx",
|
|
7
|
+
args: [
|
|
8
|
+
"-y", "-p", "@synapsor/runner", "synapsor-runner", "mcp", "serve",
|
|
9
|
+
"--config", "./examples/support-plan-credit/synapsor.runner.json",
|
|
10
|
+
"--store", "./tmp/support-plan-credit/local.db",
|
|
11
|
+
],
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const tools = await client.getTools();
|
|
16
|
+
const names = tools.map((tool) => tool.name);
|
|
17
|
+
const forbidden = names.filter((name) => /sql|approve|apply|commit|activate|revert/i.test(name));
|
|
18
|
+
if (forbidden.length) throw new Error(`unsafe model-facing tools: ${forbidden.join(", ")}`);
|
|
19
|
+
|
|
20
|
+
const proposal = tools.find((tool) => tool.name === "support.propose_plan_credit");
|
|
21
|
+
if (!proposal) throw new Error(`proposal tool missing; available: ${names.join(", ")}`);
|
|
22
|
+
|
|
23
|
+
const result = await proposal.invoke({
|
|
24
|
+
customer_id: "CUS-3001",
|
|
25
|
+
credit_cents: 2500,
|
|
26
|
+
reason: "SLA outage ticket SUP-481",
|
|
27
|
+
});
|
|
28
|
+
console.log(result);
|
|
29
|
+
console.error("Proposal only. Review and apply outside the model-facing LangChain/LangGraph agent.");
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
|
|
3
|
+
from llama_index.tools.mcp import BasicMCPClient
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
async def main() -> None:
|
|
7
|
+
client = BasicMCPClient(
|
|
8
|
+
"npx",
|
|
9
|
+
args=[
|
|
10
|
+
"-y", "-p", "@synapsor/runner", "synapsor-runner", "mcp", "serve",
|
|
11
|
+
"--config", "./examples/support-plan-credit/synapsor.runner.json",
|
|
12
|
+
"--store", "./tmp/support-plan-credit/local.db",
|
|
13
|
+
],
|
|
14
|
+
)
|
|
15
|
+
tools = await client.list_tools()
|
|
16
|
+
names = [tool.name for tool in tools.tools]
|
|
17
|
+
forbidden = [name for name in names if any(part in name.lower() for part in (
|
|
18
|
+
"sql", "approve", "apply", "commit", "activate", "revert"
|
|
19
|
+
))]
|
|
20
|
+
if forbidden:
|
|
21
|
+
raise RuntimeError(f"unsafe model-facing tools: {forbidden}")
|
|
22
|
+
|
|
23
|
+
result = await client.call_tool(
|
|
24
|
+
"support.propose_plan_credit",
|
|
25
|
+
{
|
|
26
|
+
"customer_id": "CUS-3001",
|
|
27
|
+
"credit_cents": 2500,
|
|
28
|
+
"reason": "SLA outage ticket SUP-481",
|
|
29
|
+
},
|
|
30
|
+
)
|
|
31
|
+
print(result)
|
|
32
|
+
print("Proposal only. Review and apply outside the model-facing LlamaIndex agent.")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
if __name__ == "__main__":
|
|
36
|
+
asyncio.run(main())
|
|
@@ -9,7 +9,7 @@ await synapsor.connect();
|
|
|
9
9
|
try {
|
|
10
10
|
const agent = new Agent({
|
|
11
11
|
name: "Support operations agent",
|
|
12
|
-
instructions: "Use only Synapsor business tools. Inspect evidence before proposing a plan credit.",
|
|
12
|
+
instructions: "Use only the listed Synapsor business tools. Inspect evidence before proposing a plan credit. Never request approval or apply authority; stop for human review outside the agent.",
|
|
13
13
|
mcpServers: [synapsor],
|
|
14
14
|
});
|
|
15
15
|
const result = await run(agent, "Inspect customer CUS-3001 and propose a $25 plan credit for SLA outage ticket SUP-481.");
|
|
@@ -10,7 +10,7 @@ await synapsor.connect();
|
|
|
10
10
|
try {
|
|
11
11
|
const agent = new Agent({
|
|
12
12
|
name: "Support operations agent",
|
|
13
|
-
instructions: "Use only Synapsor business tools. Inspect evidence before proposing a plan credit.",
|
|
13
|
+
instructions: "Use only the listed Synapsor business tools. Inspect evidence before proposing a plan credit. Never request approval or apply authority; stop for human review outside the agent.",
|
|
14
14
|
mcpServers: [synapsor],
|
|
15
15
|
});
|
|
16
16
|
const result = await run(agent, "Inspect customer CUS-3001 and propose a $25 plan credit for SLA outage ticket SUP-481.");
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"servers": {
|
|
3
|
+
"synapsor": {
|
|
4
|
+
"type": "stdio",
|
|
5
|
+
"command": "npx",
|
|
6
|
+
"args": [
|
|
7
|
+
"-y",
|
|
8
|
+
"-p",
|
|
9
|
+
"@synapsor/runner",
|
|
10
|
+
"synapsor-runner",
|
|
11
|
+
"mcp",
|
|
12
|
+
"serve",
|
|
13
|
+
"--config",
|
|
14
|
+
"./examples/support-plan-credit/synapsor.runner.json",
|
|
15
|
+
"--store",
|
|
16
|
+
"./tmp/support-plan-credit/local.db"
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://schemas.synapsor.ai/synapsor.contract-tests.schema.json",
|
|
3
|
+
"version": 1,
|
|
4
|
+
"name": "support.propose_plan_credit generated contract boundary",
|
|
5
|
+
"tests": [
|
|
6
|
+
{
|
|
7
|
+
"id": "support.propose_plan_credit-operator-boundary",
|
|
8
|
+
"kind": "operator_boundary",
|
|
9
|
+
"capability": "support.propose_plan_credit"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"id": "support.propose_plan_credit-proposal-effect",
|
|
13
|
+
"kind": "proposal_effect",
|
|
14
|
+
"capability": "support.propose_plan_credit",
|
|
15
|
+
"expected": {
|
|
16
|
+
"action": "grant_plan_credit",
|
|
17
|
+
"operation": {
|
|
18
|
+
"kind": "update"
|
|
19
|
+
},
|
|
20
|
+
"allowed_fields": [
|
|
21
|
+
"plan_credit_cents",
|
|
22
|
+
"credit_reason"
|
|
23
|
+
],
|
|
24
|
+
"patch": {
|
|
25
|
+
"plan_credit_cents": {
|
|
26
|
+
"from_arg": "credit_cents"
|
|
27
|
+
},
|
|
28
|
+
"credit_reason": {
|
|
29
|
+
"from_arg": "reason"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"numeric_bounds": {
|
|
33
|
+
"plan_credit_cents": {
|
|
34
|
+
"minimum": 1,
|
|
35
|
+
"maximum": 50000
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"transition_guards": {},
|
|
39
|
+
"conflict_guard": {
|
|
40
|
+
"column": "updated_at"
|
|
41
|
+
},
|
|
42
|
+
"approval": {
|
|
43
|
+
"mode": "policy",
|
|
44
|
+
"policy": "support_propose_plan_credit_auto_approval",
|
|
45
|
+
"required_role": "support_reviewer"
|
|
46
|
+
},
|
|
47
|
+
"writeback": {
|
|
48
|
+
"mode": "direct_sql"
|
|
49
|
+
},
|
|
50
|
+
"max_rows": 1
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"id": "support.propose_plan_credit-kept-out-fields",
|
|
55
|
+
"kind": "hide_fields",
|
|
56
|
+
"capability": "support.propose_plan_credit",
|
|
57
|
+
"args": {
|
|
58
|
+
"customer_id": "replace-customer_id",
|
|
59
|
+
"credit_cents": 1,
|
|
60
|
+
"reason": "replace-reason"
|
|
61
|
+
},
|
|
62
|
+
"trusted_context": {
|
|
63
|
+
"tenant_id": "replace-with-test-tenant",
|
|
64
|
+
"principal": "contract_test"
|
|
65
|
+
},
|
|
66
|
+
"fields": [
|
|
67
|
+
"card_token",
|
|
68
|
+
"raw_payment_method",
|
|
69
|
+
"internal_risk_score",
|
|
70
|
+
"private_notes"
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"id": "support.propose_plan_credit-conflict-guard",
|
|
75
|
+
"kind": "conflict_guard",
|
|
76
|
+
"capability": "support.propose_plan_credit",
|
|
77
|
+
"expected": {
|
|
78
|
+
"column": "updated_at"
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"id": "support.propose_plan_credit-trusted-scope",
|
|
83
|
+
"kind": "trusted_scope",
|
|
84
|
+
"capability": "support.propose_plan_credit",
|
|
85
|
+
"expected": {
|
|
86
|
+
"context": "support_agent_context",
|
|
87
|
+
"tenant_key": "tenant_id",
|
|
88
|
+
"tenant_binding": "tenant_id",
|
|
89
|
+
"tenant_authority": {
|
|
90
|
+
"source": "environment",
|
|
91
|
+
"key": "SYNAPSOR_TENANT_ID",
|
|
92
|
+
"required": true
|
|
93
|
+
},
|
|
94
|
+
"principal_binding": "principal",
|
|
95
|
+
"principal_authority": {
|
|
96
|
+
"source": "environment",
|
|
97
|
+
"key": "SYNAPSOR_PRINCIPAL",
|
|
98
|
+
"required": true
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"id": "support.propose_plan_credit-evidence-required",
|
|
104
|
+
"kind": "evidence_requirement",
|
|
105
|
+
"capability": "support.propose_plan_credit",
|
|
106
|
+
"expected": {
|
|
107
|
+
"required": true,
|
|
108
|
+
"query_audit": true
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"id": "support.propose_plan_credit-approval-boundary",
|
|
113
|
+
"kind": "approval_boundary",
|
|
114
|
+
"capability": "support.propose_plan_credit",
|
|
115
|
+
"expected": {
|
|
116
|
+
"approval": {
|
|
117
|
+
"mode": "policy",
|
|
118
|
+
"policy": "support_propose_plan_credit_auto_approval",
|
|
119
|
+
"required_role": "support_reviewer"
|
|
120
|
+
},
|
|
121
|
+
"policy": {
|
|
122
|
+
"kind": "approval",
|
|
123
|
+
"limits": [
|
|
124
|
+
{
|
|
125
|
+
"kind": "count",
|
|
126
|
+
"max": 20,
|
|
127
|
+
"period": "day",
|
|
128
|
+
"scope": "tenant_policy"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"field": "plan_credit_cents",
|
|
132
|
+
"kind": "total",
|
|
133
|
+
"max": 100000,
|
|
134
|
+
"period": "day",
|
|
135
|
+
"scope": "tenant_policy"
|
|
136
|
+
}
|
|
137
|
+
],
|
|
138
|
+
"mode": "green",
|
|
139
|
+
"name": "support_propose_plan_credit_auto_approval",
|
|
140
|
+
"rules": [
|
|
141
|
+
{
|
|
142
|
+
"field": "plan_credit_cents",
|
|
143
|
+
"max": 2500
|
|
144
|
+
}
|
|
145
|
+
]
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"id": "support.propose_plan_credit-allowed-effect",
|
|
151
|
+
"kind": "tool_allow",
|
|
152
|
+
"capability": "support.propose_plan_credit",
|
|
153
|
+
"args": {
|
|
154
|
+
"customer_id": "replace-customer_id",
|
|
155
|
+
"credit_cents": 1,
|
|
156
|
+
"reason": "replace-reason"
|
|
157
|
+
},
|
|
158
|
+
"trusted_context": {
|
|
159
|
+
"tenant_id": "replace-with-test-tenant",
|
|
160
|
+
"principal": "contract_test"
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"id": "support.propose_plan_credit-other-tenant-denied",
|
|
165
|
+
"kind": "tool_deny",
|
|
166
|
+
"capability": "support.propose_plan_credit",
|
|
167
|
+
"args": {
|
|
168
|
+
"customer_id": "replace-with-other-tenant-customer_id",
|
|
169
|
+
"credit_cents": 1,
|
|
170
|
+
"reason": "replace-reason"
|
|
171
|
+
},
|
|
172
|
+
"trusted_context": {
|
|
173
|
+
"tenant_id": "replace-with-test-tenant",
|
|
174
|
+
"principal": "contract_test"
|
|
175
|
+
},
|
|
176
|
+
"expected_code": "NOT_FOUND_IN_TENANT"
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
"id": "support.propose_plan_credit-source-unchanged",
|
|
180
|
+
"kind": "source_unchanged_before_approval",
|
|
181
|
+
"capability": "support.propose_plan_credit",
|
|
182
|
+
"args": {
|
|
183
|
+
"customer_id": "replace-customer_id",
|
|
184
|
+
"credit_cents": 1,
|
|
185
|
+
"reason": "replace-reason"
|
|
186
|
+
},
|
|
187
|
+
"trusted_context": {
|
|
188
|
+
"tenant_id": "replace-with-test-tenant",
|
|
189
|
+
"principal": "contract_test"
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
"id": "support.propose_plan_credit-customer_id-constraints",
|
|
194
|
+
"kind": "argument_constraint",
|
|
195
|
+
"capability": "support.propose_plan_credit",
|
|
196
|
+
"argument": "customer_id",
|
|
197
|
+
"expected": {
|
|
198
|
+
"max_length": 128
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"id": "support.propose_plan_credit-credit_cents-constraints",
|
|
203
|
+
"kind": "argument_constraint",
|
|
204
|
+
"capability": "support.propose_plan_credit",
|
|
205
|
+
"argument": "credit_cents",
|
|
206
|
+
"expected": {
|
|
207
|
+
"minimum": 1,
|
|
208
|
+
"maximum": 50000
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"id": "support.propose_plan_credit-reason-constraints",
|
|
213
|
+
"kind": "argument_constraint",
|
|
214
|
+
"capability": "support.propose_plan_credit",
|
|
215
|
+
"argument": "reason",
|
|
216
|
+
"expected": {
|
|
217
|
+
"max_length": 500
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
]
|
|
221
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { defineCapability } from "@synapsor/runner/authoring";
|
|
2
|
+
|
|
3
|
+
// Disabled authoring source. Editing this file never changes active Runner tools.
|
|
4
|
+
export default defineCapability({
|
|
5
|
+
name: "support.propose_plan_credit",
|
|
6
|
+
description: "Propose one bounded support plan credit after reviewing customer evidence.",
|
|
7
|
+
kind: "proposal",
|
|
8
|
+
context: "support_agent_context",
|
|
9
|
+
source: "local_postgres",
|
|
10
|
+
subject: {
|
|
11
|
+
schema: "public", table: "customers", primary_key: "id",
|
|
12
|
+
tenant_key: "tenant_id", conflict_key: "updated_at",
|
|
13
|
+
},
|
|
14
|
+
args: {
|
|
15
|
+
customer_id: { type: "string", required: true, max_length: 128 },
|
|
16
|
+
credit_cents: { type: "number", required: true, minimum: 1, maximum: 50000 },
|
|
17
|
+
reason: { type: "string", required: true, max_length: 500 },
|
|
18
|
+
},
|
|
19
|
+
lookup: { id_from_arg: "customer_id" },
|
|
20
|
+
visible_fields: ["id", "tenant_id", "customer_id", "plan", "invoice_status", "support_ticket_reason", "plan_credit_cents", "credit_reason", "updated_at"],
|
|
21
|
+
kept_out_fields: ["card_token", "raw_payment_method", "internal_risk_score", "private_notes"],
|
|
22
|
+
evidence: { required: true, query_audit: true },
|
|
23
|
+
max_rows: 1,
|
|
24
|
+
proposal: {
|
|
25
|
+
action: "grant_plan_credit",
|
|
26
|
+
operation: { kind: "update" },
|
|
27
|
+
allowed_fields: ["plan_credit_cents", "credit_reason"],
|
|
28
|
+
patch: { plan_credit_cents: { from_arg: "credit_cents" }, credit_reason: { from_arg: "reason" } },
|
|
29
|
+
numeric_bounds: { plan_credit_cents: { minimum: 1, maximum: 50000 } },
|
|
30
|
+
conflict_guard: { column: "updated_at" },
|
|
31
|
+
approval: { mode: "policy", policy: "support_propose_plan_credit_auto_approval", required_role: "support_reviewer" },
|
|
32
|
+
writeback: { mode: "direct_sql" },
|
|
33
|
+
},
|
|
34
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# MCP audit fixtures
|
|
2
|
+
|
|
3
|
+
These deterministic fixtures exercise the public `synapsor-runner audit`
|
|
4
|
+
contract without a database, account, telemetry, or business-tool call.
|
|
5
|
+
|
|
6
|
+
- `dangerous-tools-list.json` contains raw SQL and model-callable commit
|
|
7
|
+
authority.
|
|
8
|
+
- `reviewed-proposal-tools-list.json` contains a semantic read and an exact
|
|
9
|
+
proposal boundary.
|
|
10
|
+
- `cursor-bypass-config.json` proves that a reviewed Synapsor server does not
|
|
11
|
+
govern a second model-visible server that still exposes `execute_sql`.
|
|
12
|
+
|
|
13
|
+
Static config auditing never launches either command in the Cursor fixture.
|
|
14
|
+
Live inspection requires one exact `--live-server` name and explicit `--yes`.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mcpServers": {
|
|
3
|
+
"synapsor": {
|
|
4
|
+
"type": "stdio",
|
|
5
|
+
"command": "npx",
|
|
6
|
+
"args": [
|
|
7
|
+
"-y",
|
|
8
|
+
"-p",
|
|
9
|
+
"@synapsor/runner@1.5.3",
|
|
10
|
+
"synapsor-runner",
|
|
11
|
+
"mcp",
|
|
12
|
+
"serve",
|
|
13
|
+
"--config",
|
|
14
|
+
"${workspaceFolder}/synapsor.runner.json",
|
|
15
|
+
"--store",
|
|
16
|
+
"${workspaceFolder}/.synapsor/local.db"
|
|
17
|
+
]
|
|
18
|
+
},
|
|
19
|
+
"legacy-database": {
|
|
20
|
+
"type": "stdio",
|
|
21
|
+
"command": "legacy-database-mcp",
|
|
22
|
+
"args": [],
|
|
23
|
+
"tools": [
|
|
24
|
+
{
|
|
25
|
+
"name": "execute_sql",
|
|
26
|
+
"description": "Execute arbitrary SQL.",
|
|
27
|
+
"inputSchema": {
|
|
28
|
+
"type": "object",
|
|
29
|
+
"properties": {
|
|
30
|
+
"sql": { "type": "string" }
|
|
31
|
+
},
|
|
32
|
+
"required": ["sql"]
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"jsonrpc": "2.0",
|
|
3
|
+
"id": 1,
|
|
4
|
+
"result": {
|
|
5
|
+
"tools": [
|
|
6
|
+
{
|
|
7
|
+
"name": "execute_sql",
|
|
8
|
+
"description": "Execute arbitrary SQL against the application database.",
|
|
9
|
+
"inputSchema": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"properties": {
|
|
12
|
+
"sql": { "type": "string" },
|
|
13
|
+
"tenant_id": { "type": "string" },
|
|
14
|
+
"table_name": { "type": "string" },
|
|
15
|
+
"where": { "type": "string" }
|
|
16
|
+
},
|
|
17
|
+
"required": ["sql"]
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "approve_and_apply_change",
|
|
22
|
+
"description": "Approve and apply a database change immediately.",
|
|
23
|
+
"inputSchema": {
|
|
24
|
+
"type": "object",
|
|
25
|
+
"properties": {
|
|
26
|
+
"change_id": { "type": "string" }
|
|
27
|
+
},
|
|
28
|
+
"required": ["change_id"]
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"jsonrpc": "2.0",
|
|
3
|
+
"id": 1,
|
|
4
|
+
"result": {
|
|
5
|
+
"tools": [
|
|
6
|
+
{
|
|
7
|
+
"name": "billing.inspect_invoice",
|
|
8
|
+
"description": "Inspect one tenant-scoped invoice through reviewed visible fields.",
|
|
9
|
+
"inputSchema": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"properties": {
|
|
12
|
+
"invoice_id": { "type": "string", "maxLength": 128 }
|
|
13
|
+
},
|
|
14
|
+
"required": ["invoice_id"]
|
|
15
|
+
},
|
|
16
|
+
"outputSchema": {
|
|
17
|
+
"type": "object",
|
|
18
|
+
"properties": {
|
|
19
|
+
"status": { "type": "string" },
|
|
20
|
+
"evidence_bundle_id": { "type": "string" }
|
|
21
|
+
},
|
|
22
|
+
"required": ["status", "evidence_bundle_id"]
|
|
23
|
+
},
|
|
24
|
+
"annotations": {
|
|
25
|
+
"readOnlyHint": true,
|
|
26
|
+
"destructiveHint": false
|
|
27
|
+
},
|
|
28
|
+
"x_synapsor_test_fixture": "billing-invoice-safe"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"name": "billing.propose_late_fee_waiver",
|
|
32
|
+
"description": "Create an exact evidence-backed proposal for review before trusted writeback.",
|
|
33
|
+
"inputSchema": {
|
|
34
|
+
"type": "object",
|
|
35
|
+
"properties": {
|
|
36
|
+
"invoice_id": { "type": "string", "maxLength": 128 },
|
|
37
|
+
"reason": { "type": "string", "maxLength": 500 }
|
|
38
|
+
},
|
|
39
|
+
"required": ["invoice_id", "reason"]
|
|
40
|
+
},
|
|
41
|
+
"outputSchema": {
|
|
42
|
+
"type": "object",
|
|
43
|
+
"properties": {
|
|
44
|
+
"status": { "type": "string" },
|
|
45
|
+
"proposal_id": { "type": "string" },
|
|
46
|
+
"receipt_hash": { "type": "string" },
|
|
47
|
+
"retryable": { "type": "boolean" },
|
|
48
|
+
"source_database_changed": { "type": "boolean" }
|
|
49
|
+
},
|
|
50
|
+
"required": ["status", "proposal_id", "source_database_changed"]
|
|
51
|
+
},
|
|
52
|
+
"annotations": {
|
|
53
|
+
"readOnlyHint": false,
|
|
54
|
+
"destructiveHint": false
|
|
55
|
+
},
|
|
56
|
+
"x_synapsor_test_fixture": "billing-waiver-proposal-safe"
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synapsor/runner",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.3",
|
|
4
4
|
"description": "Stop giving AI agents execute_sql; expose reviewed Postgres/MySQL MCP actions with proposals, approval, writeback, and replay.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -8,6 +8,14 @@
|
|
|
8
8
|
"synapsor-runner": "dist/cli.js"
|
|
9
9
|
},
|
|
10
10
|
"exports": {
|
|
11
|
+
"./authoring": {
|
|
12
|
+
"types": "./dist/authoring.d.ts",
|
|
13
|
+
"import": "./dist/authoring.mjs"
|
|
14
|
+
},
|
|
15
|
+
"./shadow": {
|
|
16
|
+
"types": "./dist/shadow.d.ts",
|
|
17
|
+
"import": "./dist/shadow.mjs"
|
|
18
|
+
},
|
|
11
19
|
"./runtime": {
|
|
12
20
|
"types": "./dist/runtime.d.ts",
|
|
13
21
|
"import": "./dist/runtime.mjs"
|
|
@@ -23,6 +31,12 @@
|
|
|
23
31
|
"dist/runtime.mjs",
|
|
24
32
|
"dist/runtime.d.ts",
|
|
25
33
|
"dist/runtime.d.ts.map",
|
|
34
|
+
"dist/authoring.mjs",
|
|
35
|
+
"dist/authoring.d.ts",
|
|
36
|
+
"dist/authoring.d.ts.map",
|
|
37
|
+
"dist/shadow.mjs",
|
|
38
|
+
"dist/shadow.d.ts",
|
|
39
|
+
"dist/shadow.d.ts.map",
|
|
26
40
|
"docs/**/*.md",
|
|
27
41
|
"examples/dangerous-mcp-tools.json",
|
|
28
42
|
"examples/app-owned-writeback/**",
|
|
@@ -65,10 +79,11 @@
|
|
|
65
79
|
"model-context-protocol"
|
|
66
80
|
],
|
|
67
81
|
"engines": {
|
|
68
|
-
"node": ">=22.
|
|
82
|
+
"node": ">=22.13.0"
|
|
69
83
|
},
|
|
70
84
|
"dependencies": {
|
|
71
85
|
"@modelcontextprotocol/sdk": "1.29.0",
|
|
86
|
+
"@synapsor/spec": "^1.4.2",
|
|
72
87
|
"jose": "6.2.3",
|
|
73
88
|
"mysql2": "^3.11.0",
|
|
74
89
|
"pdf-lib": "1.17.1",
|
|
@@ -76,7 +91,7 @@
|
|
|
76
91
|
"typescript": "5.9.3",
|
|
77
92
|
"vscode-languageserver": "9.0.1",
|
|
78
93
|
"vscode-languageserver-textdocument": "1.0.12",
|
|
79
|
-
"yaml": "2.8.
|
|
94
|
+
"yaml": "2.8.3",
|
|
80
95
|
"zod": "^3.25.0"
|
|
81
96
|
},
|
|
82
97
|
"devDependencies": {
|