# 广告投放数据平台 MCP 服务
## 项目概述
这是一个基于 Model Context Protocol (MCP) 的广告投放数据服务器,为 LLM 应用提供智能的广告数据查询和分析能力。通过标准化的MCP协议,LLM可以直接调用广告投放相关的数据查询工具,获取业务洞察和决策支持。
## ✨ 核心特性
- **🔧 MCP工具集成**:提供广告查询、素材分析、指标推荐等MCP工具
- **📊 指标工具**:提供获取与验证指标的工具(推荐功能暂未启用)
- **🎯 多维数据查询**:支持按时间、媒体、分组等维度查询数据
- **🔗 标准协议支持**:完全遵循MCP协议,支持Claude Desktop等客户端
- **⚡ 异步高性能**:基于异步架构,支持并发数据查询
## 🚀 快速开始
```bash
# 1. 克隆项目
git clone <repository-url> && cd mcp
# 2. 设置API Token
export BI_API_TOKEN="your_token_here"
# 3. 安装并运行测试
uv sync && uv run python tests/test_server.py
```
### 运行服务器
#### 方式一:标准stdio模式(Claude Desktop集成)
```bash
# 直接运行
python run_server.py
# 或使用uv
uv run python run_server.py
```
#### 方式二:StreamableHTTP模式(HTTP API服务)
```bash
# 使用命令行参数
python run_server.py --transport streamable-http
# 使用uv
uv run python run_server.py --transport streamable-http
```
StreamableHTTP模式支持以下环境变量配置:
- `HTTP_HOST`: 服务器地址(默认:127.0.0.1)
- `HTTP_PORT`: 服务器端口(默认:8000)
- `STREAMABLE_HTTP_PATH`: 服务路径(默认:/mcp)
- `STATELESS_HTTP`: 无状态模式(默认:False)
- `JSON_RESPONSE`: 使用JSON响应而非SSE(默认:False)
> 💡 StreamableHTTP模式将MCP服务器运行为HTTP API,支持通过HTTP请求调用MCP工具,适用于Web应用、API集成等场景。
### Claude Desktop集成
```json
{
"mcpServers": {
"mcp-ad-server": {
"command": "uvx",
"args": ["mcp_ad_server"],
"env": {"BI_API_TOKEN": "your_token"}
}
},
"mcp-ad-server-http": {
"command": "uvx",
"args": [
"mcp-ad-server",
"--transport",
"streamable-http"
],
"env": {
"BI_API_TOKEN": "your_token",
"HTTP_HOST": "127.0.0.1",
"HTTP_PORT": "8000"
}
}
}
```
> **⚠️ 重要提示**:如果遇到 `spawn python ENOENT` 错误,请使用完整的 Python 路径(用 `which python3` 查找)而非 `python` 命令。Claude Desktop 的 PATH 环境变量与终端不同。
## 📁 项目结构
```
mcp/
├── 📄 README.md # 项目说明(本文档)
├── 📄 USER_GUIDE.md # 用户使用手册
├── 📄 DEVELOPMENT.md # 开发者指南
├── 📄 ARCHITECTURE.md # 系统架构设计
├── 🚀 run_server.py # 服务启动脚本
├── 🧪 tests/ # 自动化单元测试
│ ├── test_config.py # 配置测试
│ ├── test_dotenv.py # 环境变量测试
│ ├── test_api_models.py # API模型验证测试
│ ├── test_manager_base.py # Manager基类测试
│ └── test_response_models.py # 响应模型测试
├── 🔧 scripts/ # 开发调试工具
│ ├── debug_api_server.py # API调试服务器
│ └── compare_api_responses.py # API响应对比工具
├── ✅ manual_tests/ # 手动验证脚本
│ ├── verify_http_server.py # HTTP服务器验证
│ ├── verify_ad_query.py # 广告查询验证
│ ├── verify_mcp_server.py # MCP服务器验证
│ ├── verify_mcp_components.py # MCP组件验证
│ └── verify_api_client.py # API客户端验证
│
├── 💻 src/mcp_ad_server/ # 主要源码
│ ├── main.py # 服务器主入口
│ ├── config.py # 配置管理
│ ├── services/ # 业务服务层
│ │ └── api_client.py # BI API客户端
│ ├── managers/ # 数据管理层
│ │ ├── base.py # Manager基础类
│ │ ├── indicator_manager.py # 指标管理器
│ │ └── propmap_manager.py # 字段映射管理器
│ ├── tools/ # MCP工具实现
│ │ ├── ad_query.py # 广告查询工具
│ │ ├── material_query.py # 素材查询工具
│ │ └── indicator_query.py # 游戏指标查询工具
│ ├── resources/ # MCP资源实现
│ │ ├── indicator_resources.py # 指标资源
│ │ ├── mapping_resources.py # 映射资源
│ │ └── config_resources.py # 配置资源
│ └── prompts/ # MCP提示实现(计划中)
│
├── 📊 src/mcp_ad_server/data/ # 内置数据文件(运行时默认读取)
│ ├── indicators/ # 89个指标定义文件
│ ├── groups/ # 7个指标分组文件
│ └── propmap/ # API字段映射文件
│
└── 📚 docs/ # 原始API文档
└── api/ # API接口文档
├── GetAdCountList/ # 广告数据统计接口
└── GetMaterialCountList/ # 素材数据统计接口
```
## 🛠️ MCP 工具功能
### 1. query_ad_data - 广告数据查询
查询广告投放效果数据,支持多维度筛选和分组统计。
**参数**:
- `start_date/end_date`: 查询时间范围 (YYYY-MM-DD)
- `indicators`: 查询指标列表(中文名称)
- `media`: 媒体渠道筛选(支持中文名称:广点通、今日头条、百度等)
- `group_key`: 分组维度(广告ID、项目ID等)
- `hours_24`: 24小时维度查询,支持单天和多天并发查询
**返回结构**:
- `data.columns`: 列名列表(已做中文映射)
- `data.rows`: 二维数组格式的数据行,对应columns顺序
- `data.total`: 当前返回的数据条数
- `data.summary`: 汇总数据(如果存在)
### 2. query_material_data - 素材数据查询
查询广告素材效果和质量数据,支持素材质量筛选。
**参数**:
- `start_date/end_date`: 查询时间范围
- `indicators`: 查询指标列表
- `creative_users`: 创意人筛选
- `producers`: 制作人筛选
- `is_low_quality`: AD优/低质素材筛选
- `is_inefficient`: 低效素材筛选
**返回结构**:同广告数据查询
### 3. 游戏指标工具 - 指标验证与查询
基于游戏兼容性的指标验证和查询工具。
**可用工具**:
- `get_available_indicators` - 获取指定游戏的可用指标
- `validate_indicators` - 验证指标在指定游戏中是否可用
<!-- 场景推荐功能暂时注释,等待业务场景映射完善
- `recommend_indicators` - 基于场景智能推荐指标(开发中)
-->
## ✨ 系统特性
### 🔧 数据处理特性
- **自动总计项处理**: 智能识别和分离后端返回的总计数据
- **LLM优化数据结构**: 提供中文映射的数据格式,便于LLM理解和分析
- **参数别名兼容**: 支持历史参数名向下兼容(如 `appid` ↔ `app_id`)
- **Pydantic类型安全**: 完整的参数验证和数据类型转换
### 📊 数据返回格式
```json
{
"success": true,
"data": {
"columns": ["日期", "消耗", "新增注册", "新增付费"],
"rows": [
["2024-01-01", 100.5, 50, 5],
["2024-01-02", 120.0, 60, 8],
["2024-01-03", 80.0, 40, 3]
],
"total": 3, // 当前返回的数据条数
"summary": {...} // 汇总数据(如果后端提供)
},
"metadata": {...} // 查询元数据
}
```
### 🔄 版本管理
- **API客户端版本**: v0.0.13
- **BI API版本**: v0.2.07
- **语义化版本控制**: 主版本兼容性保证
## 📋 MCP 资源访问
### 指标相关资源
- `mcp://indicators/{指标名称}` - 获取单个指标详细定义
- `mcp://groups/{组ID}` - 获取指标组信息
- `mcp://config/groups` - 获取所有指标组概览
### 配置相关资源
- `mcp://propmap/{API名称}` - 获取API字段映射关系
- `mcp://config/media` - 获取支持的媒体渠道
- `mcp://config/group_keys` - 获取支持的分组维度
## 📊 指标体系架构
### 目前的业务场景指标组
| 指标组 | 核心用途 | 主要指标示例 |
|--------|----------|-------------|
| **投放启动决策** | 判断是否开始投放新广告 | 激活率、注册成本、创角成本、3秒播放率 |
| **投放效果监控** | 监控投放中广告实时效果 | 消耗、点击率、新增注册、新增付费 |
| **短期价值评估** | 评估首日到7日用户价值 | 首日ROI、7日ROI、新增付费率、新增ARPPU |
| **深度价值分析** | 评估用户长期价值 | 累计ROI、留存率、生命周期价值 |
| **平台数据对账** | 核对各平台上报数据 | 平台充值、平台付费人数、数据差异 |
| **终止决策预警** | 判断是否需要停止投放 | 成本预警、ROI预警、质量预警 |
| **财务核算结算** | 财务结算相关 | 分成后ROI、实际消耗、结算金额 |
## 🔌 客户端集成示例
### Claude Desktop 使用
配置完成后,可直接在Claude Desktop中进行对话查询:
```
请帮我分析一下2025年1月1-7日腾讯广点通渠道的广告投放效果,
重点关注ROI表现和用户转化情况。
```
### 程序化调用
```python
# 使用MCP Python SDK
from mcp import ClientSession
async with ClientSession("stdio", ["python", "run_server.py"]) as session:
# 查询广告数据
result = await session.call_tool("query_ad_data", {
"start_date": "2025-01-01",
"end_date": "2025-01-07",
"indicators": ["消耗", "新增注册", "首日ROI"],
"app": "正统三国",
"media": ["广点通", "今日头条"]
})
# 获取游戏可用指标
available_indicators = await session.call_tool("get_available_indicators", {
"app": "正统三国",
"query_type": "ad_query"
})
# 验证指标兼容性
validation = await session.call_tool("validate_indicators", {
"indicators": ["消耗", "展现", "点击"],
"app": "正统三国"
})
```
## 🌐 支持的媒体渠道
**MCP工具直接使用中文名称,系统会自动转换为对应的API代码:**
| 中文名称 | API代码 | 中文名称 | API代码 |
|---------|---------|---------|---------|
| 广点通 | `gdt` | 今日头条 | `tt` |
| 百度 | `bd` | 百度搜索 | `bdss` |
| B站 | `bz` | 知乎 | `zh` |
| UC | `uc` | 抖小广告量 | `dx` |
| 视频号达人 | `sphdr` | 星图 | `xt` |
| 谷歌 | `gg` | 自然量 | `nature` |
## 📚 文档指南
本项目提供完整的文档体系,请根据您的角色选择合适的文档:
| 角色 | 推荐文档 | 用途 |
|------|----------|------|
| **最终用户/运营** | [USER_GUIDE.md](USER_GUIDE.md) | 安装使用、功能操作、业务应用 |
| **开发者/贡献者** | [DEVELOPMENT.md](DEVELOPMENT.md) | 开发环境、编码规范、扩展开发 |
| **架构师/技术负责人** | [ARCHITECTURE.md](ARCHITECTURE.md) | 系统设计、组件架构、技术决策 |
### 🚀 阅读建议
1. **想要快速使用服务**:直接阅读 [USER_GUIDE.md](USER_GUIDE.md) 的"快速开始"部分
2. **想要贡献代码**:先阅读 [ARCHITECTURE.md](ARCHITECTURE.md) 了解设计,再看 [DEVELOPMENT.md](DEVELOPMENT.md) 学习开发规范
3. **想要了解技术架构**:重点阅读 [ARCHITECTURE.md](ARCHITECTURE.md)
## 🔧 技术特点
- **现代Python架构**:基于Python 3.11+
- **模块化设计**:清晰的层次分离,Manager模式管理数据
- **标准协议支持**:遵循MCP协议规范
- **高性能异步**:使用Python 3.11+ TaskGroup实现多天24小时数据并发查询,查询性能提升10-20倍
- **模块化扩展**:清晰的组件注册机制,便于添加新工具和资源
- **完整测试覆盖**:包含单元测试和集成测试
## 📈 更新日志
- v0.0.13 (2025-08-20)
- **广告指标依赖自动注入**
- `indicator_manager` 支持从 `data/indicators/dependencies/` 加载规则
- 避免“付费分成后首日ROI”等空值问题
- **配置化默认指标**
- 素材查询默认补充“素材id”“活跃用户”,广告查询默认补充“日期”改为可配置
- **文档完善**:
- 完善 GetAdCountList 派生与平台ROI支持说明
- 完善 GetMaterialCountList 的业务逻辑表述
- v0.0.12 (2025-08-19)
- **MCP工具参数描述优化**:
- 使用`Annotated`和`Field`为所有MCP工具参数添加描述,使参数在list_tools时正确显示
- 优化docstring结构,去除冗余部分
- **硬编码清理**:
- 更新测试脚本使用uv run本地运行方式,去除硬编码路径
- v0.0.11 (2025-08-19)
- **素材查询分类架构优化**:重构素材查询工具,自动分类返回
- 暂定四种素材分类模式:historical(历史素材)、active(活跃素材)、no_conversion(暂无转化)、users_only(仅用户素材)
- **测试体系重组**:
- 重新组织测试目录结构:`tests/`(单元测试)、`scripts/`(调试工具)、`manual_tests/`(手动验证脚本)
- **简化API文档叙述**
- v0.0.10 (2025-08-18)
- **StreamableHTTP传输模式支持**:新增HTTP API服务器模式,支持 `--transport` 命令行参数选择传输协议(stdio/streamable-http),支持通过HTTP请求调用MCP工具
- **环境变量配置**:完善HTTP模式的配置选项(host、port、path等)
- v0.0.9 (2025-08-15)
- **MCP工具参数类型优化**:支持字符串和列表参数混合使用
- 修复工具签名中 `media` 等参数从 `list[str]` 改为 `str | list[str]`,暂时解决模型调用工具时不 Follow 类型约束的行为
- v0.0.8 (2025-08-15)
- **日期字段自动添加**:指标查询时自动添加「日期」字段,无需手动指定
- 改进用户体验,避免因缺少日期字段而产生的错误提示,简化LLM调用工具流程
- **API模型参数处理优化**:增强GetAdCountListRequest和GetMaterialCountListRequest的参数处理能力
- 新增 `@field_validator(mode="before")` 预处理验证器
- 支持空/单字符串参数自动转换为列表,提升API使用体验
- **API文档完善**:素材查询接口的文档更新(`docs/api/GetMaterialCountList/`)
- v0.0.7 (2025-08-15)
- **文档参数更新**:统一所有文档中的参数格式,采用中文参数示例
- **GroupKey指标验证优化**:修复分组字段本身的指标验证问题
- 当使用 `group_key` 分组时,对应的分组字段(如"广告ID"、"项目ID")现在被正确识别为有效指标
- 增强 `validate_indicators` 方法,支持 `group_key` 参数进行更精确的指标验证
- **API文档完善**:新增素材查询接口的今日头条响应示例文件
- v0.0.6 (2025-08-14)
- **参数中文化改造**:MCP工具接口全面支持中文参数,提升LLM使用体验
- 游戏参数从数字ID改为中文名称(如 `app_id="59"` → `app="正统三国"`)
- 支持中文媒体渠道、投手姓名、广告状态等参数值
- 新增游戏支持:我的仙门、一起斗消乐、大头系列游戏等
- **多天24小时查询优化**:改进summary数据准确性
- 废弃手动合并summary逻辑(存在百分比/比率指标计算不准确问题)
- 通过额外API请求(`hours_24=False`)获取后端计算的准确汇总数据
- 添加注释记录未来可返回`daily_summaries`列表的改进思路
- v0.0.5 (2025-08-14)
- 指标验证系统重构和 PropMap 架构优化
- 指标体系从全局改为游戏类型分组(棋牌/非棋牌)
- PropMap 文件反向重构,管理器重写,提升可维护性
- API 客户端验证逻辑优化:支持动态条件性指标注入,基于 `group_key` 智能添加指标,与前端表现一致
- v0.0.4 (2025-08-13)
- 数据处理层重构与版本管理优化;素材数据完善;上传后端接口参考代码;基于代码更新 `docs/`
- 对指标错误提供更规范的错误提示
- 查询结果改为按日期倒序返回,且只输出筛选后的指标
- 使用 `group_key` 分组时,会在返回中追加并映射对应的 `group_key`
- v0.0.3 (2025-08-12)
- 清理推荐逻辑冗余代码,统一文件和函数命名规范
- 迁移数据目录到 `src/mcp_ad_server/data` 以支持打包分发
- 实现客户端层数据排序(普通数据按日期倒序,24 小时数据按小时正序)
- 使用 Python 3.11+ `asyncio.TaskGroup` 优化多天 24 小时查询并发处理,暂时增加间隔避免瞬间打满后端,后续或可优化。
- 通过 `uvx mcp_ad_server` 可在任意机器快速接入 MCP
- v0.0.2 (2025-08-11)
- 完善 API 客户端功能:参数别名兼容、自动总计项处理、Pydantic 数据验证
- v0.0.1 (2025-08-07)
- 重构文档体系,实现完整 MCP 服务架构
- 初始化项目结构,整理指标体系
- 添加 API 响应示例文件(原始提交于 2025-08-05)
## 🤝 技术支持
如有问题或建议,请联系:
- **技术问题**:钉钉 AI 开发团队
- **业务咨询**:广告投放团队
- **功能建议**:通过内部反馈渠道提交
## 📋 TODO (低优先级)
- **指标配置优化**:当前card_games/non_card_games结构中可能存在指标重复,可考虑抽取为分层指标集(base + extensions)以简化配置和维护
---
> **注意**:本项目中的指标分组和推荐算法为测试版本,实际使用时需要与投放团队对接校准业务逻辑。
Raw data
{
"_id": null,
"home_page": null,
"name": "mcp-ad-server",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.11",
"maintainer_email": "\u6c5f\u539a\u671b <jianghouwang@dartou.com>",
"keywords": "mcp, advertising, analytics, data-analysis",
"author": null,
"author_email": "\u6c5f\u539a\u671b <jianghouwang@dartou.com>, \u9093\u5609\u8c6a <dengjiahao@dartou.com>, \u5218\u677e\u5947 <liusongqi@dartou.com>",
"download_url": "https://files.pythonhosted.org/packages/29/2d/263b905ee4ee8e5e6a4c96a2f124df0cc41b89fdc1c19e4bd0bd978158ac/mcp_ad_server-0.0.13.tar.gz",
"platform": null,
"description": "# \u5e7f\u544a\u6295\u653e\u6570\u636e\u5e73\u53f0 MCP \u670d\u52a1\n\n## \u9879\u76ee\u6982\u8ff0\n\n\u8fd9\u662f\u4e00\u4e2a\u57fa\u4e8e Model Context Protocol (MCP) \u7684\u5e7f\u544a\u6295\u653e\u6570\u636e\u670d\u52a1\u5668\uff0c\u4e3a LLM \u5e94\u7528\u63d0\u4f9b\u667a\u80fd\u7684\u5e7f\u544a\u6570\u636e\u67e5\u8be2\u548c\u5206\u6790\u80fd\u529b\u3002\u901a\u8fc7\u6807\u51c6\u5316\u7684MCP\u534f\u8bae\uff0cLLM\u53ef\u4ee5\u76f4\u63a5\u8c03\u7528\u5e7f\u544a\u6295\u653e\u76f8\u5173\u7684\u6570\u636e\u67e5\u8be2\u5de5\u5177\uff0c\u83b7\u53d6\u4e1a\u52a1\u6d1e\u5bdf\u548c\u51b3\u7b56\u652f\u6301\u3002\n\n## \u2728 \u6838\u5fc3\u7279\u6027\n\n- **\ud83d\udd27 MCP\u5de5\u5177\u96c6\u6210**\uff1a\u63d0\u4f9b\u5e7f\u544a\u67e5\u8be2\u3001\u7d20\u6750\u5206\u6790\u3001\u6307\u6807\u63a8\u8350\u7b49MCP\u5de5\u5177\n- **\ud83d\udcca \u6307\u6807\u5de5\u5177**\uff1a\u63d0\u4f9b\u83b7\u53d6\u4e0e\u9a8c\u8bc1\u6307\u6807\u7684\u5de5\u5177\uff08\u63a8\u8350\u529f\u80fd\u6682\u672a\u542f\u7528\uff09\n- **\ud83c\udfaf \u591a\u7ef4\u6570\u636e\u67e5\u8be2**\uff1a\u652f\u6301\u6309\u65f6\u95f4\u3001\u5a92\u4f53\u3001\u5206\u7ec4\u7b49\u7ef4\u5ea6\u67e5\u8be2\u6570\u636e\n- **\ud83d\udd17 \u6807\u51c6\u534f\u8bae\u652f\u6301**\uff1a\u5b8c\u5168\u9075\u5faaMCP\u534f\u8bae\uff0c\u652f\u6301Claude Desktop\u7b49\u5ba2\u6237\u7aef\n- **\u26a1 \u5f02\u6b65\u9ad8\u6027\u80fd**\uff1a\u57fa\u4e8e\u5f02\u6b65\u67b6\u6784\uff0c\u652f\u6301\u5e76\u53d1\u6570\u636e\u67e5\u8be2\n\n## \ud83d\ude80 \u5feb\u901f\u5f00\u59cb\n\n```bash\n# 1. \u514b\u9686\u9879\u76ee\ngit clone <repository-url> && cd mcp\n\n# 2. \u8bbe\u7f6eAPI Token\nexport BI_API_TOKEN=\"your_token_here\"\n\n# 3. \u5b89\u88c5\u5e76\u8fd0\u884c\u6d4b\u8bd5\nuv sync && uv run python tests/test_server.py\n```\n\n### \u8fd0\u884c\u670d\u52a1\u5668\n\n#### \u65b9\u5f0f\u4e00\uff1a\u6807\u51c6stdio\u6a21\u5f0f\uff08Claude Desktop\u96c6\u6210\uff09\n```bash\n# \u76f4\u63a5\u8fd0\u884c\npython run_server.py\n\n# \u6216\u4f7f\u7528uv\nuv run python run_server.py\n```\n\n#### \u65b9\u5f0f\u4e8c\uff1aStreamableHTTP\u6a21\u5f0f\uff08HTTP API\u670d\u52a1\uff09\n```bash\n# \u4f7f\u7528\u547d\u4ee4\u884c\u53c2\u6570\npython run_server.py --transport streamable-http\n\n# \u4f7f\u7528uv\nuv run python run_server.py --transport streamable-http\n```\n\nStreamableHTTP\u6a21\u5f0f\u652f\u6301\u4ee5\u4e0b\u73af\u5883\u53d8\u91cf\u914d\u7f6e\uff1a\n- `HTTP_HOST`: \u670d\u52a1\u5668\u5730\u5740\uff08\u9ed8\u8ba4\uff1a127.0.0.1\uff09\n- `HTTP_PORT`: \u670d\u52a1\u5668\u7aef\u53e3\uff08\u9ed8\u8ba4\uff1a8000\uff09\n- `STREAMABLE_HTTP_PATH`: \u670d\u52a1\u8def\u5f84\uff08\u9ed8\u8ba4\uff1a/mcp\uff09\n- `STATELESS_HTTP`: \u65e0\u72b6\u6001\u6a21\u5f0f\uff08\u9ed8\u8ba4\uff1aFalse\uff09\n- `JSON_RESPONSE`: \u4f7f\u7528JSON\u54cd\u5e94\u800c\u975eSSE\uff08\u9ed8\u8ba4\uff1aFalse\uff09\n\n> \ud83d\udca1 StreamableHTTP\u6a21\u5f0f\u5c06MCP\u670d\u52a1\u5668\u8fd0\u884c\u4e3aHTTP API\uff0c\u652f\u6301\u901a\u8fc7HTTP\u8bf7\u6c42\u8c03\u7528MCP\u5de5\u5177\uff0c\u9002\u7528\u4e8eWeb\u5e94\u7528\u3001API\u96c6\u6210\u7b49\u573a\u666f\u3002\n\n### Claude Desktop\u96c6\u6210\n```json\n{\n \"mcpServers\": {\n \"mcp-ad-server\": {\n \"command\": \"uvx\",\n \"args\": [\"mcp_ad_server\"],\n \"env\": {\"BI_API_TOKEN\": \"your_token\"}\n }\n },\n \"mcp-ad-server-http\": {\n \"command\": \"uvx\",\n \"args\": [\n \"mcp-ad-server\",\n \"--transport\",\n \"streamable-http\"\n ],\n \"env\": {\n \"BI_API_TOKEN\": \"your_token\",\n \"HTTP_HOST\": \"127.0.0.1\",\n \"HTTP_PORT\": \"8000\"\n }\n }\n}\n```\n\n> **\u26a0\ufe0f \u91cd\u8981\u63d0\u793a**\uff1a\u5982\u679c\u9047\u5230 `spawn python ENOENT` \u9519\u8bef\uff0c\u8bf7\u4f7f\u7528\u5b8c\u6574\u7684 Python \u8def\u5f84\uff08\u7528 `which python3` \u67e5\u627e\uff09\u800c\u975e `python` \u547d\u4ee4\u3002Claude Desktop \u7684 PATH \u73af\u5883\u53d8\u91cf\u4e0e\u7ec8\u7aef\u4e0d\u540c\u3002\n\n\n## \ud83d\udcc1 \u9879\u76ee\u7ed3\u6784\n\n```\nmcp/\n\u251c\u2500\u2500 \ud83d\udcc4 README.md # \u9879\u76ee\u8bf4\u660e\uff08\u672c\u6587\u6863\uff09\n\u251c\u2500\u2500 \ud83d\udcc4 USER_GUIDE.md # \u7528\u6237\u4f7f\u7528\u624b\u518c\n\u251c\u2500\u2500 \ud83d\udcc4 DEVELOPMENT.md # \u5f00\u53d1\u8005\u6307\u5357\n\u251c\u2500\u2500 \ud83d\udcc4 ARCHITECTURE.md # \u7cfb\u7edf\u67b6\u6784\u8bbe\u8ba1\n\u251c\u2500\u2500 \ud83d\ude80 run_server.py # \u670d\u52a1\u542f\u52a8\u811a\u672c\n\u251c\u2500\u2500 \ud83e\uddea tests/ # \u81ea\u52a8\u5316\u5355\u5143\u6d4b\u8bd5\n\u2502 \u251c\u2500\u2500 test_config.py # \u914d\u7f6e\u6d4b\u8bd5\n\u2502 \u251c\u2500\u2500 test_dotenv.py # \u73af\u5883\u53d8\u91cf\u6d4b\u8bd5\n\u2502 \u251c\u2500\u2500 test_api_models.py # API\u6a21\u578b\u9a8c\u8bc1\u6d4b\u8bd5\n\u2502 \u251c\u2500\u2500 test_manager_base.py # Manager\u57fa\u7c7b\u6d4b\u8bd5\n\u2502 \u2514\u2500\u2500 test_response_models.py # \u54cd\u5e94\u6a21\u578b\u6d4b\u8bd5\n\u251c\u2500\u2500 \ud83d\udd27 scripts/ # \u5f00\u53d1\u8c03\u8bd5\u5de5\u5177\n\u2502 \u251c\u2500\u2500 debug_api_server.py # API\u8c03\u8bd5\u670d\u52a1\u5668\n\u2502 \u2514\u2500\u2500 compare_api_responses.py # API\u54cd\u5e94\u5bf9\u6bd4\u5de5\u5177\n\u251c\u2500\u2500 \u2705 manual_tests/ # \u624b\u52a8\u9a8c\u8bc1\u811a\u672c\n\u2502 \u251c\u2500\u2500 verify_http_server.py # HTTP\u670d\u52a1\u5668\u9a8c\u8bc1\n\u2502 \u251c\u2500\u2500 verify_ad_query.py # \u5e7f\u544a\u67e5\u8be2\u9a8c\u8bc1\n\u2502 \u251c\u2500\u2500 verify_mcp_server.py # MCP\u670d\u52a1\u5668\u9a8c\u8bc1\n\u2502 \u251c\u2500\u2500 verify_mcp_components.py # MCP\u7ec4\u4ef6\u9a8c\u8bc1\n\u2502 \u2514\u2500\u2500 verify_api_client.py # API\u5ba2\u6237\u7aef\u9a8c\u8bc1\n\u2502\n\u251c\u2500\u2500 \ud83d\udcbb src/mcp_ad_server/ # \u4e3b\u8981\u6e90\u7801\n\u2502 \u251c\u2500\u2500 main.py # \u670d\u52a1\u5668\u4e3b\u5165\u53e3\n\u2502 \u251c\u2500\u2500 config.py # \u914d\u7f6e\u7ba1\u7406\n\u2502 \u251c\u2500\u2500 services/ # \u4e1a\u52a1\u670d\u52a1\u5c42\n\u2502 \u2502 \u2514\u2500\u2500 api_client.py # BI API\u5ba2\u6237\u7aef\n\u2502 \u251c\u2500\u2500 managers/ # \u6570\u636e\u7ba1\u7406\u5c42\n\u2502 \u2502 \u251c\u2500\u2500 base.py # Manager\u57fa\u7840\u7c7b\n\u2502 \u2502 \u251c\u2500\u2500 indicator_manager.py # \u6307\u6807\u7ba1\u7406\u5668\n\u2502 \u2502 \u2514\u2500\u2500 propmap_manager.py # \u5b57\u6bb5\u6620\u5c04\u7ba1\u7406\u5668\n\u2502 \u251c\u2500\u2500 tools/ # MCP\u5de5\u5177\u5b9e\u73b0\n\u2502 \u2502 \u251c\u2500\u2500 ad_query.py # \u5e7f\u544a\u67e5\u8be2\u5de5\u5177\n\u2502 \u2502 \u251c\u2500\u2500 material_query.py # \u7d20\u6750\u67e5\u8be2\u5de5\u5177\n\u2502 \u2502 \u2514\u2500\u2500 indicator_query.py # \u6e38\u620f\u6307\u6807\u67e5\u8be2\u5de5\u5177\n\u2502 \u251c\u2500\u2500 resources/ # MCP\u8d44\u6e90\u5b9e\u73b0\n\u2502 \u2502 \u251c\u2500\u2500 indicator_resources.py # \u6307\u6807\u8d44\u6e90\n\u2502 \u2502 \u251c\u2500\u2500 mapping_resources.py # \u6620\u5c04\u8d44\u6e90\n\u2502 \u2502 \u2514\u2500\u2500 config_resources.py # \u914d\u7f6e\u8d44\u6e90\n\u2502 \u2514\u2500\u2500 prompts/ # MCP\u63d0\u793a\u5b9e\u73b0\uff08\u8ba1\u5212\u4e2d\uff09\n\u2502\n\u251c\u2500\u2500 \ud83d\udcca src/mcp_ad_server/data/ # \u5185\u7f6e\u6570\u636e\u6587\u4ef6\uff08\u8fd0\u884c\u65f6\u9ed8\u8ba4\u8bfb\u53d6\uff09\n\u2502 \u251c\u2500\u2500 indicators/ # 89\u4e2a\u6307\u6807\u5b9a\u4e49\u6587\u4ef6\n\u2502 \u251c\u2500\u2500 groups/ # 7\u4e2a\u6307\u6807\u5206\u7ec4\u6587\u4ef6\n\u2502 \u2514\u2500\u2500 propmap/ # API\u5b57\u6bb5\u6620\u5c04\u6587\u4ef6\n\u2502\n\u2514\u2500\u2500 \ud83d\udcda docs/ # \u539f\u59cbAPI\u6587\u6863\n \u2514\u2500\u2500 api/ # API\u63a5\u53e3\u6587\u6863\n \u251c\u2500\u2500 GetAdCountList/ # \u5e7f\u544a\u6570\u636e\u7edf\u8ba1\u63a5\u53e3\n \u2514\u2500\u2500 GetMaterialCountList/ # \u7d20\u6750\u6570\u636e\u7edf\u8ba1\u63a5\u53e3\n\n```\n\n## \ud83d\udee0\ufe0f MCP \u5de5\u5177\u529f\u80fd\n\n### 1. query_ad_data - \u5e7f\u544a\u6570\u636e\u67e5\u8be2\n\u67e5\u8be2\u5e7f\u544a\u6295\u653e\u6548\u679c\u6570\u636e\uff0c\u652f\u6301\u591a\u7ef4\u5ea6\u7b5b\u9009\u548c\u5206\u7ec4\u7edf\u8ba1\u3002\n\n**\u53c2\u6570**\uff1a\n- `start_date/end_date`: \u67e5\u8be2\u65f6\u95f4\u8303\u56f4 (YYYY-MM-DD)\n- `indicators`: \u67e5\u8be2\u6307\u6807\u5217\u8868\uff08\u4e2d\u6587\u540d\u79f0\uff09\n- `media`: \u5a92\u4f53\u6e20\u9053\u7b5b\u9009\uff08\u652f\u6301\u4e2d\u6587\u540d\u79f0\uff1a\u5e7f\u70b9\u901a\u3001\u4eca\u65e5\u5934\u6761\u3001\u767e\u5ea6\u7b49\uff09\n- `group_key`: \u5206\u7ec4\u7ef4\u5ea6\uff08\u5e7f\u544aID\u3001\u9879\u76eeID\u7b49\uff09\n- `hours_24`: 24\u5c0f\u65f6\u7ef4\u5ea6\u67e5\u8be2\uff0c\u652f\u6301\u5355\u5929\u548c\u591a\u5929\u5e76\u53d1\u67e5\u8be2\n\n**\u8fd4\u56de\u7ed3\u6784**\uff1a\n- `data.columns`: \u5217\u540d\u5217\u8868\uff08\u5df2\u505a\u4e2d\u6587\u6620\u5c04\uff09\n- `data.rows`: \u4e8c\u7ef4\u6570\u7ec4\u683c\u5f0f\u7684\u6570\u636e\u884c\uff0c\u5bf9\u5e94columns\u987a\u5e8f\n- `data.total`: \u5f53\u524d\u8fd4\u56de\u7684\u6570\u636e\u6761\u6570\n- `data.summary`: \u6c47\u603b\u6570\u636e\uff08\u5982\u679c\u5b58\u5728\uff09\n\n### 2. query_material_data - \u7d20\u6750\u6570\u636e\u67e5\u8be2\n\u67e5\u8be2\u5e7f\u544a\u7d20\u6750\u6548\u679c\u548c\u8d28\u91cf\u6570\u636e\uff0c\u652f\u6301\u7d20\u6750\u8d28\u91cf\u7b5b\u9009\u3002\n\n**\u53c2\u6570**\uff1a\n- `start_date/end_date`: \u67e5\u8be2\u65f6\u95f4\u8303\u56f4\n- `indicators`: \u67e5\u8be2\u6307\u6807\u5217\u8868\n- `creative_users`: \u521b\u610f\u4eba\u7b5b\u9009\n- `producers`: \u5236\u4f5c\u4eba\u7b5b\u9009\n- `is_low_quality`: AD\u4f18/\u4f4e\u8d28\u7d20\u6750\u7b5b\u9009\n- `is_inefficient`: \u4f4e\u6548\u7d20\u6750\u7b5b\u9009\n\n**\u8fd4\u56de\u7ed3\u6784**\uff1a\u540c\u5e7f\u544a\u6570\u636e\u67e5\u8be2\n\n### 3. \u6e38\u620f\u6307\u6807\u5de5\u5177 - \u6307\u6807\u9a8c\u8bc1\u4e0e\u67e5\u8be2\n\u57fa\u4e8e\u6e38\u620f\u517c\u5bb9\u6027\u7684\u6307\u6807\u9a8c\u8bc1\u548c\u67e5\u8be2\u5de5\u5177\u3002\n\n**\u53ef\u7528\u5de5\u5177**\uff1a\n- `get_available_indicators` - \u83b7\u53d6\u6307\u5b9a\u6e38\u620f\u7684\u53ef\u7528\u6307\u6807\n- `validate_indicators` - \u9a8c\u8bc1\u6307\u6807\u5728\u6307\u5b9a\u6e38\u620f\u4e2d\u662f\u5426\u53ef\u7528\n\n<!-- \u573a\u666f\u63a8\u8350\u529f\u80fd\u6682\u65f6\u6ce8\u91ca\uff0c\u7b49\u5f85\u4e1a\u52a1\u573a\u666f\u6620\u5c04\u5b8c\u5584\n- `recommend_indicators` - \u57fa\u4e8e\u573a\u666f\u667a\u80fd\u63a8\u8350\u6307\u6807\uff08\u5f00\u53d1\u4e2d\uff09\n-->\n\n## \u2728 \u7cfb\u7edf\u7279\u6027\n\n### \ud83d\udd27 \u6570\u636e\u5904\u7406\u7279\u6027\n- **\u81ea\u52a8\u603b\u8ba1\u9879\u5904\u7406**: \u667a\u80fd\u8bc6\u522b\u548c\u5206\u79bb\u540e\u7aef\u8fd4\u56de\u7684\u603b\u8ba1\u6570\u636e\n- **LLM\u4f18\u5316\u6570\u636e\u7ed3\u6784**: \u63d0\u4f9b\u4e2d\u6587\u6620\u5c04\u7684\u6570\u636e\u683c\u5f0f\uff0c\u4fbf\u4e8eLLM\u7406\u89e3\u548c\u5206\u6790\n- **\u53c2\u6570\u522b\u540d\u517c\u5bb9**: \u652f\u6301\u5386\u53f2\u53c2\u6570\u540d\u5411\u4e0b\u517c\u5bb9\uff08\u5982 `appid` \u2194 `app_id`\uff09\n- **Pydantic\u7c7b\u578b\u5b89\u5168**: \u5b8c\u6574\u7684\u53c2\u6570\u9a8c\u8bc1\u548c\u6570\u636e\u7c7b\u578b\u8f6c\u6362\n\n### \ud83d\udcca \u6570\u636e\u8fd4\u56de\u683c\u5f0f\n```json\n{\n \"success\": true,\n \"data\": {\n \"columns\": [\"\u65e5\u671f\", \"\u6d88\u8017\", \"\u65b0\u589e\u6ce8\u518c\", \"\u65b0\u589e\u4ed8\u8d39\"],\n \"rows\": [\n [\"2024-01-01\", 100.5, 50, 5],\n [\"2024-01-02\", 120.0, 60, 8],\n [\"2024-01-03\", 80.0, 40, 3]\n ],\n \"total\": 3, // \u5f53\u524d\u8fd4\u56de\u7684\u6570\u636e\u6761\u6570\n \"summary\": {...} // \u6c47\u603b\u6570\u636e\uff08\u5982\u679c\u540e\u7aef\u63d0\u4f9b\uff09\n },\n \"metadata\": {...} // \u67e5\u8be2\u5143\u6570\u636e\n}\n```\n\n### \ud83d\udd04 \u7248\u672c\u7ba1\u7406\n- **API\u5ba2\u6237\u7aef\u7248\u672c**: v0.0.13\n- **BI API\u7248\u672c**: v0.2.07\n- **\u8bed\u4e49\u5316\u7248\u672c\u63a7\u5236**: \u4e3b\u7248\u672c\u517c\u5bb9\u6027\u4fdd\u8bc1\n\n## \ud83d\udccb MCP \u8d44\u6e90\u8bbf\u95ee\n\n### \u6307\u6807\u76f8\u5173\u8d44\u6e90\n- `mcp://indicators/{\u6307\u6807\u540d\u79f0}` - \u83b7\u53d6\u5355\u4e2a\u6307\u6807\u8be6\u7ec6\u5b9a\u4e49\n- `mcp://groups/{\u7ec4ID}` - \u83b7\u53d6\u6307\u6807\u7ec4\u4fe1\u606f\n- `mcp://config/groups` - \u83b7\u53d6\u6240\u6709\u6307\u6807\u7ec4\u6982\u89c8\n\n### \u914d\u7f6e\u76f8\u5173\u8d44\u6e90\n- `mcp://propmap/{API\u540d\u79f0}` - \u83b7\u53d6API\u5b57\u6bb5\u6620\u5c04\u5173\u7cfb\n- `mcp://config/media` - \u83b7\u53d6\u652f\u6301\u7684\u5a92\u4f53\u6e20\u9053\n- `mcp://config/group_keys` - \u83b7\u53d6\u652f\u6301\u7684\u5206\u7ec4\u7ef4\u5ea6\n\n## \ud83d\udcca \u6307\u6807\u4f53\u7cfb\u67b6\u6784\n\n### \u76ee\u524d\u7684\u4e1a\u52a1\u573a\u666f\u6307\u6807\u7ec4\n\n| \u6307\u6807\u7ec4 | \u6838\u5fc3\u7528\u9014 | \u4e3b\u8981\u6307\u6807\u793a\u4f8b |\n|--------|----------|-------------|\n| **\u6295\u653e\u542f\u52a8\u51b3\u7b56** | \u5224\u65ad\u662f\u5426\u5f00\u59cb\u6295\u653e\u65b0\u5e7f\u544a | \u6fc0\u6d3b\u7387\u3001\u6ce8\u518c\u6210\u672c\u3001\u521b\u89d2\u6210\u672c\u30013\u79d2\u64ad\u653e\u7387 |\n| **\u6295\u653e\u6548\u679c\u76d1\u63a7** | \u76d1\u63a7\u6295\u653e\u4e2d\u5e7f\u544a\u5b9e\u65f6\u6548\u679c | \u6d88\u8017\u3001\u70b9\u51fb\u7387\u3001\u65b0\u589e\u6ce8\u518c\u3001\u65b0\u589e\u4ed8\u8d39 |\n| **\u77ed\u671f\u4ef7\u503c\u8bc4\u4f30** | \u8bc4\u4f30\u9996\u65e5\u52307\u65e5\u7528\u6237\u4ef7\u503c | \u9996\u65e5ROI\u30017\u65e5ROI\u3001\u65b0\u589e\u4ed8\u8d39\u7387\u3001\u65b0\u589eARPPU |\n| **\u6df1\u5ea6\u4ef7\u503c\u5206\u6790** | \u8bc4\u4f30\u7528\u6237\u957f\u671f\u4ef7\u503c | \u7d2f\u8ba1ROI\u3001\u7559\u5b58\u7387\u3001\u751f\u547d\u5468\u671f\u4ef7\u503c |\n| **\u5e73\u53f0\u6570\u636e\u5bf9\u8d26** | \u6838\u5bf9\u5404\u5e73\u53f0\u4e0a\u62a5\u6570\u636e | \u5e73\u53f0\u5145\u503c\u3001\u5e73\u53f0\u4ed8\u8d39\u4eba\u6570\u3001\u6570\u636e\u5dee\u5f02 |\n| **\u7ec8\u6b62\u51b3\u7b56\u9884\u8b66** | \u5224\u65ad\u662f\u5426\u9700\u8981\u505c\u6b62\u6295\u653e | \u6210\u672c\u9884\u8b66\u3001ROI\u9884\u8b66\u3001\u8d28\u91cf\u9884\u8b66 |\n| **\u8d22\u52a1\u6838\u7b97\u7ed3\u7b97** | \u8d22\u52a1\u7ed3\u7b97\u76f8\u5173 | \u5206\u6210\u540eROI\u3001\u5b9e\u9645\u6d88\u8017\u3001\u7ed3\u7b97\u91d1\u989d |\n\n## \ud83d\udd0c \u5ba2\u6237\u7aef\u96c6\u6210\u793a\u4f8b\n\n### Claude Desktop \u4f7f\u7528\n\u914d\u7f6e\u5b8c\u6210\u540e\uff0c\u53ef\u76f4\u63a5\u5728Claude Desktop\u4e2d\u8fdb\u884c\u5bf9\u8bdd\u67e5\u8be2\uff1a\n\n```\n\u8bf7\u5e2e\u6211\u5206\u6790\u4e00\u4e0b2025\u5e741\u67081-7\u65e5\u817e\u8baf\u5e7f\u70b9\u901a\u6e20\u9053\u7684\u5e7f\u544a\u6295\u653e\u6548\u679c\uff0c\n\u91cd\u70b9\u5173\u6ce8ROI\u8868\u73b0\u548c\u7528\u6237\u8f6c\u5316\u60c5\u51b5\u3002\n```\n\n### \u7a0b\u5e8f\u5316\u8c03\u7528\n```python\n# \u4f7f\u7528MCP Python SDK\nfrom mcp import ClientSession\n\nasync with ClientSession(\"stdio\", [\"python\", \"run_server.py\"]) as session:\n # \u67e5\u8be2\u5e7f\u544a\u6570\u636e\n result = await session.call_tool(\"query_ad_data\", {\n \"start_date\": \"2025-01-01\",\n \"end_date\": \"2025-01-07\",\n \"indicators\": [\"\u6d88\u8017\", \"\u65b0\u589e\u6ce8\u518c\", \"\u9996\u65e5ROI\"],\n \"app\": \"\u6b63\u7edf\u4e09\u56fd\",\n \"media\": [\"\u5e7f\u70b9\u901a\", \"\u4eca\u65e5\u5934\u6761\"]\n })\n\n # \u83b7\u53d6\u6e38\u620f\u53ef\u7528\u6307\u6807\n available_indicators = await session.call_tool(\"get_available_indicators\", {\n \"app\": \"\u6b63\u7edf\u4e09\u56fd\",\n \"query_type\": \"ad_query\"\n })\n\n # \u9a8c\u8bc1\u6307\u6807\u517c\u5bb9\u6027\n validation = await session.call_tool(\"validate_indicators\", {\n \"indicators\": [\"\u6d88\u8017\", \"\u5c55\u73b0\", \"\u70b9\u51fb\"],\n \"app\": \"\u6b63\u7edf\u4e09\u56fd\"\n })\n```\n\n## \ud83c\udf10 \u652f\u6301\u7684\u5a92\u4f53\u6e20\u9053\n\n**MCP\u5de5\u5177\u76f4\u63a5\u4f7f\u7528\u4e2d\u6587\u540d\u79f0\uff0c\u7cfb\u7edf\u4f1a\u81ea\u52a8\u8f6c\u6362\u4e3a\u5bf9\u5e94\u7684API\u4ee3\u7801\uff1a**\n\n| \u4e2d\u6587\u540d\u79f0 | API\u4ee3\u7801 | \u4e2d\u6587\u540d\u79f0 | API\u4ee3\u7801 |\n|---------|---------|---------|---------|\n| \u5e7f\u70b9\u901a | `gdt` | \u4eca\u65e5\u5934\u6761 | `tt` |\n| \u767e\u5ea6 | `bd` | \u767e\u5ea6\u641c\u7d22 | `bdss` |\n| B\u7ad9 | `bz` | \u77e5\u4e4e | `zh` |\n| UC | `uc` | \u6296\u5c0f\u5e7f\u544a\u91cf | `dx` |\n| \u89c6\u9891\u53f7\u8fbe\u4eba | `sphdr` | \u661f\u56fe | `xt` |\n| \u8c37\u6b4c | `gg` | \u81ea\u7136\u91cf | `nature` |\n\n## \ud83d\udcda \u6587\u6863\u6307\u5357\n\n\u672c\u9879\u76ee\u63d0\u4f9b\u5b8c\u6574\u7684\u6587\u6863\u4f53\u7cfb\uff0c\u8bf7\u6839\u636e\u60a8\u7684\u89d2\u8272\u9009\u62e9\u5408\u9002\u7684\u6587\u6863\uff1a\n\n| \u89d2\u8272 | \u63a8\u8350\u6587\u6863 | \u7528\u9014 |\n|------|----------|------|\n| **\u6700\u7ec8\u7528\u6237/\u8fd0\u8425** | [USER_GUIDE.md](USER_GUIDE.md) | \u5b89\u88c5\u4f7f\u7528\u3001\u529f\u80fd\u64cd\u4f5c\u3001\u4e1a\u52a1\u5e94\u7528 |\n| **\u5f00\u53d1\u8005/\u8d21\u732e\u8005** | [DEVELOPMENT.md](DEVELOPMENT.md) | \u5f00\u53d1\u73af\u5883\u3001\u7f16\u7801\u89c4\u8303\u3001\u6269\u5c55\u5f00\u53d1 |\n| **\u67b6\u6784\u5e08/\u6280\u672f\u8d1f\u8d23\u4eba** | [ARCHITECTURE.md](ARCHITECTURE.md) | \u7cfb\u7edf\u8bbe\u8ba1\u3001\u7ec4\u4ef6\u67b6\u6784\u3001\u6280\u672f\u51b3\u7b56 |\n\n### \ud83d\ude80 \u9605\u8bfb\u5efa\u8bae\n\n1. **\u60f3\u8981\u5feb\u901f\u4f7f\u7528\u670d\u52a1**\uff1a\u76f4\u63a5\u9605\u8bfb [USER_GUIDE.md](USER_GUIDE.md) \u7684\"\u5feb\u901f\u5f00\u59cb\"\u90e8\u5206\n2. **\u60f3\u8981\u8d21\u732e\u4ee3\u7801**\uff1a\u5148\u9605\u8bfb [ARCHITECTURE.md](ARCHITECTURE.md) \u4e86\u89e3\u8bbe\u8ba1\uff0c\u518d\u770b [DEVELOPMENT.md](DEVELOPMENT.md) \u5b66\u4e60\u5f00\u53d1\u89c4\u8303\n3. **\u60f3\u8981\u4e86\u89e3\u6280\u672f\u67b6\u6784**\uff1a\u91cd\u70b9\u9605\u8bfb [ARCHITECTURE.md](ARCHITECTURE.md)\n\n## \ud83d\udd27 \u6280\u672f\u7279\u70b9\n\n- **\u73b0\u4ee3Python\u67b6\u6784**\uff1a\u57fa\u4e8ePython 3.11+\n- **\u6a21\u5757\u5316\u8bbe\u8ba1**\uff1a\u6e05\u6670\u7684\u5c42\u6b21\u5206\u79bb\uff0cManager\u6a21\u5f0f\u7ba1\u7406\u6570\u636e\n- **\u6807\u51c6\u534f\u8bae\u652f\u6301**\uff1a\u9075\u5faaMCP\u534f\u8bae\u89c4\u8303\n- **\u9ad8\u6027\u80fd\u5f02\u6b65**\uff1a\u4f7f\u7528Python 3.11+ TaskGroup\u5b9e\u73b0\u591a\u592924\u5c0f\u65f6\u6570\u636e\u5e76\u53d1\u67e5\u8be2\uff0c\u67e5\u8be2\u6027\u80fd\u63d0\u534710-20\u500d\n- **\u6a21\u5757\u5316\u6269\u5c55**\uff1a\u6e05\u6670\u7684\u7ec4\u4ef6\u6ce8\u518c\u673a\u5236\uff0c\u4fbf\u4e8e\u6dfb\u52a0\u65b0\u5de5\u5177\u548c\u8d44\u6e90\n- **\u5b8c\u6574\u6d4b\u8bd5\u8986\u76d6**\uff1a\u5305\u542b\u5355\u5143\u6d4b\u8bd5\u548c\u96c6\u6210\u6d4b\u8bd5\n\n## \ud83d\udcc8 \u66f4\u65b0\u65e5\u5fd7\n\n- v0.0.13 (2025-08-20)\n - **\u5e7f\u544a\u6307\u6807\u4f9d\u8d56\u81ea\u52a8\u6ce8\u5165**\n - `indicator_manager` \u652f\u6301\u4ece `data/indicators/dependencies/` \u52a0\u8f7d\u89c4\u5219\n - \u907f\u514d\u201c\u4ed8\u8d39\u5206\u6210\u540e\u9996\u65e5ROI\u201d\u7b49\u7a7a\u503c\u95ee\u9898\n - **\u914d\u7f6e\u5316\u9ed8\u8ba4\u6307\u6807**\n - \u7d20\u6750\u67e5\u8be2\u9ed8\u8ba4\u8865\u5145\u201c\u7d20\u6750id\u201d\u201c\u6d3b\u8dc3\u7528\u6237\u201d\uff0c\u5e7f\u544a\u67e5\u8be2\u9ed8\u8ba4\u8865\u5145\u201c\u65e5\u671f\u201d\u6539\u4e3a\u53ef\u914d\u7f6e\n - **\u6587\u6863\u5b8c\u5584**\uff1a\n - \u5b8c\u5584 GetAdCountList \u6d3e\u751f\u4e0e\u5e73\u53f0ROI\u652f\u6301\u8bf4\u660e\n - \u5b8c\u5584 GetMaterialCountList \u7684\u4e1a\u52a1\u903b\u8f91\u8868\u8ff0\n- v0.0.12 (2025-08-19)\n - **MCP\u5de5\u5177\u53c2\u6570\u63cf\u8ff0\u4f18\u5316**\uff1a\n - \u4f7f\u7528`Annotated`\u548c`Field`\u4e3a\u6240\u6709MCP\u5de5\u5177\u53c2\u6570\u6dfb\u52a0\u63cf\u8ff0\uff0c\u4f7f\u53c2\u6570\u5728list_tools\u65f6\u6b63\u786e\u663e\u793a\n - \u4f18\u5316docstring\u7ed3\u6784\uff0c\u53bb\u9664\u5197\u4f59\u90e8\u5206\n - **\u786c\u7f16\u7801\u6e05\u7406**\uff1a\n - \u66f4\u65b0\u6d4b\u8bd5\u811a\u672c\u4f7f\u7528uv run\u672c\u5730\u8fd0\u884c\u65b9\u5f0f\uff0c\u53bb\u9664\u786c\u7f16\u7801\u8def\u5f84\n- v0.0.11 (2025-08-19)\n - **\u7d20\u6750\u67e5\u8be2\u5206\u7c7b\u67b6\u6784\u4f18\u5316**\uff1a\u91cd\u6784\u7d20\u6750\u67e5\u8be2\u5de5\u5177\uff0c\u81ea\u52a8\u5206\u7c7b\u8fd4\u56de\n - \u6682\u5b9a\u56db\u79cd\u7d20\u6750\u5206\u7c7b\u6a21\u5f0f\uff1ahistorical\uff08\u5386\u53f2\u7d20\u6750\uff09\u3001active\uff08\u6d3b\u8dc3\u7d20\u6750\uff09\u3001no_conversion\uff08\u6682\u65e0\u8f6c\u5316\uff09\u3001users_only\uff08\u4ec5\u7528\u6237\u7d20\u6750\uff09\n - **\u6d4b\u8bd5\u4f53\u7cfb\u91cd\u7ec4**\uff1a\n - \u91cd\u65b0\u7ec4\u7ec7\u6d4b\u8bd5\u76ee\u5f55\u7ed3\u6784\uff1a`tests/`\uff08\u5355\u5143\u6d4b\u8bd5\uff09\u3001`scripts/`\uff08\u8c03\u8bd5\u5de5\u5177\uff09\u3001`manual_tests/`\uff08\u624b\u52a8\u9a8c\u8bc1\u811a\u672c\uff09\n - **\u7b80\u5316API\u6587\u6863\u53d9\u8ff0**\n- v0.0.10 (2025-08-18)\n - **StreamableHTTP\u4f20\u8f93\u6a21\u5f0f\u652f\u6301**\uff1a\u65b0\u589eHTTP API\u670d\u52a1\u5668\u6a21\u5f0f\uff0c\u652f\u6301 `--transport` \u547d\u4ee4\u884c\u53c2\u6570\u9009\u62e9\u4f20\u8f93\u534f\u8bae\uff08stdio/streamable-http\uff09\uff0c\u652f\u6301\u901a\u8fc7HTTP\u8bf7\u6c42\u8c03\u7528MCP\u5de5\u5177\n - **\u73af\u5883\u53d8\u91cf\u914d\u7f6e**\uff1a\u5b8c\u5584HTTP\u6a21\u5f0f\u7684\u914d\u7f6e\u9009\u9879\uff08host\u3001port\u3001path\u7b49\uff09\n- v0.0.9 (2025-08-15)\n - **MCP\u5de5\u5177\u53c2\u6570\u7c7b\u578b\u4f18\u5316**\uff1a\u652f\u6301\u5b57\u7b26\u4e32\u548c\u5217\u8868\u53c2\u6570\u6df7\u5408\u4f7f\u7528\n - \u4fee\u590d\u5de5\u5177\u7b7e\u540d\u4e2d `media` \u7b49\u53c2\u6570\u4ece `list[str]` \u6539\u4e3a `str | list[str]`\uff0c\u6682\u65f6\u89e3\u51b3\u6a21\u578b\u8c03\u7528\u5de5\u5177\u65f6\u4e0d Follow \u7c7b\u578b\u7ea6\u675f\u7684\u884c\u4e3a\n- v0.0.8 (2025-08-15)\n - **\u65e5\u671f\u5b57\u6bb5\u81ea\u52a8\u6dfb\u52a0**\uff1a\u6307\u6807\u67e5\u8be2\u65f6\u81ea\u52a8\u6dfb\u52a0\u300c\u65e5\u671f\u300d\u5b57\u6bb5\uff0c\u65e0\u9700\u624b\u52a8\u6307\u5b9a\n - \u6539\u8fdb\u7528\u6237\u4f53\u9a8c\uff0c\u907f\u514d\u56e0\u7f3a\u5c11\u65e5\u671f\u5b57\u6bb5\u800c\u4ea7\u751f\u7684\u9519\u8bef\u63d0\u793a\uff0c\u7b80\u5316LLM\u8c03\u7528\u5de5\u5177\u6d41\u7a0b\n - **API\u6a21\u578b\u53c2\u6570\u5904\u7406\u4f18\u5316**\uff1a\u589e\u5f3aGetAdCountListRequest\u548cGetMaterialCountListRequest\u7684\u53c2\u6570\u5904\u7406\u80fd\u529b\n - \u65b0\u589e `@field_validator(mode=\"before\")` \u9884\u5904\u7406\u9a8c\u8bc1\u5668\n - \u652f\u6301\u7a7a/\u5355\u5b57\u7b26\u4e32\u53c2\u6570\u81ea\u52a8\u8f6c\u6362\u4e3a\u5217\u8868\uff0c\u63d0\u5347API\u4f7f\u7528\u4f53\u9a8c\n - **API\u6587\u6863\u5b8c\u5584**\uff1a\u7d20\u6750\u67e5\u8be2\u63a5\u53e3\u7684\u6587\u6863\u66f4\u65b0\uff08`docs/api/GetMaterialCountList/`\uff09\n- v0.0.7 (2025-08-15)\n - **\u6587\u6863\u53c2\u6570\u66f4\u65b0**\uff1a\u7edf\u4e00\u6240\u6709\u6587\u6863\u4e2d\u7684\u53c2\u6570\u683c\u5f0f\uff0c\u91c7\u7528\u4e2d\u6587\u53c2\u6570\u793a\u4f8b\n - **GroupKey\u6307\u6807\u9a8c\u8bc1\u4f18\u5316**\uff1a\u4fee\u590d\u5206\u7ec4\u5b57\u6bb5\u672c\u8eab\u7684\u6307\u6807\u9a8c\u8bc1\u95ee\u9898\n - \u5f53\u4f7f\u7528 `group_key` \u5206\u7ec4\u65f6\uff0c\u5bf9\u5e94\u7684\u5206\u7ec4\u5b57\u6bb5\uff08\u5982\"\u5e7f\u544aID\"\u3001\"\u9879\u76eeID\"\uff09\u73b0\u5728\u88ab\u6b63\u786e\u8bc6\u522b\u4e3a\u6709\u6548\u6307\u6807\n - \u589e\u5f3a `validate_indicators` \u65b9\u6cd5\uff0c\u652f\u6301 `group_key` \u53c2\u6570\u8fdb\u884c\u66f4\u7cbe\u786e\u7684\u6307\u6807\u9a8c\u8bc1\n - **API\u6587\u6863\u5b8c\u5584**\uff1a\u65b0\u589e\u7d20\u6750\u67e5\u8be2\u63a5\u53e3\u7684\u4eca\u65e5\u5934\u6761\u54cd\u5e94\u793a\u4f8b\u6587\u4ef6\n- v0.0.6 (2025-08-14)\n - **\u53c2\u6570\u4e2d\u6587\u5316\u6539\u9020**\uff1aMCP\u5de5\u5177\u63a5\u53e3\u5168\u9762\u652f\u6301\u4e2d\u6587\u53c2\u6570\uff0c\u63d0\u5347LLM\u4f7f\u7528\u4f53\u9a8c\n - \u6e38\u620f\u53c2\u6570\u4ece\u6570\u5b57ID\u6539\u4e3a\u4e2d\u6587\u540d\u79f0\uff08\u5982 `app_id=\"59\"` \u2192 `app=\"\u6b63\u7edf\u4e09\u56fd\"`\uff09\n - \u652f\u6301\u4e2d\u6587\u5a92\u4f53\u6e20\u9053\u3001\u6295\u624b\u59d3\u540d\u3001\u5e7f\u544a\u72b6\u6001\u7b49\u53c2\u6570\u503c\n - \u65b0\u589e\u6e38\u620f\u652f\u6301\uff1a\u6211\u7684\u4ed9\u95e8\u3001\u4e00\u8d77\u6597\u6d88\u4e50\u3001\u5927\u5934\u7cfb\u5217\u6e38\u620f\u7b49\n - **\u591a\u592924\u5c0f\u65f6\u67e5\u8be2\u4f18\u5316**\uff1a\u6539\u8fdbsummary\u6570\u636e\u51c6\u786e\u6027\n - \u5e9f\u5f03\u624b\u52a8\u5408\u5e76summary\u903b\u8f91\uff08\u5b58\u5728\u767e\u5206\u6bd4/\u6bd4\u7387\u6307\u6807\u8ba1\u7b97\u4e0d\u51c6\u786e\u95ee\u9898\uff09\n - \u901a\u8fc7\u989d\u5916API\u8bf7\u6c42\uff08`hours_24=False`\uff09\u83b7\u53d6\u540e\u7aef\u8ba1\u7b97\u7684\u51c6\u786e\u6c47\u603b\u6570\u636e\n - \u6dfb\u52a0\u6ce8\u91ca\u8bb0\u5f55\u672a\u6765\u53ef\u8fd4\u56de`daily_summaries`\u5217\u8868\u7684\u6539\u8fdb\u601d\u8def\n- v0.0.5 (2025-08-14)\n - \u6307\u6807\u9a8c\u8bc1\u7cfb\u7edf\u91cd\u6784\u548c PropMap \u67b6\u6784\u4f18\u5316\n - \u6307\u6807\u4f53\u7cfb\u4ece\u5168\u5c40\u6539\u4e3a\u6e38\u620f\u7c7b\u578b\u5206\u7ec4\uff08\u68cb\u724c/\u975e\u68cb\u724c\uff09\n - PropMap \u6587\u4ef6\u53cd\u5411\u91cd\u6784\uff0c\u7ba1\u7406\u5668\u91cd\u5199\uff0c\u63d0\u5347\u53ef\u7ef4\u62a4\u6027\n - API \u5ba2\u6237\u7aef\u9a8c\u8bc1\u903b\u8f91\u4f18\u5316\uff1a\u652f\u6301\u52a8\u6001\u6761\u4ef6\u6027\u6307\u6807\u6ce8\u5165\uff0c\u57fa\u4e8e `group_key` \u667a\u80fd\u6dfb\u52a0\u6307\u6807\uff0c\u4e0e\u524d\u7aef\u8868\u73b0\u4e00\u81f4\n- v0.0.4 (2025-08-13)\n - \u6570\u636e\u5904\u7406\u5c42\u91cd\u6784\u4e0e\u7248\u672c\u7ba1\u7406\u4f18\u5316\uff1b\u7d20\u6750\u6570\u636e\u5b8c\u5584\uff1b\u4e0a\u4f20\u540e\u7aef\u63a5\u53e3\u53c2\u8003\u4ee3\u7801\uff1b\u57fa\u4e8e\u4ee3\u7801\u66f4\u65b0 `docs/`\n - \u5bf9\u6307\u6807\u9519\u8bef\u63d0\u4f9b\u66f4\u89c4\u8303\u7684\u9519\u8bef\u63d0\u793a\n - \u67e5\u8be2\u7ed3\u679c\u6539\u4e3a\u6309\u65e5\u671f\u5012\u5e8f\u8fd4\u56de\uff0c\u4e14\u53ea\u8f93\u51fa\u7b5b\u9009\u540e\u7684\u6307\u6807\n - \u4f7f\u7528 `group_key` \u5206\u7ec4\u65f6\uff0c\u4f1a\u5728\u8fd4\u56de\u4e2d\u8ffd\u52a0\u5e76\u6620\u5c04\u5bf9\u5e94\u7684 `group_key`\n- v0.0.3 (2025-08-12)\n - \u6e05\u7406\u63a8\u8350\u903b\u8f91\u5197\u4f59\u4ee3\u7801\uff0c\u7edf\u4e00\u6587\u4ef6\u548c\u51fd\u6570\u547d\u540d\u89c4\u8303\n - \u8fc1\u79fb\u6570\u636e\u76ee\u5f55\u5230 `src/mcp_ad_server/data` \u4ee5\u652f\u6301\u6253\u5305\u5206\u53d1\n - \u5b9e\u73b0\u5ba2\u6237\u7aef\u5c42\u6570\u636e\u6392\u5e8f\uff08\u666e\u901a\u6570\u636e\u6309\u65e5\u671f\u5012\u5e8f\uff0c24 \u5c0f\u65f6\u6570\u636e\u6309\u5c0f\u65f6\u6b63\u5e8f\uff09\n - \u4f7f\u7528 Python 3.11+ `asyncio.TaskGroup` \u4f18\u5316\u591a\u5929 24 \u5c0f\u65f6\u67e5\u8be2\u5e76\u53d1\u5904\u7406\uff0c\u6682\u65f6\u589e\u52a0\u95f4\u9694\u907f\u514d\u77ac\u95f4\u6253\u6ee1\u540e\u7aef\uff0c\u540e\u7eed\u6216\u53ef\u4f18\u5316\u3002\n - \u901a\u8fc7 `uvx mcp_ad_server` \u53ef\u5728\u4efb\u610f\u673a\u5668\u5feb\u901f\u63a5\u5165 MCP\n- v0.0.2 (2025-08-11)\n - \u5b8c\u5584 API \u5ba2\u6237\u7aef\u529f\u80fd\uff1a\u53c2\u6570\u522b\u540d\u517c\u5bb9\u3001\u81ea\u52a8\u603b\u8ba1\u9879\u5904\u7406\u3001Pydantic \u6570\u636e\u9a8c\u8bc1\n- v0.0.1 (2025-08-07)\n - \u91cd\u6784\u6587\u6863\u4f53\u7cfb\uff0c\u5b9e\u73b0\u5b8c\u6574 MCP \u670d\u52a1\u67b6\u6784\n - \u521d\u59cb\u5316\u9879\u76ee\u7ed3\u6784\uff0c\u6574\u7406\u6307\u6807\u4f53\u7cfb\n - \u6dfb\u52a0 API \u54cd\u5e94\u793a\u4f8b\u6587\u4ef6\uff08\u539f\u59cb\u63d0\u4ea4\u4e8e 2025-08-05\uff09\n\n\n## \ud83e\udd1d \u6280\u672f\u652f\u6301\n\n\u5982\u6709\u95ee\u9898\u6216\u5efa\u8bae\uff0c\u8bf7\u8054\u7cfb\uff1a\n- **\u6280\u672f\u95ee\u9898**\uff1a\u9489\u9489 AI \u5f00\u53d1\u56e2\u961f\n- **\u4e1a\u52a1\u54a8\u8be2**\uff1a\u5e7f\u544a\u6295\u653e\u56e2\u961f\n- **\u529f\u80fd\u5efa\u8bae**\uff1a\u901a\u8fc7\u5185\u90e8\u53cd\u9988\u6e20\u9053\u63d0\u4ea4\n\n## \ud83d\udccb TODO (\u4f4e\u4f18\u5148\u7ea7)\n\n- **\u6307\u6807\u914d\u7f6e\u4f18\u5316**\uff1a\u5f53\u524dcard_games/non_card_games\u7ed3\u6784\u4e2d\u53ef\u80fd\u5b58\u5728\u6307\u6807\u91cd\u590d\uff0c\u53ef\u8003\u8651\u62bd\u53d6\u4e3a\u5206\u5c42\u6307\u6807\u96c6(base + extensions)\u4ee5\u7b80\u5316\u914d\u7f6e\u548c\u7ef4\u62a4\n\n---\n\n> **\u6ce8\u610f**\uff1a\u672c\u9879\u76ee\u4e2d\u7684\u6307\u6807\u5206\u7ec4\u548c\u63a8\u8350\u7b97\u6cd5\u4e3a\u6d4b\u8bd5\u7248\u672c\uff0c\u5b9e\u9645\u4f7f\u7528\u65f6\u9700\u8981\u4e0e\u6295\u653e\u56e2\u961f\u5bf9\u63a5\u6821\u51c6\u4e1a\u52a1\u903b\u8f91\u3002\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "MCP\u670d\u52a1\u5668\u7528\u4e8e\u5904\u7406\u5e7f\u544a\u6295\u653e\u6570\u636e",
"version": "0.0.13",
"project_urls": null,
"split_keywords": [
"mcp",
" advertising",
" analytics",
" data-analysis"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "40acba001bdbd375cd13b494e3db9ba82cad58fe04e447702fe8cb56f87c8de4",
"md5": "d1fe8168e45d1e61137a8b682b613456",
"sha256": "70b7b0cca3d142cc44c6f262260bb96ad95de4c16d8ade5ff0a55a9ed0e5a8b4"
},
"downloads": -1,
"filename": "mcp_ad_server-0.0.13-py3-none-any.whl",
"has_sig": false,
"md5_digest": "d1fe8168e45d1e61137a8b682b613456",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.11",
"size": 119330,
"upload_time": "2025-08-20T07:08:45",
"upload_time_iso_8601": "2025-08-20T07:08:45.633480Z",
"url": "https://files.pythonhosted.org/packages/40/ac/ba001bdbd375cd13b494e3db9ba82cad58fe04e447702fe8cb56f87c8de4/mcp_ad_server-0.0.13-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "292d263b905ee4ee8e5e6a4c96a2f124df0cc41b89fdc1c19e4bd0bd978158ac",
"md5": "66a1189ea48c522883648422a4979533",
"sha256": "b66235308f24fa387b76e4f3f2790c5bab37f62bb0b1724c63da3661a723fac8"
},
"downloads": -1,
"filename": "mcp_ad_server-0.0.13.tar.gz",
"has_sig": false,
"md5_digest": "66a1189ea48c522883648422a4979533",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.11",
"size": 103002,
"upload_time": "2025-08-20T07:08:47",
"upload_time_iso_8601": "2025-08-20T07:08:47.669192Z",
"url": "https://files.pythonhosted.org/packages/29/2d/263b905ee4ee8e5e6a4c96a2f124df0cc41b89fdc1c19e4bd0bd978158ac/mcp_ad_server-0.0.13.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-20 07:08:47",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"lcname": "mcp-ad-server"
}