Metadata-Version: 2.4
Name: russel-travel-safety-mcp-2026
Version: 0.2.0
Summary: Allowlist-only MCP server and Qwen travel-advice aggregator
License: MIT
Requires-Python: >=3.11
Requires-Dist: httpx<1,>=0.28
Requires-Dist: mcp<2,>=1.27
Description-Content-Type: text/markdown

# Travel Safety MCP

一个仅访问固定官方来源的旅行安全 MCP 服务。Agent 只能传入国家、别名和日期，不能传入任意 URL。

## 工具

- `get_current_time`
- `search_four_travel_advisories`：输入一次国家名称，后台并行调用千问联网检索 Agent 四次并合并结果
- `search_basic_advisories`
- `search_health_events`
- `search_disaster_events`
- `search_conflict_events`

## 千问四站聚合工具

`search_four_travel_advisories` 的最小输入只有国家名称：

```json
{
  "country": "日本"
}
```

可选传入时间 MCP 返回的日期和英文国名：

```json
{
  "country": "日本",
  "current_date": "2026-07-07",
  "country_en": "Japan"
}
```

服务会在后台并行执行中国领事服务网、澳大利亚 Smartraveller、英国
Foreign Travel Advice、美国 Travel.State.Gov 四次定向检索，只向 Agent 返回
一次合并 JSON。非目标域名 URL 会被拒绝；只有 `status=FOUND` 的页面可以用于回答。

运行前配置环境变量：

```bash
export DASHSCOPE_API_KEY="sk-你的百炼APIKey"
export QWEN_WEB_SEARCH_AGENT_ID="aid-你的联网检索应用ID"
export QWEN_WEB_SEARCH_AGENT_VERSION="release"
```

可选配置：

```bash
export QWEN_WEB_SEARCH_TIMEOUT_SECONDS="180"
export QWEN_WEB_SEARCH_MAX_RETRIES="1"
```

密钥只能通过环境变量或阿里云密钥管理注入，不要写入代码、提示词或发布包。

所有检索工具都会返回来源状态。`error` 表示访问失败，`no_match` 表示当前页面没有找到国家匹配，Agent 不得把这两种状态描述为“没有风险”。

## 安全边界

- 起始网页固定在 `config.py` 中。
- 只允许 HTTPS 443 和精确匹配的白名单域名。
- 每一次重定向都会重新检查域名。
- 拒绝解析到私网、环回、链路本地等非公网地址的域名。
- HTTP 客户端不读取系统代理配置。
- 单个响应最多 2 MB，最多跟随 5 次白名单内重定向。
- 工具不接受 URL 参数。

代码白名单可以控制 MCP 自己发出的请求。生产环境仍建议通过 VPC 出站代理或云防火墙实施“默认拒绝、按域名放行”的网络策略。

## 本地运行

需要 Python 3.11 以上和 `uv`：

```bash
uv sync
uv run travel-safety-mcp
```

运行测试：

```bash
uv run python -m unittest discover -s tests -v
```

## 发布到 PyPI

百炼的 `uvx` 脚本部署需要从公开 PyPI 安装包。当前发布包名为 `russel-travel-safety-mcp-2026`，命令名为 `travel-safety-mcp`。

```bash
uv build
uv publish
```

不要在代码或发布包中保存 PyPI Token、百炼 API Key 或其他密钥。

## 百炼脚本部署

在 `MCP 管理 -> 创建 MCP 服务 -> 使用脚本部署` 中选择：

- 安装方式：`uvx`
- 部署方式：基础模式
- 地域：北京或最接近业务的地域

使用下面的包名和版本：

```json
{
  "mcpServers": {
    "travel-safety": {
      "command": "uvx",
      "args": [
        "--from",
        "russel-travel-safety-mcp-2026==0.2.0",
        "travel-safety-mcp"
      ]
    }
  }
}
```

## Agent 提示词片段

```text
每次国家查询必须先调用 get_current_time，时区固定为 Asia/Shanghai。
随后使用中文国名和英文国名调用相应检索工具。
近一年和近两年的起止日期必须根据 get_current_time 的 date 计算。
只允许使用本 MCP 返回的 pages 内容。
status 为 error 或 no_match 时，不得推测或补写；应说明指定网站未获取到相关信息。
不同基本网站风险描述冲突时，采用最高风险描述。
```

## 当前限制

第一版通过各官方网站的固定索引页发现国家相关链接。网站改版、JavaScript 渲染、验证码或反自动化策略都可能导致单一来源返回 `error` 或 `no_match`。后续应为失败率较高的网站增加专用适配器，而不是放开通用搜索或任意 URL 抓取。
