Nacre

work.nacre由 nacre.work 發布v0.41.0更新於 Nov 1, 2026

Self-hosted permission-aware context layer. Search returns only what the caller may read.

概覽

AI 產生的概覽

自架的權限感知知識索引,讓助理只取回請求者有權閱讀的文件。

可以做什麼
  • 在自架知識索引中進行混合檢索(稠密向量加 BM25),只回傳有權限的片段
  • 將文件匯入層中,支援 PDF、Office/OpenDocument、EPUB 與 RTF 經解析側車擷取
  • 在繼承的工作區與層權限(read、write、admin)下運作,權限過濾在索引內部預先執行
  • 以 JSON、JSONL 或 CSV 讀取記錄哪些文件被讀取的稽核日誌
  • 把某個層遷移到其他嵌入模型,切換前先做召回率檢核
適用情境
適合團隊自架文件索引、又需要代理遵守依使用者的存取規則,且結果能向稽核人員證明的場景。面向開發者代理與內部應用,而非通用聊天助理。
執行需求
以 npm 套件形式作為本機 STDIO 程序執行,也提供 Streamable HTTP。需要 NACRE_SERVICE_KEY 中的服務帳號金鑰,以及部署的完整環境(資料庫與後端設定);只有金鑰不足以啟動。另需自架部署(Docker Compose、PostgreSQL、Qdrant)與相容 OpenAI 的嵌入端點。
安裝前請注意
需在本機環境提供服務帳號金鑰與完整後端設定,包括資料庫憑證。它會寫入並索引文件,也能變更層的嵌入模型而觸發重建索引。文件層級授權、拒絕規則、SSO 與多租戶屬商業模組,此版本會拒絕。屬早期軟體,文件領先於程式碼。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Nacre,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

[Nacre]

Nacre

Your index. Your access rules. Your perimeter.
Agents see exactly what they're allowed to see.

nacre.work · Docs · Quickstart · Discussions


Nacre is a self-hosted knowledge index with fine-grained access control. Agents reach it over MCP, applications over a REST API. No chat interface, no company assistant — just the context layer underneath them.

Why

Vector search is a solved problem. What isn't solved: making sure an agent querying a company index sees exactly the documents the requesting user is cleared for — and being able to prove it to an auditor.

  • Permissions that inherit. Workspaces → layers, with read/write/admin inherited top-down. write does not imply read; admin implies both. Document-level grants and deny rules are commercial — this build refuses them and says so, rather than accepting a rule it cannot propagate.
  • Filtering happens inside the index. Access filters are applied during HNSW traversal, not after ranking, so top_k returns k permitted results rather than k minus whatever got stripped out.
  • MCP as a first-class surface. Streamable HTTP per the 2026-07-28 spec, and local STDIO for developer agents. Agents authenticate with a service account key; OAuth discovery is served (RFC 9728), and client registration is the authorization server's business rather than ours.
  • Hybrid retrieval, because agents ask for identifiers. Dense vectors and BM25 fused with reciprocal rank fusion, plus a cross-encoder rerank where a deployment configures one. Not offered as a differentiator — the line above is the honest one — but an agent searching for SQLSTATE 23505, an invoice number or a variable name needs the literal match, and a dense-only index does not reliably return it.
  • Bring your own models. Embeddings through any OpenAI-compatible endpoint, bound per layer. Changing the model on an existing layer is a reindex that keeps search answering throughout, and it is gated on recall against a query set you supply before it switches over.
  • A command line client. npx @nacre.work/cli signs in, creates a layer, walks a directory into it and searches — the four curl invocations the quickstart spells out, for when you want the result rather than the contract. A document that fails to index is a non-zero exit, so a nightly ingest cannot report success having indexed nothing.
  • Stays inside your network. Docker Compose, no phone-home.

Quickstart

bash
git clone https://github.com/nacre-work/nacre && cd nacrecp .env.example .envdocker compose --profile minimal up -d

Full walkthrough: docs/quickstart.md.

On an Apple Silicon Mac, read docs/apple-silicon.md first — the images are arm64 and the stack is native, but the embedder is the one piece you run on the host.

Layout

packages/api        REST API and authorization servicepackages/mcp        MCP server (Streamable HTTP + STDIO)packages/worker     indexing pipeline: parse, chunk, embedpackages/core       data model, permission resolver, shared typespackages/sdk        TypeScript SDKpackages/admin      community admin UIservices/parser     Python sidecar: bytes → {text, blocks, metadata}docs/               specifications — normative, and ahead of the code

State

Early, and it runs. The loop works end to end and has been driven by hand against a real PostgreSQL and a real Qdrant: create an organization, create a layer, grant someone read, ingest a document, poll the job to indexed, search and get the chunk back — and search as someone without the grant and get nothing while the vectors are still sitting in the index. Both surfaces work, REST and MCP over Streamable HTTP and STDIO alike. Revoking a grant removes the document from results on the next request: the permitted set is computed from the grants on every search, so there is no cache in the index to fall behind.

Search is rate limited per organization, unsafe methods take an Idempotency-Key, collections page by cursor, and reranking runs on the search path when a deployment configures a reranker. Tombstoned vectors are collected, and the SDK and the admin UI are written.

Signing in works: email and password, with rotating refresh tokens that end the session if one is replayed. init creates the first administrator and prints a generated password once. SSO is a commercial module.

The access log is readable: GET /v1/audit, newest first, cursor-paged, as JSON, JSONL or CSV. org_admin sees which documents were read — the question an audit log exists to answer — and platform_admin sees administrative actions and never that, which is rule 2 applied to the journal.

A layer can be moved onto a different embedding model. Qdrant will not add a named vector to a collection that exists, so the collection is replaced rather than altered: every point copied across with no embeddings computed, one statement to switch the pointer, then re-embedding one layer at a time. Search stays available and stays one query throughout. Before a layer switches, its reference query set is scored against the new model and a migration that lost recall stops instead of going live — that gate is off until you write a set, because it needs documents only you can pick.

A document can be uploaded as a form as well as sent as JSON, and a PDF, an Office or OpenDocument file (text, presentation or spreadsheet), an EPUB or an RTF is extracted by the parser sidecar. Both signals have to agree — the part declares the format's type and the bytes begin with its signature — because a declared type the bytes contradict is a disagreement, and sniffing alone would make the declared type decoration. Any other binary format is still refused at the edge, and a scanned PDF with no text layer is refused rather than indexed as nothing.

Tokens can be signed with an Ed25519 key instead of a shared secret, in which case the public half is published at /.well-known/jwks.json and only the process issuing tokens holds the private one.

docker compose --profile minimal up has been run from a clean clone, and the whole loop driven through it.

What is not built is what a commercial licence covers, and docs/licensing.md lists it: multi-tenancy, SSO, document-level permissions and deny rules, ID-JAG, SIEM export, a global admin, and quotas.

docs/ is the specification, and it still runs ahead of the code in places — start with docs/authz.md, which everything else depends on.

Invariants

Six rules. Breaking any of them is a security incident, not a bug. Details in docs/authz.md.

  1. The organization comes from the token and nowhere else.
  2. Access filtering is a pre-filter, never a post-filter.
  3. A failure to evaluate permissions denies access.
  4. "No permission" and "no such object" return identical responses.
  5. A deleted document is never returned, including before garbage collection.
  6. write does not imply read.

License

Apache 2.0 — all of it. Everything above is in this repository and stays there.

Tenancy (suspension, offboarding, quotas), SSO over OIDC with SCIM group sync, issuing document-level grants and deny rules, EMA, SIEM forwarding, global admin, backup, a required second factor and filtered directory administration are commercial modules. They live in a separate private repository under a separate license and are not distributed with this one — see docs/licensing.md for the line between the two and the one question that decides it.

Where this build meets one of them it refuses in the open: a deny rule or a document-scoped grant is answered 400 with the reason, rather than accepted and silently not enforced.

The Nacre name and mark are trademarks; see TRADEMARK.md.

Supporting this

There is no hosted tier, no seat count and nothing metered here, so the open half earns nothing by being used — which is the point, and also why it is worth saying who pays for it. The commercial modules do, and they are for the organizations that need them; a developer running this on a laptop is never the person being asked.

If it saved you a week, the Sponsor button at the top of this repository is the other way to say so. Nothing in this repository is behind it, and nothing will be.

來源:README.md,提交 5b1fd3e

工具

0
SourceWeft 曾在隔離沙箱中以無憑證方式啟動該軟體包一次,以列出其工具,但未能完成:伺服器未能啟動。

版本歷史

2
  1. v0.41.0最新Oct 25, 2026
  2. v0.26.4Sep 26, 2026

評分

已滿足適用檢查項的 50%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分