@ratio-mcp/docs-server 1.5.0 → 1.6.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.
Files changed (40) hide show
  1. package/README.md +75 -0
  2. package/dist/schemas/app-distribution.json +36 -0
  3. package/dist/schemas/customers.json +26 -0
  4. package/dist/schemas/discounts.json +81 -0
  5. package/dist/schemas/draft_orders.json +112 -0
  6. package/dist/schemas/loyalty.json +147 -0
  7. package/dist/schemas/orders.json +597 -102
  8. package/dist/schemas/product_reviews.json +45 -0
  9. package/dist/schemas/products.json +401 -118
  10. package/dist/schemas/tags.json +98 -0
  11. package/dist/schemas/variants.json +112 -0
  12. package/dist/schemas/webhooks.json +94 -15
  13. package/dist/tools/get-api-reference.d.ts.map +1 -1
  14. package/dist/tools/get-api-reference.js +4 -1
  15. package/dist/tools/get-api-reference.js.map +1 -1
  16. package/dist/tools/get-scope-map.d.ts.map +1 -1
  17. package/dist/tools/get-scope-map.js +7 -1
  18. package/dist/tools/get-scope-map.js.map +1 -1
  19. package/dist/tools/get-scopes.d.ts +3 -0
  20. package/dist/tools/get-scopes.d.ts.map +1 -1
  21. package/dist/tools/get-scopes.js +13 -2
  22. package/dist/tools/get-scopes.js.map +1 -1
  23. package/dist/tools/lookup-docs.d.ts +1 -1
  24. package/dist/tools/lookup-docs.d.ts.map +1 -1
  25. package/dist/tools/lookup-docs.js +27 -4
  26. package/dist/tools/lookup-docs.js.map +1 -1
  27. package/dist/tools/validate-code.d.ts.map +1 -1
  28. package/dist/tools/validate-code.js +0 -4
  29. package/dist/tools/validate-code.js.map +1 -1
  30. package/dist/utils/schema-loader.d.ts +5 -1
  31. package/dist/utils/schema-loader.d.ts.map +1 -1
  32. package/dist/utils/schema-loader.js +8 -2
  33. package/dist/utils/schema-loader.js.map +1 -1
  34. package/package.json +3 -3
  35. package/dist/schemas/schemas/oauth.json +0 -71
  36. package/dist/schemas/schemas/orders.json +0 -167
  37. package/dist/schemas/schemas/products.json +0 -167
  38. package/dist/schemas/schemas/scopes.json +0 -52
  39. package/dist/schemas/schemas/webhooks.json +0 -69
  40. package/dist/schemas/scopes.json +0 -52
package/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # @ratio-mcp/docs-server
2
+
3
+ > Anti-hallucination reference MCP for the Ratio platform. Ground-truth lookups for scopes, REST endpoints, webhook events, and OAuth flow. Production environment.
4
+
5
+ Not installed directly — included via [`@ratio-mcp/setup`](https://www.npmjs.com/package/@ratio-mcp/setup).
6
+
7
+ ---
8
+
9
+ ## Why it exists
10
+
11
+ Without grounded references, LLMs hallucinate platform details — wrong scope codes, invented endpoints, made-up webhook topics. This server exposes 6 tools that the LLM is **required** to call before answering platform-specific questions.
12
+
13
+ When `lookup_docs` returns `found: false`, the LLM must tell the user the info isn't available — not guess.
14
+
15
+ ---
16
+
17
+ ## Tools (6)
18
+
19
+ | Tool | When the LLM must call it |
20
+ |---|---|
21
+ | `lookup_docs` | **Mandatory fallback.** Any platform question where the LLM isn't 100% sure — unified fuzzy search across all docs. |
22
+ | `get_available_scopes` | Before showing scope options to the developer. Returns all 78 resources × 147 scopes. |
23
+ | `get_api_reference` | Before generating or discussing API calls for a resource. Returns endpoint definitions. |
24
+ | `get_scope_endpoint_map` | Before code generation. Maps scopes → the endpoints they unlock. |
25
+ | `get_webhook_events` | Before answering webhook questions. Returns the full event catalog. |
26
+ | `validate_api_code` | **After generating code, before writing to disk.** Catches hallucinated fields, wrong endpoints, missing required fields. |
27
+
28
+ ---
29
+
30
+ ## Data sources
31
+
32
+ The server bundles local JSON schemas — zero network calls at runtime:
33
+
34
+ ```
35
+ packages/docs-server/src/schemas/
36
+ ├── orders.json # REST endpoints with full request/response shapes
37
+ ├── products.json # Same for products
38
+ ├── webhooks.json # Event catalog + HMAC-SHA256 verification + retry policy
39
+ └── oauth.json # OAuth flow reference
40
+ ```
41
+
42
+ > Scope data is NOT here — it lives in `@ratio-mcp/shared` (`scopes-data.ts`), sourced from `GET /api/v1/scopes`. Every other `*.json` in this dir is treated as an API resource by `getAvailableResourceFiles()`.
43
+
44
+ Currently `orders` and `products` have full type schemas. Other resources will be added as the platform exposes them via Swagger.
45
+
46
+ ---
47
+
48
+ ## Environment
49
+
50
+ **Production** — points at `https://gkx.gokwik.co/aes` for any tools that fall back to live API calls (most don't — schemas are local).
51
+
52
+ ---
53
+
54
+ ## Anti-hallucination contract
55
+
56
+ Both MCP servers (this one and `dev-server`) embed mandatory tool-usage rules in their server instructions, surfaced to the LLM via the MCP handshake:
57
+
58
+ > 1. ALWAYS call `lookup_docs` BEFORE answering questions about scopes, webhooks, APIs, or OAuth.
59
+ > 2. If `lookup_docs` returns `found: false`, tell the user the info is not available — do NOT guess.
60
+ > 3. ALWAYS call `validate_scopes` (dev-server) BEFORE presenting any scope to the developer.
61
+ > 4. ALWAYS call `validate_api_code` AFTER generating Ratio API code, BEFORE writing to disk.
62
+
63
+ These guardrails are the difference between "the LLM mostly works" and "the LLM never invents a platform field name."
64
+
65
+ ---
66
+
67
+ ## Logging
68
+
69
+ stderr + file (`logs/docs-server.log`). Key log prefixes: `[lookup_docs]`, `[validate_api_code]`.
70
+
71
+ ---
72
+
73
+ ## License
74
+
75
+ UNLICENSED — internal to the Ratio platform / GoKwik.
@@ -0,0 +1,36 @@
1
+ {
2
+ "version": 1,
3
+ "topic": "app_distribution",
4
+ "summary": "Every Ratio app has a distribution type chosen at creation: public or private. It controls who can install the app, whether it is listed in the marketplace, and whether it goes through human review.",
5
+ "types": {
6
+ "public": {
7
+ "definition": "Available to ALL merchants via the marketplace.",
8
+ "distribution": "Listed in the public marketplace; any merchant can discover and install it.",
9
+ "review": "Each submitted version must pass admin (human) review before it can be published.",
10
+ "publication": "Published manually after approval (or via the app's auto-publish setting).",
11
+ "use_case": "Third-party integrations sold to many merchants.",
12
+ "create": "Default. create_app with app_type omitted or app_type: \"public\"."
13
+ },
14
+ "private": {
15
+ "definition": "Available ONLY to an explicit whitelist of merchants.",
16
+ "distribution": "Not listed in the marketplace; installable only by whitelisted merchant IDs.",
17
+ "review": "Skips human review — versions are auto-reviewed (system actor) and auto-published on upload.",
18
+ "publication": "Immediate on version upload.",
19
+ "requirement": "At least one merchant ID must be provided at creation time.",
20
+ "whitelist_management": "Add/remove merchants any time via the manage_private_merchants tool (or GET/POST/DELETE /applications/:id/private-merchants).",
21
+ "use_case": "Custom builds for specific enterprise clients or partner integrations.",
22
+ "create": "create_app with app_type: \"private\" and merchant_ids: [\"merchant-id-1\", ...] (at least one)."
23
+ }
24
+ },
25
+ "comparison": [
26
+ { "aspect": "Distribution", "public": "All merchants", "private": "Whitelisted merchants only" },
27
+ { "aspect": "Marketplace", "public": "Listed", "private": "Hidden" },
28
+ { "aspect": "Review", "public": "Human review required", "private": "Auto-reviewed (system)" },
29
+ { "aspect": "Publication", "public": "After approval", "private": "Immediate on upload" },
30
+ { "aspect": "Merchant ID whitelist", "public": "N/A", "private": "Required (>= 1)" }
31
+ ],
32
+ "mcp_support": {
33
+ "create_app": "Accepts app_type ('public' | 'private', default public) and merchant_ids. Private requires merchant_ids (>= 1).",
34
+ "manage_private_merchants": "list | add | remove whitelisted merchants for a private app."
35
+ }
36
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "resource": "customers",
3
+ "auth": {
4
+ "type": "bearer",
5
+ "header": "Authorization",
6
+ "format": "Bearer <access_token>"
7
+ },
8
+ "_generated": "by scripts/sync-schemas.mjs from backend OpenAPI (x-required-scope). Do not hand-edit.",
9
+ "endpoints": [
10
+ {
11
+ "method": "GET",
12
+ "path": "/api/v1/customers/:id",
13
+ "controller_order": 1,
14
+ "handler_name": "getCustomerById",
15
+ "required_scope": "read_customers",
16
+ "path_params": [
17
+ {
18
+ "name": "id",
19
+ "type": "string",
20
+ "required": true
21
+ }
22
+ ],
23
+ "request_body": null
24
+ }
25
+ ]
26
+ }
@@ -0,0 +1,81 @@
1
+ {
2
+ "resource": "discounts",
3
+ "auth": {
4
+ "type": "bearer",
5
+ "header": "Authorization",
6
+ "format": "Bearer <access_token>"
7
+ },
8
+ "common_headers": {
9
+ "idempotency-key": "header"
10
+ },
11
+ "_generated": "by scripts/sync-schemas.mjs from backend OpenAPI (x-required-scope). Do not hand-edit.",
12
+ "endpoints": [
13
+ {
14
+ "method": "POST",
15
+ "path": "/api/v1/discounts",
16
+ "controller_order": 1,
17
+ "handler_name": "create",
18
+ "required_scope": "write_discounts",
19
+ "request_body": {
20
+ "content_type": "application/json",
21
+ "fields": []
22
+ }
23
+ },
24
+ {
25
+ "method": "GET",
26
+ "path": "/api/v1/discounts",
27
+ "controller_order": 2,
28
+ "handler_name": "findAll",
29
+ "required_scope": "read_discounts",
30
+ "request_body": null
31
+ },
32
+ {
33
+ "method": "GET",
34
+ "path": "/api/v1/discounts/:id",
35
+ "controller_order": 3,
36
+ "handler_name": "findOne",
37
+ "required_scope": "read_discounts",
38
+ "path_params": [
39
+ {
40
+ "name": "id",
41
+ "type": "string",
42
+ "required": true
43
+ }
44
+ ],
45
+ "request_body": null
46
+ },
47
+ {
48
+ "method": "PUT",
49
+ "path": "/api/v1/discounts/:id",
50
+ "controller_order": 4,
51
+ "handler_name": "update",
52
+ "required_scope": "write_discounts",
53
+ "path_params": [
54
+ {
55
+ "name": "id",
56
+ "type": "string",
57
+ "required": true
58
+ }
59
+ ],
60
+ "request_body": {
61
+ "content_type": "application/json",
62
+ "fields": []
63
+ }
64
+ },
65
+ {
66
+ "method": "DELETE",
67
+ "path": "/api/v1/discounts/:id",
68
+ "controller_order": 5,
69
+ "handler_name": "remove",
70
+ "required_scope": "write_discounts",
71
+ "path_params": [
72
+ {
73
+ "name": "id",
74
+ "type": "string",
75
+ "required": true
76
+ }
77
+ ],
78
+ "request_body": null
79
+ }
80
+ ]
81
+ }
@@ -0,0 +1,112 @@
1
+ {
2
+ "resource": "draft_orders",
3
+ "auth": {
4
+ "type": "bearer",
5
+ "header": "Authorization",
6
+ "format": "Bearer <access_token>"
7
+ },
8
+ "common_headers": {
9
+ "gk-merchant-id": "Required. Tenant/merchant context for the request."
10
+ },
11
+ "notes": "Paths carry a doubled /v1 segment (global /api/v1 prefix + controller 'v1/draft-orders'). Line-item / customer / address shapes mirror the orders resource.",
12
+ "endpoints": [
13
+ {
14
+ "method": "POST",
15
+ "path": "/api/v1/v1/draft-orders",
16
+ "controller_order": 1,
17
+ "handler_name": "createDraftOrder",
18
+ "required_scope": "write_draft_orders",
19
+ "summary": "Create a draft order",
20
+ "request_body": {
21
+ "content_type": "application/json",
22
+ "fields": [
23
+ { "name": "email", "type": "string", "required": false, "description": "Customer email" },
24
+ { "name": "currency", "type": "string", "required": false, "description": "Currency code (e.g. INR)" },
25
+ { "name": "line_items", "type": "array", "required": false, "description": "Line items (same shape as orders: variant_id, product_id, title, quantity, sku, price)" },
26
+ { "name": "customer", "type": "object", "required": false, "description": "Customer details (same shape as orders)" },
27
+ { "name": "billing_address", "type": "object", "required": false, "description": "Billing address (same shape as orders)" },
28
+ { "name": "shipping_address", "type": "object", "required": false, "description": "Shipping address (same shape as orders)" },
29
+ { "name": "note", "type": "string", "required": false }
30
+ ]
31
+ },
32
+ "response_schema": "DraftOrder"
33
+ },
34
+ {
35
+ "method": "PUT",
36
+ "path": "/api/v1/v1/draft-orders",
37
+ "controller_order": 2,
38
+ "handler_name": "updateDraftOrder",
39
+ "required_scope": "write_draft_orders",
40
+ "summary": "Update a draft order",
41
+ "description": "Update a draft order. The draft order id is supplied in the request body (not the path).",
42
+ "request_body": {
43
+ "content_type": "application/json",
44
+ "fields": [
45
+ { "name": "id", "type": "string", "required": true, "description": "The draft order ID to update (in body)" },
46
+ { "name": "email", "type": "string", "required": false },
47
+ { "name": "line_items", "type": "array", "required": false },
48
+ { "name": "customer", "type": "object", "required": false },
49
+ { "name": "shipping_address", "type": "object", "required": false },
50
+ { "name": "billing_address", "type": "object", "required": false }
51
+ ]
52
+ },
53
+ "response_schema": "DraftOrder"
54
+ },
55
+ {
56
+ "method": "GET",
57
+ "path": "/api/v1/v1/draft-orders",
58
+ "controller_order": 3,
59
+ "handler_name": "getDraftOrders",
60
+ "required_scope": "read_draft_orders",
61
+ "summary": "List draft orders",
62
+ "query_params": [
63
+ { "name": "limit", "type": "number", "required": false },
64
+ { "name": "offset", "type": "number", "required": false },
65
+ { "name": "status", "type": "string", "required": false }
66
+ ],
67
+ "request_body": null,
68
+ "response_schema": "DraftOrderListResponse"
69
+ },
70
+ {
71
+ "method": "GET",
72
+ "path": "/api/v1/v1/draft-orders/:id",
73
+ "controller_order": 4,
74
+ "handler_name": "getDraftOrderById",
75
+ "required_scope": "read_draft_orders",
76
+ "summary": "Get a draft order by ID",
77
+ "path_params": [
78
+ { "name": "id", "type": "string", "required": true, "description": "The draft order ID" }
79
+ ],
80
+ "request_body": null,
81
+ "response_schema": "DraftOrder"
82
+ },
83
+ {
84
+ "method": "DELETE",
85
+ "path": "/api/v1/v1/draft-orders/:id",
86
+ "controller_order": 5,
87
+ "handler_name": "deleteDraftOrder",
88
+ "required_scope": "write_draft_orders",
89
+ "summary": "Delete a draft order",
90
+ "path_params": [
91
+ { "name": "id", "type": "string", "required": true, "description": "The draft order ID to delete" }
92
+ ],
93
+ "request_body": null,
94
+ "response_schema": "DraftOrder"
95
+ }
96
+ ],
97
+ "schemas": {
98
+ "DraftOrder": {
99
+ "id": "string — draft order identifier",
100
+ "email": "string | null",
101
+ "currency": "string",
102
+ "line_items": "LineItem[] — same shape as orders",
103
+ "customer": "Customer object",
104
+ "shipping_address": "Address | null",
105
+ "billing_address": "Address | null",
106
+ "note": "string | null",
107
+ "status": "string — draft status",
108
+ "created_at": "string — ISO 8601",
109
+ "updated_at": "string — ISO 8601"
110
+ }
111
+ }
112
+ }
@@ -0,0 +1,147 @@
1
+ {
2
+ "resource": "loyalty",
3
+ "auth": {
4
+ "type": "bearer",
5
+ "header": "Authorization",
6
+ "format": "Bearer <access_token>"
7
+ },
8
+ "_generated": "by scripts/sync-schemas.mjs from backend OpenAPI (x-required-scope). Do not hand-edit.",
9
+ "endpoints": [
10
+ {
11
+ "method": "POST",
12
+ "path": "/api/v1/loyalty/points/credit",
13
+ "controller_order": 1,
14
+ "handler_name": "credit",
15
+ "required_scope": "write_loyalty",
16
+ "summary": "Credit loyalty points to a customer (idempotent).",
17
+ "description": "Adds points to the customer’s balance. Same `idempotency_key` on retry returns the existing transaction without double-crediting.",
18
+ "request_body": {
19
+ "content_type": "application/json",
20
+ "fields": [
21
+ {
22
+ "name": "phone",
23
+ "type": "string",
24
+ "required": true,
25
+ "description": "Customer phone number (loyalty key)"
26
+ },
27
+ {
28
+ "name": "points",
29
+ "type": "number",
30
+ "required": true,
31
+ "description": "Points to apply (positive integer, max 100000 per transaction)"
32
+ },
33
+ {
34
+ "name": "idempotency_key",
35
+ "type": "string",
36
+ "required": true,
37
+ "description": "Caller-supplied idempotency key. Same key on retry returns the existing transaction without double-applying."
38
+ },
39
+ {
40
+ "name": "description",
41
+ "type": "string",
42
+ "required": false,
43
+ "description": "Free-text description of the reason"
44
+ },
45
+ {
46
+ "name": "metadata",
47
+ "type": "object",
48
+ "required": false,
49
+ "description": "Arbitrary structured data attached to the ledger row"
50
+ }
51
+ ]
52
+ }
53
+ },
54
+ {
55
+ "method": "POST",
56
+ "path": "/api/v1/loyalty/points/debit",
57
+ "controller_order": 2,
58
+ "handler_name": "debit",
59
+ "required_scope": "write_loyalty",
60
+ "summary": "Debit loyalty points from a customer (idempotent).",
61
+ "description": "Deducts points from the customer’s balance. Returns 400 if the customer’s balance is insufficient.",
62
+ "request_body": {
63
+ "content_type": "application/json",
64
+ "fields": [
65
+ {
66
+ "name": "phone",
67
+ "type": "string",
68
+ "required": true,
69
+ "description": "Customer phone number (loyalty key)"
70
+ },
71
+ {
72
+ "name": "points",
73
+ "type": "number",
74
+ "required": true,
75
+ "description": "Points to apply (positive integer, max 100000 per transaction)"
76
+ },
77
+ {
78
+ "name": "idempotency_key",
79
+ "type": "string",
80
+ "required": true,
81
+ "description": "Caller-supplied idempotency key. Same key on retry returns the existing transaction without double-applying."
82
+ },
83
+ {
84
+ "name": "description",
85
+ "type": "string",
86
+ "required": false,
87
+ "description": "Free-text description of the reason"
88
+ },
89
+ {
90
+ "name": "metadata",
91
+ "type": "object",
92
+ "required": false,
93
+ "description": "Arbitrary structured data attached to the ledger row"
94
+ }
95
+ ]
96
+ }
97
+ },
98
+ {
99
+ "method": "GET",
100
+ "path": "/api/v1/loyalty/points/:phone/balance",
101
+ "controller_order": 3,
102
+ "handler_name": "getBalance",
103
+ "required_scope": "read_loyalty",
104
+ "summary": "Get a customer's current loyalty balance + lifetime stats.",
105
+ "description": "Returns the redeemable balance and lifetime earned/redeemed/expired/adjusted totals. A customer with no loyalty record yet returns a zero-balance response.",
106
+ "path_params": [
107
+ {
108
+ "name": "phone",
109
+ "type": "string",
110
+ "required": true
111
+ }
112
+ ],
113
+ "request_body": null
114
+ },
115
+ {
116
+ "method": "GET",
117
+ "path": "/api/v1/loyalty/points/:phone/history",
118
+ "controller_order": 4,
119
+ "handler_name": "getHistory",
120
+ "required_scope": "read_loyalty",
121
+ "summary": "Get a customer's loyalty transaction history (paginated).",
122
+ "description": "Returns the full points ledger (earn, redeem, adjust, reversal, expire) for the customer, most recent first, with pagination metadata.",
123
+ "query_params": [
124
+ {
125
+ "name": "page",
126
+ "type": "number",
127
+ "required": false,
128
+ "description": "Page number (1-based); os-loyalty defaults to 1"
129
+ },
130
+ {
131
+ "name": "limit",
132
+ "type": "number",
133
+ "required": false,
134
+ "description": "Rows per page"
135
+ }
136
+ ],
137
+ "path_params": [
138
+ {
139
+ "name": "phone",
140
+ "type": "string",
141
+ "required": true
142
+ }
143
+ ],
144
+ "request_body": null
145
+ }
146
+ ]
147
+ }