MCP资源服务器
使用FastMCP进行blob存储操作的模型上下文协议(MCP)服务器。此服务器提供了一个两阶段架构:摄取(将文件字节存储到blob存储中)和检索(通过blob://URI访问文件)。
概述
MCP资源服务器为blob存储操作提供了7个工具:
- 使用Blob检索Blob://URI(get_image、get_file、get_native_path等)
- 从文件字节上传Blob(upload_image_resource、upload_file_resource)
- 图像大小调整和格式转换
- 资源元数据检索
- 本机文件系统路径访问(适用于Docker环境)
特性
- 两阶段架构:单独的摄取(上传)和检索(获取)操作
- Blob://URI抽象:所有通过blob://URI访问的文件,与文件系统解耦
- 图像处理:使用PIL自动调整大小,保持纵横比
- Blob 存储:用于多服务工作流的共享卷集成
- 文件重复数据删除:基于SHA256的重复数据删除以节省存储空间
- TTL管理:自动清理过期文件
需求
- Python 3.10+
- uv包管理器
- 可选:Docker用于容器化部署
设置
1.安装依赖项
uv sync2.配置环境变量(可选)
服务器使用合理的默认值即可开箱即用。要自定义,请创建 .env 项目根目录中的文件:
# MCP Server Configuration (defaults shown)
# RESOURCE_SERVER_MASK_ERRORS=false
# Blob Storage Configuration (defaults shown)
# BLOB_STORAGE_ROOT=/mnt/blob-storage
# BLOB_MAX_SIZE_MB=100
# BLOB_TTL_HOURS=24备注:所有环境变量都是可选的,并具有合理的默认值。
3.使用Docker构建和运行
# Build the Docker image
docker-compose build
# Run the server
docker-compose up配置
环境变量
| 变量 | 默认值 | 描述 |
|---|---|---|
RESOURCE_SERVER_MASK_ERRORS | false | 向客户端隐藏内部错误详细信息 |
BLOB_STORAGE_ROOT | /mnt/blob-storage | 共享存储目录(容器)的路径 |
HOST_BLOB_STORAGE_ROOT | "" | 主机文件系统路径(适用于Docker环境) |
BLOB_MAX_SIZE_MB | 100 | 最大文件大小(MB) |
BLOB_TTL_HOURS | 24 | blob的默认生存时间 |
可用工具
Blob检索操作(需要Blob://URI)
| 工具 | 说明 |
|---|---|
get_file | 从blob存储中检索原始文件字节 |
get_image | 从blob存储中检索图像并调整其大小 |
get_image_info | 获取blob图像元数据 |
get_image_size_estimate | 估算调整尺寸(干运行) |
get_native_path | 获取blob文件的本机文件系统路径 |
Blob上传操作(存储文件字节)
| 工具 | 说明 |
|---|---|
upload_file_resource | 将原始文件字节存储在blob存储中→ 返回blob://URI |
upload_image_resource | 在blob存储中存储具有可选大小调整的图像字节→ 返回blob://URI |
共享Blob存储
服务器提供基于资源的文件存储方法(upload_image_resource 和 upload_file_resource)它允许通过映射的Docker卷与其他MCP服务器共享文件。
运作原理
- 文件字节存储在共享blob存储目录中
- 每个文件都有一个唯一的资源标识符(格式:
blob://TIMESTAMP-HASH.EXT) - 其他MCP服务器可以直接从映射的卷访问这些文件
- 使用SHA256哈希自动对文件进行重复数据消除
- 文件在可配置的TTL后过期(默认值:24小时)
Docker卷设置
要启用MCP服务器之间的资源共享,请装载共享卷:
# docker-compose.yml
services:
mcp-resource-server:
image: mcp-resource-server:latest
volumes:
# Option 1: Named volume (recommended for most use cases)
- blob-storage:/mnt/blob-storage
# Option 2: Host path mapping (use with HOST_BLOB_STORAGE_ROOT)
# - /workspace/blob-storage:/mnt/blob-storage
environment:
- BLOB_STORAGE_ROOT=/mnt/blob-storage
# Only needed when using host path mapping (Option 2)
# - HOST_BLOB_STORAGE_ROOT=/workspace/blob-storage
other-mcp-server:
image: other-mcp:latest
volumes:
- blob-storage:/mnt/blob-storage
volumes:
blob-storage:用法示例
# Store an image in shared storage
with open("photo.png", "rb") as f:
data = f.read()
response = upload_image_resource(data, "photo.png")
# Returns: ResourceResponse(
# success=True,
# resource_id="blob://1733437200-a3f9d8c2b1e4f6a7.png",
# filename="photo.png",
# mime_type="image/png",
# size_bytes=65536,
# sha256="a3f9d8c2...",
# expires_at="2024-12-08T12:00:00Z"
# )
# Other MCP servers can now access the file at:
# /mnt/blob-storage/17/33/blob://1733437200-a3f9d8c2b1e4f6a7.png使用示例
两阶段工作流程
阶段1:将文件字节上传到blob存储
# Upload image bytes to blob storage
with open("photo.png", "rb") as f:
data = f.read()
response = upload_image_resource(data, "photo.png")
blob_uri = response.resource_id # "blob://1733437200-abc123.png"
# Upload file bytes to blob storage
with open("document.pdf", "rb") as f:
data = f.read()
response = upload_file_resource(data, "document.pdf")
blob_uri = response.resource_id # "blob://1733437200-def456.pdf"阶段2:从blob存储中检索
# Get image with default sizing (max 1024px)
image = get_image("blob://1733437200-abc123.png")
# Get smaller thumbnail
image = get_image("blob://1733437200-abc123.png", max_width=256, max_height=256)
# Get original full-resolution image
image = get_image("blob://1733437200-abc123.png", max_width=0, max_height=0)
# Get image with high quality JPEG
image = get_image("blob://1733437200-abc123.jpg", quality=95)获取图像元数据
info = get_image_info("blob://1733437200-abc123.png")
# ImageInfoResponse(success=True, width=2048, height=1536,
# format='png', file_size_bytes=524288)估计调整尺寸
estimate = get_image_size_estimate("blob://1733437200-abc123.jpg", max_width=512)
# ImageSizeEstimate(success=True, original_width=2048, original_height=1536,
# estimated_width=512, estimated_height=384,
# original_size_bytes=524288, estimated_size_bytes=65536,
# would_resize=True, format='jpeg', quality=85)下载文件
data = get_file("blob://1733437200-def456.pdf")
# Returns raw bytes获取本机文件系统路径
# Useful when running in Docker and need to pass file paths to external tools
path_info = get_native_path("blob://1733437200-abc123.png")
# NativePathResponse(
# success=True,
# native_path="/workspace/blob-storage/a3/f9/1733437200-a3f9d8c2b1e4f6a7.png",
# host_path="/workspace/blob-storage/a3/f9/1733437200-a3f9d8c2b1e4f6a7.png",
# container_path="/mnt/blob-storage/a3/f9/1733437200-a3f9d8c2b1e4f6a7.png",
# blob_id="blob://1733437200-abc123.png"
# )Docker部署
塑造形象
docker compose build运行服务器
docker compose up发展
该项目旨在与VS Code和devcontainers插件配合使用。
设置开发容器
- 在VS Code中打开项目
- 安装“开发容器”扩展
- 按
Ctrl+Shift+P然后选择“开发容器:在容器中重新打开” - 容器将自动构建和安装所有依赖项
运行测试
uv run pytest重要说明
图像处理
- 调整图像大小以适应指定尺寸,同时保持纵横比
- 小图像永远不会放大
- JPEG质量设置仅影响JPEG图像(对于PNG/GIF/WebP忽略)
- RGBA图像在保存为JPEG时转换为RGB
Blob 存储
- 文件采用两级目录分片存储,以提高性能
- 重复数据删除通过重复使用相同的文件来节省存储空间
- 基于TTL的清理会自动删除过期文件
- 资源id在重复项之间是稳定的(相同的SHA256=相同的Resource_id)
Claude桌面集成
要将此MCP服务器与Claude Desktop一起使用:
- 快速开始:参见 docs/QUICK_START.md 获取5分钟的设置指南
- 完整设置指南:参见 docs/CLAUDE_DESKTOP_SETUP.md 有关详细的配置、故障排除和使用示例
