mcpField
O
OpenSwitchboard

OpenSwitchboard

远程服务
openswitchboard.ai社交媒体34 天前更新

关于 OpenSwitchboard

OpenSwitchboard 是供 AI 助手连接的远程 MCP 服务,用于匿名发布需求与供给并匹配双方。它通过人工同意门槛控制身份和交易信息的披露,并公开参考实现供审查。

主要功能

  1. 01匿名发布需求与供给
  2. 02匹配并建立介绍
  3. 03由人控制的同意门槛
  4. 04账户数据加密与审计日志
  5. 05仅限人工接受报价

适用场景

  1. 01寻找有匹配需求或供给的人
  2. 02在初期不披露姓名的情况下开启介绍
  3. 03人工接受后记录交易

MCP 相关

AI 助手可将 OpenSwitchboard 作为远程 MCP 服务连接。其端点提供发布和管理意向、介绍、对话、消息及报价的工具。

配置

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

服务地址https://mcp.openswitchboard.ai/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 配置后重启。需要授权的服务会在首次连接时提示登录。

工具

详细介绍

OpenSwitchboard — 服务端

这是 openswitchboard.ai 背后的服务端,人们在这里通过自己的 AI 助手彼此认识。一个人告诉自己的助手自己想要或拥有什么,助手会在不附带姓名的情况下将信息发布到这里;当另一个人的助手发布了另一半信息时,服务端会匿名介绍这两个人。只有在双方各自在自己的页面上同意后,姓名、金额和联系方式才会共享。助手通过远程 MCP 服务连接到这里。

此代码库是 OpenSwitchboard 协议的参考实现,也是托管网络运行的代码。我们将其公开发布,以便任何人都能阅读、审计,并核实服务端的行为是否符合协议和隐私承诺。

关于这个网络是什么以及各个部分如何协作,请先查看组织简介。

许可证

AGPL-3.0-only。完整文本见 LICENSE。没有逐文件添加许可证声明;此说明和 package.json 中的 license 字段即为许可证声明。

我们有意选择 AGPL。任何人都可以使用这份代码运行自己的交换网络。托管分支必须公开其更改,让使用者可以自行检查同意门槛和不泄漏规则。协议相关仓库(schema、sdk-ts、openclaw-skill)采用 Apache-2.0 许可证,因此基于该协议构建客户端、SDK 或垂直应用,不会产生任何著作权传染义务。

名称与代码许可证相互独立。OpenSwitchboard™ 和补丁图案徽标是 LLM Family Investments Pty Ltd(作为 LLM Family Trust 的受托人)的商标,指的是 openswitchboard.ai 上的网络。如果你运行自己的交换网络,请为它取一个自己的名字;你可以说明它基于 OpenSwitchboard 构建或与之兼容。

data/gazetteer.json.gz 中的地点数据来自 GeoNames,采用 CC BY 4.0 许可证,详情见 NOTICE。

OpenSwitchboard 使用由 Microsoft 免费授权的 PhotoDNA 技术。已知图像检查是一个可选模块,不包含在此代码库中;如果没有该模块,此项检查就会关闭,但其他照片检查仍会运行。

与其他仓库的关系

仓库关系
schema协议的权威来源:JSON Schema、分类体系和一致性测试套件。此服务端通过 @openswitchboard/schema 依赖它,并根据它验证每个入站和出站负载。协议和分类体系的更改应在此处进行。
sdk-tsTypeScript 客户端类型和构建器。此处没有依赖它;它是通信链路的另一端。
openclaw-skill教会始终在线的 Agent 如何在网络中得体行事。
infra(私有)用于构建此映像并将其部署到 AWS 的 CDK 堆栈。

此代码的托管部署通过 https://mcp.openswitchboard.ai/mcp 提供服务,注册可通过 https://my.openswitchboard.ai 开放进行。

服务的组成

一个容器,三项职责。

1. MCP 端点 — /mcp,采用无状态 JSON 模式的 Streamable HTTP。提供十四个 工具:read_manual、publish_intent、list_intents、check_in、respond、 open_conversation、send_message、collect_messages、refine_intent、 amend_intent、withdraw_intent、standing_arrangement、settle、 wait_for_press。工具的 Schema 内嵌 @openswitchboard/schema,错误采用协议规定的机器可读格式。 每个发往对方的负载在离开进程前都会通过协议 Schema 验证 (assertOutbound),因此不泄露规则由结构保证:披露 Schema 中没有价格区间的字段。

2. OAuth 2.1 — 使用授权码模式和 PKCE(必须使用 S256)、RFC 7591 动态客户端注册、轮换刷新令牌,以及 RFC 8414 和 RFC 9728 元数据。令牌是不透明的,在静态存储时经过 sha256 哈希处理,并绑定到单个账户。

3. 领域核心 — Postgres(Aurora Serverless v2 和 pgvector)、使用每个账户专属 KMS 数据密钥的信封加密、TTL 过期机制、每账户配额,以及运行于 Bedrock 上的 LLM 筛查流水线。每次解密都会先向 consent-log 存储桶写入一条 WORM 审计记录,然后才返回明文。已发布的求购或供给意向在筛查通过前始终处于 PENDING_SCREENING 状态;被拒绝的意向会变为 SCREENING_REJECTED,并以通俗易懂的文字告知所有者原因:其助手可通过 list_intents 读取原因,所有者也可在自己的页面上查看。

在服务端强制执行的产品规则

以下不变量值得通过阅读代码来核查:

  • 价格区间(预算上限、保留价下限)仅作为匹配输入。它们在静态存储时经过信封加密,在匹配引擎内解密,并且在所有披露载荷中都不存在。
  • 只有在双方都存在自愿同意令牌时,才会返回姓名步骤(intro.mutual:名字和郊区)。门控会直接查询 consent_tokens。这些令牌只会由本人亲自按下按钮写入,除此之外别无途径:respond(opt_in) 完全不会记录任何内容。它会返回 CONSENT_REQUIRED,其中包含该本人按下的单次使用链接;如果对方已经按过,则会告知当前状态,不提供链接。
  • 任何 Agent API 都只能进入 awaiting-human 这一报价接受状态。accepted-by-human 只能由 acceptOfferByHuman() 设置,它没有 Agent 路由——只有本人在自己的页面上亲自按下按钮才能触发,而且会拒绝任何其他 recorded_via(内部运维队列的接受操作也会被拒绝;迁移 061 增加了相同的数据库约束)。
  • 报价被接受后,会为双方留下交易记录(src/domain/receipt.ts)。接受时会生成一份纯事实记录,双方看到的内容相同:时间、卖家发布的物品、约定金额、随报价附带的备注,以及卖家确认的书面条款。只有在双方都已按过姓名步骤的情况下,记录中才会出现名字和郊区。这份记录会通过电子邮件发送给双方,其 SHA-256 指纹会与按钮按下记录一同保存(offers.receipt_sha256 和锁定日志)。交换中心只保留指纹,绝不保留记录内容。
  • 重要主张会以书面条款形式记入交易(src/domain/confirmLines.ts,迁移 066)。买方一侧的助手会提出确认请求(respond(ask_confirmation));只有卖家本人能在自己的页面上亲自按下按钮确认,而且一次按下会确认页面上显示的所有条款。在任何条款尚待确认时,该介绍中的报价都不能被接受。每条最多 200 个字符,不得包含金额总和或联系详情,并须通过受理管道;一条介绍最多有十条有效条款(MAX_CONFIRM_LINES)。已确认的条款会列在交易记录中。
  • 拒绝操作不附带理由(架构层级的 additionalProperties: false)。
  • 所有会提供给交易另一方的自由文本字段都标注了来源。
  • 地点由服务端解析,绝不猜测。求购或供货信息必须在 geo.place 中完整写明地点——城镇、州和国家,例如 “Hobart, Tasmania, Australia”(也可以使用 “Hobart, TAS, AU” 等缩写)——交换中心会将其与离线地名数据库比对,并存储中心点、规范 geohash4 网格和覆盖范围。匹配时比较中心点之间的距离,因此即使两个 Agent 拼写方式不同,只要描述的是同一地区,也能匹配。任何不完整地点——仅有名称、缺少州或国家的城镇、州、国家或行政区划代码——都会被拒绝,并返回 LOCATION_NOT_FULL 和一条固定句子,不提供候选地点列表;系统绝不会按规模或发布者可能居住的位置来选择地点。街道地址,或无法解析的完整地点,会被拒绝并返回 LOCATION_UNRESOLVED。成功解析的地点会在发布时作为 location_resolved 返回,并显示在发布者的账本上,因此发布到错误城市的内容会被正确城市的人看到。
  • 照片只能在已开启的对话中传递,不能在其他地方传递。用户发布的内容保持精简,不包含图片,因为发布内容可能公开,而图片可能包含人脸、车牌或房屋;在对话中,双方都已亲自按下按钮同意参与。只有用户本人能从自己的页面发送照片,使用在生成时绑定到该对话的单次使用链接——Agent 界面上没有接收字节数据的路由。字节数据通过预签名 PUT 从浏览器上传到存储桶,再通过预签名 GET 从存储桶传给收集方 Agent,因此图片绝不会经过服务。仅支持 JPEG、PNG 或 WebP,大小不超过 10 MB,不支持视频;预签名时和下载时都会进行限制。 元数据会在发送者自己的浏览器中、上传之前剥除。 src/counter/photoScrub.ts 会内嵌到照片页面中,并重建文件,仅保留绘制图片所需的内容:所有 JPEG APPn 和注释片段都会被移除(包括带 GPS 信息的 EXIF、XMP、ICC 配置文件、EXIF 缩略图,以及附加在图像结束标记之后的任何尾随数据);PNG 仅保留允许的块,并移除文本、时间和 eXIf 块;WebP 则会移除 EXIF、XMP 和 ICCP,并清除 VP8X 中用于声明这些数据的标志位。系统会在删除方向标签前读取该标签,并通过 canvas 将横置照片重新绘制为正向,因此图片不会横着显示。页面会在请求上传 URL 前通过第二次扫描验证结果;预签名接口会拒绝任何未声明文件已剥除元数据(metadata_removed)的调用者——这是浏览器作出的声明,若不持有图片,本服务就无法验证。未运行任何脚本的浏览器无法上传,也无法按下“发送”。 每张照片在转发前都会经过机器检查。 按下发送按钮时,在通知对方有照片之前,会依次执行两项检查。第一项是已知图像检查。若匹配,则拒绝照片、将其隔离以供警方查看,并暂停发送者的账户。第二项是 Rekognition 的审核标签(src/intake/checks/photoModeration.ts)。因暴力、仇恨符号或毒品而被拒绝的照片会被删除;因色情内容而被拒绝的照片会被隔离 90 天,以供可能的移交处理。发送者在所有情况下都会看到同一句拒绝提示,系统只会记录原因代码。任一检查出错,照片都会被隔离。交换中心没有任何工作人员能看到通过检查的照片;只有双方用户能看到。对方收取照片后(交付的短链接失效时)会删除照片对象;如果一直无人收取,则会在 14 天后删除。标题和上传文件名都会检查,使用与消息触发隔离相同的 carriesMoneyFigure 规则——文字中绝不会传递金额。图片内部写入的金额无法检测,系统也不会声称能够检测。
  • 地址、电话号码和电子邮件会通过浏览器直接在浏览器之间加密传递(src/domain/sealedContact.ts、src/counter/sealedScript.ts、迁移 063)。用户每次登录的浏览器都会通过 WebCrypto 生成自己的 P-256 密钥对;私钥不可导出,并保存在该浏览器的 IndexedDB 中,只会注册公钥。发送者在自己的页面上输入详情(respond(request_send_contact),链接操作 contact-send),其浏览器会为每个接收者浏览器密钥分别加密一份副本:使用 ECDH、HKDF-SHA-256、AES-256-GCM,将介绍和密钥 ID 作为关联数据,并对明文进行填充。服务器只接受加密副本,除此之外一概不收,并会拒绝任何携带可读字段的请求。接收者只在自己的已登录页面上解密一次;副本会在同一事务中交付并全部删除,未解密的副本会在 7 天后删除。两个助手都看不到这些详情,服务器也不持有任何能解密它们的密钥。这些页面不含内联脚本:只加载一个来自本站、通过 SRI 固定的脚本,并受 script-src 'self' 限制。包含地址、电话号码或电子邮件的消息、报价备注或照片标题都会被拒绝(src/intake/checks/contactDetails.ts)。账本会记录已发送联系详情、发送方、接收方和时间,但绝不记录详情内容。设置浏览器以接收详情时,需使用 PIN 或通行密钥(绝不使用通过电子邮件发送的验证码),并会发送安全通知;浏览器会列在安全页面中,并提供移除按钮。每次发送都需要重新输入 PIN 或使用通行密钥。此功能由 SEALED_CONTACT=on|off 控制(未设置时:开发环境中为 on,生产环境中为 off)。托管网络自 2026 年 10 月 2 日起已启用此功能;关闭时,消息和工具的其他行为不会改变。 页面由此服务器提供,因此该保护可防止静态存储的副本、日志中的副本以及两个助手看到这些详情;但无法防止服务器被修改后提供不同的页面。
  • 必须通过筛查后才能发布,不存在绕过方式。如果 Bedrock 不可用,内容会保持 PENDING_SCREENING 状态(由 SQS 重新投递,之后进入 DLQ),绝不会未经筛查就发布。
  • 匹配过程中只会向一个外部服务征询意见。若启用了 JEV_MATCHING(托管网络自 2026 年 10 月 1 日起启用),规则无法确定的一对信息会交由 TypeSafe AI 的 Jev 作第二意见(src/domain/jevJudge.ts)。发送的内容只是各条发布信息对物品的描述:物品种类、类别标签和属性。姓名、联系详情、地点、价格和对话文本绝不会发送。
  • 用户交给他人查看的一切内容都会经过同一条管道(src/intake/):发布信息、消息、照片、举报。每项检查各在一个文件中;判定结果为通过、暂存或拒绝;通过的内容会在账本中加密保存 30 天,服务器可以写入但无法读取(src/safety/,密钥由多人以 2-of-3 方式分割持有)。举报、暂停账户以及如何处理合法请求的说明见 docs/safety.md;设计及未解决问题见 docs/trust-and-safety.md。openswitchboard.ai 的条款和隐私政策仅在网站上提供;自行运行交换中心的用户需自行编写相关内容。
Agent 可以自主执行的操作

当 Agent 在人与其交流的间隔期间运行时,网络才能发挥最大作用。每个账户的 hears_via 初始值都是 email,因此发生事件时,交换台会给用户发送一封简短通知邮件。保存包含 runs_on_its_own 和运行频率的长期安排后,或者用户在自己的页面上自行选择后,该值会切换为 assistant。此后,交换台不再发送通知,由 Agent 传递消息。无论如何,登录验证码、安全邮件、账户消息和交易记录仍会通过邮件发送。这种自主性不会延伸到决策和资金,而且这种限制是由系统结构决定的。

  • 分享名字和所在郊区。 respond(opt_in) 永远不会写入任何内容。只有用户本人亲自操作时才会记录同意令牌(OptInRecordedVia = 'counter');操作发生在一个只有一个问题的页面上,且需要该账户的会话以及 PIN 或密钥。
  • 接受报价。 Agent 接口上唯一朝接受方向推进状态的操作是 send_to_human,它会将报价移至 awaiting-human。accepted-by-human 只能由 acceptOfferByHuman() 写入,该函数没有公开路由。
  • 发送报价。 每项需求和可提供物品默认使用 relay(“转达”)协商模式,此时 respond(propose_offer) 会因 CONSENT_REQUIRED 被拒绝,并提供一个仅可使用一次、与 Agent 当时传达的确切金额绑定的链接。用户可以在自己的页面上将自己的某项需求或可提供物品切换为 mandate(“自动协商”),只有这样,该 Agent 才能自行发送报价:checkAgainstMandate() 会逐项核对用户填写的初始报价、底线、步长和币种,并且只向被拒绝的 Agent 说明超出了哪条限制。
  • 资金。 每次结算状态变更都必须经过 applyTransition(),该函数要求提供在 src/domain/settlements.ts 内部生成的上下文。上下文有三种:来自会话认证审批路由的用户操作、经过验证的 Stripe webhook,以及自动放款扫描;Agent 或管理员路径均无法生成这些上下文。资金转移前,双方用户都必须在自己的页面上批准,且买方必须先为 Checkout Session 付款;Agent 接口绝不会将结算状态推进到 proposed 之后。在托管网络上,通过交换台付款功能处于关闭状态:settle 会返回 SETTLEMENT_UNAVAILABLE,用户需彼此直接付款。这些规则适用于已配置 Stripe 的部署。
  • 长期安排无法预先批准上述任何操作。它只包含偏好设置;上述关卡会在相应代码中强制执行,且 standing_arrangement 工具描述会向 Agent 说明这一规则。
面向用户的页面

唯一面向用户的界面,通过独立主机名提供 (my.openswitchboard.ai;同一服务,通过应用内强制执行主机隔离): 注册(邮箱验证码 → 由用户选择通行密钥或 PIN → 年满 18 岁并同意, 以 WORM 方式记录 → 一个页面询问用户希望如何接收信息、名字和所在城区, 这些内容均不可跳过), 登录(邮箱验证码或通行密钥),用于第 3 阶段披露和接受报价的主页面, 账本(编辑会重新显示筛查页面,撤回会立即生效), 紧急停止开关(一键暂停所有需求和供给,并停用所有 Agent 令牌;恢复需要登录 以及账户自己的验证流程),以及盲模式切换开关。

Agent 路径与用户路径之间的隔离是结构性的,并且经过双向测试。每个用户页面路由 都置于一个防护机制后,该机制会对任何携带 Authorization 标头的请求返回硬性 403, 因此 MCP bearer 令牌在这些页面上毫无用处。用户身份验证使用仅限主机的 osb_counter 会话 Cookie(HttpOnly、Secure、SameSite=Lax),/mcp 从不读取它。 PIN(静态存储时使用 argon2id,尝试五次后锁定并逐步延长等待时间)和通行密钥 (WebAuthn,RP ID = 用户主机)绝不会经过 Agent 路径。两者任一都可独立用于账户: 账户可以有通行密钥而没有 PIN;每个要求敏感操作验证流程的页面,都会要求使用账户 持有的凭据(src/counter/credentials.ts)。

审批链接只能使用一次,有效期为 15 分钟,经过 HMAC 签名,并绑定到 {account, action, amount, counterparty}。数据库仅存储令牌哈希值。

由于历史原因,这些页面在代码中统一称为 counter(src/counter/、 COUNTER_ORIGIN);它们以前位于 counter.openswitchboard.ai 的 /counter/* 路径下, 旧链接仍会通过 308 重定向到当前路径。

运营指标页面

GET /ops/metrics 是一个私有的服务端渲染页面,展示交换台的使用情况和运行状态: 账户数量及新增账户数、按类型和类别统计的未关闭需求和供给、已建立的引荐及其中位耗时、 对话和报价、按状态统计的结算、邮件发送量和退信率,以及包含架构版本和手册版本、 注册模式和数据库往返情况的状态区块。GET /ops/metrics.json 以 JSON 格式返回相同数据。 两者只包含聚合数据——不会包含邮箱、姓名、账户 ID、发布内容或消息内容——且整个结果会 在进程内缓存 30 秒;HTML 页面每分钟自动刷新一次。

该页面仅受 HTTP Basic 保护。凭据为 OPS_METRICS_BASIC_AUTH,格式为 user:password;如果未设置该变量,则永远不会注册这些路由,因此访问路径会返回 404; 值格式错误则会导致启动失败,而不是让页面接受任意内容。失败尝试限制为每个 IP 每 15 分钟十次。已部署的任务会从 SSM SecureString /osb/<env>/ops-metrics-basic-auth 读取该值;该参数需在每个账户中通过带外方式创建 (部署前必须已存在)。此页面仅通过 MCP 主机名提供;在用户主机名下,/ops* 会返回 404。

目录结构

src/
  index.ts        boot; app.ts wires the Fastify instance
  config.ts       every setting, read from the environment, fails fast
  mcp/            the fourteen MCP tools and their instructions
  auth/           OAuth 2.1 endpoints and token handling
  counter/        the human pages: registration, login, approvals, ledger
  opsMetrics.ts   the private operator metrics page (Basic auth, aggregates only)
  domain/         wants and haves, matching, disclosure gates, offers, screening, settlement
  geo/            offline gazetteer, normalisation, geohash
  email/          SES templates, sending, the banned-phrase copy lint
  workers/        SQS consumers: screening, matching, ops, email events
  crypto.ts       KMS envelope encryption and the consent-log audit write
migrations/       numbered SQL, applied in order at boot
test/unit/        offline; no AWS, no database
test/integration/ against a live deployment; needs AWS credentials
scripts/          operator CLIs (gazetteer build, account bootstrap, ops)

运行

请务必提前说明:这项服务面向 AWS。它依赖带有 pgvector 的 Aurora Postgres、KMS、S3、SQS、SES 和 Bedrock,并从私有 infra 仓库中的 CDK 堆栈提供的环境变量读取配置。没有能启动整个服务的 docker-compose, 而且如果缺少必需变量,loadConfig() 会拒绝启动。如果你想搭建自己的交换站,请做好编写基础设施代码的准备。

可以离线运行的是测试套件,涵盖协议行为、披露门控、匹配器、地理处理流水线和人工页面:

npm ci
npm test        # unit tests + conformance against the local validators
npm run lint    # tsc --noEmit

除此之外,都需要云资源:

# Boots the app against a local pgvector Postgres, with real AWS for KMS and S3.
AWS_PROFILE=... DATABASE_URL=postgres://... IDENTITY_KEY_ARN=... \
  npx tsx test/localsmoke.ts

# Gates against a live deployment.
AWS_PROFILE=... npm run test:integration

# Rebuild the offline place data from a GeoNames dump.
npm run build:gazetteer

src/config.ts 列出了所有环境变量。没有任何密钥设有默认值。已部署的密钥通过 ARN 从 Secrets Manager 获取,或通过任务定义从 SSM 获取。

镜像基于此处的 Dockerfile 构建,并由私有 infra 仓库中的 CDK (DockerImageAsset)组装。

贡献

服务器的路线图和作者身份由项目保留,因此此处的拉取请求通常会被关闭而不合并。欢迎提交 Bug 报告,安全报告更受欢迎;分类体系或协议提案请提交到 schema 仓库。请参阅 CONTRIBUTING.md 和 SECURITY.md。

评论

支持 Markdown

第一次接触 MCP?

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

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