内容
# AICortex
> 私有、自托管的脑部,用于您的LLM — 在您自己的NAS上。
自托管 [MCP](https://modelcontextprotocol.io) 服务器,将您的NAS转变为**个人LLM连接器** — 一个持久的“大脑”,您的助手在每次会话开始时加载。它为任何支持MCP的LLM(Claude、ChatGPT、本地模型……)提供持久身份和真正的覆盖范围,在**您的**网络中运行,并直接插入您已经使用的LLM应用程序。您的数据保留在您的硬件上。
添加它一次作为*自定义连接器/MCP服务器*,您的LLM获得:
- ⚡ **一键式 onboarding** — 一个`bootstrap`工具,任何LLM都可以调用它;在单次往返中,它加载指南*和*大脑的实时目录(内存、技能、服务、设备、计划任务),因此在任何设备上的新会话都不会是“空白”的
- 🧠 **一致的内存**,存活于您的NAS,并跨所有设备跟踪
- 📱 **任意位置工作** — 桌面和移动设备上的同一个大脑,一个账户,一个状态
- 🗂️ **技能路由器** — 您的技能存活于NAS;LLM*搜索*它们,加载正确的技能(逐步披露),并在运行时*学习*新技能(`skill_write`)
- 🛠️ **数据工具** — 使用`service_add`注册任何HTTP API,使用`call_service`调用它;新的集成不需要代码和重新部署
- 🔌 **数据设备** — 通用的**MQTT** (`mqtt_*`) 和 **FTP/FTPS** (`ftp_*`) 分发器以相同的方式引入非HTTP设备(例如,LAN上的打印机或传感器)- 作为数据,不需要重新部署
- 🖨️ **打印** — 在LAN上注册打印机 (`print_add`) 并直接通过IPP/AirPrint打印PDF/图像到它 (`print_document`),按文件或内联base64 - 将文档交给助手,它在家中打印
- 📄 **扫描** — 在LAN上的多功能设备上扫描 (`scan_document`) 并直接将其丢入Paperless-ngx — “扫描并归档”一步到位
- 🔐 **加密秘密保险箱** — 通过连接器存储API密钥/令牌(从移动设备工作);静止加密,永不显示回
- 🛡️ **默认安全** — 关闭身份验证,强制加密保险箱和SSRF出口守卫(私有/元数据IP地址被阻止,除非您允许列出它们)
- 🧭 **自我描述** — 任何连接的LLM在连接时接收使用说明+`bootstrap`/`guide`工具,并被告知在物理/出站操作前确认
- 🤝 **多代理就绪** — 共享内存+注册表,因此多个代理可以共享一个大脑
- 🔁 **跨LLM会话交接** — `session_save`/`session_load` 保持一个紧凑的、带时间戳的日志,记录工作进度,因此不同的模型或设备(Claude、ChatGPT、计划运行)可以从另一个停止的地方继续;过期会话自动过期,因此NAS不会膨胀
- ⏰ **调度和自主性** — 以数据形式定义cron作业 (`cron_add`) 从任何设备;小型NAS端运行器触发LLM运行,当作业到期时,并将结果报告给您。连接器持有计划;LLM运行时执行它。
模型保留在其提供者的云中(或本地运行)。 **您的数据、技能和秘密保留在您的NAS上。** 您的LLM通过HTTPS连接器与其对话;服务器在内部使用您的本地凭证,从不交给模型。
> ✅ **状态:工作中。** 一键式`bootstrap` onboarding,内存,技能路由器,HTTP/MQTT/FTP分发器,MCP网关,多代理协调,跨LLM会话交接,数据调度,加密秘密保险箱,OAuth(通过您自己的OIDC提供商)和SSRF出口守卫都已上线 - 连接器是*自我描述的*。自主*运行器*(NAS端的LLM运行时,它触发计划作业)是单独设置的 - 请参阅 [自主性和调度](#自主性和调度). **不要在未进行身份验证的情况下公开暴露它。**
## 工作原理
```
LLM应用程序 - 任何MCP客户端(桌面/移动)· 一个或多个代理
│ 自定义连接器/MCP服务器(HTTPS,从模型的云)
▼
反向代理(Zoraxy / Caddy / nginx / Traefik ...)
│
▼
AICortex (此容器,在您的NAS上)
│ 使用本地文件和秘密
▼
内存 · 技能 · HTTP服务 · MQTT和FTP设备 · IPP打印 · MCP网关 · 收件箱/任务 · 会话 · Cron · 秘密保险箱
(每个出站调用都经过SSRF出口守卫)
自主(可选):NAS端的运行器 - 调度的`claude -p` - 轮询
`cron_due`,通过连接器运行到期作业,然后通知您
(推送/收件箱)。连接器存储计划;运行器是LLM
运行时,实际触发它。
```
## 功能(工具一览)
| 组 | 工具 | 功能 |
|-------|-------|--------------|
| Onboarding | `bootstrap` | **从这里开始** - 一次调用返回指南 + 大脑的实时目录(内存,技能,服务,设备,cron) |
| 健康 | `ping` | 连接性检查 |
| 内存 | `memory_write` · `memory_read` · `memory_list` · `memory_search` · `memory_delete` | NAS上持久的、作用域命名的事实 |
| 技能 | `skill_search` · `skill_list` · `skill_load` · `skill_resource` · `skill_write` | 可搜索的知识;运行时学习新技能 |
| 服务(HTTP) | `service_add` · `service_list` · `call_service` | 注册并调用任何HTTP API作为数据 |
| 设备(MQTT) | `mqtt_add` · `mqtt_list` · `mqtt_publish` · `mqtt_get` | 与MQTT设备(例如LAN上的打印机或传感器)通信作为数据 |
| 文件(FTP/FTPS) | `ftp_add` · `ftp_list_endpoints` · `ftp_list` · `ftp_upload` | 通过FTP/FTPS(例如将文件推送到设备)传输文件 |
| 打印(IPP) | `print_add` · `print_list` · `print_delete` · `print_document` | 通过IPP/AirPrint将PDF/图像打印到LAN打印机 - 按文件或内联base64 |
| 扫描(eSCL) | `scan_add` · `scan_list` · `scan_delete` · `scan_document` | 在LAN设备上扫描通过eSCL/AirScan → `/data/work`,可选直接进入Paperless |
| MCP网关 | `mcp_add` · `mcp_list` · `mcp_tools` · `mcp_call` | 将其他MCP服务器的工具用作数据 |
| 多代理 | `inbox_post`/`read`/`ack` · `task_add`/`list`/`claim`/`update` · `agent_register`/`list` | 共享收件箱,任务板和代理注册表 |
| 会话 | `session_save` · `session_list` · `session_load` · `session_delete` · `session_prune` | 跨LLM交接日志 - 从任何模型/设备恢复;自动过期 |
| 调度 | `cron_add` · `cron_list` · `cron_delete` · `cron_due` · `cron_mark_run` | 数据形式的cron作业;NAS运行器触发它们 |
| 秘密 | `secret_set` · `secret_list` · `secret_delete` | 加密保险箱;值从不返回 |
| 指南 | `guide` | 自我描述(也作为服务器`instructions`发送到连接时) |
新增功能作为**数据**(技能,服务配置,秘密)- 而不是代码,无需重新部署。完整的CRUD:每个配置模块也有一个删除(`skill_delete`,`service_delete`,`mqtt_delete`,`ftp_delete`,`mcp_delete`,`task_delete`,`agent_remove`,`inbox_delete`,以及`memory_delete` / `secret_delete`),因此您可以注册和删除连接器中的任何内容。
## 项目结构
```
AICortex/
├── app/ # 服务器代码(FastMCP)
│ ├── server.py # 入口点 - 连接身份验证并注册工具模块
│ ├── bootstrap.py # “开始使用”工具 - 加载指南 + 大脑实时目录
│ ├── memory.py # 内存工具
│ ├── skills.py # 技能路由器
│ ├── services.py # 通用允许列出的HTTP服务调用者
│ ├── mqtt_tools.py # 通用MQTT分发器(数据形式的设备)
│ ├── ftp_tools.py # 通用FTP/FTPS传输(将文件推送到设备)
│ ├── print_tools.py # IPP打印到LAN打印机(数据形式的打印机)
│ ├── scan_tools.py # eSCL扫描(数据形式的扫描仪)→ /data/work / Paperless
│ ├── netguard.py # SSRF出口守卫(允许列出内部范围)
│ ├── mcp_gateway.py # 其他MCP服务器的网关(数据形式的服务器)
│ ├── coordination.py # 多代理收件箱 / 任务板 / 代理注册表
│ ├── sessions.py # 跨LLM会话交接日志(自动过期)
│ ├── secrets_store.py# 加密秘密保险箱
│ ├── guide.py # 自我描述的使用指南(DE/EN)
│ └── requirements.txt
├── data/ # 持久的,人可读的状态(git忽略的内容)
│ ├── memory/ # 内存文件 - LLM记住的关于你的内容
│ ├── skills/ # 技能库 - <skill>/SKILL.md 路由器搜索
│ ├── services/ # HTTP服务配置(数据形式的集成)
│ ├── mqtt/ # MQTT代理/设备配置
│ ├── ftp/ # FTP/FTPS端点配置
│ ├── mcp/ # 上游MCP服务器配置
│ ├── coordination/ # 多代理收件箱 / 任务 / 代理
│ ├── sessions/ # 跨LLM会话交接日志(自动过期)
│ ├── printers/ # IPP打印机配置(数据形式的打印机)
│ ├── vault/ # 加密秘密(secret_set)
│ ├── auth/ # OAuth客户端注册(持久)
│ └── work/ # 文件工作流 / 临时(CAD,导出,大文件)
├── secrets/ # 本地凭证(.env)- 永远不要离开NAS
├── logs/ # 容器日志
├── docs/ # 架构和客户端项目说明模板
├── Dockerfile # 构建镜像(在构建时安装依赖项)
├── entrypoint.sh # 在运行时将权限降至PUID:PGID(gosu)
├── docker-compose.yml
└── .env.example
```
> **没有`deps/`文件夹?** 正确 - 依赖项在构建时**编译到镜像中**,因此没有启动时安装的卷。 `data/`,`logs/`和`secrets/`文件夹通过`.gitkeep`保持其结构;其*内容*被git忽略,因此不会提交任何私有内容。
## 内存,技能和技能路由器
这是项目的核心 - 使**助手本身**可移植,而不仅仅是聊天。
- **内存** 以 `data/memory` 下的普通文件形式存在。工具(`memory_read` / `memory_write` / `memory_list`)让LLM回忆和更新它对你的了解 - 在每个设备上都一样。
- **技能** 以 `data/skills` 下的文件夹形式存在(`<skill>/SKILL.md` + 资源)。路由器工具 - `skill_search` / `skill_load` / `skill_resource` - 让LLM找到适合的技能并仅加载**它需要的内容**(逐步披露,与工具搜索的理念相同)。
- **类别保持成本低廉。** 技能带有`category`(也读取`cluster`);`skill_list()`返回类别 + 计数,`skill_list("<category>")`深入其中,而`bootstrap`将技能部分折叠到每个类别的计数中 - 因此300个技能库保持为十二行,而不是令牌转储。 一小部分原始启动技能存在于 [`examples/skills/`](examples/skills/README.md) - 将它们复制到 `data/skills` 中进行初始化。
- **先调用`bootstrap`。** 它的工具描述告诉任何LLM在每次会话开始时调用它 - 一次调用加载指南和大脑的实时目录,因此助手在回答之前是定向的。 对于不自行调用工具的客户端,请在客户端的 **项目/系统提示** 中添加一行指令(“首先调用`bootstrap`工具”) - 请参阅 [`docs/client-project-instructions.md`](docs/client-project-instructions.md)。 之后,“找到正确的技能/工具并应用它”直接发生,从任何设备。
## 工具和集成(作为数据)
新的集成不需要新代码。 **服务** 是您在运行时使用 `service_add` 注册的小型配置(存储在 `data/services` 下); `call_service` 然后到达它 - 只有已注册的服务被允许,并且服务器端从存储的秘密(`token_env`,通过 `secret_set` 到加密保险箱或通过 `.env`)注入身份验证令牌,从不存储在服务数据中或返回给模型。 将服务与 `skill_write` 技能配对以解释如何使用它,并且新的功能**无需重新部署**。
## 多代理就绪
设计允许多个代理共享一个NAS大脑而不会相互冲突:
- **命名空间内存** - 内存按范围寻址,因此代理共享公共知识,同时保持私有笔记(`shared` vs. 代理特定)。
- **共享技能和工具注册表** - 每个代理查询相同的 `skill_search` 和工具集;添加一个功能一次,所有代理都可以使用。
- **代理工作空间** - `data/work` 下的隔离工作目录用于并行任务。
- **代理收件箱 + 任务板** - `inbox_*`(仅追加消息),`task_*`(可声明的任务板)和 `agent_*`(注册表)让多个代理在一个大脑上协调。
子代理*spawn* 停留在客户端(模型存在于云中);连接器是共享的协调层。 请参阅 [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)。
## 自主性和调度
计划存在于NAS上作为**数据** - 从任何设备使用 `cron_add(name, schedule, prompt)` 创建它们(5字段cron,服务器本地时间); `cron_list` / `cron_delete` 管理它们。 连接器不能**执行**模型运行 - 必须触发LLM运行。 因此,自主性**引擎**是一个小型 **NAS端运行器**:
1. NAS上的系统cron运行一个循环代理调用(例如 `claude -p "<orchestrator>"`,或任何LLM CLI/SDK)每分钟一次。
2. 该运行调用 `cron_due` → 通过连接器执行到期作业的提示(因此它具有所有工具)→ `cron_mark_run`。
3. 它通过您配置的通道报告结果 - 如果未设置任何通道,则发布到连接器 **收件箱**,您可以从LLM应用程序读取。
**运行器运行时 - 两个选项:
| 选项 | 成本 | 说明 |
|--------|------|-------|
| **订阅** (`claude` CLI / OAuth) | 无(使用您的计划) | 消费者计划旨在 *交互式**使用 - 无视线限制。 保持每天几个作业/day。
| **API密钥**(代理SDK) | 按使用付费(轻量级日常作业的几分钱) | 授权路径用于无人值守运行。 密钥保留在保险箱中。 > 连接器接受 **以及** OIDC(FastMCP `MultiAuth`)- 交互式应用程序继续使用OIDC不变;仅头less机客户端使用令牌。
> 运行器是 **唯一** 在连接器外部存在的部分 - 模型/代理运行在其提供者的云中(或本地)并且必须被调用。 它作用于所有内容(计划,工具,内存,秘密)都保留在NAS上。
两个可部署的运行器存在于 [`runner/`](runner/README.md),因此自主层适用于 **任何**应用程序LLM:
- **Claude Code后端** - 执行连接器的OAuth登录,因此不需要更改连接器(最适合Claude用户)。
- **通用任何LLM后端**([`runner/generic/`](runner/generic/README.md))- 通过 [LiteLLM](https://github.com/BerriAI/litellm) 驱动连接器中的 **任何**模型(GPT,Gemini,Olama,Claude,…)。它使用静态的 **`RUNNER_TOKEN`**,连接器接受 **以及** OIDC(FastMCP `MultiAuth`)- 交互式应用程序继续使用OIDC不变;仅headless机客户端使用令牌。
### 要求
- 一个NAS或服务器运行 **Docker** (Compose v2)。
- 一个 **反向代理** 公开容器到公共HTTPS - 云托管的LLM客户端从其提供者的云中连接,因此端点必须可以从互联网访问。 (纯本地客户端/运行器可以直接在LAN上访问它。)
- 一个指向您的代理的域名/子域名。
- 一个支持自定义连接器/MCP服务器的 **MCP-capable 客户端** (例如Claude,ChatGPT,或任何MCP客户端;一些计划限制您可以添加的数量)。
## 快速开始
```bash
git clone git@github.com:IkarusMK/AICortex.git
cd AICortex
cp .env.example .env # 调整 PUID / PGID / HOST_PORT / TZ
docker compose up -d --build
```
MCP端点在 `http://<host>:8787/mcp` 处提供。
> **预构建镜像(无需本地构建)** 发布到GHCR的CI镜像为多架构镜像。在 `docker-compose.yml` 中,注释掉 `build: .`,取消 `image: ghcr.io/ikarusmk/aicortex:latest`,然后 `docker compose pull && docker compose up -d`。(确保GHCR包 **公开**,在仓库的*Packages*设置下,这样NAS可以拉取它而无需令牌。)
### 暴露它并添加连接器
1. 将一个子域名(例如 `agent.example.com`)指向您的反向代理。
2. 将该主机代理到 `http://<nas-ip>:8787` 通过HTTPS。
- 上游是 **纯HTTP** - 不要启用“到上游的TLS”。
- 如果您的代理使用地理封锁,**允许您的LLM提供商的出口区域**,用于此主机(例如,美国对于Anthropic-/OpenAI托管的客户端),否则连接器无法访问您。
3. 在您的MCP客户端(例如Claude):**添加自定义连接器/MCP服务器** → URL `https://agent.example.com/mcp`.
4. 测试:要求助手调用 `ping` 工具。
## 配置
所有配置都存放在 `.env` 中(从 `.env.example` 复制而来):
| 变量 | 默认值 | 描述 |
|-------------|---------|-------------|
| `HOST_PORT` | `8787` | 服务器发布的宿主端口(容器内部始终监听 `8787`) |
| `PUID` | `1000` | 进程运行的用户ID(文件所有权) |
| `PGID` | `1000` | 进程运行的组ID |
| `TZ` | `UTC` | 容器的时区 |
## 认证
在公开连接器之前,请使用 OAuth 保护它。它使用您自己的 **OIDC 身份提供者** 作为登录后端 — Pocket ID、Authentik、Keycloak、Auth0,任何具有标准 OIDC 发现功能的服务。FastMCP 的 OIDC 代理处理 MCP 端的 OAuth 2.1 流(动态客户端注册 + PKCE),MCP 客户端使用该流;您的提供者只需进行实际登录。
> ℹ️ **请勿** 在 `/mcp` 端点前放置浏览器/转发身份验证(反向代理 SSO)。MCP 连接器是一种机器客户端,无法遵循交互式登录重定向。身份验证必须在 MCP 层进行,这正是此操作的作用。
通过在 `.env` 中设置以下变量来启用它(请参阅 `.env.example`):
| 变量 | 示例 |
| --- | --- |
| `OIDC_CONFIG_URL` | `https://id.example.com/.well-known/openid-configuration` |
| `OIDC_CLIENT_ID` / `OIDC_CLIENT_SECRET` | 从您在提供者中注册的客户端获取 |
| `BASE_URL` | `https://agent.example.com` (此服务器的公共 URL) |
| `JWT_SIGNING_KEY` | `openssl rand -hex 32` |
在提供者中注册 OAuth 客户端,设置重定向 URI 为 **`<BASE_URL>/auth/callback`**。然后,在客户端中重新添加自定义连接器 — 它将通过您的提供者的登录界面引导您。**当 OIDC 变量未设置时,服务器仅绑定到 `127.0.0.1`**(本地测试);设置 `ALLOW_INSECURE=1` 以强制进行无身份验证的开放绑定(不推荐)。
> ⚠️ **身份验证 ≠ 授权**。任何可以登录到您的 IdP 的帐户都将获得 **完全** 访问每个工具和所有数据的权限 — 没有基于用户/角色的检查。请将此指向 **单用户或专用** 提供者;不要在不限制允许登录的主题的情况下重用共享的家庭/公司 IdP。
## 安全
- **身份验证失败时关闭**。如果没有 OIDC,服务器仅绑定到 `127.0.0.1`(使用 `ALLOW_INSECURE=1` 覆盖)。使用 OIDC 时,**在公开代理之前启用它** — 否则,任何到达 `/mcp` 的人都可以调用每个工具。
- **SSRF 保护**。`service_add` / `mqtt_add` / `ftp_add` 是模型可以调用的工具,因此已注册的目标列表本身并不是一个信任边界。每个出站主机都会被解析,**私有 / 回环 / 本地链接 / 云元数据地址将被阻止**,除非它们属于 `INTERNAL_ALLOW_CIDRS`(仅限操作员设置,不可由模型设置)。请将其设置为您实际使用的 LAN/VPN 范围 — 例如 `192.168.1.0/24` — 否则,对您自己的设备的调用也将被阻止。
- **加密保险库,强制执行**。集成/设备机密通过 `secret_set` 进入 **保险库**(在 `data/vault` 中加密存储,通过名称引用,永不返回给模型,可从移动设备设置)。`secret_set` **拒绝存储明文**,除非设置了 `STORAGE_ENCRYPTION_KEY`(或您选择使用 `ALLOW_PLAINTEXT_VAULT=1`)。`.env` 仅用于引导配置(OIDC 机密,`JWT_SIGNING_KEY`)— 不要要求助手编辑它来设置集成机密。
- **转发头**。`FORWARDED_ALLOW_IPS` 默认设置为 `*`(在隔离的 Docker 网络上正常)。如果容器可以直接访问,请将其范围限定为您的代理的源 IP/子网。
- `.env` 和 `data/` 内容被 git 忽略 — 永远不要提交机密。
## 在 VPS 或 VPN 上部署
连接器只是一个 HTTPS MCP 端点,因此它可以在任何支持 Docker 的地方运行 — 您的 NAS、VPS 或云盒 — 并通过您提供的网络访问设备。SSRF 保护使其安全:
- **在 VPS 上(仅限公共 API)**:相同的反向代理 + OIDC,设置 `BASE_URL` 为其公共 URL,并将 `INTERNAL_ALLOW_CIDRS` 留空,以便它只能访问公共服务。
- **从 VPS 访问家庭设备**:使用 VPN(WireGuard、Tailscale 等)将 VPS 和您的 LAN 连接起来,并将 **VPN/远程子网** 添加到 `INTERNAL_ALLOW_CIDRS`(例如 Tailscale 的 `100.64.0.0/10` 或您的 WireGuard 范围)。保护程序然后仅允许这些主机访问,而不允许其他主机。
- **多站点/企业**:将 `FORWARDED_ALLOW_IPS` 范围限定为代理,列出 `INTERNAL_ALLOW_CIDRS` 中的受信任子网,并使用专用的 OIDC 客户端(参见上面的授权说明)。
## 故障排除
在反向代理和 OIDC 提供者后面运行此程序时获得的一些经验教训。启用详细日志以查看身份验证失败的真实原因:
```yaml
# docker-compose.yml → environment:
FASTMCP_LOG_LEVEL: "DEBUG"
```
| 症状 | 原因和解决方法 |
| --- | --- |
| 登录成功,但客户端显示 *"连接时返回错误"*;日志显示 `Token verified successfully` 然后 **`Token missing required scopes`** | 代理颁发的 MCP 令牌不包含上游 OIDC 范围作为声明。**不要设置 `required_scopes`** — 成功登录就足够了。(已在 `server.py` 中删除。) |
| 日志显示 `Issued new FastMCP tokens` 立即后跟 **`Bearer token rejected`**(401 `invalid_token`) | 在 TLS 终止代理后面,uvicorn 忽略了 `X-Forwarded-Proto`,因此服务器计算出一个 `http://` URL 并拒绝其自己的 `https` 受众令牌。设置 **`FORWARDED_ALLOW_IPS: "*"}`**(已在 `docker-compose.yml` 中)。 |
| 日志警告 **`disk client_storage unavailable (Fernet key must be 32 url-safe base64-encoded bytes)`** | `STORAGE_ENCRYPTION_KEY` 不是有效的 Fernet 密钥(它与 `JWT_SIGNING_KEY` 不同)。生成:`python -c "from cryptography.fernet import Fernet;print(Fernet.generate_key().decode())"`。或者省略它以使用未加密(仍然持久)的存储。 |
| 曾经有效,然后在重新创建容器后,**旧客户端 ID** 的 `Bearer token rejected` | OAuth 客户端存储是短暂的,并且被清除。持久的 `data/auth`(此存储库)修复了它。要清除卡住的客户端:删除连接器,完全退出并重新打开应用程序,重新添加。 |
| 连接器根本无法连接;代理返回一个登录 **网页** | 您在 `/mcp` 前面放置了反向代理 SSO / 转发身份验证。机器客户端无法进行交互式登录 — **删除它**;身份验证属于 MCP 层(此服务器)。 |
| OIDC 提供者的同意/"登录"按钮无限旋转,没有 `POST …/authorize` 到达 IdP;浏览器控制台显示 `null is not an object (… scope.includes)` | 上游 `/authorize` 请求携带 **没有 `scope`**(一些 IdP 界面,例如 Pocket ID,在 `scope=null` 时崩溃)。发送一个 **不重新引入令牌范围验证** 的范围:`extra_authorize_params={"scope": "openid profile email"}`(已在 `server.py` 中;通过 `OIDC_SCOPE` 覆盖)。 |
| 对 **本地设备** 的 `call_service` / `mqtt` / `ftp` 返回 *"被网络策略阻止"* | SSRF 保护默认阻止私有 IP。 将设备的范围添加到 **`INTERNAL_ALLOW_CIDRS`**(例如 `192.168.1.0/24`)并重启。 |
## 路线图
- [x] 基础架构:`ping` 工具 + 通过 HTTPS 的远程 MCP
- [x] 身份验证:通过您自己的 OIDC 提供者(Pocket ID、Authentik、Keycloak、Auth0 等)进行 OAuth 2.1
- [x] 内存工具(`memory_write` / `memory_read` / `memory_list` / `memory_search` / `memory_delete`),为多代理范围命名
- [x] 技能路由器(`skill_search` / `skill_list` / `skill_load` / `skill_resource` / `skill_write`)
- [x] 通用服务调用者(`call_service` / `service_add` / `service_list`)— 集成作为数据 + 技能,无需重新部署
- [x] 加密秘密保险库(`secret_set` / `secret_list` / `secret_delete`)— 通过连接器设置秘密;值在存储时加密,永不返回
- [x] 自描述:连接时的服务器 `instructions` 和 `guide` 工具,以便任何 LLM 立即了解连接器是什么以及如何使用它
- [x] 一键式初始化:一个 `bootstrap` '开始这里' 工具,加载指南 + 一个实时脑图目录,单次调用,因此任何设备上的新会话都不会空白
- [x] 通用设备调度器 — **MQTT** (`mqtt_*`) 和 **FTP/FTPS** (`ftp_*`),因此非 HTTP LAN 设备(打印机,传感器,执行器...)也是数据
- [x] IPP 打印(`print_add` / `print_list` / `print_delete` / `print_document`)— 通过 IPP/AirPrint 将 PDF/图像打印到 LAN 打印机,文件或内联 base64;自动升级到 TLS/IPPS 并自动回落到 octet-stream
- [x] eSCL 扫描(`scan_add` / `scan_list` / `scan_delete` / `scan_document`)— 通过 eSCL/AirScan 在 LAN 设备上扫描到 `/data/work`,可选地直接上传到 Paperless-ngx
- [x] 硬化 — 关闭身份验证失败,强制加密保险库,SSRF 出口保护(`INTERNAL_ALLOW_CIDRS`);VPS/VPN 友好
- [x] MCP 网关 — 连接到其他 MCP 服务器作为数据(`mcp_add` / `mcp_list` / `mcp_tools` / `mcp_call`)
- [ ] 捆绑服务配置和技能(Home Assistant,Mealie,...)
- [x] 多代理协调:共享收件箱,任务板和代理注册表(`inbox_*` / `task_*` / `agent_*`)— 子代理 *生成* 保留在客户端
- [x] 调度:作为数据的时间作业(`cron_add` / `cron_list` / `cron_delete` + `cron_due` / `cron_mark_run`)
- [x] 跨 LLM 会话交接:时间戳,自动过期检查点(`session_save` / `session_list` / `session_load` / `session_delete` / `session_prune`),因此任何模型/设备都可以从另一个设备离开的地方继续 — 5 个最近的会话在 `bootstrap` 的顶部显示
- [x] 自主运行程序:具有可交换 LLM 后端的参考 NAS 端运行程序([`runner/`](runner/README.md))— 触发到期作业并通知您
- [x] GHCR 上的预构建镜像 — 通过 GitHub Actions 进行多架构(amd64/arm64)构建和推送
## 许可证
[MIT](LICENSE) 2026 IkarusMK 版权所有
连接信息
猜你喜欢
暂无推荐服务器