What is the Model Context Protocol?
The Model Context Protocol (MCP) is a standard that allows AI models to invoke external tools during a conversation. Instead of the application code calling an API and injecting results into the prompt, the model itself decides when to call a tool, what parameters to pass, and how to use the result.
Think of MCP as a USB-C port for AI models — a standardized interface that any tool can implement, and any MCP-compatible model can use without custom integration code.
Before MCP, giving an AI agent access to memory required custom orchestration:
# Pre-MCP: application orchestrates everything
user_message = "What did I say about my budget last week?"
# 1. Application decides to search memory (custom logic)
memories = memory_api.search(query=user_message, limit=5)
# 2. Application injects results into prompt (manual formatting)
prompt = f"Context from memory:\n{format_memories(memories)}\n\nUser: {user_message}"
# 3. Model generates response (no awareness of memory system)
response = llm.complete(prompt)
With MCP, the model handles this autonomously:
# With MCP: model decides when and how to use memory
# The model sees available tools and calls them as needed:
# Model internally decides: "I should search memory for this"
# Model calls: memory_search(query="budget discussion", created_after="2026-05-09")
# Model receives results and incorporates them into its response
# No application orchestration needed
How MCP Works: The Protocol
MCP uses a JSON-RPC-based communication protocol between the model host (client) and tool servers. The lifecycle has three phases:
1. Discovery
When a model session starts, the client connects to configured MCP servers and discovers available tools:
// Client -> Server: list available tools
{"jsonrpc": "2.0", "method": "tools/list", "id": 1}
// Server -> Client: tool definitions
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "memory_add",
"description": "Store a new memory",
"inputSchema": {
"type": "object",
"properties": {
"namespace": {"type": "string"},
"content": {"type": "string"},
"importance": {"type": "number", "minimum": 0, "maximum": 1}
},
"required": ["namespace", "content"]
}
},
{
"name": "memory_search",
"description": "Search memories by semantic similarity",
"inputSchema": { ... }
}
// ... 81 more tools
]
}
}
2. Invocation
During conversation, the model decides to call a tool and the client forwards the request:
// Client -> Server: invoke a tool
{
"jsonrpc": "2.0",
"method": "tools/call",
"id": 2,
"params": {
"name": "memory_search",
"arguments": {
"namespace": "user-conversations",
"query": "budget discussion last week",
"limit": 5,
"recency_weight": 0.5
}
}
}
// Server -> Client: tool result
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{
"type": "text",
"text": "[{\"id\": \"mem_abc\", \"content\": \"User mentioned Q3 budget is $50k...\", \"score\": 0.89}]"
}
]
}
}
3. Continuation
The model incorporates the tool result into its reasoning and continues generating a response. It may call additional tools if needed — for example, searching memory, then updating a knowledge graph edge based on what it found.
Dakera's 83 MCP Tools
Dakera exposes its entire API surface as MCP tools. This means any MCP-compatible model (Claude, GPT-4, Gemini, local models with MCP support) can directly interact with the memory system. The tools are organized into categories:
| Category | Tools | Examples |
|---|---|---|
| Memory CRUD | 12 | memory_add, memory_get, memory_update, memory_delete |
| Search | 8 | memory_search, memory_search_hybrid, memory_search_by_metadata |
| Knowledge Graph | 14 | kg_add_edge, kg_traverse, kg_get_entity, kg_delete_edge |
| Sessions | 10 | session_create, session_list, session_add_memory |
| Namespaces | 8 | namespace_create, namespace_configure, namespace_stats |
| Temporal | 6 | memory_search_timerange, memory_decay_status |
| Analytics | 9 | memory_count, namespace_usage, search_analytics |
| Admin | 16 | backup, restore, health, metrics, config_reload |
Setting Up Dakera as an MCP Server
Dakera runs as an MCP server using stdio transport (for local models) or SSE transport (for remote connections). Configuration is typically done in your model client's MCP settings.
Claude Desktop / Claude Code
// .mcp.json or claude_desktop_config.json
{
"mcpServers": {
"dakera": {
"command": "dakera",
"args": ["mcp-serve"],
"env": {
"DAKERA_HOST": "localhost",
"DAKERA_PORT": "3300"
}
}
}
}
Custom MCP Client
// For applications building their own MCP client
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
const transport = new StdioClientTransport({
command: "dakera",
args: ["mcp-serve"]
});
const client = new Client({
name: "my-agent",
version: "1.0.0"
});
await client.connect(transport);
// List available tools
const tools = await client.listTools();
console.log(`Dakera exposes ${tools.tools.length} MCP tools`);
// Call a tool
const result = await client.callTool({
name: "memory_search",
arguments: {
namespace: "user-data",
query: "user preferences",
limit: 5
}
});
Why MCP Matters for Agent Memory
The Model Decides When to Remember
Without MCP, your application code must decide when to store and retrieve memories. You write heuristics: "after every user message, search memory" or "store important facts after each turn." These heuristics are brittle and miss edge cases.
With MCP, the model itself decides when memory operations are needed. It can:
- Search memory proactively before answering a question
- Store a fact immediately when the user shares something important
- Update the knowledge graph when it discovers a relationship
- Check temporal context when a question involves time
Reduced Integration Complexity
Instead of writing custom integration code for each model provider, you implement the MCP server once and it works with every MCP-compatible client. Adding memory to a new agent framework becomes a single configuration line rather than a custom integration.
Tool Composition
Models can compose multiple MCP tools in a single turn. A model might:
- Call
memory_searchto find relevant context - Call
kg_traverseto understand entity relationships - Call
memory_addto store a new insight - Call
kg_add_edgeto record a discovered relationship
All within a single conversation turn, autonomously.
MCP Tool Design Principles
Dakera's MCP tools follow several design principles that make them effective for model consumption:
Descriptive Tool Names
Tool names are verb_noun format: memory_search, kg_add_edge, session_create. Models parse these intuitively.
Rich Descriptions
Each tool has a detailed description that helps the model understand when and how to use it:
{
"name": "memory_search",
"description": "Search memories by semantic similarity and keyword matching. Use this when you need to recall information the user previously shared or when answering questions that might require historical context. Returns ranked results with relevance scores.",
"inputSchema": { ... }
}
Sensible Defaults
Optional parameters have defaults that work for common cases. A model can call memory_search with just a query and namespace — the limit defaults to 5, the mode defaults to hybrid, recency weight defaults to 0.3.
Structured Output
Tool results are JSON-structured so models can parse and reason about them:
// memory_search result
{
"memories": [
{
"id": "mem_7f3a2b",
"content": "User prefers dark mode and monospace fonts for code",
"score": 0.92,
"created_at": "2026-05-14T10:30:00Z",
"importance": 0.8,
"namespace": "preferences"
}
],
"total_matches": 12,
"search_time_ms": 8
}
Common MCP Memory Patterns
Pattern: Auto-Remember
The model stores important information without being told to:
// User says: "My team uses Python 3.11 and we deploy to AWS EKS"
// Model recognizes this as valuable context and calls:
memory_add({
namespace: "user-context",
content: "Team uses Python 3.11, deploys to AWS EKS",
importance: 0.7,
metadata: { category: "tech-stack" }
})
Pattern: Contextual Recall
The model checks memory before answering questions that might have personalized answers:
// User asks: "What testing framework should I use?"
// Model calls memory_search first to check for existing context:
memory_search({
namespace: "user-context",
query: "testing framework preferences tech stack",
limit: 3
})
// If it finds "Team uses pytest with coverage > 90% policy"
// it tailors the recommendation accordingly
Pattern: Graph Building
The model builds understanding of the user's world over time:
// User mentions: "Alice from my team reviewed the PR"
// Model extracts and stores the relationship:
kg_add_edge({
namespace: "user-world",
source: { type: "person", name: "Alice" },
target: { type: "team", name: "user's team" },
edge_type: "part_of",
metadata: { role: "code reviewer" }
})
Security Considerations
MCP tools have full access to the memory system, which means a compromised or misbehaving model could:
- Delete memories (use read-only tool subsets for untrusted models)
- Exfiltrate data through tool calls (monitor tool call logs)
- Poison the knowledge graph with false relationships
Dakera mitigates these risks through:
- Tool filtering — expose only the tools each agent needs
- Namespace ACLs — restrict which namespaces each MCP session can access
- Audit logging — every MCP tool call is logged with the session context
- Rate limiting — prevent runaway tool calls from filling storage
MCP vs. REST API
Dakera exposes the same capabilities through both MCP (for model-initiated access) and REST API (for application-initiated access). Choose based on your architecture:
| Use MCP when | Use REST API when |
|---|---|
| Model decides when to use memory | Application decides when to use memory |
| Running with MCP-compatible clients | Building custom orchestration |
| Want autonomous agent behavior | Want deterministic control flow |
| Prototyping agent capabilities | Production pipelines with strict SLAs |
Many production systems use both: MCP for the model's autonomous memory operations, and REST API for application-level operations like backup, monitoring, and batch ingestion.
For a deeper dive into setting up Dakera as an MCP server, see the MCP Server documentation.