上下文记忆更新器

MCP应用是一个基于LLM的系统,通过模型上下文协议(MCP)工具展示上下文记忆功能,允许用户存储、检索和更新旅行偏好及其他通用记忆,并提供工具使用统计以支持持续改进和成本控制。

  • by phnx
  • Python
  • 本地部署
  • 更新于
在 GitHub 查看 phnx/context-mcp

使用说明

MCP应用程序-上下文内存更新程序

此应用程序展示了在基于LLM的系统中使用模型上下文协议(MCP)工具的上下文存储。 它允许不同的用户通过聊天界面使用智能助手存储、检索和更新他们的旅行偏好和其他一般记忆。

在分析方面,该应用程序总结了工具使用统计数据,以支持持续改进和成本控制,并回答了哪些工具调用序列发生得更频繁等问题?或者哪个工具产生的代币最多?

目录

  1. 系统设计
  2. 设置、开发和使用
  3. 测试
  4. 部署
  5. 未来工作
  6. 最后的想法
  7. 附录:快速测试

系统设计

关键设计原理

  1. 集装箱化MCP服务器

    • 选择无服务器来维护持久的数据库连接、稳定的多轮工具状态以及MCP服务器和网关的可重复部署。
    • 提供轻量级进程和网络隔离,允许MCP服务器以最低权限和仅限内部访问运行。
  2. 清除服务器-网关分离

    • MCP服务器处理工具执行和内存逻辑;Python API网关管理浏览器安全访问、身份验证和LLM请求整形。
    • 防止泄露秘密并保持协议逻辑的干净。
  3. 数据库设计

    • SQLite 可移植性和本地测试;模块化数据访问允许在生产环境中直接替换PostgreSQL。
  4. 身份验证和隔离

    • 通过以下方式进行注册、代币发行和严格的每用户数据隔离 user_id;架构为RBAC/IAM扩展留出了空间。
  5. 统一客户端架构

    • CLI和web客户端共享一个 client_core,确保MCP行为的一致性,而不会重复逻辑。
    • 为了安全和简单起见,Web客户端仅通过网关进行通信。
    • 易用性: 这两个客户端都公开了一个简单的聊天界面,即用户内存检索,使交互在不同环境中对称。
    • LLM客户端适配器: 可插拔LLM适配器抽象API调用,允许系统在不修改客户端逻辑的情况下在不同的LLM提供程序之间切换。
  6. 工装结构

    • 记忆、旅行偏好和外部 虚拟的 这些工具对不同的MCP交互模式、CRUD状态、检索和模拟的外部操作进行建模,支持强大的LLM行为测试。
  7. 可测试性和分析

    • 内置工具使用分析,用于了解LLM行为和令牌成本。
    • 多层测试(单元、LLM集成、Puppeteer E2E)确保了可靠性和可控的快速评估。
  8. 堆栈选择

    • FastMCP 用于标准化MCP协议和工具执行,通过Pydantic实现LLM互操作性。
    • FastAPI 用于简单、异步友好的API网关。
    • Render 用于快速容器化应用程序托管。
    • Pytest + Puppeteer 用于单元、集成和端到端测试。

MCP服务器

  • LLM在自然语言查询时可以使用标准化的特定工具:用于用户一般记忆和旅行偏好的CRUD操作
  • 用于上下文记忆的统一数据模型和数据存储
  • 容器化:更持久,比无服务器部署更适合LLM集成

可用工具

向LLM公开标准化工具的核心引擎。

  • 上下文工具: store_, retrieve_, update_, delete_ 对两者 旅行偏好 和 通用存储器.
  • 外部服务模拟: 虚拟工具 lookup_flights, book_hotels等,以测试复杂的工具链能力。

MCP客户端

  • 基于聊天的用户界面、自我识别、个人背景信息
  • 轻量级服务器分析-客户端如何利用MCP服务器?-工具使用的宏观统计
  • 两个版本的客户端,共享相同的核心功能

命令行客户端

  • 带有交互式聊天循环的原生Python cli应用程序
  • 无需部署,仅连接到本地MCP服务器和LLM API

web客户端

  • 与单个网关交互的轻量级前端,不包含密钥和用户信息
  • 使用vanilla JS的单页应用程序
  • 用于MCP&LLM API的Python API网关
  • 集装箱化和可部署
  • 替代:更重的前端JS框架作为与LLM和MCP连接的一站式解决方案,这也需要自己的部署过程和秘密管理,因此退回到简单的客户端网关解决方案

设置、开发和使用

更新本地环境密钥。永远不要硬编码一。

cp .env.example .env
vi .env # update OPENAI_API_KEY

本地依赖关系。在Python 3.13上测试。使用 PyEnv 建议管理本地Python版本。

# option 1: installing in virtual environment (Pipenv--https://pipenv.pypa.io)
pipenv install
pipenv shell

# option 2: installing from frozen requirements.txt
pip install -r requirements.txt

MCP服务器和客户端

MCP服务器和可用客户端可以在多个选项中运行。

选项1) 正在启动没有容器的服务器。

# start server
python src/context-updater/server.py

选项2) 使用单个容器(mcp服务器和web客户端)启动服务器并同步主机数据。

# build images
docker build --target mcp-server -t context-mcp-server:latest .
docker build --target web-client -t context-web-client:latest .

# start mcp-server container
docker run -d --rm -p 0.0.0.0:8000:8000 \
    -v $(pwd)/database:/app/database \
    context-mcp-server:latest

# start web-client container
docker run -d --rm -p 0.0.0.0:8001:8001 \
    --env-file .env \
    -e MCP_SERVER_URL=http://host.docker.internal:8000/mcp \
    -e PYTHONUNBUFFERED=1 \
    context-web-client:latest

选项3) 使用docker compose构建和启动所有容器(mcp服务器和web客户端)。

docker-compose build
docker-compose up -d

非集装箱客户

正在启动CLI客户端,仅适用于本地使用。

# register new user
python src/context-updater/cli_client.py --register

# login or enter chat using stored token
python src/context-updater/cli_client.py

# start web gateway & client
python src/context-updater/web-client/web_gateway.py
# web client runs on http://127.0.0.1:8001

任一选项都应产生以下端点URL:

  • MCP-http://127.0.0.1:8000
    • 匿名内存概述-http://127.0.0.1:8000/memory_overview
  • Web客户端-http://127.0.0.1:8001

测试

单元测试MCP工具在没有LLM的情况下是否正常工作。

# Install dev dependencies
pipenv install --dev

# MCP functional test
pytest test/test_server.py test/test_auth_db.py -v -s

集成测试LLM是否理解来自MCP工具的数据,并能够正确地与MCP工具交互。

# make sure to start server with test flag - do not contaminate real database
IS_MCP_CONTEXT_UPDATER_TEST=true  python src/context-updater/server.py

# LLM hallunication test ~$0.20 per run - can still be flaky :/
RUN_LLM_TESTS=true pytest tests/test_llm.py -v -s

# Single test case
RUN_LLM_TESTS=true pytest test/test_llm.py::TestLLMRealHallucination::test_llm_empty_database_no_hallucination -v -s

测试端到端场景

跑 操纵者 直观地测试聊天场景。

# check pre-dependency Node.js ≥ 18 & npm
node -v
npm -v

# install Puppeteer with its own bundled Chromium
npm install puppeteer

开始测试场景。

# use local env to run e2e test
pipenv shell
# spin web-client & mcp-server -> run puppeteer
bash run-puppeteer.sh tony

部署

在渲染上部署(请参见 行动 脚本)。

  • MCP-https://context-mcp-server.onrender.com/
    • 匿名内存概述-https://context-mcp-server.onrender.com/memory_overview
  • Web客户端-https://context-web-client.onrender.com/

未来工作

上有几个待处理的任务 全部.

  • 可扩展数据库:目前,我使用SQLite存储MCP数据。这绝对不理想。我可以替换数据库函数,使用更健壮的数据库解决方案,例如PostgreSQL或托管数据库服务——只需修改 server_database.py.
  • 更好的用户授权:当前简单的基于令牌的身份验证既不能扩展也不支持基于角色的系统。为了满足这些要求,我可以实现遵循最小权限原则的IAM系统,这样每个用户或客户端只能访问他们实际需要的工具和操作。
  • 模型性能试验:我用 gpt-4o-mini 由于其成本效益。应该测试一下,切换到更高级的模型是否值得为这类任务付出代价。我可以创建语义上困难的数据集和问题来测试这一点。

最后的想法

我出于好奇选择了MCP选项,因为我最近实施了一个 LLM文件助理 我的旧博客是一个玩具项目,它涵盖了RAG选项所需的大部分功能,部分是数据驱动的助手选项。 我觉得这是一个从头开始构建MCP服务器的好机会,因为我只使用过其他人实现的MCP工具。 然而,这是一个相当开放的要求,为解释留下了空间。我希望到目前为止我没有误解它:)

我遇到的最具挑战性的问题是所有基本库和工具的API规范的快速变化。 这使得AI编码助手 非常 不可靠的。 文档也没有提供很好的支持。 在这种情况下,试错法是最好的解决方法,它会对小而简洁的问题提出非常具体的问题。 整体激励永远不会奏效。

附录-快速测试

提示在MCP应用中起着重要作用。为了确保快速效率,我对不同的快速版本进行了测试,这些版本侧重于不同的方面:极简主义、探索性、分析性、风险意识和全面性。 我创建模拟对话场景,收集工具使用统计数据和响应成功率,并选择最佳提示作为应用程序的初始版本。

我结合了变体1(全面)和变体2(分析),因为工具调用分布均衡,预期响应合理,令牌可接受,反映了LLM成本。

pipenv install --dev
python test/prompt_test/test_prompts.py
python test/prompt_test/plot_result.py