Install
$ agentstack add mcp-verevoir-mcp ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
@verevoir/mcp
MCP server exposing the Verevoir foundation as Claude-Code-usable tools. Cached file reads, tree-sitter symbol search, and kanban / issue / objective operations behind one stdio MCP process.
Purpose
Lets an LLM agent (or anyone driving Claude Code) work against multiple sources — GitHub repos, local filesystems, Notion workspaces, Trello boards, and Obsidian Kanban boards — through one stable tool surface. Reads are cached via @verevoir/context; writes go through the underlying adapter and populate the cache so subsequent reads see the new content without a refetch.
Sibling to @verevoir/sources, @verevoir/context, and @verevoir/workflows. This package wires them together as an MCP server.
Prerequisites
- Node
>=20. - One or more of:
- GitHub PAT — fine-grained, with
Contents: Read + Writeon whichever repos you want the tools to touch. AddPull requests: Read + WriteandWorkflows: Read + Writeif you'll expand the tool surface later. - Trello Power-Up — created at https://trello.com/power-ups/admin. From the Power-Up's API Key tab, generate the API key + the user token (the "Token" hyperlink on the same page). Note the allowed-origin URL — the MCP server must send it as the
Refereror Trello returns 401. - Notion integration — create one at https://www.notion.so/profile/integrations, then share the relevant pages / databases with the integration from Notion's "Connections" UI. The integration token (
ntn_…) is what you set asNOTION_API_KEY. - Obsidian Kanban — no credentials required. Pass the absolute path (or
file://URL) to a Kanban board.mdasboardUrl. Optional tuning via env vars read at call time:OBSIDIAN_VAULT_PATH,OBSIDIAN_ID_FIELD(defaultid),OBSIDIAN_CARD_FOLDER,OBSIDIAN_DATE_FIELD(defaultdue),OBSIDIAN_TAGS_FIELD(defaulttags).
Install
Option A — via npm (recommended for stable use)
npm install -g @verevoir/mcp
Or invoke via npx (no global install).
Option B — local path (recommended while iterating on the server)
Clone, build, and point your MCP config at the local dist/bin.js. Skips the publish cycle on every server change.
git clone git@github.com:verevoir/mcp.git
cd mcp
npm install
npm run build
Configuration in Claude Code
Add to ~/.claude/mcp.json:
Option A — npm
{
"mcpServers": {
"verevoir": {
"command": "npx",
"args": ["-y", "@verevoir/mcp"],
"alwaysLoad": true,
"env": {
"GITHUB_TOKEN": "ghp_...",
"TRELLO_API_KEY": "...",
"TRELLO_API_TOKEN": "...",
"TRELLO_REFERER": "https://your-power-up-origin",
"NOTION_API_KEY": "ntn_..."
}
}
}
}
Option B — local path
{
"mcpServers": {
"verevoir": {
"command": "node",
"args": ["/absolute/path/to/mcp/dist/bin.js"],
"alwaysLoad": true,
"env": {
"GITHUB_TOKEN": "ghp_...",
"TRELLO_API_KEY": "...",
"TRELLO_API_TOKEN": "...",
"TRELLO_REFERER": "https://your-power-up-origin",
"NOTION_API_KEY": "ntn_..."
}
}
}
}
Restart Claude Code (the MCP server loads at session start; claude --resume works too — it spawns a new process which re-reads mcp.json).
Pointing the server at a project
The server injects an operating doctrine into the model's context on connect. When it finds a project pointer manifest, it appends a project-specific section naming this project's work tracker, project record, and ADR database as concrete Notion URLs.
Add a verevoir-mcp block to your project's AGENTS.md. This is the way to point the server at project documentation and task trackers. AGENTS.md is already the per-repo agent context file the agent-context-file-maintained practice requires — putting the manifest there keeps the pointer with the rest of the project context, with no separate file to drift.
The server reads AGENTS.md from its working directory at startup. Add a fenced code block whose info-string is verevoir-mcp anywhere in the file; the block body is parsed as the manifest JSON:
````markdown
Project context
This repo is part of the acme project. Work tracker, decisions, and project record are in Notion — the verevoir MCP reads from there.
```verevoir-mcp { "notion": { "workspaceRootPageId": "11112222-3333-4444-5555-666677778888", "databases": { "work_tracker": "aaaa1111-2222-3333-4444-555566667777", "adrs": "bbbb1111-2222-3333-4444-555566667777" } }, "governance": [ { "source": "../guardrails", "paths": ["corpus/practices"] } ] }
````
**Resolution precedence.** The server tries each source in order; the first that yields a valid manifest wins:
1. `--manifest ` — explicit flag, always wins. Accepts a JSON file or a Markdown file containing the `verevoir-mcp` block. Supply it after the script path: `"args": ["/path/to/mcp/dist/bin.js", "--manifest", "/path/to/project/AGENTS.md"]`. Throws on a missing/bad flag value — a botched arg fails loudly rather than silently dropping to no-project mode.
2. `AGENTS.md` in the working directory — if it contains a `verevoir-mcp` fenced block with valid JSON (the recommended path above).
3. `verevoir-mcp.json` in the working directory — accepted fallback; no dedicated setup example here.
4. `aigency.json` in the working directory — legacy fallback; accepted long-term but not the recommended approach.
5. None found → **no-project mode**: the server still starts and serves the universal doctrine; only the project-specific section is omitted.
A present-but-malformed source at any step (bad JSON, missing block) is skipped gracefully and resolution continues to the next candidate.
#### Why `"alwaysLoad": true`
Without this flag, Claude Code auto-defers MCP tool schemas when total tool definitions exceed ~10% of the context window — only tool _names_ are sent up front; the model must call `ToolSearch` to load each schema before using it. That extra step makes the verevoir tools lose against always-on shell reflex (`grep`, `cat`, `find`) at the moment of choosing a tool — defeating the cache + freshness benefits of the MCP layer. `alwaysLoad: true` (Claude Code v2.1.121+) forces every tool from this server into the session at startup, so `read_file` / `grep` / `find_symbol` / `list_cards` are reflex-reachable. Older Claude Code versions ignore the flag (no breakage). The cost is ~2–5KB of context — worth it.
Env vars are read per-tool: GitHub tools only need `GITHUB_TOKEN`; Trello tools only need the three `TRELLO_*` vars; Notion tools (both source and workflow) only need `NOTION_API_KEY`. The server starts regardless of which are set — missing-env errors surface at tool-call time with clear messages naming the variable.
## Using with other MCP clients
`@verevoir/mcp` is a stdio server and works with any MCP client. See [docs/clients.md](docs/clients.md) for per-client config snippets covering Warp, Cursor, Gemini CLI, OpenAI Codex CLI, opencode, Cline, Continue, and Zed.
## Sanity check
Once configured + restarted, ask Claude to call `list_columns` against your Trello board. You should get an array of columns back. If you see "TRELLO_API_KEY not set" or "Trello returned 401: invalid key", the auth env or the Power-Up referer mismatch is the cause.
## Prompts
The server also registers the guardrails **reasoning skills** (`corpus/skills/*.md`) as MCP prompts. Invoking a prompt returns the skill's instructions plus your supplied arguments as a message for **your** model to execute — so a skill runs on the host's own tokens. Deterministic (handler-backed) skills are not registered as prompts; the host usually already has those capabilities. The corpus source defaults to the canonical guardrails repo and is overridable with `AIGENCY_GUARDRAILS_URL`; loading is best-effort, so a missing `GITHUB_TOKEN` simply means no skill prompts are registered. Requires an MCP client that supports prompts.
## Tools
### Source tools (file-shape sources)
All take a `sourceUrl` and route to the appropriate cached adapter:
- `https://github.com/owner/repo` → cached GitHub adapter.
- `https://www.notion.so//` (or any notion.so URL form) → cached Notion adapter. Pages become "files"; child pages become "subdirectories"; reads/writes traverse `path` through the page tree.
- Absolute filesystem path (or `file://...`) → cached FS adapter.
| Tool | Args | Returns |
| ------------------- | -------------------------------------------------------- | ---------------------- |
| `read_file` | `{ sourceUrl, path, ref? }` | `{ content, sha }` |
| `list_files` | `{ sourceUrl, prefix?, ref? }` | `DirEntry[]` |
| `get_repo_tree` | `{ sourceUrl, ref? }` | `RepoTree` |
| `grep` | `{ sourceUrl, pattern, ref?, ignoreCase?, maxResults? }` | `GrepHit[]` |
| `find_symbol` | `{ sourceUrl, name, ref?, kind? }` | `SymbolHit[]` |
| `write_file` | `{ sourceUrl, path, content, branch, commitMessage }` | `{ ok: true }` |
| `edit_file` | `{ sourceUrl, path, oldString, newString, branch?, … }` | `{ ok, replacements }` |
| `ensure_fork` | `{ sourceUrl }` | `{ workingUrl }` |
| `ensure_branch` | `{ workingUrl, branch }` | `{ ok, branch }` |
| `open_pull_request` | `{ sourceUrl, workingUrl, branch, base, title, body }` | `{ prUrl }` |
`grep` and `find_symbol` operate on **cached** content only — call `read_file` first on any files you want searchable. The cache is per-process, lazy-population.
**Fork-isolated write flow (GitHub).** A repo is addressed by its **source URL** — its identity and the PR target. Once forked, the fork is the **working URL**: the workspace you actually read, write, branch, and commit on. The source repo is never written directly; it only ever receives a pull request from the fork — so an agent can change a repo it does **not** own _hermetically_. The shape:
1. `ensure_fork(sourceUrl)` → `{ workingUrl }` — forks into the configured fork org, idempotent.
2. `ensure_branch(workingUrl, branch)` — branch on the fork.
3. `write_file` / `edit_file` against the **workingUrl** — the change lands on the fork.
4. `open_pull_request(sourceUrl, workingUrl, branch, base, …)` — the cross-repo head (`:branch`) is built from the working URL for you; the PR is opened against the source.
For a repo you own, pass the same URL for both `sourceUrl` and `workingUrl` (a same-repo PR, no fork).
### Workflow tools (kanban / issue / objective sources)
All take a `boardUrl`:
- `https://trello.com/b/` → Trello adapter.
- `https://www.notion.so//?v=...` (or any notion.so URL form pointing at a database) → Notion adapter. Rows become `Card`s; auto-detects which property is the status / column from the database schema.
- Absolute filesystem path or `file://` URL ending in `.md` → Obsidian Kanban adapter. Local board `.md`; `## headings` are columns; `- [ ] [[Note]]` wikilinks are cards; the linked note is the card source of truth; no credentials required.
- Absolute filesystem path or `file://` URL to a **directory** (the project root or its `backlog/` dir) → Backlog.md adapter. `backlog/config.yml` statuses are columns; `backlog/tasks/*.md` are cards (frontmatter `id` / `title` / `status` / `labels` / `assignee` / `parent_task_id`, markdown body as the description); for tracking work as committable files inside a code repo; no credentials required.
| Tool | Args | Returns |
| --------------- | ----------------------------------------------------------------------------------- | -------------- |
| `list_columns` | `{ boardUrl }` | `Column[]` |
| `list_cards` | `{ boardUrl, columnId?, assigneeId?, labelId?, parentId? }` | `Card[]` |
| `get_card` | `{ boardUrl, cardId }` | `Card` |
| `create_card` | `{ boardUrl, columnId, title, body?, labelIds?, assigneeIds?, dueDate? }` | `Card` |
| `update_card` | `{ boardUrl, cardId, title?, body?, columnId?, labelIds?, assigneeIds?, dueDate? }` | `{ ok: true }` |
| `move_card` | `{ boardUrl, cardId, toColumnId }` | `{ ok: true }` |
| `list_comments` | `{ boardUrl, cardId }` | `Comment[]` |
| `add_comment` | `{ boardUrl, cardId, body }` | `{ ok: true }` |
### Governance tools
Surface the project's governance — the ADRs / principles / glossary in the project record, and the **practices** (quality standards) in the guardrails corpus.
| Tool | Args | Returns |
| ----------------- | --------------------------------- | -------------------------------------------------------------------------------------- |
| `find_governance` | `{ query? }` | A scannable, narrowable index of governance entries (title + how to `read_file` each). |
| `provision` | `{ prose?, concerns?, autoTag? }` | The **practices held to** + the **capabilities that may fit**, in one call. |
`provision` reads from the guardrails corpus (override the source with `AIGENCY_GUARDRAILS_URL`).
- **Practices** (the bar): the foundational floor always comes back in full, with no model call. How the concern practices are chosen depends on the caller (STDIO-348):
- **default** — the floor plus a **menu** of the concern practices (id + one-line summary). A capable coordinator sees the whole task, so it narrows the menu itself and calls back with `concerns: ['id', …]` to pull the bodies — no key, and it out-selects an isolated classifier (which only ever sees a prose blurb).
- **`concerns: [...]`** — the floor plus exactly those concern bodies: a complete frame you can inject into a worker.
- **`autoTag: true`** — for a weak/headless caller with no coordinator to narrow: select the concerns in-MCP via the configured reasoning provider (needs its key, e.g. `ANTHROPIC_API_KEY`). `delegate` uses this for its worker. The only path that needs a key.
- **Capabilities** (pre-built procedures, advisory): retrieved via an embedding bin when an embeddings endpoint is configured — `AIGENCY_EMBEDDINGS_API_KEY` (falls back to `OPENAI_API_KEY`), `AIGENCY_EMBEDDINGS_URL` (default OpenAI; point at any OpenAI-compatible provider — Mistral / DeepSeek / Voyage / …), `AIGENCY_EMBEDDINGS_MODEL` (default `text-embedding-3-small`). No endpoint → the capability section is omitted.
Both halves degrade gracefully — an unreadable source, a failed tagging call, or a retrieval error falls back rather than erroring.
Every frame is prefixed with a **corpus trust-boundary banner** (STDIO-399): the governance is injected into the model's prompt, so the banner frames it as the bar for _standards_, not a channel for commands — an instruction embedded in a practice/capability body is a poisoning _finding_ to report rather than follow. When the corpus is loaded from a non-canonical `AIGENCY_GUARDRAILS_URL`, the banner discloses that provenance.
### Worker tools (delegate / dispatch)
`delegate` hands a self-contained sub-task
…
## Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [verevoir](https://github.com/verevoir)
- **Source:** [verevoir/mcp](https://github.com/verevoir/mcp)
- **License:** Apache-2.0
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.