memkit

memkit

A fully local, persistent memory layer for AI agents that runs as an MCP stdio server and provides an AI SDK adapter for seamless integration with generateText/streamText agents.

Category
Visit Server

README

memkit

A fully local, persistent memory layer for AI agents. Runs as an MCP server over stdio for Claude Desktop, OpenCode, and any MCP client — and also ships a native AI SDK adapter so you can drop it directly into any generateText / streamText agent without any MCP wiring.

Your AI remembers things. Across sessions. Across projects. Without sending anything to the cloud (unless you want it to).

What it does

Every time your AI learns something worth keeping, it calls add_memory. That memory gets embedded into a vector, stored in a local SQLite database, and automatically linked to similar memories in the same project through a lightweight graph.

When the AI needs to recall something, it calls search_memory. Semantic search finds the closest matches, and optionally walks the graph one hop out to surface related context the AI might not have thought to ask for.

Three tables. Six tools. One SQLite file on your disk.

How it works

Your AI agent
    |
    |--- AI SDK adapter (import "code-memory/adapter")
    |         |
    |         |-- memoryTools       injected into generateText/streamText
    |         |-- memoryMiddleware  auto recall + auto store via wrapLanguageModel
    |         |-- MemoryEmbeddingModel  AI SDK-compatible EmbeddingModelV3
    |
    |--- MCP stdio server (bun run start)
    |         |
    |         | stdio (JSON-RPC)
    |
    |--- Embedding Backend (ollama / openai)
    |
    |--- SQLite
           |-- session
           |-- memory (content + embedding blob)
           |-- memory_edge (similarity links)

When you add a memory:

  1. Text gets embedded via your chosen backend
  2. Inserted into SQLite with the embedding as a raw float32 blob
  3. Similarity scan runs against all memories in the same project
  4. Any pair above the threshold (default 0.82 cosine similarity) gets a graph edge

When you search:

  1. Query gets embedded
  2. Cosine similarity computed against all project memories
  3. Results ranked and filtered by minimum score
  4. If expand_graph is on, neighbors of top results are pulled in

AI SDK Adapter

This is the recommended way to use code-memory when building agents with the Vercel AI SDK. No MCP client, no subprocess, no boilerplate — just import and go.

Install

bun add memkit ai
# or
npm install memkit ai

Set your embedding backend env vars (see Configuration below), then:

createMemory — one call setup

import { createMemory } from "memkit/adapter"
import { streamText, stepCountIs } from "ai"
import { openai } from "@ai-sdk/openai"

const memory = createMemory({
  projectId: "my-app",
  sessionId: "user-abc",
})

// Wrap your model — auto recall before generation, auto store after
const model = memory.wrapModel(openai("gpt-4o"))

const result = await streamText({
  model,
  tools: { ...memory.tools },
  stopWhen: stepCountIs(10),
  messages,
})

That's it. Every call to streamText or generateText will:

  • Search for relevant past memories and inject them into the system prompt
  • Store the assistant's response as a new memory after generation

memoryMiddleware — manual control

If you want to wire the middleware yourself via wrapLanguageModel:

import { wrapLanguageModel, streamText } from "ai"
import { memoryMiddleware } from "memkit/adapter"
import { anthropic } from "@ai-sdk/anthropic"

const model = wrapLanguageModel({
  model: anthropic("claude-sonnet-4-5"),
  middleware: memoryMiddleware({
    projectId: "my-app",
    sessionId: "user-abc",
    searchOptions: {
      limit: 5,         // top memories to inject (default: 5)
      minScore: 0.55,   // similarity threshold (default: 0.55)
      expandGraph: true // pull in graph neighbors (default: false)
    },
    autoRecall: true,   // inject memories before generation (default: true)
    autoStore: true,    // store assistant replies after generation (default: true)
    // optional: customize the memory block injected into the system prompt
    systemPromptTemplate: (memories) =>
      `<memory>\n${memories.map(m => m.content).join("\n")}\n</memory>`,
  }),
})

const result = await streamText({ model, messages })

memoryTools — explicit tool use

Give the model direct control over memory. Useful when you want the model to decide what to remember rather than auto-storing everything.

import { generateText, stepCountIs } from "ai"
import { memoryTools } from "memkit/adapter"
import { openai } from "@ai-sdk/openai"

const result = await generateText({
  model: openai("gpt-4o"),
  tools: { ...memoryTools },
  stopWhen: stepCountIs(10),
  system: `You have persistent memory. Use add_memory to store important context.
Use search_memory before answering questions that might benefit from past context.`,
  messages,
})

Available tools: add_memory, search_memory, delete_memory, list_sessions, get_graph, forget_session.

createMemoryAsync — with embedding model

If you also need the EmbeddingModel (for embed() / embedMany() calls), use the async factory:

import { createMemoryAsync } from "memkit/adapter"
import { embed } from "ai"

const memory = await createMemoryAsync({
  projectId: "my-app",
  sessionId: "user-abc",
})

// memory.embeddingModel is a fully typed EmbeddingModelV3
const { embedding } = await embed({
  model: memory.embeddingModel,
  value: "some text to embed",
})

Adapter API reference

Export Type Description
createMemory(config) sync Returns { tools, middleware, wrapModel }
createMemoryAsync(config) async Same + embeddingModel resolved
memoryTools object All 6 tools as a named map, spread into tools
memoryMiddleware(config) function LanguageModelMiddleware for wrapLanguageModel
getMemoryEmbeddingModel() async Returns a MemoryEmbeddingModel (EmbeddingModelV3)
MemoryEmbeddingModel class AI SDK-compatible embedding model class

CreateMemoryConfig:

{
  projectId: string
  sessionId: string
  searchOptions?: {
    limit?: number       // default 5
    minScore?: number    // default 0.55
    expandGraph?: boolean // default false
  }
  autoStore?: boolean    // default true
  autoRecall?: boolean   // default true
  systemPromptTemplate?: (memories: SearchResult[]) => string
}

MCP Server

The stdio MCP server works unchanged for non-AI-SDK consumers.

Getting started

You need bun and an embedding backend. The easiest local option is ollama:

curl -fsSL https://ollama.ai/install.sh | sh
ollama pull nomic-embed-text
git clone https://github.com/xmanish/memkit.git
cd memkit
bun install
bun run start

With Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json on macOS:

{
  "mcpServers": {
    "memory": {
      "command": "bun",
      "args": ["run", "/path/to/memkit/src/server.ts"],
      "env": {
        "EMBEDDING_BACKEND": "ollama"
      }
    }
  }
}

With OpenCode

Add to .opencode/config.json:

{
  "mcp": {
    "memory": {
      "type": "stdio",
      "command": "bun",
      "args": ["run", "/path/to/code-memory/src/server.ts"],
      "env": {
        "EMBEDDING_BACKEND": "ollama"
      }
    }
  }
}

Via AI SDK MCP client

import { streamText, experimental_createMCPClient } from "ai"

const mcp = await experimental_createMCPClient({
  transport: {
    type: "stdio",
    command: "bun",
    args: ["run", "/path/to/code-memory/src/server.ts"],
  },
})

const tools = await mcp.tools()

const result = await streamText({
  model: "anthropic/claude-sonnet-4-5",
  tools,
  messages,
  system: `You have persistent memory. Use add_memory to store important context.
Use search_memory before answering questions that benefit from past context.`,
})

Configuration

All configuration is via environment variables:

# embedding backend: "ollama" (default) or "openai"
EMBEDDING_BACKEND=ollama

# ollama
OLLAMA_BASE_URL=http://localhost:11434
OLLAMA_EMBED_MODEL=nomic-embed-text

# openai (only needed if EMBEDDING_BACKEND=openai)
OPENAI_API_KEY=sk-...
OPENAI_EMBED_MODEL=text-embedding-3-small

# database location
DB_PATH=~/.memkit/memory.db

# graph linking
EDGE_THRESHOLD=0.82
EDGE_TOP_K=10

Tools reference

add_memory

Store something the AI should remember.

{
  "content": "The user prefers dark mode and uses vim keybindings",
  "session_id": "sess_abc123",
  "project_id": "proj_myapp",
  "metadata": { "source": "user_preference" }
}

Returns { "id": "mem_...", "linked_count": 3 }.

search_memory

Find relevant memories by meaning.

{
  "query": "what editor settings does the user like",
  "project_id": "proj_myapp",
  "limit": 5,
  "min_score": 0.6,
  "expand_graph": true
}

get_graph

Traverse the memory graph from any node.

{ "memory_id": "mem_abc123", "depth": 2 }

Returns { "nodes": [...], "edges": [...] }.

delete_memory

{ "id": "mem_abc123" }

list_sessions

{ "project_id": "proj_myapp" }

forget_session

Delete all memories for a session.

{ "session_id": "sess_abc123" }

How the graph works

When you add a memory it doesn't just sit in a table. It gets compared against every other memory in the project and any pair with similarity above the threshold gets linked.

"user likes dark mode" ----0.91---- "prefers dark themes in all apps"
                           |
                         0.85
                           |
                  "UI should default to dark"

A search for "theme preferences" might directly hit "user likes dark mode", and graph expansion pulls in "UI should default to dark" even if that memory's embedding isn't a top match for the query.


Project structure

code-memory/
  src/
    server.ts              MCP stdio server, tool routing
    memory.ts              core logic: add, search, graph traversal
    db.ts                  SQLite setup, migrations, cosine similarity
    types.ts               zod schemas for all inputs and outputs
    embeddings/
      index.ts             backend factory (ollama | openai)
      ollama.ts            ollama embedding client
      openai.ts            openai embedding client
    adapter/               AI SDK integration layer
      index.ts             public exports
      tools.ts             AI SDK tool() definitions
      middleware.ts        LanguageModelMiddleware — auto recall + store
      embedding-model.ts   EmbeddingModelV3 adapter
      create-memory.ts     createMemory() / createMemoryAsync() factories
  package.json
  tsconfig.json
  README.md

Roadmap

  • Memory compaction (summarize old memories to save space)
  • TTL / expiry on memories
  • Better graph algorithms (PageRank-style importance scoring)
  • npm package

License

MIT

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured