Metadata-Version: 2.4
Name: cypherwolf-mcp
Version: 0.1.1
Summary: CypherWolf MCP server — Neo4j Cypher query revision from a curated corpus, for @neo4j.com users.
Author: Neo4j Customer Success
License: Proprietary
Project-URL: Homepage, https://github.com/neo-gerlt/cypherwolf
Project-URL: Repository, https://github.com/neo-gerlt/cypherwolf
Keywords: neo4j,cypher,mcp,query-tuning
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Operating System :: OS Independent
Classifier: Intended Audience :: Developers
Classifier: Topic :: Database
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: mcp>=1.0.0
Requires-Dist: httpx
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"

# cypherwolf-mcp

**CypherWolf** revises Neo4j Cypher queries against a curated corpus of Neo4j
engineering precedent, returning corpus-grounded rewrite options plus the
index/constraint validation gates to confirm before applying a rewrite.

It ships as a single-tool MCP server (`revise_query`) that runs locally over
stdio and proxies to the CypherWolf HTTPS service. **Access is restricted to
`@neo4j.com` users.** The package holds **no** API key, **no** shared secret,
and **no** Aura credentials — all access control is enforced server-side via an
email gate plus a 30-day session token.

---

## Install

```bash
pip install cypherwolf-mcp
```

Requires Python 3.10+. Dependencies are just `mcp` and `httpx` — no database
driver, no cloud SDKs.

## Sign in (first run)

Before the MCP server can revise queries, sign in once in a normal terminal with
your Neo4j email:

```bash
cypherwolf-mcp auth
```

You will see the following disclosure, then be prompted for your email and a
6-digit code sent to it:

> This will email a 6-digit code to verify your @neo4j.com address. Your
> queries and the rewrites are saved to a Neo4j-internal folder under your
> email for internal use only.

The resulting session token is cached at `~/.cypherwolf/credentials.json`
(mode `0600`) and is valid for 30 days. After it expires — or if the token is
revoked — the tool will ask you to run `cypherwolf-mcp auth` again.

## Configure your MCP client

Point your MCP client at the `cypherwolf-mcp` console script (installed on your
`PATH` by `pip`).

### Cursor (`~/.cursor/mcp.json`)

```json
{
  "mcpServers": {
    "cypherwolf": {
      "command": "cypherwolf-mcp"
    }
  }
}
```

### Claude Code (`settings.json`)

```json
{
  "mcpServers": {
    "cypherwolf": {
      "command": "cypherwolf-mcp"
    }
  }
}
```

Restart the client after editing the config. The `cypherwolf` server exposes a
single tool, `revise_query`.

## Coworker testing checklist

After the PyPI upload is live, use these steps for Neo4j coworker testing while
the source repo remains private:

1. Install or upgrade the package:

   ```bash
   python -m pip install --upgrade cypherwolf-mcp
   ```

2. Sign in once:

   ```bash
   cypherwolf-mcp auth
   ```

   Use your `@neo4j.com` email, then paste the 6-digit code emailed to you. The
   package stores a 30-day session token at `~/.cypherwolf/credentials.json`
   with file mode `0600`.

3. Add the MCP server to Cursor:

   ```json
   {
     "mcpServers": {
       "cypherwolf": {
         "command": "cypherwolf-mcp"
       }
     }
   }
   ```

4. Restart Cursor and confirm a `cypherwolf` MCP server with one tool,
   `revise_query`, is available.

   For Claude Code, use the `settings.json` snippet in
   [Configure your MCP client](#configure-your-mcp-client).

5. Ask Cursor to call `revise_query` with a Cypher query and optional schema
   context. The shim is already pointed at the deployed service:
   `https://cypherwolf-shim-ez6emjisaa-uc.a.run.app`.

Expected auth behavior:

- Non-`@neo4j.com` emails are rejected.
- Expired or revoked sessions return an auth-required response telling you to
  rerun `cypherwolf-mcp auth`.
- Queries and rewrites are logged to Neo4j-internal storage keyed by your email,
  as disclosed during sign-in.

## The `revise_query` tool

| Arg | Required | Description |
|---|---|---|
| `query` | yes | The Cypher query to revise. |
| `context` | no | Schema or context details (labels, indexes, cardinalities). |
| `neo4j_version` | no | Target Neo4j version, e.g. `"5.26"`. |
| `mode` | no | Optional tuning mode, e.g. `"verbose"`. |

**Response** (structured JSON):

```json
{
  "option_a": "MATCH (u:User {id: $id}) RETURN u",
  "option_b": "…optional second rewrite…",
  "validation_gates": ["Equality predicate on :User(id) — confirm CREATE INDEX …"],
  "why": ["Corpus precedent (Slack, Fauth): …"],
  "top_n": ["[0.91] Slack — Fauth: supernode pagination"],
  "no_rewrite_reason": null
}
```

- **Corpus-gap is a success.** When the corpus has no relevant precedent,
  `option_a` is `null` and `no_rewrite_reason` explains why (`"corpus-gap"`).
  CypherWolf never bluffs a rewrite.
- On an auth / rate-limit / upstream error the tool returns a structured payload
  with an `error` field and a matching `no_rewrite_reason`
  (`"auth-required"`, `"rate-limited"`, `"upstream-unavailable"`) rather than
  throwing.

## Configuration

| Environment variable | Default | Purpose |
|---|---|---|
| `CYPHERWOLF_SHIM_URL` | `https://cypherwolf-shim-ez6emjisaa-uc.a.run.app` | CypherWolf service base URL. |
| `CYPHERWOLF_SESSION_TOKEN` | *(unset)* | Supply a session token directly, bypassing the on-disk cache (CI / scripted use). |

Credentials cache: `~/.cypherwolf/credentials.json` (mode `0600`), holding
`{email, session_token, issued_at}`.

## Privacy

Your submitted queries and the returned rewrites are logged server-side to a
Neo4j-internal storage location, keyed by your email, for internal use only.
See the sign-in disclosure above.

---

## Publishing

The package is prepared for public PyPI as `cypherwolf-mcp`. The source repo can
stay private during the Neo4j-only coworker-testing phase because the wheel ships
no secrets and all access control is enforced by the hosted shim's `@neo4j.com`
email-code gate.

**Canonical publish path: PyPI API token via `twine upload`.** The project is
live on PyPI (first release `0.1.0`), so every subsequent release is a plain
`twine upload` authenticated with a `cypherwolf-mcp`-scoped API token from
`~/.pypirc`. Do **not** rely on the GitHub Release / Trusted Publishing flow —
see the note under *Trusted Publishing* below.

### Build the artifacts

```bash
cd mcp
python -m build            # produces dist/cypherwolf_mcp-<version>-py3-none-any.whl + .tar.gz
```

Verify a clean install in a throwaway venv:

```bash
python -m venv /tmp/cw && /tmp/cw/bin/pip install dist/cypherwolf_mcp-*.whl
/tmp/cw/bin/cypherwolf-mcp --help
/tmp/cw/bin/pip freeze | grep -iE 'google|neo4j'   # must be empty
```

### Release a new version (canonical)

1. Bump the version in **both** `mcp/pyproject.toml` and
   `mcp/cypherwolf/__init__.py`.
2. Commit the change (workspace clean-trailer pattern).
3. Build and upload from a committed tree:

```bash
cd mcp
rm -f dist/*
python -m build
python -m twine check dist/*
python -m twine upload dist/cypherwolf_mcp-<version>*
```

`twine` reads credentials from `~/.pypirc` (`[pypi]`, `username = __token__`,
`password = pypi-<token>`). The token must be a valid **`cypherwolf-mcp`-scoped**
API token. Never paste the token into a shell command or commit it.

After upload, verify in a clean environment:

```bash
python -m venv /tmp/cw-pypi
/tmp/cw-pypi/bin/pip install --upgrade cypherwolf-mcp
/tmp/cw-pypi/bin/cypherwolf-mcp --help
/tmp/cw-pypi/bin/pip freeze | grep -iE 'google|neo4j'   # must be empty
```

**403 "Invalid or non-existent authentication information"** = the token in
`~/.pypirc` is stale/revoked (the account-scoped bootstrap token used for
`0.1.0` was retired). Mint a fresh project-scoped token on pypi.org and update
`~/.pypirc` before retrying.

### Trusted Publishing via GitHub Actions — NOT in use

`.github/workflows/publish-mcp.yml` exists but is **dormant**: the PyPI Trusted
Publisher for `neo-gerlt/cypherwolf` was never confirmed, so cutting a GitHub
Release / running the workflow will **fail** on the OIDC publish step. Do not
use this path. If Trusted Publishing is ever adopted, register the publisher
(repo `neo-gerlt/cypherwolf`, workflow `publish-mcp.yml`, environment `pypi`) on
PyPI first, confirm a dry run, then update this section.

### Release checklist

- Bump `version` in `pyproject.toml` and `cypherwolf/__init__.py` for each
  release.
- Build from `repos/cypherwolf/mcp/` and publish with Trusted Publishing or a
  scoped PyPI token. Do **not** commit any token to the repo.
- Verify a fresh install in a clean virtual environment:

  ```bash
  python -m venv /tmp/cw && /tmp/cw/bin/pip install cypherwolf-mcp
  /tmp/cw/bin/cypherwolf-mcp --help
  /tmp/cw/bin/pip freeze | grep -iE 'google|neo4j'   # must be empty
  ```

- Repo split to `neo-gerlt/cypherwolf-mcp` remains deferred (follow-on #10) and
  is **not** required to publish — a `pyproject.toml` rooted at `mcp/` ships the
  wheel from the monorepo today.
