Metadata-Version: 2.4
Name: zh-file-mcp
Version: 0.1.0
Summary: MCP file gateway for downloading and uploading business-system files into the agent workspace
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: fastmcp>=2.5.2
Requires-Dist: httpx>=0.27.0
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: pydantic>=2.7.0

# zh-file-mcp

`zh-file-mcp` is a stdio-first MCP file gateway. It downloads files from configured business systems into the agent workspace and uploads local workspace files back to those systems.

It is intentionally generic: systems such as `wpos` are configured with JSON instead of hard-coded MCP tools.

## Features

- Stdio MCP server for Cherry Studio, web-agent, and other MCP clients.
- Config-driven HTTP download, upload, list, and metadata requests.
- Cookie, bearer, custom header, static headers, and no-auth modes.
- Files are written under the MCP process working directory.
- Tool results return `relative_path` so agents can continue reading files.
- Paths are constrained to the workspace.
- Large business IDs can be passed as strings to avoid JavaScript precision loss.

## Tools

| Tool | Description |
| --- | --- |
| `get_workspace_info` | Show current working directory, download root, and configured systems. |
| `download_file` | Download a configured system file into the workspace. |
| `upload_file` | Upload a workspace file to a configured system. |
| `list_files` | List files from a configured system, if the system defines `list`. |
| `get_file_info` | Get file metadata, if the system defines `file_info`. |

## Install

```bash
cd /Users/linchuanke/lck/zhonghui/zh-file-mcp
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
```

Verify:

```bash
/Users/linchuanke/lck/zhonghui/zh-file-mcp/.venv/bin/zh-file-mcp --help
```

After code changes, reinstall:

```bash
source .venv/bin/activate
pip install -e .
```

## Environment

| Variable | Default | Description |
| --- | --- | --- |
| `FILE_MCP_SYSTEMS_JSON` | - | Inline JSON systems config. Takes precedence over config file. |
| `FILE_MCP_SYSTEMS_CONFIG` | - | Path to a JSON systems config file. |
| `FILE_MCP_WORK_DIR` | process cwd | Optional explicit working directory. |
| `FILE_MCP_DOWNLOAD_DIR` | `downloads` | Relative download root inside work dir. |
| `FILE_MCP_MAX_BYTES` | `524288000` | Max download/upload size in bytes. |
| `FILE_MCP_TIMEOUT_SECONDS` | `60` | HTTP request timeout. |
| `FILE_MCP_VERIFY_SSL` | `true` | Verify HTTPS certificates. |
| `FILE_MCP_LOG_LEVEL` | `INFO` | Logging level. |
| `AUTH_TOKEN` | - | Common business login token env used by examples. |

If neither `FILE_MCP_SYSTEMS_JSON` nor `FILE_MCP_SYSTEMS_CONFIG` is set, the server can still create a default `wpos` config from legacy `WPOS_*` variables. New deployments should prefer explicit systems config.

## Cherry Studio Config

This is a single-file Cherry config using inline `FILE_MCP_SYSTEMS_JSON`:

```json
{
  "mcpServers": {
    "zh-file-mcp": {
      "command": "/Users/linchuanke/lck/zhonghui/zh-file-mcp/.venv/bin/zh-file-mcp",
      "args": [],
      "env": {
        "AUTH_TOKEN": "你的tk值",
        "FILE_MCP_WORK_DIR": "/Users/linchuanke/lck/zhonghui/cherry-workspace",
        "FILE_MCP_DOWNLOAD_DIR": "input",
        "FILE_MCP_SYSTEMS_JSON": "{\"systems\":{\"wpos\":{\"base_url\":\"http://wpos.dev.zhrdc.zhcpa.cn:8084\",\"auth\":{\"type\":\"cookie\",\"cookie_name\":\"tk\",\"token_env\":\"AUTH_TOKEN\"},\"download\":{\"method\":\"GET\",\"path\":\"/api/project/file/downloadGet\",\"params\":{\"projectId\":\"$project_id\",\"fileId\":\"$file_id\"},\"headers\":{\"download-source\":\"CLIENT\"}},\"upload\":{\"method\":\"POST\",\"path\":\"/api/project/file/upload\",\"content_type\":\"multipart\",\"file_field\":\"file\",\"params\":{\"projectId\":\"$project_id\",\"catalogId\":\"$catalog_id\",\"nameStrategy\":\"$name_strategy\"}},\"list\":{\"method\":\"GET\",\"path\":\"/wpos/api/project/file/listByParent\",\"params\":{\"projectId\":\"$project_id\",\"parentId\":\"$parent_id\"}},\"file_info\":{\"method\":\"GET\",\"path\":\"/api/project/file/get\",\"params\":{\"projectId\":\"$project_id\",\"fileId\":\"$file_id\"},\"unwrap\":\"data\"}}}}"
      }
    }
  }
}
```

## web-agent Config

For web-agent Docker images where `zh-file-mcp` is installed in the runtime image:

```json
{
  "name": "zh-file-mcp",
  "type": "stdio",
  "command": "zh-file-mcp",
  "env": {
    "AUTH_TOKEN": "${AUTH_TOKEN}",
    "UV_INDEX_URL": "https://pypi.tuna.tsinghua.edu.cn/simple",
    "FILE_MCP_DOWNLOAD_DIR": "downloads",
    "FILE_MCP_SYSTEMS_JSON": "{\"systems\":{\"wpos\":{\"base_url\":\"http://wpos.dev.zhrdc.zhcpa.cn:8084\",\"auth\":{\"type\":\"cookie\",\"cookie_name\":\"tk\",\"token_env\":\"AUTH_TOKEN\"},\"download\":{\"method\":\"GET\",\"path\":\"/api/project/file/downloadGet\",\"params\":{\"projectId\":\"$project_id\",\"fileId\":\"$file_id\"},\"headers\":{\"download-source\":\"CLIENT\"}},\"upload\":{\"method\":\"POST\",\"path\":\"/api/project/file/upload\",\"content_type\":\"multipart\",\"file_field\":\"file\",\"params\":{\"projectId\":\"$project_id\",\"catalogId\":\"$catalog_id\",\"nameStrategy\":\"$name_strategy\"}},\"list\":{\"method\":\"GET\",\"path\":\"/wpos/api/project/file/listByParent\",\"params\":{\"projectId\":\"$project_id\",\"parentId\":\"$parent_id\"}},\"file_info\":{\"method\":\"GET\",\"path\":\"/api/project/file/get\",\"params\":{\"projectId\":\"$project_id\",\"fileId\":\"$file_id\"},\"unwrap\":\"data\"}}}}"
  },
  "tools": [
    "get_workspace_info",
    "download_file",
    "upload_file",
    "list_files",
    "get_file_info"
  ],
  "rewrite_workspace_paths": true
}
```

Do not set `FILE_MCP_WORK_DIR` in web-agent unless you have a specific reason. Let web-agent start MCP in the session workspace so downloaded files land in that session.

## Systems Config

For readability, you can store systems config in a file and set `FILE_MCP_SYSTEMS_CONFIG` instead of using inline JSON.

Example `file-mcp-systems.json`:

```json
{
  "systems": {
    "wpos": {
      "base_url": "http://wpos.dev.zhrdc.zhcpa.cn:8084",
      "auth": {
        "type": "cookie",
        "cookie_name": "tk",
        "token_env": "AUTH_TOKEN"
      },
      "download": {
        "method": "GET",
        "path": "/api/project/file/downloadGet",
        "params": {
          "projectId": "$project_id",
          "fileId": "$file_id"
        },
        "headers": {
          "download-source": "CLIENT"
        }
      },
      "upload": {
        "method": "POST",
        "path": "/api/project/file/upload",
        "content_type": "multipart",
        "file_field": "file",
        "params": {
          "projectId": "$project_id",
          "catalogId": "$catalog_id",
          "nameStrategy": "$name_strategy"
        }
      },
      "list": {
        "method": "GET",
        "path": "/wpos/api/project/file/listByParent",
        "params": {
          "projectId": "$project_id",
          "parentId": "$parent_id"
        }
      },
      "file_info": {
        "method": "GET",
        "path": "/api/project/file/get",
        "params": {
          "projectId": "$project_id",
          "fileId": "$file_id"
        },
        "unwrap": "data"
      }
    }
  }
}
```

## Prompt Examples

Check configuration:

```text
调用 zh-file-mcp 的 get_workspace_info。
```

Download a wpos file:

```text
用 zh-file-mcp 从系统 "wpos" 下载项目 "336" 的文件 "2069307013493440513"，project_id 和 file_id 都必须按字符串传。下载完成后返回 relative_path 和 absolute_path。
```

Upload a file to wpos:

```text
用 zh-file-mcp 把 "outputs/old.xlsx" 上传到系统 "wpos" 的项目 "336"，upload_name 用 "old.xlsx"，catalog_id 用 "目录ID"，name_strategy 用 1。
```

List files:

```text
用 zh-file-mcp 列出系统 "wpos" 项目 "336" 的目录 "目录ID" 下的文件。
```

Get metadata:

```text
用 zh-file-mcp 查询系统 "wpos" 项目 "336" 的文件 "2069307013493440513" 的信息。
```

## Upload Filename

`upload_file` uses the local filename by default. To force the filename stored by the target system, pass `upload_name`:

```json
{
  "system": "wpos",
  "project_id": "336",
  "file_path": "outputs/old20260623141153.xlsx",
  "upload_name": "old.xlsx",
  "catalog_id": "1234567890123456789",
  "name_strategy": 1
}
```

For wpos, `name_strategy` is handled by wpos:

- `1`: overwrite
- `2`: coexist with a generated name when there is a duplicate
- `3`: fail on duplicate

## Large IDs

Many business IDs are larger than JavaScript's safe integer range. Always pass large IDs as strings:

```json
{
  "system": "wpos",
  "project_id": "336",
  "file_id": "2069307013493440513"
}
```

## Auth Types

Supported auth configs:

```json
{ "type": "cookie", "cookie_name": "tk", "token_env": "AUTH_TOKEN" }
```

```json
{ "type": "bearer", "token_env": "OTHER_TOKEN" }
```

```json
{ "type": "header", "header_name": "token", "token_env": "AUTH_TOKEN" }
```

```json
{
  "type": "headers",
  "headers": {
    "Cookie": "${WPOS_COOKIE}",
    "X-Tenant": "${TENANT_ID}"
  }
}
```

```json
{ "type": "none" }
```

## Template Variables

System configs can use:

- `$system`
- `$file_id`
- `$project_id`
- `$catalog_id`
- `$parent_id`
- `$upload_name`
- `$name_strategy`
- `$extra.xxx`
- `${ENV_NAME}`

## Build Wheel

```bash
cd /Users/linchuanke/lck/zhonghui/zh-file-mcp
source .venv/bin/activate
pip install build
rm -rf build dist src/zh_file_mcp.egg-info
python -m build --wheel
```

Install the generated wheel into the image that runs stdio MCP.
