tugra
# tugra
Part of [VERAX](https://verax-ai.com), by VERAX Teknoloji. Start with the VERAX body: [verax-ai/verax](https://github.com/verax-ai/verax). Sister projects: [Conarium](https://github.com/dogrucanemek-alt/conarium) · [Cedulon](https://github.com/dogrucanemek-alt/cedulon).
```bash
npx tugra init
```
That creates a vault, writes a sample fact, and prints a config block. Paste the block into your MCP client. On a TTY, `npx tugra` prints help and exits. Piped (Claude Desktop, Cursor, Claude Code) it is the MCP server.
Provenance-aware memory for AI agents. Every claim carries its **source**, its **age**, and its **boundary**. There is no cloud.
## What it is
A fact that cannot name where it came from is not a fact. Tugra stores each claim as a file whose frontmatter holds source, last verification date, shelf life, and — when the topic is off-limits — a boundary that forbids invention. Search ranks by token score, then freshness, then confidence. Retired and rotten facts stay out of the default set.
## Tools
| Tool | What it does |
| --- | --- |
| `fact_search` | Search the vault. Retired/rotten omitted unless `archive: true`. |
| `fact_read` | Read one fact by `uid`. Body is escaped before the model sees it. |
| `fact_propose` | Write a draft. Secret patterns are rejected before any write. `type: "boundary"` is always quarantined. |
| `event_report` | Append a local telemetry line. No network. |
Stored field names stay in the vault's native shape (`kaynak`, `guven`, `raf_omru`, `sinir`). The tool names and parameter names above are the public contract.
## Install — env paths (optional)
`tugra init` is enough to start. Override the two paths only if you already have a vault elsewhere. Without them, the server looks next to the installed package — that is wrong for a bare `npx` with no init.
- `TUGRA_VAULT` — vault (markdown facts)
- `TUGRA_EVENTS` — telemetry directory
Authorization: if no authorization store is configured, **single-user mode** is on — search and propose work without a profile. If an authorization store *is* configured (a `yetki/` directory, or `TUGRA_AUTH`), each agent needs a JSON profile or search returns unauthorized.
### Claude Desktop
`claude_desktop_config.json`:
```json
{
"mcpServers": {
"tugra": {
"command": "npx",
"args": ["-y", "tugra"],
"env": {
"TUGRA_VAULT": "/absolute/path/to/vault",
"TUGRA_EVENTS": "/absolute/path/to/events"
}
}
}
}
```
### Claude Code
`.mcp.json` at the project root, or `claude mcp add`:
```json
{
"mcpServers": {
"tugra": {
"command": "npx",
"args": ["-y", "tugra"],
"env": {
"TUGRA_VAULT": "/absolute/path/to/vault",
"TUGRA_EVENTS": "/absolute/path/to/events"
}
}
}
}
```
### Cursor
`.cursor/mcp.json` or Cursor Settings → MCP:
```json
{
"mcpServers": {
"tugra": {
"command": "npx",
"args": ["-y", "tugra"],
"env": {
"TUGRA_VAULT": "/absolute/path/to/vault",
"TUGRA_EVENTS": "/absolute/path/to/events"
}
}
}
}
```
### Windsurf
`mcp_config.json`:
```json
{
"mcpServers": {
"tugra": {
"command": "npx",
"args": ["-y", "tugra"],
"env": {
"TUGRA_VAULT": "/absolute/path/to/vault",
"TUGRA_EVENTS": "/absolute/path/to/events"
}
}
}
}
```
### Codex
`~/.codex/config.toml`:
```toml
[mcp_servers.tugra]
command = "npx"
args = ["-y", "tugra"]
[mcp_servers.tugra.env]
TUGRA_VAULT = "/absolute/path/to/vault"
TUGRA_EVENTS = "/absolute/path/to/events"
```
Windows: use a full path (`C:\\Users\\…\\vault`). Node 20 or newer.
More client notes: [docs/install.md](https://github.com/dogrucanemek-alt/tugra/blob/main/docs/install.md).
## Shared-vault authorization (optional)
Single-user setups do **not** need this. Add `TUGRA_AUTH` only when several agents share one vault and each needs its own profile (`mcp-readonly@tugra` and others as JSON files in that directory). A missing profile then returns unauthorized. An empty `TUGRA_AUTH` is treated as unset — single-user mode stays on.
## Host library surface (not the MCP wire)
The MCP tools (`fact_search`, `fact_read`, `fact_propose`, `event_report`) enforce authorization on every call. The published package also ships `dist-paket/akis.js` and `dist-paket/yetki.js` so a **host application** (cron, mirror, cockpit) can write telemetry without going through JSON-RPC.
Those modules are public on purpose. `akisBildir({ atlaYetki: true })`, `eylem: "yetki_talebi"`, and `dosyaYoksaIzin` (default true) skip or relax the check. `harcamaEkle` mutates a profile. The host that imports them owns authorization. The MCP wire cannot set these flags — the tool schema does not accept them.
### Scale vault vs target vault
A0–A5 levels are facts (`yonetisim.yetki.a0` … `a5`) in a vault. The stdio server reads them from `TUGRA_VAULT`, or from the cockpit `kasa/` when that variable is unset.
`tugraArac` / `createTugraMcp` take an optional `kasaKok` (the write/search **target**). Scale does **not** follow that target. It defaults to `varsayilanKasa()` — the same central vault the stdio server uses. A host that points `kasaKok` at a data-only tree keeps using the cockpit / `TUGRA_VAULT` scale. To read scale from a different tree, pass `skalaKasa` explicitly.
All four tools share one resolver. This is the contract: separate target + central governance stays reachable. YAYIN/12 briefly defaulted scale to `kasaKok`; that broke the split-root host. YAYIN/13 restores the central default.
## What we do not guarantee
- **No cloud sync.** The vault is the files you pointed at. Nothing is uploaded.
- **No automatic merge.** Two writers, two files. You reconcile.
- **No delete in this release.** Retirement exists; erasure is later.
- **No automatic conflict detection.** Contradictory facts can sit side by side until a human says otherwise.
- **No hosted service.** `npx tugra` is a local stdio process.
This package is not published as a SaaS. There is no price table here.
## Requirements
- Node.js 20 or newer. This is a support decision, not a technical floor: the
package is tested on 20 and 22 in CI, and it also runs on 18 — but 18 is past
its end of life, so we do not support it.
- A vault directory you own
## Topic map (optional)
`<vault>/_konu-haritasi.json` — `{ "desen", "bayrak", "konu" }` rules in
`harita`, `alt_kirilim`, and `stem`. If the file is missing the map is empty:
unknown text falls back to `kurum.genel` or `dunya.<world>.genel`. Broken or
over-long patterns are skipped and logged. This package does not ship a
company taxonomy.
## License
Apache-2.0. See `LICENSE` and `NOTICE`.
The marketing page lives in `../site/` (`npm run preview` there). It is not deployed from this package.
Compatibility: `TUGRA_KASA`, `TUGRA_AKIS`, `TUGRA_YETKI` (and the older `TALAMUS_*` / `MULTI_*` names) still work as a fallback when the English name is unset.
TDQS
Scored across 4 tools
Each tool targets a distinct operation: searching facts, reading by UID, proposing a draft fact, and appending telemetry. There is no meaningful overlap between fact_search, fact_read, fact_propose, and event_report.
All tool names use lowercase snake_case and an object-first pattern (fact_search, fact_read, fact_propose, event_report). Although event_report lacks the fact_ prefix, it follows the same noun-verb shape, making the naming predictable and consistent.
Four tools is a well-scoped surface for a fact-store server: two retrieval paths, one proposal/write path, and one telemetry path. Each tool earns its place without redundancy or bloat.
The search/read/propose set covers the main fact consumption and contribution workflows. Direct lifecycle operations such as update, retire, or approve are absent, but the proposal mechanism and archive flag suggest a curated interface where this is an acceptable minor gap.