@oneentry/mcp-platform-server 0.1.0 → 0.1.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.
Files changed (71) hide show
  1. package/README.md +113 -71
  2. package/data/permissions.json +411 -0
  3. package/dist/api/build-catalog.d.ts +24 -0
  4. package/dist/api/build-catalog.d.ts.map +1 -0
  5. package/dist/api/build-catalog.js +257 -0
  6. package/dist/api/build-catalog.js.map +1 -0
  7. package/dist/api/catalog.d.ts +22 -3
  8. package/dist/api/catalog.d.ts.map +1 -1
  9. package/dist/api/catalog.js +69 -4
  10. package/dist/api/catalog.js.map +1 -1
  11. package/dist/api/normalize-schema.d.ts +14 -0
  12. package/dist/api/normalize-schema.d.ts.map +1 -0
  13. package/dist/api/normalize-schema.js +151 -0
  14. package/dist/api/normalize-schema.js.map +1 -0
  15. package/dist/api/swagger-source.d.ts +22 -0
  16. package/dist/api/swagger-source.d.ts.map +1 -0
  17. package/dist/api/swagger-source.js +76 -0
  18. package/dist/api/swagger-source.js.map +1 -0
  19. package/dist/api/types.d.ts +1 -1
  20. package/dist/api/types.d.ts.map +1 -1
  21. package/dist/bin/cli.js +11 -3
  22. package/dist/bin/cli.js.map +1 -1
  23. package/dist/config/config.d.ts +84 -10
  24. package/dist/config/config.d.ts.map +1 -1
  25. package/dist/config/config.js +69 -6
  26. package/dist/config/config.js.map +1 -1
  27. package/dist/index.d.ts +9 -2
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +5 -1
  30. package/dist/index.js.map +1 -1
  31. package/dist/knowledge/github.d.ts +46 -0
  32. package/dist/knowledge/github.d.ts.map +1 -0
  33. package/dist/knowledge/github.js +214 -0
  34. package/dist/knowledge/github.js.map +1 -0
  35. package/dist/knowledge/loader.d.ts +46 -19
  36. package/dist/knowledge/loader.d.ts.map +1 -1
  37. package/dist/knowledge/loader.js +92 -105
  38. package/dist/knowledge/loader.js.map +1 -1
  39. package/dist/knowledge/search.d.ts +11 -0
  40. package/dist/knowledge/search.d.ts.map +1 -1
  41. package/dist/knowledge/search.js +36 -3
  42. package/dist/knowledge/search.js.map +1 -1
  43. package/dist/knowledge/tar.d.ts +22 -0
  44. package/dist/knowledge/tar.d.ts.map +1 -0
  45. package/dist/knowledge/tar.js +120 -0
  46. package/dist/knowledge/tar.js.map +1 -0
  47. package/dist/knowledge/types.d.ts +31 -10
  48. package/dist/knowledge/types.d.ts.map +1 -1
  49. package/dist/server.d.ts +3 -2
  50. package/dist/server.d.ts.map +1 -1
  51. package/dist/server.js +13 -6
  52. package/dist/server.js.map +1 -1
  53. package/dist/session.d.ts +6 -0
  54. package/dist/session.d.ts.map +1 -1
  55. package/dist/session.js +8 -0
  56. package/dist/session.js.map +1 -1
  57. package/dist/tools/guide.d.ts.map +1 -1
  58. package/dist/tools/guide.js +9 -2
  59. package/dist/tools/guide.js.map +1 -1
  60. package/dist/tools/whoami.d.ts.map +1 -1
  61. package/dist/tools/whoami.js +4 -0
  62. package/dist/tools/whoami.js.map +1 -1
  63. package/dist/transports/http.d.ts.map +1 -1
  64. package/dist/transports/http.js +26 -1
  65. package/dist/transports/http.js.map +1 -1
  66. package/dist/transports/stdio.js +1 -1
  67. package/dist/transports/stdio.js.map +1 -1
  68. package/knowledge/operating-rules.md +176 -0
  69. package/package.json +4 -4
  70. package/data/catalog.json +0 -1
  71. package/data/knowledge.json +0 -1
@@ -0,0 +1,176 @@
1
+ # Operating rules — OneEntry CMS Admin API
2
+
3
+ Read this before your first write. Every rule below is one that has actually broken payloads.
4
+ Each links to the bundled reference doc that explains it in full — open it with
5
+ `cms_docs_read`.
6
+
7
+ ## 0. The loop you should follow
8
+
9
+ 1. `cms_guide` — once, at the start.
10
+ 2. `cms_docs_search` — find the rules for the entity you are about to touch. **Before** writing,
11
+ not after a 400.
12
+ 3. `cms_api_search` → `cms_api_describe` — get the real operation and its payload shape.
13
+ 4. `cms_api_call` — with `dryRun: true` first for anything mutating.
14
+
15
+ Do not guess a path or a body key. The catalog is authoritative for paths; the docs are
16
+ authoritative for semantics.
17
+
18
+ ## 1. The OpenAPI schema is only half-trustworthy — read the `example`
19
+
20
+ The CMS generates its swagger from NestJS decorators, and 311 `type` values in it are TypeScript
21
+ expressions rather than JSON Schema types: `Record<string, any>`, `CommonLocalizeInfos`,
22
+ `AttributesSets`, `number | string`, `image`, `date`. `cms_api_describe` normalizes what it can and
23
+ marks the rest `"x-loose": true`.
24
+
25
+ **When a field is `x-loose`, the `example` is the contract.** Copy its shape. Client-side
26
+ validation is deliberately advisory — the server is the real validator, so a call is never blocked
27
+ just because a loose field could not be checked.
28
+
29
+ ## 2. Content lives under a locale key: `localizeInfos`
30
+
31
+ Titles and content are never plain strings. They are objects keyed by locale code:
32
+
33
+ ```json
34
+ { "localizeInfos": { "en_US": { "title": "Catalog", "plainContent": "…", "htmlContent": "<b>…</b>", "menuTitle": "Catalog" } } }
35
+ ```
36
+
37
+ `localizeInfos` is **required** on product creation and effectively required on pages. Get the
38
+ active locale codes from the Locales operations (`cms_api_search "locales"`) — never hardcode
39
+ `en_US`. Writing a locale that is not configured on the stand silently produces content nobody
40
+ can see.
41
+
42
+ → `back/docs/postgres-db-with-attribute-index`, `front/docs/isPrice-attribute`
43
+
44
+ ## 3. Product/page payloads are attribute-set-driven — and `attributesSets` is locale-keyed
45
+
46
+ `CreateProductDto` requires all three of `localizeInfos`, `attributeSetId` and `attributesSets`.
47
+ `attributesSets` is `Record<locale, Record<key, value>>` — **two levels**, the outer one a locale
48
+ code. The inner key encodes the attribute type and id: `<type>_id<attributeId>`.
49
+
50
+ ```json
51
+ {
52
+ "attributeSetId": 44,
53
+ "attributesSets": {
54
+ "en_US": { "string_id1": "Haircut", "float_id3": 35, "groupOfImages_id7": [] }
55
+ }
56
+ }
57
+ ```
58
+
59
+ **The swagger `example` on this field is wrong**: it shows the flat map `{ "id7": 7,
60
+ "string_id18": "" }`. Posting that flat shape returns **201 and stores `attributesSets: {}`** —
61
+ no warning, no 400. The product then exists with a title and is empty in every field. This is the
62
+ one place where the rule "the example is the contract" (§1) does not hold; the locale-wrapped
63
+ shape above is confirmed against stored products.
64
+
65
+ So you cannot construct a product payload without first reading the attribute set: fetch it, see
66
+ which attributes it declares, then build the map under the active locale code. Skipping this is
67
+ the single most common cause of a product that saves but shows up empty.
68
+
69
+ After creating a product, **read it back by id** and check that `attributesSets` is not `{}`.
70
+ That single read is the only defence against the silent drop.
71
+
72
+ → `back/docs/postgres-db-with-attribute-index`, `back/docs/attribute-indexing`
73
+
74
+ ## 4. `position` is a lexorank string on some endpoints and a number on others
75
+
76
+ - Content API positions — **numeric** display index.
77
+ - Admin API *parent-scoped* positions (block on a page, page in a menu, child in a tree) —
78
+ **lexorank strings**.
79
+ - Admin API *flat lists* (e.g. `GET /api/admin/blocks`) — **numeric** display index, intentionally.
80
+
81
+ Never send a number where a lexorank is expected, and never sort by a lexorank numerically.
82
+ Reordering is done through the dedicated `…/position` operations, not by patching the field.
83
+
84
+ → `back/tests/e2e-conventions` §2, `back/docs/filters`
85
+
86
+ ## 5. Writes are eventually consistent — a read straight after a write can lie
87
+
88
+ Attribute values reach `index_attribute_data` through the Bull `index-data` queue; Elasticsearch
89
+ (`products_v1`, `pages_v1`, `blocks_v1`) and the materialized views (`pages_view`, `blocks_view`)
90
+ lag behind the base tables. A freshly created entity may be absent from a list or search response
91
+ for seconds.
92
+
93
+ If a read does not show your write: re-read the entity by id (base tables, always current) before
94
+ concluding the write failed. Never "fix" it by writing again — you will create duplicates.
95
+
96
+ → `back/docs/attribute-indexing`, `back/docs/elastic`, `back/tests/e2e-conventions` §3
97
+
98
+ ## 6. `marker` is the stable identifier; `id` is not portable
99
+
100
+ Blocks, modules, forms and general types are addressed by `marker` across stands. An `id` from a
101
+ dev stand is meaningless on production. When you have a choice of operation, prefer the
102
+ marker-based one.
103
+
104
+ ## 7. Never touch these without a human saying so in this conversation
105
+
106
+ `immutable-settings`, `admins`, `backups`, `modules/{id}/deploy|suspend|resume`,
107
+ `payments/webhook/**`, `auth/logout/all-users`, `settings-general`. They are permanently
108
+ confirm-gated regardless of the `--allow` level. If a prompt implies one of them, say what you
109
+ would do and stop.
110
+
111
+ ## 8. Permissions are per-action and pre-checked
112
+
113
+ Every admin carries an `AdminPermissionsEnum` map (`settings.attributes.create`,
114
+ `menu.items.changePositions`, …). 243 operations declare a required permission, and `cms_api_call`
115
+ refuses locally when the authenticated admin lacks it — so a permission error means "ask for the
116
+ grant", not "retry".
117
+
118
+ Note the Admin API rejects accounts flagged `isDeveloper`: those belong to the separate Developer
119
+ API, which this server does not expose.
120
+
121
+ → `back/docs/user-permissions`
122
+
123
+ ## 9. If you changed backend code, a test suite may be mandatory
124
+
125
+ `back/CLAUDE` lists modules whose e2e suite **must** be run after a change:
126
+ attributes-sets, admins, menus, templates, template-previews, import, orders. Never edit a test to
127
+ make it green.
128
+
129
+ → `back/CLAUDE`, `back/tests/e2e-conventions`
130
+
131
+ ## 10. Responses are truncated on purpose
132
+
133
+ A list response is capped and the overflow replaced with `_truncated: { shown, total, hint }`.
134
+ That is not an API limit — narrow the query with the operation's own `limit`/`offset`/filter
135
+ parameters instead of asking for everything.
136
+
137
+ ## 11. Known dnk-back defects — do not debug them, work around them
138
+
139
+ Every item here was hit for real against a stock stand. They are backend defects, not payload
140
+ mistakes: retrying with a "better" body will not help.
141
+
142
+ - **`POST /forms` wants the payload nested under `newForm`.** The controller binds
143
+ `@Body('newForm')`, but swagger documents `CreateFormDto` flat — so the catalog and
144
+ `cms_api_describe` show the wrong shape. A flat body gives
145
+ `500 — null value in column "processing_type"`. Send
146
+ `{ "newForm": { "identifier": "…", "processingType": "db", "localizeInfos": { … } } }`.
147
+ - **`PUT /products/{id}` needs `blocks`.** Omitting it gives
148
+ `500 — updateProductDto.blocks is not iterable`; send `blocks: []` when you have nothing to set.
149
+ Conversely `forms` is accepted by the DTO and then explodes in TypeORM
150
+ (`No entity column "forms" was found`) — never send it on update.
151
+ - **`GET /locales` answers `500 — column "nan" does not exist`.** Use
152
+ `AdminLocalesController_findAllActive` (`GET /locales/active/all`) to read locale codes.
153
+ - **There is no `GET /products` list.** The list operation is `POST /products/all`
154
+ (`AdminProductsController_findAll`); `GET /products/quick/search?name=…` is the cheap lookup but
155
+ returns only `{ id, title, pageId }`. Fetch the full object with `GET /products/{id}`.
156
+ - **`orders.export`, `payments.export`, `users.export`** are required by controllers but absent
157
+ from `AdminPermissionsEnum`, so those operations always answer 403. `cms_whoami` reports this as
158
+ a catalog warning; report it to the human rather than retrying.
159
+
160
+ ## 12. Type ids that no document states
161
+
162
+ `typeId` on an attribute set is **not** the general type of a page — it is the separate audience
163
+ enum `AttributesSetType` (`forAdmins`, `forBlocks`, `forOrders`, `forPages`, `forProducts`,
164
+ `forUsers`, `forUserGroups`, `forDiscounts`; note the key `forBlock` maps to the value `forBlocks`).
165
+ It is stored as a row id in `attribute_set_types`, that table can hold values beyond the enum, and
166
+ there is no lookup operation for it — so the numeric ids are **stand data, not constants**.
167
+
168
+ Observed on one stock stand: `2 = forBlocks`, `4 = forPages`, `5 = forProducts`, `6 = forUsers`,
169
+ `7 = forForms`, `9 = forEvents`, `10 = system`; page `generalTypeId` `4 = catalog_page`,
170
+ `11 = form`, `17 = common_page`, `18 = common_block`, `23 = discount`. Treat these as a hint, not
171
+ a contract. **Verify before writing**: read `GET /general-types` for page types, and read an
172
+ existing attribute set of the kind you want to see its `typeId`. An id from another stand is not
173
+ portable (§6).
174
+
175
+ Discount configuration values: `discountType ∈ {NONE, PERCENTAGE, FIXED_AMOUNT, FIXED_PRICE}`,
176
+ `applicability ∈ {TO_PRODUCT, TO_ORDER}`, `type ∈ {DISCOUNT, BONUS, PERSONAL_DISCOUNT}`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oneentry/mcp-platform-server",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "MCP server that lets an AI agent operate the OneEntry Admin API, grounded in the project's own rules",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -28,16 +28,16 @@
28
28
  "files": [
29
29
  "dist",
30
30
  "data",
31
+ "knowledge",
31
32
  "README.md"
32
33
  ],
33
34
  "scripts": {
34
35
  "build": "tsc -p tsconfig.build.json",
35
36
  "prepublishOnly": "npm run build",
36
- "prestart": "npm run check:drift",
37
37
  "start": "node dist/bin/cli.js",
38
38
  "dev": "tsx src/bin/cli.ts",
39
- "sync:from-cms": "tsx build/sync.ts",
40
- "check:drift": "tsx build/sync.ts --check",
39
+ "sync:permissions": "tsx build/sync-permissions.ts",
40
+ "publish:knowledge": "tsx build/publish-knowledge.ts",
41
41
  "lint": "eslint \"{src,build,__tests__}/**/*.ts\"",
42
42
  "test": "vitest run",
43
43
  "test:watch": "vitest",