### Run development server
Source: https://github.com/puliczek/mcp-memory/blob/main/README.md
Starts the local development environment.
```bash
npm run dev
```
--------------------------------
### Install project dependencies
Source: https://github.com/puliczek/mcp-memory/blob/main/README.md
Installs the necessary packages for the MCP Memory project.
```bash
npm install
```
--------------------------------
### Setup Copy Configuration Button
Source: https://github.com/puliczek/mcp-memory/blob/main/static/index.html
This function sets up a button to copy configuration code to the clipboard, dynamically inserting a provided URL. It handles success and error states with visual feedback. Ensure the button, code block, and URL span elements exist in the DOM.
```javascript
document.addEventListener("DOMContentLoaded", () => {
function setupConfigCopyButton(buttonId, codeBlockSelector, urlSpanId) {
const copyButton = document.getElementById(buttonId);
const codeBlock = document.querySelector(codeBlockSelector);
if (!copyButton || !codeBlock) {
console.warn(\`Could not setup copy button: ${buttonId} - elements not found.
cies `);
return;
}
const originalButtonHtml = copyButton.innerHTML;
const originalButtonClasses = Array.from(copyButton.classList);
copyButton.addEventListener("click", () => {
const sseUrl = document.getElementById("sse-url")?.value || "";
const urlSpan = codeBlock.querySelector(` #${urlSpanId}`);
let codeToCopy = "";
const codeLines = codeBlock.textContent.split("\n");
const urlPlaceholder = `YOUR_MCP_URL_HERE`;
codeToCopy = codeLines
.map((line) => {
const indentation = line.match(/^\s*/) || "";
if (line.includes(urlPlaceholder)) {
return `${indentation}"${sseUrl}"`;
}
return line;
})
.join("\n");
if (!codeToCopy.includes(sseUrl) && codeBlock.textContent) {
console.warn(
"Placeholder replacement failed for",
buttonId,
"using raw textContent with manual replace."
);
codeToCopy = codeBlock.textContent.replace(urlPlaceholder, `"${sseUrl}"`);
}
if (!sseUrl || sseUrl === "YOUR_MCP_URL_HERE" || sseUrl.startsWith("Error")) {
alert("MCP Server URL is not available yet.");
return;
}
navigator.clipboard
.writeText(codeToCopy.trim())
.then(() => {
copyButton.innerHTML = ` Copied!`;
copyButton.className = "";
copyButton.classList.add(...originalButtonClasses);
copyButton.classList.remove("bg-gray-700", "hover:bg-gray-600", "text-gray-300");
copyButton.classList.add("bg-amber-500", "hover:bg-amber-600", "text-white");
setTimeout(() => {
copyButton.innerHTML = originalButtonHtml;
copyButton.className = "";
copyButton.classList.add(...originalButtonClasses);
}, 2000);
})
.catch((err) => {
console.error(`Failed to copy config for ${buttonId}: `, err);
alert("Failed to copy code. Please copy it manually.");
});
});
}
setupConfigCopyButton("copy-cursor-config-button", "#cursor-tab pre code", "cursor-config-url");
setupConfigCopyButton("copy-cla
```
--------------------------------
### REST API: Get All Memories
Source: https://context7.com/puliczek/mcp-memory/llms.txt
Retrieves all memories for a specific user from the D1 database.
```bash
# Get all memories for a user
curl -X GET "https://your-mcp-memory.workers.dev/{userId}/memories"
# Response on success:
{
"success": true,
"memories": [
{ "id": "550e8400-e29b-41d4-a716-446655440000", "content": "User prefers dark mode" },
{ "id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8", "content": "User's timezone is PST" }
]
}
# Response on error:
{
"success": false,
"error": "Failed to retrieve memories"
}
```
--------------------------------
### GET /{userId}/memories
Source: https://context7.com/puliczek/mcp-memory/llms.txt
Retrieves all memories for a specific user from the D1 database.
```APIDOC
## GET /{userId}/memories
### Description
Retrieves all memories for a specific user from the D1 database, ordered by creation date (newest first).
### Method
GET
### Endpoint
/{userId}/memories
### Parameters
#### Path Parameters
- **userId** (string) - Required - The unique identifier for the user
### Response
#### Success Response (200)
- **success** (boolean) - Status of the request
- **memories** (array) - List of memory objects containing id and content
#### Response Example
{
"success": true,
"memories": [
{ "id": "550e8400-e29b-41d4-a716-446655440000", "content": "User prefers dark mode" }
]
}
```
--------------------------------
### Create MCP Memory project via CLI
Source: https://github.com/puliczek/mcp-memory/blob/main/README.md
Initializes a new project using the Cloudflare CLI template.
```bash
npm create cloudflare@latest --git https://github.com/puliczek/mcp-memory
```
--------------------------------
### Initialize Configuration Copy Buttons
Source: https://github.com/puliczek/mcp-memory/blob/main/static/index.html
Sets up click handlers for copy buttons associated with Claude and Windsurf configuration blocks.
```javascript
ude-config-button", "#claude-tab pre code", "claude-config-url"); setupConfigCopyButton("copy-windsurf-config-button", "#windsurf-tab pre code", "windsurf-config-url"); });
```
--------------------------------
### Create Vectorize index
Source: https://github.com/puliczek/mcp-memory/blob/main/README.md
Sets up the Vectorize index required for similarity search with specific dimensions and metric.
```bash
npx wrangler vectorize create mcp-memory-vectorize --dimensions 1024 --metric cosine
```
--------------------------------
### Deploy MCP Memory to Cloudflare Workers
Source: https://context7.com/puliczek/mcp-memory/llms.txt
Commands for setting up and deploying the service, including Vectorize index creation and wrangler configuration.
```bash
# Option 1: Create from template using Cloudflare CLI
npm create cloudflare@latest --git https://github.com/puliczek/mcp-memory
# Option 2: Clone and setup manually
git clone https://github.com/puliczek/mcp-memory
cd mcp-memory
npm install
# Create Vectorize index (required before first deploy)
npx wrangler vectorize create mcp-memory-vectorize --dimensions 1024 --metric cosine
# Run locally for development
npm run dev
# Deploy to Cloudflare Workers
npm run deploy
# wrangler.jsonc configuration highlights:
{
"name": "mcp-memory",
"main": "src/index.ts",
"d1_databases": [{ "binding": "DB", "database_name": "mcp-memory-db" }],
"vectorize": [{ "binding": "VECTORIZE", "index_name": "mcp-memory-vectorize" }],
"ai": { "binding": "AI" },
"durable_objects": { "bindings": [{ "class_name": "MyMCP", "name": "MCP_OBJECT" }] },
"unsafe": {
"bindings": [{
"name": "RATE_LIMITER",
"type": "ratelimit",
"simple": { "limit": 100, "period": 60 }
}]
}
}
```
--------------------------------
### Configure Cursor IDE for MCP Memory
Source: https://context7.com/puliczek/mcp-memory/llms.txt
Add the server configuration to the global or project-specific mcp.json file.
```json
// Global config: ~/.cursor/mcp.json
// Project config: .cursor/mcp.json (in project root)
{
"mcpServers": {
"mcp-memory": {
"url": "https://your-mcp-memory.workers.dev/{your-user-id}/sse"
}
}
}
```
--------------------------------
### Configure Claude Desktop for mcp-memory
Source: https://github.com/puliczek/mcp-memory/blob/main/static/index.html
Add this JSON object to your Claude Desktop claude_desktop_config.json file to integrate mcp-memory. Replace YOUR_MCP_URL_HERE with your server URL and ensure npx is available.
```json
{
"mcpServers": {
"mcp-memory": {
"command": "npx",
"args": [
"mcp-remote",
"YOUR_MCP_URL_HERE"
]
}
}
}
```
--------------------------------
### Configure Claude Desktop for MCP Memory
Source: https://context7.com/puliczek/mcp-memory/llms.txt
Update the Claude Desktop configuration file to use the mcp-remote bridge via npx.
```json
// macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
// Windows: %APPDATA%\Claude\claude_desktop_config.json
// Linux: ~/.config/Claude/claude_desktop_config.json
{
"mcpServers": {
"mcp-memory": {
"command": "npx",
"args": [
"mcp-remote",
"https://your-mcp-memory.workers.dev/{your-user-id}/sse"
]
}
}
}
```
--------------------------------
### Configure Windsurf for MCP Memory
Source: https://context7.com/puliczek/mcp-memory/llms.txt
Add the server URL to the mcp_config.json file in the Windsurf configuration directory.
```json
// Config location: ~/.codeium/windsurf/mcp_config.json
{
"mcpServers": {
"mcp-memory": {
"serverUrl": "https://your-mcp-memory.workers.dev/{your-user-id}/sse"
}
}
}
```
--------------------------------
### MCP Client Configuration: Claude Desktop
Source: https://context7.com/puliczek/mcp-memory/llms.txt
Configure Claude Desktop to use MCP Memory using the mcp-remote bridge. This requires npx to be available in your environment.
```APIDOC
## MCP Client Configuration: Claude Desktop
Configure Claude Desktop to use MCP Memory using the mcp-remote bridge. This requires npx to be available in your environment.
```json
// macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
// Windows: %APPDATA%\Claude\claude_desktop_config.json
// Linux: ~/.config/Claude/claude_desktop_config.json
{
"mcpServers": {
"mcp-memory": {
"command": "npx",
"args": [
"mcp-remote",
"https://your-mcp-memory.workers.dev/{your-user-id}/sse"
]
}
}
}
```
```
--------------------------------
### Deploy worker
Source: https://github.com/puliczek/mcp-memory/blob/main/README.md
Deploys the application to the Cloudflare network.
```bash
npm run deploy
```
--------------------------------
### Direct API SSE Connection
Source: https://context7.com/puliczek/mcp-memory/llms.txt
Establish an SSE connection and send JSON-RPC requests to the postEndpointUri.
```bash
# 1. Establish SSE connection
curl -N "https://your-mcp-memory.workers.dev/{userId}/sse"
# Server sends initial message event with:
# data: {"postEndpointUri": "https://your-mcp-memory.workers.dev/{userId}/mcp"}
# 2. Send JSON-RPC requests to the postEndpointUri
curl -X POST "https://your-mcp-memory.workers.dev/{userId}/mcp" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "addToMCPMemory",
"arguments": { "thingToRemember": "User prefers TypeScript over JavaScript" }
},
"id": 1
}'
# 3. Responses arrive as SSE message events on the original connection
# data: {"jsonrpc":"2.0","result":{"content":[{"type":"text","text":"Remembered: User prefers TypeScript over JavaScript"}]},"id":1}
```
--------------------------------
### Configure Windsurf (Codeium) for mcp-memory
Source: https://github.com/puliczek/mcp-memory/blob/main/static/index.html
Add this JSON object to your Windsurf mcp_config.json file to connect mcp-memory. Replace YOUR_MCP_URL_HERE with your server URL.
```json
{
"mcpServers": {
"mcp-memory": {
"serverUrl": "YOUR_MCP_URL_HERE"
}
}
}
```
--------------------------------
### MCP Client Configuration: Windsurf
Source: https://context7.com/puliczek/mcp-memory/llms.txt
Configure Windsurf (Codeium) to use MCP Memory by adding the server URL to the mcp_config.json file.
```APIDOC
## MCP Client Configuration: Windsurf
Configure Windsurf (Codeium) to use MCP Memory by adding the server URL to the mcp_config.json file.
```json
// Config location: ~/.codeium/windsurf/mcp_config.json
{
"mcpServers": {
"mcp-memory": {
"serverUrl": "https://your-mcp-memory.workers.dev/{your-user-id}/sse"
}
}
}
```
```
--------------------------------
### Configure Cursor for mcp-memory
Source: https://github.com/puliczek/mcp-memory/blob/main/static/index.html
Add this JSON object to your Cursor mcp.json file to connect to your mcp-memory server. Ensure you replace YOUR_MCP_URL_HERE with your actual server URL.
```json
{
"mcpServers": {
"mcp-memory": {
"url": "YOUR_MCP_URL_HERE"
}
}
}
```
--------------------------------
### Fetch and Display Memories
Source: https://github.com/puliczek/mcp-memory/blob/main/static/index.html
Fetches memories for a given user and dynamically renders them in a list. Includes handling for successful fetches, empty states, and errors. This function should be called when the memory list needs to be populated or refreshed.
```javascript
console.log("Fetching memories...");
fetch(`/${userUuid}/memories`)
.then((response) => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then((data) => {
memoriesList.innerHTML = ""; // Clear previous content or loading message
let hasMemories = false;
if (data.success && data.memories && data.memories.length > 0) {
hasMemories = true;
data.memories.forEach((memory) => {
const li = document.createElement("li");
// Added padding and subtle hover effect for light mode
li.className = "memory-item px-4 py-3 sm:px-6 flex justify-between items-center hover:bg-gray-50 transition duration-150 ease-in-out";
li.dataset.memoryId = memory.id;
const contentContainer = document.createElement("div");
contentContainer.className = "flex-grow mr-4 overflow-hidden"; // Added overflow hidden
const contentSpan = document.createElement("span");
contentSpan.className = "memory-content text-sm text-gray-800 block truncate"; // Ensure text wraps/truncates nicely
contentSpan.textContent = memory.content || "Empty memory";
contentContainer.appendChild(contentSpan);
li.appendChild(contentContainer);
const buttonContainer = document.createElement("div");
buttonContainer.className = "flex space-x-2 flex-shrink-0"; // Prevent buttons shrinking too much
// Edit button - Light mode style
const editButton = document.createElement("button");
editButton.textContent = "Edit";
editButton.className = "edit-button inline-flex items-center rounded border border-gray-300 bg-white px-2.5 py-1 text-xs font-medium text-gray-700 shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-orange-500 focus:ring-offset-2";
buttonContainer.appendChild(editButton);
// Delete button - Light mode style
const deleteButton = document.createElement("button");
deleteButton.textContent = "Delete";
deleteButton.className = "delete-button inline-flex items-center rounded border border-red-300 bg-red-50 px-2.5 py-1 text-xs font-medium text-red-700 shadow-sm hover:bg-red-100 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2";
buttonContainer.appendChild(deleteButton);
li.appendChild(buttonContainer);
memoriesList.appendChild(li);
});
} else if (data.success) {
// No memories found - Enhanced Empty State
const li = document.createElement("li");
li.className = "px-6 py-12 sm:px-8 text-center"; // Increased padding
const emptyStateContainer = document.createElement("div");
emptyStateContainer.className = "flex flex-col items-center space-y-3"; // SVG Icon (Example: Document Add icon from Heroicons)
const svgIcon = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svgIcon.setAttribute("class", "h-12 w-12 text-gray-400");
svgIcon.setAttribute("fill", "none");
svgIcon.setAttribute("viewBox", "0 0 24 24");
svgIcon.setAttribute("stroke", "currentColor");
svgIcon.setAttribute("stroke-width", "1");
svgIcon.innerHTML = ``;
emptyStateContainer.appendChild(svgIcon);
const heading = document.createElement("h3");
heading.className = "text-lg font-semibold text-gray-800";
heading.textContent = "No Memories Stored Yet";
emptyStateContainer.appendChild(heading);
const paragraph = document.createElement("p");
paragraph.className = "text-sm text-gray-500";
paragraph.textContent = "Add your first memory through your MCP client (like Cursor, Claude, etc.).";
emptyStateContainer.appendChild(paragraph);
li.appendChild(emptyStateContainer);
memoriesList.appendChild(li);
} else {
throw new Error(data.error || "Failed to fetch memories");
}
})
.catch((error) => {
console.error("Error fetching or processing memories:", error);
memoriesList.innerHTML = "";
const li = document.createElement("li");
li.className = "px-4 py-4 sm:px-6 text-red-600"; // Adjusted error text color
li.textContent = `Failed to load memories: ${error.message}`;
memoriesList.appendChild(li);
});
countdown = refreshIntervalSeconds;
updateTimerDisplay();
```
--------------------------------
### Copy API URL to Clipboard
Source: https://github.com/puliczek/mcp-memory/blob/main/static/index.html
Enables copying the SSE endpoint URL to the clipboard with visual feedback.
```javascript
document.addEventListener("DOMContentLoaded", () => { const copyDirectApiButton = document.getElementById("copy-direct-api-url-button"); const directApiUrlCode = document.getElementById("direct-api-url"); if (copyDirectApiButton && directApiUrlCode) { const originalButtonHtml = copyDirectApiButton.innerHTML; copyDirectApiButton.addEventListener("click", () => { const urlToCopy = directApiUrlCode.textContent || ""; if (!urlToCopy || urlToCopy === "YOUR_SSE_ENDPOINT_HERE") { alert("URL not generated yet."); return; } navigator.clipboard .writeText(urlToCopy) .then(() => { copyDirectApiButton.innerHTML = ` C
```
--------------------------------
### Initialize Memory Refresh Logic
Source: https://github.com/puliczek/mcp-memory/blob/main/static/index.html
This JavaScript code initializes the logic for refreshing memories. It sets up a countdown timer and interval for fetching memories, with configurable refresh intervals. It also includes basic error handling for missing UI elements or user identifiers.
```javascript
document.addEventListener("DOMContentLoaded", () => {
const memoriesList = document.getElementById("memories-list");
const refreshTimerSpan = document.getElementById("refresh-timer");
const refreshButton = document.getElementById("refresh-button");
const userUuid = localStorage.getItem("mcpUserUuid");
const refreshIntervalSeconds = 30;
let countdown = refreshIntervalSeconds;
let fetchIntervalId = null;
let timerIntervalId = null;
function updateTimerDisplay() {
if (refreshTimerSpan) {
refreshTimerSpan.textContent = `(${countdown}s) `;
}
}
function fetchAndDisplayMemories() {
if (!memoriesList || !userUuid) {
console.error("Missing memories list element or user UUID.");
if (memoriesList) {
memoriesList.innerHTML = ""; // Clear loading
const li = document.createElement("li");
li.className = "px-4 py-4 sm:px-6 text-red-600"; // Use a suitable error color
li.textCont
```
--------------------------------
### Copy SSE URL to Clipboard
Source: https://github.com/puliczek/mcp-memory/blob/main/static/index.html
This JavaScript code adds an event listener to a button that copies the generated SSE URL to the user's clipboard. It provides visual feedback by changing the button's text and style upon successful copy and reverts after a delay. Error handling is included for copy failures.
```javascript
if (copyButton && sseUrlInput && userUuid) {
copyButton.addEventListener("click", () => {
navigator.clipboard
.writeText(sseUrl)
.then(() => {
// Use specific classes for the "Copied" state
copyButton.innerHTML = ` Copied!`;
copyButton.classList.remove("bg-orange-600", "hover:bg-orange-700");
copyButton.classList.add("bg-amber-500", "hover:bg-amber-600");
// Green for success
setTimeout(() => {
copyButton.innerHTML = originalButtonHtml; // Revert to original text + icon
copyButton.classList.remove("bg-amber-500", "hover:bg-amber-600");
copyButton.classList.add("bg-orange-600", "hover:bg-orange-700");
}, 2000);
})
.catch((err) => {
console.error("Failed to copy URL: ", err);
alert("Failed to copy URL. Please copy it manually.");
});
});
} else if (copyButton) {
copyButton.disabled = true;
copyButton.title = "Cannot copy URL";
}
```
--------------------------------
### MCP Tool: searchMCPMemory
Source: https://context7.com/puliczek/mcp-memory/llms.txt
Searches the user's persistent memory layer for relevant information using semantic matching.
```APIDOC
## MCP Tool: searchMCPMemory
### Description
Searches the user's persistent memory layer for relevant information using semantic matching. Returns up to 10 matches ranked by similarity score, filtering out results below 0.5 similarity threshold.
### Parameters
#### Request Body
- **informationToGet** (string) - Required - The search query
### Response
#### Success Response (200)
- **content** (array) - Array containing a text object with found memories and their similarity scores, or a 'No relevant memories found' message.
```
--------------------------------
### MCP Client Configuration: Cursor
Source: https://context7.com/puliczek/mcp-memory/llms.txt
Configure Cursor IDE to use MCP Memory by adding the server configuration to your mcp.json file. This can be done globally or per-project.
```APIDOC
## MCP Client Configuration: Cursor
Configure Cursor IDE to use MCP Memory by adding the server configuration to your mcp.json file. The configuration can be added globally or per-project.
```json
// Global config: ~/.cursor/mcp.json
// Project config: .cursor/mcp.json (in project root)
{
"mcpServers": {
"mcp-memory": {
"url": "https://your-mcp-memory.workers.dev/{your-user-id}/sse"
}
}
}
```
```
--------------------------------
### Deployment: Cloudflare Workers
Source: https://context7.com/puliczek/mcp-memory/llms.txt
Deploy your own instance of MCP Memory to Cloudflare using the CLI or one-click deploy button. The Vectorize index must be configured with 1024 dimensions and cosine similarity metric.
```APIDOC
## Deployment: Cloudflare Workers
Deploy your own instance of MCP Memory to Cloudflare using the CLI or one-click deploy button. The Vectorize index must be configured with 1024 dimensions and cosine similarity metric.
```bash
# Option 1: Create from template using Cloudflare CLI
npm create cloudflare@latest --git https://github.com/puliczek/mcp-memory
# Option 2: Clone and setup manually
git clone https://github.com/puliczek/mcp-memory
cd mcp-memory
npm install
# Create Vectorize index (required before first deploy)
npx wrangler vectorize create mcp-memory-vectorize --dimensions 1024 --metric cosine
# Run locally for development
npm run dev
# Deploy to Cloudflare Workers
npm run deploy
# wrangler.jsonc configuration highlights:
{
"name": "mcp-memory",
"main": "src/index.ts",
"d1_databases": [{ "binding": "DB", "database_name": "mcp-memory-db" }],
"vectorize": [{ "binding": "VECTORIZE", "index_name": "mcp-memory-vectorize" }],
"ai": { "binding": "AI" },
"durable_objects": { "bindings": [{ "class_name": "MyMCP", "name": "MCP_OBJECT" }] },
"unsafe": {
"bindings": [{
"name": "RATE_LIMITER",
"type": "ratelimit",
"simple": { "limit": 100, "period": 60 }
}]
}
}
```
```
--------------------------------
### searchMCPMemory Tool Implementation
Source: https://context7.com/puliczek/mcp-memory/llms.txt
Performs semantic search on stored memories using Vectorize, filtering results by a minimum similarity score of 0.5.
```typescript
// MCP Tool Schema
{
name: "searchMCPMemory",
parameters: {
informationToGet: z.string() // The search query
}
}
// Internal implementation flow:
// 1. Generate embedding for the search query
const queryVector = await generateEmbeddings(query, env);
// 2. Search Vectorize with user's namespace
const results = await env.VECTORIZE.query(queryVector, {
namespace: userId,
topK: 10,
returnMetadata: "all"
});
// 3. Filter by minimum similarity score (0.5)
const memories = results.matches
.filter(match => match.score > 0.5)
.map(match => ({
content: match.metadata.content,
score: match.score,
id: match.id
}));
// Response with matches:
{
content: [{
type: "text",
text: "Found memories:\n" + memories.map(m =>
`${m.content} (score: ${m.score.toFixed(4)})`
).join("\n")
}]
}
// Response when no matches:
{ content: [{ type: "text", text: "No relevant memories found." }] }
```
--------------------------------
### Direct API: SSE Connection
Source: https://context7.com/puliczek/mcp-memory/llms.txt
Establish a Server-Sent Events connection for direct MCP protocol communication. The connection provides a postEndpointUri for sending JSON-RPC requests.
```APIDOC
## Direct API: SSE Connection
Establish a Server-Sent Events connection for direct MCP protocol communication. The connection provides a postEndpointUri for sending JSON-RPC requests.
```bash
# 1. Establish SSE connection
curl -N "https://your-mcp-memory.workers.dev/{userId}/sse"
# Server sends initial message event with:
# data: {"postEndpointUri": "https://your-mcp-memory.workers.dev/{userId}/mcp"}
# 2. Send JSON-RPC requests to the postEndpointUri
curl -X POST "https://your-mcp-memory.workers.dev/{userId}/mcp" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "addToMCPMemory",
"arguments": { "thingToRemember": "User prefers TypeScript over JavaScript" }
},
"id": 1
}'
# 3. Responses arrive as SSE message events on the original connection
# data: {"jsonrpc":"2.0","result":{"content":[{"type":"text","text":"Remembered: User prefers TypeScript over JavaScript"}]},"id":1}
```
```
--------------------------------
### PUT /{userId}/memories/{memoryId}
Source: https://context7.com/puliczek/mcp-memory/llms.txt
Updates the content of an existing memory for a user.
```APIDOC
## PUT /{userId}/memories/{memoryId}
### Description
Updates the content of an existing memory for a user. This updates both the D1 database record and regenerates the vector embedding in Vectorize.
### Method
PUT
### Endpoint
/{userId}/memories/{memoryId}
### Parameters
#### Path Parameters
- **userId** (string) - Required - The unique identifier for the user
- **memoryId** (string) - Required - The unique identifier for the memory record
#### Request Body
- **content** (string) - Required - The updated memory content
```
--------------------------------
### Persist Memory Changes
Source: https://github.com/puliczek/mcp-memory/blob/main/static/index.html
Sends updated memory content to the server via a PUT request and handles UI feedback.
```javascript
function saveChanges(listItem) { const memoryId = listItem.dataset.memoryId; const input = listItem.querySelector(".memory-input"); const saveButton = listItem.querySelector(".save-button"); const newContent = input.value.trim(); if (!newContent) { alert("Memory content cannot be empty."); input.focus(); return; } saveButton.disabled = true; saveButton.textContent = "Saving..."; fetch(`/${userUuid}/memories/${memoryId}`, { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ content: newContent }), }) .then((response) => { if (!response.ok) { return response .json() .then((err) => { throw new Error(err.error || `HTTP error! status: ${response.status}`); }) .catch(() => { throw new Error(`HTTP error! status: ${response.status}`); }); } return response.json(); }) .then((data) => { if (data.success) { console.log(`Memory ${memoryId} updated successfully.`); exitEditMode(listItem, newContent); } else { throw new Error(data.error || "Update failed on the server."); } }) .catch((error) => { console.error("Error updating memory:", error); alert(`Failed to update memory: ${error.message}`); saveButton.disabled = false; saveButton.textContent = "Save"; // Keep Save text on error }); }
```
--------------------------------
### addToMCPMemory Tool Implementation
Source: https://context7.com/puliczek/mcp-memory/llms.txt
Stores user information by generating vector embeddings and saving them to both Vectorize and D1.
```typescript
// MCP Tool Schema
{
name: "addToMCPMemory",
parameters: {
thingToRemember: z.string() // The content to store in memory
}
}
// Internal implementation flow:
// 1. Generate vector embedding using @cf/baai/bge-m3 model
const memoryId = await storeMemory(thingToRemember, userId, env);
// 2. Store in Vectorize with user namespace
await env.VECTORIZE.upsert([{
id: memoryId,
values: vectorEmbedding,
namespace: userId,
metadata: { content: thingToRemember }
}]);
// 3. Store original text in D1 database
await env.DB.prepare(
"INSERT INTO memories (id, userId, content) VALUES (?, ?, ?)"
).bind(memoryId, userId, content).run();
// Response on success:
{ content: [{ type: "text", text: "Remembered: " + thingToRemember }] }
```
--------------------------------
### Manage Refresh Intervals
Source: https://github.com/puliczek/mcp-memory/blob/main/static/index.html
Handles automatic data fetching and countdown timer updates.
```javascript
// Timer countdown logic function startTimer() { if (timerIntervalId) clearInterval(timerIntervalId); timerIntervalId = setInterval(() => { countdown--; if (countdown < 0) { // Reset when it hits 0 or below countdown = refreshIntervalSeconds; } updateTimerDisplay(); }, 1000); } // Function to reset the automatic fetch interval function resetAutoRefresh() { if (fetchIntervalId) clearInterval(fetchIntervalId); fetchIntervalId = setInterval(fetchAndDisplayMemories, refreshIntervalSeconds * 1000); countdown = refreshIntervalSeconds; updateTimerDisplay(); startTimer(); } // Initial setup if (userUuid && memoriesList && refreshTimerSpan && refreshButton) { fetchAndDisplayMemories(); // Initial fetch resetAutoRefresh(); // Start intervals and timer refreshButton.addEventListener("click", () => { console.log("Manual refresh triggered."); fetchAndDisplayMemories(); // Fetch immediately resetAutoRefresh(); // Reset the interval and timer }); // Event delegation for memory list actions memoriesList.addEventListener("click", function (event) {
```
--------------------------------
### API Response Formats
Source: https://context7.com/puliczek/mcp-memory/llms.txt
Standard JSON response structures for successful operations, missing memory, and validation errors.
```json
{
"success": true
}
```
```json
{
"success": false,
"error": "Memory with ID {memoryId} not found for user {userId} or content unchanged."
}
```
```json
{
"success": false,
"error": "Invalid or missing content in request body"
}
```
--------------------------------
### Handle Memory Item Interactions
Source: https://github.com/puliczek/mcp-memory/blob/main/static/index.html
Manages click events for editing, saving, and deleting memory items, including dynamic DOM updates for empty states.
```javascript
) { const target = event.target; const listItem = target.closest(".memory-item"); if (!listItem) return; const memoryId = listItem.dataset.memoryId; // Edit/Save Click if (target.classList.contains("edit-button")) { enterEditMode(listItem); } else if (target.classList.contains("save-button")) { saveChanges(listItem); } // Delete/Cancel Click else if (target.classList.contains("delete-button")) { if (confirm(`Are you sure you want to delete this memory?`)) { const deleteButton = target; deleteButton.disabled = true; deleteButton.textContent = "Deleting..."; fetch(`/${userUuid}/memories/${memoryId}`, { method: "DELETE" }) .then((response) => { if (!response.ok) { return response .json() .then((err) => { throw new Error(err.error || `HTTP error! status: ${response.status}`); }) .catch(() => { throw new Error(`HTTP error! status: ${response.status}`); }); } return response.json(); }) .then((data) => { if (data.success) { console.log(`Memory ${memoryId} deleted successfully.`); listItem.remove(); // Check if list is now empty after deletion const hasMemories = memoriesList.querySelector(".memory-item") !== null; if (!hasMemories) { const li = document.createElement("li"); li.className = "px-6 py-12 sm:px-8 text-center"; // Match the enhanced empty state style const emptyStateContainer = document.createElement("div"); emptyStateContainer.className = "flex flex-col items-center space-y-3"; // SVG Icon const svgIcon = document.createElementNS("http://www.w3.org/2000/svg", "svg"); svgIcon.setAttribute("class", "h-12 w-12 text-gray-400"); svgIcon.setAttribute("fill", "none"); svgIcon.setAttribute("viewBox", "24 24"); svgIcon.setAttribute("stroke", "currentColor"); svgIcon.setAttribute("stroke-width", "1"); svgIcon.innerHTML = ``; emptyStateContainer.appendChild(svgIcon); const heading = document.createElement("h3"); heading.className = "text-lg font-semibold text-gray-800"; heading.textContent = "No Memories Stored Yet"; emptyStateContainer.appendChild(heading); const paragraph = document.createElement("p"); paragraph.className = "text-sm text-gray-500"; paragraph.textContent = "Add your first memory through your connected MCP client (like Cursor, Claude, etc.)."; emptyStateContainer.appendChild(paragraph); li.appendChild(emptyStateContainer); memoriesList.appendChild(li); } } else { throw new Error(data.error || "Deletion failed on the server."); } }) .catch((error) => { console.error("Error deleting memory:", error); alert(`Failed to delete memory: ${error.message}`); deleteButton.disabled = false; deleteButton.textContent = "Delete"; // Revert button text on error }); } } else if (target.classList.contains("cancel-button")) { const originalContent = listItem.dataset.originalContent || ""; // Fallback if somehow missing exitEditMode(listItem, originalContent); } }); // Handle Enter/Escape key press in edit mode input field memoriesList.addEventListener("keydown", function (event) { if (event.key === "Enter" && event.target.classList.contains("memory-input")) { event.preventDefault(); // Prevent form submission if inside a form const listItem = event.target.closest(".memory-item"); if (listItem) { saveChanges(listItem); } } else if (event.key === "Escape" && event.target.classList.contains("memory-input")) { event.preventDefault(); // Prevent potential browser actions const listItem = event.target.closest(".memory-item"); if (listItem) { const originalContent = listItem.dataset.originalContent || ""; exitEditMode(listItem, originalContent); } } }); } else { // Handle missing elements or UUID on initial load if (refreshTimerSpan) refreshTimerSpan.textContent = "Setup Error"; if (memoriesList && !userUuid) { memoriesList.innerHTML = ""; const li = document.createElement("li"); li.className = "px-4 py-4 sm:px-6 text-red-600"; // Use error color li.textContent = "Could not identify user to load memories."; memoriesList.appendChild(li); } console.error("Initial setup failed: Missing critical elements or UUID."); });
```
--------------------------------
### DELETE /{userId}/memories/{memoryId}
Source: https://context7.com/puliczek/mcp-memory/llms.txt
Deletes a specific memory for a user from both D1 database and Vectorize index.
```APIDOC
## DELETE /{userId}/memories/{memoryId}
### Description
Deletes a specific memory for a user from both D1 database and Vectorize index to maintain consistency.
### Method
DELETE
### Endpoint
/{userId}/memories/{memoryId}
### Parameters
#### Path Parameters
- **userId** (string) - Required - The unique identifier for the user
- **memoryId** (string) - Required - The unique identifier for the memory record
### Response
#### Success Response (200)
- **success** (boolean) - Status of the request
```
--------------------------------
### Update SSE Endpoint URL and Config Placeholders
Source: https://github.com/puliczek/mcp-memory/blob/main/static/index.html
This JavaScript code updates an input field with the Server-Sent Events (SSE) URL based on the current origin and a user's UUID. It also updates placeholder text for various configuration URLs (Claude, Cursor, Windsurf, Direct API) to reflect the generated SSE URL.
```javascript
if (sseUrlInput) {
const currentOrigin = window.location.origin;
if (userUuid) {
sseUrl = `${currentOrigin}/${userUuid}/sse`;
sseUrlInput.value = sseUrl;
// Update Claude config URL placeholder
const claudeUrlSpan = document.getElementById("claude-config-url");
if (claudeUrlSpan) {
claudeUrlSpan.textContent = sseUrl;
}
// Update Cursor config URL placeholder
const cursorUrlSpan = document.getElementById("cursor-config-url");
if (cursorUrlSpan) {
cursorUrlSpan.textContent = sseUrl;
}
// Update Windsurf config URL placeholder
const windsurfUrlSpan = document.getElementById("windsurf-config-url");
if (windsurfUrlSpan) {
windsurfUrlSpan.textContent = sseUrl;
}
// Update Direct API URL placeholder
const directApiUrlCode = document.getElementById("direct-api-url");
if (directApiUrlCode) {
directApiUrlCode.textContent = sseUrl;
}
} else {
sseUrlInput.value = "Error generating user identifier.";
console.error("Could not generate or retrieve UUID.");
if (copyButton) {
copyButton.disabled = true;
copyButton.title = "Cannot copy URL without a user identifier";
}
sseUrlInput.readOnly = true; // Keep readonly even on error
}
}
```
--------------------------------
### Handle Tab Switching Logic
Source: https://github.com/puliczek/mcp-memory/blob/main/static/index.html
This JavaScript code manages the display of tabbed content. It adds event listeners to tab buttons to show the corresponding content and update active tab styles. Ensure HTML elements have appropriate classes and data attributes.
```javascript
document.addEventListener("DOMContentLoaded", function () {
const tabs = document.querySelectorAll(".tab-button");
const tabContents = document.querySelectorAll(".tab-content");
tabs.forEach((tab) => {
tab.addEventListener("click", function () {
const target = document.querySelector(tab.dataset.tabTarget);
// Hide all tab contents
tabContents.forEach((tc) => {
tc.classList.add("hidden");
});
// Show the target tab content
if (target) {
target.classList.remove("hidden");
}
// Update tab button styles
tabs.forEach((t) => {
t.classList.remove("border-orange-500", "text-orange-600");
t.classList.add("border-transparent", "text-gray-500", "hover:text-gray-700", "hover:border-gray-300");
t.removeAttribute("aria-current");
});
// Style the active tab button
tab.classList.add("border-orange-500", "text-orange-600");
tab.classList.remove("border-transparent", "text-gray-500", "hover:text-gray-700", "hover:border-gray-300");
tab.setAttribute("aria-current", "page");
});
});
});
```
--------------------------------
### MCP Tool: addToMCPMemory
Source: https://context7.com/puliczek/mcp-memory/llms.txt
Stores user information in the persistent memory layer using semantic vector embeddings.
```APIDOC
## MCP Tool: addToMCPMemory
### Description
Stores important user information in a persistent memory layer. Use this tool when a user explicitly asks to remember something, when you detect significant user preferences, or when technical details emerge.
### Parameters
#### Request Body
- **thingToRemember** (string) - Required - The content to store in memory
### Response
#### Success Response (200)
- **content** (array) - Array containing a text object confirming the stored memory.
```
--------------------------------
### REST API: Update Memory
Source: https://context7.com/puliczek/mcp-memory/llms.txt
Updates memory content and regenerates the corresponding vector embedding.
```bash
# Update a memory's content
curl -X PUT "https://your-mcp-memory.workers.dev/{userId}/memories/{memoryId}" \
-H "Content-Type: application/json" \
-d '{"content": "Updated memory content here"}'
```
--------------------------------
### Manage Edit Mode State
Source: https://github.com/puliczek/mcp-memory/blob/main/static/index.html
Functions to toggle input fields and button styles when entering or exiting edit mode for memory items.
```javascript
tent; input.className = "memory-input block w-full rounded-md border-gray-300 bg-white py-1 px-2 text-gray-900 shadow-sm focus:border-orange-500 focus:ring focus:ring-orange-500 focus:ring-opacity-50 sm:text-sm"; // Light mode input contentContainer.replaceChild(input, contentSpan); input.focus(); input.select(); // Select text for easy replacement // Change buttons to Save/Cancel - Light mode styling editButton.textContent = "Save"; // Remove old styles, add new Save button styles (green) editButton.classList.remove( "edit-button", "border-gray-300", "bg-white", "text-gray-700", "hover:bg-gray-50" ); editButton.classList.add( "save-button", "border-green-500", "bg-green-50", "text-green-700", "hover:bg-green-100", "focus:ring-green-500" ); deleteButton.textContent = "Cancel"; // Remove old Delete styles, add new Cancel button styles (neutral gray) deleteButton.classList.remove( "delete-button", "border-red-300", "bg-red-50", "text-red-700", "hover:bg-red-100", "focus:ring-red-500" ); deleteButton.classList.add( "cancel-button", "border-gray-300", "bg-white", "text-gray-700", "hover:bg-gray-50", "focus:ring-orange-500" ); // Neutral style for cancel } function exitEditMode(listItem, newContent) { const contentContainer = listItem.querySelector(".flex-grow"); const input = contentContainer.querySelector(".memory-input"); const buttonContainer = listItem.querySelector(".flex.space-x-2"); const saveButton = buttonContainer.querySelector(".save-button"); const cancelButton = buttonContainer.querySelector(".cancel-button"); // Replace input with span const contentSpan = document.createElement("span"); contentSpan.className = "memory-content text-sm text-gray-800 block truncate"; // Reapply correct light mode class contentSpan.textContent = newContent; contentContainer.replaceChild(contentSpan, input); delete listItem.dataset.originalContent; // Change buttons back to Edit/Delete - Light mode styling saveButton.textContent = "Edit"; // Remove Save styles, add back Edit styles saveButton.classList.remove( "save-button", "border-green-500", "bg-green-50", "text-green-700", "hover:bg-green-100", "focus:ring-green-500" ); saveButton.classList.add( "edit-button", "border-gray-300", "bg-white", "text-gray-700", "hover:bg-gray-50", "focus:ring-orange-500" ); saveButton.disabled = false; cancelButton.textContent = "Delete"; // Remove Cancel styles, add back Delete styles cancelButton.classList.remove( "cancel-button", "border-gray-300", "bg-white", "text-gray-700", "hover:bg-gray-50", "focus:ring-orange-500" ); cancelButton.classList.add( "delete-button", "border-red-300", "bg-red-50", "text-red-700", "hover:bg-red-100", "focus:ring-red-500" ); }
```
--------------------------------
### REST API: Delete Memory
Source: https://context7.com/puliczek/mcp-memory/llms.txt
Removes a specific memory from both the D1 database and the Vectorize index.
```bash
# Delete a specific memory
curl -X DELETE "https://your-mcp-memory.workers.dev/{userId}/memories/{memoryId}"
# Response on success:
{
"success": true
}
# Response on error:
{
"success": false,
"error": "Failed to delete memory"
}
```