mcpField
D
Doroseek

Doroseek

本地服务
github.com/junjieproAI 与智能体075 周前更新

关于 Doroseek

Doroseek 是基于 Deno 和 Fresh 的应用,可管理兼容 OpenAI 的端点与 API 密钥,也可作为 MCP 服务和代理。它还提供本地服务隧道、实时通信房间和小文件分享功能。

主要功能

  1. 01管理端点和 API 密钥
  2. 02为模型设置别名
  3. 03提供内置 MCP 服务
  4. 04代理其他 MCP 服务
  5. 05隧道转发本地服务并支持通信房间
  6. 06通过 URL 分享小文件

适用场景

  1. 01访问多个兼容 OpenAI 的端点
  2. 02让客户端连接其他 MCP 服务
  3. 03通过隧道公开本地 Web 服务
  4. 04分享小文件或启用房间消息通信

MCP 相关

Doroseek 提供内置 MCP 服务,也可代理其他 MCP 服务,并通过 SSE 路由建立连接。其 Agent Mode 可连接远程 Doroseek 实例以转发本地服务。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

暂未收录安装方式

我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。

代码仓库

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

Doroseek

使用 Deno 和 Fresh 构建的简单 AI 应用。

  1. 使用相同的基础 URL 和 API 密钥访问所有 OpenAI Compatible 端点。你也可以与他人共享 Doroseek API 密钥,以便他们访问这些端点。
  2. 作为 MCP 服务,内置多个服务。
  3. 作为 MCP 代理服务,连接到其他 MCP 服务。

主页

功能

  • OpenAI Compatible 端点
    • 管理端点和 API 密钥
    • 生成 Doroseek API 密钥
    • 为模型分配别名
    • 路由
      • 管理路由:/{key}
      • OpenAI Compatible 路由:/api
  • MCP SSE 服务
  • MCP 代理服务
    • 路由
      • stdio: /mcp/proxy/sse?apiKey={apiKey}&transport=stdio&command=&args=&env=
      • sse:/mcp/proxy/sse?apiKey={apiKey}&transport=sse&url=
    • 示例
      • Sequential Thinking: /mcp/proxy/sse?apiKey={apiKey}&transport=stdio&command=npx&args=-y @modelcontextprotocol/server-sequential-thinking&env={}

新的核心功能(基于 MCP)

Doroseek 现已包含多个强大的基于 MCP 的服务,可用于高级场景:

  1. **内网穿透(隧道):**将本地服务暴露到互联网。
  2. **多用户通信室:**支持多个客户端之间实时通信。
  3. **资源共享:**上传和共享小型文件或数据片段。

这些功能利用 WebSocket 实现实时通信,并在适用时使用 Deno KV 进行持久化。

1. 内网穿透(隧道)

概念: 此功能可让你通过与 Doroseek 实例建立的安全隧道,将私有网络中运行的服务(例如本地开发服务器、数据库或任何 TCP/HTTP 服务)暴露到公共互联网。

本地代理: 要使用此功能,必须在可访问私有服务的计算机上运行本地代理(客户端软件)。Doroseek 本身也可以运行在此“代理模式”下。有关如何将 Doroseek 配置并作为本地代理运行的详细信息,请参阅下文的代理模式部分。本地代理负责连接远程 Doroseek 实例(充当中继)、管理隧道,以及在中继与本地服务之间转发流量。

注册流程(代理到中继):

  1. **连接:**本地代理与 Doroseek MCP 服务建立 WebSocket 连接:

    wss://your-doroseek-instance/mcp/tunnel/register?apiKey=<your_api_key>
    

    注册时必须提供 API 密钥。

  2. **注册消息:**建立 WebSocket 连接后,代理会发送一条 register 消息,详细说明它希望暴露的服务。 代理发送的 register 消息示例:

    {
      "type": "register",
      "data": {
        "services": [
          { "type": "http", "local_port": 3000, "subdomain_or_path": "my-web-app" },
          { "type": "http", "local_port": 8080, "subdomain_or_path": "api-service" }
          // Other types like 'tcp' might be supported by the agent protocol in the future.
        ]
      }
    }
    
  3. **服务器响应:**注册成功后,Doroseek 会返回一条 registered 消息,其中包含唯一的 tunnelId 和用于访问隧道服务的公共基础 URL。 服务器发送的 registered 消息示例:

    {
      "type": "registered",
      "data": {
        "tunnelId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "public_base_url": "https://your-doroseek-instance/t/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
      }
    }
    

访问隧道服务: 隧道建立后,可通过公共基础 URL(public_base_url)以及注册时定义的 subdomain_or_path 拼接出的公共 URL 访问本地服务。例如,如果 your-doroseek-instance 为 example.com,且某服务注册时使用了 subdomain_or_path: 'my-web-app',则它可能可通过以下地址访问:

https://example.com/t/<tunnelId>/my-web-app/...

具体 URL 结构取决于公共路由(/t/:tunnelId/...)如何配置,以映射到特定服务。

本地代理职责(概要):

  • 发起并维持到 /mcp/tunnel/register 的 WebSocket 连接。
  • 发送包含服务定义的 register 消息。
  • 监听 Doroseek 通过 WebSocket 发送的 httpRequest 消息。每条 httpRequest 消息都包含:
    • requestId:请求的唯一 ID。
    • data:包含传入公共请求的 method、path、headers 和 body 的对象。
  • 收到 httpRequest 后,代理会向其本地服务发起相应请求(例如 http://localhost:3000/some/path)。
  • 本地服务响应后,代理会通过 WebSocket 向 Doroseek 发送 httpResponse 消息,其中包含原始 requestId 和响应详情(状态、标头、正文)。
  • (目前,Doroseek 面向公共网络的隧道路由中仅预留了通过隧道进行 WebSocket 代理的功能,计划在未来增强。)
2. 多用户通信房间

概念: 在多个客户端之间实现实时双向通信。可将其用作 Web 应用中实时聊天、协作编辑或其他多用户交互体验等功能的后端。

连接到房间: 客户端使用 WebSocket 连接到房间。roomId 在路径中指定。

  • WebSocket 端点:
    wss://your-doroseek-instance/mcp/room/:roomId?apiKey=<optional_api_key>
    
  • 身份验证:
    • **匿名访问:**目前,客户端无需 API 密钥即可连接。
    • **通过 API 密钥验证的访问:**如果在查询字符串中提供了 apiKey,系统会对其进行验证。这样便可在需要时将用户与 API 密钥所有者关联起来。

核心功能:

  • **加入房间:**用户成功建立与房间端点的 WebSocket 连接后,即加入房间。
    • 加入时,服务器会向该用户发送 ServerRoomInfoMessage,其中包含房间内现有用户的列表。
    • 房间内的其他用户会收到 ServerUserJoinedMessage。
  • **离开房间:**用户的 WebSocket 连接关闭时,该用户会自动从房间中移除。
    • 房间内的其他用户会收到 ServerUserLeftMessage。
  • **发送聊天消息:**客户端通过 WebSocket 发送聊天消息。 客户端发送的 ClientChatMessage 示例:
    {
      "type": "chatMessage",
      "payload": {
        "roomId": "your-target-room-id", // Though roomId is in path, can be in payload
        "message": "Hello everyone!"
      }
    }
    
  • **接收消息:**客户端监听服务器发送的消息。
    • ServerChatMessage:由房间内其他用户发送的聊天消息。
      {
        "type": "chatMessage",
        "payload": {
          "roomId": "the-room-id",
          "fromUserId": "user-id-of-sender",
          "message": "Hello everyone!",
          "timestamp": "2023-01-01T12:00:00.000Z"
        }
      }
      
    • ServerUserJoinedMessage:通知有新用户加入。
    • ServerUserLeftMessage:通知有用户离开。

客户端交互概念示例(JavaScript):

const roomId = "my-chat-room";
const apiKey = "your-optional-api-key"; // Or leave undefined for anonymous
const socket = new WebSocket(`wss://your-doroseek-instance/mcp/room/${roomId}?apiKey=${apiKey}`);

socket.onopen = () => {
  console.log("Connected to room:", roomId);
  // Send a chat message
  socket.send(JSON.stringify({
    type: "chatMessage",
    payload: { roomId, message: "Hi from client!" }
  }));
};

socket.onmessage = (event) => {
  const serverMessage = JSON.parse(event.data);
  console.log("Received message:", serverMessage);
  if (serverMessage.type === "chatMessage") {
    // Display chat: serverMessage.payload.fromUserId, serverMessage.payload.message
  } else if (serverMessage.type === "userJoined") {
    // Update user list
  } // etc.
};

socket.onclose = () => {
  console.log("Disconnected from room:", roomId);
};

socket.onerror = (error) => {
  console.error("WebSocket error:", error);
};
3. 资源共享

概念: 允许用户将小型文件或数据片段(例如配置文件、JSON 数据、小图片)上传到 Doroseek,并通过唯一的公开访问 URL 分享。

上传流程(MCP WebSocket):

  1. **端点:**通过 WebSocket 连接到 /mcp/fileshare/upload。

    wss://your-doroseek-instance/mcp/fileshare/upload?apiKey=<your_api_key>
    

    上传文件必须使用有效的 API 密钥。

  2. 消息流程:

    • 客户端 -> 服务端:ClientInitiateUploadMessage 客户端首先发送一条消息以启动上传,并提供文件元数据。
      {
        "type": "initiateUpload",
        "payload": {
          "filename": "config.json",
          "filetype": "application/json",
          "size": 1024 // Size in bytes
        }
      }
      
    • 服务端 -> 客户端:ServerUploadReadyMessage 如果服务端接受上传(例如,文件大小未超出限制),则会返回唯一的 resourceId。
      {
        "type": "uploadReady",
        "payload": {
          "resourceId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
        }
      }
      
    • 客户端 -> 服务端:ClientFileDataMessage 客户端发送实际文件数据,并使用 base64 编码。
      {
        "type": "fileData",
        "payload": {
          "resourceId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
          "data": "eyJrZXkiOiAidmFsdWUifQ==" // Base64 encoded content of the file
        }
      }
      
    • 服务端 -> 客户端:ServerUploadCompleteMessage 成功保存文件数据后,服务端会确认上传完成并提供下载 URL。
      {
        "type": "uploadComplete",
        "payload": {
          "resourceId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
          "downloadUrl": "https://your-doroseek-instance/shared/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
        }
      }
      

下载流程(HTTP GET):

  • **URL 格式:**可通过向以下地址发送简单的 HTTP GET 请求来下载文件:
    https://your-doroseek-instance/shared/:resourceId
    
  • **身份验证:**默认情况下,下载无需 API 密钥。只要知道链接,任何人都可以公开访问。

限制:

  • 文件大小限制:此功能目前适用于小型文件。由于直接使用 Deno KV 作为文件数据存储后端,单个文件的大小实际上受限于 Deno KV 的值大小限制,通常约为 60KB。超出此限制的上传将被拒绝。未来可能会支持分块上传较大的文件。

本地运行

本节介绍如何以默认的服务端模式运行 Doroseek。如需将 Doroseek 作为 Tunneling 功能的本地 Agent 运行,请参阅Agent 模式一节。

服务端模式配置

将 .env.example 复制为 .env

# .env
ADMIN_KEY=the_admin_key_here
MCP_MAX_DURATION=60

默认情况下,项目允许任何密钥创建对应的设置。如果 需要将访问限制为特定密钥,则需要设置 ADMIN_KEY 环境变量。

MCP SSE 连接最多可保持 MCP_MAX_DURATION 秒。

如有需要,设置数据库

// services/database.ts
export const db = await Deno.openKv("./db");
以服务端模式运行

若要以默认服务端模式运行应用,请确保未将 DOROSEEK_AGENT_MODE_ENABLED 设置为 "true"。 你需要安装 Deno。然后在此仓库的根目录运行:

deno task start

Agent 模式(用于内网穿透)

Doroseek 也可以在 Agent 模式下运行。在此模式下,它不会启动 Fresh Web 服务,而是作为本地客户端 Agent 连接到远程 Doroseek 实例(充当中继服务),将私有网络中的服务暴露到互联网。

这是区别于默认服务端模式的另一种运行模式。启用并正确配置 Agent 模式后,Doroseek 将只执行 Agent 职责。

Agent 模式配置

要启用并配置 Agent 模式,需要设置以下环境变量:

  • DOROSEEK_AGENT_MODE_ENABLED:

    • 设置为 "true" 以启用 Agent 模式。如果未设置为 "true",Doroseek 将尝试以服务端模式启动。
  • DOROSEEK_RELAY_URL:

    • 此 Agent 应连接的远程 Doroseek 实例(充当中继服务)的 WebSocket URL。此 URL 应指向中继的隧道注册端点。
    • 示例: wss://your-remote-doroseek.com/mcp/tunnel/register
  • DOROSEEK_AGENT_API_KEY:

    • 此 Agent 用于向远程 Doroseek 中继服务进行身份验证的 API 密钥。中继服务必须能够识别并授权此 API 密钥。
  • DOROSEEK_AGENT_SERVICES_JSON:

    • 定义本地服务数组的 JSON 字符串,Agent 应通过隧道暴露这些服务。

    • 数组中的每个服务对象都必须包含以下字段:

      • id(字符串):服务的唯一标识符(由你指定,例如 "my-web")。
      • name(字符串):易于识别的服务名称(例如 "My Local Web Server")。
      • type(字符串):服务类型。目前,Agent 的 HTTP 处理程序仅支持 "http"。
      • local_host(字符串):本地服务的主机名或 IP 地址(例如 "localhost"、"127.0.0.1")。
      • local_port(数字):本地服务运行所在的端口号(例如 8080)。
      • subdomainOrPath(字符串):中继服务将使用此字符串来构建该服务的公共 URL。字符串中不能包含 / 或空格。它实际上会成为中继公共隧道 URL 中的一个路径段。
        • 例如,如果中继提供的基础 URL 为 https://<relay-public-domain>/t/<tunnelId>,并且你将 subdomainOrPath 设置为 "myweb",则可以通过 https://<relay-public-domain>/t/<tunnelId>/myweb/... 访问你的服务。
    • DOROSEEK_AGENT_SERVICES_JSON 的示例值:

      [
        {
          "id": "web1",
          "name": "My Local Web Server",
          "type": "http",
          "local_host": "localhost",
          "local_port": 8080,
          "subdomainOrPath": "myweb"
        },
        {
          "id": "api2",
          "name": "Backend API",
          "type": "http",
          "local_host": "127.0.0.1",
          "local_port": 3000,
          "subdomainOrPath": "myapi"
        }
      ]
      

      要将其设置为环境变量,通常需要将 JSON 字符串压缩为单行(不含换行),并在某些 Shell 环境中进行正确转义。例如,在 .env 文件或 Shell 中: DOROSEEK_AGENT_SERVICES_JSON='[{"id":"web1","name":"My Local Web Server","type":"http","local_host":"localhost","local_port":8080,"subdomainOrPath":"myweb"},{"id":"api2","name":"Backend API","type":"http","local_host":"127.0.0.1","local_port":3000,"subdomainOrPath":"myapi"}]'

在 Agent 模式下运行
  1. 设置上方列出的所有必需环境变量。确保 DOROSEEK_AGENT_MODE_ENABLED 设置为 "true"。
  2. 使用标准命令运行应用:
    deno task start
    
  3. 如果配置有效,Doroseek 将以 Agent 模式启动。你将不会看到常见的 Fresh 服务启动日志(例如,“Listening on http://localhost:8000/”)。
  4. 请留意表明 Agent 模式正在运行的日志消息,例如:
    • [Main] Doroseek starting in Agent Mode.
    • [Agent Config] Agent configuration loaded successfully.
    • [Agent Connector] Initialized with Relay URL: wss://your-remote-doroseek.com/mcp/tunnel/register
    • [Agent Connector] Attempting to connect to ...
    • [Agent Connector] WebSocket connection established.
    • [Agent Connector] Sent registration request: ...
    • [Agent Connector] Successfully registered. Tunnel ID: <your-tunnel-id>, Public URL: <your-public-base-url>
    • [Main] Agent is connected and registered with the relay.
    • [Main] Tunnel ID: <your-tunnel-id>
    • [Main] Public Base URL: <your-public-base-url>
    • - Service 'My Local Web Server' (web1) accessible via: <your-public-base-url>/myweb
    • - Service 'Backend API' (api2) accessible via: <your-public-base-url>/myapi
与中继交互(Agent 视角)
  • Agent(此 Doroseek 实例以 Agent 模式运行)会与 DOROSEEK_RELAY_URL 建立 WebSocket 连接。该 URL 应为以 Server 模式运行的远程 Doroseek 实例的 /mcp/tunnel/register 端点。
  • Agent 会发送一条注册消息,其中包含在 DOROSEEK_AGENT_SERVICES_JSON 中定义的本地服务的详细信息。
  • 注册成功后,远程中继服务会为 Agent 提供唯一的 tunnelId 和 public_base_url。
  • 随后,当中继服务收到与该隧道匹配的公共 HTTP 请求时,会通过已建立的 WebSocket 隧道将这些请求作为 httpRequest 消息转发给 Agent。
  • Agent 处理这些 httpRequest 消息,向已配置的本地服务发起请求,然后向中继发送 httpResponse 消息。
  • Agent 还会以 pong 消息响应中继发送的 ping 消息,以报告自身状态及其主要本地服务的健康状况。
隧道健康检查 API

为了监控已建立隧道的状态以及底层本地服务的状态,Doroseek 提供了一个健康检查 API 端点。

  • 端点: GET /tunnel/:tunnelId/status

  • 描述: 此端点允许你查询由 :tunnelId 标识的特定隧道的当前状态。它会检查中继服务器到本地 Agent 的 WebSocket 连接,以及 Agent 是否能够访问已配置的本地服务。

  • 身份验证: 此端点目前不需要特定的 API 密钥身份验证,但 tunnelId 必须有效且为系统所知。如有需要,可以通过标准反向代理或网关机制添加访问控制。

  • 响应正文(HealthStatusReport): API 会返回具有以下结构的 JSON 对象:

    {
      "tunnelId": "string", // 被检查的隧道 ID
      "tunnelStatus": "connected" | "disconnected" | "unknown",
      "localServiceStatus": "ok" | "error" | "unconfigured" | "timeout" | "unknown" | "agent_unresponsive",
      "checkedByInstanceId": "string", // 执行或报告此次检查的中继实例 ID
      "timestamp": "string" // 执行检查时的 ISO 8601 时间戳
    }
    
    • tunnelId:已检查隧道的 ID。
    • tunnelStatus:
      • "connected":中继服务器已与此隧道的本地 Agent 建立活动的 WebSocket 连接。
      • "disconnected":中继服务器未与本地 Agent 建立活动的 WebSocket 连接。
      • "unknown":无法确定隧道状态(例如,在主数据库中找不到隧道 ID)。
    • localServiceStatus:
      • "ok":本地 Agent 已响应健康检查 ping,并报告其主要配置的本地服务可访问。
      • "error":本地 Agent 已响应,但在尝试检查本地服务时报告了错误。
      • "unconfigured":本地 Agent 已响应,但未配置要检查的本地服务,或者 Agent 无法检查该服务类型。
      • "timeout":本地 Agent 已响应,但其检查本地服务的尝试超时。
      • "agent_unresponsive":中继服务器已连接到 Agent,但 Agent 未在预期时间内响应健康检查 ping。
      • "unknown":无法确定本地服务的状态(例如,因为 tunnelStatus 不是 "connected")。
    • checkedByInstanceId:执行或最近一次报告健康状态的中继服务器实例的唯一 ID。适用于多实例部署。
    • timestamp:确定健康状态时的 ISO 8601 时间戳。
  • 使用示例: 请求:

    GET /tunnel/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/status
    

    响应示例:

    {
      "tunnelId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "tunnelStatus": "connected",
      "localServiceStatus": "ok",
      "checkedByInstanceId": "yyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy",
      "timestamp": "2023-10-27T10:30:00.000Z"
    }
    

    另一个示例(Agent 已连接,但本地服务已停止):

    {
      "tunnelId": "zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz",
      "tunnelStatus": "connected",
      "localServiceStatus": "error",
      "checkedByInstanceId": "wwwwwww-wwww-wwww-wwww-wwwwwwwwwwww",
      "timestamp": "2023-10-27T10:35:00.000Z"
    }
    

评论

支持 Markdown

第一次接触 MCP?

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

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