synartesis 0.1.0
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/LICENSE +21 -0
- package/README.md +501 -0
- package/dist/chunk-K3QIPVBY.js +85 -0
- package/dist/chunk-K3QIPVBY.js.map +1 -0
- package/dist/chunk-X4VQNEP5.js +1383 -0
- package/dist/chunk-X4VQNEP5.js.map +1 -0
- package/dist/cli.js +1708 -0
- package/dist/cli.js.map +1 -0
- package/dist/demo-agent.js +67 -0
- package/dist/demo-agent.js.map +1 -0
- package/dist/proxy.js +913 -0
- package/dist/proxy.js.map +1 -0
- package/dist/toy-crm.js +293 -0
- package/dist/toy-crm.js.map +1 -0
- package/manifests/filesystem.yaml +97 -0
- package/manifests/git.yaml +77 -0
- package/manifests/github.yaml +175 -0
- package/manifests/memory.yaml +96 -0
- package/manifests/toy-crm.yaml +66 -0
- package/package.json +67 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Policy for mcp-server-git, the official git server, run through uvx.
|
|
2
|
+
#
|
|
3
|
+
# Verified against the real server on a real repository.
|
|
4
|
+
#
|
|
5
|
+
# The finding worth carrying away from writing this one: nearly every read this
|
|
6
|
+
# server offers answers in prose meant for a person -- git_status says "On
|
|
7
|
+
# branch main", not {"branch": "main"}. A snapshot is only useful if something
|
|
8
|
+
# can be read back out of it by path, so almost nothing here can be inverted
|
|
9
|
+
# from a captured state, however reversible the underlying git operation is.
|
|
10
|
+
# The limit is the server's, not git's, and pretending otherwise would produce
|
|
11
|
+
# a policy that reports work as undone without having undone it.
|
|
12
|
+
version: 1
|
|
13
|
+
|
|
14
|
+
servers:
|
|
15
|
+
git:
|
|
16
|
+
command: uvx
|
|
17
|
+
args: ["--from", "mcp-server-git", "mcp-server-git"]
|
|
18
|
+
|
|
19
|
+
tools:
|
|
20
|
+
# --- reads -------------------------------------------------------------
|
|
21
|
+
- match: "git.git_status"
|
|
22
|
+
class: readonly
|
|
23
|
+
- match: "git.git_diff"
|
|
24
|
+
class: readonly
|
|
25
|
+
- match: "git.git_diff_staged"
|
|
26
|
+
class: readonly
|
|
27
|
+
- match: "git.git_diff_unstaged"
|
|
28
|
+
class: readonly
|
|
29
|
+
- match: "git.git_log"
|
|
30
|
+
class: readonly
|
|
31
|
+
- match: "git.git_show"
|
|
32
|
+
class: readonly
|
|
33
|
+
- match: "git.git_branch"
|
|
34
|
+
class: readonly
|
|
35
|
+
|
|
36
|
+
# --- the index ---------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
# git_reset here unstages everything, not only what this call staged, so
|
|
39
|
+
# undoing an add can unstage work a person staged by hand beforehand. It is
|
|
40
|
+
# recorded as a compensation for that reason, and undo says so.
|
|
41
|
+
- match: "git.git_add"
|
|
42
|
+
class: compensable
|
|
43
|
+
inverse:
|
|
44
|
+
tool: "git.git_reset"
|
|
45
|
+
args:
|
|
46
|
+
repo_path: "$.repo_path"
|
|
47
|
+
|
|
48
|
+
# Unstaging destroys nothing: every change is still in the working tree, and
|
|
49
|
+
# re-staging is one command. Gating it would spend a person's attention on
|
|
50
|
+
# the cheapest operation here and leave less of it for the commit below.
|
|
51
|
+
- match: "git.git_reset"
|
|
52
|
+
class: irreversible
|
|
53
|
+
gate: never
|
|
54
|
+
|
|
55
|
+
# --- history -----------------------------------------------------------
|
|
56
|
+
|
|
57
|
+
# This server offers no reset, no revert and no way to move a branch, so
|
|
58
|
+
# nothing it exposes can take a commit back. Held for a person.
|
|
59
|
+
- match: "git.git_commit"
|
|
60
|
+
class: irreversible
|
|
61
|
+
gate: always
|
|
62
|
+
|
|
63
|
+
# No delete-branch tool exists here either. `git branch -d` removes one by
|
|
64
|
+
# hand in a second, which is precisely the sentence undo cannot say for you.
|
|
65
|
+
- match: "git.git_create_branch"
|
|
66
|
+
class: irreversible
|
|
67
|
+
gate: always
|
|
68
|
+
|
|
69
|
+
# Checking out changes no history and destroys nothing: git refuses outright
|
|
70
|
+
# when the working tree would be lost. It cannot be undone through this
|
|
71
|
+
# server because no read here reports the current branch as data, so it is
|
|
72
|
+
# recorded honestly as irreversible and deliberately not gated. A gate on
|
|
73
|
+
# every branch switch is a gate people learn to approve without reading, and
|
|
74
|
+
# that costs more than it buys on the commit above.
|
|
75
|
+
- match: "git.git_checkout"
|
|
76
|
+
class: irreversible
|
|
77
|
+
gate: never
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# Policy for GitHub's MCP server.
|
|
2
|
+
#
|
|
3
|
+
# NOT verified against a live account. Everything here is derived from GitHub's
|
|
4
|
+
# documented API shapes, which is exactly the position the filesystem policy was
|
|
5
|
+
# in before it met a real server and turned out to be wrong in one place. Run
|
|
6
|
+
# `synartesis check --manifest manifests/github.yaml` against your own token
|
|
7
|
+
# before trusting it, and expect to correct at least one field.
|
|
8
|
+
#
|
|
9
|
+
# The npm package @modelcontextprotocol/server-github is deprecated. The
|
|
10
|
+
# supported server is github/github-mcp-server. Synartesis speaks stdio only,
|
|
11
|
+
# so use the local binary rather than GitHub's hosted remote server.
|
|
12
|
+
#
|
|
13
|
+
# The honest limit of this adapter: GitHub has no ordinary-scope delete for most
|
|
14
|
+
# things it creates. An issue can be closed but not un-created; a comment is
|
|
15
|
+
# gone only if the author removes it; a published release stays published.
|
|
16
|
+
# Anything that puts a permanent, publicly visible record into the world is
|
|
17
|
+
# gated rather than dressed up as reversible.
|
|
18
|
+
version: 1
|
|
19
|
+
|
|
20
|
+
servers:
|
|
21
|
+
github:
|
|
22
|
+
command: github-mcp-server
|
|
23
|
+
args: ["stdio"]
|
|
24
|
+
# Read from your shell; never written into this file.
|
|
25
|
+
env:
|
|
26
|
+
GITHUB_PERSONAL_ACCESS_TOKEN: "${GITHUB_PERSONAL_ACCESS_TOKEN}"
|
|
27
|
+
|
|
28
|
+
tools:
|
|
29
|
+
# --- reads -------------------------------------------------------------
|
|
30
|
+
- match: "github.get_*"
|
|
31
|
+
class: readonly
|
|
32
|
+
- match: "github.list_*"
|
|
33
|
+
class: readonly
|
|
34
|
+
- match: "github.search_*"
|
|
35
|
+
class: readonly
|
|
36
|
+
|
|
37
|
+
# --- issues ------------------------------------------------------------
|
|
38
|
+
|
|
39
|
+
# An issue cannot be deleted through the API, only closed. Closing is not
|
|
40
|
+
# the same as never having existed: people were notified.
|
|
41
|
+
- match: "github.create_issue"
|
|
42
|
+
class: irreversible
|
|
43
|
+
gate: always
|
|
44
|
+
|
|
45
|
+
# get_issue returns labels and assignees as objects while update_issue takes
|
|
46
|
+
# bare names, so the inverse projects the one field it needs out of each.
|
|
47
|
+
# `[]` reads the same key from every element and does nothing else; it is
|
|
48
|
+
# still a path, not a transform.
|
|
49
|
+
- match: "github.update_issue"
|
|
50
|
+
class: reversible
|
|
51
|
+
snapshot:
|
|
52
|
+
tool: "github.get_issue"
|
|
53
|
+
args:
|
|
54
|
+
owner: "$.owner"
|
|
55
|
+
repo: "$.repo"
|
|
56
|
+
issue_number: "$.issue_number"
|
|
57
|
+
inverse:
|
|
58
|
+
tool: "github.update_issue"
|
|
59
|
+
args:
|
|
60
|
+
owner: "$.owner"
|
|
61
|
+
repo: "$.repo"
|
|
62
|
+
issue_number: "$.issue_number"
|
|
63
|
+
title: "$snapshot.title"
|
|
64
|
+
body: "$snapshot.body"
|
|
65
|
+
state: "$snapshot.state"
|
|
66
|
+
labels: "$snapshot.labels[].name"
|
|
67
|
+
assignees: "$snapshot.assignees[].login"
|
|
68
|
+
|
|
69
|
+
- match: "github.add_issue_comment"
|
|
70
|
+
class: irreversible
|
|
71
|
+
gate: always
|
|
72
|
+
|
|
73
|
+
# --- pull requests -----------------------------------------------------
|
|
74
|
+
- match: "github.create_pull_request"
|
|
75
|
+
class: irreversible
|
|
76
|
+
gate: always
|
|
77
|
+
|
|
78
|
+
- match: "github.update_pull_request"
|
|
79
|
+
class: reversible
|
|
80
|
+
snapshot:
|
|
81
|
+
tool: "github.get_pull_request"
|
|
82
|
+
args:
|
|
83
|
+
owner: "$.owner"
|
|
84
|
+
repo: "$.repo"
|
|
85
|
+
pull_number: "$.pull_number"
|
|
86
|
+
inverse:
|
|
87
|
+
tool: "github.update_pull_request"
|
|
88
|
+
args:
|
|
89
|
+
owner: "$.owner"
|
|
90
|
+
repo: "$.repo"
|
|
91
|
+
pull_number: "$.pull_number"
|
|
92
|
+
title: "$snapshot.title"
|
|
93
|
+
body: "$snapshot.body"
|
|
94
|
+
state: "$snapshot.state"
|
|
95
|
+
|
|
96
|
+
- match: "github.merge_pull_request"
|
|
97
|
+
class: irreversible
|
|
98
|
+
gate: always
|
|
99
|
+
- match: "github.create_pull_request_review"
|
|
100
|
+
class: irreversible
|
|
101
|
+
gate: always
|
|
102
|
+
- match: "github.create_and_submit_pull_request_review"
|
|
103
|
+
class: irreversible
|
|
104
|
+
gate: always
|
|
105
|
+
- match: "github.submit_pending_pull_request_review"
|
|
106
|
+
class: irreversible
|
|
107
|
+
gate: always
|
|
108
|
+
|
|
109
|
+
# A pending review is a draft only its author can see, so deleting one puts
|
|
110
|
+
# nothing into the world. Recreating it restores the draft but not the
|
|
111
|
+
# comments that were inside it, which is a compensation rather than a
|
|
112
|
+
# reversal, and undo will report it as unverified.
|
|
113
|
+
- match: "github.delete_pending_pull_request_review"
|
|
114
|
+
class: compensable
|
|
115
|
+
inverse:
|
|
116
|
+
tool: "github.create_pending_pull_request_review"
|
|
117
|
+
args:
|
|
118
|
+
owner: "$.owner"
|
|
119
|
+
repo: "$.repo"
|
|
120
|
+
pull_number: "$.pull_number"
|
|
121
|
+
|
|
122
|
+
- match: "github.create_pending_pull_request_review"
|
|
123
|
+
class: compensable
|
|
124
|
+
inverse:
|
|
125
|
+
tool: "github.delete_pending_pull_request_review"
|
|
126
|
+
args:
|
|
127
|
+
owner: "$.owner"
|
|
128
|
+
repo: "$.repo"
|
|
129
|
+
pull_number: "$.pull_number"
|
|
130
|
+
|
|
131
|
+
# --- file contents -----------------------------------------------------
|
|
132
|
+
|
|
133
|
+
# The sha must be the blob being replaced at the moment of the revert, which
|
|
134
|
+
# is the one this very call created, not the one it replaced. Passing
|
|
135
|
+
# $snapshot.sha here is the natural mistake and GitHub rejects it as a
|
|
136
|
+
# conflict.
|
|
137
|
+
- match: "github.create_or_update_file"
|
|
138
|
+
class: reversible
|
|
139
|
+
snapshot:
|
|
140
|
+
tool: "github.get_file_contents"
|
|
141
|
+
args:
|
|
142
|
+
owner: "$.owner"
|
|
143
|
+
repo: "$.repo"
|
|
144
|
+
path: "$.path"
|
|
145
|
+
ref: "$.branch"
|
|
146
|
+
inverse:
|
|
147
|
+
tool: "github.create_or_update_file"
|
|
148
|
+
args:
|
|
149
|
+
owner: "$.owner"
|
|
150
|
+
repo: "$.repo"
|
|
151
|
+
path: "$.path"
|
|
152
|
+
branch: "$.branch"
|
|
153
|
+
content: "$snapshot.content"
|
|
154
|
+
sha: "$result.content.sha"
|
|
155
|
+
message: "Revert agent change to $.path"
|
|
156
|
+
|
|
157
|
+
# A multi-file push is one commit touching many paths. This format captures
|
|
158
|
+
# one pre-read per action, not one per path, so there is nothing honest to
|
|
159
|
+
# restore from.
|
|
160
|
+
- match: "github.push_files"
|
|
161
|
+
class: irreversible
|
|
162
|
+
gate: always
|
|
163
|
+
|
|
164
|
+
- match: "github.create_branch"
|
|
165
|
+
class: irreversible
|
|
166
|
+
gate: always
|
|
167
|
+
- match: "github.fork_repository"
|
|
168
|
+
class: irreversible
|
|
169
|
+
gate: always
|
|
170
|
+
- match: "github.create_repository"
|
|
171
|
+
class: irreversible
|
|
172
|
+
gate: always
|
|
173
|
+
- match: "github.create_release"
|
|
174
|
+
class: irreversible
|
|
175
|
+
gate: always
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Policy for @modelcontextprotocol/server-memory, the knowledge graph an agent
|
|
2
|
+
# keeps about you between sessions.
|
|
3
|
+
#
|
|
4
|
+
# Verified against the real server: every tool named here was listed by it, and
|
|
5
|
+
# the shapes below were read off its own responses rather than from docs.
|
|
6
|
+
#
|
|
7
|
+
# This is the server the taxonomy fits best. Almost everything it does has an
|
|
8
|
+
# exact opposite sitting next to it in the same toolbox, which is what
|
|
9
|
+
# compensable means. Two things do not, and they are gated rather than
|
|
10
|
+
# approximated.
|
|
11
|
+
version: 1
|
|
12
|
+
|
|
13
|
+
servers:
|
|
14
|
+
memory:
|
|
15
|
+
command: npx
|
|
16
|
+
args: ["-y", "@modelcontextprotocol/server-memory"]
|
|
17
|
+
# Where the graph lives. Point it wherever your client already points it,
|
|
18
|
+
# or the agent will remember into a different file than it reads from.
|
|
19
|
+
env:
|
|
20
|
+
MEMORY_FILE_PATH: "${MEMORY_FILE_PATH}"
|
|
21
|
+
|
|
22
|
+
tools:
|
|
23
|
+
# --- reads -------------------------------------------------------------
|
|
24
|
+
- match: "memory.read_graph"
|
|
25
|
+
class: readonly
|
|
26
|
+
- match: "memory.search_nodes"
|
|
27
|
+
class: readonly
|
|
28
|
+
- match: "memory.open_nodes"
|
|
29
|
+
class: readonly
|
|
30
|
+
|
|
31
|
+
# --- writes ------------------------------------------------------------
|
|
32
|
+
|
|
33
|
+
# The inverse names the result rather than the arguments, and the difference
|
|
34
|
+
# matters: this server silently ignores an entity that already exists, so
|
|
35
|
+
# undoing by argument would delete a Grace who was there long before the
|
|
36
|
+
# agent ran. The result carries only what was actually created.
|
|
37
|
+
#
|
|
38
|
+
# $result.entities, not $result: this server answers with both a text block
|
|
39
|
+
# holding a bare array and a structuredContent object wrapping it, and
|
|
40
|
+
# structured data wins over re-parsed text. Written against the text block,
|
|
41
|
+
# the first version of this policy resolved to nothing and undo halted. It is
|
|
42
|
+
# the same mistake the filesystem policy made, and the reason neither of them
|
|
43
|
+
# can be trusted until it has met a real server.
|
|
44
|
+
#
|
|
45
|
+
# $result is the structured block, not the text one, and here the two
|
|
46
|
+
# disagree: the text is a bare list of entities while structuredContent wraps
|
|
47
|
+
# it as {"entities": [...]}. The structured block is the machine-readable
|
|
48
|
+
# contract, so that is the one a path walks. Writing $result[].name here is
|
|
49
|
+
# the natural mistake, and it was the first thing this policy got wrong
|
|
50
|
+
# against the live server.
|
|
51
|
+
- match: "memory.create_entities"
|
|
52
|
+
class: compensable
|
|
53
|
+
inverse:
|
|
54
|
+
tool: "memory.delete_entities"
|
|
55
|
+
args:
|
|
56
|
+
entityNames: "$result.entities[].name"
|
|
57
|
+
|
|
58
|
+
- match: "memory.create_relations"
|
|
59
|
+
class: compensable
|
|
60
|
+
inverse:
|
|
61
|
+
tool: "memory.delete_relations"
|
|
62
|
+
args:
|
|
63
|
+
relations: "$result.relations"
|
|
64
|
+
|
|
65
|
+
# The one place this policy over-reaches, and it is written down rather than
|
|
66
|
+
# hidden: delete_relations answers in prose, so the inverse has to work from
|
|
67
|
+
# the arguments. Undoing it re-creates every relation the call named,
|
|
68
|
+
# including any that were already absent when it ran.
|
|
69
|
+
- match: "memory.delete_relations"
|
|
70
|
+
class: compensable
|
|
71
|
+
inverse:
|
|
72
|
+
tool: "memory.create_relations"
|
|
73
|
+
args:
|
|
74
|
+
relations: "$.relations"
|
|
75
|
+
|
|
76
|
+
# Deleting an entity also deletes every relation touching it. open_nodes can
|
|
77
|
+
# capture both beforehand, but a policy declares one inverse, and one call
|
|
78
|
+
# cannot put back both the entities and their relations. Restoring half of a
|
|
79
|
+
# graph and reporting it as undone is the exact failure this product exists
|
|
80
|
+
# to prevent, so it asks instead.
|
|
81
|
+
- match: "memory.delete_entities"
|
|
82
|
+
class: irreversible
|
|
83
|
+
gate: always
|
|
84
|
+
|
|
85
|
+
# add_observations and delete_observations are exact opposites that disagree
|
|
86
|
+
# about what to call the same field: one takes `observations[].contents`, the
|
|
87
|
+
# other `deletions[].observations`. A path can read a field and cannot rename
|
|
88
|
+
# one, and the manifest is deliberately not a language, so this inverse
|
|
89
|
+
# cannot be written here at all. That is a limit of the format, stated rather
|
|
90
|
+
# than papered over.
|
|
91
|
+
- match: "memory.add_observations"
|
|
92
|
+
class: irreversible
|
|
93
|
+
gate: always
|
|
94
|
+
- match: "memory.delete_observations"
|
|
95
|
+
class: irreversible
|
|
96
|
+
gate: always
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Policy for the toy CRM fixture. Every class in the taxonomy appears here, so
|
|
2
|
+
# this doubles as the worked example of the manifest format.
|
|
3
|
+
version: 1
|
|
4
|
+
|
|
5
|
+
servers:
|
|
6
|
+
crm:
|
|
7
|
+
command: node
|
|
8
|
+
args: ["dist/toy-crm.js"]
|
|
9
|
+
|
|
10
|
+
tools:
|
|
11
|
+
- match: "crm.get_customer"
|
|
12
|
+
class: readonly
|
|
13
|
+
|
|
14
|
+
# The id is assigned by the server, so it is only knowable from the result.
|
|
15
|
+
- match: "crm.create_customer"
|
|
16
|
+
class: compensable
|
|
17
|
+
inverse:
|
|
18
|
+
tool: "crm.delete_customer"
|
|
19
|
+
args:
|
|
20
|
+
id: "$result.id"
|
|
21
|
+
|
|
22
|
+
# A patch, so the inverse has to restore every field rather than re-apply the
|
|
23
|
+
# patch: fields the agent did not touch must still come back unchanged if the
|
|
24
|
+
# same record is updated twice in one run.
|
|
25
|
+
- match: "crm.update_customer"
|
|
26
|
+
class: reversible
|
|
27
|
+
snapshot:
|
|
28
|
+
tool: "crm.get_customer"
|
|
29
|
+
args:
|
|
30
|
+
id: "$.id"
|
|
31
|
+
inverse:
|
|
32
|
+
tool: "crm.update_customer"
|
|
33
|
+
args:
|
|
34
|
+
id: "$.id"
|
|
35
|
+
name: "$snapshot.name"
|
|
36
|
+
email: "$snapshot.email"
|
|
37
|
+
plan: "$snapshot.plan"
|
|
38
|
+
notes: "$snapshot.notes"
|
|
39
|
+
|
|
40
|
+
# Reversible rather than irreversible because the pre-read captures the whole
|
|
41
|
+
# record and restore_customer puts it back under its original id.
|
|
42
|
+
- match: "crm.delete_customer"
|
|
43
|
+
class: reversible
|
|
44
|
+
snapshot:
|
|
45
|
+
tool: "crm.get_customer"
|
|
46
|
+
args:
|
|
47
|
+
id: "$.id"
|
|
48
|
+
inverse:
|
|
49
|
+
tool: "crm.restore_customer"
|
|
50
|
+
args:
|
|
51
|
+
id: "$snapshot.id"
|
|
52
|
+
name: "$snapshot.name"
|
|
53
|
+
email: "$snapshot.email"
|
|
54
|
+
plan: "$snapshot.plan"
|
|
55
|
+
notes: "$snapshot.notes"
|
|
56
|
+
|
|
57
|
+
- match: "crm.restore_customer"
|
|
58
|
+
class: compensable
|
|
59
|
+
inverse:
|
|
60
|
+
tool: "crm.delete_customer"
|
|
61
|
+
args:
|
|
62
|
+
id: "$.id"
|
|
63
|
+
|
|
64
|
+
- match: "crm.send_email"
|
|
65
|
+
class: irreversible
|
|
66
|
+
gate: always
|
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "synartesis",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "An undo layer for AI agents.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"private": false,
|
|
7
|
+
"author": "Arhaan (https://github.com/ArhaanDev24)",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"homepage": "https://github.com/ArhaanDev24/Synartesis",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/ArhaanDev24/Synartesis.git"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/ArhaanDev24/Synartesis/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"mcp",
|
|
19
|
+
"model-context-protocol",
|
|
20
|
+
"undo",
|
|
21
|
+
"rollback",
|
|
22
|
+
"ai-agents",
|
|
23
|
+
"saga"
|
|
24
|
+
],
|
|
25
|
+
"bin": {
|
|
26
|
+
"synartesis": "dist/cli.js",
|
|
27
|
+
"synartesis-proxy": "dist/proxy.js"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist",
|
|
31
|
+
"manifests",
|
|
32
|
+
"README.md",
|
|
33
|
+
"LICENSE"
|
|
34
|
+
],
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=22"
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "tsup",
|
|
40
|
+
"typecheck": "tsc --noEmit",
|
|
41
|
+
"lint": "eslint .",
|
|
42
|
+
"test": "vitest run",
|
|
43
|
+
"test:watch": "vitest",
|
|
44
|
+
"pretest": "tsup --silent",
|
|
45
|
+
"demo": "tsup --silent && ./demo/filesystem-demo.sh",
|
|
46
|
+
"demo:memory": "tsup --silent && ./demo/memory-demo.sh",
|
|
47
|
+
"prepublishOnly": "tsup"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
51
|
+
"better-sqlite3": "^13.0.3",
|
|
52
|
+
"pino": "^10.3.1",
|
|
53
|
+
"yaml": "^2.9.0",
|
|
54
|
+
"zod": "^4.4.3"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@modelcontextprotocol/server-filesystem": "^2026.7.10",
|
|
58
|
+
"@types/better-sqlite3": "^9.6.0",
|
|
59
|
+
"@types/node": "^26.2.0",
|
|
60
|
+
"eslint": "^10.8.1",
|
|
61
|
+
"tsup": "^8.5.1",
|
|
62
|
+
"typescript": "^5.9.3",
|
|
63
|
+
"typescript-eslint": "^8.67.0",
|
|
64
|
+
"vitest": "^4.1.11"
|
|
65
|
+
},
|
|
66
|
+
"packageManager": "pnpm@9.15.9+sha512.68046141893c66fad01c079231128e9afb89ef87e2691d69e4d40eee228988295fd4682181bae55b58418c3a253bde65a505ec7c5f9403ece5cc3cd37dcf2531"
|
|
67
|
+
}
|