adrkit decision memory

dev.adrkit由 adrkit.dev 發布v0.20.0更新於 Oct 24, 2026

Deterministic, offline, read-only ADR decision memory for coding agents. No model or network calls.

發布方自己的服務:Memory.fit

已驗證STDIO僅桌面知識與記憶開發者工具

概覽

AI 產生的概覽

一個本機唯讀 MCP 伺服器,讓編碼助理查詢以 Git 為基礎的 ADR 決策庫:已決定什麼、哪些檔案受哪些決策約束、哪些決策已被取代或否決。

可以做什麼
依 id、標題、標籤與內文做字面搜尋,可依狀態、標籤與範圍篩選,預設包含已取代與被否決的紀錄。依本機 id 取得單一決策的完整型別化 frontmatter 與內文。依各紀錄自身的 affects 比對規則,為相對於儲存庫的檔案路徑找出約束性、進行中提案與歷史決策。列出所有已取代紀錄及其直接替代狀態,包括懸空、歧義或聯邦目標。每次回應都附帶語料健康資訊與解析/驗證發現,並支援游標分頁。
適用情境
適用於在保存架構決策紀錄(ADR)的儲存庫中工作的助理,在提出變更前先核對既有決策,或避免重複提出團隊已否決的方案。最適合在 Git 中以 docs/adr 風格維護 Markdown 語料的團隊。
執行需求
透過 npx 以 stdio 在本機執行,需要 Node.js 22 或更新版本;無需驗證。需要一個包含可讀 .git 項目的儲存庫根目錄,由 ADRKIT_MCP_CWD 或 --cwd 指定(預設為行程工作目錄),以及由 ADRKIT_MCP_DIR 或 --dir 指定的 ADR 目錄(預設為 docs/adr),且必須位於根目錄內。僅限桌面用戶端,不支援網頁執行。
安裝前請注意
設計上唯讀:不寫入、不呼叫模型或網路、無驗證。它會讀取所設定儲存庫目錄中的 Markdown 檔案並回傳其內容,因此只應指向你願意讓助理看到的儲存庫。聯邦 log:id 參照會被辨識但從不解析。軟體仍處於 1.0 之前,建議固定明確的套件版本而非使用 latest。

安裝

在 SourceWeft 中

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

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

其他 MCP 客戶端

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

README

@adrkit/mcp

Deterministic, offline, read-only decision memory for coding agents — including the decisions you already rejected.

A local Model Context Protocol server that lets an agent harness query one Git-backed ADR (Architecture Decision Record) corpus over stdio: "has this been decided?", "what governs these files?", and "what replaced this?" It surfaces superseded and rejected decisions specifically so agents stop re-proposing paths the team already ruled out.

No model calls. No network calls. No writes. The server reads Markdown files from your repo and returns structured JSON. It never calls an LLM, never opens a socket, and never mutates your corpus. Every tool is annotated readOnlyHint: true, openWorldHint: false.

Part of adrkit. The corpus lives in git as one Markdown file per decision with typed YAML frontmatter (@adrkit/core); this server only reads it. Listed in the official MCP registry as dev.adrkit/mcp (this is the Node/npm @adrkit/mcp package — unrelated to the adr-kit Python package on PyPI).

Status

Published on npm for Node 22+ with a deliberately small, read-only stdio surface: four tools and no write path.

adrkit is still pre-1.0. If you need repeatable client installs, pin an explicit @adrkit/mcp version in your MCP config instead of floating latest.

Quick start

The published binary is adrkit-mcp. Run it with npx (no install):

sh
npx -y @adrkit/mcp --cwd /path/to/your/repo --dir docs/adr

It speaks JSON-RPC over stdio, so you normally point an MCP client at it rather than running it by hand. Copy-pasteable client configs follow.

Claude Desktop

Edit claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/claude_desktop_config.json). Claude launches servers from an arbitrary working directory, so set ADRKIT_MCP_CWD to your repo's absolute path:

json
{  "mcpServers": {    "adrkit": {      "command": "npx",      "args": ["-y", "@adrkit/mcp"],      "env": {        "ADRKIT_MCP_CWD": "/absolute/path/to/your/repo",        "ADRKIT_MCP_DIR": "docs/adr"      }    }  }}

VS Code

Create .vscode/mcp.json in your workspace (VS Code uses the servers key and substitutes ${workspaceFolder}):

json
{  "servers": {    "adrkit": {      "type": "stdio",      "command": "npx",      "args": ["-y", "@adrkit/mcp", "--cwd", "${workspaceFolder}", "--dir", "docs/adr"]    }  }}

Cursor

Create .cursor/mcp.json (project) or ~/.cursor/mcp.json (global):

json
{  "mcpServers": {    "adrkit": {      "command": "npx",      "args": ["-y", "@adrkit/mcp"],      "env": {        "ADRKIT_MCP_CWD": "/absolute/path/to/your/repo",        "ADRKIT_MCP_DIR": "docs/adr"      }    }  }}

GitHub Copilot CLI

Add to ~/.copilot/mcp-config.json (user-level) or ./.copilot/mcp-config.json (per-repo). Copilot CLI runs servers from the trusted repo directory, so the default cwd usually resolves correctly:

json
{  "mcpServers": {    "adrkit": {      "type": "local",      "command": "npx",      "args": ["-y", "@adrkit/mcp", "--dir", "docs/adr"],      "tools": ["*"]    }  }}

You can also add it interactively with /mcp add inside a copilot session.

Configuration reference

OptionEnvDefaultMeaning
--cwd <path>ADRKIT_MCP_CWDprocess.cwd()Repository root; must canonicalize to a directory containing a readable .git entry (a normal clone or a linked-worktree .git file).
--dir <path>ADRKIT_MCP_DIRdocs/adrADR directory, resolved against --cwd and required to stay contained within it (realpath-checked, so a symlink escape is rejected).

Flags win over environment variables, which win over the defaults. An unusable configuration exits non-zero with a diagnostic on stderr (2 for an unparseable flag, 1 for an invalid root/directory) and never starts a transport. stdout is reserved for JSON-RPC protocol frames only.

Protocol revisions

The server speaks both MCP protocol eras on the same stdio connection, and the client picks. The opening exchange selects the era and pins it for the connection's lifetime:

Client opens withServer serves
server/discover, or any request carrying a 2026 _meta envelope2026-07-28 — stateless, no handshake
initialize / notifications/initializedthe 2025-era revision it negotiates

On 2026-07-28 there is no initialize handshake and no session id: every request carries its own protocol version and client capabilities in _meta, and every result is self-describing (resultType, plus server identity in _meta). tools/list and server/discover are cacheable (SEP-2549) and are served with ttlMs: 300000, cacheScope: "public" because the 4-tool surface is fixed for the life of the process and carries no corpus content. Corpus reads are never cacheable: every tools/call loads a fresh projection.

Nothing else about the tools changes between eras — same names, same schemas, same annotations, same structured results. The server uses none of the features the 2026-07-28 revision deprecated (roots, sampling, logging) or removed (sessions, ping, resources/subscribe).

The four tools

Exactly four tools, all read-only. Each shares fixed annotations (readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false), returns a deterministic human-readable summary line in content[0].text, and carries a findings page with the corpus's own parse/validation findings. Every substantive response also includes a corpusHealth sibling: { fingerprint, recordCount, excludedCount }.

Shapes below are the real input/output contracts (see packages/mcp/src/tools). Each tool's structured output is { corpusHealth?, result }; the objects shown under "output" are the members of that discriminated result union (keyed on outcome). findings and every growing array are cursor-paginated (see Pagination); findings and repeated pagination fields are elided here for brevity.

search_decisions

Normalized literal substring search over id, title, tags, and body (the graveyard of superseded/rejected records is included by default). Filters are ANDed: status/scope match any-of; tags matches all-of.

jsonc
// input{  "query": "postgres",          // required, 1–256 code units, non-empty after trim  "status": ["accepted"],        // optional, ≤6, any-of  "tags": ["database"],          // optional, ≤32 tags × ≤64 chars, all-of  "scope": ["backend"]           // optional, ≤3, any-of}// output → single "results" branch (empty results use the same branch){  "outcome": "results",  "items": [    {      "id": "0007",      "title": "Adopt Postgres",      "status": "accepted",      "sourcePath": "docs/adr/0007-adopt-postgres.md",      "matchedFields": ["title", "body"]   // subset of id | title | tag | body    }  ],  "cursor": null}

get_decision

The complete typed frontmatter + body for one ref.

jsonc
// input{ "ref": "0007" }               // AdrRef, 1–128 chars (local id, or a "log:id" federated ref)// output → discriminated on "outcome"// found (the full record is nested under "decision"):{  "outcome": "found",  "decision": {    "requestedRef": "0007",    "id": "0007",    "title": "Adopt Postgres",    "status": "accepted",    "sourcePath": "docs/adr/0007-adopt-postgres.md",    "frontmatter": { /* typed YAML: status, tags, affects, relations, ... */ },    "body": "## Context\n..."  }}// other outcomes:// { "outcome": "not-found", "requestedRef": "9999" }// { "outcome": "ambiguous-local-id", "requestedRef": "0007", "candidates": [ /* DecisionSummary[] */ ] }// { "outcome": "federated-log-unavailable", "requestedRef": "core:12", "log": "core", "id": "12" }

A log:id federated ref is recognized but never resolved or substituted — this server reads exactly one local corpus.

get_decision_context

Governing / active-proposal / historical decisions for repo-relative files[], via each record's own affects matchers. Paths are compared against patterns only — never opened.

jsonc
// input{  "files": ["src/db/pool.ts", "src/db/schema.sql"]  // 1–256 entries; each POSIX, 1–1024 chars; no leading "/", no "..", no drive, no "\"}// output → single "matches" branch (all three arrays; empty is the same branch){  "outcome": "matches",  "governing": [    {      "id": "0007",      "title": "Adopt Postgres",      "status": "accepted",      "sourcePath": "docs/adr/0007-adopt-postgres.md",      "firedMatchers": [ { "type": "path", "pattern": "src/db/**" } ],      "relations": { "supersedes": [], "supersededBy": null, "relatesTo": [], "conflictsWith": [] }    }  ],  "activeProposals": [],  "history": []}

list_superseded

Every superseded record with its direct local replacement state — the tool that keeps agents from re-proposing rejected paths.

jsonc
// input (pagination only){}// output → single "entries" branch{  "outcome": "entries",  "items": [    {      "id": "0003",      "title": "Use MySQL",      "status": "superseded",      "sourcePath": "docs/adr/0003-use-mysql.md",      "supersededBy": {            // one of four states:        "resolved": true,        "target": { "id": "0007", "title": "Adopt Postgres", "status": "accepted", "sourcePath": "docs/adr/0007-adopt-postgres.md" }      }      // unresolved states:      //   { "resolved": false, "targetRef": "0099", "reason": "dangling" }      //   { "resolved": false, "targetRef": "0007", "reason": "ambiguous", "candidateCount": 2 }      //   { "resolved": false, "targetRef": "core:1", "reason": "federated-unavailable", "log": "core", "id": "1" }    }  ],  "cursor": null}

Relation refs (supersedes, supersededBy, relatesTo, conflictsWith) are surfaced verbatim and never expanded — follow them with a second get_decision call. Supersession is reported one hop deep; there is no transitive traversal.

Library surface

The package root exports only a sealed lifecycle factory. There is no way to reach the underlying SDK server, its registrations, or its transport:

ts
import { createAdrkitMcpServer } from '@adrkit/mcp';
const server = createAdrkitMcpServer({ cwd: process.cwd(), dir: 'docs/adr' });await server.start();   // validates the root, then serves one stdio connection// ... later:await server.close();

createAdrkitMcpServer(options?) performs no filesystem access at construction and returns a frozen, null-prototype handle with exactly start() and close().

Transport failures — a transport that fails to start, or a background stream error such as the EPIPE from a client that has gone away — are reported through the optional onError option, which defaults to a stderr diagnostic. The adrkit-mcp binary additionally exits non-zero. Nothing is written to stdout: that is reserved for protocol frames.

Closing stdin is the shutdown signal, as the MCP stdio binding specifies: the adrkit-mcp binary exits 0 with nothing on stderr. Requests still in flight when stdin closes are aborted and not answered, so a client (or a script piping requests in) must keep stdin open until it has read every response it wants.

Limits

query 1–256 code units (non-empty after trimming); ref 1–128; files[] 1–256 entries of 1–1024 POSIX-only chars (no leading /, no .., no drive letter, no backslash); status ≤6, scope ≤3, tags ≤32 × ≤64 chars; result and findings pages default 20, max 100; a per-record ADR source cap of 64 KiB (oversized records are excluded and surfaced as a record-too-large finding, never truncated). Every input object is strict — an unknown field is rejected before any corpus access.

Pagination and cursor restart

Every growing channel returns a cursor (null on the last page). Cursors are opaque, versioned, and bound to both the corpus fingerprint and the call's query shape. Reuse a returned cursor only with identical request parameters against an unchanged corpus; otherwise the response is a non-error invalid-cursor outcome (corpus-changed, query-mismatch, wrong-channel, offset-out-of-range, cursor-not-applicable, version-unsupported, or decode-failed) and you should restart the walk from no cursor. The primary-result and findings channels page independently. A corpus-unavailable outcome is returned when the ADR directory cannot be read.

Boundaries (out of scope by design)

No fifth tool; no writes, proposals, or PR creation; no MCP prompts, resources, subscriptions, or sampling; no HTTP/SSE transport or authentication; no model, embedding, ranking, or network access; no persistent cache/index/database; no named-log federation or multi-repository aggregation; no transitive supersession traversal.

Toolchain

Developed and tested with Bun; published artifacts are ESM targeting Node.js >=22 and are verified on Node 22 and 24. Runtime dependencies are exactly @adrkit/core, @modelcontextprotocol/server (MCP TypeScript SDK v2), and zod.

Apache-2.0.

來源:packages/mcp/README.md,提交 7b831be

工具

0
SourceWeft 尚未在沙箱中啟動過該軟體包,因此其工具未知。

版本歷史

7
  1. v0.20.0最新Oct 11, 2026
  2. v0.19.0Oct 10, 2026
  3. v0.18.0Oct 9, 2026
  4. v0.17.0Oct 3, 2026
  5. v0.15.0Sep 28, 2026
  6. v0.14.0Sep 22, 2026
  7. v0.13.0Sep 16, 2026

評分

已滿足適用檢查項的 50%

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

  • 近 30 天內可連通25 分

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

  • 已宣告認證方式10 分

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

  • 已列出工具15 分

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

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

其他 Memory 整合