edumem-mcp
README.md
# edumem-mcp
**Directory-scoped agent memory using markdown files** — an MCP server that gives LLM agents persistent, per-project memory without cluttering their context.
---
## Why edumem-mcp?
Agents forget everything between sessions. Dumping all memories into the context is messy and doesn't scale. `edumem-mcp` solves this by:
- **Scoping memory by directory** — The agent only sees memories relevant to the workspace it's working in.
- **Using plain Markdown files** — Human-readable, git-friendly, easy to edit or browse manually.
- **Supporting shared, read-only memories** — Configure `--self-mem` directories with global notes, coding conventions, or project knowledge that appear alongside workspace memories.
- **Zero enforced structure** — Write any markdown you want; no schemas, no templates, no restrictions.
---
## Installation
> **Note:** This package is not yet published to npm. Install directly from the git repository:
### Install globally from git
```bash
npm install -g github:SkillfulElectro/edumem-mcp
```
### Or run with npx (no install)
```bash
npx -y github:SkillfulElectro/edumem-mcp
```
### Clone and build locally
```bash
git clone https://github.com/SkillfulElectro/edumem-mcp.git
cd edumem-mcp
npm install
npm run build
```
---
## Configuration
Add to your MCP client config (Claude Desktop, Cursor, etc.):
```json
{
"mcpServers": {
"edumem-mcp": {
"command": "npx",
"args": ["-y", "github:SkillfulElectro/edumem-mcp"]
}
}
}
```
### ⚠️ Important: Do NOT use `npm start`
When running via an MCP client config, the server communicates over **stdin/stdout** using JSON-RPC. **`npm start` prints lifecycle banners to stdout** (like `> edumem-mcp@1.0.0 start`), which break the JSON-RPC protocol. Always launch the server directly:
```json
{
"mcpServers": {
"edumem-mcp": {
"command": "npx",
"args": ["-y", "github:SkillfulElectro/edumem-mcp"]
}
}
}
```
Or if running from a local clone:
```json
{
"mcpServers": {
"edumem-mcp": {
"command": "node",
"args": ["/absolute/path/to/edumem-mcp/dist/index.js"]
}
}
}
```
### CLI Options
| Option | Default | Description |
|---|---|---|
| `--wname` | `.edumem-mcp` | Name of the per-workspace memory directory |
| `--self-mem` | *(none)* | Comma-separated list of absolute paths to directories whose `.md` files act as extra (read-only) memory sources |
| `--workspace`, `--prefix` | *(none)* | Default workspace directory. When set, the `workspace_path` tool parameter becomes **optional** and defaults to this path |
**Example with custom options:**
```json
{
"mcpServers": {
"edumem-mcp": {
"command": "npx",
"args": [
"-y", "github:SkillfulElectro/edumem-mcp",
"--wname", ".myproject-memory",
"--self-mem", "/Users/alex/global-notes,/Users/alex/team-conventions",
"--workspace", "/Users/alex/projects/myapp"
]
}
}
}
```
---
## How It Works
For any `workspace_path` the agent is working in, `edumem-mcp` looks for memory files in:
1. **Workspace memory:** `<workspace_path>/.edumem-mcp/*.md` (read/write by the agent)
2. **Self-mem directories:** Any directories passed via `--self-mem` (read-only by the agent)
The agent can list, read, write, delete, and search across all sources seamlessly.
---
## Tools
### `list_memories`
List all `.md` memory files visible from a workspace.
| Parameter | Type | Default | Description |
|---|---|---|---|
| `workspace_path` | string | *(optional if --workspace set)* | The directory to list memories for |
| `recursive` | boolean | `false` | Include subdirectories of each memory source |
**Returns** an array of `{ name, source, size }` objects.
---
### `read_memory`
Read the full content of a memory file by name.
| Parameter | Type | Default | Description |
|---|---|---|---|
| `workspace_path` | string | *(optional if --workspace set)* | Directory context for the read |
| `memory_name` | string | *(required)* | File name (e.g. `"setup"` or `"decisions/why-rust"`) |
Looks in workspace memory first, then self-mem directories. Returns the raw markdown content.
---
### `search_memories`
Search across all memory files for a query string (case-insensitive).
| Parameter | Type | Default | Description |
|---|---|---|---|
| `workspace_path` | string | *(optional if --workspace set)* | Directory context for the search |
| `query` | string | *(required)* | Substring to search for |
| `recursive` | boolean | `false` | Search in subdirectories too |
| `source_filter` | `"workspace"` \| `"all"` | `"all"` | Limit search to a specific source |
**Returns** an array of `{ name, source, snippet, line }` objects.
---
### `write_memory`
Create or update a memory file. Only writes to the workspace's own memory directory; cannot modify self-mem files.
| Parameter | Type | Default | Description |
|---|---|---|---|
| `workspace_path` | string | *(optional if --workspace set)* | Where to write the memory |
| `memory_name` | string | *(required)* | File name (`.md` appended automatically if missing) |
| `content` | string | *(required)* | Markdown content to write |
| `mode` | `"overwrite"` \| `"append"` | `"overwrite"` | Write strategy |
---
### `delete_memory`
Delete a memory file from the workspace. Cannot delete self-mem files.
| Parameter | Type | Default | Description |
|---|---|---|---|
| `workspace_path` | string | *(optional if --workspace set)* | Where to delete from |
| `memory_name` | string | *(required)* | Name of the file to delete |
---
## Usage Examples
### Agent writes a project decision
```
Tool: write_memory
Args: {
"workspace_path": "/home/alex/projects/myapp",
"memory_name": "decisions/why-postgres",
"content": "## Why PostgreSQL\n\nChose PostgreSQL over MySQL for:\n- Better JSON support\n- Stronger ACID compliance\n- Familiar team experience"
}
Result: Memory "decisions/why-postgres.md" written successfully.
```
### Agent recalls past decisions
```
Tool: list_memories
Args: { "workspace_path": "/home/alex/projects/myapp" }
Result: [
{ "name": "decisions/why-postgres.md", "source": "workspace", "size": 156 },
{ "name": "setup-notes.md", "source": "workspace", "size": 89 }
]
Tool: read_memory
Args: { "workspace_path": "/home/alex/projects/myapp", "memory_name": "decisions/why-postgres.md" }
Result: ## Why PostgreSQL ...
```
### Agent searches for anything about "auth"
```
Tool: search_memories
Args: { "workspace_path": "/home/alex/projects/myapp", "query": "auth" }
Result: [
"[workspace] setup-notes.md:12 — Configured OAuth2 with Google and GitHub",
"[/Users/alex/global-notes] conventions.md:5 — All services must use the auth-gateway"
]
```
---
## Architecture
```
edumem-mcp/
├── src/
│ ├── index.ts # Entry point: CLI parsing, MCP server, stdio transport
│ ├── memory-service.ts # Core logic: file I/O, path security, source resolution
│ └── tools.ts # MCP tool registrations with Zod schemas
├── dist/ # Compiled JavaScript (published to npm)
├── package.json
├── tsconfig.json
└── README.md
```
---
## Security
- All file operations are restricted to allowed memory directories.
- Path traversal attacks (e.g. `../../../etc/passwd`) are blocked.
- Self-mem directories are read-only — the agent cannot modify or delete them.
- Only `.md` files are returned by list/search; other files are ignored.
---
## Development
```bash
git clone https://github.com/SkillfulElectro/edumem-mcp.git
cd edumem-mcp
npm install
npm run build # compile TypeScript
npm start # run the compiled server
# or for dev:
npm run dev # run directly with ts-node
```
### Testing
```bash
# Manual stdio test
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' | node dist/index.js
```
---
## License
MIT
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing