javascript debugging troubleshooting tutorial

MCP Debugging: When Memory Goes Wrong (JavaScript)

Practical troubleshooting guide for common MCP memory issues in JavaScript. Learn to diagnose connection failures, stale memories, and retrieval problems.

CodeMem Team

Your MCP memory setup was working perfectly—until it wasn't. Your AI assistant suddenly forgets everything, searches return nothing relevant, or memories seem to vanish into the void. Sound familiar?

This guide covers the most common MCP memory issues JavaScript developers face and exactly how to fix them. We'll go from quick diagnostics to deep debugging techniques.

Quick Diagnostic Checklist

Before diving deep, run through this 60-second checklist:

# 1. Is the MCP server running?
claude mcp list

# 2. Is your API key valid?
curl -H "Authorization: Bearer $CODEMEM_API_KEY" \
  https://codemem.dev/api/health

# 3. Can you manually search?
claude mcp call codemem search_memory '{"query": "test"}'

If any of these fail, you've found your problem. Let's fix the specific issues.

Issue #1: "MCP Server Not Found"

Symptom: Claude says it doesn't have access to memory tools, or claude mcp list doesn't show codemem.

Common causes:

  • MCP registration was per-project, not global
  • Config file got corrupted or overwritten
  • Wrong working directory when running Claude

Fix: Re-register with the global flag:

# Remove existing registration
claude mcp remove codemem

# Re-add with OAuth (opens browser for auth)
claude mcp add codemem --transport http \
  --url https://app.codemem.dev/mcp

# Verify
claude mcp list

Issue #2: Authentication Failures

Symptom: Memory operations return 401/403 errors, or work locally but fail in CI/CD.

Debug approach: Check which key is actually being used:

// debug-auth.mjs
import { execSync } from 'child_process';

const mcpConfig = JSON.parse(
  execSync('claude mcp show codemem --json').toString()
);

console.log('Using key:', mcpConfig.key?.slice(0, 10) + '...');
console.log('Endpoint:', mcpConfig.url);

// Test the key directly
const response = await fetch('https://codemem.dev/api/health', {
  headers: { 'Authorization': `Bearer ${mcpConfig.key}` }
});

console.log('Auth status:', response.status);
console.log('Response:', await response.json());

Common fixes:

  • Regenerate your API key in the dashboard
  • Check for environment variable conflicts (CODEMEM_API_KEY vs config)
  • Ensure the key has the right scopes (read/write vs read-only)

Issue #3: Memories Saved But Not Found

Symptom: You saved a memory, but searching for it returns nothing. This is the most frustrating issue.

Debug with this script:

// debug-retrieval.mjs
async function debugMemoryRetrieval() {
  // 1. Save a test memory with unique content
  const testId = `debug-${Date.now()}`;
  const testContent = `Debug memory ${testId}: TypeScript strict mode`;
  
  console.log('Saving:', testContent);
  await addMemory({ content: testContent, tags: ['debug'] });
  
  // 2. Wait for indexing (embeddings take time)
  console.log('Waiting 3s for indexing...');
  await new Promise(r => setTimeout(r, 3000));
  
  // 3. Search with exact terms
  const exactSearch = await searchMemory({ query: testId });
  console.log('Exact match:', exactSearch.length > 0 ? '✓' : '✗');
  
  // 4. Search with semantic terms
  const semanticSearch = await searchMemory({ 
    query: 'TypeScript configuration' 
  });
  console.log('Semantic match:', semanticSearch.length > 0 ? '✓' : '✗');
  
  // 5. Check if project filter is the culprit
  const noFilterSearch = await searchMemory({ 
    query: testId,
    project: null  // explicitly no project filter
  });
  console.log('Without project filter:', noFilterSearch.length);
}

Common causes:

  • Project mismatch: Memory saved with project "app-v1", searching in "app-v2"
  • Indexing delay: Search happening before embeddings are generated
  • Semantic gap: Search query too different from stored content

Issue #4: Stale or Outdated Memories

Symptom: Your AI keeps using old information even after you updated it.

Memory doesn't auto-update—you need to explicitly manage versions:

// memory-hygiene.mjs
async function updateMemory(oldContent, newContent, tags) {
  // 1. Find the old memory
  const existing = await searchMemory({ 
    query: oldContent, 
    limit: 1 
  });
  
  if (existing.length > 0) {
    // 2. Delete the old one
    await deleteMemory({ id: existing[0].id });
    console.log('Deleted outdated memory:', existing[0].id);
  }
  
  // 3. Add the new version
  const newId = await addMemory({ 
    content: newContent, 
    tags: [...tags, 'updated-' + new Date().toISOString().slice(0,10)]
  });
  
  console.log('Created updated memory:', newId);
  return newId;
}

// Usage
await updateMemory(
  'We use Jest for testing',
  'We migrated from Jest to Vitest in Feb 2026',
  ['testing', 'tooling']
);

Issue #5: Timeout and Performance Problems

Symptom: Memory operations are slow or timeout, especially with large memory stores.

Quick wins:

// 1. Reduce search scope
const results = await searchMemory({ 
  query: 'API design patterns',
  limit: 5,           // Don't fetch more than needed
  project: 'my-api',  // Filter by project
  tags: ['architecture']  // Narrow by tags
});

// 2. Use streaming for large operations
const stream = await searchMemoryStream({ query: 'all preferences' });
for await (const memory of stream) {
  processMemory(memory);  // Handle one at a time
}

// 3. Batch writes instead of individual calls
await addMemories([
  { content: 'Prefer named exports', tags: ['style'] },
  { content: 'Use ESM not CJS', tags: ['modules'] },
  { content: 'Error boundaries in every route', tags: ['react'] }
]);

Advanced: Enable Debug Logging

When all else fails, enable verbose logging to see exactly what's happening:

# Set debug environment variable
export DEBUG=codemem:*

# Or in your code
import { setLogLevel } from '@codemem/sdk';
setLogLevel('debug');

// Now every MCP call logs:
// → Request: search_memory { query: "...", limit: 10 }
// → Response: 200 OK (47ms) [3 results]

Prevention: Memory Health Checks

Add this to your CI pipeline to catch memory issues early:

// scripts/memory-health.mjs
const checks = [
  { name: 'Connection', fn: () => healthCheck() },
  { name: 'Write', fn: () => addMemory({ content: 'CI test', tags: ['ci'] }) },
  { name: 'Read', fn: () => searchMemory({ query: 'CI test', limit: 1 }) },
  { name: 'Delete', fn: async () => {
    const [mem] = await searchMemory({ query: 'CI test', tags: ['ci'] });
    if (mem) await deleteMemory({ id: mem.id });
  }}
];

for (const check of checks) {
  try {
    await check.fn();
    console.log(`✓ ${check.name}`);
  } catch (e) {
    console.error(`✗ ${check.name}: ${e.message}`);
    process.exit(1);
  }
}

Pro tip: Most memory issues come from project/environment mismatches. When debugging, always start by verifying you're using the same project identifier and API key that was used when the memory was created. The dashboard shows all your memories with their project tags—use it to verify what's actually stored.

Still Stuck?

If you've tried everything above and still have issues:

Memory is the foundation of intelligent AI assistants. When it works, it's magic. When it breaks, use this guide to get back on track quickly.