Metadata-Version: 2.4
Name: opyt
Version: 0.1.0a1
Summary: OPYT — a local-first knowledge base served over an MCP server, installable on any MCP client.
Author: David Maimon
License-Expression: MIT
Project-URL: Homepage, https://github.com/maimond123/opyt
Project-URL: Repository, https://github.com/maimond123/opyt
Keywords: mcp,knowledge-base,claude,rag,local-first,obsidian
Classifier: Development Status :: 3 - Alpha
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: MacOS
Classifier: Topic :: Text Processing :: Indexing
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: fastmcp>=3.0.0
Requires-Dist: numpy>=1.24.0
Requires-Dist: pyyaml>=6.0.1
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: requests>=2.31.0
Requires-Dist: browser-cookie3>=0.19.0
Requires-Dist: curl_cffi>=0.7.0
Requires-Dist: trafilatura>=2.0.0
Requires-Dist: html2text>=2024.2.0
Requires-Dist: feedparser>=6.0.0
Requires-Dist: beautifulsoup4>=4.12.0
Requires-Dist: yt-dlp>=2025.1.1
Requires-Dist: pypdf>=4.0.0
Requires-Dist: htmldate>=1.8.0
Requires-Dist: urllib3>=1.26.0
Provides-Extra: server
Requires-Dist: fastapi>=0.110.0; extra == "server"
Requires-Dist: uvicorn>=0.27.0; extra == "server"
Dynamic: license-file

# OPYT

A local-first knowledge base built from credible people's public output, served entirely
through an MCP server.

OPYT tracks people you trust — via a GitHub, Substack, blog, or X handle — pulls their full
public archive, and turns it into one queryable SQLite store your AI assistant can search,
read, and reason over. There is no separate chat UI: the MCP server hands data to whatever
client is already asking (Claude Code, Cursor, Claude Desktop, Windsurf), and that client's
own model does the synthesis.

> The moat is the data and the retrieval, not a hand-built UI. OPYT is MCP-first: tools
> return data, your host model does the reasoning, on your own subscription.

## How it works

Two independent ways content enters the store, as **atoms** — OPYT's unit of stored content,
one per post, repo, or paper:

**1. Track a person.** Call `add_oracle` (or run `oracle` to browse candidates first) with a
handle. OPYT auto-detects which of X, Substack, a personal blog, and GitHub that person
actually publishes to, then pulls their full archive from each. A background rail keeps every
tracked person's sources current without you asking again.

**2. Let Frontier watch your standing topics.** Frontier is a passive research-discovery
rail: it runs your standing queries against arXiv and GitHub on a schedule, judges what it
finds against your topics, and stages the good ones. You review the queue with `frontier`
when you want to — OPYT tells you at the start of a session if something new is waiting,
without ever pushing the list itself into context uninvited.

Everything lands in one SQLite database (`~/.opyt/opyt.db`) — atoms, their chunks, a
full-text index, and the entity/trust edges between tracked people. No vault of markdown
files, no dashboard, no daemon process: the MCP server is the only interface, and it creates
its own store on first use.

## MCP tools

| Tool | What it does |
|---|---|
| `search` / `open` / `aggregate` | Ranked hits across your atoms, one atom in full, distributional counts — the retrieval core. LLM-free: these return data, your host model reasons over it. |
| `onboard` | Run this first. Walks you through API keys (loopback OAuth, never a key pasted into chat) and your X bookmark session, then hands off to `oracle`. |
| `oracle` / `add_oracle` | Screen candidates, confirm who to track, and start ingesting them. |
| `frontier` | The ranked queue of research artifacts (papers, repos) Frontier staged for you since you last looked. |
| `hopper` | The manual "keep this" tool — hand it any URL and it routes to the right ingester, previews what it found, and asks you to confirm before writing. |
| `sitting` | Read one topical region of your knowledge base end to end, in publication order, and turn it into standing queries — the complement to `search`, which finds a few best matches instead of reading everything. |

Several background rails also spawn automatically each session — refreshing tracked
people's sources, running Frontier's stages, pulling new X bookmarks — each independently
gated so a stalled or failing rail never blocks the others or the server itself.

## Quick start

```bash
git clone https://github.com/maimond123/opyt
cd opyt
bash scripts/setup.sh          # venv, deps, .env template, git hooks
```

Register the MCP server with your client. For Claude Code:

```bash
claude mcp add opyt -- /absolute/path/to/opyt/venv/bin/opyt-mcp
```

For Cursor, Claude Desktop, or Windsurf, the installer merges the config for you (it backs up
the existing file first):

```bash
venv/bin/opyt-install-client --all      # or --cursor / --claude-desktop / --windsurf
```

Restart your client, open a chat, and call `onboard`. It walks you through getting an
OpenRouter key (a browser tab opens; you click Approve — nothing to paste), a twitterapi.io
key (opens a *local* page to paste into, never the chat itself), and detecting your logged-in
X browser session for free bookmark syncing. Then call `oracle` to pick who to track.

If you'd rather manage credentials by hand than go through `onboard`, `opyt-keys --list`
shows which are set (never their values), and `.env.example` documents each one.

## Design principles

Three constraints hold across the whole codebase, enforced by an AST-based guard
(`scripts/guard.py` + `.guards.py`) that runs in CI and pre-commit:

- **Distributable** — nothing may assume a specific machine. Paths are derived at runtime
  (`sys.executable`, `Path(__file__)`), never hardcoded.
- **Client-agnostic** — the core and every knowledge tool run on any MCP client, not just
  Claude Code. Claude-Code-specific behavior is opt-in and never load-bearing.
- **Fail-safe** — a missing optional input degrades to an empty result, not a crash. A failed
  external call skips cleanly; it never writes partial state or marks unfinished work done.

## License

MIT — see [LICENSE](LICENSE).
