
AICortex
io.github.IkarusMK由 GitHub 账号 IkarusMK 发布v2.3.4更新于 Nov 5, 2026
Self-hosted brain for any LLM: memory, skills, encrypted vault, devices and scheduled jobs.
概览
自托管的 MCP 服务器,为任意 LLM 提供持久“大脑”:类型化记忆、技能、加密密钥库、设备集成与定时任务。
- 可以做什么
- 加载会话简报与完整工具目录,并通过路由器查找和调用任意工具
- 写入、读取、搜索和审核类型化记忆,并搜索、加载和编写技能
- 注册并调用 HTTP 服务、MQTT 设备、FTP/WebDAV 存储、CalDAV 日历、SSH/SFTP 主机、SMTP/IMAP 邮件、IPP 打印与 eSCL 扫描
- 管理沙箱化工作区文件、入站与出站 webhook,以及其他 MCP 服务器的工具
- 协调代理与任务、保存并恢复跨 LLM 会话、安排 cron 定时任务
- 在加密密钥库中保存机密,管理员还可配置按用户划分的租户区域
- 适用场景
- 适合拥有自有硬件、希望让 Claude、ChatGPT 或本地模型在桌面与手机上共享同一份私有持久上下文和工具层,并能访问局域网服务与设备而不把凭据交给模型的人。
- 运行要求
- 需要运行 Docker Compose 的 NAS 或服务器、以公网 HTTPS 提供该容器的反向代理与域名,以及支持 MCP 的客户端。需在 .env 中配置 OIDC 提供方参数(OIDC_CONFIG_URL、OIDC_CLIENT_ID、OIDC_CLIENT_SECRET)、BASE_URL、JWT_SIGNING_KEY 以及必填的 STORAGE_ENCRYPTION_KEY;未配置 OIDC 时改用 bearer 令牌或按代理分配的密钥。
安装
在 SourceWeft 中
- 打开 控制台中的 AICortex,将其添加到工作区。
- 为需要使用其工具的对话启用该服务。
Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。
其他 MCP 客户端
参照 仓库 中的启动说明。
README
[AICortex — your self-hosted LLM brain, on your own NAS]
[License: Apache 2.0] [Latest release] [Build] [Protocol: MCP] [Self-hosted] [Buy me a coffee]
A private, self-hosted brain for your LLM — on your own NAS.
In 30 seconds: AICortex is one container on your own hardware that every AI you use connects to.
- It remembers who you are, how you work and what you're building — and hands that to Claude, ChatGPT or a local model at the start of every chat, on desktop and phone.
- It reaches your stuff — services, devices, mail, calendars, files — with the secrets in an encrypted vault the model never sees.
- It keeps your schedule: tell your AI "tomorrow at 8: summarise yesterday's notes". AICortex stores the job and at 8 wakes your Claude (or asks ChatGPT, an API key or a local Ollama) to do it.
Try it in 5 minutes · Run it on your NAS · More screenshots · Connect your AI
AICortex is a self-hosted MCP server that turns your NAS into a personal LLM connector: a persistent "brain" your assistant loads at the start of every session. Any MCP-capable LLM — Claude, ChatGPT, or a fully local model — gains a durable identity and real reach into your own services and devices, while running inside your network. Non-MCP tools (n8n, LangChain, your own scripts) reach the same brain through a native REST API with scoped per-user keys — and humans get a built-in admin WebUI at /ui for the vault, skills, users and audit log.
The model stays in its provider's cloud (or runs locally). Your memory, skills and secrets stay on your NAS. The assistant talks to AICortex over an HTTPS connector; the server uses your local credentials internally and never hands them to the model. New capabilities are added as data — a skill, a service config, a secret — with no redeploy.
Highlights
🧠 A brain that travels with you
- One short
cortex_startcall — who you are, how you work, and the current project's notes, open tasks and last session (a few hundred characters;cortex_cataloghas the full list) - Self-learning, typed memory with a review queue, so it grows without polluting itself
- A skill router — search your skills, load only what's needed, author new ones at runtime
- Playbooks — multi-stage work where a person approves each stage's artifact (e.g. Anthropic's AI-native SDLC:
intent.md→spec.md→plan.md…), bundled as a template — see docs/playbooks.md - The same brain across models, desktop and mobile — one account, one state
🔌 Real reach — every integration is just data
- Email (SMTP send + IMAP read), calendars (CalDAV), HTTP services, MQTT & FTP/FTPS devices, WebDAV cloud, SSH/SFTP
- IPP printing & eSCL scanning (straight into Paperless-ngx) on LAN multifunction devices
- Event-driven: inbound webhooks (
POST /hooks/<name>, secret/HMAC-verified) turn external events into inbox items; outbound webhooks notify - An MCP gateway to use other MCP servers' tools — register any integration with one call, no code, no redeploy
🌐 Beyond MCP — drive it over plain HTTP
- A native REST API: every tool as
POST /api/v1/tools/<name>with an auto-generated OpenAPI 3.1 spec — plug AICortex into n8n, LangChain, an OpenAI-compatible client or a shell script, no MCP client required - Per-user API keys: scoped (default-deny), hashed at rest, rate-limited, optional expiry — and a key runs the same per-user areas as an OIDC session, never admin by default
🖥 Built-in admin WebUI — no terminal needed
- Every signed-in person manages their own notes, scheduled jobs and playbook runs (and approves playbook stages) at
/ui; admins also get the vault (secret names only — values are write-only), skills, users & roles, services & devices editing and the audit log — language-switchable DE/EN - Same SSO as the connector (OIDC + PKCE against your IdP, e.g. Pocket ID), CSRF-guarded, fully self-contained (strict CSP, no CDNs, no build step) — served by the same container, no extra service
- Every page takes the same policy path as the MCP tools, so the browser never gets more than the person's AI
- See it in screenshots
👥 Team, autonomy & continuity
- A presence-aware multi-agent board: live presence, capability-routed task pull, context-preserving handoff
- Cross-LLM session handoff — resume exactly where another model or device left off
- Cron-as-data scheduling with per-user act-as: a scheduled job runs confined to its owner's area, via a short-lived per-job token — never a standing god-token
- Runners carry the jobs out — AICortex wakes your Claude (a Claude Code cloud task on your plan) with the due job, or asks your ChatGPT plan, an API key or a local Ollama; each person sets up their own in the WebUI and gives each job its runner, no extra container (how)
🔒 Secure & multi-tenant
- Your own OIDC login and roles (admin / user / viewer) — one switch,
AUTH_ENFORCE - Per-user isolation and capability areas: private memory + vault per person, plus default-deny service/skill allow-lists an admin assigns — so not everyone may use every tool
- An encrypted secret vault, an SSRF egress guard, and capability checks that fail closed — end-to-end on your hardware, including a local model (Ollama)
How it works
How AICortex differs
The "LLM brain" space has some great projects — AICortex deliberately sits in a different spot:
- GBrain is a memory engine — markdown-first, Postgres/PGLite-backed, with a self-wiring knowledge graph and hybrid/vector search. Deep retrieval, one concern.
- CortexPrism is a full agent operating system — its own runtime, ~30 LLM providers, a plugin marketplace, sandboxed code execution and multi-user teams. Batteries included, heavyweight.
- AICortex is a single, lightweight MCP connector: one container that gives any client a persistent brain — memory and skills, devices, sessions, secrets and scheduling — where new integrations are added as data, no redeploy. And unlike most brain projects it isn't MCP-only: the same tools are exposed over a native REST API with an auto-generated OpenAPI spec, so non-MCP clients (n8n, LangChain, a script) plug in too. No database, no graph, no marketplace; you bring your own client.
Rule of thumb: want a dedicated memory/graph engine → GBrain; want a batteries-included agent OS → CortexPrism; want a minimal self-hosted connector that plugs your existing LLM app into your own stuff → AICortex.
Try it in 5 minutes
Just want to look around? Run it on your own computer — no NAS, domain or login needed, only Docker:
- Open http://localhost:8787/ui — the WebUI, already signed in as admin.
- Connect an AI that runs on the same computer. Claude Code:
claude mcp add --transport http aicortex http://localhost:8787/mcp, then ask it to callcortex_start. Other local clients: docs/clients.md. The Claude and ChatGPT apps connect from their provider's cloud, so they need the real setup. - Tell it something about you, or "tomorrow at 8: summarise yesterday's notes" — it shows up under Notes and Scheduled jobs. A job runs once you add a runner with an API key (OpenRouter's free models work); waking Claude needs your own login, so that, too, is the real setup.
⚠️ No login in this mode.
ALLOW_INSECURE=1switches authentication off: whoever reaches the port is admin. Keep the port on127.0.0.1as above, keep real secrets out, and never run it like this on a server. For everyday use, follow the Quick start with your own login.
Done looking? docker rm -f aicortex && docker volume rm aicortex-data && rm aicortex.env
removes it with all its data.
Requirements
- A NAS or server running Docker (Compose v2).
- A reverse proxy serving the container over public HTTPS (cloud-hosted LLM clients connect from their provider's cloud, so the endpoint must be reachable from the internet; a purely local client can reach it on the LAN).
- A domain/subdomain pointing at your proxy.
- An MCP-capable client that supports custom connectors / MCP servers (Claude, ChatGPT, or any MCP client).
Quick start
🤖 Installing with an AI coding agent? Point it at INSTALL_FOR_AGENTS.md — it walks the agent through the whole install and verification, handing the human-only steps (DNS, proxy, OIDC) back to you.
The MCP endpoint is served at http://<host>:8787/mcp.
Prebuilt image (no local build): a multi-arch image is published to GHCR by CI. In
docker-compose.yml, comment outbuild: ., uncommentimage: ghcr.io/ikarusmk/aicortex:latest, thendocker compose pull && docker compose up -d.
Updating from 1.x: pull the new image and restart with the same
data/folder and.env— there is no migration step. Connected apps stay signed in; memory, skills, vault, services, tasks, sessions and API keys carry over. What changes is listed in CHANGELOG.md.
Expose it & add the connector:
- Point a subdomain (e.g.
agent.example.com) at your reverse proxy. - Proxy that host to
http://<nas-ip>:8787over HTTPS — the upstream is plain HTTP, so do not enable "TLS to upstream". If your proxy geo-blocks, allow your LLM provider's egress region. The published port binds to127.0.0.1by default (only this host's proxy reaches it, not the LAN); a host-network proxy useshttp://127.0.0.1:8787, a bridge-network proxy needsBIND_ADDR=0.0.0.0(or a shared Docker network). - In your MCP client: add a custom connector / MCP server → URL
https://agent.example.com/mcp. Agents and CLIs that can only send a header (Claude Code, Codex, Hermes, OpenClaw, LM Studio, …) use a per-agent key instead — setup for every client: docs/clients.md. - Test: ask the assistant to call
cortex_start. The briefing starts withAICortex v<version>; on a fresh install it is short because the memory is still empty. (pingworks too, but it is not among the eleven tools clients see up front.)
Authentication & authorization
AICortex separates authentication (who may connect) from authorization (what they may do). Set up the login once, then pick your mode with a single line in .env.
1. Authenticate with your own OIDC provider
Exposing the connector publicly requires OAuth. AICortex uses your own identity provider as the login backend — Pocket ID, Authentik, Keycloak, Auth0, anything with standard OIDC discovery. FastMCP's OIDC proxy handles the MCP-side OAuth 2.1 flow (Dynamic Client Registration + PKCE); your provider does the actual login.
Register the OAuth client in your provider with redirect URI <BASE_URL>/auth/callback, then (re-)add the connector in your client to be sent through the login.
🟣 Using Pocket ID? Follow the click-by-click Pocket ID setup guide — creating the OIDC client, the exact
.env, and optional groups → roles.
ℹ️ Don't put reverse-proxy SSO / forward-auth in front of
/mcp— an MCP connector is a machine client and can't follow an interactive login redirect. Authentication belongs at the MCP layer, which is exactly what this does. When the OIDC variables are unset,/mcpaccepts bearer tokens only (per-agent keys andRUNNER_TOKEN);ALLOW_INSECURE=1turns all auth off for local testing.
2. Pick your mode — one line in .env
🏠 Homelab — keep it simple
Every authenticated caller gets every tool — one shared brain, zero friction. Authentication (OIDC) still guards the front door; you've just turned off the internal role gate.
🏢 Enterprise — several people, one brain
AUTH_ENFORCE=1 is the one switch — "enforce means enforce". It turns on roles (admin / user / viewer), per-user isolation, and per-user capability areas together. Roles are driven by your IdP groups (mapped in data/auth/policy.json, or managed live with the tenancy_* admin tools). Each non-admin is confined to their own memory scope and private vault namespace — two people never read or overwrite each other's data — and reaches only the services & skills an admin assigns (default-deny); an admin provisions per-user secrets (secret_set owner=…) and areas (tenancy_set services=… skills=…). Admins keep full access.
Both modes run the same image. Private data (memory, vault) fails open so a glitch never strands the operator; shared capabilities (services, skills) fail closed under enforce. Full guides: docs/authorization.md · docs/per-user-areas.md.
Capabilities
Every register has a matching delete (skill_delete, service_delete, mqtt_delete, memory_delete, secret_delete, …), so anything you register you can also remove via the connector.
Memory, skills & the skill router
This is the heart of the project — making the assistant itself portable, not just the chat.
- Memory lives as plain files under
data/memory; thememory_*tools let the LLM recall and update what it knows about you, the same on every device. The catalog groups it by tier — 🧭 Core (identity & preferences) → 📂 Projects → 🛠 Working style → 🔗 References, derived from each memory'stype, with short-term/current state in the sessions layer — so a fresh LLM sees who you are before the ephemera. - Skills live as folders under
data/skills(<skill>/SKILL.md+ resources). The router (skill_search/skill_load/skill_resource) finds the right skill and pulls in only what it needs (progressive disclosure). - Categories keep it cheap — and are mandatory.
skill_writerefuses an uncategorized skill and snaps near-duplicate spellings onto the existing category, so a 300-skill library stays a dozen lines incortex_catalog, not a token dump. Starter skills live inexamples/skills/and ship with the image — Skills → Add starter skills in the WebUI adds them. cortex_startfirst. The server instructions ask every model to call it at the start of a conversation (with the project name). The briefing names every general working rule (afeedbackmemory without a project) — tag a rulepinnedto put it first with its text — while rules that belong to a project only come along for that project. For clients that don't pass the instructions on, add a short block to your client's project/system prompt — seedocs/client-project-instructions.md.
Auto-memory — a brain that learns by itself
Most assistants forget the moment a chat ends. AICortex closes that loop — and stays tidy while doing it.
- Typed & tiered. Every memory is
user,feedback,projectorreference;memory_writerefuses an untyped memory, andcortex_cataloggroups them into tiers (Core → Projects → Working style → References) so the catalog reads long-term → ephemeral — the brain stays sorted by intent. - Learns in-session, at zero extra cost. The model already talking to you distills the durable facts and writes them back — no second model, no background loop.
- Dedup-first. A write flags overlapping entries so related facts merge into one file instead of multiplying.
- A review queue. Anything captured automatically (or staged with
memory_note) lands as a candidate, not live memory — youmemory_promotethe keepers andmemory_rejectthe rest. SetLEARN_AUTOCAPTURE=0to turn auto-capture off.
Tools & integrations (as data)
New integrations don't need new code. A service is a small config you register at runtime with service_add (stored under data/services); call_service then reaches it — only registered services are allowed, and the auth token is injected server-side from the vault (token_env), never stored in service data or returned to the model. Every service takes a category (like skills — service_add refuses without one), so the catalog stays grouped and findable. Pair a service with a skill_write skill that explains how to use it, and a new capability is live without a redeploy.
Multi-agent — one brain, many agents
Run your assistants as a team: Claude on the desktop, a local model on the NAS, your phone — sharing one brain and one task board.
- Live presence.
agent_registerdoubles as a heartbeat;agent_listshows who's online / idle / away, andcortex_catalogsurfaces the team. - Pull work, don't hunt for it.
task_next(owner)recommends the best open task (assigned-to-you → capability match → unassigned);task_claimtakes it. - Hand off with full context.
task_handoff(id, to)reassigns a task, notifies the recipient, and attaches the work session — theysession_loadand pick up exactly where the other stopped. - Namespaced memory. Shared knowledge in
shared, private notes inagents/<name>.
Sub-agent spawning stays client-side; the connector is the shared coordination layer they meet on. See docs/ARCHITECTURE.md.
Autonomy & scheduling
New here? → Scheduled jobs and runners, step by step.
Schedules live on the NAS as data — cron_add(name, schedule, prompt[, runner, once]) from any device, or Scheduled jobs in the WebUI (presets, a preview of the next runs, on/off, the job's runner). Runners carry them out — set up in the WebUI, tab Runners, by every person for their own jobs; no extra container, nothing to install:
- Once a minute, on the minute, AICortex checks for due jobs — without any model, so an idle minute costs nothing. A minute it missed (slow run, restart) is caught up for five minutes.
- Only when a job is due does it wake or ask the job's runner. A job that names none goes to its person's own default runner (their first one, or the one they chose), else to the standard runner (one of an admin's). A one-off job (
once) switches itself off after its run. - The job runs through this connector and reports via your configured channel or the connector inbox;
cron_mark_runrecords the result.
Kinds of runner:
A key typed in is stored encrypted as the runner's own vault entry (RUNNER_KEY_<id>, an internal name no service can use) and never shown again; picking an existing entry (e.g. OPENROUTER_API_KEY) needs no second copy — a person may pick only their own entries, an admin shared ones too. Where AICortex asks the model itself, each job is a conversation of its own: AICortex confines it to the job owner's area (act-as) before the model sees it, ends that afterwards and records the run — the model never sees a token or the runner plumbing; its tool calls go through /mcp, so roles and audit apply as for any caller. A job gets five minutes; runners work side by side, so a slow one holds up nobody else. Test on a runner asks its model one tiny question, or wakes the cloud task with a harmless check and shows the link to the Claude session. Limits: 10 runners per person (admins: no limit), keys up to 1,024 characters, job prompts up to 20,000.
A Claude runner acts as you. The cloud task runs with your full rights in AICortex and all your claude.ai connectors, so a Claude runner only carries out jobs you wrote yourself — their prompt, name and recipient — and never ones written with an agent key. Anthropic marks the wake-up text as untrusted data that can't grant approval — like every runner, a job does only what is read-only or explicitly allowed in its prompt. Limits: 30 wake-ups an hour per task (AICortex keeps two minutes between them), no automatic retry (a retried wake-up would start a second session). Why not
claude setup-token? Anthropic refuses a subscription token outside Claude Code (HTTP 429 "Error"), so 2.3.0 dropped that way; a 2.2 setup using it becomes a switched-off Claude runner.
The ChatGPT plan (Plus or Pro) uses OpenAI's Sign in with ChatGPT for open-source apps: choose ChatGPT plan, click Sign in with ChatGPT, open the sign-in and allow AICortex to use the plan. OpenAI then sends the browser to http://127.0.0.1:1455/… — the computer you sit at, not the NAS — so the page shows an error; paste that whole address into the field below and finish. AICortex checks the ID token, keeps the tokens encrypted in the vault, refreshes them itself (the sign-in stays valid as long as AICortex renews it within 30 days, which it does on its own) and runs jobs through OpenAI's Responses API. Leave the model empty for your account's first model, or pick one of the suggestions. On Plus, all apps share the plan's five-hour limit; Sign out revokes the sign-in at OpenAI.
An own runner outside AICortex that calls cron_due with the static RUNNER_TOKEN from the connector's .env keeps working: it gets the jobs assigned to external, and the unassigned ones while no standard runner is on. A job is handed out once per scheduled minute, so two runners never run it twice.
What the runner may do. In homelab mode (
AUTH_ENFORCE=0) it has full access. In enterprise mode (AUTH_ENFORCE=1) it is a least-privilegeuser: it can't register integrations or set secrets, and reaches only the services/skills an admin assigned. For a runner that should act broadly, setRUNNER_ROLE=admin; for scheduled work on a person's behalf, give the job an owner so it runs act-as in that user's area (short-lived per-job token, no standing authority). See docs/authorization.md.Plan or API key? A Claude cloud task and the ChatGPT sign-in are the providers' own ways for this and count against your plan's limits; an API key bills per use. Because a runner is only woken when a job is due, the usage stays small either way.
Run it with a local model (Ollama)
AICortex is model-agnostic — including fully local models. LibreChat is a self-hosted chat UI with first-class MCP support, Ollama runs the model locally, AICortex is the brain/tools — nothing leaves your network. LibreChat connects to your existing AICortex over MCP with per-person OAuth (the same OAuth 2.1 + dynamic-registration flow Claude.ai uses) — no connector changes needed.
In short: make Ollama reachable on your LAN (OLLAMA_HOST=0.0.0.0), bring up the LibreChat stack (its own compose — never merged into AICortex's), add AICortex as an MCP server (type: streamable-http, requiresOAuth: true), authenticate once through your IdP, and drive it through a curated Agent so a mid-size local model isn't overwhelmed by 100+ tools.
Pick a tool-capable model (recent Qwen/Llama-class; small <7B models struggle with multi-step tools). Full step-by-step guide — compose,
.env, the OAuth connect, troubleshooting, and optional cloud models (OpenRouter, Ollama Cloud): docs/local-llm-librechat.md.
FAQ
Why a separate "brain" when Claude and ChatGPT already have memory? Because processing your data isn't the same as owning it. Built-in memory lives inside one vendor, one app, one model. AICortex is yours: model- and client-agnostic (the same brain on Claude, ChatGPT, a local Ollama model, desktop or phone — no lock-in), it reaches your own devices and files, and it keeps secrets in a vault on your NAS. Its action tools reduce what you paste into a cloud chat rather than add exposure — the sensitive value stays server-side and is referenced by name.
Why keyword search instead of semantic / vector search?
Deliberate. Memory is a curated, typed catalog — the handful of facts you (or the assistant) chose to keep — not an embedding pile you hope to retrieve from. A typed, human-readable catalog stays debuggable, portable and free of a vector database. (If the skill library ever grows large enough that paraphrase-matching hurts, opt-in local embeddings for skill_search only is the escape hatch — not a memory-wide graph.)
Why no built-in code sandbox / executor?
A code executor would be the single biggest attack surface and it breaks the no code, no redeploy principle. The sandbox pattern already exists as data: ssh_add a disposable, LAN-isolated jail host and ssh_run there. It's a documented pattern, not something baked into the connector.
Why no built-in Telegram / Slack / ntfy / … integrations?
Those are just HTTP APIs — so they're service_add + a skill, not new code. That's the whole point: a new capability is data + a skill, never a redeploy.
Do I need OIDC and a reverse proxy? For a public/cloud LLM client, yes — the endpoint must be reachable over HTTPS and authenticated (see Authentication & authorization). Running a purely local client? You can keep it on the LAN. Homelab mode keeps auth simple; enterprise mode adds roles + per-user isolation with one switch — see docs/authorization.md.
Security
- Auth fails closed. Without OIDC,
/mcpaccepts only bearer tokens (RUNNER_TOKENor a per-agent key);ALLOW_INSECURE=1runs it open for local development only. Enable OIDC before exposing the proxy for Claude or ChatGPT. - DNS rebinding blocked. Browser requests (and the WebUI) must come from an IP address, localhost, a name without a dot, a private-use name or the
BASE_URLhost; native clients are unaffected.MCP_ALLOWED_HOSTSmakes the host check strict. - SSRF guard.
service_add/mqtt_add/ftp_addare model-callable, so the registered-target list isn't a trust boundary by itself. Every outbound host is resolved and private / loopback / link-local / cloud-metadata addresses are blocked unless they fall insideINTERNAL_ALLOW_CIDRS(operator-only). Set it to the LAN/VPN ranges you actually use. - Encrypted vault, enforced. Secrets go in the vault via
secret_set(encrypted at rest, referenced by name, never returned).secret_setrefuses plaintext unlessSTORAGE_ENCRYPTION_KEYis set..envis only for bootstrap config. - Inbound webhooks authenticate themselves.
POST /hooks/<name>is served alongside/mcp/but not behind the MCP OAuth (external senders can't do OAuth) — instead each hook validates a shared secret token (theX-Webhook-Tokenheader only — never a URL query, so it can't leak into logs) and/or an HMAC signature (constant-time). Unknown hooks and bad/unsigned requests both return a uniform401(no hook-name enumeration), the body size is capped, and it only ever deposits into the inbox — it never reaches the tool surface. Expose only/hooks/*past your reverse proxy's auth, never/mcp. Don't want any public receiver? Leave webhooks unregistered (opt-in) or keep the/hookspath LAN-only. - TLS verified by default for FTP / MQTT / WebDAV / scanning; self-signed LAN devices opt out per-endpoint via the admin-only registration tools (
tls_insecure/ca_bundle). .envanddata/contents are git-ignored — never commit secrets.
AICortex has been through external security review (fail-closed vault, SSH host-key pinning, connect-time DNS-rebinding protection, resource limits, the authorization layer and per-user isolation). Full status & reporting: SECURITY.md.
🔐 How your secrets stay secret — encrypted at rest, never returned to the model, never in chat/repo, and how to set them safely (
secret_setor.env): docs/secrets.md.
REST API (for non-MCP clients)
Not every client speaks MCP. The native REST layer exposes the same tools over plain HTTP, so n8n, LangChain, an OpenAI-compatible client or a shell script can drive AICortex directly — through the same authorization and per-user areas as an OIDC session.
Three routes, served next to /mcp but authenticated by a per-user API key instead of OAuth:
An admin mints keys (they run through the same policy, never admin by default):
Call it with the key as a bearer token:
Security, by design: keys are hashed at rest (constant-time compare) and default-deny — a key reaches only the tools in its scopes allow-list, further narrowed by the identity's role and device areas. Secret-, key- and tenancy-management tools are never reachable via a key. Each key is rate-limited; pass ?stream=1 (or Accept: text/event-stream) for SSE on long-running tools. Full detail: docs/rest-api.md.
Proxy: expose
/api/*(and/hooks/*) past the reverse proxy without OIDC — the API authenticates itself by key. Never expose/mcpthat way.
Admin WebUI
Not everyone wants to manage secrets from a terminal or chat. /ui is a built-in,
self-contained admin panel (no extra container, no build step, no CDNs — strict CSP),
language-switchable DE/EN:
Screenshots use made-up demo data.
Login rides on your existing IdP (authorization code + PKCE): register one extra
redirect URI in the OIDC client — <BASE_URL>/ui/callback — and open <BASE_URL>/ui.
Everyone works in their own area; the management pages are for the admin role. Sessions
are signed HttpOnly cookies, mutations are CSRF-guarded, every action lands in the audit log
(names only, never values). Each page runs the same policy path as the MCP tools, so the
browser gets exactly the rights of the person's AI.
Without OIDC (local testing) the UI is open on the localhost-only bind — the same trust
model as the MCP endpoint itself. There is no separate username/password login: remote
access always goes through your IdP. Opt-out: UI_ENABLED=0.
First steps after the install — sign in, set up people, create keys and connect Claude, ChatGPT, Claude Code and other agents: docs/clients.md → Step by step.
Configuration
All config lives in .env (copy from .env.example):
OIDC, authorization and hardening variables are documented inline in .env.example and the Authentication & authorization section.
Deploying on a VPS or over a VPN
The connector is just an HTTPS MCP endpoint, so it runs anywhere Docker does. The SSRF guard keeps that safe:
- VPS, public APIs only: same reverse proxy + OIDC, set
BASE_URLto its public URL, leaveINTERNAL_ALLOW_CIDRSempty. - Reach home devices from a VPS: link the VPS and your LAN with a VPN (WireGuard, Tailscale, …) and add the VPN/remote subnet to
INTERNAL_ALLOW_CIDRS(e.g.100.64.0.0/10for Tailscale). - Multi-site: scope
FORWARDED_ALLOW_IPSto the proxy, list only trusted subnets inINTERNAL_ALLOW_CIDRS, and use a dedicated OIDC client.
Project structure
Dependencies are baked into the image at build time — no install-on-start volume.
data/,logs/andsecrets/keep their structure via.gitkeep; their contents are git-ignored.
Troubleshooting
See what's wrong first
A handful of read-only commands surface almost everything. Replace the placeholders (<compose-dir>, <device-ip>) with your own values.
After pulling a new image, restart your LLM client session — don't just "refresh tools". MCP clients freeze the tool list at connect, so new tools/parameters only appear on a fresh session. If a new parameter still doesn't show after
docker compose pull && up -d --force-recreate, confirm the container is really on the new image with command #3 above.
Common issues & fixes
Support ☕
AICortex is free and open source, and it will stay that way — no paid tier, no features held back.
If it keeps your assistant's memory going and you feel like saying thanks, a coffee is always gladly received:
Not in the mood for coffee? These help just as much:
- ⭐ A star — so others looking for a self-hosted brain find the project.
- 🐛 An issue — when something is wrong, unclear or could be better.
- 💬 A word to a friend — who wishes their assistant would finally remember them.
License
Apache License 2.0 © 2026 IkarusMK
来源:README.md,提交 ba4592c
工具
0版本历史
2- v2.3.4最新Nov 5, 2026
- v2.3.3Nov 4, 2026
评分
已满足适用检查项的 50%
该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。
- 近 30 天内可连通25 分
请保持端点能够响应 MCP 握手;SourceWeft 每 30 天探测一次。
- 已声明认证方式10 分
请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。
- 已列出工具15 分
请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。
- 描述必需15 分
- 图标10 分
- 文档15 分
- 许可证10 分