Umtri

io.umtri由 umtri.io 發布官方發布者v1.7.1更新於 Nov 6, 2026

Give your AI agent a persistent map of your project's structure, dependencies, and bugs.

已驗證Streamable HTTP可網頁執行效率與工作流知識與記憶開發者工具

概覽

AI 產生的概覽

Umtri 為 AI 程式助理提供專案結構、相依性、API 與缺陷的持久化地圖,以樹狀結構儲存並透過 MCP 查詢。

可以做什麼
  • 列出專案,讀取專案的結構圖、季節、API 與缺陷,可依子樹、層級、角色或季節限定範圍
  • 從節點或缺陷出發追蹤影響範圍,查看變更或故障會波及哪些部分
  • 建立、更新與軟刪除節點、邊、API、缺陷與季節,封存季節前需使用者確認
  • 把提交記錄關聯到其實作的節點,並將計畫節點提交為正式結構
  • 讀取、寫入、編輯與刪除 wiki 頁面,並瀏覽其修訂歷史
  • 將整個專案匯出為單一 JSON 文件,並讀取僅追加的變更歷史
適用情境
適合助理每次工作階段都要重新推導程式庫、而你希望結構、相依性與已知缺陷只存一次並跨工作階段重用的情境。也適合需要回答「改動某處會影響什麼」的問題,前提是團隊會透過提交同步習慣讓地圖保持更新。
執行需求
可使用 mcp.umtri.io 的託管端點,或以 npx 透過 stdio 執行本機 npm 套件 umtri-mcp。需要 Umtri 應用程式產生的個人存取權杖:託管端點透過 Authorization 標頭以 Bearer 方式傳入,stdio 方式則透過 UMTRI_API_TOKEN 傳入。自架時可用 UMTRI_API_BASE 覆寫 API 基礎位址。需要能存取 Umtri API 的網路。
安裝前請注意
權杖在設定時不會被驗證,權杖錯誤或僅有讀取權限時可連線但寫入工具會失敗。許多工具會寫入、修改或刪除資料,包括永久刪除缺陷與 wiki 頁面,以及串聯刪除節點。伺服器從不讀取檔案或 git,若不記錄提交,地圖會落後於程式碼;送出的內容都會被儲存,因此不要在節點或頁面中放入密鑰、憑證或個人資料。

安裝

在 SourceWeft 中

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

Web executable,透過 Streamable HTTP。 遠端服務在工作區中設定後即可從網頁執行環境執行。

交給代理程式安裝

把這段提示詞貼上到 Claude Code、Codex、Cursor 等代理程式,或 SourceWeft 對話中。代理程式會讀取該伺服器的安裝指南,先向你展示發布者、端點和登入方式,經你同意後再把它新增到你的客戶端。金鑰不會寫進任何命令。

閱讀 https://sourceweft.com/mcp/io.umtri%2Fumtri/install.md,並按其中說明把這個 MCP 伺服器接入我的客戶端。修改任何設定之前,先告訴我它的發布者、端點和登入方式,等我確認。不要把 API 金鑰寫進命令或我會提交的檔案;問我金鑰應從哪裡取得。

檢視代理程式所依據的安裝指南

其他 MCP 客戶端

把它新增到你客戶端的 mcpServers 設定中。

{
  "mcpServers": {
    "umtri": {
      "type": "http",
      "url": "https://mcp.umtri.io/"
    }
  }
}

README

umtri-mcp

[Umtri MCP server]

MCP server for Umtri — give your AI coding agent a persistent map of your project's structure, dependencies, and bugs.

Your agent re-derives your codebase from scratch every session. Umtri stores the structure once and hands it back through MCP: a tree of what the system is made of, the calls and dependencies between its parts, and the bugs eroding it. Ask "what breaks if I change this?" and get an answer traced through recorded connections rather than guessed from a grep.

Quick start

The fastest path is the hosted endpoint at https://mcp.umtri.io — nothing to install. Generate a token at app.umtri.io → Settings → API Tokens, then:

bash
claude mcp add --transport http umtri https://mcp.umtri.io \  --header "Authorization: Bearer umtri_pat_xxxxxxxxxxxxxxxx"

Any MCP client that takes a config object uses the same shape:

json
{  "mcpServers": {    "umtri": {      "type": "http",      "url": "https://mcp.umtri.io",      "headers": { "Authorization": "Bearer umtri_pat_xxxxxxxxxxxxxxxx" }    }  }}

Run it yourself (stdio)

Use this package when you want to pin a version or point at a self-hosted API:

bash
claude mcp add umtri \  -e UMTRI_API_TOKEN=umtri_pat_xxxxxxxxxxxxxxxx \  --transport stdio \  -- npx -y umtri-mcp
VariableRequiredDefault
UMTRI_API_TOKENyes—
UMTRI_API_BASEnohttps://api.umtri.io

The token is not validated at setup time, so a bad token connects but every call fails. If tools appear and then error, re-check the token and its scope — read tokens cannot call any write tool.

Tools

Read — get_graph, get_bug, get_impact, list_projects, list_bugs, list_seasons, list_events, export_ground

Write — create_project, create_node, update_node, delete_node (a subtree only with cascade: true), create_edge, delete_edge, create_api, update_api, delete_api, create_bug, update_bug, delete_bug, create_season (acts only after the user confirms)

Plan loop — commit_plan, record_commit

Wiki — list_wiki, get_wiki, list_wiki_revisions, write_wiki, edit_wiki, delete_wiki. The ground's encyclopedia: pages form a table of contents (parent, position) read from an overview down, each has a kind, and every write comes back with warnings when a page strays from the skeleton.

Feedback — send_feedback files a suggestion or defect about Umtri itself.

get_graph returns a slice, not a dump: scope by subtree (rootId), by layer (maxType), by role, or by season, and control description weight separately. A large tree stays cheap to read.

Resources

Ten read-only documents the agent can pull for domain rules — the plant vocabulary (trunk/limb/twig/leaf/vein), what counts as a node and what does not, how seasons work, how plan nodes are meant to be realized, how a ground behaves while transplanting, keeping the tree in step with commits, and how to write and organize the wiki.

umtri://rules/vocabulary            umtri://rules/planumtri://rules/vocabulary-detailed   umtri://rules/commit-syncumtri://rules/system-structure      umtri://rules/wikiumtri://rules/seasons               umtri://templates/wikiumtri://rules/transplant            umtri://about/vision

Links

License

Apache-2.0. See LICENSE.

來源:README.md,提交 16fa299

工具

32

list_projects

List grounds (projects)

Returns all grounds the authenticated user can access, with latest activity timestamp. Use this first to discover slugs for other tools. By default returns a summary view — each ground carries slug, name, isActive, transplanting, nodeCount, openBugs, seasonCount, nowSeasonLabel, latestActivityAt, plus a 200-char description excerpt. A ground that belongs to a team also carries org (the team slug) and role (owner/editor/reporter/viewer) — a viewer can read but every write tool returns 403 there; a reporter can only create_bug and update_bug. A ground with wiki pages also carries wikiCount — prose the tree cannot hold (conventions, decisions, glossary); read it with list_wiki. Pass view="full" for all fields (seedMeta — the ground's human-written intent: goal, endDate, budget, audience — plus typeCounts, raw metadata, timestamps); the icon base64 in metadata is always stripped (UI-only).

輸入參數view

get_graph

Get the graph of a ground

Returns the tree(nodes), edges, apis, seasons, and bugs for one ground. The tree is the project's information-structure (IA) diagram — each node is a structural element (an object, or an action it performs), not a work-log entry. Node types follow the plant metaphor: trunk → limb → twig → leaf → vein. See resource umtri://rules/vocabulary. By default returns a summary view — nodes carry id/label/type/parent/season, plus a 200-char description excerpt, metadata.implements, placeholder/dormant flags (soft-deleted nodes are omitted). Pass view="full" only when you need timestamps, full descriptions, all metadata keys, or tags — that response is ~3× larger. For a large tree, read it in slices instead of all at once: rootId (+depth) for one trunk or limb; maxType for a layer (e.g. maxType="twig" = the skeleton without leaves/veins — a cheap overview); role for a cross-section; season for what was born in one season. Filters combine. Node ids come from the graph itself, so the standard drill-down is two calls: first get_graph with maxType="trunk" (or "limb") for a cheap skeleton, find the id you want, then call again with rootId set to it to get just that trunk/limb and its subtree. Control the heaviest field with descriptions: "none" drops descriptions for a pure structural overview, "excerpt" (default) gives a 200-char preview, "full" returns them verbatim when you drill into a limb. The summary response also carries shape (nodeCount, maxDepth, nodes-per-level, over-wide branches) so you can judge whether the tree is too deep or too wide without rebuilding it, a childCount on each branch node, and iaHints flagging structural smells. A bushy tree (mass at mid-levels) is healthy — don't over-nest sparse parents into twigs. Bugs default to active (open + in_progress) — pass bugStatus="all" to also see healed (resolved/closed) ones. Nodes may carry plan:true — these are the human's node-based brief (intent drawn as structure, not a prompt); read them as instructions and rea

輸入參數roleslug必填viewdepthrootIdseasonmaxTypebugStatusdescriptions

get_impact

Trace the blast radius of a node or bug

Walks the connection graph (edges + apis) from a start node — or a bug's target — to find which other nodes a problem would reach. This is the tool for "if this breaks / I change this, what else do I need to check?" and for QA scoping. Impact does NOT always flow with the arrow. direction="affected" (default) answers "if the start breaks, who is hurt?" and follows: dependency edges backward (target→source), data_flow edges forward (source→target), apis backward (callee→caller). direction="dependsOn" is the reverse ("what does the start rely on?"). direction="both" unions them. See umtri://rules/system-structure (How problems propagate). Provide exactly one start: node (a node id) or bug (a bug id — starts from its target node, or both endpoints if the bug is on an api; ground-level bugs are rejected). Traversal is over CURRENT (live) structure only. Returns reached[] (each with hops distance, the node `from` which it was reached, and the connection `via` it came through — so you can reconstruct the chain), bugs[] (active bugs sitting on any reached node/api, worst score first), and coverage. IMPORTANT: the result is a list of nodes to CHECK, not a proven failure set — it is only as complete as the connections recorded. coverage.startsWithoutConnections flags when the start has no connections at all: an empty result then means "nothing recorded," not "nothing affected" — record edges/apis first.

輸入參數bugnodeslug必填maxDepthdirection

list_bugs

List bugs of a ground

Scans the bugs (issues eroding the ground) of one ground. Looking at ONE bug you already know the number/id of? Call get_bug instead — no need to list. Bugs default to status="active" (wild + chasing): a healed bug is history, and history is not what a scan is for. Ask for "resolved" or "all" when you actually want it. Status speaks the product's own words — wild (found, nobody on it) → chasing (someone is fixing it) → resolved (it landed) — the same words the UI shows. Each bug has a score (0–8 change-risk; 8 = riskiest), and any bug whose solution carries a checklist also carries solutionProgress ("2/5" — ticked/total), so you can see what is left without opening a single body. Targets: a node, an api, or the ground itself. By default returns a summary view — each bug carries id, seq (the number a human says, "#14"), target, title, score, status, createdAt/resolvedAt, plus a 200-char description excerpt. Each node/api bug also carries impactCount — how many other nodes its target reaches by blast radius (affected direction), so you can spot wide-blast bugs at a glance; call get_impact on that bug for the full reached list. Pass view="full" for full descriptions and metadata. Use limit + order to bound a scan (e.g. the 5 newest) instead of pulling every bug.

輸入參數slug必填viewlimitorderstatus

get_bug

Get one bug of a ground

Returns a single bug by reference — the cheap path when you already know which bug you mean. `ref` accepts either the human-facing number shown in the UI (seq — "14" or #14) or the internal id (bug-<uuid>), so a human saying "#8" needs no listing at all. Unlike list_bugs this ignores status: a resolved bug is still readable by number, which is how you review what a past fix actually did. Use list_bugs only to scan for bugs you cannot yet name. The response carries the full description and metadata, plus impact — the blast radius reached from the bug's target (reachedCount, the reached nodes with hop distance, and other active bugs sitting in that radius). Numbers are per-ground and never reused, so a deleted bug leaves a gap rather than shifting the others. Returns an error if no bug matches.

輸入參數ref必填slug必填solutiondescriptions

list_seasons

List seasons of a ground

Returns the seasons (time epochs) of a ground in chronological order. A season is the human's declaration that a chapter closed. You may create one with create_season, but only after the user confirms it — see umtri://rules/seasons. By default returns a summary view (id, label, state, startedAt, grownAt). Pass view="full" to also include metadata.

輸入參數slug必填view

export_ground

Export a whole ground as JSON

Returns everything in a ground as one JSON document — project, seasons, nodes (removed ones included, with removedAt), edges, apis, bugs and wiki pages with full bodies. For backups, moving off Umtri, or answering "can I take my data out?" (yes — see umtri://about/data). The result is large; save it to a file rather than summarising it, and do not call it for ordinary reads (use get_graph).

輸入參數slug必填

list_events

List change history of a ground

Returns the append-only change history (most recent first) of a ground: node/edge/api/bug create, update (with a field-level diff {from,to}), delete, and plan_commit. Each event carries the actor ("user:<id>" for humans, "token:<id>" for agents/automation), a summary label, and for updates a diff. Use it to answer "what changed, when, and by whom" — e.g. a bug's status transitions or a node's edits over time. Filter with entityType/entityId to get a single entity's timeline. Note: git commits recorded via record_commit live in a node's metadata.commits, not here.

輸入參數slug必填limitbeforeentityIdentityType

create_bug

Report a bug on a ground

Creates a new bug (issue eroding the target). target.kind = "node" or "api" requires target.id of an existing node/api in the ground. target.kind = "ground" attaches the bug to the project itself (no id). score = change risk on a 0–8 scale (8 = riskiest). It blends functional impact with fix difficulty (a harder fix is likelier to break things, so it ranks higher within a tier). 0: no risk — idea / memo. 1: no risk — copy / wording edit. 2: no functional error, but may change usability. 3: minor functional issue possible — simple fix. 4: minor — complex fix. 5: significant functional issue possible — simple fix. 6: significant — complex fix. 7: critical functional issue possible — simple fix. 8: critical — complex fix. Defaults to 4. Urgency is intentionally NOT part of this score. status defaults to "open". solution is the fix, and it belongs to agents — the app gives people no way to edit it, so a human's own proposed fix arrives in description instead. At report time solution holds the plan, and by the time the bug is resolved it should describe what was actually applied. Same field — overwrite it as understanding changes; project_events keeps the diff. Write what remains as "- [ ] item" lines so the app can render them as cards and later moves cost one small op (update_bug patch:{solutionItem}). Leave it empty rather than guessing. For a node/api bug, the response auto-attaches impact (the affected blast radius from the target): reachedCount, the reached nodes with hop distance and the connection each was reached through, other active bugs sitting in that radius, and a coverage note. Use it to scope what else to check/QA. If the target has no recorded connections the radius is empty — that means nothing is recorded, not that nothing is affected (record edges/apis). Requires a write-scope token. See umtri://rules/vocabulary for bug semantics.

輸入參數slug必填scoretitle必填statustarget必填solutiondescription

create_project

Create a new ground (project)

Creates a new ground. Slug must match /^[a-z0-9][a-z0-9-]{0,49}$/ and be unique. By default it goes into the authenticated user's personal space; pass org (a team slug, as list_projects shows it) to create it in a team — only the team's owner can. Requires a write-scope token.

輸入參數orgname必填slug必填description

create_season

Create a new season

Creates a new season and makes it the "now" season. This is not an additive act: the ground's current now-season is sealed as past and every node in it is marked grown, which locks that node's parent/season/type/sproutedAt. CONFIRMATION GATE: call once WITHOUT confirm to get back what would be sealed, put that to the user in your own words, and call again with confirm:true only after they say yes. Never pass confirm:true on your own judgment — a season is the human's declaration that one chapter closed and the next began, and inventing one makes the ground's timeline meaningless. Unsure which season a node belongs to? Attach it to the existing now-season instead of opening a new one. See umtri://rules/seasons.

輸入參數slug必填label必填confirm

create_node

Create a node in a ground

Creates a node. Follows the plant vocabulary protocol — see umtri://rules/vocabulary. type ∈ trunk · limb · twig · leaf · vein. Role is derived (structure / object / action). Build leaf-first: when adding a leaf/vein, create only the missing trunk/limb/twig ancestors on its path, then the leaf — do NOT pre-build every trunk, then every limb, then leaves (see Build order in umtri://rules/vocabulary). Aim for a faithful, COMPLETE map of the project, not a summary: every meaningful module/screen/endpoint/table/integration should become a node (grouped at the information-unit grain, not one-per-file). A real project yields many leaves — under-capturing to a few nodes is the more common mistake. See Completeness in umtri://rules/system-structure. parent ∈ existing node id; omit to create a root-level node. season ∈ existing season id; omit to use the active "now" season. Past seasons are normally rejected, but allowed while the ground is transplanting (project.transplanting=true) — nodes added then are auto-stamped metadata.transplanted=true for audit. See umtri://rules/transplant. The tool validates against protocol policies. Hierarchy violations are rejected. Soft issues (reserved-domain labels, leaf↔vein heuristic, trunk naming) come back as warnings in the response — reconsider before continuing if warnings appear. A trunk carries metadata.kind ∈ front · server · database · library · device · tooling, and its limbs follow that kind's axis: same domain name across trunks with no suffix ("예약", not "예약 API"), no technical-layer limbs, and at most one common limb (metadata.common=true). Read umtri://rules/trunk-kinds before creating a trunk or a limb under one. After creating a leaf/vein, consider its connections: if it calls/feeds another node add an api (create_api), if it depends on/is built on another add an edge (create_edge). The response carries a connectionCheck reminder. See umtri://rules/system-structure (Connections). Do not open a new season just because none

輸入參數slug必填tagstype必填label必填parentseasonmetadatasproutedAtdescription

update_node

Update a node

Partial update of a node. Patchable fields: label, type, parent, season, description, tags, metadata, sproutedAt. metadata is merged key by key: only the keys you send change, keys you leave out (commits that record_commit accumulated, transplanted, and so on) are kept, and a key sent as null is removed. So to change implements, send just { metadata: { implements: [...] } }. Type change reclassifies role; parent change recomputes the ltree path automatically. On a grown (past-season) node, only the tree's shape and timeline are locked — parent, season, type and sproutedAt are rejected. Content fields (label, description, metadata, tags) stay editable, so you can keep metadata.implements current when code moves without reopening transplanting. Moving any node into a `past` season is rejected. Both restrictions lift while the ground is transplanting (project.transplanting=true), so historical structure can be reconstructed (see umtri://rules/transplant). Same protocol validation as create_node — reject on hierarchy violations, warn on soft issues.

輸入參數id必填slug必填patch必填

delete_node

Soft-delete a node

Sets removed_at on the node. By default this tool rejects deletion if the node has any active descendant, so a subtree is never lost silently. To soft-delete the node together with all its active descendants, pass cascade=true — only when the human asked to remove the whole branch; soft-deleted nodes cannot be restored. The response lists the cascaded ids. EXCEPTION — while the ground is transplanting (project.transplanting=true), the active-descendant guard is lifted (subtree cascade allowed) and you may pass hard=true to permanently remove import mistakes, including grown (past-season) nodes. Once the human roots the ground, normal guards return.

輸入參數id必填hardslug必填cascade

commit_plan

Commit a realized plan node

Promotes a plan node (metadata.plan=true) to the real tree by clearing the plan flag. VERIFICATION GATE: the node must already carry metadata.implements (the source path(s) you wrote) — without it the commit is rejected, because an uncommitted plan node with no implements is not considered realized. Call this only after you have actually written the code and recorded implements via update_node. Commit from the top down: a node whose parent is still a plan is rejected — commit the parent first. See umtri://rules/plan.

輸入參數id必填slug必填

record_commit

Record a git commit onto the nodes it touched

Configuration record (CI/CD). Given a commit SHA and the files it changed, finds nodes whose metadata.implements include any of those files and appends the commit (sha + timestamp + optional message) to their metadata.commits (deduped by sha). Returns the matched node ids. When one commit touches several nodes that are NOT yet connected, the response also carries coChangeCandidates[] ({a, aLabel, b, bLabel}) — nodes that change together are dependency candidates; review them and add a create_edge/create_api where a real relation exists (not auto-created; suppressed for large multi-node commits; pass coChange=false to skip them entirely when nobody will review, e.g. a CI step that only records). Umtri does not run jobs or read git itself — a GitHub Action / CI step or an agent supplies the sha+files. Recording a commit is the LAST step: first make sure the change is in the tree (new unit → create_node with metadata.implements; moved file → update_node), otherwise the sha lands on the nodes that happen to exist and the new ones stay invisible. A repo that keeps forgetting should write the habit down — see umtri://rules/commit-sync. See also umtri://rules/plan.

輸入參數sha必填slug必填files必填messagecoChange

create_edge

Create an edge between two nodes

Creates a directed edge (source → target) for a STRUCTURAL relation: type "dependency" (A is built on / needs B) or "data_flow" (data moves A → B outside a request). Use for module/library deps, a route depending on the data store, a job writing a table. For a runtime request/call/integration use create_api instead, not an edge. Reserve connections for relations a maintainer would trace — don't wire everything. type ∈ project.edge_types; same source and target is rejected. See umtri://rules/system-structure (Connections).

輸入參數slug必填type必填labelsource必填target必填metadata

delete_edge

Delete an edge

Removes an edge from the ground. Use to retire dependencies/flows that no longer reflect reality.

輸入參數id必填slug必填

create_api

Create an API flow between two nodes

Records an API flow (start → end) for a RUNTIME request / call / data flow: a screen calling an endpoint, an endpoint hitting a table, an external integration (payment, SMS, webhook). Direction is caller → callee. APIs are first-class (apis table), not generic edges — for a build-time/structural reliance use create_edge (dependency) instead. Add the flows a maintainer would trace; don't wire everything. start/end must be existing node ids. See umtri://rules/system-structure (Connections).

輸入參數end必填slug必填labelstart必填metadatadescription

update_api

Update an API entry

Partial update of an API. Patchable fields: label, description, metadata, start, end.

輸入參數id必填slug必填patch必填

delete_api

Soft-delete an API entry

Sets removed_at on the API. History is preserved — the API can still be seen in past season views via the time slider.

輸入參數id必填slug必填

update_bug

Update a bug

Partial update of a bug. Most common use: status transition. Send only the fields that actually change. A status transition is patch:{status} alone — do not re-send an unchanged solution, description, or metadata. Those fields carry prose, and re-emitting them costs far more time than the update itself and risks a malformed-argument retry. Follow the lifecycle one step at a time: open (wild) → in_progress (chasing) → resolved. Set status="in_progress" the moment you start the fix, not after it lands — it is the only marker that someone is already on this bug, so a parallel agent can see the work in flight instead of duplicating it. Then set "resolved" once it ships. Skipping straight from open to resolved returns a warning (not a rejection) — acceptable when the fix was genuinely instant. Other patchable fields: title, description, solution, score (0–8 change-risk), metadata. solution is yours to maintain — the app does not let people edit it, so what you write is what the human reads. Their own proposed fix arrives in description instead. Keep solution as a checklist: prose for what you learned, "- [ ] item" lines for what remains. To move one item use patch:{solutionItem:{…}} instead of re-sending the whole field — add: "text", or check/uncheck/remove: <1-based item number>. Pass expect:"<start of that item text>" alongside a number so a shifted list fails loudly instead of ticking the wrong line. This is the cheap path: one short op, not a re-emitted body. When resolving, rewrite solution to what you actually applied — at report time it held the plan, and leaving a stale plan there is worse than leaving it empty. To mark a bug as fixed, prefer status="resolved" over delete — that preserves the history of what eroded the tree. When resolving, you may record the shipped release in metadata.resolvedVersion (e.g. "v2.3.1"); metadata is replaced wholesale, so include existing keys you want to keep.

輸入參數id必填slug必填patch必填

delete_bug

Delete a bug (hard delete)

Permanently removes a bug record. Bugs do not have history — once deleted, the record is gone. For "I resolved this", use update_bug with status="resolved" instead, so the tree remembers what was eroded.

輸入參數id必填slug必填

send_feedback

Send feedback about Umtri itself

Files a suggestion or a defect report about **Umtri the product** — this MCP server, its tools, the app, the docs. This is NOT for issues in the user's own project: those are bugs on a ground (create_bug). Call this ONLY when the human explicitly asks to leave feedback ("건의해줘", "report this to Umtri"). Do not file feedback on your own initiative — an inbox filled by agents stops being read. kind: "bug" = something in Umtri is broken or wrong; "improvement" = a suggestion / wish (default). source: where it surfaced — the ground slug you were working in, the tool name that felt wrong, the screen. It is free text and is not validated, but it is what makes a report actionable later. One-way: this files the report, and there is no reading it back — do not promise the human a status thread. Requires a write-scope token.

輸入參數bodykindtitle必填source

list_feedback

List feedback filed about Umtri

Lists feedback filed about **Umtri the product** (see send_feedback) — not the bugs of any ground. Umtri operators only: every other account gets 403, so do not call this to check on feedback you filed. Newest first. Status: open (untouched) → done (handled) / wontfix (declined, with the reason in note). Defaults to every status; pass status to narrow. Use limit to bound a scan.

輸入參數kindlimitorderstatus

update_feedback

Update filed feedback

Updates one feedback record about **Umtri the product** — typically closing it: status="done" once it shipped, or "wontfix" when it was declined. Put what was actually done (or why not) in note; that is the part worth reading a year later. Umtri operators only: every other account gets 403. Send only the fields that change. Requires a write-scope token.

輸入參數id必填bodykindnotetitlesourcestatus

list_wiki

List wiki pages of a ground

Lists the ground's wiki — the prose the tree cannot hold: conventions, decisions and why they were made, glossary, onboarding. Reference entries describing how things work, not a log of what happened: the change record is list_events, the page's own past is in its revisions. Not the structure itself (get_graph) and not defects (list_bugs). Bodies come back as 200-char excerpts by default so a scan stays cheap; pass body="full" only when you mean to read them, or body="none" for a pure index. A page may hang off a node (nodeId) or float free — pass node=<id> for one node's pages, or node="none" for the pages not yet attached to anything, which is the list worth reviewing when the tree has grown. The wiki is a tree: each page has a parent page and a position among its siblings, starting from an overview page. order="tree" returns the whole table of contents in reading order (depth-first, with depth) — use it to read the wiki front to back or to see where a new page belongs. Every page also has a kind (overview / concept / component / rule / glossary); kind="none" lists the pages not yet classified.

輸入參數bodykindnodeslug必填limitorder

get_wiki

Read one wiki page — in full, as an outline, one section, or the lines around a phrase

Returns one wiki page. `ref` takes either the page slug (what a human says) or the internal id (wiki-<uuid>) — renaming a page changes its slug but never its id, so ids stay safe to store. Every response carries rev (the current revision, what you pass as baseRev when you write) and bodyChars. By default the whole body comes back. **Pages run long (tens of thousands of characters); do not read one in full to answer a small question.** view="outline" returns the lead paragraph and the heading tree (path like "1.2", level, heading, line, chars per section) — start there on a page you have not seen. section="<heading text or path>" returns just that section (through its sub-headings), plus the footnote definitions it references; it must match exactly one heading, and on an ambiguous match the error lists the candidates with their paths. find="<text>" returns the lines containing the text (case-insensitive, literal) with context lines around each, merged into blocks with line numbers — a block is ready to be the oldString of edit_wiki. find inside one section: pass both. Read in full before write_wiki mode="replace" — it overwrites the body wholesale, and an outline is not the body. For a one-passage fix, find or section the spot and call edit_wiki instead. Pass rev=<n> to read an older revision instead of the current page (list them with list_wiki_revisions; outline/section/find work there too). To put an old revision back, do not paste its body into a write — use write_wiki mode="restore", which cannot mangle the prose in transit.

輸入參數ref必填revfindslug必填viewcontextsection

list_wiki_revisions

List the revision history of a wiki page

Returns what this page said before, newest first — rev number, who wrote it, when, and the body length. Bodies are not included (a history of twenty full documents is expensive to skim); read one with get_wiki rev=<n>. Use it to answer "what did this say last week", to see whether a write of yours dropped something, and to find the rev to hand back to write_wiki mode="restore". Consecutive writes by the same actor within 30 minutes fold into one revision rather than piling up, so the list stays readable — a working session is one entry, not eight. The practical guarantee: whatever an agent does to a page in one session, the body from before that session is still a separate revision. Revisions start at the moment the ground gained this feature; edits older than that were never recorded and cannot be recovered.

輸入參數ref必填slug必填limitorder

write_wiki

Create or update a wiki page

Writes one wiki page. Creates it if the page slug is new, updates it otherwise — you do not need to check first. **The wiki is the project's encyclopedia: one page is one entry, and its body is the current spec and rules of that thing.** It is a tree read front to back: an overview page at the top, chapter pages under it, entries under those — place every page with parent (a page slug or id) and position (its order among siblings), and check list_wiki order="tree" to see where it belongs. For a new wiki, follow the table of contents in umtri://templates/wiki. The title is a plain noun for the thing in the reader's language (조직, 배포, Billing) — no dash, colon, parenthetical or sentence; the description goes in the lead. Give every page a kind — overview (the top page and chapter pages that introduce what is under them), concept (a product/domain concept or model), component (how one part of the system works), rule (a convention that must be kept), glossary (the project's vocabulary). Write it to this skeleton: a lead paragraph first (1–3 sentences saying what the thing is — not a heading, quote or list), then "## 스펙" / "## Spec" (how it works now; break it down with ###), then "## 규칙" / "## Rules" (invariants, prohibitions, required order). concept and component need Spec; rule needs Rules; overview and glossary are free-form after the lead. No other top-level (##) sections. Background, history, rejected alternatives and side notes go into footnotes — [^name] in the text, [^name]: … at the end — not into the body. A reason stays in the body only if someone changing the code would get it wrong without it. Write what the tree cannot hold and what a maintainer would otherwise have to reconstruct: why a decision went the way it did, the vocabulary this project uses, what an investigation concluded. Do not restate the structure — that is what nodes are for. **A page is a description, not a log.** Write it in the present tense, as a reference entry for the thing: how it wor

輸入參數revbodykindmodenodepage必填slug必填titleparentrenamebaseRevposition另有 1 個

edit_wiki

Change one passage of a wiki page

Replaces one passage of an existing wiki page without resending the body. Pass the exact text to replace (oldString) and what it becomes (newString) — the same contract as a code editor's Edit: oldString must occur **exactly once** on the page. If it is missing, or occurs more than once, nothing is written and the error says which; copy the text verbatim from get_wiki (whitespace and line breaks count) or include more surrounding text to make it unique. newString="" deletes the passage. Matching is literal, not a regex. This is the normal way to fix a sentence, update a value, or correct one rule on a page that already exists. Use write_wiki when you are composing a page or rewriting several sections at once, and mode="append" there when a section is genuinely missing. The edit is a revision like any other write: it folds into your previous write within 30 minutes unless newRevision=true, and baseRev refuses the edit when the page moved on since you read it. The response carries rev, coalesced, previousBodyChars and bodyChars, plus warnings[] when the page as a whole now strays from the skeleton — not the body. Requires a write-scope token.

輸入參數page必填slug必填baseRevnewString必填oldString必填newRevision

delete_wiki

Delete a wiki page

Permanently removes a wiki page **and its whole revision history** — unlike an overwrite, this cannot be undone, and only the history entry (list_events) remains to say it happened. Prefer rewriting a page that went stale over deleting it: a page that records a decision you have since reversed is worth keeping with the reversal written in. Deleting is for a page that should never have existed, not for one that is out of date.

輸入參數ref必填slug必填

版本歷史

9
  1. v1.7.1最新Nov 6, 2026
  2. v1.5.3Oct 3, 2026
  3. v1.5.2Oct 1, 2026
  4. v1.4.2Sep 30, 2026
  5. v1.3.3Sep 27, 2026
  6. v1.3.2Sep 23, 2026
  7. v1.3.1Sep 23, 2026
  8. v1.2.0Sep 23, 2026
  9. v1.1.0Sep 16, 2026

評分

已滿足適用檢查項的 100%

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

  • 近 30 天內可連通必需25 分
  • 已宣告認證方式必需10 分
  • 已列出工具必需15 分
  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分