umtri-mcp 1.7.0 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/core/api-client.js +9 -1
- package/core/instructions.js +2 -0
- package/core/resources/data.md +60 -0
- package/core/resources/system-structure.md +17 -0
- package/core/resources.js +7 -0
- package/core/tools.js +17 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -56,7 +56,7 @@ appear and then error, re-check the token and its scope — `read` tokens cannot
|
|
|
56
56
|
## Tools
|
|
57
57
|
|
|
58
58
|
**Read** — `get_graph`, `get_bug`, `get_impact`, `list_projects`, `list_bugs`, `list_seasons`,
|
|
59
|
-
`list_events`
|
|
59
|
+
`list_events`, `export_ground`
|
|
60
60
|
|
|
61
61
|
**Write** — `create_project`, `create_node`, `update_node`, `delete_node` (a subtree only with
|
|
62
62
|
`cascade: true`), `create_edge`, `delete_edge`, `create_api`, `update_api`, `delete_api`,
|
package/core/api-client.js
CHANGED
|
@@ -6,9 +6,17 @@
|
|
|
6
6
|
export function createApiClient({ baseUrl, getToken }) {
|
|
7
7
|
const base = String(baseUrl || '').replace(/\/$/, '');
|
|
8
8
|
|
|
9
|
+
// 토큰 없는 연결(HTTP 익명 discovery)에서 도구를 부르면 여기서 멈춘다. 연결은 되고 호출만
|
|
10
|
+
// 실패하는 모양이라, 이 문구가 사람에게 닿는 유일한 안내다 — 발급 위치와 넣는 자리를 한 번에.
|
|
9
11
|
async function authHeader() {
|
|
10
12
|
const token = await getToken();
|
|
11
|
-
if (!token)
|
|
13
|
+
if (!token) {
|
|
14
|
+
throw new Error(
|
|
15
|
+
'This connection has no API token, so tools cannot run. Sign in at app.umtri.io, generate a personal access token in Settings → API Tokens, ' +
|
|
16
|
+
'then send it as "Authorization: Bearer umtri_pat_…" (remote https://mcp.umtri.io) or set UMTRI_API_TOKEN (npx umtri-mcp). ' +
|
|
17
|
+
'Guide: https://docs.umtri.io/en/token',
|
|
18
|
+
);
|
|
19
|
+
}
|
|
12
20
|
return `Bearer ${token}`;
|
|
13
21
|
}
|
|
14
22
|
|
package/core/instructions.js
CHANGED
|
@@ -15,6 +15,8 @@ export const SERVER_INSTRUCTIONS = `Umtri maps a project's structure as a tree (
|
|
|
15
15
|
|
|
16
16
|
Umtri never reads git. A commit reaches the ground only because something called create_node / update_node / record_commit — so the tree drifts behind the code unless the repo has a habit that says otherwise. If this repo's own rules file (CLAUDE.md, AGENTS.md, …) has no commit-sync policy, read umtri://rules/commit-sync and offer the human a short one to paste in.
|
|
17
17
|
|
|
18
|
+
Umtri holds only what tool calls send — labels, descriptions, file paths, connections, bug and wiki text. It never reads files or git. Never put secrets, environment values, credentials or personal data into a node or page; metadata.implements is a path, not content. If the human asks what is sent or whether it is safe, read umtri://about/data and answer from it.
|
|
19
|
+
|
|
18
20
|
Before creating or reclassifying nodes, read umtri://rules/vocabulary; before creating a trunk or a limb under one, also umtri://rules/trunk-kinds. Opening a season seals the current one, so create_season only acts after the user confirms (umtri://rules/seasons).
|
|
19
21
|
|
|
20
22
|
If Umtri itself gets in your way — a call rejected for a reason that looks wrong, a capability that is missing, a tool description that misled you — tell the human what happened and offer to file it with send_feedback. Never file it on your own initiative.`;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# What Umtri receives — and what it never sees
|
|
2
|
+
|
|
3
|
+
Umtri is a map of a project, not a copy of it. This page is for the agent that
|
|
4
|
+
is about to draw a tree: it says exactly what leaves the machine, so you can
|
|
5
|
+
answer the human plainly instead of hesitating, and so you send only what the
|
|
6
|
+
map needs. The human-facing version is https://docs.umtri.io/en/data
|
|
7
|
+
(Korean: https://docs.umtri.io/ko/data).
|
|
8
|
+
|
|
9
|
+
## Only what a tool call sends
|
|
10
|
+
|
|
11
|
+
Umtri holds nothing it was not handed through the app or an MCP tool call:
|
|
12
|
+
|
|
13
|
+
- node labels, descriptions, types and metadata — including `implements`,
|
|
14
|
+
which is a list of **file paths**, never file contents
|
|
15
|
+
- connections between nodes (edges, api flows) and their labels
|
|
16
|
+
- bug titles, descriptions and solutions
|
|
17
|
+
- wiki prose
|
|
18
|
+
- season labels and the ground's name
|
|
19
|
+
|
|
20
|
+
Umtri never reads the repository. There is no git integration, no file
|
|
21
|
+
scanning, no agent on the machine. A commit reaches a ground only because
|
|
22
|
+
something called `record_commit` with a SHA and a list of paths. If you do not
|
|
23
|
+
put something into a call, it does not exist on Umtri.
|
|
24
|
+
|
|
25
|
+
## What not to record
|
|
26
|
+
|
|
27
|
+
The map describes *structure*. Keep out of every label, description, metadata
|
|
28
|
+
value and wiki page:
|
|
29
|
+
|
|
30
|
+
- secrets, API keys, tokens, passwords, environment values
|
|
31
|
+
- customer or personal data (names, emails, ids from production tables)
|
|
32
|
+
- verbatim source code — point at the file (`implements`), do not paste it
|
|
33
|
+
- internal hostnames, IPs and URLs beyond what the structure needs to say
|
|
34
|
+
|
|
35
|
+
`implements` is a path, not content. A description says what a thing is for,
|
|
36
|
+
not how its code reads. If a `.env` or a credentials file would be the honest
|
|
37
|
+
`implements` of a node, name the node and leave `implements` empty.
|
|
38
|
+
|
|
39
|
+
## Where it goes and who sees it
|
|
40
|
+
|
|
41
|
+
- Stored at `api.umtri.io` (AWS, Seoul) in PostgreSQL; every connection is TLS.
|
|
42
|
+
- No ground is public. Only the members of the organisation that owns the
|
|
43
|
+
ground — and, in a team, only the people assigned to that ground — can read
|
|
44
|
+
it. The public demo (`app.umtri.io/demo`) is separate, fictional data.
|
|
45
|
+
- API tokens are stored as SHA-256 hashes; the plain token is shown once. A
|
|
46
|
+
`read` token cannot write. Tokens can be revoked at any time.
|
|
47
|
+
- Deleting a ground removes it immediately and cannot be undone. Deleting an
|
|
48
|
+
account removes it immediately.
|
|
49
|
+
- Everything can be taken out at any time: `export_ground` (or
|
|
50
|
+
`GET /api/projects/<slug>/export`) returns the whole ground as one JSON.
|
|
51
|
+
|
|
52
|
+
## When the human asks "is this safe?"
|
|
53
|
+
|
|
54
|
+
Answer from this page: what will be sent (the list above, nothing else), where
|
|
55
|
+
it goes, who can see it, how it is deleted and exported. Point them to the docs
|
|
56
|
+
page and let them decide. Do not refuse on their behalf, and do not send more
|
|
57
|
+
than the map needs. If the project's own rules forbid naming a part of the
|
|
58
|
+
system, leave that part out and say so in the ground's wiki.
|
|
59
|
+
|
|
60
|
+
Privacy policy: https://umtri.io/privacy/ (Korean: https://umtri.io/ko/privacy/).
|
|
@@ -81,6 +81,23 @@ served to users (its pages, its i18n, its shell) is a product surface and
|
|
|
81
81
|
belongs in the tree. The line is not "markdown vs code" — it is *served to
|
|
82
82
|
users* vs *read by us*.
|
|
83
83
|
|
|
84
|
+
## What not to record — the map is structure, not contents
|
|
85
|
+
|
|
86
|
+
Everything above is about *which* things become nodes. This is about what goes
|
|
87
|
+
into a node once it exists. A label, a description, a metadata value or a wiki
|
|
88
|
+
page never holds:
|
|
89
|
+
|
|
90
|
+
- **secrets** — API keys, tokens, passwords, environment values
|
|
91
|
+
- **customer or personal data** — names, emails, ids copied from production
|
|
92
|
+
- **verbatim source code** — point at the file with `implements`; do not paste
|
|
93
|
+
the function
|
|
94
|
+
- **internal hostnames, IPs, URLs** beyond what the structure needs to say
|
|
95
|
+
|
|
96
|
+
`implements` is a list of paths, not contents. A description says what a thing
|
|
97
|
+
is for, not how its code reads. If the honest `implements` of a node would be a
|
|
98
|
+
`.env` or a credentials file, name the node and leave `implements` empty. The
|
|
99
|
+
full statement of what Umtri receives and keeps is `umtri://about/data`.
|
|
100
|
+
|
|
84
101
|
## Trunk and limb rules
|
|
85
102
|
|
|
86
103
|
- `trunk` = a big domain (e.g. `www`, `server`, `db`). Pick stable,
|
package/core/resources.js
CHANGED
|
@@ -78,6 +78,13 @@ const RESOURCES = [
|
|
|
78
78
|
title: 'Nodes represent information structures',
|
|
79
79
|
description: 'Modelling principle: nodes are user-visible units, not code files. Metadata key conventions.',
|
|
80
80
|
},
|
|
81
|
+
{
|
|
82
|
+
name: 'data',
|
|
83
|
+
uri: 'umtri://about/data',
|
|
84
|
+
file: 'data.md',
|
|
85
|
+
title: 'What Umtri receives — and what it never sees',
|
|
86
|
+
description: 'Umtri holds only what tool calls send (labels, descriptions, file paths, connections, bug and wiki text) and never reads files or git. Lists what must not be recorded (secrets, env values, personal data, verbatim code), where data is stored, who can see it, and how it is exported or deleted. Read when the human asks whether it is safe to map their project, or before drawing a tree for a new ground.',
|
|
87
|
+
},
|
|
81
88
|
{
|
|
82
89
|
name: 'vision',
|
|
83
90
|
uri: 'umtri://about/vision',
|
package/core/tools.js
CHANGED
|
@@ -534,6 +534,23 @@ export function registerTools(server, { api }) {
|
|
|
534
534
|
},
|
|
535
535
|
);
|
|
536
536
|
|
|
537
|
+
server.registerTool(
|
|
538
|
+
'export_ground',
|
|
539
|
+
{
|
|
540
|
+
title: 'Export a whole ground as JSON',
|
|
541
|
+
description: '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).',
|
|
542
|
+
inputSchema: z.object({
|
|
543
|
+
slug: z.string().min(1).describe('Ground slug.'),
|
|
544
|
+
}),
|
|
545
|
+
},
|
|
546
|
+
async ({ slug }) => {
|
|
547
|
+
try {
|
|
548
|
+
const data = await api.get(`/api/projects/${encodeURIComponent(slug)}/export`);
|
|
549
|
+
return jsonResult(data);
|
|
550
|
+
} catch (e) { return errorResult(e); }
|
|
551
|
+
},
|
|
552
|
+
);
|
|
553
|
+
|
|
537
554
|
server.registerTool(
|
|
538
555
|
'list_events',
|
|
539
556
|
{
|
package/package.json
CHANGED