iit-mcp-hudu 0.4.0 → 0.5.0
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/CHANGELOG.md +10 -0
- package/README.md +5 -5
- package/dist/tools/article-loss.js +3 -1
- package/dist/tools/dispatch.js +1 -1
- package/dist/tools/lists.js +21 -6
- package/dist/tools.js +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## 0.5.0
|
|
6
|
+
|
|
7
|
+
**Upgrading from 0.4.0:** clients now see `markdown_lossy` / `markdown_lossy_codes` on `articles.getSection`, with a section-specific note (the signal describes the whole article, so the loss may be in another section). Whole-article read text is unchanged. `hudu_list` compact rows are unchanged. node-hudu 0.17.0 -> 0.18.0, plan hash re-stamped to `9d110798...`, operation set unchanged (236).
|
|
8
|
+
|
|
9
|
+
- `articles.getSection` lifts the SDK's whole-body `content_loss` into `markdown_lossy` / `markdown_lossy_codes` like the other article reads; `content_loss` is never passed through. This supersedes the 0.4.0 note that section reads carry no signal (#42, #39).
|
|
10
|
+
- `COMPACT_FIELDS` is built from the SDK's `SUMMARY_FIELDS` plus explicit extras (`created_at`, `url`), with a test that derives from the SDK and a literal pin of the final lists, so SDK drift fails CI. Served rows are byte-identical (#42, #39).
|
|
11
|
+
- Dependency: node-hudu 0.17.0 -> 0.18.0 (exact pin). Plan hash re-stamped to `9d110798...`; operation set unchanged (236).
|
|
12
|
+
|
|
3
13
|
## 0.4.0
|
|
4
14
|
|
|
5
15
|
**Upgrading from 0.3.0:** `hudu_list` now returns compact summary rows by default. Callers that read custom `fields`, article `content` or layout `fields` from list rows must pass `expand: true`. Everything else is additive or a fix.
|
package/README.md
CHANGED
|
@@ -31,7 +31,7 @@ four old names. Rows are compact summaries by default (id, name, key scalar fiel
|
|
|
31
31
|
25-row assets page under 20,000 characters instead of ~88,000; pass `expand: true` for the full
|
|
32
32
|
records (`hudu_read` `articles.list` rows are always full). Article rows carry no body unless expanded. Paging is unchanged (`asset_layouts` still takes no `page_size`).
|
|
33
33
|
|
|
34
|
-
These tools run on node-hudu 0.
|
|
34
|
+
These tools run on node-hudu 0.18.0; the `SDK behaviour (0.12.0)` section below covers the behaviours that shape them: redirect refusal, the closed input contract, the error envelope, and the client opt-ins. Numeric ids must be positive integers on every tool; anything else is refused before a request is made.
|
|
35
35
|
|
|
36
36
|
`hudu_fetch_many` (node-hudu 0.12.0) fetches up to 20 single records across mixed resources in
|
|
37
37
|
one call: each item is exactly `{ resource, id, fields? }` — one of the 22 bare-id resources, a
|
|
@@ -281,10 +281,10 @@ those operations take no format. Rules a caller needs:
|
|
|
281
281
|
(for example a `<video>`); send HTML to keep it. The SDK's loss guard runs on every write.
|
|
282
282
|
- Prefer Markdown (or editor-native HTML): Hudu reshapes API-written HTML on the next UI save (h5/h6 flattened, `small`/`abbr`/`q`/`section`/`aside` unwrapped, `thead` removed, an unknown callout type becomes info).
|
|
283
283
|
- `articles.getSection` / `articles.patchSection` read or edit one section as Markdown, with dry-run.
|
|
284
|
-
`articles.getSection` carries
|
|
285
|
-
|
|
284
|
+
`articles.getSection` carries the same `markdown_lossy` / `markdown_lossy_codes` signal as `articles.get`;
|
|
285
|
+
it describes the whole article, so the loss may be in another section.
|
|
286
286
|
- A Markdown read can be incomplete: anything the dialect cannot express is dropped or reduced
|
|
287
|
-
(`<video>` and `<script>` are dropped entirely). `hudu_read` (`articles.get` / `getContext` / `resolve`) and
|
|
287
|
+
(`<video>` and `<script>` are dropped entirely). `hudu_read` (`articles.get` / `getContext` / `getSection` / `resolve`) and
|
|
288
288
|
`hudu_get_article_context` then set `markdown_lossy: true` (with `markdown_lossy_codes`, the SDK's
|
|
289
289
|
`diffArticleRoundTrip` content-loss codes) and add one sentence to the result text; fetch the stored
|
|
290
290
|
HTML with `hudu_fetch_many` (`{items:[{resource:"articles", id}]}`) to see the full body. The read is one
|
|
@@ -371,7 +371,7 @@ pnpm run dev
|
|
|
371
371
|
|
|
372
372
|
CI (`.github/workflows/ci.yml`) runs `typecheck`, `lint` and `test` on every push and pull request.
|
|
373
373
|
|
|
374
|
-
`node-hudu` is pinned to `0.
|
|
374
|
+
`node-hudu` is pinned to `0.18.0`. The catalog hash test detects metadata drift; upgrades require
|
|
375
375
|
review of the client authority, operation enums and redaction regressions. Docker uses `pnpm install --frozen-lockfile`.
|
|
376
376
|
|
|
377
377
|
## Deployment
|
|
@@ -14,6 +14,8 @@ const RECORD_PATHS = {
|
|
|
14
14
|
// resolve answers the record itself; the `{ value }` envelope is the helper form of the same read.
|
|
15
15
|
'articles.resolve': [[], ['value']],
|
|
16
16
|
'articles.getContext': [['article']],
|
|
17
|
+
// The SDK reports getSection loss for the WHOLE body (the loss may sit in another section).
|
|
18
|
+
'articles.getSection': [[]],
|
|
17
19
|
};
|
|
18
20
|
const isObject = (v) => v !== null && typeof v === 'object' && !Array.isArray(v);
|
|
19
21
|
const take = (node, path, codes) => {
|
|
@@ -43,4 +45,4 @@ export function takeContentLoss(operation, result) {
|
|
|
43
45
|
return { result: stripped, codes: [...codes].sort() };
|
|
44
46
|
}
|
|
45
47
|
/** The one short sentence appended to the result text when a read lost content. */
|
|
46
|
-
export const lossyNote = (codes) => ` markdown_lossy: true (${codes.join(', ')}): the Markdown body is incomplete; fetch the stored HTML with hudu_fetch_many {items:[{resource:"articles", id}]} to see all of it.`;
|
|
48
|
+
export const lossyNote = (codes, operation) => ` markdown_lossy: true (${codes.join(', ')}): ${operation === 'articles.getSection' ? 'the Markdown read of this article is incomplete (the loss may be in another section)' : 'the Markdown body is incomplete'}; fetch the stored HTML with hudu_fetch_many {items:[{resource:"articles", id}]} to see all of it.`;
|
package/dist/tools/dispatch.js
CHANGED
|
@@ -120,7 +120,7 @@ export function registerDispatchTools(server, ctx) {
|
|
|
120
120
|
}
|
|
121
121
|
const simulated = result !== null && typeof result === 'object' && result.simulated === true;
|
|
122
122
|
// A Markdown article read that lost content says so; a lossless read is byte-identical to before.
|
|
123
|
-
return ok((simulated ? `Dry run: nothing was written (${operation}).` : `${operation} completed.`) + (lossy.length ? lossyNote(lossy) : ''), {
|
|
123
|
+
return ok((simulated ? `Dry run: nothing was written (${operation}).` : `${operation} completed.`) + (lossy.length ? lossyNote(lossy, operation) : ''), {
|
|
124
124
|
simulated,
|
|
125
125
|
operation,
|
|
126
126
|
result: result ?? null,
|
package/dist/tools/lists.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as z from 'zod/v4';
|
|
2
|
+
import { SUMMARY_FIELDS } from 'node-hudu';
|
|
2
3
|
import { getCapability } from 'node-hudu/capabilities';
|
|
3
4
|
import { configError } from 'node-hudu/mcp';
|
|
4
5
|
import { assertSecretReadPermitted, assertWritePermitted } from '../policy.js';
|
|
@@ -96,14 +97,28 @@ function assertNonSearchableListReadPermitted(operation, ctx) {
|
|
|
96
97
|
assertSecretReadPermitted(operation, config, log);
|
|
97
98
|
}
|
|
98
99
|
/**
|
|
99
|
-
*
|
|
100
|
-
*
|
|
100
|
+
* Extras beyond the SDK's `SUMMARY_FIELDS` (the keys of the node-hudu `*Summary` shapes). Timestamps go last
|
|
101
|
+
* in the served row, so `updated_at` (an SDK key where present) is moved after these extras.
|
|
102
|
+
*/
|
|
103
|
+
const COMPACT_EXTRAS = {
|
|
104
|
+
companies: ['created_at'],
|
|
105
|
+
articles: ['url', 'created_at'],
|
|
106
|
+
assets: ['created_at'],
|
|
107
|
+
asset_layouts: ['url', 'created_at', 'updated_at'],
|
|
108
|
+
};
|
|
109
|
+
const compactFields = (r) => {
|
|
110
|
+
const base = SUMMARY_FIELDS[r];
|
|
111
|
+
return [...base.filter((k) => k !== 'updated_at'), ...COMPACT_EXTRAS[r], ...(base.includes('updated_at') ? ['updated_at'] : [])];
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Compact row fields per resource: `SUMMARY_FIELDS` plus `COMPACT_EXTRAS`. `test/tools/lists-compact.test.ts`
|
|
115
|
+
* derives them from the SDK and also pins the final lists literally. `hudu_list` projects each row onto these unless `expand: true`.
|
|
101
116
|
*/
|
|
102
117
|
export const COMPACT_FIELDS = {
|
|
103
|
-
companies:
|
|
104
|
-
articles:
|
|
105
|
-
assets:
|
|
106
|
-
asset_layouts:
|
|
118
|
+
companies: compactFields('companies'),
|
|
119
|
+
articles: compactFields('articles'),
|
|
120
|
+
assets: compactFields('assets'),
|
|
121
|
+
asset_layouts: compactFields('asset_layouts'),
|
|
107
122
|
};
|
|
108
123
|
/** Project rows onto the compact fields; a field the row lacks is omitted, not nulled. */
|
|
109
124
|
export function compactRows(resource, rows) {
|
package/dist/tools.js
CHANGED
|
@@ -30,4 +30,4 @@ export { MAX_SCOPED_CLIENTS, ScopedClientCache, createMcpServerFactory } from '.
|
|
|
30
30
|
* it against the installed `CATALOG_PLAN_HASH`, so the upgrade fails CI instead of quietly shipping
|
|
31
31
|
* a tool surface that no longer describes the SDK behind it.
|
|
32
32
|
*/
|
|
33
|
-
export const BUILT_AGAINST_PLAN_HASH = '
|
|
33
|
+
export const BUILT_AGAINST_PLAN_HASH = '9d11079847a9e2a8d73f4a075a4004b49f59624be5ffc8253636fc41cf677702';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iit-mcp-hudu",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "MCP server for Hudu IT documentation, built on the node-hudu SDK",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Max Soukhomlinov",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@modelcontextprotocol/server": "^2.3.1",
|
|
46
|
-
"node-hudu": "0.
|
|
46
|
+
"node-hudu": "0.18.0",
|
|
47
47
|
"zod": "^4.6.7"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|