mcpField
H
Handoff: Send Files to Users & Agents

Handoff: Send Files to Users & Agents

远程服务
hand-off.space文件与存储04 天前更新

关于 Handoff: Send Files to Users & Agents

Handoff 是面向 AI Agent 的托管文件分享 MCP 服务和 REST API,可将文件交给用户或其他 Agent,并通过链接控制访问。链接支持有效期、打开次数、审批、指定 Agent、撤销和访问日志。

主要功能

  1. 01创建文件分享链接
  2. 02设置有效期和打开次数
  3. 03限制指定 Agent 访问
  4. 04审批后开放文件
  5. 05撤销链接并查看访问日志
  6. 06保存、列出和删除文件

适用场景

  1. 01向用户交付报告或文件
  2. 02在两个 Agent 间传递文件
  3. 03审批后再向接收方开放文件
  4. 04撤销链接并检查访问记录

MCP 相关

远程 MCP 服务通过 Streamable HTTP 暴露文件保存、分享、审批、状态查询、撤销和访问日志等工具。首次调用可免密分享文件并创建账户;后续管理操作使用 API 密钥。

配置

远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。

服务地址https://hand-off.space/mcp
一键复制安装命令
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。

全部服务地址
Streamable HTTPhttps://hand-off.space/mcp需要授权

工具

详细介绍

Handoff 标志

Handoff:面向 AI Agent 的文件共享

通过受控共享链接,将文件从 AI Agent 发送给用户或其他 Agent:可设置过期时间、最大打开次数、人工审批、仅限 Agent 访问,并支持撤销和访问日志。远程 MCP 服务 + REST API,无需人工注册。

Handoff 为 Agent 提供了一种安全的方式,可将文件交给其他人,无论对方是人还是其他 Agent。一次调用(通过 MCP 调用 share_file,或调用 POST /v1/share)即可返回下载链接,无需 API 密钥。 如需更多控制,Agent 可以先私下保存文件,再根据需要创建共享链接并设置规则:过期时间、最大打开次数、可选的人工审批步骤,以及指定的接收 Agent。Agent 可以随时查看状态、撤销链接并读取访问日志。

  • 远程 MCP 服务: https://hand-off.space/mcp(Streamable HTTP)
  • REST API: https://hand-off.space/v1(OpenAPI、llms.txt)
  • 身份验证: 首次调用无需身份验证。无需密钥调用 share_file / POST /v1/share 会创建账户,并仅返回一次 api_key。后续调用需发送 Authorization: Bearer <api_key>(如果客户端无法设置请求头,也可将 api_key 作为工具参数传入)。你也可以单独通过 signup / POST /v1/signup 获取密钥。无需邮箱、银行卡或人工账户。
  • 14 个 MCP 工具: share_file、signup、save_file、list_files、create_share_link、get_share_status、approve_share、deny_share、revoke_share、get_access_log、fetch_shared_file、delete_file、list_shares、update_share。initialize 和 tools/list 无需密钥。
  • 注册表名称: io.github.jueluddinsf/handoff

此代码仓库包含文档和目录列表元数据。该服务托管在云端,因此无需安装任何内容。

适用于 Agent 需要……

  • 向用户发送报告。 Agent 保存 report.pdf,然后发送一个 24 小时后过期且最多打开 3 次的链接。
  • 将文件交给另一个 Agent。 只有指定的接收 Agent 出示自己的密钥后,才能打开链接。
  • 等待人工审批后再发布文件。 链接会保持锁定状态(pending_approval),直到所有者批准。
  • 撤回已发送的内容。 撤销链接,并查看所有成功和被拒绝的打开记录。

Agent 常问的问题

  • Agent 如何向用户发送文件(PDF、CSV、报告、图片)? 调用带有 name 和 content_text(或 content_base64)的 share_file,或调用 POST /v1/share,然后将返回的 url 发给用户。用户可在浏览器中打开链接。下载无需账户。
  • 如何获取临时下载链接或设置链接过期时间? share_file 生成的链接默认在 7 天后过期。可在 share_file 或 create_share_link 中设置 expires_in_hours 和 max_opens。之后访问链接会返回 410 expired 或 429 limit。
  • 如何在两个 Agent 之间传输文件? 将 audience 设为 "agent",并填写接收方的 agent_id。只有该 Agent 的密钥才能通过 fetch_shared_file 或普通的 GET 打开文件。
  • 文件发布前能否由人工审批? 可以。将 requires_approval: true 设为启用。调用 approve_share 之前,文件无法打开。
  • 能否撤销链接或查看是谁打开了链接? 可以。使用 revoke_share 和 get_access_log。被拒绝的打开请求也会记录在日志中。
  • 这是公共文件托管服务或粘贴板吗? 不是。文件默认是私有的,每个链接都是由你控制的明确授权。

指南

快速开始:一次调用

REST,原始字节。 响应是 URL;如果此次调用创建了账户,则会在第二行返回 api_key: hf_…:

curl -s --data-binary @report.pdf "https://hand-off.space/v1/share?name=report.pdf&format=url"
# https://hand-off.space/g/…
# api_key: hf_…

REST,JSON:

curl -s -X POST https://hand-off.space/v1/share -H 'content-type: application/json' \
  -d '{"name":"notes.md","content_text":"# Notes","expires_in_hours":24,"max_opens":3}'
# → {"url":"https://hand-off.space/g/…","expires_at":"…","max_opens":3,"requires_approval":false,
#    "file_id":"…","grant_id":"…","token_prefix":"…","next":{…},"api_key":"hf_…"}

MCP。 无需身份验证,连接到 https://hand-off.space/mcp,然后调用:

{"name": "share_file", "arguments": {"name": "notes.md", "content_text": "# Notes"}}

结果包含 url、expires_at(默认 7 天)、grant_id、file_id,以及新账户的一次性 api_key。将 url 提供给接收者,对方可以通过普通的 GET 下载。请保存 api_key:撤销链接、查看状态或读取访问日志时都需要它。后续调用时,请通过 Authorization: Bearer <api_key>(或 api_key 参数)发送它,这样新文件就会保存在同一账户中。

share_file 和 POST /v1/share 还接受 expires_in_hours、max_opens、audience(anyone_with_link 或 agent)、audience_value、requires_approval、mime 和可选的 ref 标签。对于原始字节,请将这些参数作为查询参数传递。

更多控制:REST(3 次调用)

如果你想只存储一次文件,并为其创建多个具有不同规则的链接,请使用此方式。

BASE=https://hand-off.space

# 1. Sign up. The key is shown once, so store it.
curl -s -X POST $BASE/v1/signup -H 'content-type: application/json' -d '{"agent_id":"my-agent"}'
# → {"account_id":"…","api_key":"hf_…","agent_id":"my-agent","caps":{…},"next":…}
export HANDOFF_API_KEY=hf_...

# 2. Save a file privately (content_text, or content_base64 for binary)
curl -s -X POST $BASE/v1/files -H "authorization: Bearer $HANDOFF_API_KEY" -H 'content-type: application/json' \
  -d '{"name":"report.md","mime":"text/markdown","content_text":"# Q3 report"}'
# → {"id":"FILE_ID","name":"report.md",…}

# 3. Create a share link
curl -s -X POST $BASE/v1/files/FILE_ID/grants -H "authorization: Bearer $HANDOFF_API_KEY" -H 'content-type: application/json' \
  -d '{"audience":"anyone_with_link","expires_in_hours":24,"max_opens":3}'
# → {"grant_id":"…","url":"https://hand-off.space/g/…","token":"…","token_prefix":"…"}

更多控制:MCP(3 次工具调用)

  1. 将客户端连接到 https://hand-off.space/mcp(配置见下文)。
  2. 使用 signup MCP 工具获取密钥(无需密钥),或调用 POST /v1/signup。将密钥放入客户端的 Authorization: Bearer … 标头并重新连接,或在每次调用时传递 api_key。
  3. 调用 save_file → create_share_link,然后将返回的 url 交给接收者。
工具
工具功能
share_file一次调用。 提供 name 加上 content_text 或 content_base64。可选参数:mime、expires_in_hours(默认 168)、max_opens、audience、audience_value、requires_approval、ref。返回 url、expires_at、grant_id、file_id;如果未发送密钥,还会一次性返回 api_key。无需密钥。
signup创建账户并一次性返回 API 密钥。无需密钥。可选参数:agent_id。
save_file私密保存文件:name、content_text 或 content_base64,以及可选的 mime。返回文件 ID。不会创建链接。
list_files按从新到旧的顺序列出你的文件。
create_share_link提供 file_id、audience(anyone_with_link 或 agent),以及可选的 audience_value(接收者的 agent_id)、expires_in_hours(默认 168,即 7 天)、max_opens、requires_approval。返回 grant_id、url(仅显示一次)、expires_at 和 max_opens。
get_share_status查看链接的审批、过期、撤销和 open_count 状态,不会消耗可打开次数。
approve_share批准使用 requires_approval 创建的链接。此操作成功前,链接无法打开。
deny_share拒绝等待审批的链接。该链接将继续被阻止。
revoke_share永久撤销链接。文件会保留。
get_access_log获取链接最近最多 1,000 次打开和拒绝记录。
fetch_shared_file从 Handoff 分享链接 url 或令牌下载文件(遵循过期时间、打开次数限制、审批状态和 Agent 受众限制)。不超过 1 MB 的文件会以内联的 content_base64 返回(文本文件还会返回 content_text);较大的文件会返回错误,提示你对该 URL 执行 GET。
delete_file删除你拥有的文件。文件字节会被移除,现有分享链接也会停止工作。
list_shares列出你拥有的链接,可选按一个 file_id 筛选:grant_id、状态、open_count、max_opens、expires_at、受众。不返回令牌或 URL。
update_share设置链接的过期时间:grant_id、从现在起计算的 expires_in_hours(例如,168 表示 7 天)。

除 share_file、signup 和 fetch_shared_file(针对 anyone_with_link 分享)之外,所有工具都需要你的 API 密钥。未提供密钥时,share_file 会创建一个新账户。

客户端配置

你可以完全不带标头进行连接并调用 share_file,然后保存其返回的 api_key。如需添加密钥,请在下方配置中将 YOUR_HANDOFF_API_KEY 替换为你的密钥,或使用所示的环境变量形式。

Claude Code
claude mcp add --transport http handoff https://hand-off.space/mcp \
  --header "Authorization: Bearer YOUR_HANDOFF_API_KEY"

你也可以提交项目级 .mcp.json,本仓库中的文件就是如此。Claude Code 会从环境变量中展开 ${HANDOFF_API_KEY}:

{ "mcpServers": { "handoff": { "type": "http", "url": "https://hand-off.space/mcp",
  "headers": { "Authorization": "Bearer ${HANDOFF_API_KEY}" } } } }
Claude Desktop

Claude Desktop 自定义连接器不支持静态请求头,因此可在 claude_desktop_config.json 中通过 mcp-remote 桥接:

{
  "mcpServers": {
    "handoff": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://hand-off.space/mcp",
               "--header", "Authorization:${HANDOFF_AUTH}"],
      "env": { "HANDOFF_AUTH": "Bearer YOUR_HANDOFF_API_KEY" }
    }
  }
}
Cursor(~/.cursor/mcp.json 或 .cursor/mcp.json)
{
  "mcpServers": {
    "handoff": {
      "url": "https://hand-off.space/mcp",
      "headers": { "Authorization": "Bearer ${env:HANDOFF_API_KEY}" }
    }
  }
}
VS Code / GitHub Copilot(.vscode/mcp.json)
{
  "inputs": [
    { "type": "promptString", "id": "handoff_api_key", "description": "Handoff API key", "password": true }
  ],
  "servers": {
    "handoff": {
      "type": "http",
      "url": "https://hand-off.space/mcp",
      "headers": { "Authorization": "Bearer ${input:handoff_api_key}" }
    }
  }
}
Cline(cline_mcp_settings.json)

请明确设置 "type": "streamableHttp"。如果省略此项,Cline 会回退到旧版 SSE。

{
  "mcpServers": {
    "handoff": {
      "type": "streamableHttp",
      "url": "https://hand-off.space/mcp",
      "headers": { "Authorization": "Bearer YOUR_HANDOFF_API_KEY" },
      "disabled": false,
      "autoApprove": []
    }
  }
}
Windsurf(~/.codeium/windsurf/mcp_config.json)
{
  "mcpServers": {
    "handoff": {
      "serverUrl": "https://hand-off.space/mcp",
      "headers": { "Authorization": "Bearer ${env:HANDOFF_API_KEY}" }
    }
  }
}
OpenAI Agents SDK(Python)
import asyncio, os
from agents import Agent, Runner
from agents.mcp import MCPServerStreamableHttp

async def main():
    async with MCPServerStreamableHttp(
        name="handoff",
        params={
            "url": "https://hand-off.space/mcp",
            "headers": {"Authorization": f"Bearer {os.environ['HANDOFF_API_KEY']}"},
        },
        cache_tools_list=True,
    ) as handoff:
        agent = Agent(
            name="Reporter",
            instructions="Write the report, save it with Handoff, and reply with a share link that expires in 24h.",
            mcp_servers=[handoff],
        )
        print((await Runner.run(agent, "Summarize Q3 sales into report.md and share it.")).final_output)

asyncio.run(main())
LangChain / LangGraph(langchain-mcp-adapters)
import os
from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain.agents import create_agent

client = MultiServerMCPClient({
    "handoff": {
        "transport": "streamable_http",
        "url": "https://hand-off.space/mcp",
        "headers": {"Authorization": f"Bearer {os.environ['HANDOFF_API_KEY']}"},
    }
})
tools = await client.get_tools()
agent = create_agent("openai:gpt-4.1", tools)  # or langgraph.prebuilt.create_react_agent
Hermes Agent(~/.hermes/config.yaml)
mcp_servers:
  handoff:
    url: "https://hand-off.space/mcp"
    headers:
      Authorization: "Bearer YOUR_HANDOFF_API_KEY"
OpenClaw(~/.openclaw/openclaw.json)

请明确设置 transport,因为 OpenClaw 默认使用 SSE。开始时请省略 headers,以便使用 share_file。

{ "mcp": { "servers": { "handoff": {
  "url": "https://hand-off.space/mcp",
  "transport": "streamable-http",
  "headers": { "Authorization": "Bearer ${HANDOFF_API_KEY}" } } } } }
其他 MCP 客户端
设置值
URLhttps://hand-off.space/mcp
传输方式Streamable HTTP(无状态,仅 POST)
请求头Authorization: Bearer <api_key>

llms-install.md 中提供了面向 Agent 的分步设置说明。

Agent Skill(无需 MCP)

本仓库还提供了一个 Agent Skill,可教会任何支持 Skill 的 Agent(Claude Code、Codex、Copilot、Cursor 等)使用 REST API:

npx skills add jueluddinsf/handoff-mcp

与 Grok Bot 配合使用

添加 Handoff 作为自定义 MCP 连接器:

设置值
URLhttps://hand-off.space/mcp
请求头初始无需设置;之后设置为 Authorization: Bearer <api_key>

Bot 无需密钥即可立即调用 share_file。保存它返回的 api_key(只显示一次),然后将其填入请求头并重新连接;或者将其作为 api_key 工具参数传入。

也可以让 Bot 按照 skills/handoff/SKILL.md 的说明,通过普通 HTTP 调用 REST API。

提示词示例:

  • 将这份报告保存到 Handoff,并发送一个 24 小时后过期的链接给我。
  • 只与我的另一个 Agent 共享此文件。
  • 告诉我谁打开了该链接,然后撤销它。

使用示例

Agent → 人类报告,一次调用

share_file(name="report.md", content_text=…, expires_in_hours=24, max_opens=3) → 发送 url。

Agent → 人类报告,设置过期时间(三步)

save_file(report.pdf) → create_share_link(audience="anyone_with_link", expires_in_hours=24, max_opens=3) → 发送 url。使用 get_access_log 确认文件已被打开。

Agent → Agent 移交

Agent A 调用 share_file(name=…, content_text=…, audience="agent", audience_value="agent-b");如果文件已保存,则调用 create_share_link(audience="agent", audience_value="agent-b")。Agent B 使用自己的密钥下载:

curl -L -H "authorization: Bearer $AGENT_B_KEY" -o out.bin "$URL"

通过 MCP,Agent B 也可以调用 fetch_shared_file(url_or_token=URL)。其他任何调用方都会收到 401 {"error":"unauthorized",…}。

人工审批关卡

调用 share_file(..., requires_approval=true) 或 create_share_link(..., requires_approval=true)。在所有者批准之前,打开链接会返回 403 {"error":"pending_approval",…}。如需批准或拒绝,请调用 approve_share / deny_share MCP 工具,或:

curl -X POST -H "authorization: Bearer $HANDOFF_API_KEY" $BASE/v1/grants/GRANT_ID/approve   # or /deny

限制(免费、未认领的账户)

  • 总容量 100 MB,最多 50 个文件,单个文件不超过 10 MB,每天最多成功打开 200 次。
  • 允许的文件类型包括文本、Markdown、HTML、代码、CSV、JSON、PDF、图片、Office 文档和 zip 压缩包。
  • 不允许上传可执行文件。
  • Slack、X、Discord 等平台的链接预览抓取不会计入打开次数。
  • 注册按 IP 限流。
下载响应
状态错误含义
410expired链接已过期。
410limit链接已达到最大打开次数。
429limit账户已达到每日上限。
403revoked / denied / pending_approval已撤销、已拒绝或仍在等待批准。
401unauthorized此链接属于其他 Agent。

安全模型

  • 文件默认设为私密。每次分享都是一项拥有独立令牌的明确授权。
  • 下载内容以 application/octet-stream 附件形式提供,并设置 Content-Security-Policy: sandbox 和 nosniff。
  • 每次尝试,无论成功还是被拒绝,都会记录日志。
  • API 密钥以哈希形式存储,且仅显示一次。

请私下报告安全问题(参见 CONTRIBUTING.md)。

许可证

MIT。此许可证适用于本仓库中的文档和示例。托管服务由 Juel Uddin 运营。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。