cypherwolf-mcp 0.1.0__tar.gz
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.
- cypherwolf_mcp-0.1.0/PKG-INFO +284 -0
- cypherwolf_mcp-0.1.0/README.md +261 -0
- cypherwolf_mcp-0.1.0/cypherwolf/__init__.py +13 -0
- cypherwolf_mcp-0.1.0/cypherwolf/auth.py +256 -0
- cypherwolf_mcp-0.1.0/cypherwolf/client.py +183 -0
- cypherwolf_mcp-0.1.0/cypherwolf/config.py +71 -0
- cypherwolf_mcp-0.1.0/cypherwolf/server.py +211 -0
- cypherwolf_mcp-0.1.0/cypherwolf/validation.py +627 -0
- cypherwolf_mcp-0.1.0/cypherwolf_mcp.egg-info/PKG-INFO +284 -0
- cypherwolf_mcp-0.1.0/cypherwolf_mcp.egg-info/SOURCES.txt +18 -0
- cypherwolf_mcp-0.1.0/cypherwolf_mcp.egg-info/dependency_links.txt +1 -0
- cypherwolf_mcp-0.1.0/cypherwolf_mcp.egg-info/entry_points.txt +2 -0
- cypherwolf_mcp-0.1.0/cypherwolf_mcp.egg-info/requires.txt +5 -0
- cypherwolf_mcp-0.1.0/cypherwolf_mcp.egg-info/top_level.txt +1 -0
- cypherwolf_mcp-0.1.0/pyproject.toml +47 -0
- cypherwolf_mcp-0.1.0/setup.cfg +4 -0
- cypherwolf_mcp-0.1.0/tests/test_auth.py +277 -0
- cypherwolf_mcp-0.1.0/tests/test_client.py +194 -0
- cypherwolf_mcp-0.1.0/tests/test_server.py +194 -0
- cypherwolf_mcp-0.1.0/tests/test_validation.py +483 -0
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cypherwolf-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: CypherWolf MCP server — Neo4j Cypher query revision from a curated corpus, for @neo4j.com users.
|
|
5
|
+
Author: Neo4j Customer Success
|
|
6
|
+
License: Proprietary
|
|
7
|
+
Project-URL: Homepage, https://github.com/neo-gerlt/cypherwolf
|
|
8
|
+
Project-URL: Repository, https://github.com/neo-gerlt/cypherwolf
|
|
9
|
+
Keywords: neo4j,cypher,mcp,query-tuning
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Topic :: Database
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
Requires-Dist: mcp>=1.0.0
|
|
20
|
+
Requires-Dist: httpx
|
|
21
|
+
Provides-Extra: dev
|
|
22
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
23
|
+
|
|
24
|
+
# cypherwolf-mcp
|
|
25
|
+
|
|
26
|
+
**CypherWolf** revises Neo4j Cypher queries against a curated corpus of Neo4j
|
|
27
|
+
engineering precedent, returning corpus-grounded rewrite options plus the
|
|
28
|
+
index/constraint validation gates to confirm before applying a rewrite.
|
|
29
|
+
|
|
30
|
+
It ships as a single-tool MCP server (`revise_query`) that runs locally over
|
|
31
|
+
stdio and proxies to the CypherWolf HTTPS service. **Access is restricted to
|
|
32
|
+
`@neo4j.com` users.** The package holds **no** API key, **no** shared secret,
|
|
33
|
+
and **no** Aura credentials — all access control is enforced server-side via an
|
|
34
|
+
email gate plus a 30-day session token.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Install
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install cypherwolf-mcp
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Requires Python 3.10+. Dependencies are just `mcp` and `httpx` — no database
|
|
45
|
+
driver, no cloud SDKs.
|
|
46
|
+
|
|
47
|
+
## Sign in (first run)
|
|
48
|
+
|
|
49
|
+
Before the MCP server can revise queries, sign in once in a normal terminal with
|
|
50
|
+
your Neo4j email:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
cypherwolf-mcp auth
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
You will see the following disclosure, then be prompted for your email and a
|
|
57
|
+
6-digit code sent to it:
|
|
58
|
+
|
|
59
|
+
> This will email a 6-digit code to verify your @neo4j.com address. Your
|
|
60
|
+
> queries and the rewrites are saved to a Neo4j-internal folder under your
|
|
61
|
+
> email for internal use only.
|
|
62
|
+
|
|
63
|
+
The resulting session token is cached at `~/.cypherwolf/credentials.json`
|
|
64
|
+
(mode `0600`) and is valid for 30 days. After it expires — or if the token is
|
|
65
|
+
revoked — the tool will ask you to run `cypherwolf-mcp auth` again.
|
|
66
|
+
|
|
67
|
+
## Configure your MCP client
|
|
68
|
+
|
|
69
|
+
Point your MCP client at the `cypherwolf-mcp` console script (installed on your
|
|
70
|
+
`PATH` by `pip`).
|
|
71
|
+
|
|
72
|
+
### Cursor (`~/.cursor/mcp.json`)
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"mcpServers": {
|
|
77
|
+
"cypherwolf": {
|
|
78
|
+
"command": "cypherwolf-mcp"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Claude Code (`settings.json`)
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"mcpServers": {
|
|
89
|
+
"cypherwolf": {
|
|
90
|
+
"command": "cypherwolf-mcp"
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Restart the client after editing the config. The `cypherwolf` server exposes a
|
|
97
|
+
single tool, `revise_query`.
|
|
98
|
+
|
|
99
|
+
## Coworker testing checklist
|
|
100
|
+
|
|
101
|
+
After the PyPI upload is live, use these steps for Neo4j coworker testing while
|
|
102
|
+
the source repo remains private:
|
|
103
|
+
|
|
104
|
+
1. Install or upgrade the package:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
python -m pip install --upgrade cypherwolf-mcp
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
2. Sign in once:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
cypherwolf-mcp auth
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Use your `@neo4j.com` email, then paste the 6-digit code emailed to you. The
|
|
117
|
+
package stores a 30-day session token at `~/.cypherwolf/credentials.json`
|
|
118
|
+
with file mode `0600`.
|
|
119
|
+
|
|
120
|
+
3. Add the MCP server to Cursor:
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"mcpServers": {
|
|
125
|
+
"cypherwolf": {
|
|
126
|
+
"command": "cypherwolf-mcp"
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
4. Restart Cursor and confirm a `cypherwolf` MCP server with one tool,
|
|
133
|
+
`revise_query`, is available.
|
|
134
|
+
|
|
135
|
+
For Claude Code, use the `settings.json` snippet in
|
|
136
|
+
[Configure your MCP client](#configure-your-mcp-client).
|
|
137
|
+
|
|
138
|
+
5. Ask Cursor to call `revise_query` with a Cypher query and optional schema
|
|
139
|
+
context. The shim is already pointed at the deployed service:
|
|
140
|
+
`https://cypherwolf-shim-ez6emjisaa-uc.a.run.app`.
|
|
141
|
+
|
|
142
|
+
Expected auth behavior:
|
|
143
|
+
|
|
144
|
+
- Non-`@neo4j.com` emails are rejected.
|
|
145
|
+
- Expired or revoked sessions return an auth-required response telling you to
|
|
146
|
+
rerun `cypherwolf-mcp auth`.
|
|
147
|
+
- Queries and rewrites are logged to Neo4j-internal storage keyed by your email,
|
|
148
|
+
as disclosed during sign-in.
|
|
149
|
+
|
|
150
|
+
## The `revise_query` tool
|
|
151
|
+
|
|
152
|
+
| Arg | Required | Description |
|
|
153
|
+
|---|---|---|
|
|
154
|
+
| `query` | yes | The Cypher query to revise. |
|
|
155
|
+
| `context` | no | Schema or context details (labels, indexes, cardinalities). |
|
|
156
|
+
| `neo4j_version` | no | Target Neo4j version, e.g. `"5.26"`. |
|
|
157
|
+
| `mode` | no | Optional tuning mode, e.g. `"verbose"`. |
|
|
158
|
+
|
|
159
|
+
**Response** (structured JSON):
|
|
160
|
+
|
|
161
|
+
```json
|
|
162
|
+
{
|
|
163
|
+
"option_a": "MATCH (u:User {id: $id}) RETURN u",
|
|
164
|
+
"option_b": "…optional second rewrite…",
|
|
165
|
+
"validation_gates": ["Equality predicate on :User(id) — confirm CREATE INDEX …"],
|
|
166
|
+
"why": ["Corpus precedent (Slack, Fauth): …"],
|
|
167
|
+
"top_n": ["[0.91] Slack — Fauth: supernode pagination"],
|
|
168
|
+
"no_rewrite_reason": null
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
- **Corpus-gap is a success.** When the corpus has no relevant precedent,
|
|
173
|
+
`option_a` is `null` and `no_rewrite_reason` explains why (`"corpus-gap"`).
|
|
174
|
+
CypherWolf never bluffs a rewrite.
|
|
175
|
+
- On an auth / rate-limit / upstream error the tool returns a structured payload
|
|
176
|
+
with an `error` field and a matching `no_rewrite_reason`
|
|
177
|
+
(`"auth-required"`, `"rate-limited"`, `"upstream-unavailable"`) rather than
|
|
178
|
+
throwing.
|
|
179
|
+
|
|
180
|
+
## Configuration
|
|
181
|
+
|
|
182
|
+
| Environment variable | Default | Purpose |
|
|
183
|
+
|---|---|---|
|
|
184
|
+
| `CYPHERWOLF_SHIM_URL` | `https://cypherwolf-shim-ez6emjisaa-uc.a.run.app` | CypherWolf service base URL. |
|
|
185
|
+
| `CYPHERWOLF_SESSION_TOKEN` | *(unset)* | Supply a session token directly, bypassing the on-disk cache (CI / scripted use). |
|
|
186
|
+
|
|
187
|
+
Credentials cache: `~/.cypherwolf/credentials.json` (mode `0600`), holding
|
|
188
|
+
`{email, session_token, issued_at}`.
|
|
189
|
+
|
|
190
|
+
## Privacy
|
|
191
|
+
|
|
192
|
+
Your submitted queries and the returned rewrites are logged server-side to a
|
|
193
|
+
Neo4j-internal storage location, keyed by your email, for internal use only.
|
|
194
|
+
See the sign-in disclosure above.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Publishing
|
|
199
|
+
|
|
200
|
+
The package is prepared for public PyPI as `cypherwolf-mcp`. The source repo can
|
|
201
|
+
stay private during the Neo4j-only coworker-testing phase because the wheel ships
|
|
202
|
+
no secrets and all access control is enforced by the hosted shim's `@neo4j.com`
|
|
203
|
+
email-code gate.
|
|
204
|
+
|
|
205
|
+
Current publish status: distribution artifacts build and pass `twine check`, but
|
|
206
|
+
the first production PyPI upload is blocked until an account-scoped `pypi.org`
|
|
207
|
+
API token is available. A project-scoped token cannot create the first release
|
|
208
|
+
because the `cypherwolf-mcp` project does not exist on PyPI yet.
|
|
209
|
+
|
|
210
|
+
### Build the artifacts
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
cd mcp
|
|
214
|
+
python -m build # produces dist/cypherwolf_mcp-<version>-py3-none-any.whl + .tar.gz
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Verify a clean install in a throwaway venv:
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
python -m venv /tmp/cw && /tmp/cw/bin/pip install dist/cypherwolf_mcp-*.whl
|
|
221
|
+
/tmp/cw/bin/cypherwolf-mcp --help
|
|
222
|
+
/tmp/cw/bin/pip freeze | grep -iE 'google|neo4j' # must be empty
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### First production publish — one-shot account token
|
|
226
|
+
|
|
227
|
+
Use an account-scoped PyPI API token exactly once to create the production
|
|
228
|
+
`cypherwolf-mcp` project. Build from a committed tree, publish, verify the public
|
|
229
|
+
install, then remove the account token from the release path.
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
cd mcp
|
|
233
|
+
rm -rf dist build *.egg-info
|
|
234
|
+
python -m build
|
|
235
|
+
python -m twine check dist/*
|
|
236
|
+
python -m twine upload dist/*
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
After upload, verify in a clean environment:
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
python -m venv /tmp/cw-pypi
|
|
243
|
+
/tmp/cw-pypi/bin/pip install cypherwolf-mcp
|
|
244
|
+
/tmp/cw-pypi/bin/cypherwolf-mcp --help
|
|
245
|
+
/tmp/cw-pypi/bin/pip freeze | grep -iE 'google|neo4j' # must be empty
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Ongoing publish path — PyPI Trusted Publishing via GitHub Actions
|
|
249
|
+
|
|
250
|
+
Trusted Publishing (OIDC) is preferred over a long-lived API token: no secret to
|
|
251
|
+
store or rotate.
|
|
252
|
+
|
|
253
|
+
1. On PyPI, add a **Trusted Publisher** for the `neo-gerlt/cypherwolf` repo,
|
|
254
|
+
workflow `.github/workflows/publish-mcp.yml`, and environment `pypi`.
|
|
255
|
+
2. Cut a GitHub Release, or run the workflow manually if PyPI's Trusted
|
|
256
|
+
Publisher settings allow it. The workflow builds `mcp/`, runs `twine check`,
|
|
257
|
+
and publishes with OIDC.
|
|
258
|
+
3. Retire the account-scoped token after Trusted Publishing is confirmed.
|
|
259
|
+
|
|
260
|
+
### Alternative — manual publish after the project exists
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
cd mcp
|
|
264
|
+
python -m build
|
|
265
|
+
python -m twine upload dist/* # with a project-scoped token
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Release checklist
|
|
269
|
+
|
|
270
|
+
- Bump `version` in `pyproject.toml` and `cypherwolf/__init__.py` for each
|
|
271
|
+
release.
|
|
272
|
+
- Build from `repos/cypherwolf/mcp/` and publish with Trusted Publishing or a
|
|
273
|
+
scoped PyPI token. Do **not** commit any token to the repo.
|
|
274
|
+
- Verify a fresh install in a clean virtual environment:
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
python -m venv /tmp/cw && /tmp/cw/bin/pip install cypherwolf-mcp
|
|
278
|
+
/tmp/cw/bin/cypherwolf-mcp --help
|
|
279
|
+
/tmp/cw/bin/pip freeze | grep -iE 'google|neo4j' # must be empty
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
- Repo split to `neo-gerlt/cypherwolf-mcp` remains deferred (follow-on #10) and
|
|
283
|
+
is **not** required to publish — a `pyproject.toml` rooted at `mcp/` ships the
|
|
284
|
+
wheel from the monorepo today.
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
# cypherwolf-mcp
|
|
2
|
+
|
|
3
|
+
**CypherWolf** revises Neo4j Cypher queries against a curated corpus of Neo4j
|
|
4
|
+
engineering precedent, returning corpus-grounded rewrite options plus the
|
|
5
|
+
index/constraint validation gates to confirm before applying a rewrite.
|
|
6
|
+
|
|
7
|
+
It ships as a single-tool MCP server (`revise_query`) that runs locally over
|
|
8
|
+
stdio and proxies to the CypherWolf HTTPS service. **Access is restricted to
|
|
9
|
+
`@neo4j.com` users.** The package holds **no** API key, **no** shared secret,
|
|
10
|
+
and **no** Aura credentials — all access control is enforced server-side via an
|
|
11
|
+
email gate plus a 30-day session token.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install cypherwolf-mcp
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Requires Python 3.10+. Dependencies are just `mcp` and `httpx` — no database
|
|
22
|
+
driver, no cloud SDKs.
|
|
23
|
+
|
|
24
|
+
## Sign in (first run)
|
|
25
|
+
|
|
26
|
+
Before the MCP server can revise queries, sign in once in a normal terminal with
|
|
27
|
+
your Neo4j email:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
cypherwolf-mcp auth
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
You will see the following disclosure, then be prompted for your email and a
|
|
34
|
+
6-digit code sent to it:
|
|
35
|
+
|
|
36
|
+
> This will email a 6-digit code to verify your @neo4j.com address. Your
|
|
37
|
+
> queries and the rewrites are saved to a Neo4j-internal folder under your
|
|
38
|
+
> email for internal use only.
|
|
39
|
+
|
|
40
|
+
The resulting session token is cached at `~/.cypherwolf/credentials.json`
|
|
41
|
+
(mode `0600`) and is valid for 30 days. After it expires — or if the token is
|
|
42
|
+
revoked — the tool will ask you to run `cypherwolf-mcp auth` again.
|
|
43
|
+
|
|
44
|
+
## Configure your MCP client
|
|
45
|
+
|
|
46
|
+
Point your MCP client at the `cypherwolf-mcp` console script (installed on your
|
|
47
|
+
`PATH` by `pip`).
|
|
48
|
+
|
|
49
|
+
### Cursor (`~/.cursor/mcp.json`)
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"mcpServers": {
|
|
54
|
+
"cypherwolf": {
|
|
55
|
+
"command": "cypherwolf-mcp"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Claude Code (`settings.json`)
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"mcpServers": {
|
|
66
|
+
"cypherwolf": {
|
|
67
|
+
"command": "cypherwolf-mcp"
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Restart the client after editing the config. The `cypherwolf` server exposes a
|
|
74
|
+
single tool, `revise_query`.
|
|
75
|
+
|
|
76
|
+
## Coworker testing checklist
|
|
77
|
+
|
|
78
|
+
After the PyPI upload is live, use these steps for Neo4j coworker testing while
|
|
79
|
+
the source repo remains private:
|
|
80
|
+
|
|
81
|
+
1. Install or upgrade the package:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
python -m pip install --upgrade cypherwolf-mcp
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
2. Sign in once:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
cypherwolf-mcp auth
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Use your `@neo4j.com` email, then paste the 6-digit code emailed to you. The
|
|
94
|
+
package stores a 30-day session token at `~/.cypherwolf/credentials.json`
|
|
95
|
+
with file mode `0600`.
|
|
96
|
+
|
|
97
|
+
3. Add the MCP server to Cursor:
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"mcpServers": {
|
|
102
|
+
"cypherwolf": {
|
|
103
|
+
"command": "cypherwolf-mcp"
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
4. Restart Cursor and confirm a `cypherwolf` MCP server with one tool,
|
|
110
|
+
`revise_query`, is available.
|
|
111
|
+
|
|
112
|
+
For Claude Code, use the `settings.json` snippet in
|
|
113
|
+
[Configure your MCP client](#configure-your-mcp-client).
|
|
114
|
+
|
|
115
|
+
5. Ask Cursor to call `revise_query` with a Cypher query and optional schema
|
|
116
|
+
context. The shim is already pointed at the deployed service:
|
|
117
|
+
`https://cypherwolf-shim-ez6emjisaa-uc.a.run.app`.
|
|
118
|
+
|
|
119
|
+
Expected auth behavior:
|
|
120
|
+
|
|
121
|
+
- Non-`@neo4j.com` emails are rejected.
|
|
122
|
+
- Expired or revoked sessions return an auth-required response telling you to
|
|
123
|
+
rerun `cypherwolf-mcp auth`.
|
|
124
|
+
- Queries and rewrites are logged to Neo4j-internal storage keyed by your email,
|
|
125
|
+
as disclosed during sign-in.
|
|
126
|
+
|
|
127
|
+
## The `revise_query` tool
|
|
128
|
+
|
|
129
|
+
| Arg | Required | Description |
|
|
130
|
+
|---|---|---|
|
|
131
|
+
| `query` | yes | The Cypher query to revise. |
|
|
132
|
+
| `context` | no | Schema or context details (labels, indexes, cardinalities). |
|
|
133
|
+
| `neo4j_version` | no | Target Neo4j version, e.g. `"5.26"`. |
|
|
134
|
+
| `mode` | no | Optional tuning mode, e.g. `"verbose"`. |
|
|
135
|
+
|
|
136
|
+
**Response** (structured JSON):
|
|
137
|
+
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"option_a": "MATCH (u:User {id: $id}) RETURN u",
|
|
141
|
+
"option_b": "…optional second rewrite…",
|
|
142
|
+
"validation_gates": ["Equality predicate on :User(id) — confirm CREATE INDEX …"],
|
|
143
|
+
"why": ["Corpus precedent (Slack, Fauth): …"],
|
|
144
|
+
"top_n": ["[0.91] Slack — Fauth: supernode pagination"],
|
|
145
|
+
"no_rewrite_reason": null
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
- **Corpus-gap is a success.** When the corpus has no relevant precedent,
|
|
150
|
+
`option_a` is `null` and `no_rewrite_reason` explains why (`"corpus-gap"`).
|
|
151
|
+
CypherWolf never bluffs a rewrite.
|
|
152
|
+
- On an auth / rate-limit / upstream error the tool returns a structured payload
|
|
153
|
+
with an `error` field and a matching `no_rewrite_reason`
|
|
154
|
+
(`"auth-required"`, `"rate-limited"`, `"upstream-unavailable"`) rather than
|
|
155
|
+
throwing.
|
|
156
|
+
|
|
157
|
+
## Configuration
|
|
158
|
+
|
|
159
|
+
| Environment variable | Default | Purpose |
|
|
160
|
+
|---|---|---|
|
|
161
|
+
| `CYPHERWOLF_SHIM_URL` | `https://cypherwolf-shim-ez6emjisaa-uc.a.run.app` | CypherWolf service base URL. |
|
|
162
|
+
| `CYPHERWOLF_SESSION_TOKEN` | *(unset)* | Supply a session token directly, bypassing the on-disk cache (CI / scripted use). |
|
|
163
|
+
|
|
164
|
+
Credentials cache: `~/.cypherwolf/credentials.json` (mode `0600`), holding
|
|
165
|
+
`{email, session_token, issued_at}`.
|
|
166
|
+
|
|
167
|
+
## Privacy
|
|
168
|
+
|
|
169
|
+
Your submitted queries and the returned rewrites are logged server-side to a
|
|
170
|
+
Neo4j-internal storage location, keyed by your email, for internal use only.
|
|
171
|
+
See the sign-in disclosure above.
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Publishing
|
|
176
|
+
|
|
177
|
+
The package is prepared for public PyPI as `cypherwolf-mcp`. The source repo can
|
|
178
|
+
stay private during the Neo4j-only coworker-testing phase because the wheel ships
|
|
179
|
+
no secrets and all access control is enforced by the hosted shim's `@neo4j.com`
|
|
180
|
+
email-code gate.
|
|
181
|
+
|
|
182
|
+
Current publish status: distribution artifacts build and pass `twine check`, but
|
|
183
|
+
the first production PyPI upload is blocked until an account-scoped `pypi.org`
|
|
184
|
+
API token is available. A project-scoped token cannot create the first release
|
|
185
|
+
because the `cypherwolf-mcp` project does not exist on PyPI yet.
|
|
186
|
+
|
|
187
|
+
### Build the artifacts
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
cd mcp
|
|
191
|
+
python -m build # produces dist/cypherwolf_mcp-<version>-py3-none-any.whl + .tar.gz
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Verify a clean install in a throwaway venv:
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
python -m venv /tmp/cw && /tmp/cw/bin/pip install dist/cypherwolf_mcp-*.whl
|
|
198
|
+
/tmp/cw/bin/cypherwolf-mcp --help
|
|
199
|
+
/tmp/cw/bin/pip freeze | grep -iE 'google|neo4j' # must be empty
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### First production publish — one-shot account token
|
|
203
|
+
|
|
204
|
+
Use an account-scoped PyPI API token exactly once to create the production
|
|
205
|
+
`cypherwolf-mcp` project. Build from a committed tree, publish, verify the public
|
|
206
|
+
install, then remove the account token from the release path.
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
cd mcp
|
|
210
|
+
rm -rf dist build *.egg-info
|
|
211
|
+
python -m build
|
|
212
|
+
python -m twine check dist/*
|
|
213
|
+
python -m twine upload dist/*
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
After upload, verify in a clean environment:
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
python -m venv /tmp/cw-pypi
|
|
220
|
+
/tmp/cw-pypi/bin/pip install cypherwolf-mcp
|
|
221
|
+
/tmp/cw-pypi/bin/cypherwolf-mcp --help
|
|
222
|
+
/tmp/cw-pypi/bin/pip freeze | grep -iE 'google|neo4j' # must be empty
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Ongoing publish path — PyPI Trusted Publishing via GitHub Actions
|
|
226
|
+
|
|
227
|
+
Trusted Publishing (OIDC) is preferred over a long-lived API token: no secret to
|
|
228
|
+
store or rotate.
|
|
229
|
+
|
|
230
|
+
1. On PyPI, add a **Trusted Publisher** for the `neo-gerlt/cypherwolf` repo,
|
|
231
|
+
workflow `.github/workflows/publish-mcp.yml`, and environment `pypi`.
|
|
232
|
+
2. Cut a GitHub Release, or run the workflow manually if PyPI's Trusted
|
|
233
|
+
Publisher settings allow it. The workflow builds `mcp/`, runs `twine check`,
|
|
234
|
+
and publishes with OIDC.
|
|
235
|
+
3. Retire the account-scoped token after Trusted Publishing is confirmed.
|
|
236
|
+
|
|
237
|
+
### Alternative — manual publish after the project exists
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
cd mcp
|
|
241
|
+
python -m build
|
|
242
|
+
python -m twine upload dist/* # with a project-scoped token
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Release checklist
|
|
246
|
+
|
|
247
|
+
- Bump `version` in `pyproject.toml` and `cypherwolf/__init__.py` for each
|
|
248
|
+
release.
|
|
249
|
+
- Build from `repos/cypherwolf/mcp/` and publish with Trusted Publishing or a
|
|
250
|
+
scoped PyPI token. Do **not** commit any token to the repo.
|
|
251
|
+
- Verify a fresh install in a clean virtual environment:
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
python -m venv /tmp/cw && /tmp/cw/bin/pip install cypherwolf-mcp
|
|
255
|
+
/tmp/cw/bin/cypherwolf-mcp --help
|
|
256
|
+
/tmp/cw/bin/pip freeze | grep -iE 'google|neo4j' # must be empty
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
- Repo split to `neo-gerlt/cypherwolf-mcp` remains deferred (follow-on #10) and
|
|
260
|
+
is **not** required to publish — a `pyproject.toml` rooted at `mcp/` ships the
|
|
261
|
+
wheel from the monorepo today.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""CypherWolf MCP client.
|
|
2
|
+
|
|
3
|
+
A pip-installable MCP server exposing a single ``revise_query`` tool that
|
|
4
|
+
proxies to the CypherWolf HTTPS shim. Ships no secrets, no Aura driver, and no
|
|
5
|
+
GCP libraries — all access control is server-side via the ``@neo4j.com`` email
|
|
6
|
+
gate + a 30-day opaque session token.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
__version__ = "0.1.0"
|
|
12
|
+
|
|
13
|
+
__all__ = ["__version__"]
|