@ratio-mcp/dev-server 1.5.1 → 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 (76) hide show
  1. package/dist/index.js +0 -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/oauth.json +71 -0
  8. package/dist/schemas/orders.json +601 -106
  9. package/dist/schemas/product_reviews.json +45 -0
  10. package/dist/schemas/products.json +405 -122
  11. package/dist/schemas/tags.json +98 -0
  12. package/dist/schemas/variants.json +112 -0
  13. package/dist/schemas/webhooks.json +148 -0
  14. package/dist/server.d.ts.map +1 -1
  15. package/dist/server.js +39 -5
  16. package/dist/server.js.map +1 -1
  17. package/dist/services/app-state-sync.d.ts +34 -0
  18. package/dist/services/app-state-sync.d.ts.map +1 -0
  19. package/dist/services/app-state-sync.js +85 -0
  20. package/dist/services/app-state-sync.js.map +1 -0
  21. package/dist/services/elicitation.d.ts +25 -0
  22. package/dist/services/elicitation.d.ts.map +1 -0
  23. package/dist/services/elicitation.js +101 -0
  24. package/dist/services/elicitation.js.map +1 -0
  25. package/dist/services/flow-profiles.d.ts +46 -0
  26. package/dist/services/flow-profiles.d.ts.map +1 -0
  27. package/dist/services/flow-profiles.js +100 -0
  28. package/dist/services/flow-profiles.js.map +1 -0
  29. package/dist/services/questionnaire.d.ts +89 -0
  30. package/dist/services/questionnaire.d.ts.map +1 -0
  31. package/dist/services/questionnaire.js +167 -0
  32. package/dist/services/questionnaire.js.map +1 -0
  33. package/dist/services/session-state.d.ts +17 -0
  34. package/dist/services/session-state.d.ts.map +1 -1
  35. package/dist/services/session-state.js +26 -1
  36. package/dist/services/session-state.js.map +1 -1
  37. package/dist/services/tool-guard.d.ts +15 -18
  38. package/dist/services/tool-guard.d.ts.map +1 -1
  39. package/dist/services/tool-guard.js +150 -97
  40. package/dist/services/tool-guard.js.map +1 -1
  41. package/dist/tools/app-management.d.ts.map +1 -1
  42. package/dist/tools/app-management.js +181 -33
  43. package/dist/tools/app-management.js.map +1 -1
  44. package/dist/tools/gather-requirements.d.ts.map +1 -1
  45. package/dist/tools/gather-requirements.js +5 -3
  46. package/dist/tools/gather-requirements.js.map +1 -1
  47. package/dist/tools/get-status.d.ts.map +1 -1
  48. package/dist/tools/get-status.js +45 -34
  49. package/dist/tools/get-status.js.map +1 -1
  50. package/dist/tools/index.js +1 -1
  51. package/dist/tools/index.js.map +1 -1
  52. package/dist/tools/lifecycle.d.ts.map +1 -1
  53. package/dist/tools/lifecycle.js +6 -3
  54. package/dist/tools/lifecycle.js.map +1 -1
  55. package/dist/tools/reference-data.d.ts +16 -0
  56. package/dist/tools/reference-data.d.ts.map +1 -1
  57. package/dist/tools/reference-data.js +12 -8
  58. package/dist/tools/reference-data.js.map +1 -1
  59. package/dist/tools/requirements.d.ts.map +1 -1
  60. package/dist/tools/requirements.js +17 -9
  61. package/dist/tools/requirements.js.map +1 -1
  62. package/dist/tools/submission.d.ts.map +1 -1
  63. package/dist/tools/submission.js +50 -13
  64. package/dist/tools/submission.js.map +1 -1
  65. package/dist/tools/webhooks.d.ts.map +1 -1
  66. package/dist/tools/webhooks.js +3 -1
  67. package/dist/tools/webhooks.js.map +1 -1
  68. package/dist/utils/logger.d.ts +3 -2
  69. package/dist/utils/logger.d.ts.map +1 -1
  70. package/dist/utils/logger.js +19 -10
  71. package/dist/utils/logger.js.map +1 -1
  72. package/dist/utils/schema-resources.d.ts +8 -0
  73. package/dist/utils/schema-resources.d.ts.map +1 -0
  74. package/dist/utils/schema-resources.js +25 -0
  75. package/dist/utils/schema-resources.js.map +1 -0
  76. package/package.json +12 -13
@@ -0,0 +1,98 @@
1
+ {
2
+ "resource": "tags",
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": "Order tags. These endpoints reuse the ORDER scopes: read_orders for reads, order-create for writes (NOT a separate tags scope).",
12
+ "endpoints": [
13
+ {
14
+ "method": "POST",
15
+ "path": "/api/v1/tags",
16
+ "controller_order": 1,
17
+ "handler_name": "create",
18
+ "required_scope": "order-create",
19
+ "summary": "Create a tag",
20
+ "request_body": {
21
+ "content_type": "application/json",
22
+ "fields": [
23
+ { "name": "name", "type": "string", "required": true, "description": "Tag name" },
24
+ { "name": "is_active", "type": "boolean", "required": false, "default": true, "description": "Whether the tag is active" }
25
+ ]
26
+ },
27
+ "response_schema": "Tag"
28
+ },
29
+ {
30
+ "method": "GET",
31
+ "path": "/api/v1/tags",
32
+ "controller_order": 2,
33
+ "handler_name": "getTags",
34
+ "required_scope": "read_orders",
35
+ "summary": "List tags",
36
+ "query_params": [
37
+ { "name": "is_active", "type": "boolean", "required": false, "description": "Filter by active state" },
38
+ { "name": "search", "type": "string", "required": false, "description": "Search by tag name" }
39
+ ],
40
+ "request_body": null,
41
+ "response_schema": "TagListResponse"
42
+ },
43
+ {
44
+ "method": "GET",
45
+ "path": "/api/v1/tags/:id",
46
+ "controller_order": 3,
47
+ "handler_name": "getTagById",
48
+ "required_scope": "read_orders",
49
+ "summary": "Get a tag by ID",
50
+ "path_params": [
51
+ { "name": "id", "type": "string", "required": true, "description": "The tag ID" }
52
+ ],
53
+ "request_body": null,
54
+ "response_schema": "Tag"
55
+ },
56
+ {
57
+ "method": "PUT",
58
+ "path": "/api/v1/tags/:id",
59
+ "controller_order": 4,
60
+ "handler_name": "updateTag",
61
+ "required_scope": "order-create",
62
+ "summary": "Update a tag",
63
+ "path_params": [
64
+ { "name": "id", "type": "string", "required": true, "description": "The tag ID to update" }
65
+ ],
66
+ "request_body": {
67
+ "content_type": "application/json",
68
+ "fields": [
69
+ { "name": "name", "type": "string", "required": false },
70
+ { "name": "is_active", "type": "boolean", "required": false }
71
+ ]
72
+ },
73
+ "response_schema": "Tag"
74
+ },
75
+ {
76
+ "method": "DELETE",
77
+ "path": "/api/v1/tags/:id",
78
+ "controller_order": 5,
79
+ "handler_name": "deleteTag",
80
+ "required_scope": "order-create",
81
+ "summary": "Delete a tag",
82
+ "path_params": [
83
+ { "name": "id", "type": "string", "required": true, "description": "The tag ID to delete" }
84
+ ],
85
+ "request_body": null,
86
+ "response_schema": "Tag"
87
+ }
88
+ ],
89
+ "schemas": {
90
+ "Tag": {
91
+ "id": "string — tag identifier",
92
+ "name": "string — tag name",
93
+ "is_active": "boolean",
94
+ "created_at": "string — ISO 8601",
95
+ "updated_at": "string — ISO 8601"
96
+ }
97
+ }
98
+ }
@@ -0,0 +1,112 @@
1
+ {
2
+ "resource": "variants",
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": "Product variants (sub-resource of products). Uses product scopes: read_products for reads, write_products for writes. Paths carry a doubled /v1 segment (global /api/v1 prefix + controller 'v1/variants').",
12
+ "endpoints": [
13
+ {
14
+ "method": "GET",
15
+ "path": "/api/v1/v1/variants",
16
+ "controller_order": 1,
17
+ "handler_name": "findAll",
18
+ "required_scope": "read_products",
19
+ "summary": "List variants",
20
+ "query_params": [
21
+ { "name": "product_id", "type": "string", "required": false, "description": "Filter by product" },
22
+ { "name": "limit", "type": "number", "required": false },
23
+ { "name": "offset", "type": "number", "required": false }
24
+ ],
25
+ "request_body": null,
26
+ "response_schema": "VariantListResponse"
27
+ },
28
+ {
29
+ "method": "GET",
30
+ "path": "/api/v1/v1/variants/:id",
31
+ "controller_order": 2,
32
+ "handler_name": "findOne",
33
+ "required_scope": "read_products",
34
+ "summary": "Get a variant by ID",
35
+ "path_params": [
36
+ { "name": "id", "type": "string", "required": true, "description": "The variant ID" }
37
+ ],
38
+ "request_body": null,
39
+ "response_schema": "Variant"
40
+ },
41
+ {
42
+ "method": "DELETE",
43
+ "path": "/api/v1/v1/variants/:id",
44
+ "controller_order": 3,
45
+ "handler_name": "remove",
46
+ "required_scope": "write_products",
47
+ "summary": "Delete a variant",
48
+ "path_params": [
49
+ { "name": "id", "type": "string", "required": true, "description": "The variant ID to delete" }
50
+ ],
51
+ "request_body": null,
52
+ "response_schema": "Variant"
53
+ },
54
+ {
55
+ "method": "PUT",
56
+ "path": "/api/v1/v1/variants/:id",
57
+ "controller_order": 4,
58
+ "handler_name": "update",
59
+ "required_scope": "write_products",
60
+ "summary": "Update a variant",
61
+ "path_params": [
62
+ { "name": "id", "type": "string", "required": true, "description": "The variant ID to update" }
63
+ ],
64
+ "request_body": {
65
+ "content_type": "application/json",
66
+ "fields": [
67
+ { "name": "title", "type": "string", "required": false },
68
+ { "name": "sku", "type": "string", "required": false },
69
+ { "name": "price", "type": "number", "required": false },
70
+ { "name": "cost", "type": "number", "required": false },
71
+ { "name": "inventory", "type": "number", "required": false, "description": "Inventory quantity" }
72
+ ]
73
+ },
74
+ "response_schema": "Variant"
75
+ },
76
+ {
77
+ "method": "POST",
78
+ "path": "/api/v1/v1/variants/:productId",
79
+ "controller_order": 5,
80
+ "handler_name": "create",
81
+ "required_scope": "write_products",
82
+ "summary": "Create a variant for a product",
83
+ "path_params": [
84
+ { "name": "productId", "type": "string", "required": true, "description": "The product to attach the variant to" }
85
+ ],
86
+ "request_body": {
87
+ "content_type": "application/json",
88
+ "fields": [
89
+ { "name": "title", "type": "string", "required": false },
90
+ { "name": "sku", "type": "string", "required": false },
91
+ { "name": "price", "type": "number", "required": false },
92
+ { "name": "cost", "type": "number", "required": false },
93
+ { "name": "inventory", "type": "number", "required": false, "description": "Inventory quantity" }
94
+ ]
95
+ },
96
+ "response_schema": "Variant"
97
+ }
98
+ ],
99
+ "schemas": {
100
+ "Variant": {
101
+ "id": "string — variant identifier",
102
+ "product_id": "string",
103
+ "title": "string | null",
104
+ "sku": "string | null",
105
+ "price": "number",
106
+ "cost": "number | null",
107
+ "inventory": "number — inventory quantity",
108
+ "created_at": "string — ISO 8601",
109
+ "updated_at": "string — ISO 8601"
110
+ }
111
+ }
112
+ }
@@ -0,0 +1,148 @@
1
+ {
2
+ "version": 2,
3
+ "verification": {
4
+ "method": "HMAC-SHA256",
5
+ "header": "X-Webhook-Signature",
6
+ "description": "Verify authenticity by computing HMAC-SHA256 of the raw request body using your app's webhook secret (returned once when the webhook is created). The computed digest must equal the X-Webhook-Signature header. Each delivery also carries X-Webhook-Id, X-Webhook-Topic, and X-Merchant-Id headers."
7
+ },
8
+ "retry_policy": {
9
+ "max_retries": 3,
10
+ "retry_intervals": ["1s", "5s", "30s"],
11
+ "timeout": "30s",
12
+ "failure_action": "Webhook is auto-disabled after 10 consecutive failed deliveries"
13
+ },
14
+ "events": [
15
+ {
16
+ "topic": "orders/create",
17
+ "description": "Triggered when a new order is placed",
18
+ "resource": "orders",
19
+ "required_scope": "read_orders"
20
+ },
21
+ {
22
+ "topic": "orders/updated",
23
+ "description": "Triggered when an order is updated",
24
+ "resource": "orders",
25
+ "required_scope": "read_orders"
26
+ },
27
+ {
28
+ "topic": "orders/paid",
29
+ "description": "Triggered when an order is paid",
30
+ "resource": "orders",
31
+ "required_scope": "read_orders"
32
+ },
33
+ {
34
+ "topic": "orders/fulfilled",
35
+ "description": "Triggered when an order is fully fulfilled",
36
+ "resource": "orders",
37
+ "required_scope": "read_orders"
38
+ },
39
+ {
40
+ "topic": "orders/cancelled",
41
+ "description": "Triggered when an order is cancelled",
42
+ "resource": "orders",
43
+ "required_scope": "read_orders"
44
+ },
45
+ {
46
+ "topic": "orders/partially_fulfilled",
47
+ "description": "Triggered when an order is partially fulfilled",
48
+ "resource": "orders",
49
+ "required_scope": "read_orders"
50
+ },
51
+ {
52
+ "topic": "orders/delete",
53
+ "description": "Triggered when an order is deleted",
54
+ "resource": "orders",
55
+ "required_scope": "read_orders"
56
+ },
57
+ {
58
+ "topic": "orders/edited",
59
+ "description": "Triggered when an order is edited",
60
+ "resource": "orders",
61
+ "required_scope": "read_orders"
62
+ },
63
+ {
64
+ "topic": "products/create",
65
+ "description": "Triggered when a new product is created",
66
+ "resource": "products",
67
+ "required_scope": "read_products"
68
+ },
69
+ {
70
+ "topic": "products/update",
71
+ "description": "Triggered when a product is updated",
72
+ "resource": "products",
73
+ "required_scope": "read_products"
74
+ },
75
+ {
76
+ "topic": "products/delete",
77
+ "description": "Triggered when a product is deleted",
78
+ "resource": "products",
79
+ "required_scope": "read_products"
80
+ },
81
+ {
82
+ "topic": "customers/create",
83
+ "description": "Triggered when a new customer is created",
84
+ "resource": "customers",
85
+ "required_scope": "read_customers"
86
+ },
87
+ {
88
+ "topic": "customers/update",
89
+ "description": "Triggered when customer information is updated",
90
+ "resource": "customers",
91
+ "required_scope": "read_customers"
92
+ },
93
+ {
94
+ "topic": "customers/delete",
95
+ "description": "Triggered when a customer is deleted",
96
+ "resource": "customers",
97
+ "required_scope": "read_customers"
98
+ },
99
+ {
100
+ "topic": "collections/create",
101
+ "description": "Triggered when a new collection is created",
102
+ "resource": "collections",
103
+ "required_scope": "read_products"
104
+ },
105
+ {
106
+ "topic": "collections/update",
107
+ "description": "Triggered when a collection is updated",
108
+ "resource": "collections",
109
+ "required_scope": "read_products"
110
+ },
111
+ {
112
+ "topic": "collections/delete",
113
+ "description": "Triggered when a collection is deleted",
114
+ "resource": "collections",
115
+ "required_scope": "read_products"
116
+ },
117
+ {
118
+ "topic": "loyalty/points_credited",
119
+ "description": "Triggered when a customer's loyalty point balance increases (earn, admin credit, refund/reversal credit)",
120
+ "resource": "loyalty",
121
+ "required_scope": "read_loyalty"
122
+ },
123
+ {
124
+ "topic": "loyalty/points_debited",
125
+ "description": "Triggered when a customer's loyalty point balance decreases (redeem, admin debit, cancellation/reversal debit, expiry)",
126
+ "resource": "loyalty",
127
+ "required_scope": "read_loyalty"
128
+ },
129
+ {
130
+ "topic": "reviews/create",
131
+ "description": "Triggered when a customer submits a product review",
132
+ "resource": "reviews",
133
+ "required_scope": "read_products"
134
+ },
135
+ {
136
+ "topic": "reviews/update",
137
+ "description": "Triggered when a merchant moderates or edits a review (hide, show, archive, edit)",
138
+ "resource": "reviews",
139
+ "required_scope": "read_products"
140
+ },
141
+ {
142
+ "topic": "app/uninstalled",
143
+ "description": "Fired when the app is uninstalled by a merchant",
144
+ "resource": "app",
145
+ "required_scope": null
146
+ }
147
+ ]
148
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAyCpE;;GAEG;AACH,wBAAgB,eAAe,IAAI,SAAS,CA2F3C"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAmDpE;;GAEG;AACH,wBAAgB,eAAe,IAAI,SAAS,CAqH3C"}
package/dist/server.js CHANGED
@@ -4,6 +4,7 @@ import { allDevTools } from './tools/index.js';
4
4
  import { logger } from './utils/logger.js';
5
5
  import { checkToolPrerequisites } from './services/tool-guard.js';
6
6
  import { recordToolSuccess } from './services/session-state.js';
7
+ import { setElicitationServer } from './services/elicitation.js';
7
8
  const DEV_SERVER_INSTRUCTIONS = `You are a developer assistant for the Ratio Agentic Ecosystem — a B2B app marketplace where developers build agents (apps) that extend merchant store functionality. Merchants discover and install these agents to access their store data (orders, products, customers, etc.).
8
9
 
9
10
  FIRST RESPONSE BEHAVIOR (non-negotiable):
@@ -19,17 +20,26 @@ CONVERSATION FLOW — guide the developer step by step:
19
20
  4. CALLBACK URL: Ask if they have their own callback URL or need Hookdeck for local development.
20
21
  - Own URL → use it as redirect_uri in create_app
21
22
  - No URL → call setup_hookdeck first to provision a tunnel
22
- 5. CREATE APP: Call create_app with confirmed categories and callback URL.
23
+ 5. CREATE APP: The SERVER owns the configuration wizard — distribution type (public/private), app kind, merchant whitelist (private only) and categories are collected FROM THE DEVELOPER, never decided by you. Any app_type / app_kind / merchant_ids / category_ids you pass are treated only as suggested defaults the developer confirms or changes.
24
+ - If the client supports elicitation: create_app asks the developer directly via forms and creates the app in one call.
25
+ - Otherwise: create_app returns status "awaiting_developer_input" with a questions list. Present those questions to the developer VERBATIM, WAIT for their answers, then call create_app again with the same name/description plus their answers. Partial answers are fine — remaining questions come back until everything is answered.
26
+ Key facts for the conversation: PUBLIC = marketplace, any merchant, admin review. PRIVATE = whitelisted merchants only, AUTO-PUBLISHES on build upload (no review/publish step; merchant IDs required). APP KIND: "embedded" (iframe frontend, built + zipped + uploaded) or "no_ui" (backend-only — no scaffold/build/zip steps); "extension" / "web_pixel" / "flow" can be created but their manifest/bundle upload is portal-only for now. Use lookup_docs "private app" for the grounded public/private difference.
23
27
  6. SCOPES: Based on what they want to build, call gather_requirements with their description. It recommends scopes. Then call validate_scopes to verify them. ONLY present scopes that validate_scopes confirms as valid.
24
28
  7. CONFIRM SCOPES: Call define_app_requirements with confirmed=false to show a preview. Discuss with developer. Then call with confirmed=true to save.
25
- 8. WEBHOOKS: After scopes are confirmed, recommend relevant webhook events. Currently only order and product webhooks are supported. Ask if they want real-time event handling.
26
- 9. BUILD PIPELINE: scaffold_frontend build_frontend validate_build create_submission_zip upload_build submit_for_review
27
- 10. AFTER APPROVAL: scaffold_backendgenerate_api_routes (auto-generates backend code filtered by the developer's selected scopes)
29
+ 8. WEBHOOKS: After scopes are confirmed, recommend relevant webhook events (call get_webhook_topics — it filters by the confirmed scopes). Supported categories: orders, products, customers, collections, loyalty, reviews (+ app/uninstalled). Ask if they want real-time event handling.
30
+ 9. PIPELINE depends on app_kind and app_type (follow the next_steps in tool responses and get_status):
31
+ - embedded: scaffold_frontendbuild_frontend validate_build create_submission_zip upload_build
32
+ - no_ui: upload_build directly (NO frontend steps, NO zip — the version is created file-less)
33
+ - public: then submit_for_review → wait for admin approval → publish_app
34
+ - private: upload_build AUTO-PUBLISHES — skip submit/publish entirely
35
+ 10. AFTER PUBLISH: scaffold_backend → generate_api_routes (auto-generates backend code filtered by the developer's selected scopes)
36
+ 11. SKIPPED RESPONSES: When a tool returns {"skipped": true}, that step does not exist for this app's flow — this is NOT an error. Read "next_step" and continue there. Never retry a skipped tool.
28
37
 
29
38
  CRITICAL RULES:
30
39
  - ANTI-HALLUCINATION: When you don't know something about the Ratio platform, call lookup_docs BEFORE answering. NEVER guess or make up platform capabilities, API endpoints, scopes, or features.
31
40
  - If lookup_docs returns no results, tell the developer honestly: "I don't have information from Ratio about this. Would you like me to answer in a generic way?"
32
41
  - BLOCKED TOOLS: When a tool returns an error with "blocked": true, read the "chain" field — it tells you the exact sequence of tools to call. Never retry a blocked tool without completing its prerequisites first.
42
+ - AWAITING INPUT: When a tool returns status "awaiting_developer_input", the operation did NOT happen. Relay the "questions" to the developer verbatim, WAIT for their reply, and only then call the tool again with their answers. NEVER invent answers to skip this step.
33
43
  - DEVELOPER CONFIRMATION: Always show options and get explicit confirmation before proceeding (categories, scopes, callback URL choice). Never assume choices on behalf of the developer.
34
44
  - SCOPE VALIDATION: Always call validate_scopes before presenting any scope to the developer. Never show unvalidated scopes.
35
45
  - OAUTH: OAuth is MERCHANT-INITIATED — the merchant clicks "Install" on the marketplace, which triggers the /callback endpoint. NEVER construct OAuth URLs or manual token exchange code.
@@ -46,6 +56,9 @@ export function createDevServer() {
46
56
  }, {
47
57
  instructions: DEV_SERVER_INSTRUCTIONS,
48
58
  });
59
+ // Elicitation: tools can ask the human developer for input mid-call
60
+ // (app kind, distribution type) when the client supports it.
61
+ setElicitationServer(server);
49
62
  // Register all tools
50
63
  for (const tool of allDevTools) {
51
64
  // Pass Zod shape directly — MCP SDK handles Zod-to-JSON conversion internally
@@ -54,9 +67,29 @@ export function createDevServer() {
54
67
  logger.toolCall(tool.name, args);
55
68
  const startTime = Date.now();
56
69
  // ── Guard: check prerequisites before executing ──────────────
57
- const guard = checkToolPrerequisites(tool.name);
70
+ const guard = await checkToolPrerequisites(tool.name);
58
71
  if (!guard.allowed) {
59
72
  const duration = Date.now() - startTime;
73
+ // Skipped = the step doesn't exist for this app's flow profile
74
+ // (e.g. submit_for_review on a private app, scaffold_frontend on no_ui).
75
+ // Informational, NOT an error — the LLM should move to next_step.
76
+ if (guard.skipped) {
77
+ logger.info(`SKIPPED ${tool.name} (${duration}ms): ${guard.message}`);
78
+ return {
79
+ content: [
80
+ {
81
+ type: 'text',
82
+ text: JSON.stringify({
83
+ skipped: true,
84
+ message: guard.message,
85
+ next_step: guard.nextStep,
86
+ tool: tool.name,
87
+ hint: guard.hint,
88
+ }, null, 2),
89
+ },
90
+ ],
91
+ };
92
+ }
60
93
  logger.info(`BLOCKED ${tool.name} (${duration}ms): ${guard.message}`);
61
94
  return {
62
95
  content: [
@@ -67,6 +100,7 @@ export function createDevServer() {
67
100
  blocked: true,
68
101
  message: guard.message,
69
102
  required_tools: guard.requiredTools,
103
+ chain: guard.chain,
70
104
  tool: tool.name,
71
105
  hint: `Please call ${guard.requiredTools?.join(' or ')} first, then retry ${tool.name}.`,
72
106
  }, null, 2),
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * App facts — the platform is the source of truth for app state.
3
+ *
4
+ * Guards used to trust only the local tool-call history, which broke whenever
5
+ * the platform had an alternate path to a state (e.g. private apps auto-publish
6
+ * on upload, or the MCP server restarted mid-flow). getAppFacts() resolves the
7
+ * real state from GET /applications/:id, with a short TTL cache, and degrades
8
+ * gracefully to session/requirements-store data when the network call fails.
9
+ */
10
+ export interface AppFacts {
11
+ appId: string;
12
+ /** Application status: draft | submitted | in_review | approved | rejected | published | ... */
13
+ status?: string;
14
+ /** Latest version status (versions are newest-first in the API response) */
15
+ versionStatus?: string;
16
+ latestVersionId?: string;
17
+ appType?: string;
18
+ appKind?: string;
19
+ /** Where the facts came from — 'platform' | 'cache' | 'local' */
20
+ source: 'platform' | 'cache' | 'local';
21
+ }
22
+ /** Effective status: version status wins when the app-level status lags behind
23
+ * (the backend's approveVersion updates the VERSION but leaves the app 'submitted'). */
24
+ export declare function effectiveStatus(facts: AppFacts): string | undefined;
25
+ /**
26
+ * Resolve current app facts. Platform first (cached for 30s), local fallback.
27
+ * Never throws — guards must keep working offline/pre-auth.
28
+ */
29
+ export declare function getAppFacts(appId: string, opts?: {
30
+ force?: boolean;
31
+ }): Promise<AppFacts>;
32
+ /** Drop the cached facts for an app (call after mutations like upload/submit/publish). */
33
+ export declare function invalidateAppFacts(appId: string): void;
34
+ //# sourceMappingURL=app-state-sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-state-sync.d.ts","sourceRoot":"","sources":["../../src/services/app-state-sync.ts"],"names":[],"mappings":"AAKA;;;;;;;;GAQG;AAEH,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,gGAAgG;IAChG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,MAAM,EAAE,UAAU,GAAG,OAAO,GAAG,OAAO,CAAC;CACxC;AAKD;yFACyF;AACzF,wBAAgB,eAAe,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,CASnE;AAgCD;;;GAGG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAqC9F;AAED,0FAA0F;AAC1F,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAEtD"}
@@ -0,0 +1,85 @@
1
+ import { developerApiRequest, getDeveloperId } from '../api/developer.js';
2
+ import { getRequirements } from '../store/requirements-store.js';
3
+ import { getSession, getAppState, updateAppContext } from './session-state.js';
4
+ import { logger } from '../utils/logger.js';
5
+ const TTL_MS = 30_000;
6
+ const cache = new Map();
7
+ /** Effective status: version status wins when the app-level status lags behind
8
+ * (the backend's approveVersion updates the VERSION but leaves the app 'submitted'). */
9
+ export function effectiveStatus(facts) {
10
+ const { status, versionStatus } = facts;
11
+ if ((status === 'submitted' || status === 'in_review') &&
12
+ (versionStatus === 'approved' || versionStatus === 'published')) {
13
+ return versionStatus;
14
+ }
15
+ return status;
16
+ }
17
+ function localFacts(appId) {
18
+ const appState = getAppState(appId);
19
+ const session = getSession();
20
+ const requirements = getRequirements(appId);
21
+ const ctx = appState?.context ?? {};
22
+ return {
23
+ appId,
24
+ status: ctx.appPublished || session.context.appPublished
25
+ ? 'published'
26
+ : ctx.appApproved || session.context.appApproved
27
+ ? 'approved'
28
+ : undefined,
29
+ appType: ctx.appType ?? requirements?.app_type,
30
+ appKind: ctx.appKind ?? requirements?.app_kind,
31
+ latestVersionId: ctx.latestVersionId ?? session.context.latestVersionId,
32
+ source: 'local',
33
+ };
34
+ }
35
+ function syncSessionFromFacts(facts) {
36
+ const eff = effectiveStatus(facts);
37
+ updateAppContext(facts.appId, {
38
+ ...(facts.appType ? { appType: facts.appType } : {}),
39
+ ...(facts.appKind ? { appKind: facts.appKind } : {}),
40
+ ...(facts.latestVersionId ? { latestVersionId: facts.latestVersionId } : {}),
41
+ ...(eff === 'approved' || eff === 'published' ? { appApproved: true } : {}),
42
+ ...(eff === 'published' ? { appPublished: true } : {}),
43
+ });
44
+ }
45
+ /**
46
+ * Resolve current app facts. Platform first (cached for 30s), local fallback.
47
+ * Never throws — guards must keep working offline/pre-auth.
48
+ */
49
+ export async function getAppFacts(appId, opts) {
50
+ const cached = cache.get(appId);
51
+ if (!opts?.force && cached && Date.now() - cached.fetchedAt < TTL_MS) {
52
+ return { ...cached.facts, source: 'cache' };
53
+ }
54
+ // Not authenticated yet → platform lookup is impossible; use local state.
55
+ if (!getDeveloperId())
56
+ return localFacts(appId);
57
+ try {
58
+ const response = await developerApiRequest('GET', `/applications/${appId}`);
59
+ const data = (response?.['data'] ?? response);
60
+ const versions = data?.['versions'];
61
+ const latestVersion = versions?.[0];
62
+ const facts = {
63
+ appId,
64
+ status: data?.['status']?.toLowerCase(),
65
+ versionStatus: latestVersion?.['status']?.toLowerCase(),
66
+ latestVersionId: latestVersion?.['id'] ? String(latestVersion['id']) : undefined,
67
+ appType: (data?.['appType'] ?? data?.['app_type']),
68
+ appKind: (data?.['appKind'] ?? data?.['app_kind']),
69
+ source: 'platform',
70
+ };
71
+ cache.set(appId, { facts, fetchedAt: Date.now() });
72
+ syncSessionFromFacts(facts);
73
+ logger.info(`[app-state-sync] ${appId}: status=${facts.status}, versionStatus=${facts.versionStatus}, appType=${facts.appType}, appKind=${facts.appKind}`);
74
+ return facts;
75
+ }
76
+ catch (err) {
77
+ logger.warn(`[app-state-sync] Platform lookup failed for ${appId} (${err instanceof Error ? err.message : err}) — using local state`);
78
+ return localFacts(appId);
79
+ }
80
+ }
81
+ /** Drop the cached facts for an app (call after mutations like upload/submit/publish). */
82
+ export function invalidateAppFacts(appId) {
83
+ cache.delete(appId);
84
+ }
85
+ //# sourceMappingURL=app-state-sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-state-sync.js","sourceRoot":"","sources":["../../src/services/app-state-sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function setElicitationServer(server: McpServer): void;
3
+ export declare function isElicitationSupported(): boolean;
4
+ export interface EnumChoice {
5
+ value: string;
6
+ title: string;
7
+ description?: string;
8
+ }
9
+ export type ElicitOutcome<T> = {
10
+ kind: 'answered';
11
+ value: T;
12
+ } | {
13
+ kind: 'declined';
14
+ } | {
15
+ kind: 'unsupported';
16
+ };
17
+ /**
18
+ * Ask the user to pick one option from a list. Returns 'unsupported' when the
19
+ * client can't render elicitation — the caller must then fall back to
20
+ * instructing the LLM to ask in chat.
21
+ */
22
+ export declare function elicitChoice(message: string, fieldName: string, fieldTitle: string, choices: EnumChoice[]): Promise<ElicitOutcome<string>>;
23
+ /** Ask the user for free text (e.g. comma-separated merchant IDs). */
24
+ export declare function elicitText(message: string, fieldName: string, fieldTitle: string, description?: string): Promise<ElicitOutcome<string>>;
25
+ //# sourceMappingURL=elicitation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elicitation.d.ts","sourceRoot":"","sources":["../../src/services/elicitation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAwBzE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAE5D;AAED,wBAAgB,sBAAsB,IAAI,OAAO,CAOhD;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,aAAa,CAAC,CAAC,IACvB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GACpB;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,CAAC;AAE5B;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,UAAU,EAAE,GACpB,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAmChC;AAED,sEAAsE;AACtE,wBAAsB,UAAU,CAC9B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CA2BhC"}