Skip to content

Latest commit

 

History

History
176 lines (135 loc) · 6.35 KB

File metadata and controls

176 lines (135 loc) · 6.35 KB

v2 Upgrade Runbook — Both Connectors

Everything below is copy-paste CLI. Connector URLs, tool names, and default behavior are unchanged — Claude just gains new optional parameters and tools. Total hands-on time: ~15 minutes. Wall-clock time: depends on backfill size (the scripts tell you with --dry-run).

What changed (summary)

Email_RAG Old_Firm_RAG
recipient filter (To/Cc) NEW
email_cc in results NEW
Hybrid search (BM25 + vector, RRF) NEW NEW
exact_phrase must-contain filter NEW NEW
include_urls=False lean mode + get_links NEW NEW
Full-message reader NEW get_email NEW read_document
Adjacent-chunk fetch NEW get_neighbors
Cookbook behaviors baked into docstrings NEW NEW
Blank scanned-PDF text fixed (OCR backfill) NEW
Full body text stored (was 500-char preview) NEW

New/changed files per repo:

server/mcp_server.py        (v2, backward compatible)
server/mcp_server.v1.bak    (your v1, kept for instant rollback)
server/requirements.txt     (Old_Firm only: + pypdf)
scripts/backfill_*.py       (one-time data repair, resumable)
scripts/build_fts.py        (enables hybrid search)
scripts/diagnose.py         (read-only index health report)

Step 0 — One-time local setup (once, not per repo)

# From wherever your local clones live:
pip install -U "lancedb==0.30.2" pypdf google-genai google-cloud-storage --break-system-packages

# Make sure Application Default Credentials are current:
gcloud auth application-default login

Copy the new/changed files from the bundle into your local clones of each repo (preserving paths), or unzip the bundle over them.

Set the env vars each script needs (same values your ingest already uses — they're in your .env). Per repo, in the shell you'll run scripts from:

# Old_Firm repo shell:
export INDEX_URI="gs://<your-oldfirm-index-bucket>/lance"
export TABLE_NAME="documents"
export GEMINI_API_KEY="<your key>"        # for OCR fallback

# Email repo shell:
export INDEX_URI="gs://<your-email-index-bucket>/lance"
export TABLE_NAME="emails"
export RAW_BUCKET="<your-email-raw-bucket>"   # no gs:// prefix

Step 1 — Diagnose (read-only, 1 minute each)

# In each repo:
python scripts/diagnose.py

Old_Firm: confirms the blank-preview rate on PDFs (expect high — scans). Email: tells you definitively whether the PDF-attachment gap is a mislabel (cheap fix) or a skip (needs an attachments-only ingest pass — your existing ingest.py + legacy reuse handles that; bodies cost $0).

Step 2 — Backfill (the only long-running part; resumable, re-run freely)

# Old_Firm — fills blank scanned-PDF text via pypdf, Gemini OCR fallback:
python scripts/backfill_previews.py --dry-run     # counts + worst files
python scripts/backfill_previews.py --limit 50    # calibration
python scripts/backfill_previews.py               # full run

# Email — stores full body text (previews were 500 chars).
# Do high-value folders first; run the rest overnight if you want:
python scripts/backfill_text.py --dry-run
python scripts/backfill_text.py --folders "Drafts" "Sent Items" "Inbox"
python scripts/backfill_text.py                   # everything else

Both scripts skip already-filled rows, so interrupting is always safe.

Step 3 — Build the FTS index (enables hybrid search; ~minutes)

# In each repo:
python scripts/build_fts.py

Re-run any time after more backfilling; it replaces the index in place.

Step 4 — Deploy the v2 servers (same command you always use)

# Old_Firm:
cd server/
gcloud run deploy oldfirm-mcp --source . --region=us-east4

# Email:
cd server/
gcloud run deploy email-mcp --source . --region=us-east4

(Keep whatever extra flags your original deploy used — env vars/secrets are preserved across revisions, so plain --source . redeploys are fine.)

Deploying also makes the servers open the post-backfill table version. If you re-run backfills later WITHOUT a deploy, bounce the revision:

gcloud run services update oldfirm-mcp --region=us-east4 \
  --update-env-vars REFRESH=$(date +%s)

Step 5 — Smoke test from Claude (any device)

Ask Claude (Mac app or claude.ai — same connectors, nothing to reconfigure):

  1. "Query Old_Firm for the exact phrase '11-32857' " → should exact-match via hybrid/FTS.
  2. "read_document the BankUnited settlement" → text in-chat, no link needed.
  3. "Search my email for what Valero received from me in 2022" → exercises the new recipient filter.
  4. "Run an Old_Firm query with include_urls false, then get_links for the top 2" → lean mode round trip.

Rollback at any point: git checkout server/mcp_server.v1.bak, copy it over mcp_server.py, redeploy. The backfilled columns are additive and ignored by v1.

Step 6 — Commit and push (per repo)

git checkout -b v2-hybrid-search
git add -A
git commit -m "v2: hybrid FTS+vector search, recipient filter, in-chat document reading, OCR/text backfill tooling

- Server: RRF-fused hybrid search (graceful fallback), exact_phrase,
  include_urls lean mode, get_links; get_email / read_document /
  get_neighbors readers; cookbook behaviors encoded in tool docstrings.
- Scripts: resumable text backfills (pypdf + Gemini OCR for scans),
  native FTS index builder, read-only diagnostics.
- Backward compatible: same URL, tool names, and default behavior."
git push -u origin v2-hybrid-search

Then merge on GitHub (or push straight to main if you prefer: git checkout main && git merge v2-hybrid-search && git push).

Before pushing, double-check no secrets: your .gitignore already excludes .env and indexes; the new scripts read everything from env vars and contain none. git diff --stat main should show only .py/.md/.txt.


Deferred (deliberately not in this pass)

  • Email PDF-attachment ingest (if diagnose says "skipped"): run your existing ingest with legacy reuse — attachments-only cost.
  • Content-derived dates for Old_Firm (doc_date_content): worthwhile phase 2 once text_content exists; trivial script on the same pattern.
  • Cross-encoder reranking: hybrid + RRF captures most of the win; add only if you see relevance misses in practice.
  • Token rotation: unrelated to v2, but do it on your next ops pass (docs/06-operations.md) — the URL is a shared secret with mileage on it.