Iris

官方

MCP原生代理評估與可觀測性伺服器,具備追蹤記錄、輸出品質評估、成本追蹤、12個內建評估規則、即時儀表板及PII偵測功能

你可以用 Iris MCP 做什麼?

  • 記錄並評估代理執行 — 要求您的助理將任務記錄到 Iris,並針對輸出取得確定性的品質、安全性與成本評分。
  • 查詢追蹤歷史 — 透過篩選、分頁與時間範圍支援,擷取已儲存的代理執行紀錄,以檢視過往表現。
  • 跨時間比較執行 — 在同一組問題上並排分析兩次執行,以找出代理行為中的退化或改進。
  • 評分輸出品質 — 針對 25 條內建規則評估任何文字,涵蓋完整性、相關性、安全性與成本,並具備 PII 與提示注入偵測。
  • 執行示範儀表板 — 啟動一個內含範例失敗與判決的種子示範資料庫,以便在本機探索 Iris 的評分引擎。

文件

Iris — 別再靠感覺交付 agent

Glama Score Install in Cursor Install in VS Code npm version GitHub stars CI OpenSSF Scorecard OpenSSF Best Practices License: MIT Docker PulseMCP mcp.so

Iris 為每一次 agent 執行評分品質、安全性與成本——在你的機器上,無需 SDK、無需帳號。 多數 agent 專案靠跑幾個記得的提示詞、再目測輸出,來檢查品質。Iris 用你可稽核的數字取代這套做法:你的 agent 執行紀錄會落入你磁碟上的 SQLite 資料庫,25 條內建規則以確定性方式為其評分——PII、提示注入、幻覺標記、成本門檻,以及 agent 自身的工具呼叫——免費、不需 LLM 呼叫,另可選配設有每次評估硬性成本上限的 LLM 評審,處理語意層面的問題。每一條規則都可檢視、可編輯,因為無法稽核的評審,不過是披著數字的感覺。MIT 授權、無遙測。除非你開啟以下任一功能,否則沒有任何資料離開你的機器:OpenTelemetry 端點(IRIS_OTEL_ENDPOINT),可將追蹤匯出到你指定的 collector;使用你自己金鑰的 LLM 評審,會將受評文字傳送給該供應商,其引用檢查會抓取輸出所引用的頁面;或 webhook,只會將 ID、判定與規則名稱(絕不含文字)貼到你設定的位址。

需要 Node.js 22.13 或更新版本。 用 node --version 檢查。

The demo: Failures, a failure opened, two runs compared

示範資料庫,由 scripts/demo-media.mts 錄製;來源是 demo.mp4。靜態圖:dashboard-overview.png。

60 秒內在畫面上看到失敗案例

不需要 agent 接線、不需要設定——一條指令:

npx @iris-eval/mcp-server --demo

這會建立一個示範資料庫——五個小型 agent、兩週的執行紀錄、每一條判定都是引擎自己的——並在 http://localhost:6920 提供儀表板(首次執行時瀏覽器會自動開啟)。儀表板預設停在 Failures:先顯示最嚴重、最新的失敗,每張卡片標明規則與證據。值得點進去看看——被安全規則攔下的 PII 外洩、論壇貼文中隱藏指令被摘要器遵從、來源文件從未提到的數字、同一組十二道問題的兩次執行以區間比較(Runs)、一條已部署的自訂規則與一條暫停的規則及其稽核列,以及一次失敗的 LLM 評審分數與其理由。

示範資料存放在獨立資料庫(你 Iris 家目錄下的 demo.db——macOS/Linux 為 ~/.iris,Windows 為 %USERPROFILE%\.iris),絕不會與你的真實追蹤混在一起。用一條指令即可全部移除:

npx @iris-eval/mcp-server --demo-clear

接上你自己的 agent

首先,證明安裝在此機器上可用——它離線執行,不會開啟你的任何東西:

npx @iris-eval/mcp-server --self-test   # exit 0 = healthy

接著把 Iris 加入你的 MCP 用戶端。一條指令即可寫入用戶端自己的設定檔、保留其中所有其他伺服器,並鎖定你執行的版本:

npx -y @iris-eval/mcp-server install claude-code

支援的用戶端:claude-code、claude-desktop、cursor、windsurf、continue、vscode、cline、zed、codex、gemini。install --list 會顯示此機器上找到的用戶端、各自執行的 Iris 版本與讀取的設定檔;install <client> --uninstall 則將 Iris 移除。每個用戶端共用同一個資料庫,因此升級後可用 install --upgrade 一次全部遷移(更新)。重新啟動用戶端即可載入。

Claude Desktop:一鍵完成。 從 0.20.0 起的每個版本都附帶 iris-eval.mcpb,一個 MCP Bundle:下載最新版、開啟,Claude Desktop 便會顯示安裝對話框。其中沒有任何必填項目——LLM 評審用的 Anthropic 或 OpenAI 金鑰為選配,儀表板則是一個預設關閉的開關。該 bundle 內含 npm 套件及其相依項目,因此無需另行安裝任何東西:Claude Desktop 會在其搭載的 Node 為 22.13 或更新版本時(Claude Desktop 1.1.6679 搭載 24.13)以該 Node 執行 Iris,而 Iris 使用 Node 內建的 SQLite 儲存追蹤,存放在與其他安裝相同的 ~/.iris。發行說明會說明如何驗證其簽章與建置證明。

它可在任何 MCP 用戶端中執行,而它所點名的每個用戶端都有一列記錄實際檢查過的內容。每次 CI 執行皆已驗證:Claude Code、Gemini CLI——真實用戶端會從安裝程式寫入的設定啟動 Iris,並回報已連線(claude mcp list、gemini mcp list),涵蓋 Linux、macOS 與 Windows;Claude Code 的 capture 外掛鉤子也是透過真實腳本驅動。根據各用戶端自身的 MCP 文件宣稱支援——安裝程式會寫入用戶端文件所記載的設定形狀,且該寫入器已針對該形狀測試;Iris 團隊無人實際看過其連線:Claude Desktop、Cursor、Devin Desktop (Windsurf)、Continue、VS Code、Cline、Zed、OpenAI Codex CLI。每一列都附來源與讀取日期:https://iris-eval.com/clients. 若要手動操作,一個區塊即可,含儀表板:

{
  "mcpServers": {
    "iris-eval": {
      "command": "npx",
      "args": ["-y", "@iris-eval/mcp-server", "--dashboard"]
    }
  }
}

你的用戶端會在連線時列出 Iris 的十二個工具,儀表板則在 http://localhost:6920. 提供服務。現在把這段貼給你的 agent:

把最後那項任務記錄到 Iris 並評估輸出。

追蹤會連同分數出現在儀表板上。偏好無頭模式的 MCP 伺服器?從參數中移除 --dashboard——你隨時可用 npx @iris-eval/mcp-server --dashboard 開啟同一個儀表板。

一開始值得知道的一件事: MCP 工具是在模型決定呼叫時才會被呼叫。Iris 不會攔截你的 agent,因此追蹤是在你的 agent 要求記錄時才會被記錄——無論是你叫它做,還是你的程式碼直接呼叫工具。叫你的 agent「把這個記錄到 Iris 並評估」即可。如果你想要不依賴模型選擇的擷取方式,POST /api/v1/traces 正是做這件事——你的程式碼透過純 HTTP 傳送追蹤,迴路中沒有模型(見 docs/http-ingest.md)。路線圖上的 CLI 與主機鉤子將是同一端點的輕量用戶端。

透過 HTTP 擷取(迴路中無模型)

ingest 端點位於儀表板埠——預設為 6920,而非 MCP 傳輸埠——且僅在儀表板執行期間存在。傳入 --dashboard(或設定 IRIS_DASHBOARD=true);單獨的 --transport http 不會啟動它,而對傳輸埠的請求會回傳 404。儀表板啟動後,任何能傳送 HTTP 請求的東西都能記錄追蹤——並可選擇在同一請求中執行確定性評估。同一埠上的 GET /api/v1/capabilities 會說明此伺服器能評判什麼、每條規則需要什麼、評審狀態及啟用步驟、以及限制——與 MCP 資源 iris://capabilities 提供的物件相同——因此 HTTP 呼叫端能取得 MCP 用戶端在 initialize 時得到的框架:

curl -s -X POST "http://127.0.0.1:6920/api/v1/traces" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_name": "support-bot",
    "input": "What is the refund policy?",
    "output": "Refunds are available within 30 days of purchase.",
    "evaluate": true,
    "eval_type": "safety"
  }'

回傳 201,內含已儲存的 trace_id 與評估結果(在 --demo 模式下,端點會以 403 拒絕寫入,因此示範資料絕不會與你的資料混在一起)。端點接受與 log_trace 工具相同的主體,並與儀表板其餘部分共用同一中介層堆疊:預設啟用 loopback 綁定與 DNS-rebinding 防護,設定 Bearer 驗證後亦會啟用。關於它的兩個事實: 除非 Iris 以 --api-key(或 IRIS_API_KEY)啟動,否則它接受未驗證的寫入——loopback 綁定是預設將其限制在你機器上的機制,因此在綁定到 loopback 之外前請先設定金鑰;它所儲存的內容是逐字保留——input 與 output 會以原樣存入 iris.db,包括 no_pii 隨後標記的任何文字。完整契約、欄位參考與錯誤語意:docs/http-ingest.md。

擷取每個 Claude Code 回合(選配)

/plugin marketplace add iris-eval/mcp-server
/plugin install iris-eval-capture@iris-eval

第二個、另行安裝的外掛:三個鉤子會記錄每個回合的提示詞、工具呼叫與最終答案,並以分離方式交給 iris-eval ingest,儲存的評估文字中會遮蔽關鍵片段——這種擷取不依賴模型決定呼叫工具。它絕不會記錄模型已記錄過的回合、絕不輸出、絕不阻塞、絕不將任何資料傳送到任何地方。單獨安裝 iris-eval 不會改變你的回合迴路。限制與移除方式:claude-plugin-capture/README.md。

Python

pip install iris-eval
from iris_eval import IrisClient
iris = IrisClient()                       # IRIS_URL, or the running dashboard's runtime.json
iris.evaluate_output("…", input="…", agent_name="support-bot")["verdict"]   # {"state": "pass", "basis": "clean", "by": []}

一個針對 0.16.0 及更新版本伺服器 HTTP API 的輕量用戶端,獨立版本化——iris_eval.__version__ 與 PyPI 頁面會標示其版本號,與伺服器版本不同:log_trace()、evaluate_output()、get_traces()、get_trace()、health()、capabilities(),同步與非同步、型別化答案、伺服器對拒絕的原始說明——以及一個 pytest 外掛:iris fixture 與 assert_iris(output, expect="pass"),可對判定的狀態做斷言。packages/python/README.md。

記錄每一次 OpenAI 與 Anthropic 呼叫

from iris_eval import wrap_openai
client = wrap_openai(OpenAI(), agent_name="support-bot")   # every call: a GenAI span to POST /v1/traces, scored
import { wrapOpenAI } from '@iris-eval/sdk';
const openai = wrapOpenAI(new OpenAI(), { agentName: 'support-bot' });

將供應商用戶端包一層,每次模型呼叫就會變成一個 OpenTelemetry GenAI span,傳送到 OTLP 入口,連同輸入、輸出、token 用量與工具呼叫一起儲存並評分:這種擷取不依賴模型呼叫工具。Python 用戶端中的 wrap_openai / wrap_anthropic;@iris-eval/sdk 中 Vercel AI SDK 的 wrapOpenAI、wrapAnthropic 與 irisMiddleware。兩者皆尚未發布(下一個 iris-eval 版本會在 PyPI 上;@iris-eval/sdk 在首次 npm 發布前以原始碼建置)。涵蓋串流、SDK 的串流輔助函式與工具呼叫,原始用戶端不會被修改,且 Iris 當機絕不會中斷呼叫——packages/sdk/README.md、packages/python/README.md。

為每一次 LangChain 與 LangGraph 執行評分

from iris_eval.langchain import IrisCallbackHandler
graph.invoke(inputs, config={"callbacks": [IrisCallbackHandler(agent_name="support-bot")]})

每個頂層執行會變成一個追蹤(該執行、其模型呼叫、工具呼叫與圖形節點作為 GenAI span),含輸入、輸出、工具呼叫、token 用量與判定。Python 在用戶端中(下一個版本,尚未發布至 PyPI),JavaScript 則為 @iris-eval/langchain(尚未發布至 npm)。兩者皆已在 CI 中以真實 LangGraph 應用程式搭配腳本化模型驗證;LangSmith 自身的 OpenTelemetry 匯出也以同樣方式驗證——docs/otel-recipes.md。

無需伺服器的 CI 閘道

npx -y @iris-eval/mcp-server ingest --file traces.ndjson --evaluate --fail-on detector_veto

或 GitHub Action(0.16.0),會在你指定的判定上讓工作失敗、將收據寫入工作摘要,並以單一 pull-request 留言原位更新發布:uses: iris-eval/mcp-server/.github/actions/gate@v0.19.0 搭配 traces: traces.ndjson——docs/ci-gate.md。 第四道門(0.15.0):POST /v1/traces 在儀表板連接埠上接收您的 OpenTelemetry 儀器已發出的 OTLP/HTTP JSON 或 protobuf(Python SDK 的匯出器僅支援 protobuf,因此這也是 Python 的入口),每個 OTLP trace 都會變成一個帶有其 spans 的 Iris trace — docs/otel-integration.md;每個框架一個配方(Pydantic AI、Google ADK、LangGraph via LangSmith、CrewAI、OpenAI Agents SDK(Python 和 JavaScript)、LlamaIndex、AutoGen、Microsoft Agent Framework、Semantic Kernel、Vercel AI SDK 和 Mastra),每個配方都由一個 fixture 驗證,詳見 docs/otel-recipes.md。ingest 從 stdin 或檔案讀取一個 JSON trace(或 NDJSON,每行一個),儲存它,並在 evaluate_output 執行的完全相同的規則下評估它,每個 trace 輸出一行 JSON,包含 verdict 及其依據,當 verdict 符合 --fail-on 時以退出碼 1 結束。--dataset <id|label> 將該門檻限制為資料集中的 case keys(POST /api/v1/datasets 將一次執行的 case keys 提升為一個),因此工作只會在您選擇的 cases 上失敗。完整配方、退出碼和八個依據位於 docs/ci-gate.md。

將規則寫成程式碼

eval.plugins 在 config.json 中載入您編寫的規則 — 一個 ES module,其 default export 是 { name, kind, mechanism, version, needs, evaluate(ctx) } — 並以檔案的 sha256 固定,因此自您固定以來已更改的檔案會拒絕啟動而不是執行。已載入的外掛程式會像內建規則一樣觸發,並顯示在 list_rules 下的 plugins。合約、雜湊配方以及外掛程式可能回傳的內容:docs/plugins.md。

在您自己的程序中使用的引擎

評估引擎是可匯入的 — 無需伺服器、無需資料庫、無需模型:

import { EvalEngine, defaultConfig } from '@iris-eval/mcp-server/engine';

const engine = new EvalEngine(defaultConfig.eval.defaultThreshold, defaultConfig.eval.ruleThresholds, defaultConfig.eval);
const result = await engine.evaluateAll({ output: answer, input: prompt, toolCalls, costUsd });
result.verdict.state;       // 'pass' | 'fail' | 'unknown', with result.verdict.basis and result.interpretations

伺服器執行的相同引擎、相同規則和相同 composer;builtInRules()、createCustomRule()、compose() 以及已發布準確度讀取器與其一起匯出。

HTTP 路由的型別化用戶端

import { createClient } from '@iris-eval/mcp-server/client';

const iris = createClient({ baseUrl: 'http://127.0.0.1:6920', apiKey: process.env.IRIS_API_KEY });
const { trace_id, evaluation } = await iris.logTrace({ agent_name: 'support-bot', input, output, tool_calls, evaluate: true });
evaluation?.verdict?.state;  // the same object evaluate_output returns

每個入口上的一個 body:它是 log_trace 和 iris-eval ingest 接受的內容。拒絕會拋出 IrisClientError,包含伺服器自己的句子和狀態。兩個子路徑在每次建置時都從打包的 tarball 中檢查。

驗證您的安裝

npx @iris-eval/mcp-server --self-test   # offline diagnostic; exit 0 = healthy, 1 = a check failed
npx @iris-eval/mcp-server --version     # prints the bare version, e.g. 1.2.3

--self-test 首先建立您的 Iris home(如果缺失)並檢查它是否可寫入(如果不是,退出碼 1,並指明路徑),報告您的資料庫搜尋索引的位置(完整、背景建置迄今已索引多少 traces,或此 SQLite 上沒有 FTS5),讀取您的資料庫 schema(如果此版本或固定到較舊版本的 MCP 用戶端無法開啟它,退出碼 1,並附上修復方法),然後在隔離的臨時 home 中執行其檢查 — 儲存往返、植入的 SSN 和植入的注入被安全規則捕獲、儀表板啟動、DNS-rebinding 防護。您的真實資料庫只會被讀取,絕不會更改。Iris 寫入的所有內容都位於一個目錄下,您的 Iris home:預設為 ~/.iris(Windows 上為 %USERPROFILE%\.iris),或 IRIS_HOME 指向的任何位置。iris.db、config.json、custom-rules.json、audit.log、preferences.json 和 demo 檔案都位於此處;將 IRIS_HOME 指向暫存目錄以試用 Iris,而不觸及您的真實資料。

按工具設定
用戶端狀態含義閱讀
Claude Code已驗證測試在每次 CI 執行中驅動真實用戶端2026-09-25
Claude Desktop已聲稱安裝程式寫入用戶端文件記錄的形狀,且該寫入器已針對該形狀測試;Iris 方面沒有人看過它連線2026-09-25
Cursor已聲稱安裝程式寫入用戶端文件記錄的形狀,且該寫入器已針對該形狀測試;Iris 方面沒有人看過它連線2026-09-25
Devin Desktop (Windsurf)已聲稱安裝程式寫入用戶端文件記錄的形狀,且該寫入器已針對該形狀測試;Iris 方面沒有人看過它連線2026-09-25
Continue已聲稱安裝程式寫入用戶端文件記錄的形狀,且該寫入器已針對該形狀測試;Iris 方面沒有人看過它連線2026-09-25
VS Code已聲稱安裝程式寫入用戶端文件記錄的形狀,且該寫入器已針對該形狀測試;Iris 方面沒有人看過它連線2026-09-25
Cline已聲稱安裝程式寫入用戶端文件記錄的形狀,且該寫入器已針對該形狀測試;Iris 方面沒有人看過它連線2026-09-25
Zed已聲稱安裝程式寫入用戶端文件記錄的形狀,且該寫入器已針對該形狀測試;Iris 方面沒有人看過它連線2026-09-25
OpenAI Codex CLI已聲稱安裝程式寫入用戶端文件記錄的形狀,且該寫入器已針對該形狀測試;Iris 方面沒有人看過它連線2026-09-25
Gemini CLI已驗證測試在每次 CI 執行中驅動真實用戶端2026-09-25

每一行都包含檢查內容:iris-eval.com/clients。沒有行就不會稱任何用戶端為受支援。

npx -y @iris-eval/mcp-server install <client> 為您寫入這些內容。手動操作,按用戶端:

Claude Desktop

編輯您的 MCP 設定檔:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json

新增上述 JSON 設定,然後重新啟動 Claude Desktop。

Claude Code

claude mcp add --transport stdio iris-eval -- npx -y @iris-eval/mcp-server

然後重新啟動工作階段(/clear 或重新啟動)以載入工具。

Windows 注意事項: 不要 使用 cmd /c 包裝器 — 它會導致路徑解析問題。npx 命令可直接使用。

Cursor

將上述 JSON 設定新增到 ~/.cursor/mcp.json(每個專案)或工作區中的 .cursor/mcp.json,並在 iris-eval 條目中帶上 "type": "stdio" — Cursor 的文件將其標記為必填。

Devin Desktop (Windsurf)

將上述 JSON 設定新增到 mcp_config.json:macOS 和 Linux 上為 ~/.config/devin/mcp_config.json,Windows 上為 %APPDATA%\devin\mcp_config.json。

Continue

將上述 JSON 設定儲存為 Continue 的 mcpServers 資料夾中的獨立檔案:~/.continue/mcpServers/iris-eval.json(每個工作區)或其中一個的 .continue/mcpServers/iris-eval.json。

VS Code(原生 MCP)

新增到工作區中的 .vscode/mcp.json(注意:VS Code 使用 servers,而不是 mcpServers):

{
  "servers": {
    "iris-eval": {
      "command": "npx",
      "args": ["-y", "@iris-eval/mcp-server"]
    }
  }
}

Cline

開啟 Cline 的 MCP Servers 面板 → Configure MCP Servers,並將上述 mcpServers JSON 設定新增到 cline_mcp_settings.json(~/.cline/data/settings/cline_mcp_settings.json,由 Cline 在 VS Code、JetBrains 和 CLI 中共享)。

Zed

新增到 Zed settings.json:

{
  "context_servers": {
    "iris-eval": {
      "command": "npx",
      "args": ["-y", "@iris-eval/mcp-server"],
      "env": {}
    }
  }
}

OpenAI Codex CLI

新增到 ~/.codex/config.toml:

[mcp_servers.iris-eval]
command = "npx"
args = ["-y", "@iris-eval/mcp-server"]

Gemini CLI

將上述 mcpServers JSON 設定新增到 ~/.gemini/settings.json。Gemini CLI 僅在它信任的資料夾中連線到 MCP 伺服器:如果 gemini mcp list 顯示 iris-eval 為 Disabled,請在該資料夾中執行 /permissions。

其他支援 MCP 的用戶端

Iris 是一個標準的 stdio MCP 伺服器 — 一個 npx @iris-eval/mcp-server 命令,無需 SDK,無需程式碼更改。如果您的用戶端支援 MCP,它就支援 Iris。用戶端設定格式會更改;如有疑問,請查閱您用戶端的 MCP 文件並將其指向該命令。

其他安裝方法

# Global install (recommended for persistent data and faster startup)
npm install -g @iris-eval/mcp-server
iris-eval --dashboard

# Docker — two servers, two ports: 3000 = MCP HTTP transport,
# 6920 = dashboard (which also serves the POST /api/v1/traces ingest endpoint).
# The image binds 0.0.0.0 inside the container, so a key is required (see Production).
# The volume is the Iris home: the database, deployed rules and audit log persist in it.
docker run -p 3000:3000 -p 6920:6920 -v iris-data:/data \
  -e IRIS_API_KEY="$(openssl rand -hex 32)" ghcr.io/iris-eval/mcp-server

提示: 全域安裝(npm install -g)將 traces 持久儲存在 ~/.iris/iris.db。使用 npx,traces 會持久儲存在相同位置,但由於套件解析,啟動速度較慢。

您獲得的內容

Trace 記錄具有每個工具呼叫延遲、token 使用量和 USD 成本的階層式 span 樹。儲存在 SQLite 中,可即時查詢。
輸出評估4 個類別中的 25 個內建規則:完整性、相關性、安全性、成本。PII 偵測(21 種模式:SSN、信用卡、電話、電子郵件、IBAN、出生日期、MRN、IP、API 金鑰、護照,加上 AWS/Slack/SendGrid/GitHub/Google/npm/DigitalOcean tokens、URL 中的憑證、secret 命名的指派、PEM 私鑰區塊和種子短語;出生日期、醫療記錄號碼、護照和種子短語僅在其標籤旁邊觸發,依設計)、提示注入(38 種模式,短語 + 結構)、stub 輸出偵測、幻覺偵測(25 種基於上下文的捏造/矛盾訊號 — 傳遞 input 以針對代理的來源材料進行接地),以及六個讀取代理所做事情的軌跡規則:未確認的失敗工具呼叫、重複的呼叫(按呼叫、按重複序列,或一旦您傳送 tools 則按目標)、工具自己的 JSON Schema 拒絕其引數且代理從未重試的呼叫、答案引用但代理讀取的內容中未出現的檔案、目錄或 URL、在 TOOL RESULT 中到達且隨後被後續呼叫遵守的指令,以及花費比您的步驟預算更多工具呼叫的任務。軌跡可以作為 tool_calls 或作為 OpenTelemetry TOOL spans 到達。使用 Zod schemas 新增自訂規則。
LLM-as-Judge可選的語義評分,透過 Anthropic 或 OpenAI — 自備 API 金鑰。七個範本。設定 IRIS_RELEVANCE_JUDGE_MODEL 後,answers_the_ask 會詢問 relevance 評判者並使離題答案失敗;沒有它,規則會以詞彙方式讀取請求並提供建議。每次評估的硬性成本上限(IRIS_LLM_JUDGE_MAX_COST_USD_PER_EVAL,預設 $0.25),結果中會揭露每次評估的定價。
成本可見性任何時間範圍內所有代理的總成本。設定預算閾值。當代理超支時收到標記。一個傳送 token 計數和模型但沒有成本的 trace(大多數 OpenTelemetry 和框架 traces)會以模型的列表價格定價,並在其顯示的所有位置標記為估計值;pricing.models 在 config.json 中為內建表格未涵蓋的模型定價 — docs/cost.md。
Web 儀表板即時深色模式 UI,首先顯示失敗、最差和最新的項目 — 具有對每個 trace 文字的全文搜尋的 trace 視覺化、評估結果、成本分解,以及一個命令面板(⌘K),可搜尋您自己的規則、traces 和 evals。
本地優先所有內容都位於您磁碟上的 SQLite 中。無帳戶、無註冊、無遙測。僅在您選擇加入的地方發生對外 HTTP:您自己的 LLM-judge 金鑰、引用擷取、您設定的 OTel 匯出器,或您設定的 webhook。

接下來發展方向:能力地圖 — 每個 Iris 可以被問到的關於每個主題的問題,以及它擁有和缺少的內容 — 和 三條軌道。

已測量,而非聲稱

每個內建規則都有公開的精確率、召回率和 F1 值,附 95% 信賴區間,這些數值是在本儲存庫中的標註語料庫(proof/corpus/)上測量的,並可透過單一指令 npm run proof 離線重新產生,無需金鑰或模型參與。這些數字分屬兩種不同類型,頁面從不將它們混為一談:有些規則是針對模型透過閱讀失敗本身所給出的標籤來測量,這衡量的是偵測能力;其餘規則則對照其自身記錄的定義進行獨立檢查,這顯示程式碼實作了其公式,但對於該公式是否能捕捉失敗則不置可否。proof/RESULTS.md 和證明頁面會標記每個規則。CI 會在每次拉取請求時重新執行測量,若提交的數字與程式碼產生的結果不同則失敗,因此規則不能在不改變其數字的情況下變更。這些數字位於 iris-eval.com/proof 和 proof/RESULTS.md;語料庫的製作方式、其不包含的內容,以及如何解讀區間,請參閱 docs/proof.md。該語料庫是合成且由模型標註的——人工盲標尚待完成,頁面已如此聲明;node proof/blind-sample.mjs 會抽取可重現的樣本以解決此問題。

MCP 工具

Iris 註冊了十二個工具,任何相容 MCP 的代理程式皆可呼叫——涵蓋追蹤與規則生命週期、跨執行比較、LLM 作為評判者,以及語意引用驗證:

  • log_trace — 記錄代理程式執行,包含跨度、工具呼叫、Token 用量和成本;傳入 evaluate: true 可在同一次呼叫中進行評分
  • evaluate_output — 根據完整性、相關性、安全性和成本規則(啟發式、確定性、免費)評分輸出品質
  • get_traces — 查詢已儲存的追蹤,支援篩選、分頁和時間範圍,並透過 q 找到代理程式說出某句話的執行:對輸入、輸出、工具呼叫值和中繼資料進行全文檢索,依相關性排序,並標記符合的字詞
  • list_rules — 列舉已部署的自訂評估規則(唯讀)
  • deploy_rule — 註冊新的自訂評估規則,使其在該類別的每次 evaluate_output 時觸發
  • delete_rule — 移除已部署的自訂規則(具破壞性、冪等)
  • delete_trace — 依 ID 移除單一已儲存追蹤(具破壞性、租戶範圍)
  • evaluate_with_llm_judge — 透過 LLM(Anthropic 或 OpenAI)進行語意評估。七種範本:準確性、有用性、安全性、正確性、忠實性、任務完成、相關性。有成本上限,每次評估價格公開。自備 API 金鑰(IRIS_ANTHROPIC_API_KEY 或 IRIS_OPENAI_API_KEY)——Iris 不代理或轉發 LLM 呼叫。
  • verify_citations — 從輸出中擷取引用(編號、作者-年份、URL、DOI),透過受 SSRF 防護且網域白名單的解析器取得來源,並使用 LLM 評判者檢查每個來源是否確實支援被引用的主張。選擇性啟用對外 HTTP。與 evaluate_with_llm_judge 相同的 BYOK 要求。
  • compare_runs — 變更是否讓代理程式變差?比較兩次已儲存評估的執行:當執行共用案例金鑰時使用配對精確檢定,否則使用差異區間,誠實的「無法判斷」並附上所需案例數,或「在容許範圍內等效」。每個規則都帶有自己的單尾檢定,並一起校正(Benjamini–Hochberg),因此二十個規則無法製造出虛假的迴歸
  • compare_traces — 代理程式回答相同問題的可靠性如何?每個案例的通過率附區間,不穩定案例優先,並有尊重重複的整體比率
  • evaluate_runs — 在今日規則下重新評分執行中的所有追蹤,產生新的執行,因此規則變更永遠不會被解讀為代理程式變更

啟用 LLM 評判者(選用;確定性規則永遠不需要)

  1. 從 Anthropic 或 OpenAI 取得 API 金鑰。
  2. 將其放入執行 Iris 的處理程序環境中,而不僅是你的 shell。Claude Code、Claude Desktop、Cursor 和大多數 MCP 用戶端:在 MCP 設定中 iris-eval 條目的「env」區塊——「iris-eval」:{「command」:「npx」,「args」:[「-y」,「@iris-eval/mcp-server」],「env」:{「IRIS_ANTHROPIC_API_KEY」:「sk-ant-...」} }(OpenAI 金鑰則用 IRIS_OPENAI_API_KEY)。Docker:在 run 指令加上 -e IRIS_ANTHROPIC_API_KEY=...。HTTP 或 CI:在啟動 iris-eval 前先 export。
  3. 重新啟動 MCP 工作階段。執行中的處理程序永遠不會看到啟動後才設定的變數。
  4. 從用戶端內部確認:讀取 iris://capabilities——judge.enabled 必須為 true。在你的 shell 中 export 的金鑰不會傳遞給你用戶端啟動的處理程序,除非其設定列出它。在機器上,npx @iris-eval/mcp-server --self-test 會印出該 shell 的評判者行,而 GET /api/v1/health 會回報執行中儀表板的 judge.enabled。
  5. 花費防護:每次呼叫由 IRIS_LLM_JUDGE_MAX_COST_USD_PER_EVAL(預設 0.25 美元)設上限,若最壞情況會超過則在花費前拒絕。Iris 直接使用你的金鑰呼叫提供者,絕不代理。
  6. 選用:設定 IRIS_RELEVANCE_JUDGE_MODEL 為有價格的模型 ID(例如 claude-haiku-4-5),讓 answers_the_ask 要求評判者檢查每個答案是否回應其提問,並讓離題的答案失敗。這是每次帶有輸入的評估的一次評判者呼叫,使用你的金鑰且在上述上限內;僅有金鑰不會啟用它。每次呼叫會將該輸入和輸出傳送給模型的提供者,個人資料和憑證的 no_pii 旗標會先被取代(IRIS_RELEVANCE_JUDGE_REDACT=off 則原樣傳送)。每個 UTC 日最多花費 IRIS_RELEVANCE_JUDGE_DAILY_BUDGET_USD(預設 1 美元),每個請求最多進行 IRIS_RELEVANCE_JUDGE_MAX_CALLS_PER_REQUEST 次呼叫(預設 20);超過任一限制後,answers_the_ask 會以詞彙方式讀取提問並說明原因。

當 IRIS_OTEL_ENDPOINT 已設定時,log_trace 呼叫也會發出盡力而為的 OTLP/HTTP JSON 匯出,送往任何 OpenTelemetry 收集器(Jaeger、Grafana Tempo、Datadog OTLP、Honeycomb 等)。請參閱 docs/otel-integration.md。

passed 如何決定

evaluate_output 同時回傳 score 和 passed 旗標——它們回答不同的問題:

  • score(0..1)是執行規則的加權平均值——品質梯度。
  • passed 是出貨/不出貨的裁決,且永遠不會參考分數。組合器依每個規則所提出的主張類型來讀取:你設定的政策會阻擋;關鍵偵測器會否決;被要求但無法回答的關鍵檢查會使裁決為未知(passed: false)而非乾淨;其餘每個偵測器結合成輸出為不良的單一機率,並與你在 eval.falsePassCost 中陳述的損失比率(預設 1,因此臨界值為 0.5)權衡。verdict.basis 指出決定層,verdict.by 指出規則,verdict.also 列出所有也會決定它的後續層;interpretations[] 說明失敗的規則為何未決定,以及哪個設定會改變此情況,並指出未被評判的問題以及可讓其被評判的輸入。

真正的安全違規會硬性失敗。預設情況下,no_pii、no_injection_patterns 和 no_blocklist_words 是關鍵規則:若其中一個失敗,無論其他規則得分多高,評估都會回報 passed: false,且回應會在 critical_failures 中指出肇事者。洩漏的 SSN 無法被平均掉。哪些內建規則是關鍵的是部署設定(eval.criticalRules / eval.nonCriticalRules);每個規則結果都帶有有效的 critical 旗標和 criticalSource,且 list_rules 會回報此伺服器套用的名冊。使用 severity: "high" 或 "critical" 部署的自訂規則以相同方式硬性失敗;low/medium 嚴重性僅影響分數。一個需要知道的界線,在所有介面上以相同方式陳述:跳過的關鍵規則(缺少上下文、定義損壞,或正則表達式在沙箱預算中被終止)尚未評判輸出且不會否決——每個此類規則都會在 critical_skipped 中被點名。必須關閉失敗的閘道會將非空的 critical_skipped 視為未知而非乾淨,且可能將 rule_results 中任何 budgetExceeded 的跳過視為相同。

對於 CI 閘道:若你省略 eval_type,所有套件都會執行——完整性、相關性、安全性、成本和任何自訂規則——且回應會以 note 說明 eval_type: "all" 已執行預設,並附上每個套件的 categories 對應。沒有可評判內容的套件(無 cost_usd 的成本、無 input 的相關性)會在該處回報 passed: null——未評估、未失敗——且永遠不計入裁決。回應永遠會回應已執行的 eval_type,因此你的閘道可以驗證覆蓋範圍;以 passed 作為裁決的關鍵,且僅在想要較窄的執行時指定套件。

編寫自訂規則

新增規則有兩種方式。內聯規則隨單次 evaluate_output 呼叫(custom_rules,每次呼叫最多 10 個)一起執行;它們與你選擇的任何 eval_type 套件一起觸發,或單獨使用 eval_type: "custom"。已部署規則透過 deploy_rule 註冊一次,在 custom-rules.json 中你的 Iris 主目錄下持久化,並在未來每次其 evalType 的 evaluate_output 時觸發。定義無論哪種方式都是相同形狀:

欄位必填說明
name是1–80 個字元;在結果中顯示為 ruleName
type是下列之一:regex_match · regex_no_match · min_length · max_length · contains_keywords · excludes_keywords · json_schema · cost_threshold
config是該類型的金鑰:pattern(+ 選用 flags)用於兩種正則表達式類型 · min_length / max_length(字元數)· keywords(+ 選用 threshold,0–1,預設 1 = 全部必須出現)用於兩種關鍵字類型 · {} 用於 json_schema · max_cost(美元)用於 cost_threshold
weight否分數中的權重;預設 1

deploy_rule 以 name、選用的 description、evalType(completeness · relevance · safety · cost · custom)和 severity 包裝定義。嚴重性說明失敗的意義:low/medium 僅降低分數;high/critical 硬性失敗評估——passed: false,在 critical_failures 中點名的規則——無論加權分數為何。跳過的規則(沒有 cost_usd 的 cost_threshold 規則,或在 100 毫秒沙箱預算中被終止的正則表達式)尚未評判輸出,並改列在 critical_skipped 中。部署一個禁止代理程式說出任何內部主機名稱的關鍵規則:

{
  "name": "no_internal_hostnames",
  "description": "Output must not mention internal hostnames.",
  "evalType": "safety",
  "severity": "critical",
  "definition": {
    "name": "no_internal_hostnames",
    "type": "regex_no_match",
    "config": { "pattern": "\\b[a-z0-9-]+\\.internal\\.example\\b", "flags": "i" }
  }
}

回應是已持久化的規則——保留 id 以供 delete_rule 使用:

{ "rule": { "id": "rule-588823d0", "name": "no_internal_hostnames", "evalType": "safety", "severity": "critical", "enabled": true, "version": 1, "definition": { "…": "…" } } }

從下一次帶有 eval_type: "safety" 的 evaluate_output 開始,提及 db-primary.internal.example 的輸出會以 passed: false 回傳,附上 critical_failures: ["no_internal_hostnames"]——即使所有五個內建安全規則都通過且加權分數為 0.895。正則表達式模式必須在部署時通過 ReDoS 檢查,且總是在沙箱工作者中於 100 毫秒的硬性期限內執行。list_rules 顯示已部署的內容;儀表板的規則組合器會從你點擊的失敗中建立相同形狀。完整參考、每種類型的評分方式,以及實際範例:docs/custom-rules.md。

完整的工具結構和設定:iris-eval.com

託管功能

Iris 目前完全在你的機器上執行,它所做的一切都是免費且 MIT 授權,沒有限制也不需要帳號。 託管儲存、共享團隊歷史紀錄與警示功能正在評估中,尚未開始建置。目前沒有定價,也沒有任何需要購買的項目。如果共享歷史紀錄對您有幫助,等候名單是我們了解這是否值得開發的方式——加入名單不需承擔任何義務。

無論如何,我們有兩項承諾不變:今日免費的功能絕不會移到付費牆之後,且在取得合規認證之前,絕不會宣稱擁有該認證。

範例

社群

設定與安全性

CLI 參數

旗標預設值說明
--transportstdio傳輸類型:stdio 或 http
--port3000HTTP 傳輸連接埠
--db-path~/.iris/iris.dbSQLite 資料庫路徑
--config~/.iris/config.json設定檔路徑
--api-key—用於 HTTP 驗證的 API 金鑰(傳輸與儀表板,包括 POST /api/v1/traces)
--dashboardfalse啟用網頁儀表板。這也是 POST /api/v1/traces 接收端點啟動的唯一方式——它絕不會隨 --transport http 隱式啟動
--dashboard-port6920儀表板連接埠
--dashboard-host127.0.0.1儀表板綁定位址。預設為迴路(loopback)——儀表板在未設定 --api-key 時不具驗證,因此綁定至迴路之外會暴露您的完整追蹤歷史紀錄
--demofalse植入示範資料庫(與您的真實追蹤分開)並針對其提供儀表板服務
--demo-clearfalse刪除示範資料庫並結束
--self-testfalse在隔離的暫存主目錄中執行離線安裝診斷,然後結束(0 = 正常,1 = 有檢查失敗)。它也會以唯讀方式讀取設定的資料庫,若此版本或固定的 MCP 用戶端無法開啟,則失敗
--purgefalse從設定的資料庫中刪除所有儲存的追蹤、跨度與評估,壓縮檔案並截斷寫入前日誌,使已刪除的文字不會殘留在磁碟上,然後結束。已部署的規則、稽核日誌與偏好設定會保留。此操作不可逆。請先停止任何執行中的 Iris 伺服器——檔案會就地壓縮。拒絕與 --demo、--demo-clear 或 --self-test 合併使用
--version—將純版本號(例如 1.2.3)輸出至 stdout 並以 0 結束。不會讀取您 Iris 主目錄下的任何內容

三個命令會接受各自的參數並結束:iris-eval ingest 從檔案或 stdin 載入追蹤(無需伺服器的 CI 閘道),iris-eval export traces|evaluations --format csv|jsonl 將儲存的內容(如同儀表板清單般篩選)寫入 stdout 或 --out(docs/api-reference.md),而 iris-eval install <client> 將 Iris 寫入 MCP 用戶端的設定——--uninstall 將其移除,--list 顯示此機器上找到的用戶端及各自執行的 Iris,--upgrade 將所有執行 Iris 的用戶端移至此版本(連接您自己的代理、更新)。以上皆不會啟動伺服器。

config.json 在 Iris 啟動時會進行驗證。 一個 Iris 不讀取的金鑰——例如 eval.critcalRules 的拼寫錯誤、來自其他工具的金鑰——或錯誤類型的值,會以一句話拒絕啟動,並指出完整的金鑰名稱、最可能意指的金鑰,或所需的類型。檔案中沒有任何內容會被靜默忽略。

環境變數

每個變數皆由 --help 記錄。當兩者同時設定時,CLI 旗標優先於環境變數。

變數說明
IRIS_TRANSPORT傳輸類型(stdio 或 http)
IRIS_HOSTHTTP 傳輸綁定位址(預設 127.0.0.1)
IRIS_PORTHTTP 傳輸連接埠(1-65535,預設 3000)
IRIS_HOME所有使用者檔案的目錄:config.json、iris.db、custom-rules.json、audit.log、preferences.json(預設 ~/.iris)
IRIS_DB_PATHSQLite 資料庫路徑(僅對資料庫覆寫 IRIS_HOME)
IRIS_SQLITE_DRIVER持有資料庫的 SQLite 驅動程式:native(better-sqlite3,預設)或 node(Node 內建的 node:sqlite,Node 22.13+)。未設定:使用原生模組,當原生模組無法載入(或為會在此 Node 上中止的建置)時,Iris 會警告一次並回退至內建模組
IRIS_SEARCH_BUDGET_MS單次追蹤搜尋(q)在回覆目前已找到的相符項目及 search.complete: false 之前可讀取的時間,以毫秒為單位(50 至 60000,預設 1000)。搜尋在讀取期間會暫停其他請求,因此這也是其他請求最長的等待時間。亦為 storage.searchBudgetMs 於 config.json 中
IRIS_SEARCH_INDEXon(預設)或 off。off 不保留追蹤的全文索引:寫入僅儲存追蹤本身,追蹤搜尋(q)會在 IRIS_SEARCH_BUDGET_MS 內讀取追蹤本身,最新的優先,因此在大型儲存體上可能僅回覆部分相符項目(search.complete: false)。關閉會清除資料庫保留的索引;重新開啟會在背景建立新索引。亦為 storage.searchIndex 於 config.json 中
IRIS_LOG_LEVEL日誌等級:debug、info、warn、error
IRIS_DASHBOARDtrue/1/yes/on 啟用網頁儀表板;false/0/no/off 停用(亦覆寫 dashboard.enabled 於 config.json 中)
IRIS_DASHBOARD_PORT儀表板連接埠(1-65535,預設 6920)
IRIS_WEBHOOK_URL在特定時刻觸發的 webhook 接收者——合併至 notify.webhook 於 config.json 中(docs/webhooks.md)
IRIS_WEBHOOK_SECRETwebhook 的簽章金鑰(任何字串,或 whsec_ + base64);iris 格式在沒有金鑰時拒絕執行
IRIS_DASHBOARD_HOST儀表板綁定位址(預設 127.0.0.1)
IRIS_API_KEY用於 HTTP 驗證的 API 金鑰。綁定 HTTP 傳輸或儀表板至迴路之外(0.0.0.0、LAN 位址、容器)時為必填:沒有金鑰則伺服器拒絕啟動
IRIS_API_KEY_FILE檔案路徑,其修剪後的內容即為 API 金鑰——Docker 與 Kubernetes 掛載的密鑰檔案模式,使金鑰絕不置於環境區塊中。設定此項或 IRIS_API_KEY,不可同時設定
IRIS_ALLOW_UNAUTHENTICATED設為 1 以刻意在無金鑰的情況下執行非迴路綁定(解除拒絕;網路即為您的邊界)
IRIS_ALLOWED_ORIGINS以逗號分隔的來源允許清單。儀表板:CORS 標頭(支援萬用字元,例如 http://localhost:*)。HTTP 傳輸:用於 DNS 重新綁定保護的完全比對 Origin 允許清單(忽略萬用字元;伺服器自身的迴路來源永遠允許)
IRIS_NO_AUTO_LAUNCH設為 1 以停用首次執行的儀表板自動啟動
IRIS_ANTHROPIC_API_KEY由 evaluate_with_llm_judge + verify_citations 搭配 provider=anthropic 時必填
IRIS_OPENAI_API_KEY由 evaluate_with_llm_judge + verify_citations 搭配 provider=openai 時必填
IRIS_LLM_JUDGE_MAX_COST_USD_PER_EVAL每次 LLM 評審呼叫的硬性成本上限(預設 0.25)
IRIS_RELEVANCE_JUDGE_MODEL有定價的評審模型 ID(例如 claude-haiku-4-5)。設定後,搭配該提供者的金鑰,answers_the_ask 會在每次帶有輸入的評估中詢問此 LLM 評審,並根據其相關性判定進行門控——每次評估一次評審呼叫,受上述成本上限及以下兩個限制約束。此類評估的輸入與輸出會以您的金鑰傳送至該模型的提供者(Anthropic 或 OpenAI),其中 no_pii 標記的個人資料與憑證會先被替換。未設定(預設)時,answers_the_ask 以詞彙方式讀取請求並提供建議,不會傳送任何內容(docs/llm-as-judge.md)
IRIS_RELEVANCE_JUDGE_DAILY_BUDGET_USD相關性評審每個 UTC 日、每個租戶可花費的上限(預設 1)。儲存於資料庫中,因此重新啟動不會重設。僅在最壞情況符合剩餘額度時才會進行呼叫;超過後,answers_the_ask 以詞彙方式讀取請求,且 judge.withheld 為 daily_budget。0 停止所有呼叫
IRIS_RELEVANCE_JUDGE_MAX_CALLS_PER_REQUEST單一請求可進行的相關性評審呼叫次數(預設 20):OTLP 批次或 evaluate_runs 重新評分會評審其前 20 個追蹤,其餘以詞彙方式讀取,搭配 judge.withheld: "request_cap"
IRIS_RELEVANCE_JUDGE_REDACTon(預設):no_pii 在輸入與輸出中標記的每個跨度(個人資料與憑證)在傳送至相關性評審前,會以 [REDACTED:<kind>#<n>] 標記替換。off 則原樣傳送
IRIS_CITATION_ALLOW_FETCH設為 1 以允許 verify_citations 中的對外 HTTP(預設關閉)
IRIS_CITATION_DOMAINS以逗號分隔的 verify_citations 主機名稱允許清單(後綴比對)
IRIS_OTEL_ENDPOINT啟用盡力而為的 OTLP/HTTP JSON 追蹤匯出至此收集器 URL
IRIS_OTEL_SERVICE_NAME用於 OTel 匯出的 service.name 資源屬性(預設 iris-eval)
IRIS_OTEL_HEADERS以逗號分隔的 OTel 匯出 k=v 標頭(例如 authorization=Bearer abc)
IRIS_OTEL_TIMEOUT_MS每次匯出的逾時時間(預設 15000)
RATE_LIMIT_SALT僅限網站等候名單 API——在 iris-eval.com 網站部署時必填;伺服器絕不會讀取它

安全性

使用 HTTP 傳輸時,Iris 包含:

  • 具時間安全比較的 API 金鑰驗證(API 用戶端使用 Bearer;透過 ?key= 進行儀表板瀏覽器登入)
  • CORS 預設限制為 localhost
  • 每個用戶端位址與分鐘的速率限制:儀表板 API 600 個請求(security.rateLimit.api)與 MCP 端點 20 個請求(security.rateLimit.mcp),兩者皆於 config.json 中設定;超過限制的 MCP 請求會收到指名金鑰的 JSON-RPC 錯誤
  • Helmet 安全性標頭
  • 所有路由上的 Zod 輸入驗證
  • 自訂評估規則的 ReDoS 安全正規表達式
  • 每個傳輸的單一 1MB 請求大小限制(security.requestSizeLimit):HTTP 回覆 413,stdio 回覆 JSON-RPC 錯誤並保持工作階段開啟
# Production deployment
iris-eval --transport http --port 3000 --api-key "$(openssl rand -hex 32)" --dashboard

設定金鑰後,API 用戶端(MCP 用戶端、擷取 SDK、POST /api/v1/traces)會傳送 Authorization: Bearer <key>。若要在瀏覽器中開啟儀表板,請將金鑰附加到任何儀表板 URL 一次,http://localhost:6920/?key=<api key>:Iris 會將其換成 HttpOnly、SameSite=Lax 的工作階段 Cookie,並重新導向至相同頁面,同時從網址列移除金鑰。在沒有工作階段的情況下開啟的頁面會顯示登入表單,執行相同的交換。金鑰永遠不會儲存在瀏覽器中,且工作階段只存在於伺服器程序中(同時最多 256 個;若登入時發現全部都在使用中,則會拒絕而非逐出其中一個)。

正式環境

多把金鑰,且輪替時無空窗期。 security.apiKeys 中的 config.json 可容納任意數量的其他金鑰,每把金鑰都有 id,且恰好是 keyFile(一個檔案,其去除空白後的內容即為金鑰)或 keyHash(金鑰的 sha256 十六進位,因此設定檔不包含機密——printf %s "$KEY" | openssl dgst -sha256)其中之一,以及一個選用的 expiresAt(ISO 8601),之後該金鑰會在那個時刻立即停止比對。輪替方式:新增新金鑰、移動您的用戶端、移除舊金鑰。config.json 和金鑰檔案中的金鑰無需重新啟動即可生效(0.20.0):在每個請求上,伺服器會檢查 config.json 或其指定的金鑰檔案是否已變更,若是,則在回應前重新讀取金鑰。從 security.apiKeys 移除金鑰,或刪除其金鑰檔案,會在下次請求時撤銷它:該請求會被拒絕,且所有用它開啟的瀏覽器工作階段都會登出。無法讀取的 config.json(例如,寫入一半)會以失敗關閉,且在修復之前,只接受來自 IRIS_API_KEY 或 --api-key 的金鑰。IRIS_API_KEY 或 --api-key 本身的金鑰,以及驗證是否開啟,仍然只在重新啟動時變更。每把金鑰在移除或到期前都會持續驗證,無論是在 Bearer 路徑或瀏覽器登入上皆然;啟動日誌會列出 ID。security.rateLimit.mcpKeyBy: "apiKey" 會依金鑰而非用戶端位址來計算 MCP 端點的每分鐘預算,因此同一位址後的多個代理程式各自擁有自己的分鐘數。

Iris 在 HTTP 傳輸或儀表板繫結到迴路之外(0.0.0.0、LAN 位址、容器)且沒有 API 金鑰時,拒絕啟動,並用一句話說明,指出 IRIS_API_KEY。這包括映像的裸 docker run,它會繫結容器內的 0.0.0.0,因為透過已發佈的連接埠無法到達迴路。沒有金鑰的迴路仍可運作(HTTP 傳輸上會有警告):機器邊界是那裡的暴露控制。

# The image: pass a key
docker run -p 3000:3000 -p 6920:6920 -v iris-data:/data \
  -e IRIS_API_KEY="$(openssl rand -hex 32)" ghcr.io/iris-eval/mcp-server

# Compose: the file requires the variable and refuses before the container starts
IRIS_API_KEY="$(openssl rand -hex 32)" docker compose up

# A network you have already fenced some other way: run open, on purpose
IRIS_ALLOW_UNAUTHENTICATED=1 iris-eval --transport http --dashboard

在有金鑰的伺服器上,依設計開放:傳輸上的 GET /health 和儀表板上的 GET /api/v1/health 在沒有金鑰且不受任何速率限制的情況下回應,形式統一:狀態、版本、運作時間、SQLite 驅動程式、用於儲存的 checks、已部署規則檔案和遷移(套用於已知項目)、搜尋索引的狀態(search:就緒,或建置在追蹤中所達到的比例),以及是否有評判金鑰——絕不含金鑰、追蹤或其計數。status 只有在所有檢查都通過時才是 ok;否則為 HTTP 503 的 degraded,Docker 映像自己的 HEALTHCHECK 會讀取它。其他一切都需要 Authorization: Bearer <key> 或瀏覽器工作階段。保留會在每台伺服器上執行:比 retention.days(預設 30)更舊的追蹤和評估會在啟動時、伺服器開始回應後,以及每 retention.sweepIntervalHours 刪除一次,以簡短步驟進行,絕不會讓請求等待太久;--self-test 會列印此安裝的原則,而 iris://capabilities / GET /api/v1/capabilities 會以 retention 攜帶它。

Webhook 會在特定時刻觸發(0.16.0):config.json 中的 notify.webhook(或 IRIS_WEBHOOK_URL 和 IRIS_WEBHOOK_SECRET)指定接收者,當裁決失敗、重大偵測否決、成本為離群值、規則失敗率轉變,或案例首次以兩種方式回答時,Iris 會發布一則簽署訊息——ID、裁決、規則和數字,絕不含代理程式的文字。同時以 Standard Webhooks 和 GitHub 方式簽署,以退避方式重試,依代理程式和規則冷卻,絕不阻礙評估;內建 Slack 和 Discord 訊息內文。docs/webhooks.md。

您磁碟上的資料

Iris 儲存的所有內容都位於您的 Iris 主目錄下(~/.iris 或 IRIS_HOME)。iris.db 會逐字保留每個追蹤的 input 和 output——包括 no_pii 之後可能標記的任何文字;偵測不會編輯,除非您要求:config.json 中的 storage.redact: "critical_spans" 會儲存每個評估的輸出,並將重大偵測器標記的跨度替換為 [REDACTED:<pattern>](預設關閉;證據偏移仍會索引呼叫者看到的文字)。storage.synchronous 設定寫入何時到達磁碟:normal(預設)在每個檢查點同步預寫日誌,因此 Iris 當機不會遺失任何內容,且檔案不會損毀,但停電或作業系統當機可能會復原自上次同步以來的寫入;full 會同步每個提交並在兩者之間保留,每次寫入約多 1.5 毫秒。在啟動時,以及之後每 retention.sweepIntervalHours(預設 24,0 停用計時器),比 retention.days(預設 30,0 停用,在 config.json 中設定)更舊的追蹤和評估會被刪除,並檢查點預寫日誌。刪除追蹤——透過 delete_trace 或清除——會抹除與其連結的每個評估的文字(輸出、預期文字和規則訊息),並蓋上 erased_at 戳記;裁決、分數和證據偏移會保留。每次刪除在返回前都會檢查點預寫日誌,因此已刪除的文字不會留在 iris.db 或 iris.db-wal 中可讀(如果搜尋在該時刻正在讀取檔案,或另一個程序正在讀取或寫入它,刪除會在不等待的情況下返回,文字會在完成後立即離開檔案)。若要立即移除所有內容,請停止伺服器並執行 --purge:它會刪除每個儲存的追蹤、跨度和評估,壓縮資料庫並截斷預寫日誌,使文字從磁碟上消失,並保留您已部署的規則、稽核日誌和偏好設定。在版本將遷移套用至現有 iris.db 之前,它會將檔案複製到其旁邊(iris.db.<from>-to-<to>.<time>.bak,僅擁有者,保留最新的三個;降級):複本會保留追蹤原樣,因此保留清除會刪除比 retention.days 更舊的追蹤,而 --purge 會刪除全部。伺服器在回應其用戶端後,在自己的執行緒上執行複製和遷移:同時到達的工具呼叫、資源讀取和 HTTP 請求會等待它們,每個最多 30 秒,然後以一句話說明伺服器在做什麼(IRIS_STORAGE_ERROR,可重試;HTTP 503 帶 Retry-After)來拒絕。健康檢查在整個過程中回應,並說明升級在做什麼。從 0.19.0 開始,在 100,000 個追蹤(每個都是代理程式迴圈)下,複製和遷移花了約 6 秒。iris-eval ingest、--purge 和 --self-test 仍會在做任何其他事情之前升級。

Iris 不會加密其靜態資料。iris.db 及其預寫日誌檔案以僅擁有者(模式 600)建立,Iris 主目錄以模式 700 建立(在 Windows 上,由檔案 ACL 管理)。資料庫不儲存 LLM 提供者金鑰:IRIS_ANTHROPIC_API_KEY 和 IRIS_OPENAI_API_KEY 從環境讀取,絕不寫入磁碟。它確實逐字儲存追蹤輸入和輸出,因此請將 Iris 主目錄放在加密磁碟或磁碟區上(FileVault、BitLocker、LUKS,或用於 Docker 映像 /data 掛載的加密雲端磁碟區)。

匯出——儀表板「追蹤」和「評估」頁面上的匯出按鈕、GET /api/v1/traces/export 和 /api/v1/evaluations/export,或 iris-eval export——會按原樣攜帶此儲存文字,與儀表板顯示的相同:追蹤輸入和輸出逐字、評估輸出套用 storage.redact。請像對待其來源資料庫一樣對待匯出的檔案。

疑難排解

第一步:執行自我測試

npx @iris-eval/mcp-server --self-test

它會在隔離的暫存主目錄中檢查儲存、確定性評估和儀表板,並列印逐步裁決——失敗輸出會指出失敗的步驟。結束代碼 0 表示安裝健康。

Iris 無法啟動 / ERR_MODULE_NOT_FOUND

您可能快取了較舊版本。清除 npx 快取並重試:

npx --yes @iris-eval/mcp-server@latest

或全域安裝以完全避免快取問題:

npm install -g @iris-eval/mcp-server@latest

npm install --ignore-scripts 破壞了 SQLite 繫結

Iris 使用 better-sqlite3 儲存追蹤,這是一個原生模組,會在安裝指令碼中擷取或編譯其繫結。如果該指令碼被跳過——命令列上的 --ignore-scripts、.npmrc 中的 ignore-scripts=true(在企業機器上很常見),或剝離 postinstall 的 registry 鏡像——啟動會失敗,並出現一長串「Could not locate the bindings file」傾印,列出它嘗試過的十幾個路徑。重建該單一模組:

npm rebuild better-sqlite3
# for a global install:
npm rebuild -g better-sqlite3

工具未顯示在 Claude Code 中

MCP 工具只會在會話開始時載入。新增 iris-eval 後,使用 /clear 重新啟動會話,或重新啟動終端機。

版本檢查

npx @iris-eval/mcp-server --version

第一行啟動日誌也會攜帶它(Starting Iris MCP server vX.Y.Z),而 --self-test 會在其摘要中列印它。對於全域安裝,npm ls -g @iris-eval/mcp-server 會顯示已安裝的版本。

更新

機器上的每個 MCP 用戶端共用一個資料庫、~/.iris/iris.db,而 install 會將每個用戶端釘選到寫入其設定的版本。當版本變更資料庫的結構時,該版本的第一個開啟檔案的程序會升級它,之後釘選到較舊版本的用戶端會拒絕啟動。因此,請在升級之前或之後立即一次移動所有用戶端:

npx -y @iris-eval/mcp-server@latest install --upgrade

它會找到此機器上執行 Iris 的每個用戶端設定,將每個釘選移到該版本(保留您新增到項目的任何內容,例如 --dashboard 或 env 區塊),不觸碰釘選到較新版本的釘選,以及執行非 npm 套件的項目,並列出它做了什麼。重新啟動它指名的用戶端。install --list 會顯示每個用戶端執行哪個 Iris。

兩個安裝位於這些檔案之外:Claude Desktop 擴充功能(iris-eval.mcpb)會在您開啟較新的套件時移動,而 Claude Code 外掛程式則使用 claude plugin marketplace update iris-eval 然後 claude plugin update iris-eval@iris-eval(以及用於擷取外掛程式的 claude plugin update iris-eval-capture@iris-eval)。

從 0.19.x 升級到 0.20.0。 0.20.0 新增了搜尋索引和資料庫的其他新增項目(遷移 015 及之後)。一旦任何 0.20.0 程序開啟了 ~/.iris/iris.db(Claude Desktop 擴充功能、npx iris-eval 或無版本的 npx @iris-eval/mcp-server),釘選到 0.19.x 的用戶端會以 This database was migrated by a newer Iris (…) — migration(s) 015-trace-search, … are unknown to v0.19.0. Upgrade Iris, … 停止。該訊息來自 0.19.x,無法變更;修復方法是上面的命令。升級前,0.20.0 會將檔案複製到其旁邊,因此也可以返回(如下)。

啟動時升級資料庫會在 stderr 上列印它做了什麼:它進行的複製、哪些較舊版本無法再開啟檔案,以及此機器上釘選到其中之一的任何用戶端,並附上命令。--self-test 會在不變更的情況下讀取資料庫,並在您啟動任何東西之前說同樣的話。

對於全域安裝,npm update -g @iris-eval/mcp-server,然後 iris-eval install --upgrade。

降級

一個升級版本的發行會先複製資料庫,並放在其旁邊:iris.db.<from>-to-<to>.<time>.bak 位於您的 Iris 主目錄中(<from> 是上次變更檔案結構描述的版本,<to> 是執行升級的版本;啟動時輸出的那一行會印出確切路徑)。若要還原:

  1. 停止所有 MCP 用戶端,以及任何其他使用該資料庫的 Iris 程序。
  2. 保留升級後的檔案,以防您之後想回來:將 iris.db 重新命名為 iris.db.upgraded,並刪除 iris.db-wal 和 iris.db-shm(如果它們存在的話)。
  3. 將備份複製到 iris.db:cp ~/.iris/iris.db.0.19.0-to-0.20.0.<time>.bak ~/.iris/iris.db。
  4. 將每個用戶端釘回較舊的版本:對每個用戶端執行 npx -y @iris-eval/mcp-server@0.19.0 install <client>(install --upgrade 永遠不會將用戶端移回舊版)。

升級後儲存的追蹤記錄位於 iris.db.upgraded,而非備份中。如果沒有進行複製(啟動行會說明原因,例如磁碟已滿),較舊的版本將無法開啟升級後的檔案,而前進的方向是 install --upgrade。

儲存驅動程式

在沒有預先建置的 better-sqlite3 的平台上,安裝仍然會成功。 better-sqlite3 是選用相依項目:當 npm 既無法為您的 Node 和平台下載預先建置的二進位檔,也無法編譯一個(編譯需要 Python 和 C++ 工具鏈——在 Windows 上是 Visual Studio 的 C++ 建置工具)時,npm 會印出建置錯誤、跳過該模組,並完成安裝。Iris 接著會執行於 Node 內建的 SQLite,並會如此說明:啟動時會在 stderr 印出一行說明原因,而 --self-test 會顯示 driver node: better-sqlite3 is not installed …。若要取回原生驅動程式,請在存在預先建置或工具鏈的地方安裝它(在專案中為 npm install better-sqlite3;若是全域安裝,一旦工具鏈可用,請使用 npm install -g @iris-eval/mcp-server 再次安裝 Iris)。CI 會安裝打包好的伺服器,並在每次變更時強制原生建置失敗,且要求安裝完成,以及自我測試能在內建驅動程式上儲存和讀取一筆追蹤記錄。

Iris 將所有內容保存在單一 SQLite 檔案中,由 better-sqlite3 開啟——這是一個為您的 Node 和平台下載或編譯的原生附加元件。當該模組無法載入時,Iris 會回退到 Node 內建的 SQLite(node:sqlite,Node 22.13 或更新版本),並在 stderr 上發出一個警告,因此缺少預先建置只會導致啟動較慢,而非無法啟動。在載入之前,它也會對在您的機器上針對 Node 24.19 或更新版本標頭編譯的 better-sqlite3 執行相同操作:到目前為止,在每個 24.x 版本中,這樣的二進位檔在首次釋放語句時都會中止整個程序(Assertion failed: (env) != nullptr,nodejs/node#65446),而 npm rebuild better-sqlite3 會以安全的預先建置二進位檔取代它。IRIS_SQLITE_DRIVER=node 會刻意選擇內建驅動程式,native 則禁止回退。內建驅動程式在載入時會關閉擴充功能載入和 trusted_schema;Node 在載入時會自行在 stderr 印出 ExperimentalWarning: SQLite is an experimental feature 行,而 Iris 不會將其靜音。--self-test 和 GET /health 會指出目前使用的驅動程式;證明頁面上的每個數字都是在原生驅動程式上測量的,而測試套件在 CI 中會同時在兩者上執行。

Node.js 版本

Iris 需要 Node.js 22.13 或更新版本。Node 20 已於 2026-04-30 達到生命週期結束,且不受支援;Node 18 則於 2025 年 4 月結束。

底線是 22.13 而非 22.0,因為 22.13.0 是第一個搭載 node:sqlite 的版本。這使其成為第一個讓所有受支援的 Iris 安裝都具有第二個儲存驅動程式的版本:當原生 better-sqlite3 附加元件無法載入時,Iris 會回退到 Node 內建的 SQLite,而不是無法啟動。在 22.13 以下——以及 Node 20 的整個生命週期——永遠只有一個驅動程式,而缺少預先建置就等於無法啟動。

node --version  # Must be v22.13.0 or newer

Windows:不需要 cmd /c

Claude Code 的 /doctor 可能會建議使用 cmd /c 包裝 npx。這並非必要,且會導致路徑解析問題。請直接使用 npx:

# Correct
claude mcp add --transport stdio iris-eval -- npx -y @iris-eval/mcp-server

# Wrong (causes /c to be parsed as a path)
claude mcp add --transport stdio iris-eval -- cmd /c "npx -y @iris-eval/mcp-server"

如果 Iris 對您有用,請考慮為儲存庫加星——這有助於其他人找到它。

Star on GitHub

MIT 授權。