sbuilder-mcp 0.34.0 → 0.36.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 CHANGED
@@ -6,6 +6,23 @@ All notable changes to this project are documented in this file.
6
6
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
7
7
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
8
8
 
9
+ ## [0.36.0] - 2026-09-11
10
+
11
+ ### Added
12
+ - The `/apps` call sheet now explains marketplace app installation as two separate questions: suggesting one is always possible on any credential (`GET /api/sites/{siteId}/apps` plus `GET /oauth/authorize-info` for the app's publisher, privacy policy, scopes, and price), while installing one requires a session (`POST /oauth/authorize`) because an agent key is not an access token and the platform refuses it by design. It also documents that a paid app is refused without an explicit `acceptedPrice`, so this server can never commit a merchant to a subscription on its own.
13
+ - The catalog now carries the two `/oauth` operations behind that flow, `GET /oauth/authorize-info` and `POST /oauth/authorize`, including the request shape for the latter.
14
+
15
+ ### Changed
16
+ - The `builtin-apps` call sheet no longer tells the caller that a marketplace app "cannot be installed from here at all"; that line was stricter than the platform actually enforces.
17
+
18
+ ## [0.35.0] - 2026-09-11
19
+
20
+ ### Added
21
+ - The catalog now carries five page-history operations that reached the platform's own browser and swagger.json but had never carried an `@Router` annotation, so they were invisible to this server: `GET`/`POST .../pages/{pageId}/versions` (list and label a snapshot of the current draft), `POST .../pages/{pageId}/versions/{versionId}/restore`, `GET .../pages/{pageId}/history` (the autosave checkpoints written on every draft save), and `POST .../pages/{pageId}/history/{historyId}/restore`.
22
+
23
+ ### Changed
24
+ - sb_undo's description now points to this page history and restore surface as the better way to recover a page, since it survives process exit while sb_undo's own undo stack is in-process, capped, and gone on exit; it no longer claims the platform has no page history at all.
25
+
9
26
  ## [0.34.0] - 2026-09-11
10
27
 
11
28
  ### Added
package/CHANGELOG.vi.md CHANGED
@@ -6,6 +6,23 @@ Mọi thay đổi đáng chú ý của dự án được ghi lại trong file n
6
6
  Định dạng dựa trên [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
7
7
  và dự án tuân theo [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
8
8
 
9
+ ## [0.36.0] - 2026-09-11
10
+
11
+ ### Added
12
+ - Call sheet của `/apps` giờ giải thích việc cài một app từ marketplace như hai câu hỏi tách biệt: gợi ý một app luôn khả thi với bất kỳ credential nào (`GET /api/sites/{siteId}/apps` cùng `GET /oauth/authorize-info` để lấy nhà phát hành, chính sách riêng tư, scope và giá của app), còn cài đặt thì cần một session (`POST /oauth/authorize`) vì agent key không phải access token và nền tảng cố tình từ chối nó. Call sheet cũng ghi rõ một app trả phí sẽ bị từ chối nếu thiếu `acceptedPrice` tường minh, nên server này không bao giờ tự ý khiến merchant phải trả tiền cho một gói đăng ký.
13
+ - Catalog giờ mang theo hai operation `/oauth` phía sau luồng đó, `GET /oauth/authorize-info` và `POST /oauth/authorize`, kèm request shape cho operation thứ hai.
14
+
15
+ ### Changed
16
+ - Call sheet của `builtin-apps` không còn nói với caller rằng một app marketplace "không thể cài từ đây được"; câu đó khắt khe hơn mức nền tảng thực sự yêu cầu.
17
+
18
+ ## [0.35.0] - 2026-09-11
19
+
20
+ ### Added
21
+ - Catalog giờ mang theo năm operation lịch sử trang từng có mặt trên trình duyệt của nền tảng và trong swagger.json nhưng chưa từng được gắn annotation `@Router`, nên trước đây server này không thể thấy chúng: `GET`/`POST .../pages/{pageId}/versions` (liệt kê và gắn nhãn một bản chụp của bản nháp hiện tại), `POST .../pages/{pageId}/versions/{versionId}/restore`, `GET .../pages/{pageId}/history` (các checkpoint autosave được ghi ở mỗi lần lưu bản nháp), và `POST .../pages/{pageId}/history/{historyId}/restore`.
22
+
23
+ ### Changed
24
+ - Mô tả của sb_undo giờ trỏ tới bề mặt lịch sử và khôi phục trang này như cách tốt hơn để phục hồi một trang, vì nó tồn tại qua cả khi tiến trình thoát, trong khi ngăn xếp undo của chính sb_undo chỉ nằm trong tiến trình, có giới hạn, và mất đi khi thoát; nó không còn khẳng định nền tảng hoàn toàn không có lịch sử trang.
25
+
9
26
  ## [0.34.0] - 2026-09-11
10
27
 
11
28
  ### Added
@@ -1,8 +1,8 @@
1
1
  export const SWAGGER_SOURCE = {
2
- "operations": 501,
2
+ "operations": 508,
3
3
  "definitions": 105,
4
- "bodyCarrying": 179,
5
- "bodyUndescribed": 64,
4
+ "bodyCarrying": 183,
5
+ "bodyUndescribed": 68,
6
6
  "generatedFrom": "server/docs/swagger.json"
7
7
  };
8
8
  export const API_OPERATIONS = [
@@ -9532,6 +9532,113 @@ export const API_OPERATIONS = [
9532
9532
  "bodyRef": null,
9533
9533
  "credential": "siteScoped"
9534
9534
  },
9535
+ {
9536
+ "id": "get:/api/sites/{siteId}/pages/{pageId}/history",
9537
+ "method": "GET",
9538
+ "path": "/api/sites/{siteId}/pages/{pageId}/history",
9539
+ "tags": [
9540
+ "pages",
9541
+ "pages"
9542
+ ],
9543
+ "summary": "Restore a page's draft from an autosave checkpoint",
9544
+ "params": [
9545
+ {
9546
+ "name": "siteId",
9547
+ "in": "path",
9548
+ "required": true,
9549
+ "type": "string",
9550
+ "description": "Site ID"
9551
+ },
9552
+ {
9553
+ "name": "pageId",
9554
+ "in": "path",
9555
+ "required": true,
9556
+ "type": "string",
9557
+ "description": "Page ID"
9558
+ },
9559
+ {
9560
+ "name": "limit",
9561
+ "in": "query",
9562
+ "required": false,
9563
+ "type": "integer",
9564
+ "description": "1-… , default 50"
9565
+ },
9566
+ {
9567
+ "name": "siteId",
9568
+ "in": "path",
9569
+ "required": true,
9570
+ "type": "string",
9571
+ "description": "Site ID"
9572
+ },
9573
+ {
9574
+ "name": "pageId",
9575
+ "in": "path",
9576
+ "required": true,
9577
+ "type": "string",
9578
+ "description": "Page ID"
9579
+ }
9580
+ ],
9581
+ "bodyDescribed": false,
9582
+ "bodyRef": null,
9583
+ "credential": "siteScoped"
9584
+ },
9585
+ {
9586
+ "id": "post:/api/sites/{siteId}/pages/{pageId}/history/{historyId}/restore",
9587
+ "method": "POST",
9588
+ "path": "/api/sites/{siteId}/pages/{pageId}/history/{historyId}/restore",
9589
+ "tags": [
9590
+ "pages",
9591
+ "pages"
9592
+ ],
9593
+ "summary": "Restore a page's draft from an autosave checkpoint",
9594
+ "params": [
9595
+ {
9596
+ "name": "siteId",
9597
+ "in": "path",
9598
+ "required": true,
9599
+ "type": "string",
9600
+ "description": "Site ID"
9601
+ },
9602
+ {
9603
+ "name": "pageId",
9604
+ "in": "path",
9605
+ "required": true,
9606
+ "type": "string",
9607
+ "description": "Page ID"
9608
+ },
9609
+ {
9610
+ "name": "limit",
9611
+ "in": "query",
9612
+ "required": false,
9613
+ "type": "integer",
9614
+ "description": "1-… , default 50"
9615
+ },
9616
+ {
9617
+ "name": "siteId",
9618
+ "in": "path",
9619
+ "required": true,
9620
+ "type": "string",
9621
+ "description": "Site ID"
9622
+ },
9623
+ {
9624
+ "name": "pageId",
9625
+ "in": "path",
9626
+ "required": true,
9627
+ "type": "string",
9628
+ "description": "Page ID"
9629
+ },
9630
+ {
9631
+ "name": "historyId",
9632
+ "in": "path",
9633
+ "required": true,
9634
+ "type": "string",
9635
+ "description": "History ID from the list"
9636
+ }
9637
+ ],
9638
+ "bodyDescribed": false,
9639
+ "bodyRef": null,
9640
+ "credential": "siteScoped"
9641
+ },
9535
9642
  {
9536
9643
  "id": "get:/api/sites/{siteId}/pages/{pageId}/preview",
9537
9644
  "method": "GET",
@@ -9616,6 +9723,250 @@ export const API_OPERATIONS = [
9616
9723
  "bodyRef": null,
9617
9724
  "credential": "siteScoped"
9618
9725
  },
9726
+ {
9727
+ "id": "get:/api/sites/{siteId}/pages/{pageId}/versions",
9728
+ "method": "GET",
9729
+ "path": "/api/sites/{siteId}/pages/{pageId}/versions",
9730
+ "tags": [
9731
+ "pages",
9732
+ "pages",
9733
+ "pages"
9734
+ ],
9735
+ "summary": "Restore a page's draft from a version snapshot",
9736
+ "params": [
9737
+ {
9738
+ "name": "siteId",
9739
+ "in": "path",
9740
+ "required": true,
9741
+ "type": "string",
9742
+ "description": "Site ID"
9743
+ },
9744
+ {
9745
+ "name": "pageId",
9746
+ "in": "path",
9747
+ "required": true,
9748
+ "type": "string",
9749
+ "description": "Page ID"
9750
+ },
9751
+ {
9752
+ "name": "limit",
9753
+ "in": "query",
9754
+ "required": false,
9755
+ "type": "integer",
9756
+ "description": "1-… , default 50"
9757
+ },
9758
+ {
9759
+ "name": "offset",
9760
+ "in": "query",
9761
+ "required": false,
9762
+ "type": "integer",
9763
+ "description": "default 0"
9764
+ },
9765
+ {
9766
+ "name": "siteId",
9767
+ "in": "path",
9768
+ "required": true,
9769
+ "type": "string",
9770
+ "description": "Site ID"
9771
+ },
9772
+ {
9773
+ "name": "pageId",
9774
+ "in": "path",
9775
+ "required": true,
9776
+ "type": "string",
9777
+ "description": "Page ID"
9778
+ },
9779
+ {
9780
+ "name": "body",
9781
+ "in": "body",
9782
+ "required": true,
9783
+ "type": "object",
9784
+ "description": "{label, document?}"
9785
+ },
9786
+ {
9787
+ "name": "siteId",
9788
+ "in": "path",
9789
+ "required": true,
9790
+ "type": "string",
9791
+ "description": "Site ID"
9792
+ },
9793
+ {
9794
+ "name": "pageId",
9795
+ "in": "path",
9796
+ "required": true,
9797
+ "type": "string",
9798
+ "description": "Page ID"
9799
+ }
9800
+ ],
9801
+ "bodyDescribed": false,
9802
+ "bodyRef": null,
9803
+ "credential": "siteScoped"
9804
+ },
9805
+ {
9806
+ "id": "post:/api/sites/{siteId}/pages/{pageId}/versions",
9807
+ "method": "POST",
9808
+ "path": "/api/sites/{siteId}/pages/{pageId}/versions",
9809
+ "tags": [
9810
+ "pages",
9811
+ "pages",
9812
+ "pages"
9813
+ ],
9814
+ "summary": "Restore a page's draft from a version snapshot",
9815
+ "params": [
9816
+ {
9817
+ "name": "siteId",
9818
+ "in": "path",
9819
+ "required": true,
9820
+ "type": "string",
9821
+ "description": "Site ID"
9822
+ },
9823
+ {
9824
+ "name": "pageId",
9825
+ "in": "path",
9826
+ "required": true,
9827
+ "type": "string",
9828
+ "description": "Page ID"
9829
+ },
9830
+ {
9831
+ "name": "limit",
9832
+ "in": "query",
9833
+ "required": false,
9834
+ "type": "integer",
9835
+ "description": "1-… , default 50"
9836
+ },
9837
+ {
9838
+ "name": "offset",
9839
+ "in": "query",
9840
+ "required": false,
9841
+ "type": "integer",
9842
+ "description": "default 0"
9843
+ },
9844
+ {
9845
+ "name": "siteId",
9846
+ "in": "path",
9847
+ "required": true,
9848
+ "type": "string",
9849
+ "description": "Site ID"
9850
+ },
9851
+ {
9852
+ "name": "pageId",
9853
+ "in": "path",
9854
+ "required": true,
9855
+ "type": "string",
9856
+ "description": "Page ID"
9857
+ },
9858
+ {
9859
+ "name": "body",
9860
+ "in": "body",
9861
+ "required": true,
9862
+ "type": "object",
9863
+ "description": "{label, document?}"
9864
+ },
9865
+ {
9866
+ "name": "siteId",
9867
+ "in": "path",
9868
+ "required": true,
9869
+ "type": "string",
9870
+ "description": "Site ID"
9871
+ },
9872
+ {
9873
+ "name": "pageId",
9874
+ "in": "path",
9875
+ "required": true,
9876
+ "type": "string",
9877
+ "description": "Page ID"
9878
+ }
9879
+ ],
9880
+ "bodyDescribed": false,
9881
+ "bodyRef": null,
9882
+ "credential": "siteScoped"
9883
+ },
9884
+ {
9885
+ "id": "post:/api/sites/{siteId}/pages/{pageId}/versions/{versionId}/restore",
9886
+ "method": "POST",
9887
+ "path": "/api/sites/{siteId}/pages/{pageId}/versions/{versionId}/restore",
9888
+ "tags": [
9889
+ "pages",
9890
+ "pages",
9891
+ "pages"
9892
+ ],
9893
+ "summary": "Restore a page's draft from a version snapshot",
9894
+ "params": [
9895
+ {
9896
+ "name": "siteId",
9897
+ "in": "path",
9898
+ "required": true,
9899
+ "type": "string",
9900
+ "description": "Site ID"
9901
+ },
9902
+ {
9903
+ "name": "pageId",
9904
+ "in": "path",
9905
+ "required": true,
9906
+ "type": "string",
9907
+ "description": "Page ID"
9908
+ },
9909
+ {
9910
+ "name": "limit",
9911
+ "in": "query",
9912
+ "required": false,
9913
+ "type": "integer",
9914
+ "description": "1-… , default 50"
9915
+ },
9916
+ {
9917
+ "name": "offset",
9918
+ "in": "query",
9919
+ "required": false,
9920
+ "type": "integer",
9921
+ "description": "default 0"
9922
+ },
9923
+ {
9924
+ "name": "siteId",
9925
+ "in": "path",
9926
+ "required": true,
9927
+ "type": "string",
9928
+ "description": "Site ID"
9929
+ },
9930
+ {
9931
+ "name": "pageId",
9932
+ "in": "path",
9933
+ "required": true,
9934
+ "type": "string",
9935
+ "description": "Page ID"
9936
+ },
9937
+ {
9938
+ "name": "body",
9939
+ "in": "body",
9940
+ "required": true,
9941
+ "type": "object",
9942
+ "description": "{label, document?}"
9943
+ },
9944
+ {
9945
+ "name": "siteId",
9946
+ "in": "path",
9947
+ "required": true,
9948
+ "type": "string",
9949
+ "description": "Site ID"
9950
+ },
9951
+ {
9952
+ "name": "pageId",
9953
+ "in": "path",
9954
+ "required": true,
9955
+ "type": "string",
9956
+ "description": "Page ID"
9957
+ },
9958
+ {
9959
+ "name": "versionId",
9960
+ "in": "path",
9961
+ "required": true,
9962
+ "type": "string",
9963
+ "description": "Version ID from the list"
9964
+ }
9965
+ ],
9966
+ "bodyDescribed": false,
9967
+ "bodyRef": null,
9968
+ "credential": "siteScoped"
9969
+ },
9619
9970
  {
9620
9971
  "id": "get:/api/sites/{siteId}/payment-gateways",
9621
9972
  "method": "GET",
@@ -14888,6 +15239,62 @@ export const API_OPERATIONS = [
14888
15239
  "bodyDescribed": false,
14889
15240
  "bodyRef": null,
14890
15241
  "credential": "apiKey"
15242
+ },
15243
+ {
15244
+ "id": "post:/oauth/authorize",
15245
+ "method": "POST",
15246
+ "path": "/oauth/authorize",
15247
+ "tags": [
15248
+ "apps"
15249
+ ],
15250
+ "summary": "Agree to an app's scopes and install it on a site",
15251
+ "params": [
15252
+ {
15253
+ "name": "body",
15254
+ "in": "body",
15255
+ "required": true,
15256
+ "type": "object",
15257
+ "description": "{siteId, clientId, versionId, redirectUri, scopes, state, acceptedPrice?}"
15258
+ }
15259
+ ],
15260
+ "bodyDescribed": false,
15261
+ "bodyRef": null,
15262
+ "credential": "siteScoped"
15263
+ },
15264
+ {
15265
+ "id": "get:/oauth/authorize-info",
15266
+ "method": "GET",
15267
+ "path": "/oauth/authorize-info",
15268
+ "tags": [
15269
+ "apps"
15270
+ ],
15271
+ "summary": "What an app is asking for, before anyone agrees to it",
15272
+ "params": [
15273
+ {
15274
+ "name": "client_id",
15275
+ "in": "query",
15276
+ "required": true,
15277
+ "type": "string",
15278
+ "description": "The app's client id"
15279
+ },
15280
+ {
15281
+ "name": "version_id",
15282
+ "in": "query",
15283
+ "required": false,
15284
+ "type": "string",
15285
+ "description": "A specific version; the current one otherwise"
15286
+ },
15287
+ {
15288
+ "name": "redirect_uri",
15289
+ "in": "query",
15290
+ "required": true,
15291
+ "type": "string",
15292
+ "description": "Must match one the app registered"
15293
+ }
15294
+ ],
15295
+ "bodyDescribed": false,
15296
+ "bodyRef": null,
15297
+ "credential": "siteScoped"
14891
15298
  }
14892
15299
  ];
14893
15300
  export const API_DEFINITIONS = {
@@ -114,9 +114,29 @@ export function describeOperation(op) {
114
114
  'reduces the subtree back to the reference. Configure the block through its own ' +
115
115
  'props/slots, never by editing what it rendered.',
116
116
  installing: 'A BUILT-IN app installs with POST /api/sites/{siteId}/builtin-apps/{key} and that key ' +
117
- "parameter's description names every installable one. A MARKETPLACE app cannot be " +
118
- 'installed from here at all: it goes through an OAuth consent screen a person has to ' +
119
- 'approve, so ask the merchant to install it and then read /apps/blocks again.',
117
+ "parameter's description names every installable one.",
118
+ // A MARKETPLACE APP IS A PERMISSION GRANT, and who may make it is the
119
+ // platform's line rather than this client's caution. `consent`
120
+ // authenticates as a USER — the platform parses an ACCESS TOKEN, so a
121
+ // session reaches it and a `wbk_` key does not — because an installed app
122
+ // holds SCOPES against the store. And `acceptedPrice` is a pointer:
123
+ // omitting it means a free app, and omitting it for a paid one is REFUSED
124
+ // rather than assumed, so nothing automated can commit a merchant to a
125
+ // subscription.
126
+ //
127
+ // So the honest answer is neither "ask a human" nor "just install it". It
128
+ // is: always be able to SUGGEST, and install only what the credential in
129
+ // hand is allowed to install, having shown what it grants.
130
+ marketplace: 'SUGGESTING one is always available: GET /api/sites/{siteId}/apps lists what this store ' +
131
+ 'can install, and GET /oauth/authorize-info?client_id=… answers with the app, its ' +
132
+ 'publisher, its privacy policy, the SCOPES it would hold and whether it is paid. Show ' +
133
+ 'that to whoever is accountable for it. INSTALLING is POST /oauth/authorize with ' +
134
+ '{siteId, clientId, versionId, redirectUri, scopes} — it needs a SESSION ' +
135
+ '(SB_EMAIL/SB_PASSWORD), because an agent key is not an access token and the platform ' +
136
+ 'refuses it by design: the app holds scopes against the store. A FREE app installs with ' +
137
+ 'no acceptedPrice; a PAID one is refused without it rather than having a price assumed ' +
138
+ 'on the merchant\'s behalf, so never send one they have not seen. Then read ' +
139
+ '/apps/blocks again for what it contributed.',
120
140
  };
121
141
  }
122
142
  const shape = REQUEST_SHAPES[op.id];
@@ -1,7 +1,7 @@
1
1
  export const SHAPE_SOURCE = {
2
- "writeOperations": 219,
3
- "shaped": 169,
4
- "fromHandlers": 169,
2
+ "writeOperations": 223,
3
+ "shaped": 170,
4
+ "fromHandlers": 170,
5
5
  "fromSwaggerOnly": 0,
6
6
  "withReadOnly": 26,
7
7
  "structsRead": 1658
@@ -31,6 +31,41 @@ export const REQUEST_SHAPES = {
31
31
  "source": "go",
32
32
  "goType": "versionChoice"
33
33
  },
34
+ "post:/oauth/authorize": {
35
+ "fields": [
36
+ {
37
+ "name": "siteId",
38
+ "type": "string"
39
+ },
40
+ {
41
+ "name": "clientId",
42
+ "type": "string"
43
+ },
44
+ {
45
+ "name": "versionId",
46
+ "type": "string"
47
+ },
48
+ {
49
+ "name": "redirectUri",
50
+ "type": "string"
51
+ },
52
+ {
53
+ "name": "scopes",
54
+ "type": "string[]"
55
+ },
56
+ {
57
+ "name": "state",
58
+ "type": "string"
59
+ },
60
+ {
61
+ "name": "AcceptedPrice",
62
+ "type": "object",
63
+ "note": "AcceptedPrice is the amount the merchant was LOOKING AT when they pressed the button, echoed back from the authorize response above."
64
+ }
65
+ ],
66
+ "source": "go",
67
+ "goType": "(inline)"
68
+ },
34
69
  "post:/api/orgs/{orgId}/apps": {
35
70
  "fields": [
36
71
  {
@@ -113,8 +113,12 @@ export class UndoLog {
113
113
  */
114
114
  export function registerUndoTools(server, ctx) {
115
115
  server.registerTool('sb_undo', {
116
- description: 'Put back what a PUT through sb_api_call replaced. The platform has no page history ' +
117
- 'or restore, so this is the only way back. No argument lists what is undoable.',
116
+ description: 'Put back what a PUT through sb_api_call replaced settings, a product, a form, ' +
117
+ 'anything with a shape. IN THIS PROCESS ONLY, capped, and gone when it exits. For a ' +
118
+ 'PAGE the platform keeps its own: GET .../pages/{pageId}/history lists the autosave ' +
119
+ 'checkpoint it writes on every draft save, versions lists the labelled snapshots, and ' +
120
+ 'either restores. That one survives everything and is the better answer whenever the ' +
121
+ 'thing to recover is a page. No argument lists what is undoable here.',
118
122
  inputSchema: {
119
123
  index: z.number().int().min(1).optional().describe('1 is the most recent write'),
120
124
  dry_run: z.boolean().optional(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sbuilder-mcp",
3
- "version": "0.34.0",
3
+ "version": "0.36.0",
4
4
  "description": "MCP server that designs and operates a Store Builder site — pages, data, theme and publish — through the platform's own API and live-edit protocol.",
5
5
  "mcpName": "io.github.vuluu2k/sbuilder-mcp",
6
6
  "type": "module",