MCP tools
The PLUR MCP server (@plur-ai/mcp) exposes ~24 tools. These are the same tools the OpenClaw plugin, Hermes adapter, and CLI delegate to under the hood — same names, same parameters, same return shape.
Tools are grouped below by lifecycle: session → memory → episodes → ingestion → meta → system → packs → stores.
Every tool returns _next (most logical follow-up tool) and _related (2–4 related tool names) where applicable, creating an implicit navigation graph the agent can follow without prompting.
Session lifecycle
Section titled “Session lifecycle”plur_session_start
Section titled “plur_session_start”Start a session and inject relevant engrams for the upcoming task. This is the most important tool — it’s the one that makes PLUR feel like memory rather than a tool the agent has to think about.
plur_session_start(task: string, tags?: string[]) → SessionStartResultWhen agents call it: at the start of every conversation. Adapters with lifecycle hooks (Claude Code via SessionStart, OpenClaw via bootstrap, Hermes via pre_llm_call) call it automatically. Direct callers (Cursor, Windsurf, custom) should call it as the first tool invocation per task.
What happens server-side: the engine runs plur_inject against the task, picks the top engrams within the token budget, formats them into a ## DIRECTIVES / ## CONSTRAINTS / ## ALSO CONSIDER block, and returns the formatted text along with the engram IDs for downstream feedback.
Return shape:
{ session_id: string, engrams: { text: string, // ready-to-paste system-prompt block count: number, injected_ids: string[] // for plur_feedback later }, store_stats: { engram_count: number, episode_count: number, pack_count: number }, guide: string // short instruction back to the agent}Gotchas:
- Calling
plur_session_starttwice in the same conversation is harmless but produces a new session ID — episodes can get split across IDs. Prefer one start per task. - An empty
task(e.g., the user’s first message is “hi”) still works; injection falls back to high-activation pinned engrams.
plur_session_end
Section titled “plur_session_end”End a session, capture summary and learnings.
plur_session_end( session_id?: string, summary: string, engram_suggestions: EngramSuggestion[]) → SessionEndResultWhen agents call it: before the conversation wraps up. engram_suggestions is a list of typed assertions the agent learned during the session (“user prefers terse responses,” “this codebase uses Caddy not nginx,” …). The server runs each suggestion through dedup, classification, and the candidate → active pipeline.
What happens server-side: writes a final episode for the session, processes each suggestion (some are auto-accepted, some become candidates pending recurrence), and updates activation for any engrams that were injected and not corrected.
Gotchas:
- Don’t dump every thought as a suggestion. The bar is “I’d want this engram on Monday morning.” Filter aggressively before calling.
- If
session_idis omitted, the server uses the most recent open session for the calling agent.
Memory operations
Section titled “Memory operations”plur_learn
Section titled “plur_learn”Save an engram. The explicit write path, parallel to the CLI’s plur learn.
plur_learn( statement: string, type?: "behavioral" | "terminological" | "procedural" | "architectural", domain?: string, scope?: string, tags?: string[], rationale?: string, commitment?: "exploring" | "leaning" | "decided" | "locked", pinned?: boolean, source?: string, locked_reason?: string) → LearnResultWhen agents call it: any time the user says something the agent should remember — corrections (“from now on, X”), preferences (“always Y”), conventions (“we name files Z”). With adapter hooks, this fires automatically; without hooks, the agent should call it explicitly whenever the user uses correction language.
Return shape:
{ engram: Engram, _next: "plur_feedback", _related: [...] }Gotchas:
- A self-contained
statementis critical. “Always validate input at API boundaries” beats “Do that.” commitmentdefaults toleaning— fine for most. Reservelockedfor safety/operating principles you never want to drift away from.- Setting
pinned: truemakes the engram always-load — see Activation & decay.
plur_recall_hybrid
Section titled “plur_recall_hybrid”The default search. BM25 + local embeddings + Reciprocal Rank Fusion. Fully local, zero API cost.
plur_recall_hybrid( query: string, domain?: string, scope?: string, limit?: number, // default 20 include_episodes?: boolean) → RecallResultWhen agents call it: before answering a factual question the user asks, especially anything project-specific. The PLUR convention is “check memory before guessing” — if plur_recall_hybrid returns relevant engrams, cite them; if it returns nothing, fall back to other tools.
Return shape:
{ results: Array<{ id: string, statement: string, type: string, scope: string, domain?: string, retrieval_strength: number, score: number, // RRF-fused score episode_summary?: string // if include_episodes }>, count: number, truncated: boolean, mode: "hybrid"}Gotchas:
limit > 100rarely helps and starts to bloat latency from embedding scoring.- For a sub-100ms keyword-only path, use
plur_recallinstead.
plur_recall
Section titled “plur_recall”BM25 keyword search. Instant; no embedder needed.
plur_recall(query: string, scope?: string, domain?: string, limit?: number) → RecallResultWhen to choose this over hybrid: latency-sensitive paths (inline tab-completion suggestions, real-time autocompletes), or when you know the exact word the engram uses. Otherwise default to plur_recall_hybrid.
plur_inject / plur_inject_hybrid
Section titled “plur_inject / plur_inject_hybrid”Load relevant memories for a current task — returns a structured block ready to drop into a system prompt.
plur_inject(task: string, max_engrams?: number, max_tokens?: number) → InjectResultplur_inject_hybrid(task: string, max_engrams?: number, max_tokens?: number) → InjectResultDifference from recall: recall returns by relevance to a query string. inject returns budget-aware, diversity-aware results suitable for prepending to context. The hook layer calls inject_hybrid automatically; agents rarely call it themselves.
When agents call it manually: when starting a sub-task within a session that’s substantively different from the session task (plur_session_start already injected). Example: mid-conversation pivot from “fix login bug” to “deploy frontend” — call plur_inject_hybrid("deploy frontend") to refresh context.
plur_feedback
Section titled “plur_feedback”Rate an engram. Trains future recall.
plur_feedback(id: string, signal: "positive" | "negative") → FeedbackResultWhen agents call it: at the end of a turn or session, for engrams that were injected at session start. Positive when the engram visibly helped; negative when it was off-topic or contradicted. Hooks emit implicit feedback automatically; the explicit call is reserved for the unambiguous cases.
Return shape:
{ engram_id: string, activation_delta: number, ok: true }Gotchas:
- One feedback signal moves activation a small amount; the loop matters at volume, not per-call.
- Negative signals are weighted ~3× stronger than positive — calibrate accordingly.
plur_forget
Section titled “plur_forget”Retire an engram. History preserved; eligible for un-retirement.
plur_forget(id_or_query: string, reason?: string) → ForgetResultWhen agents call it: when a saved rule was wrong (not just outdated — outdated engrams decay naturally). Include a reason so the audit trail makes sense later.
plur_promote
Section titled “plur_promote”Promote a candidate engram to active.
plur_promote(id: string) → PromoteResultCandidates are engrams created by auto-extraction that need confirmation. plur_promote makes one active immediately — useful in workflows where you ingest a batch (plur_ingest) and then promote selectively after review.
Episodes
Section titled “Episodes”plur_capture
Section titled “plur_capture”Record an episode (timestamped event).
plur_capture( summary: string, channel?: "session" | "hook" | "incident" | "mcp" | "webhook", agent?: string, links?: string[] // engram IDs to associate) → CaptureResultWhen agents call it: anything you’d put in an event log — deploys, incidents, decisions, agent-emitted milestones. Hooks call plur_capture automatically at afterTurn / on_session_end; explicit calls are for application-driven events.
plur_timeline
Section titled “plur_timeline”Query episode history.
plur_timeline( from?: ISO-date, to?: ISO-date, agent?: string, channel?: string, session?: string, limit?: number) → TimelineResultWhen agents call it: post-mortem questions (“what happened in this session before the failure?”), weekly-review questions (“what got captured in incident channel last week?”). Pair with plur_recall_hybrid for the engrams that correspond to those episodes.
plur_episode_to_engram
Section titled “plur_episode_to_engram”Promote a recurring episode into an engram.
plur_episode_to_engram(episode_id: string, type?: EngramType) → LearnResultWhen agents call it: post-mortem distillation. When an incident timeline reveals a recurring failure mode, promoting the lesson into an engram makes it persist and inject next time.
Ingestion
Section titled “Ingestion”plur_ingest
Section titled “plur_ingest”Extract engrams from arbitrary text.
plur_ingest( text: string, domain?: string, scope?: string, auto_promote?: boolean) → IngestResultWhen agents call it: meeting transcripts, ADRs, post-mortem write-ups, slack threads — anything narrative-shaped that contains engram-worthy lessons. The server runs an extractor LLM (or pattern-matcher in zero-LLM mode), surfaces candidates, and (by default) leaves them as status: candidate for review.
Return shape:
{ candidates: EngramSuggestion[], extracted: number }Gotchas:
auto_promote: truewrites directly toactive. Only use on trusted input.- Long inputs are chunked — extraction is per-chunk so context can be lost across chunk boundaries. Provide structured input where possible.
Meta-engrams
Section titled “Meta-engrams”plur_extract_meta
Section titled “plur_extract_meta”Distil cross-domain principles from your engrams. Looks for patterns that appear in multiple engrams (e.g., “validate at boundaries” appears in API, deploy, and DB engrams → meta-engram).
plur_extract_meta(scope?: string, min_examples?: number) → ExtractMetaResultWhen agents call it: rarely directly; usually as part of a scheduled maintenance pass. The Enterprise admin dashboard exposes this as a button.
plur_meta_engrams
Section titled “plur_meta_engrams”List extracted meta-engrams.
plur_meta_engrams(limit?: number) → MetaListResultplur_validate_meta
Section titled “plur_validate_meta”Test a principle against a new domain.
plur_validate_meta(meta_id: string, domain: string) → ValidateMetaResultReturns a confidence score for whether the meta-engram applies to engrams in the target domain — useful when porting principles between projects.
System
Section titled “System”plur_status
Section titled “plur_status”Health check.
plur_status() → StatusResultReturns: storage path, engram count, episode count, embedder health, index status, hook installation. The same shape as plur status --json from the CLI.
When agents call it: the user asks “is PLUR working?” or the agent suspects something’s off (tools silently returning empty results).
plur_doctor
Section titled “plur_doctor”Diagnose embedder, hooks, MCP config, permissions.
plur_doctor() → DoctorResultDetailed diagnostic — each red line includes a fix command. Same as CLI plur doctor.
plur_sync
Section titled “plur_sync”Sync engrams across machines via git.
plur_sync(remote?: string) → SyncResultFirst call requires remote; subsequent calls reuse it. The MCP path is functionally identical to the CLI’s plur sync — see Sync for the full conceptual walkthrough.
plur_packs_install
Section titled “plur_packs_install”plur_packs_install(source: string) → PacksInstallResultsource can be a local path, URL, or pack identifier (@plur-ai/datacore-conventions). The server verifies the integrity hash before importing; conflicts are surfaced for review.
plur_packs_list
Section titled “plur_packs_list”plur_packs_list() → PacksListResultplur_packs_uninstall
Section titled “plur_packs_uninstall”plur_packs_uninstall(name: string) → PacksUninstallResultRetires the engrams that came from the pack — history preserved.
plur_packs_export
Section titled “plur_packs_export”plur_packs_export( scope?: string, ids?: string[], out: string, version: string, target_scope?: string) → PacksExportResultEither scope or ids is required. Writes the pack directory with a manifest including the computed integrity hash. See Building a Knowledge Pack.
plur_packs_discover / plur_packs_preview
Section titled “plur_packs_discover / plur_packs_preview”plur_packs_discover() → PacksDiscoverResultplur_packs_preview(source: string) → PacksPreviewResultdiscover hits the static community index; preview inspects a pack’s contents without installing.
plur_stores_add
Section titled “plur_stores_add”Connect to a remote PLUR store (typically a PLUR Enterprise server).
plur_stores_add( name: string, url: string, token: string // API key from /me/api-keys) → StoresAddResultAfter this, your local PLUR can read from and write to scopes you have access to on the named store. Personal engrams (global, project:*, user:*) stay local; shared scopes (group:*, org:*) hit the server.
plur_stores_list
Section titled “plur_stores_list”plur_stores_list() → StoresListResultConventions
Section titled “Conventions”Tool response envelope
Section titled “Tool response envelope”Every tool returns a JSON object with:
{ ...payload, _next?: string, // most logical next tool _related?: string[] // 2-4 related tools}_next is contextual: a successful plur_learn suggests plur_feedback; a failed plur_recall suggests plur_inject. Agents can follow these hints without further prompting — the navigation graph is implicit in the responses.
Error responses
Section titled “Error responses”All tool errors are returned as MCP error objects with a stable code:
{ error: { code: "INVALID_SCOPE", message: "...", details: {...} } }Common codes: INVALID_SCOPE, NOT_FOUND, PERMISSION_DENIED, EMBEDDER_UNAVAILABLE, INTEGRITY_MISMATCH (pack install), VALIDATION (bad input).
Permissions (Enterprise only)
Section titled “Permissions (Enterprise only)”When the MCP server is @plur-ai/enterprise, every tool call goes through permission-wrapper.ts — the user’s resolved scope set is checked against the requested operation server-side. Local @plur-ai/mcp has no permission layer (single user); the tool surface is identical so agents work the same in both modes.
Tool name stability
Section titled “Tool name stability”Do not rename these tools. Agents trained on PLUR — including the engram store itself, which references tool names in stored engrams — expect exact names. If you’re building a custom adapter, preserve the names verbatim.