Skip to main content

scry

Scry Marker Specification - This project implements a formal, generic scry marker contract defined here

See scryspec.com for an overview.

Marker-indexed SQL cache MCP server. Scry indexes in-file @scry.* markers into a SQLite database that agents query via read-only SQL, providing structured project knowledge without LLM reasoning.

PyPI Python

Install

uv pip install scry-mcp
# or:
pip install scry-mcp

The PyPI distribution is scry-mcp (the bare name scry was already taken on PyPI). The import name and the installed console command are both scry.

Quickstart

# In your project root:
scry init                # scaffolds agent/ + driver dirs, updates .gitignore

Then add it to your MCP client config:

{
  "mcpServers": {
    "scry": {
      "command": "scry"
    }
  }
}

The MCP client inherits cwd from wherever it's launched, and scry walks up from there looking for an agent/ directory — so the same config works for any project. Bare scry (no subcommand) starts the MCP server over stdio — that's what Claude calls. Other subcommands:

Command Purpose
scry Run the MCP server (default).
scry init [path] Create .scry/{data,runtime,scripts}/ and a .scry/.gitignore. Idempotent — safe to run inside an ACP project.
scry surface [--force] One-shot batch reindex without booting the server.
scry version Print the package version.

The server walks up from cwd until it finds a .scry/ directory; that becomes the project root (falling back to cwd when none is found). The cache lives at .scry/data/project.db and is gitignored.

Marker mode

marker_mode in .scry/config.toml controls how markers are handled:

Mode Behavior
inline (default) Markers live embedded in source files.
sidecar Markers live in agent/scry/ sidecar files, keeping source clean; extras.source points at the described file.
off No markers read or written. Only scry_grep, scry_surface, and scry_db_health are registered — scry becomes a fast full-text file search. Point it at any project (create .scry/config.toml with marker_mode = "off"); no marker adoption required.

Markers

Scry recognizes three marker kinds per scry-spec v1.2.0: @scry.entry and @scry.anchor are block markers with a YAML body between open/close tokens; @scry.bind is a line or block marker declaring cross-references.

<!-- @scry.entry
id: design.auth-flow~a1b2c3d4
kind: design
summary: >
  JWT auth middleware, token validation, refresh flow
status: active
weight: 0.85
tags: ["scope:auth", "topic:security"]
rationale: >
  Missing this causes auth bypass bugs
applies: modifying auth, adding protected endpoints
seeded_questions:
  - How does token refresh work?
extras:
  owner: auth-team
  jira: AUTH-1247
  reviewed_at: 2026-05-19
@scry.entry.end -->

<!-- @scry.anchor auth-check~f1e2d3c4
description: JWT validation point for protected routes
@scry.anchor.end -->
# @scry.bind validate-jwt~a1b2c3d4 spec.auth~xyz89012#FR3
# @scry.bind jwt-expiry~b2c3d4e5 spec.auth~xyz89012#UT1

Block markers can be embedded in any host-language comment style (HTML, Python, JS, JSDoc, Rust, bare YAML). Comment prefixes are inferred from the YAML body — there is no per-language config.

extras field (scry-spec v1.2.0, FR4.B)

@scry.entry accepts an optional extras field: a single-depth map of arbitrary string keys to scalar values (string | number | boolean | null). Use it to attach structured metadata that isn't part of the core schema — ownership, ticket IDs, cost ledgers, review timestamps, anything you want to query later.

Constraints:

  • Single depth only — values must be scalars; nested maps and lists are diagnostic violations.
  • Serialized size ≤ 4 KB (the spec's SHOULD-level cap).
  • Oversize payloads MUST round-trip intact — the cap is a diagnostic, not a truncation gate. Empty extras: {} emits a SHOULD-level warning.

Indexed and queryable as of v0.17.0. The extras field is serialized to compact JSON-text in the scry__doc.extras column (NULL when absent), and exposed to scry_sql via SQLite JSON1. A doc with

extras:
  cost_usd: 12.5
  tier: gold
  active: true

answers queries like:

SELECT id,
       json_extract(extras, '$.cost_usd') AS cost,
       json_extract(extras, '$.tier')     AS tier
FROM scry__doc
WHERE kind = 'deliverable'
  AND json_extract(extras, '$.active') = 1
ORDER BY cost DESC;

Round-trip is byte-equivalent for the YAML scalar map: integers, floats, strings, booleans, and null are preserved.

@scry.entry kind values (v1.2.0 baseline)

kind use for
design architecture and design docs
pattern canonical recipes, established patterns
spec requirements and specifications
lesson post-mortems, "I tried X and it failed because Y"
internal service quirks, undocumented behaviors
task discrete work items
milestone phase markers, exit criteria
goal objective satisfied by a deliverable set via the satisfies typed edge (v1.2.0)
report wake/session reports
audit security or integrity audits
research research notes
code implementation-specific docs

MCP tools

Tool Purpose
scry_sql(query) Read-only SQL gateway. Rejects mutator keywords. Returns {results, row_count} JSON.
scry_grep(query, kind?, status?, path_glob?, limit?) Full-text search over indexed file bodies (scry__file_fts). Complements scry_sql when you want to search prose, not just marker fields.
scry_mint(kind, prefix) Generate a collision-free ID and the marker schema.
scry_mint_with_check(kind, prefix) Preferred minter — same as scry_mint plus tier-1/tier-2 collision warnings.
scry_surface(force=false, path?) Batch reindex from disk. force=true hard-deletes records whose source file no longer exists; path scopes the walk to a single file or subdirectory.
scry_sink(then_surface=false) Lower the index back to disk-only state — truncates all index tables atomically (schema preserved, disk markers untouched). Requires user confirmation; then_surface=true rebuilds in one call.
scry_scrub() Create a <branch>--clean git branch with all @scry.* markers stripped from non-agent files.
scry_script(action, script?, params?) Discover and run validation scripts from src/scry/scripts/ and .scry/scripts/.
scry_db_health() Probe the project DB and report status ∈ {ok, corrupt, locked}, integrity_check result, and scry__doc row count. For substrate auto-restore loops that need to distinguish corruption from transient WAL write-lock contention.

Database schema

Marker-backed core tables:

Table Holds
scry__doc One row per @scry.entry marker — id, kind, status, weight, summary, rationale, applies, current_path, ephemeral, missing_since, content_hash, extras, timestamps.
scry__doc_tag Tags as a join table — (doc_id, tag).
scry__doc_seeded_question Seeded questions per doc — (doc_id, ordinal, question).
scry__anchor One row per @scry.anchor marker — id, doc_id, description, content_hash, timestamps.
scry__anchor_seeded_question Seeded questions per anchor — (anchor_id, ordinal, question).
scry__bind One row per @scry.bind marker — source_doc_id, source_local_id, target_id, target_fragment, comment, content_hash, timestamps.
scry__rel Typed edges between docs — (from_id, to_id, predicate, fragment). Predicates: depends_on, implements, supersedes. Cycle detection enforced on depends_on.
scry__file Universal file-body index — (path, doc_id, body, content_hash, last_modified). Populated during scry_surface.
scry__warning Lint-style warnings emitted by the parser/indexer — id, kind, marker_kind, marker_id, file_path, message, detected_at.
migration Schema migration ledger.

FTS5 virtual tables (trigger-maintained, queryable via FTS MATCH):

FTS table Searches
scry__doc_fts Doc summary, rationale, applies, current_path.
scry__doc_tag_fts Tag strings.
scry__doc_seeded_question_fts Doc seeded questions.
scry__anchor_fts Anchor descriptions.
scry__bind_fts Bind source_local_id, target_id, comment.
scry__file_fts Full file bodies. Prefer the scry_grep tool over hand-rolled queries.

The cache is fully reconstructable from disk via scry_surface. The DB is gitignored; after git pull, agents call scry_surface to rebuild.

Watcher

A daemon thread runs alongside the MCP server, watching the project tree with a 150 ms debounce window. A lock file at .scry/runtime/lock performs PID-based primary election so multiple sessions don't race writes. The primary instance runs a cold scan on startup; secondaries observe and wait.

On file deletion: docs are soft-deleted (missing_since set); anchors and binds are hard-deleted.

Tests

uv pip install -e ".[dev]"
pytest

159 tests cover the parser, SQL gateway, mint, surface, watcher plumbing, script discovery, relationship cycle detection, FR4.B extras indexing + JSON1 queryability, schema-migration backfill, and concurrent-connection retry behavior.

License

MIT — see LICENSE.

Metadata

Release files for scry-mcp 0.21.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for scry-mcp 0.21.0
File Size Uploaded Provenance
scry_mcp-0.21.0.tar.gz 76.1 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for scry-mcp 0.21.0
File Interpreter ABI Platform
scry_mcp-0.21.0-py3-none-any.whl Python 3 none any Details

Total release size: 134.2 kB

Release files / scry_mcp-0.21.0.tar.gz

Download URL scry_mcp-0.21.0.tar.gz
Size 76.1 kB
Tags Source
SHA-256 checksum
How to use checksums
977185a2479218e791f32b2a51b4b343ca451b1822ff19fedd464d1a25d0f445
BLAKE2b-256 checksum
How to use checksums
a6f6406c0dda0ea6eaf7ee15c494e4668c778da3b7c7eb1da85f5fb7c65182f9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / scry_mcp-0.21.0-py3-none-any.whl

Download URL scry_mcp-0.21.0-py3-none-any.whl
Size 58.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
769abf569993bcef59755321c9062b05a7fd7aa9db11d9c77f7947055246a6a0
BLAKE2b-256 checksum
How to use checksums
c403ab8d0914caf21954edf84839383366bf9c23640473ad62d426d0fa02e968
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for scry-mcp 0.21.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.21.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page