@plur-ai/mcp
Advanced tools
Sorry, the diff of this file is too big to display
| import { | ||
| CURSOR_CORE_TOOL_NAMES, | ||
| VERSION, | ||
| getToolDefinitions, | ||
| mcpCanary, | ||
| registerFlushOnExit, | ||
| validateToolArgs | ||
| } from "./chunk-TPL7QPPO.js"; | ||
| // src/server.ts | ||
| import { Server, ProtocolError, ProtocolErrorCode } from "@modelcontextprotocol/server"; | ||
| import { StdioServerTransport } from "@modelcontextprotocol/server/stdio"; | ||
| import { existsSync, readFileSync, writeFileSync } from "fs"; | ||
| import { join } from "path"; | ||
| import { homedir } from "os"; | ||
| import { Plur, checkForUpdate } from "@plur-ai/core"; | ||
| function serverPidPath(baseDir) { | ||
| return join(baseDir ?? join(homedir(), ".plur"), "server.pid"); | ||
| } | ||
| function readEnterpriseToken(baseDir) { | ||
| const configPath = join(baseDir ?? join(homedir(), ".plur"), "config.json"); | ||
| if (!existsSync(configPath)) return void 0; | ||
| try { | ||
| const cfg = JSON.parse(readFileSync(configPath, "utf8")); | ||
| const ent = cfg?.enterprise; | ||
| if (!ent || typeof ent.url !== "string" || typeof ent.token !== "string") return void 0; | ||
| return { url: ent.url, token: ent.token, username: ent.username }; | ||
| } catch { | ||
| return void 0; | ||
| } | ||
| } | ||
| var _pendingReload = false; | ||
| function isPendingReload() { | ||
| return _pendingReload; | ||
| } | ||
| function clearPendingReload() { | ||
| _pendingReload = false; | ||
| } | ||
| var INSTRUCTIONS = `PLUR is your persistent memory. Corrections, preferences, and conventions persist across sessions as engrams. | ||
| PLUR is a GLOBAL tool \u2014 one MCP server, one engram store (~/.plur/), available in every project. Multi-project scoping uses domain/scope fields on engrams, not separate installations. | ||
| TOOL PROFILE: by default only the core session tools are exposed directly (lean profile). Every other plur_* operation is reachable via plur_admin: { action: "<tool name>", args: {...} } \u2014 same arguments and validation as a direct call. PLUR_TOOL_PROFILE=full exposes everything directly. | ||
| SESSION LIFECYCLE: | ||
| - With hooks installed (plur init): engrams are injected automatically on first message. You do NOT need to call plur_session_start \u2014 it happens via hooks. Just call plur_session_end before the conversation ends. | ||
| - Without hooks: call plur_session_start at the start, plur_session_end at the end. | ||
| DURING the session: | ||
| - When user corrects you ("no, use X not Y") \u2192 call plur_learn immediately | ||
| - When user states a preference ("always X", "never Y") \u2192 call plur_learn immediately | ||
| - When you discover a codebase convention or pattern \u2192 call plur_learn | ||
| SCOPE SELECTION (set scope PER engram, by content \u2014 not once per session): | ||
| A single session produces engrams that belong in different stores. Choose the | ||
| "scope" on EACH plur_learn call from what the engram is about: | ||
| - Team / engineering / architecture / shared-convention knowledge \u2192 the matching | ||
| team store scope (e.g. "group:<org>/<team>"). plur_session_start lists the | ||
| scopes this install can write to \u2014 use them. | ||
| - Personal preferences, your workflow, or details specific to one project \u2192 the | ||
| default/local scope (or "project:<name>"). | ||
| - "global" is for genuinely cross-project facts only (language gotchas, tool | ||
| quirks). Do NOT let team-relevant knowledge fall back to "global" by omitting | ||
| scope \u2014 with a team store configured it never reaches the team store. If no | ||
| scope fits, prefer the project/local default over global. | ||
| OPTIONAL but improves quality: | ||
| - Call plur_feedback to rate which injected engrams helped (positive/negative) | ||
| - Call plur_recall before answering factual questions \u2014 the answer may be in memory | ||
| Do not ask permission to use these tools \u2014 they are your memory system. | ||
| Setup: If this is a fresh install, suggest the user run: npx @plur-ai/mcp init | ||
| This installs hooks for automatic injection + session management. One-time global setup.`; | ||
| var GUIDE_RESOURCE = `# PLUR \u2014 Agent Guide | ||
| ## What is PLUR? | ||
| Persistent memory for AI agents. Corrections, preferences, and conventions are stored as **engrams** \u2014 small assertions that strengthen with use and decay when irrelevant (ACT-R model). Storage is plain YAML on disk. Search is fully local (BM25 + embeddings). Zero API calls. | ||
| ## Quick Start | ||
| 1. \`plur_session_start\` \u2014 start a session, inject relevant context | ||
| 2. \`plur_learn\` \u2014 store a new learning | ||
| 3. \`plur_feedback\` \u2014 rate injected engrams | ||
| 4. \`plur_session_end\` \u2014 capture summary and new learnings | ||
| ## When to Call Each Tool | ||
| | Trigger | Tool | | ||
| |---------|------| | ||
| | Session starts | \`plur_session_start\` with task description | | ||
| | User corrects you | \`plur_learn\` with the correction | | ||
| | User states preference ("always X", "never Y") | \`plur_learn\` with scope and type | | ||
| | You used a recalled engram successfully | \`plur_feedback\` with "positive" | | ||
| | A recalled engram was wrong or irrelevant | \`plur_feedback\` with "negative" | | ||
| | User says "forget X" or a memory is outdated | \`plur_forget\` | | ||
| | You need to check what's stored | \`plur_status\` or \`plur_packs_list\` | | ||
| | User asks what memory did for them / is memory working | \`plur_receipt\` (relay its \`summary\`; activation_rate is coverage, not quality) | | ||
| | End of session | \`plur_session_end\` with summary and suggestions | | ||
| ## Tool Categories | ||
| ### Session Management | ||
| - **plur_session_start** \u2014 start a session, inject relevant context | ||
| - **plur_session_end** \u2014 end a session, capture summary and new learnings | ||
| ### Core Memory | ||
| - **plur_learn** \u2014 store a correction, preference, or convention | ||
| - **plur_recall** \u2014 hybrid search by default (BM25 + embeddings); pass mode:"keyword" for BM25-only | ||
| - **plur_feedback** \u2014 rate an engram (trains relevance) | ||
| - **plur_forget** \u2014 retire an outdated engram | ||
| - **plur_promote** \u2014 activate a candidate engram | ||
| ### Context Injection | ||
| - **plur_inject** \u2014 select engrams for a task (BM25) | ||
| - **plur_inject_hybrid** \u2014 select engrams for a task (BM25 + embeddings, recommended) | ||
| ### Episodic Timeline | ||
| - **plur_capture** \u2014 record what happened in a session | ||
| - **plur_timeline** \u2014 query past episodes | ||
| ### Knowledge Management | ||
| - **plur_ingest** \u2014 extract engrams from text content | ||
| - **plur_packs_install** \u2014 install curated engram packs | ||
| - **plur_packs_list** \u2014 list installed packs | ||
| - **plur_packs_export** \u2014 export engrams as a shareable pack | ||
| ### Multi-Store | ||
| - **plur_stores_add** \u2014 register an additional engram store | ||
| - **plur_stores_list** \u2014 list all configured stores | ||
| **Note:** Multi-store is currently config-only. Recall and inject search the primary store. Cross-store search coming in a future release. | ||
| ### Sync & Status | ||
| - **plur_sync** \u2014 sync engrams across devices via git | ||
| - **plur_sync_status** \u2014 check sync state | ||
| - **plur_status** \u2014 system health | ||
| - **plur_receipt** \u2014 counted report of what memory retrieved for the user (local, read-only) | ||
| ## Scoping | ||
| Use \`scope\` to namespace engrams per project: | ||
| - \`scope: "global"\` \u2014 applies everywhere (default) | ||
| - \`scope: "project:my-app"\` \u2014 applies only to my-app | ||
| - Scoped recall automatically includes global engrams | ||
| ## Storage | ||
| \`\`\` | ||
| ~/.plur/ | ||
| \u251C\u2500\u2500 engrams.yaml # learned knowledge | ||
| \u251C\u2500\u2500 episodes.yaml # session timeline | ||
| \u2514\u2500\u2500 config.yaml # settings | ||
| \`\`\` | ||
| Override with \`PLUR_PATH\` environment variable. | ||
| `; | ||
| async function createServer(plur, options) { | ||
| const instance = plur ?? new Plur(); | ||
| const tools = getToolDefinitions(options?.profile ?? "lean"); | ||
| checkForUpdate("@plur-ai/mcp", VERSION, (r) => { | ||
| if (r.updateAvailable) { | ||
| console.error(`[plur] Update available: ${r.current} \u2192 ${r.latest}. Run: npx @plur-ai/mcp@latest`); | ||
| } | ||
| }); | ||
| const server = new Server( | ||
| { name: "plur-mcp", version: VERSION }, | ||
| { | ||
| capabilities: { | ||
| tools: {}, | ||
| resources: {}, | ||
| prompts: {}, | ||
| logging: {} | ||
| }, | ||
| instructions: INSTRUCTIONS | ||
| } | ||
| ); | ||
| server.setRequestHandler("tools/list", async () => ({ | ||
| tools: tools.map((t) => ({ | ||
| name: t.name, | ||
| description: t.description, | ||
| inputSchema: t.inputSchema, | ||
| ...t.annotations && { annotations: t.annotations } | ||
| })) | ||
| })); | ||
| server.setRequestHandler("tools/call", async (request) => { | ||
| const tool = tools.find((t) => t.name === request.params.name); | ||
| if (!tool) { | ||
| const hidden = getToolDefinitions("full").find((t) => t.name === request.params.name); | ||
| if (hidden) { | ||
| return { | ||
| content: [{ type: "text", text: JSON.stringify({ | ||
| error: `Tool "${request.params.name}" exists but is not directly callable under the current tool profile.`, | ||
| success: false, | ||
| hint: `Call it via plur_admin: { action: "${request.params.name}", args: { ... } } \u2014 same arguments, same validation, same result. To expose all tools directly, set PLUR_TOOL_PROFILE=full.` | ||
| }) }], | ||
| isError: true | ||
| }; | ||
| } | ||
| return { | ||
| content: [{ type: "text", text: JSON.stringify({ error: `Unknown tool: ${request.params.name}`, success: false }) }], | ||
| isError: true | ||
| }; | ||
| } | ||
| mcpCanary.tick(); | ||
| try { | ||
| let args = request.params.arguments ?? {}; | ||
| const validated = validateToolArgs(tool, args); | ||
| if (!validated.ok) { | ||
| return { | ||
| content: [{ type: "text", text: JSON.stringify(validated.errorPayload) }], | ||
| isError: true | ||
| }; | ||
| } | ||
| args = validated.data; | ||
| const result = await tool.handler(args, instance); | ||
| let payload = result; | ||
| let resultIsError = false; | ||
| if (result && typeof result === "object" && result._isError === true) { | ||
| resultIsError = true; | ||
| const { _isError, ...rest } = result; | ||
| payload = rest; | ||
| } | ||
| return { | ||
| content: [{ type: "text", text: JSON.stringify(payload, null, 2) }], | ||
| ...resultIsError ? { isError: true } : {} | ||
| }; | ||
| } catch (err) { | ||
| const message = err?.message ?? String(err); | ||
| server.sendLoggingMessage({ level: "error", data: `Tool ${request.params.name} failed: ${message}` }); | ||
| return { | ||
| content: [{ type: "text", text: JSON.stringify({ error: message, success: false }) }], | ||
| isError: true | ||
| }; | ||
| } | ||
| }); | ||
| server.setRequestHandler("resources/list", async () => ({ | ||
| resources: [ | ||
| { | ||
| uri: "plur://guide", | ||
| name: "PLUR Agent Guide", | ||
| description: "Complete reference for all PLUR tools, when to use them, scoping, and storage", | ||
| mimeType: "text/markdown" | ||
| }, | ||
| { | ||
| uri: "plur://status", | ||
| name: "PLUR Status", | ||
| description: "Live system health \u2014 engram count, episode count, pack count, storage path", | ||
| mimeType: "application/json" | ||
| } | ||
| ] | ||
| })); | ||
| server.setRequestHandler("resources/read", async (request) => { | ||
| const uri = request.params.uri; | ||
| if (uri === "plur://guide") { | ||
| const cursorNote = options?.profile === "cursor" || options?.profile === "lean" || options?.profile == null ? ` | ||
| ## Lean tool profile (default) | ||
| Most tools above are NOT directly callable in this session \u2014 only ${[...CURSOR_CORE_TOOL_NAMES].join(", ")} are top-level tools here. Everything else in this guide is reachable through **plur_admin**: call it with \`{ action: "<tool name above>", args: {...} }\`. Set \`PLUR_TOOL_PROFILE=full\` to expose all ${getToolDefinitions("full").length} tools directly.` : ""; | ||
| return { | ||
| contents: [{ | ||
| uri: "plur://guide", | ||
| mimeType: "text/markdown", | ||
| text: GUIDE_RESOURCE + cursorNote | ||
| }] | ||
| }; | ||
| } | ||
| if (uri === "plur://status") { | ||
| const status = await instance.status(); | ||
| return { | ||
| contents: [{ | ||
| uri: "plur://status", | ||
| mimeType: "application/json", | ||
| text: JSON.stringify({ | ||
| engram_count: status.engram_count, | ||
| episode_count: status.episode_count, | ||
| pack_count: status.pack_count, | ||
| storage_root: status.storage_root, | ||
| version: VERSION | ||
| }, null, 2) | ||
| }] | ||
| }; | ||
| } | ||
| throw new ProtocolError(ProtocolErrorCode.InvalidRequest, `Unknown resource: ${uri}`); | ||
| }); | ||
| server.setRequestHandler("prompts/list", async () => ({ | ||
| prompts: [ | ||
| { | ||
| name: "plur-getting-started", | ||
| description: "Step-by-step guide to set up and start using PLUR memory" | ||
| }, | ||
| { | ||
| name: "plur-session-start", | ||
| description: "Load relevant context for a task \u2014 call at the start of each session", | ||
| arguments: [ | ||
| { name: "task", description: "Brief description of the task or goal", required: true }, | ||
| { name: "scope", description: "Project scope (e.g. project:my-app)", required: false } | ||
| ] | ||
| } | ||
| ] | ||
| })); | ||
| server.setRequestHandler("prompts/get", async (request) => { | ||
| const name = request.params.name; | ||
| if (name === "plur-getting-started") { | ||
| const status = await instance.status(); | ||
| return { | ||
| description: "Get started with PLUR memory", | ||
| messages: [{ | ||
| role: "user", | ||
| content: { | ||
| type: "text", | ||
| text: `I just set up PLUR. Here's my current status: | ||
| - Engrams stored: ${status.engram_count} | ||
| - Episodes recorded: ${status.episode_count} | ||
| - Packs installed: ${status.pack_count} | ||
| - Storage: ${status.storage_root} | ||
| ${status.engram_count === 0 ? `I have no memories yet. Help me get started by: | ||
| 1. Teaching me a coding preference or convention (I'll use plur_learn) | ||
| 2. Then recalling it to verify it works (I'll use plur_recall) | ||
| 3. Rating the recall quality (I'll use plur_feedback)` : `I have ${status.engram_count} engrams stored. Try asking me something related to your project \u2014 I'll check my memory first.`}` | ||
| } | ||
| }] | ||
| }; | ||
| } | ||
| if (name === "plur-session-start") { | ||
| const task = request.params.arguments?.task ?? "general work"; | ||
| const scope = request.params.arguments?.scope; | ||
| return { | ||
| description: "Load relevant context for this session", | ||
| messages: [{ | ||
| role: "user", | ||
| content: { | ||
| type: "text", | ||
| text: `Starting a new session. Task: ${task}${scope ? ` (scope: ${scope})` : ""} | ||
| Please: | ||
| 1. Call plur_recall with query "${task}"${scope ? ` and scope "${scope}"` : ""} to load relevant memories | ||
| 2. Review the recalled engrams and apply any relevant conventions or preferences | ||
| 3. If any recalled engrams are helpful, call plur_feedback with "positive" | ||
| 4. If any are irrelevant, call plur_feedback with "negative"` | ||
| } | ||
| }] | ||
| }; | ||
| } | ||
| throw new ProtocolError(ProtocolErrorCode.InvalidRequest, `Unknown prompt: ${name}`); | ||
| }); | ||
| return server; | ||
| } | ||
| async function runStdio() { | ||
| const envProfile = process.env.PLUR_TOOL_PROFILE; | ||
| const profile = envProfile === "full" ? "full" : envProfile === "cursor" ? "cursor" : "lean"; | ||
| const server = await createServer(void 0, { profile }); | ||
| registerFlushOnExit({}); | ||
| try { | ||
| writeFileSync(serverPidPath(), String(process.pid)); | ||
| } catch { | ||
| } | ||
| if (process.platform !== "win32") { | ||
| process.on("SIGUSR1", () => { | ||
| _pendingReload = true; | ||
| }); | ||
| } | ||
| const transport = new StdioServerTransport(); | ||
| await server.connect(transport); | ||
| } | ||
| export { | ||
| INSTRUCTIONS, | ||
| clearPendingReload, | ||
| createServer, | ||
| isPendingReload, | ||
| readEnterpriseToken, | ||
| runStdio, | ||
| serverPidPath | ||
| }; |
| import { Plur } from '@plur-ai/core'; | ||
| interface ToolAnnotations { | ||
| title?: string; | ||
| readOnlyHint?: boolean; | ||
| destructiveHint?: boolean; | ||
| idempotentHint?: boolean; | ||
| openWorldHint?: boolean; | ||
| } | ||
| interface ToolDefinition { | ||
| name: string; | ||
| description: string; | ||
| inputSchema: { | ||
| type: 'object'; | ||
| [key: string]: unknown; | ||
| }; | ||
| annotations?: ToolAnnotations; | ||
| handler: (args: Record<string, unknown>, plur: Plur) => Promise<unknown>; | ||
| } | ||
| /** | ||
| * Validate raw tool-call arguments against a ToolDefinition's inputSchema. | ||
| * Shared by the top-level CallToolRequestSchema handler (server.ts) and the | ||
| * plur_admin dispatch handler below — one validation path AND one error- | ||
| * formatting path, not two that can drift. (An earlier draft of this plan | ||
| * only shared the Zod validation and left the #297 array-bug hint / isError | ||
| * flag duplicated in server.ts alone — audit review caught that plur_admin's | ||
| * ~30 dispatched tools would silently lose both. errorPayload below is the | ||
| * fix: the full formatted error, including the `_isError` marker server.ts | ||
| * checks generically after ANY tool handler returns, not just this one.) | ||
| */ | ||
| declare function validateToolArgs(tool: ToolDefinition, rawArgs: Record<string, unknown>): { | ||
| ok: true; | ||
| data: Record<string, unknown>; | ||
| } | { | ||
| ok: false; | ||
| errorPayload: { | ||
| error: string; | ||
| success: false; | ||
| received_fields: string[]; | ||
| _isError: true; | ||
| }; | ||
| }; | ||
| type ToolProfile = 'full' | 'lean' | 'cursor'; | ||
| declare const CURSOR_CORE_TOOL_NAMES: ReadonlySet<string>; | ||
| declare function getToolDefinitions(profile?: ToolProfile): ToolDefinition[]; | ||
| /** | ||
| * Side-effect-free subpath export: @plur-ai/mcp/tools | ||
| * | ||
| * Importable without starting the MCP server or parsing process.argv. | ||
| * Use this to access PLUR's tool surface — names, descriptions, input schemas | ||
| * — from a consumer that re-exposes or validates the definitions without | ||
| * running the server. | ||
| */ | ||
| /** Tool definition without the runtime handler — plain data, safe to serialize. */ | ||
| interface ToolSchema { | ||
| name: string; | ||
| description: string; | ||
| inputSchema: { | ||
| type: 'object'; | ||
| [key: string]: unknown; | ||
| }; | ||
| annotations?: ToolAnnotations; | ||
| } | ||
| /** | ||
| * Return tool definitions as plain, handler-free schema objects. | ||
| * | ||
| * Useful when you need the MCP tool surface — name, description, and input | ||
| * schema — without the runtime handlers that require a live Plur instance. | ||
| * A downstream consumer that re-exposes a filtered subset can import this | ||
| * list and keep its copy in sync without duplicating schemas. | ||
| */ | ||
| declare function getToolSchemas(profile?: ToolProfile): ToolSchema[]; | ||
| export { CURSOR_CORE_TOOL_NAMES, type ToolAnnotations, type ToolDefinition, type ToolProfile, type ToolSchema, getToolDefinitions, getToolSchemas, validateToolArgs }; |
| import { | ||
| CURSOR_CORE_TOOL_NAMES, | ||
| getToolDefinitions, | ||
| validateToolArgs | ||
| } from "./chunk-TPL7QPPO.js"; | ||
| // src/tools-export.ts | ||
| function getToolSchemas(profile) { | ||
| return getToolDefinitions(profile).map(({ name, description, inputSchema, annotations }) => ({ | ||
| name, | ||
| description, | ||
| inputSchema, | ||
| ...annotations !== void 0 ? { annotations } : {} | ||
| })); | ||
| } | ||
| export { | ||
| CURSOR_CORE_TOOL_NAMES, | ||
| getToolDefinitions, | ||
| getToolSchemas, | ||
| validateToolArgs | ||
| }; |
+6
-6
@@ -8,3 +8,3 @@ #!/usr/bin/env node | ||
| import { homedir, platform } from "os"; | ||
| var VERSION = "0.15.0"; | ||
| var VERSION = "0.16.0"; | ||
| var HELP = `plur-mcp v${VERSION} \u2014 persistent memory for AI agents | ||
@@ -109,3 +109,3 @@ | ||
| 2. **Learn**: When corrected or discovering something new, call \`plur_learn\` immediately | ||
| 3. **Recall**: Before answering factual questions, call \`plur_recall_hybrid\` \u2014 check memory first | ||
| 3. **Recall**: Before answering factual questions, call \`plur_recall\` \u2014 check memory first | ||
| 4. **Feedback**: Rate injected engrams with \`plur_feedback\` (positive/negative) \u2014 trains relevance | ||
@@ -238,3 +238,3 @@ 5. **End**: Call \`plur_session_end\` with summary + engram_suggestions \u2014 a SessionEnd hook auto-closes the lifecycle if you forget, but calling it yourself captures higher-quality learnings | ||
| try { | ||
| plur.installPack(join(bundledPacksDir, entry)); | ||
| await plur.installPack(join(bundledPacksDir, entry)); | ||
| newPacks.push(entry); | ||
@@ -245,3 +245,3 @@ } catch { | ||
| try { | ||
| plur.installPack(join(bundledPacksDir, entry)); | ||
| await plur.installPack(join(bundledPacksDir, entry)); | ||
| upgradedPacks.push( | ||
@@ -292,3 +292,3 @@ `${entry} ${installedVersion ?? "unknown"}\u2192${bundledVersion}` | ||
| try { | ||
| const result = plur.installPack(source); | ||
| const result = await plur.installPack(source); | ||
| process.stdout.write(`Installed pack '${result.name}' (${result.installed} engrams) | ||
@@ -359,3 +359,3 @@ `); | ||
| if (arg === "serve" || arg === void 0) { | ||
| const { runStdio } = await import("./server-7JVOIBJV.js"); | ||
| const { runStdio } = await import("./server-VHSO4XMV.js"); | ||
| runStdio().catch((err) => { | ||
@@ -362,0 +362,0 @@ console.error("Failed to start PLUR MCP server:", err); |
+6
-2
| { | ||
| "name": "@plur-ai/mcp", | ||
| "mcpName": "io.github.plur-ai/plur", | ||
| "version": "0.15.0", | ||
| "version": "0.16.0", | ||
| "type": "module", | ||
@@ -19,3 +19,3 @@ "bin": { | ||
| "zod": "^3.23.0", | ||
| "@plur-ai/core": "0.15.0" | ||
| "@plur-ai/core": "0.16.0" | ||
| }, | ||
@@ -47,2 +47,6 @@ "devDependencies": { | ||
| "import": "./dist/index.js" | ||
| }, | ||
| "./tools": { | ||
| "types": "./dist/tools-export.d.ts", | ||
| "import": "./dist/tools-export.js" | ||
| } | ||
@@ -49,0 +53,0 @@ }, |
@@ -93,3 +93,3 @@ engrams: | ||
| Before answering factual questions about the user's project, codebase, | ||
| preferences, infrastructure, or past decisions, call plur_recall_hybrid | ||
| preferences, infrastructure, or past decisions, call plur_recall | ||
| first. The answer may already be in memory. Do not fabricate or compose | ||
@@ -103,6 +103,6 @@ answers from prior-conversation context — that context is often stale | ||
| domain: plur.recall | ||
| tags: [recall, search, before-answering, plur_recall_hybrid, confabulation] | ||
| tags: [recall, search, before-answering, plur_recall, confabulation] | ||
| activation: { retrieval_strength: 0.95, storage_strength: 0.95, frequency: 0, last_accessed: "2026-05-04" } | ||
| dual_coding: | ||
| example: "User asks 'how do we deploy to production?' — call plur_recall_hybrid('deployment production') before answering. You might find 'deploy requires git push to nightshift server, not GitHub' from a previous session." | ||
| example: "User asks 'how do we deploy to production?' — call plur_recall('deployment production') before answering. You might find 'deploy requires git push to nightshift server, not GitHub' from a previous session." | ||
| analogy: "Like checking your notes before answering a question in a meeting, instead of guessing." | ||
@@ -109,0 +109,0 @@ pack: effective-memory |
@@ -42,3 +42,3 @@ --- | ||
| - **Capture** — call `plur_learn` immediately on corrections; detect correction-shaped phrases. | ||
| - **Recall** — `plur_recall_hybrid` before factual answers; don't confabulate. | ||
| - **Recall** — `plur_recall` before factual answers; don't confabulate. | ||
| - **Session lifecycle** — bookend with `plur_session_start` / `plur_session_end`; `plur_feedback` on injected engrams; `plur_timeline` for long-horizon agents. | ||
@@ -45,0 +45,0 @@ - **Verification** — artifact-first; never bulk-mark as done from narrative text. |
+4
-3
@@ -49,3 +49,3 @@ # @plur-ai/mcp | ||
| By default (lean profile), your agent gets 11 tools. Everything else is reachable through `plur_admin`: | ||
| By default (lean profile), your agent gets 12 tools. Everything else is reachable through `plur_admin`: | ||
@@ -56,3 +56,3 @@ | Tool | What it does | | ||
| | `plur_learn` | Store a memory — correction, preference, convention, or decision | | ||
| | `plur_recall_hybrid` | **Best default** — BM25 + embeddings merged via RRF. Zero cost. | | ||
| | `plur_recall` | **Best default** — hybrid (BM25 + embeddings via RRF) by default; pass `mode:"keyword"` for BM25-only. Zero cost. | | ||
| | `plur_feedback` | Rate a memory — trains relevance over time | | ||
@@ -63,2 +63,3 @@ | `plur_forget` | Retire a memory (history preserved) | | ||
| | `plur_doctor` | Diagnose embedder, hybrid search, and remote-store auth | | ||
| | `plur_receipt` | Show why a memory was injected — the evidence behind a recall | | ||
| | `plur_packs_uninstall` | Remove an installed pack | | ||
@@ -68,3 +69,3 @@ | `plur_tensions_purge` | Clear stale/resolved tensions | | ||
| Less commonly needed tools (`plur_recall`, `plur_inject_hybrid`, `plur_learn_batch`, `plur_ingest`, `plur_sync`, `plur_packs_install`, `plur_packs_list`, `plur_capture`, `plur_timeline`, and more) are all reachable via `plur_admin`. Set `PLUR_TOOL_PROFILE=full` to expose all 40 tools directly. | ||
| Less commonly needed tools (`plur_recall_hybrid`, `plur_inject_hybrid`, `plur_learn_batch`, `plur_ingest`, `plur_sync`, `plur_packs_install`, `plur_packs_list`, `plur_capture`, `plur_timeline`, and more) are all reachable via `plur_admin`. Set `PLUR_TOOL_PROFILE=full` to expose all 40 tools directly. | ||
@@ -71,0 +72,0 @@ ## Sync across machines |
Sorry, the diff of this file is too big to display
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
191246
4.09%11
37.5%3150
4.93%119
0.85%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
Updated