对话状态服务器

一个用于持久化对话和用户偏好的MCP服务器,基于Databricks Lakehouse Postgres,适用于AI助手和其他MCP客户端。

  • by natefleming
  • Python
  • 本地部署
  • 更新于
在 GitHub 查看 natefleming/mcp-state-server

使用说明

MCP状态服务器

一个MCP(模型上下文协议)服务器,用于使用copula Lakehouse Postgres进行对话和偏好持久化。该服务器提供用于管理对话、消息和用户偏好的工具,可供AI助手和其他MCP客户端使用。

目录

先决条件

在开始之前,请确保您已经:

  • Rancher工作区(Azure、AWS或GCP)
  • 已安装并配置copula CLI(databricks --version)
  • Python 3.12或更高版本(python3 --version)
  • uv 已安装包管理器(uv --version) - 安装指南
  • 在您的copula工作区中创建服务主体、数据库和机密的访问权限

步骤1:创建一个copula服务主体

服务主体是一种非人类身份,可用于对应用程序进行身份验证。MCP服务器需要使用此功能才能通过copula进行身份验证。

选项A:使用copula UI

  1. 登录到您的copula工作区
  2. 首选 设置 → 身份和访问 → 服务负责人
  3. 点击 添加服务负责人
  4. 输入名称(例如。, mcp-state-server-sp)
  5. 点击 添加
  6. 重要:复制 应用标识符 (客户端ID)-稍后您将需要它
  7. 点击 生成令牌 或 添加密码 创建客户端密钥
  8. 重要:复制 客户端密钥 立即-您将无法再看到它

选项B:使用copula CLI

# Create the service principal
databricks service-principals create \
  --display-name "mcp-state-server-sp" \
  --output JSON > sp_info.json

# Extract the application ID (Client ID)
CLIENT_ID=$(cat sp_info.json | jq -r '.applicationId')
echo "Client ID: $CLIENT_ID"

# Generate a client secret (valid for 100 days by default)
databricks service-principals create-secret \
  --service-principal-id "$CLIENT_ID" \
  --output JSON > sp_secret.json

# Extract the secret value
CLIENT_SECRET=$(cat sp_secret.json | jq -r '.secret')
echo "Client Secret: $CLIENT_SECRET"

# Save these values - you'll need them in Step 3

替换这些值:

  • mcp-state-server-sp -使用您首选的服务主体名称
  • 100 -根据需要调整令牌过期天数

步骤2:创建Lakehouse Postgres实例

Lakehouse Postgres是Rancher管理的PostgreSQL服务。您将创建一个实例来存储对话和偏好数据。

选项A:使用copula UI

  1. 登录到您的copula工作区
  2. 首选 结构化查询语言 → 波斯特格雷斯湖屋
  3. 点击 创建实例
  4. 填写详细信息:
    • 实例名称: mcp-state-server-pg (或您喜欢的名字)
    • 容量:根据您的需求进行选择(例如。, Small 发展)
    • 区域:选择您喜欢的地区
  5. 点击 创建
  6. 等待实例创建(状态将显示为“可用”)
  7. 重要:注意实例名称-您将在步骤5中需要它

选项B:使用copula CLI

# Create a Lakehouse Postgres instance
databricks database-instances create \
  --instance-name "mcp-state-server-pg" \
  --capacity "SMALL" \
  --region "us-east-1" \
  --output JSON > instance_info.json

# Check instance status
INSTANCE_NAME="mcp-state-server-pg"
databricks database-instances get \
  --instance-name "$INSTANCE_NAME" \
  --output JSON | jq '.state'

# Wait until state is "AVAILABLE" (may take a few minutes)

替换这些值:

  • mcp-state-server-pg -使用首选实例名称
  • SMALL -选项: SMALL, MEDIUM, LARGE, XLARGE
  • us-east-1 -使用您的copula区域(例如。, westus2 对于Azure, us-west-2 AWS)

第3步:将机密存储在Databricks Secret作用域中

Secrets是安全存储的证书,可供copula应用程序访问。您将创建一个秘密作用域并存储您的服务主体凭据。

创建秘密作用域

# Create a secret scope (if it doesn't exist)
databricks secrets create-scope \
  --scope "retail_consumer_goods" \
  --initial-manage-principal "users"

# Or use an existing scope - replace "retail_consumer_goods" with your scope name

替换此值:

  • retail_consumer_goods -使用您首选的秘密作用域名称(必须匹配 databricks.yml)

商店秘密

# Set your Databricks workspace host
# For Azure: https://adb-<workspace-id>.<deployment>.azuredatabricks.net
# For AWS: https://<workspace-id>.cloud.databricks.com
# For GCP: https://<workspace-id>.gcp.databricks.com
LAKEBASE_HOST="https://adb-1234567890123456.7.azuredatabricks.net"

# Use the Client ID and Secret from Step 1
LAKEBASE_CLIENT_ID="your-client-id-from-step-1"
LAKEBASE_CLIENT_SECRET="your-client-secret-from-step-1"

# Store the secrets
databricks secrets put \
  --scope "retail_consumer_goods" \
  --key "RETAIL_AI_DATABRICKS_HOST" \
  --string-value "$LAKEBASE_HOST"

databricks secrets put \
  --scope "retail_consumer_goods" \
  --key "RETAIL_AI_DATABRICKS_CLIENT_ID" \
  --string-value "$LAKEBASE_CLIENT_ID"

databricks secrets put \
  --scope "retail_consumer_goods" \
  --key "RETAIL_AI_DATABRICKS_CLIENT_SECRET" \
  --string-value "$LAKEBASE_CLIENT_SECRET"

# Verify secrets are stored
databricks secrets list --scope "retail_consumer_goods"

替换这些值:

  • retail_consumer_goods -必须与中的作用域名称匹配 databricks.yml
  • LAKEBASE_HOST -您的copula工作区URL(例如。, https://adb-1234567890123456.7.azuredatabricks.net)
  • LAKEBASE_CLIENT_ID -步骤1中的应用ID(UUID格式。, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
  • LAKEBASE_CLIENT_SECRET -步骤1中的客户端密码(请确保其安全,切勿进行版本控制!)

备注:如果使用不同的秘密作用域名称,请更新 databricks.yml 匹配:

# In databricks.yml, update these lines:
scope: retail_consumer_goods  # Change to your scope name

步骤4:安装依赖项

使用安装Python依赖项 uv (推荐)或 pip.

使用紫外线(推荐)

# Navigate to the project directory
cd /path/to/mcp_state_server

# Install dependencies
uv sync

# Verify installation
uv run python -c "import mcp_state_server; print('✓ Installation successful')"

使用pip

# Navigate to the project directory
cd /path/to/mcp_state_server

# Install dependencies
pip install -r requirements.txt

# Verify installation
python -c "import mcp_state_server; print('✓ Installation successful')"

步骤5:配置环境变量

创建一个 .env 项目根目录中的文件包含您的配置。

创建.env文件

# Copy the example (if it exists) or create a new file
cp .env.example .env  # If example exists
# OR
touch .env  # Create new file

编辑.env文件

打开 .env 在文本编辑器中,添加以下内容:

# Databricks Workspace Configuration (for service principal authentication)
LAKEBASE_HOST=https://adb-1234567890123456.7.azuredatabricks.net
LAKEBASE_CLIENT_ID=your-client-id-from-step-1
LAKEBASE_CLIENT_SECRET=your-client-secret-from-step-1

# Lakehouse Postgres Instance
LAKEBASE_INSTANCE_NAME=your-instance-name-from-step-2
DATABRICKS_POSTGRES_INSTANCE_NAME=your-instance-name-from-step-2

# Alternative: Direct PostgreSQL Connection (for local testing)
# PGHOST=localhost
# PGPORT=5432
# PGDATABASE=databricks_postgres
# PGUSER=postgres
# PGPASSWORD=your-password

# Logging
LOG_LEVEL=DEBUG

替换这些值:

  • LAKEBASE_HOST -您在第3步中的copula工作区URL(例如。, https://adb-1234567890123456.7.azuredatabricks.net)
  • LAKEBASE_CLIENT_ID -步骤1中的应用ID(客户端ID)(UUID格式。, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
  • LAKEBASE_CLIENT_SECRET -步骤1中的客户端密码(请确保其安全,切勿进行版本控制!)
  • LAKEBASE_INSTANCE_NAME -步骤2中的实例名称(例如。, mcp-state-server-pg)
  • DATABRICKS_POSTGRES_INSTANCE_NAME -与LAKEBASE_INSTANCE_NAME相同

用于本地测试 (可选):

  • 如果你有一个本地PostgreSQL实例,取消注释并配置 PGHOST, PGPORT等线路
  • 集 use_databricks_auth=False 在测试配置中

步骤6:在本地运行

部署前在本地测试服务器。

启动服务器

# Using uv
uv run python main.py

# OR using the entry point
uv run mcp-state-server

# OR with custom port
uv run mcp-state-server --port 8080

# OR using python directly
python main.py --port 8000

验证服务器是否正在运行

打开一个新终端并测试服务器:

# Check health endpoint
curl http://localhost:8000/

# Expected response:
# {"message":"MCP State Server is running","status":"healthy","description":"MCP server for conversation and preference persistence"}

服务器应启动于 http://localhost:8000 默认情况下。

步骤7:部署为copula应用程序

将MCP服务器部署为copula应用程序,以便工作区中的用户可以访问它。

更新databricks.yml(如果需要)

如果在步骤3中使用了不同的秘密作用域名称,请更新 databricks.yml:

# In databricks.yml, update the scope name:
scope: your-secret-scope-name  # Change from "retail_consumer_goods" if different

使用copula资产包进行部署

# Validate the bundle configuration
databricks bundle validate

# Deploy the app
databricks bundle deploy \
  --var lakebase_instance_name="mcp-state-server-pg"

# Check deployment status
databricks apps list

替换此值:

  • mcp-state-server-pg -步骤2中的实例名称

验证部署

# List deployed apps
databricks apps list

# Get app details
databricks apps get --app-name "mcp-state-server"

# Get app URL
databricks apps get --app-name "mcp-state-server" --output JSON | jq -r '.url'

应用程序URL的格式为: https://mcp-state-server-<workspace-id>.<deployment>.databricksapps.com

步骤8:测试服务器

测试部署的MCP服务器以确保其正常工作。

测试运行状况端点

# Replace <app-url> with your actual app URL from Step 7
APP_URL="https://mcp-state-server-1234567890123456.11.azure.databricksapps.com"

# Test health endpoint
curl "$APP_URL/"

# Expected response:
# {"message":"MCP State Server is running","status":"healthy",...}

测试MCP工具(使用MCP客户端)

如果您配置了MCP客户端:

# Connect to the MCP server
# The server URL is: <app-url>/messages-sse

# Example using MCP CLI (if installed)
mcp connect sse "$APP_URL/messages-sse" \
  --auth "Bearer $DATABRICKS_TOKEN"

# List available tools
mcp list-tools

使用Python进行测试

import httpx
from mcp.client.sse import sse_client
from mcp import ClientSession

# Replace with your app URL
app_url = "https://mcp-state-server-1234567890123456.11.azure.databricksapps.com"
sse_url = f"{app_url}/messages-sse"

# Get Databricks token
import os
token = os.getenv("DATABRICKS_TOKEN")  # Set this in your environment

# Create auth header
auth = httpx.BasicAuth(token, "")

# Connect and test
async with sse_client(sse_url, auth=auth) as (read, write):
    async with ClientSession(read, write) as session:
        await session.initialize()
        
        # List tools
        tools = await session.list_tools()
        print(f"Available tools: {[t.name for t in tools.tools]}")
        
        # Test health tool
        result = await session.call_tool("health", arguments={})
        print(f"Health check: {result.content[0].text}")

故障排除

服务器无法在本地启动

问题: ModuleNotFoundError 或导入错误

解决方案:

# Ensure dependencies are installed
uv sync

# Or with pip
pip install -r requirements.txt

数据库连接失败

问题: psycopg2.OperationalError 或身份验证错误

解决方案:

  1. 验证您的 .env 文件具有正确的值:

    # Check environment variables are set
    cat .env | grep -E "(LAKEBASE|DATABRICKS|PG)"
    
  2. 验证服务主体是否具有访问权限:

    # Test service principal authentication
    databricks service-principals get --service-principal-id "$CLIENT_ID"
    
  3. 验证Lakehouse Postgres实例是否可用:

    databricks database-instances get \
      --instance-name "mcp-state-server-pg" \
      --output JSON | jq '.state'
    # Should be "AVAILABLE"
    

应用程序部署失败

问题: Error: failed to update app 或资源错误

解决方案:

  1. 验证是否存在机密:

    databricks secrets list --scope "retail_consumer_goods"
    
  2. 验证实例名称是否匹配:

    # Check instance exists
    databricks database-instances get \
      --instance-name "mcp-state-server-pg"
    
  3. 检查捆绑包验证:

    databricks bundle validate
    

“角色不存在”错误

问题: FATAL: role "..." does not exist

解决方案:服务主体的应用程序ID正被用作PostgreSQL角色,该角色可能不存在。确保:

  • 服务主体具有适当的权限
  • 该实例允许服务主体连接
  • 考虑使用不同的身份验证方法进行本地测试

未找到秘密作用域

问题: Error: Secret scope 'retail_consumer_goods' not found

解决方案:

  1. 创建秘密作用域(参见步骤3)
  2. 或更新 databricks.yml 使用现有作用域名称

其他资源

支持

对于问题或疑问:

  1. 检查 故障排除 章节
  2. 查看上面的copula文档链接
  3. 检查服务器日志: LOG_LEVEL=DEBUG 在 .env 用于详细记录