Runar
# Runar
Runar is a self-hosted, MCP-native context server for AI agents. It gives MCP clients a durable
place to save project knowledge and retrieve only the context that is useful for the current task.
Runar does **not** call an LLM, proxy prompts, select models, or depend on a model provider. Your
MCP client remains in control of orchestration and inference.
```text
AI client ── MCP ──> Runar ──> PostgreSQL + Markdown
│ │
│<── useful context─┘
│
└── model request ──> provider chosen by the client
```
## What you can do with Runar
- Save decisions, facts, constraints, preferences, and other reusable memories.
- Search with PostgreSQL full-text search, metadata filters, and bounded relations.
- Persist structured session notes without uploading complete chat transcripts.
- Publish reusable skills and persona packs as declarative Markdown/YAML.
- Build compact context packs with predictable item, character, and token-estimate budgets.
- Run a fixed set of safe analytics without exposing arbitrary SQL.
- Serve local clients over stdio or remote clients over Streamable HTTP.
Search results are intentionally concise. Clients can fetch full content later through MCP
resources such as `memory://<id>` and `session://<id>`.
## Quick start
You need Python 3.12 or 3.13, [uv](https://docs.astral.sh/uv/), Docker, and Docker Compose.
```bash
cp .env.example .env
uv sync
docker compose up -d postgres
uv run alembic upgrade head
uv run runar-mcp --transport stdio
```
The final command starts the local MCP server. A client configuration typically launches the same
command from this repository:
```json
{
"command": "uv",
"args": ["run", "runar-mcp", "--transport", "stdio"],
"cwd": "/absolute/path/to/runar-mcp"
}
```
Exact client configuration keys vary by MCP host. Runar writes logs to stderr so stdout remains a
clean MCP protocol stream.
To use Streamable HTTP during local development:
```bash
uv run runar-mcp --transport streamable-http
```
The endpoint is `http://127.0.0.1:8080/mcp`. Remote staging and production deployments require
OAuth configuration and HTTPS; see the [deployment guide](docs/deployment.md).
## Main MCP capabilities
| Area | Tools |
|---|---|
| Memory | `memory.propose`, `memory.read`, `memory.search`, `memory.archive` |
| Sessions | `session.write`, `session.list` |
| Context | `context.build`, `memory.analyze` |
| Skills | `skill.list`, `skill.get`, `skill.validate`, `skill.enable`, `skill.disable` |
| Persona | `persona.list`, `persona.validate` |
Full payloads, filters, permissions, resources, and error behavior are documented in the
[MCP reference](docs/mcp-reference.md).
## How data is stored
Runar uses two coordinated stores:
- PostgreSQL holds metadata, revisions, search projections, relations, sessions, jobs, and audit
events.
- Markdown files hold canonical memory and session documents.
Both are required for a complete backup. Writes are recoverable across the two stores, and
`uv run runar-cli reconcile` reports inconsistencies without deleting data automatically.
## Development checks
```bash
uv run ruff check .
uv run ruff format --check .
uv run pyright
uv run pytest
uv run runar-eval --json
```
PostgreSQL integration tests use a database selected explicitly through `TEST_DATABASE_URL`:
```bash
TEST_DATABASE_URL=postgresql+psycopg://runar:runar@localhost:5432/runar_test \
uv run pytest -m integration
```
Run `./scripts/mcp_inspector_smoke.sh` for the MCP Inspector compatibility check.
## Documentation
Start with the [documentation guide](docs/README.md), or go directly to architecture, the MCP
reference, deployment, security, backup/restore, and migrations.
## Current limits
Runar v1 uses deterministic lexical retrieval; semantic retrieval is not implemented. Relations
are bounded rather than recursively traversed. The local Markdown adapter is the implemented
canonical store, while the S3 setting is reserved for a future adapter. The built-in remote rate
limiter is process-local, so multi-instance deployments need shared ingress rate limiting.
Runar remains independent of whichever LLM, provider, or model router an MCP host chooses.
TDQS
Scored across 15 tools
Each tool is scoped to a distinct resource namespace and action, so memory, session, skill, persona, and context operations are easy to separate. The only conceptually adjacent pair, memory.search and context.build, is clearly distinguished by 'find candidates' versus 'build pack'.
All tools follow a consistent lowercase namespace.action convention with predictable verbs like list, get, validate, enable, disable, read, and write. There is no mixing of separator styles or naming patterns, so agents can infer related tools across resource types.
Fifteen tools is at the upper edge of the ideal range, but each tool maps to a necessary operation across the server's five related domains. There is no obvious redundancy or dead weight in the set.
Core workflows are covered: memories can be proposed, read, searched, archived, and analyzed; skills can be listed, inspected, validated, and toggled; sessions and contexts have write/build paths. Minor gaps exist—such as no direct memory update or persona activation tool—but archive-and-repropose and resource URI patterns provide reasonable workarounds.