synartesis 0.8.8 → 0.9.1
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 +179 -0
- package/README.md +90 -4
- package/dist/{chunk-JE7MOCZO.js → chunk-H4SPMXQW.js} +1875 -73
- package/dist/cli.js +776 -1026
- package/dist/proxy.js +189 -53
- package/manifests/aws-docs.yaml +26 -0
- package/manifests/brave.yaml +33 -0
- package/manifests/chrome-devtools.yaml +115 -0
- package/manifests/exa.yaml +20 -0
- package/manifests/fetch.yaml +20 -0
- package/manifests/github.yaml +67 -85
- package/manifests/playwright.yaml +106 -0
- package/manifests/tavily.yaml +27 -0
- package/package.json +4 -1
package/manifests/github.yaml
CHANGED
|
@@ -1,27 +1,34 @@
|
|
|
1
|
-
# Policy for GitHub's MCP server
|
|
1
|
+
# Policy for GitHub's MCP server, github/github-mcp-server, written against
|
|
2
|
+
# the tool reference in its README at v1.12.2.
|
|
2
3
|
#
|
|
3
|
-
# NOT verified against a live account.
|
|
4
|
-
#
|
|
5
|
-
# in before it met a real server and turned out to be
|
|
6
|
-
#
|
|
7
|
-
#
|
|
4
|
+
# NOT verified against a live account. Every name and argument below was read
|
|
5
|
+
# from GitHub's own documentation, which is exactly the position the
|
|
6
|
+
# filesystem policy was in before it met a real server and turned out to be
|
|
7
|
+
# wrong in one place. Run `synartesis check` against your own token before
|
|
8
|
+
# trusting it, and expect to correct at least one field.
|
|
8
9
|
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
10
|
+
# Why this was rewritten: 1.12 folded get_issue, update_issue, create_issue and
|
|
11
|
+
# get_pull_request into issue_read, issue_write and pull_request_read, and
|
|
12
|
+
# renamed update_pull_request's pull_number to pullNumber. The previous policy
|
|
13
|
+
# still named the old tools, and a policy that calls tools a server does not
|
|
14
|
+
# have used to stop the proxy starting -- so everyone who had wrapped GitHub
|
|
15
|
+
# and let it update was left with no GitHub at all. The proxy now holds such a
|
|
16
|
+
# rule instead of refusing to start, and this file names what 1.12 exposes.
|
|
12
17
|
#
|
|
13
|
-
# The honest limit of this adapter: GitHub has no ordinary-scope delete for
|
|
14
|
-
# things it creates. An issue can be closed but not un-created; a comment
|
|
15
|
-
# gone only if
|
|
18
|
+
# The honest limit of this adapter: GitHub has no ordinary-scope delete for
|
|
19
|
+
# most things it creates. An issue can be closed but not un-created; a comment
|
|
20
|
+
# is gone only if its author removes it; a published release stays published.
|
|
16
21
|
# Anything that puts a permanent, publicly visible record into the world is
|
|
17
|
-
#
|
|
22
|
+
# held rather than dressed up as reversible -- and every write this file does
|
|
23
|
+
# not name is held too, because an unlisted tool falls to the fail-closed
|
|
24
|
+
# default.
|
|
18
25
|
version: 1
|
|
19
26
|
|
|
20
27
|
servers:
|
|
21
28
|
github:
|
|
22
29
|
command: github-mcp-server
|
|
23
30
|
args: ["stdio"]
|
|
24
|
-
# Read from
|
|
31
|
+
# Read from where the server is started; never written into this file.
|
|
25
32
|
env:
|
|
26
33
|
GITHUB_PERSONAL_ACCESS_TOKEN: "${GITHUB_PERSONAL_ACCESS_TOKEN}"
|
|
27
34
|
# Nothing here has met a real github; every shape below comes from
|
|
@@ -30,50 +37,39 @@ servers:
|
|
|
30
37
|
|
|
31
38
|
tools:
|
|
32
39
|
# --- reads -------------------------------------------------------------
|
|
40
|
+
# 1.12 names most of its reads by suffix -- issue_read, pull_request_read,
|
|
41
|
+
# actions_get, projects_list -- as well as by the older prefixes.
|
|
33
42
|
- match: "github.get_*"
|
|
34
43
|
class: readonly
|
|
35
44
|
- match: "github.list_*"
|
|
36
45
|
class: readonly
|
|
37
46
|
- match: "github.search_*"
|
|
38
47
|
class: readonly
|
|
48
|
+
- match: "github.*_read"
|
|
49
|
+
class: readonly
|
|
50
|
+
- match: "github.*_get"
|
|
51
|
+
class: readonly
|
|
52
|
+
- match: "github.*_list"
|
|
53
|
+
class: readonly
|
|
54
|
+
|
|
55
|
+
# The one tool the `*_read` suffix would misread: it *marks* notifications
|
|
56
|
+
# read, which is a write. The longer name wins over the pattern above.
|
|
57
|
+
- match: "github.mark_all_notifications_read"
|
|
58
|
+
class: irreversible
|
|
59
|
+
gate: always
|
|
39
60
|
|
|
40
61
|
# --- issues ------------------------------------------------------------
|
|
41
62
|
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
|
|
63
|
+
# One tool that creates an issue or updates one, chosen by its `method`
|
|
64
|
+
# argument. An update could be undone from an issue_read taken first; a
|
|
65
|
+
# creation cannot be undone at all -- an issue can be closed but not
|
|
66
|
+
# un-created, and people were notified. A rule matches a tool by name alone,
|
|
67
|
+
# so it cannot tell the two apart, and treating the whole tool as undoable
|
|
68
|
+
# would promise an undo for every issue the agent opens. Held.
|
|
69
|
+
- match: "github.issue_write"
|
|
45
70
|
class: irreversible
|
|
46
71
|
gate: always
|
|
47
72
|
|
|
48
|
-
# get_issue returns labels and assignees as objects while update_issue takes
|
|
49
|
-
# bare names, so the inverse projects the one field it needs out of each.
|
|
50
|
-
# `[]` reads the same key from every element and does nothing else; it is
|
|
51
|
-
# still a path, not a transform.
|
|
52
|
-
- match: "github.update_issue"
|
|
53
|
-
class: reversible
|
|
54
|
-
snapshot:
|
|
55
|
-
tool: "github.get_issue"
|
|
56
|
-
args:
|
|
57
|
-
owner: "$.owner"
|
|
58
|
-
repo: "$.repo"
|
|
59
|
-
issue_number: "$.issue_number"
|
|
60
|
-
# What GitHub says when the thing is not there. Anything else the
|
|
61
|
-
# pre-read reports -- a permissions change, a rate limit -- is a failed
|
|
62
|
-
# snapshot rather than absence, and the write is refused instead of being
|
|
63
|
-
# offered for approval as a creation.
|
|
64
|
-
absent_when: ["Not Found", "404"]
|
|
65
|
-
inverse:
|
|
66
|
-
tool: "github.update_issue"
|
|
67
|
-
args:
|
|
68
|
-
owner: "$.owner"
|
|
69
|
-
repo: "$.repo"
|
|
70
|
-
issue_number: "$.issue_number"
|
|
71
|
-
title: "$snapshot.title"
|
|
72
|
-
body: "$snapshot.body"
|
|
73
|
-
state: "$snapshot.state"
|
|
74
|
-
labels: "$snapshot.labels[].name"
|
|
75
|
-
assignees: "$snapshot.assignees[].login"
|
|
76
|
-
|
|
77
73
|
- match: "github.add_issue_comment"
|
|
78
74
|
class: irreversible
|
|
79
75
|
gate: always
|
|
@@ -83,14 +79,17 @@ tools:
|
|
|
83
79
|
class: irreversible
|
|
84
80
|
gate: always
|
|
85
81
|
|
|
82
|
+
# pullNumber, not pull_number, in 1.12 -- the previous policy's inverse would
|
|
83
|
+
# have lost the one argument that says which pull request to put back.
|
|
86
84
|
- match: "github.update_pull_request"
|
|
87
85
|
class: reversible
|
|
88
86
|
snapshot:
|
|
89
|
-
tool: "github.
|
|
87
|
+
tool: "github.pull_request_read"
|
|
90
88
|
args:
|
|
89
|
+
method: "get"
|
|
91
90
|
owner: "$.owner"
|
|
92
91
|
repo: "$.repo"
|
|
93
|
-
|
|
92
|
+
pullNumber: "$.pullNumber"
|
|
94
93
|
# What GitHub says when the thing is not there. Anything else the
|
|
95
94
|
# pre-read reports -- a permissions change, a rate limit -- is a failed
|
|
96
95
|
# snapshot rather than absence, and the write is refused instead of being
|
|
@@ -101,7 +100,7 @@ tools:
|
|
|
101
100
|
args:
|
|
102
101
|
owner: "$.owner"
|
|
103
102
|
repo: "$.repo"
|
|
104
|
-
|
|
103
|
+
pullNumber: "$.pullNumber"
|
|
105
104
|
title: "$snapshot.title"
|
|
106
105
|
body: "$snapshot.body"
|
|
107
106
|
state: "$snapshot.state"
|
|
@@ -109,38 +108,14 @@ tools:
|
|
|
109
108
|
- match: "github.merge_pull_request"
|
|
110
109
|
class: irreversible
|
|
111
110
|
gate: always
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
gate: always
|
|
118
|
-
- match: "github.submit_pending_pull_request_review"
|
|
111
|
+
|
|
112
|
+
# Creates, submits or deletes a review, by `method`. A submitted review is
|
|
113
|
+
# public and cannot be withdrawn; held whole for the same reason issue_write
|
|
114
|
+
# is.
|
|
115
|
+
- match: "github.pull_request_review_write"
|
|
119
116
|
class: irreversible
|
|
120
117
|
gate: always
|
|
121
118
|
|
|
122
|
-
# A pending review is a draft only its author can see, so deleting one puts
|
|
123
|
-
# nothing into the world. Recreating it restores the draft but not the
|
|
124
|
-
# comments that were inside it, which is a compensation rather than a
|
|
125
|
-
# reversal, and undo will report it as unverified.
|
|
126
|
-
- match: "github.delete_pending_pull_request_review"
|
|
127
|
-
class: compensable
|
|
128
|
-
inverse:
|
|
129
|
-
tool: "github.create_pending_pull_request_review"
|
|
130
|
-
args:
|
|
131
|
-
owner: "$.owner"
|
|
132
|
-
repo: "$.repo"
|
|
133
|
-
pull_number: "$.pull_number"
|
|
134
|
-
|
|
135
|
-
- match: "github.create_pending_pull_request_review"
|
|
136
|
-
class: compensable
|
|
137
|
-
inverse:
|
|
138
|
-
tool: "github.delete_pending_pull_request_review"
|
|
139
|
-
args:
|
|
140
|
-
owner: "$.owner"
|
|
141
|
-
repo: "$.repo"
|
|
142
|
-
pull_number: "$.pull_number"
|
|
143
|
-
|
|
144
119
|
# --- file contents -----------------------------------------------------
|
|
145
120
|
|
|
146
121
|
# The sha must be the blob being replaced at the moment of the revert, which
|
|
@@ -172,6 +147,13 @@ tools:
|
|
|
172
147
|
sha: "$result.content.sha"
|
|
173
148
|
message: "Revert agent change to $.path"
|
|
174
149
|
|
|
150
|
+
# A commit removing the file. The contents are gone from the branch head and
|
|
151
|
+
# would have to be read first to be put back, which this server's read does
|
|
152
|
+
# not return in a form an inverse can use unchanged. Held.
|
|
153
|
+
- match: "github.delete_file"
|
|
154
|
+
class: irreversible
|
|
155
|
+
gate: always
|
|
156
|
+
|
|
175
157
|
# A multi-file push is one commit touching many paths. This format captures
|
|
176
158
|
# one pre-read per action, not one per path, so there is nothing honest to
|
|
177
159
|
# restore from.
|
|
@@ -188,13 +170,13 @@ tools:
|
|
|
188
170
|
- match: "github.create_repository"
|
|
189
171
|
class: irreversible
|
|
190
172
|
gate: always
|
|
191
|
-
- match: "github.
|
|
173
|
+
- match: "github.delete_repository"
|
|
192
174
|
class: irreversible
|
|
193
175
|
gate: always
|
|
194
176
|
|
|
195
|
-
#
|
|
196
|
-
#
|
|
197
|
-
#
|
|
198
|
-
#
|
|
199
|
-
#
|
|
200
|
-
#
|
|
177
|
+
# Written for github-mcp-server v1.12.2. A later version can keep a tool's name
|
|
178
|
+
# and change what it takes, which would leave the policy above describing
|
|
179
|
+
# something else -- and undo would still produce an answer. `synartesis pin`
|
|
180
|
+
# prints a `pins:` block for the server you actually have; with it pasted in, a
|
|
181
|
+
# tool whose shape has moved stops the proxy at startup instead of being
|
|
182
|
+
# quietly trusted.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Policy for @playwright/mcp.
|
|
2
|
+
#
|
|
3
|
+
# Written against 1.64.0 from the server's own tools/list, read-only hints and
|
|
4
|
+
# all.
|
|
5
|
+
#
|
|
6
|
+
# Nothing a browser does can be undone. There is no inverse for a click, a
|
|
7
|
+
# submitted form or a page left behind. Holding every one of them made this
|
|
8
|
+
# server unusable behind Synartesis, since an agent driving a page clicks
|
|
9
|
+
# dozens of times a minute. So this policy records instead of holding: each
|
|
10
|
+
# interaction is classed as a call that cannot be undone, so every screen says
|
|
11
|
+
# so, and is written to the journal with its arguments. `show` gives you the
|
|
12
|
+
# whole session afterwards. It does not ask before each one.
|
|
13
|
+
#
|
|
14
|
+
# Three tools are still held, because each reaches past the page. Running code
|
|
15
|
+
# the agent wrote has the full reach of the browser context, and it is how a
|
|
16
|
+
# page's contents become an arbitrary action. A file upload sends something
|
|
17
|
+
# from your disk to whoever runs the page, and so does a drop, which carries
|
|
18
|
+
# files too. A tool this file does not mention is held until a rule says
|
|
19
|
+
# otherwise, the same as everywhere else, so a new tool in a later version is
|
|
20
|
+
# not let through by accident.
|
|
21
|
+
#
|
|
22
|
+
# Recorded is not reversible. If a page is somewhere an agent's click could do
|
|
23
|
+
# real harm -- your bank, a production admin panel -- this policy does not
|
|
24
|
+
# protect you from that click. It tells you it happened.
|
|
25
|
+
version: 1
|
|
26
|
+
|
|
27
|
+
servers:
|
|
28
|
+
playwright:
|
|
29
|
+
command: npx
|
|
30
|
+
args: ["-y", "@playwright/mcp@latest"]
|
|
31
|
+
provenance: live
|
|
32
|
+
|
|
33
|
+
tools:
|
|
34
|
+
# --- reads: the tools the server itself marks read-only ------------------
|
|
35
|
+
- match: "playwright.browser_snapshot"
|
|
36
|
+
class: readonly
|
|
37
|
+
- match: "playwright.browser_take_screenshot"
|
|
38
|
+
class: readonly
|
|
39
|
+
- match: "playwright.browser_console_messages"
|
|
40
|
+
class: readonly
|
|
41
|
+
- match: "playwright.browser_network_requests"
|
|
42
|
+
class: readonly
|
|
43
|
+
- match: "playwright.browser_network_request"
|
|
44
|
+
class: readonly
|
|
45
|
+
- match: "playwright.browser_find"
|
|
46
|
+
class: readonly
|
|
47
|
+
- match: "playwright.browser_wait_for"
|
|
48
|
+
class: readonly
|
|
49
|
+
|
|
50
|
+
# --- held: each reaches past the page -------------------------------------
|
|
51
|
+
- match: "playwright.browser_run_code_unsafe"
|
|
52
|
+
class: irreversible
|
|
53
|
+
gate: always
|
|
54
|
+
- match: "playwright.browser_evaluate"
|
|
55
|
+
class: irreversible
|
|
56
|
+
gate: always
|
|
57
|
+
- match: "playwright.browser_file_upload"
|
|
58
|
+
class: irreversible
|
|
59
|
+
gate: always
|
|
60
|
+
- match: "playwright.browser_drop"
|
|
61
|
+
class: irreversible
|
|
62
|
+
gate: always
|
|
63
|
+
|
|
64
|
+
# --- recorded, not held: what driving a page is ---------------------------
|
|
65
|
+
- match: "playwright.browser_navigate"
|
|
66
|
+
class: irreversible
|
|
67
|
+
gate: never
|
|
68
|
+
- match: "playwright.browser_navigate_back"
|
|
69
|
+
class: irreversible
|
|
70
|
+
gate: never
|
|
71
|
+
- match: "playwright.browser_click"
|
|
72
|
+
class: irreversible
|
|
73
|
+
gate: never
|
|
74
|
+
- match: "playwright.browser_type"
|
|
75
|
+
class: irreversible
|
|
76
|
+
gate: never
|
|
77
|
+
- match: "playwright.browser_fill_form"
|
|
78
|
+
class: irreversible
|
|
79
|
+
gate: never
|
|
80
|
+
- match: "playwright.browser_press_key"
|
|
81
|
+
class: irreversible
|
|
82
|
+
gate: never
|
|
83
|
+
- match: "playwright.browser_select_option"
|
|
84
|
+
class: irreversible
|
|
85
|
+
gate: never
|
|
86
|
+
- match: "playwright.browser_hover"
|
|
87
|
+
class: irreversible
|
|
88
|
+
gate: never
|
|
89
|
+
- match: "playwright.browser_drag"
|
|
90
|
+
class: irreversible
|
|
91
|
+
gate: never
|
|
92
|
+
- match: "playwright.browser_handle_dialog"
|
|
93
|
+
class: irreversible
|
|
94
|
+
gate: never
|
|
95
|
+
- match: "playwright.browser_tabs"
|
|
96
|
+
class: irreversible
|
|
97
|
+
gate: never
|
|
98
|
+
- match: "playwright.browser_resize"
|
|
99
|
+
class: irreversible
|
|
100
|
+
gate: never
|
|
101
|
+
- match: "playwright.browser_emulate_media"
|
|
102
|
+
class: irreversible
|
|
103
|
+
gate: never
|
|
104
|
+
- match: "playwright.browser_close"
|
|
105
|
+
class: irreversible
|
|
106
|
+
gate: never
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Policy for tavily-mcp.
|
|
2
|
+
#
|
|
3
|
+
# Written against 0.2.22 from the server's own tools/list.
|
|
4
|
+
#
|
|
5
|
+
# Search, extract, crawl, map and research all read the web and change
|
|
6
|
+
# nothing. The server does not mark them read-only.
|
|
7
|
+
#
|
|
8
|
+
# A tool a later version adds is held until a rule says what it does.
|
|
9
|
+
version: 1
|
|
10
|
+
|
|
11
|
+
servers:
|
|
12
|
+
tavily:
|
|
13
|
+
command: npx
|
|
14
|
+
args: ["-y", "tavily-mcp"]
|
|
15
|
+
provenance: live
|
|
16
|
+
|
|
17
|
+
tools:
|
|
18
|
+
- match: "tavily.tavily_search"
|
|
19
|
+
class: readonly
|
|
20
|
+
- match: "tavily.tavily_extract"
|
|
21
|
+
class: readonly
|
|
22
|
+
- match: "tavily.tavily_crawl"
|
|
23
|
+
class: readonly
|
|
24
|
+
- match: "tavily.tavily_map"
|
|
25
|
+
class: readonly
|
|
26
|
+
- match: "tavily.tavily_research"
|
|
27
|
+
class: readonly
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "synartesis",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"description": "An undo layer for AI agents.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -58,6 +58,8 @@
|
|
|
58
58
|
"demo": "tsup --silent && ./demo/filesystem-demo.sh",
|
|
59
59
|
"demo:memory": "tsup --silent && ./demo/memory-demo.sh",
|
|
60
60
|
"check": "pnpm build && pnpm typecheck && pnpm lint && pnpm test",
|
|
61
|
+
"stress": "tsup --silent && SYNARTESIS_STRESS_SESSIONS=500 SYNARTESIS_KILL_ROUNDS=25 SYNARTESIS_RACE_ROUNDS=10 vitest run tests/stress-undo.test.ts tests/kill-undo.test.ts tests/race-approval.test.ts",
|
|
62
|
+
"coverage": "tsup --silent && vitest run --testTimeout=240000 --coverage --coverage.provider=v8 --coverage.include='src/**' --coverage.reportOnFailure",
|
|
61
63
|
"prepublishOnly": "pnpm check"
|
|
62
64
|
},
|
|
63
65
|
"dependencies": {
|
|
@@ -93,6 +95,7 @@
|
|
|
93
95
|
"@types/react": "^19.3.0",
|
|
94
96
|
"@types/react-dom": "^19.3.0",
|
|
95
97
|
"@vitejs/plugin-react": "^6.1.1",
|
|
98
|
+
"@vitest/coverage-v8": "4.1.11",
|
|
96
99
|
"electron": "^44.3.0",
|
|
97
100
|
"electron-builder": "^26.15.3",
|
|
98
101
|
"eslint": "^10.8.1",
|