个人日记MCP服务器

一个具有持久记忆、语义搜索、健康追踪和杂货集成功能的个人日记MCP服务器,为Claude等AI提供历史对话上下文。

  • by anicka-net
  • C#
  • 本地部署
  • 1 星标
  • 更新于
在 GitHub 查看 anicka-net/recall

使用说明

召回

注: 这是一个个人学习项目。我用它来学习C#。NET构建我每天实际使用的东西。工作在 Linux、macOS和Windows.PR受欢迎,但预计会有粗糙的边缘。

一个具有持久内存、语义搜索、健康跟踪和杂货集成的个人日记MCP服务器。

Recall允许Claude(或任何兼容MCP的AI)访问您过去的对话。每一次新的对话都是从自动检索到的相关上下文开始的,因此人工智能总是知道你之前讨论过什么。

运作原理

召回是 MCP服务器 它将日记条目存储在SQLite中,并带有用于语义搜索的向量嵌入(通过ONNX Runtime的全MiniLM-L6-v2)。工具使用动作参数模式来保持工具数量低:

工具 行动 目的
diary 写、更新、获取、固定 创建、编辑、获取或固定日记条目
diary_search 上下文、查询、列表 查找条目:对话开始上下文、关键字搜索、最近列表
diary_day 查看、计划、总结 日视图、设置计划、存储每日总结
diary_time -- 当前日期/时间(以便AI知道它是什么时候)
health 最近、查询、log_migraine、log_period 健康/健身数据、偏头痛和周期跟踪
rohlik_search 搜索,最后一分钟 搜索Rohlik.cz杂货产品
rohlik_cart 查看、添加、删除、更新、检查 购物车管理
rohlik_orders 历史记录、详细信息、即将发布 订单历史记录和跟踪
rohlik_delivery 信息、时隙、预留 交货时隙
rohlik_account 溢价、公告、包、结账、购物列表 帐户信息
rohlik_checkout 提交、付款 订单提交和付款(TOTP保护)

快速启动

先决条件

安装并连接到Claude Code

git clone https://github.com/anicka-net/recall.git
cd recall
dotnet build

# Register with Claude Code
claude mcp add --transport stdio --scope user recall -- \
    dotnet run --project /path/to/recall/src/Recall.Server/Recall.Server.csproj

日记工具现在可以在您的Claude Code对话中使用。

配置

配置文件: ~/.recall/config.json

{
  "databasePath": "~/.recall/recall.db",
  "systemPrompt": "Custom instructions for the AI",
  "promptFile": "~/.recall/prompt.txt",
  "autoContextLimit": 5,
  "searchResultLimit": 10,
  "tools": ["diary", "health"],
  "rohlikUsername": "user@example.com",
  "rohlikPassword": "password",
  "rohlikBaseUrl": "https://www.rohlik.cz"
}

所有字段都是可选的。默认值开箱即用。

这 tools 数组控制注册哪些工具模块。有效模块: diary, health, rohlik。当省略或为空时,所有模块都将启用。Rohlik还要求出示证件。

数据存储

所有数据都存储在本地 ~/.recall/recall.db (SQLite)。除非您配置远程传输,否则任何东西都不会离开您的机器。

语义搜索模型

召回用途 全迷你LM-L6-v2 用于语义搜索。下载模型文件:

mkdir -p ~/.recall/models/all-MiniLM-L6-v2
curl -L -o ~/.recall/models/all-MiniLM-L6-v2/model.onnx \
    https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2/resolve/main/onnx/model.onnx
curl -L -o ~/.recall/models/all-MiniLM-L6-v2/vocab.txt \
    https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2/resolve/main/vocab.txt

如果没有模型文件,Recall将退回到子字符串(LIKE)搜索。

身份验证和访问控制

Recall有两层身份验证: 传输层 (谁可以连接)和 刀具水平仪 (他们所看到的)。

传输:本地与远程

本地(stdio): Claude Code通过stdio连接,无需传输身份验证。

远程(HTTP): 具有PKCE或API密钥的OAuth 2.1控制谁可以连接。

# OAuth setup (for claude.ai)
dotnet run -- oauth setup
# Prompts for a passphrase and your server's public URL

# API keys (for other clients)
dotnet run -- key create "my-client"    # Generate a key (shown once)
dotnet run -- key list                  # List all keys
dotnet run -- key revoke 3              # Revoke by ID

这两种方法同时起作用。如果没有任何配置,服务器将打开运行。

工具级别:四层访问

每次日记/健康工具调用(除 diary_time)需要a secret 参数。服务器对其进行哈希运算,并与配置的哈希值进行比较,以确定访问级别。当根本没有配置身份验证哈希时,服务器默认为特权访问(仅供本地使用)。Rohlik工具没有访问控制(它们由是否配置凭据来控制)。

级别 日记 健康 固定/基础 写限制
享有特权的 所有未分类的条目,所有层级 是 是 有
编程 无限制+仅无范围 否 否
作用域的 仅限自己的范围 否 否
无 (无/坏秘密) 拒绝 拒绝

在中配置 ~/.recall/config.json:

{
  "guardianSecretHash": "<sha256 of privileged passphrase>",
  "codingSecretHash": "<sha256 of coding passphrase>"
}

使用以下方法生成哈希值: echo -n "your-passphrase" | sha256sum

将秘密注入克劳德密码 --使用a PreTool使用挂钩 它将编码秘密添加到每个Recall工具调用中。示例 ~/.claude/hooks/recall-secret.sh:

#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')

# diary_time needs no secret
if [ "$TOOL_NAME" = "mcp__claude_ai_Recall__diary_time" ]; then
    exit 0
fi

TOOL_INPUT=$(echo "$INPUT" | jq -r '.tool_input')
UPDATED=$(echo "$TOOL_INPUT" | jq '. + {"secret": "YOUR_CODING_SECRET"}')

jq -n --argjson updated "$UPDATED" '{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "allow",
    "updatedInput": $updated
  }
}'

在中注册 ~/.claude/settings.json:

{
  "hooks": {
    "PreToolUse": [{
      "matcher": "mcp__claude_ai_Recall__.*",
      "hooks": [{"type": "command", "command": "/path/to/recall-secret.sh"}]
    }]
  }
}

对于claude.ai(特权),在系统提示符中包含特权秘密,并指示将其作为 secret 每个工具调用中的参数。

范围用户(独立项目)

多个用户或项目可以共享一个完全隔离的Recall实例。每个作用域用户都有自己的日记空间——他们只能查看和写入标记有其作用域的条目。管理员(特权用户)默认情况下会看到全局条目,并可以选择查看任何范围。

级别 看到 写入 健康
享有特权的 全局条目(根据请求提供所有范围) 任何范围 是
编程 仅全局无限制 全局无限制 no
作用域的 只有范围 只有范围 没有

设置范围:

# Generate credentials
PASSPHRASE=$(openssl rand -base64 24)
HASH=$(echo -n "$PASSPHRASE" | sha256sum | cut -d' ' -f1)
echo "Passphrase: $PASSPHRASE"
echo "Hash: $HASH"

添加 ~/.recall/config.json 在服务器上:

{
  "Scopes": [
    { "Name": "project-name", "SecretHash": "<hash from above>" }
  ]
}

重新启动服务。将密码提供给用户——请参阅 ONBOARDING.md 对于他们的设置步骤。

范围隔离是如何工作的:

  • 条目有 scope 列(NULL=全局,“项目名称”=范围)
  • 作用域用户的写入会自动标记其作用域
  • 查询在SQL级别按作用域过滤——ONNX矢量搜索仅扫描匹配的条目,而不是整个数据库
  • 现有条目(作用域=NULL)对特权和编码仍然可见,对作用域用户不可见

重要提示:PreToolUse挂钩 updatedInput 替换,而不是合并。 钩子脚本必须读取原始脚本 tool_input 从stdin中,将秘密合并到其中 jq,并返回完整的组合对象。如果你只回来 {secret: "..."},所有其他参数(如 content)丢失,工具调用失败。看 ONBOARDING.md 以获取正确的钩子脚本。

分层老化

随着条目的积累,较旧的条目会自动降低优先级,因此最近的上下文仍然具有相关性。参赛作品分为三个层次:

级别 姓名 年龄 diary_search 上下文 diary_search 查询 diary_search 列表
0 热门 <7天 最近+搜索 是 是
1 温暖 7-90天 仅搜索 是 否
2 寒冷 >90天 否 是 否

衰老在每个开始时都很缓慢 diary_search action=上下文调用。阈值是可配置的:

{
  "tierHotDays": 7,
  "tierWarmDays": 90
}

固定和基础条目

置顶 条目(diary action=pin id=42)免于自动老化——它们永远保持在当前级别。

基础的 条目(diary action=pin id=42 basical=true)被固定,并且始终显示在顶部 diary_search action=特权用户的上下文。它们显示为紧凑的索引(ID+第一行) diary action=获取完整内容。对于应始终与上下文相关的参考材料很有用。

这两个功能都是特权。

日历

日历提供日记的日视图:计划、摘要和链接条目。

运作原理

每个日期都可以有一个包含两个字段的日历条目:

  • 计划 --你打算做什么(可以为未来的日期设置)
  • 摘要 --对所发生事情的简明记录(事后写成)

日记条目根据其创建日期自动链接到日历日。呼叫 diary_day action=带日期的视图,在一个视图中查看所有内容。

访问控制

日历条目遵循与日记条目相同的访问模型:

级别 看到 可以创建
享有特权的 所有日历条目(任何范围,无论是否受限) 受限和不受限
编程 无范围,仅无限制 仅无限制
作用域的 仅限自己的范围

一个日期可以有多个具有不同访问级别的日历条目。例如,特权用户可能会在同一天同时编写受限摘要(包含私人详细信息)和非受限摘要(对编码会话安全)。这 restricted 日历条目上的标记控制可见性的方式与日记条目相同。

生成摘要

摘要是存储的文本,不是自动生成的。预期的工作流程:

  1. 呼叫 diary_day action=查看查看条目的日期
  2. 写一个简明的总结
  3. 呼叫 diary_day action=总结以存储它

这可以手动完成,也可以作为跨历史日期的批处理操作编写脚本。

健康数据集成

Recall可以存储Fitbit的每日健康摘要(睡眠、心率、活动、SpO2)、天气数据、月经周期跟踪和偏头痛跟踪。这 tools/ 目录包含:

脚本 目的
tools/fitbit-sync.py 通过API获取Fitbit数据,丰富天气(Open-Meteo),写入recall.db
tools/fitbit-cron.sh 每小时定时任务:同步+推送到远程+偏头痛风险预测
tools/cycle.py 月经周期跟踪与预测
tools/migraine.py 偏头痛记录、历史与天气/周期背景、7天风险预测

健康数据通过 health MCP工具(操作:最近,查询)。偏头痛和月经开始可以直接通过 health 工具(操作:log_migraine、log_period)或通过CLI脚本。

偏头痛预测

migraine.py predict 获取7天的天气预报,每天根据以下因素对偏头痛风险进行评分:

  • 大气压下降(>5 hPa=中等,>10 hPa=高风险)
  • 月经周期阶段(月经=高,排卵=中等)
  • 温度波动(每日范围>12°C)

风险预测会写入日历表,以便显示在 diary_day 意见。

部署

本地(stdio)

只需按照快速入门中的说明使用Claude Code注册即可。不需要服务器进程。

远程(HTTP)

发布a 独立的 二进制文件,并将其作为服务运行。除非准确无误,否则依赖框架的构建将无法工作。NET运行时已安装在服务器上。

# Build (self-contained for Linux x64)
dotnet publish src/Recall.Server/Recall.Server.csproj \
    -c Release --self-contained -r linux-x64 -o publish/

# Copy to server
rsync -av publish/ server:~/recall-server/

# Run
./publish/Recall.Server --http --port 3000

systemd服务 (/etc/systemd/system/recall.service):

[Unit]
Description=Recall MCP Server
After=network.target

[Service]
Type=exec
User=recall
WorkingDirectory=/opt/recall
ExecStart=/opt/recall/Recall.Server --http --port 3000
Restart=on-failure
RestartSec=5
Environment=DOTNET_ENVIRONMENT=Production

[Install]
WantedBy=multi-user.target
sudo systemctl enable --now recall

在TLS前面放置一个反向代理(Apache/nnginx/Caddy)。Claude.ai需要HTTPS。

更新正在运行的服务器

dotnet publish src/Recall.Server/Recall.Server.csproj \
    -c Release --self-contained -r linux-x64 -o publish/
rsync -av publish/ server:~/recall-server/
# On the server:
sudo systemctl restart recall

SQLite数据库在重新启动时保留。架构迁移在启动时自动运行。

代理外部MCP服务器

Recall可以作为其他MCP服务器的OAuth网关。任何基于stdio的MCP服务器都封装在 超级通道 可以通过Recall的现有身份验证进行代理,无需额外的OAuth设置。(注意:Rohlik杂货工具现在直接集成到召回服务器二进制文件中,而不是代理。)

它是如何工作的:

claude.ai ──HTTPS──▶ reverse proxy ──▶ Recall ──▶ supergateway ──▶ stdio MCP server
                                    (OAuth gate)   (Streamable HTTP)

步骤1:使用supergateway设置外部MCP服务器

# Install on the server
mkdir -p ~/my-mcp && cd ~/my-mcp
npm init -y
npm install supergateway @some/mcp-server

# Create credentials file (if needed)
cat > ~/.config/my-mcp.env << 'EOF'
MY_USERNAME=user@example.com
MY_PASSWORD=secret
EOF
chmod 600 ~/.config/my-mcp.env

步骤2:创建systemd用户单元

# ~/.config/systemd/user/my-mcp.service
[Unit]
Description=My MCP Server (supergateway)
After=network.target

[Service]
Type=exec
EnvironmentFile=%h/.config/my-mcp.env
ExecStart=/usr/bin/npx --prefix %h/my-mcp supergateway \
    --stdio "node %h/my-mcp/node_modules/@some/mcp-server/dist/index.js" \
    --port 8385 \
    --outputTransport streamableHttp \
    --streamableHttpPath /mcp \
    --logLevel info
Restart=on-failure
RestartSec=5

[Install]
WantedBy=default.target
systemctl --user daemon-reload
systemctl --user enable --now my-mcp
loginctl enable-linger  # persist after logout

步骤3:将代理添加到Recall的配置中

在 ~/.recall/config.json:

{
  "mcpProxies": [
    { "prefix": "my-mcp", "target": "http://127.0.0.1:8385" }
  ]
}

重新启动召回。工具现在可以在 https://your-server/recall/my-mcp/mcp 使用相同的OAuth令牌。

步骤4:添加claude.ai连接器

在claude.ai设置中,添加一个MCP连接器,URL为:

https://your-server/recall/my-mcp/mcp

它使用与Recall相同的OAuth密码,没有单独的身份验证设置。

重要提示:

  • 使用 --outputTransport streamableHttp 在supergateway中,claude.ai更喜欢流式HTTP而不是SSE
  • Apache/nnginx中不需要代理配置——现有 /recall/ 代理规则覆盖所有子路径
  • 当 mcpProxies 不存在或为空,零代理代码运行——对Recall没有影响
  • 外部服务的凭据放在env文件中,从不放在Recall的配置或仓库中

建筑

┌─────────────────────────────────────────────┐
│             Recall MCP Server               │
│  SQLite + vector search + OAuth 2.1         │
│                                             │
│  /sse, /message  →  diary, health, rohlik   │
│  /{prefix}/*     →  proxy to backend (opt)  │
└──────┬──────────────────┬───────────────────┘
       │                  │
  MCP protocol      reverse proxy (opt)
       │                  │
  ┌────┴────────┐   ┌─────┴──────────┐
  │ Claude Code │   │  supergateway  │
  │  claude.ai  │   │  (external     │
  │  any client │   │   MCP servers) │
  └─────────────┘   └────────────────┘

建筑

dotnet build                       # Build
dotnet test src/Recall.Tests       # Run tests

许可证

麻省理工学院