@restforgejs/mcp-server 1.2.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 (135) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +149 -0
  3. package/dist/index.d.ts +2 -0
  4. package/dist/index.js +7 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/lib/env-parser.d.ts +30 -0
  7. package/dist/lib/env-parser.js +150 -0
  8. package/dist/lib/env-parser.js.map +1 -0
  9. package/dist/lib/exec.d.ts +29 -0
  10. package/dist/lib/exec.js +38 -0
  11. package/dist/lib/exec.js.map +1 -0
  12. package/dist/server.d.ts +1 -0
  13. package/dist/server.js +220 -0
  14. package/dist/server.js.map +1 -0
  15. package/dist/tools/codegen/create-dashboard.d.ts +2 -0
  16. package/dist/tools/codegen/create-dashboard.js +256 -0
  17. package/dist/tools/codegen/create-dashboard.js.map +1 -0
  18. package/dist/tools/codegen/create-endpoint.d.ts +2 -0
  19. package/dist/tools/codegen/create-endpoint.js +263 -0
  20. package/dist/tools/codegen/create-endpoint.js.map +1 -0
  21. package/dist/tools/codegen/dbschema-generate-ddl.d.ts +2 -0
  22. package/dist/tools/codegen/dbschema-generate-ddl.js +187 -0
  23. package/dist/tools/codegen/dbschema-generate-ddl.js.map +1 -0
  24. package/dist/tools/codegen/dbschema-init.d.ts +2 -0
  25. package/dist/tools/codegen/dbschema-init.js +158 -0
  26. package/dist/tools/codegen/dbschema-init.js.map +1 -0
  27. package/dist/tools/codegen/dbschema-introspect.d.ts +2 -0
  28. package/dist/tools/codegen/dbschema-introspect.js +241 -0
  29. package/dist/tools/codegen/dbschema-introspect.js.map +1 -0
  30. package/dist/tools/codegen/dbschema-migrate.d.ts +2 -0
  31. package/dist/tools/codegen/dbschema-migrate.js +219 -0
  32. package/dist/tools/codegen/dbschema-migrate.js.map +1 -0
  33. package/dist/tools/codegen/dbschema-models.d.ts +2 -0
  34. package/dist/tools/codegen/dbschema-models.js +146 -0
  35. package/dist/tools/codegen/dbschema-models.js.map +1 -0
  36. package/dist/tools/codegen/dbschema-validate.d.ts +2 -0
  37. package/dist/tools/codegen/dbschema-validate.js +153 -0
  38. package/dist/tools/codegen/dbschema-validate.js.map +1 -0
  39. package/dist/tools/codegen/describe-table.d.ts +2 -0
  40. package/dist/tools/codegen/describe-table.js +259 -0
  41. package/dist/tools/codegen/describe-table.js.map +1 -0
  42. package/dist/tools/codegen/diff-payload.d.ts +2 -0
  43. package/dist/tools/codegen/diff-payload.js +165 -0
  44. package/dist/tools/codegen/diff-payload.js.map +1 -0
  45. package/dist/tools/codegen/generate-payload.d.ts +2 -0
  46. package/dist/tools/codegen/generate-payload.js +145 -0
  47. package/dist/tools/codegen/generate-payload.js.map +1 -0
  48. package/dist/tools/codegen/get-dashboard-catalog.d.ts +2 -0
  49. package/dist/tools/codegen/get-dashboard-catalog.js +213 -0
  50. package/dist/tools/codegen/get-dashboard-catalog.js.map +1 -0
  51. package/dist/tools/codegen/get-dbschema-catalog.d.ts +2 -0
  52. package/dist/tools/codegen/get-dbschema-catalog.js +244 -0
  53. package/dist/tools/codegen/get-dbschema-catalog.js.map +1 -0
  54. package/dist/tools/codegen/get-field-validation-catalog.d.ts +2 -0
  55. package/dist/tools/codegen/get-field-validation-catalog.js +186 -0
  56. package/dist/tools/codegen/get-field-validation-catalog.js.map +1 -0
  57. package/dist/tools/codegen/get-query-declarative-catalog.d.ts +2 -0
  58. package/dist/tools/codegen/get-query-declarative-catalog.js +200 -0
  59. package/dist/tools/codegen/get-query-declarative-catalog.js.map +1 -0
  60. package/dist/tools/codegen/index.d.ts +2 -0
  61. package/dist/tools/codegen/index.js +43 -0
  62. package/dist/tools/codegen/index.js.map +1 -0
  63. package/dist/tools/codegen/list-tables.d.ts +2 -0
  64. package/dist/tools/codegen/list-tables.js +220 -0
  65. package/dist/tools/codegen/list-tables.js.map +1 -0
  66. package/dist/tools/codegen/sync-payload.d.ts +2 -0
  67. package/dist/tools/codegen/sync-payload.js +177 -0
  68. package/dist/tools/codegen/sync-payload.js.map +1 -0
  69. package/dist/tools/codegen/validate-dashboard-payload.d.ts +2 -0
  70. package/dist/tools/codegen/validate-dashboard-payload.js +239 -0
  71. package/dist/tools/codegen/validate-dashboard-payload.js.map +1 -0
  72. package/dist/tools/codegen/validate-payload.d.ts +2 -0
  73. package/dist/tools/codegen/validate-payload.js +166 -0
  74. package/dist/tools/codegen/validate-payload.js.map +1 -0
  75. package/dist/tools/codegen/validate-sql.d.ts +2 -0
  76. package/dist/tools/codegen/validate-sql.js +270 -0
  77. package/dist/tools/codegen/validate-sql.js.map +1 -0
  78. package/dist/tools/health/index.d.ts +2 -0
  79. package/dist/tools/health/index.js +5 -0
  80. package/dist/tools/health/index.js.map +1 -0
  81. package/dist/tools/health/ping.d.ts +2 -0
  82. package/dist/tools/health/ping.js +68 -0
  83. package/dist/tools/health/ping.js.map +1 -0
  84. package/dist/tools/runtime/check-launcher-exists.d.ts +2 -0
  85. package/dist/tools/runtime/check-launcher-exists.js +111 -0
  86. package/dist/tools/runtime/check-launcher-exists.js.map +1 -0
  87. package/dist/tools/runtime/check-status.d.ts +2 -0
  88. package/dist/tools/runtime/check-status.js +417 -0
  89. package/dist/tools/runtime/check-status.js.map +1 -0
  90. package/dist/tools/runtime/detect-config.d.ts +2 -0
  91. package/dist/tools/runtime/detect-config.js +130 -0
  92. package/dist/tools/runtime/detect-config.js.map +1 -0
  93. package/dist/tools/runtime/detect-project.d.ts +2 -0
  94. package/dist/tools/runtime/detect-project.js +132 -0
  95. package/dist/tools/runtime/detect-project.js.map +1 -0
  96. package/dist/tools/runtime/generate-launcher.d.ts +2 -0
  97. package/dist/tools/runtime/generate-launcher.js +438 -0
  98. package/dist/tools/runtime/generate-launcher.js.map +1 -0
  99. package/dist/tools/runtime/index.d.ts +2 -0
  100. package/dist/tools/runtime/index.js +15 -0
  101. package/dist/tools/runtime/index.js.map +1 -0
  102. package/dist/tools/runtime/validate-preflight.d.ts +2 -0
  103. package/dist/tools/runtime/validate-preflight.js +209 -0
  104. package/dist/tools/runtime/validate-preflight.js.map +1 -0
  105. package/dist/tools/setup/create-folder.d.ts +2 -0
  106. package/dist/tools/setup/create-folder.js +138 -0
  107. package/dist/tools/setup/create-folder.js.map +1 -0
  108. package/dist/tools/setup/get-config-schema.d.ts +2 -0
  109. package/dist/tools/setup/get-config-schema.js +158 -0
  110. package/dist/tools/setup/get-config-schema.js.map +1 -0
  111. package/dist/tools/setup/get-init-template.d.ts +2 -0
  112. package/dist/tools/setup/get-init-template.js +130 -0
  113. package/dist/tools/setup/get-init-template.js.map +1 -0
  114. package/dist/tools/setup/index.d.ts +2 -0
  115. package/dist/tools/setup/index.js +21 -0
  116. package/dist/tools/setup/index.js.map +1 -0
  117. package/dist/tools/setup/init-config.d.ts +2 -0
  118. package/dist/tools/setup/init-config.js +120 -0
  119. package/dist/tools/setup/init-config.js.map +1 -0
  120. package/dist/tools/setup/install-package.d.ts +2 -0
  121. package/dist/tools/setup/install-package.js +133 -0
  122. package/dist/tools/setup/install-package.js.map +1 -0
  123. package/dist/tools/setup/read-env.d.ts +2 -0
  124. package/dist/tools/setup/read-env.js +138 -0
  125. package/dist/tools/setup/read-env.js.map +1 -0
  126. package/dist/tools/setup/update-env.d.ts +2 -0
  127. package/dist/tools/setup/update-env.js +176 -0
  128. package/dist/tools/setup/update-env.js.map +1 -0
  129. package/dist/tools/setup/validate-config.d.ts +2 -0
  130. package/dist/tools/setup/validate-config.js +138 -0
  131. package/dist/tools/setup/validate-config.js.map +1 -0
  132. package/dist/tools/setup/write-env.d.ts +2 -0
  133. package/dist/tools/setup/write-env.js +168 -0
  134. package/dist/tools/setup/write-env.js.map +1 -0
  135. package/package.json +60 -0
@@ -0,0 +1,145 @@
1
+ import { z } from 'zod';
2
+ import { access } from 'node:fs/promises';
3
+ import { resolve, join } from 'node:path';
4
+ import { execProcess } from '../../lib/exec.js';
5
+ export function registerCodegenGeneratePayload(server) {
6
+ server.registerTool('codegen_generate_payload', {
7
+ title: 'Generate Payload',
8
+ description: `Generate a payload spec file (metadata, fields, action specs) from a database table by introspecting its schema via restforge.
9
+
10
+ USE WHEN:
11
+ - The user asks to generate a payload, payload spec, or payload metadata file from a database table
12
+ - The user asks things like "buatkan payload dari table X", "generate payload guest_book", "scan schema table to JSON", "create payload for endpoint generation"
13
+ - The user wants to "introspect" or "scan" a database table into a JSON spec
14
+ - Starting CLI codegen workflow after the project config has been validated
15
+ - Re-generating payload after a schema change in the database
16
+
17
+ DO NOT USE FOR:
18
+ - Filling in credentials in db-connection.env -> use 'setup_write_env'
19
+ - Validating config before generating payload -> use 'setup_validate_config'
20
+ - Creating the project / endpoint code from a payload -> that is the next CLI step (will be wrapped in a future tool, not yet available)
21
+
22
+ This tool runs: npx restforge payload --table=<table> --config=<config> in the given cwd.
23
+ The CLI connects to the database described in the config file, reads the table schema,
24
+ and writes a payload JSON file (e.g. table 'guest_book' -> 'guest-book.json' with underscore
25
+ mapped to hyphen). The payload file is the input for the next codegen step (project + endpoint creation).
26
+
27
+ Preconditions:
28
+ - The project must have @restforgejs/platform installed in node_modules.
29
+ - The config file (default 'db-connection.env') must exist in the project and contain valid
30
+ database credentials. This tool does not pre-check that — if the CLI fails, the failure response
31
+ will surface the underlying cause.
32
+
33
+ PRESENTATION GUIDANCE:
34
+ - Match the user's language. If the user writes in Indonesian, respond in Indonesian.
35
+ - Never mention internal tool names in the reply to the user. Describe actions by what they do (e.g. "install the package", "fill in the credentials", "generate the payload").
36
+ - Speak in plain language. Summarise the result; do not paste raw CLI output unless the user explicitly asks.
37
+ - When a precondition is not met, frame it as a question or next-step suggestion rather than an error.`,
38
+ inputSchema: {
39
+ cwd: z
40
+ .string()
41
+ .min(1)
42
+ .describe('Absolute path of the project folder (must contain node_modules/@restforgejs/platform and the config file)'),
43
+ table: z
44
+ .string()
45
+ .min(1)
46
+ .describe('Name of the database table to introspect (e.g. guest_book)'),
47
+ config: z
48
+ .string()
49
+ .min(1)
50
+ .default('db-connection.env')
51
+ .describe('Config file name (relative to project) used by the CLI to connect to the database'),
52
+ },
53
+ annotations: {
54
+ title: 'Generate Payload',
55
+ readOnlyHint: false,
56
+ idempotentHint: false,
57
+ },
58
+ }, async ({ cwd, table, config }) => {
59
+ const projectCwd = resolve(cwd);
60
+ // Precondition check: @restforgejs/platform must be present in node_modules.
61
+ // Treated as a non-error precondition per the authoring guide §3.4.
62
+ try {
63
+ await access(join(projectCwd, 'node_modules', '@restforgejs', 'platform'));
64
+ }
65
+ catch {
66
+ return {
67
+ content: [
68
+ {
69
+ type: 'text',
70
+ text: `Precondition not met: the RESTForge package is not installed in this project.
71
+
72
+ Project path: ${projectCwd}
73
+ Expected location: node_modules/@restforgejs/platform
74
+ Requested table: ${table}
75
+ Requested config: ${config}
76
+
77
+ For the assistant:
78
+ - The user needs to install the RESTForge package before a payload can be generated from a table schema.
79
+ - Use the appropriate package-installation tool to do this, then retry generating the payload.
80
+ - When explaining to the user, say something like "the RESTForge package isn't installed yet — should I install it first?". Do not mention internal tool names.`,
81
+ },
82
+ ],
83
+ isError: false, // per §3.4
84
+ };
85
+ }
86
+ const result = await execProcess('npx', ['restforge', 'payload', 'generate', `--table=${table}`, `--config=${config}`], { cwd: projectCwd, timeout: 30_000 });
87
+ // CLI failure: real error per §3.4; structured per §3.5.
88
+ if (!result.success) {
89
+ return {
90
+ content: [
91
+ {
92
+ type: 'text',
93
+ text: `Failed to generate payload.
94
+
95
+ Project path: ${projectCwd}
96
+ Table: ${table}
97
+ Config: ${config}
98
+ Command: ${result.command}
99
+ Exit code: ${result.exitCode}
100
+
101
+ --- CLI output ---
102
+ stdout:
103
+ ${result.stdout}
104
+
105
+ stderr:
106
+ ${result.stderr}
107
+ --- end CLI output ---
108
+
109
+ For the assistant:
110
+ - Tell the user that generating the payload did not complete successfully.
111
+ - Summarise the likely cause from the CLI output in plain language (common causes: the config file is missing or has incomplete credentials, the database is unreachable, or the requested table does not exist in the database). Do not paste the raw stdout/stderr unless the user explicitly asks.
112
+ - Offer to retry once the underlying issue is resolved. Do not mention internal tool names.`,
113
+ },
114
+ ],
115
+ isError: true, // per §3.4
116
+ };
117
+ }
118
+ // Success: one-line summary + labeled facts + fenced raw output per §3.5.
119
+ // The CLI itself prints the output filename in stdout; we do not try to re-derive it here.
120
+ return {
121
+ content: [
122
+ {
123
+ type: 'text',
124
+ text: `Payload generated successfully.
125
+
126
+ Project path: ${projectCwd}
127
+ Table: ${table}
128
+ Config: ${config}
129
+ Output: payload file generated by restforge (see CLI output below for the exact filename; underscores in the table name are mapped to hyphens, e.g. 'guest_book' -> 'guest-book.json').
130
+
131
+ --- CLI output ---
132
+ ${result.stdout}
133
+ --- end CLI output ---
134
+
135
+ For the assistant:
136
+ - Confirm to the user that the payload spec for the requested table is ready.
137
+ - Mention in plain language that the payload is the input for the next codegen step (generating the project and endpoint code from this payload). That follow-up step is part of the CLI workflow but is not wrapped as a tool yet.
138
+ - Suggest that the user can review or edit the generated payload file before the next step.
139
+ - Keep the reply concise. Do not paste the raw CLI output unless the user explicitly asks. Do not mention internal tool names.`,
140
+ },
141
+ ],
142
+ };
143
+ });
144
+ }
145
+ //# sourceMappingURL=generate-payload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-payload.js","sourceRoot":"","sources":["../../../src/tools/codegen/generate-payload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,UAAU,8BAA8B,CAAC,MAAiB;IAC9D,MAAM,CAAC,YAAY,CACjB,0BAA0B,EAC1B;QACE,KAAK,EAAE,kBAAkB;QACzB,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uGA6BoF;QACjG,WAAW,EAAE;YACX,GAAG,EAAE,CAAC;iBACH,MAAM,EAAE;iBACR,GAAG,CAAC,CAAC,CAAC;iBACN,QAAQ,CAAC,2GAA2G,CAAC;YACxH,KAAK,EAAE,CAAC;iBACL,MAAM,EAAE;iBACR,GAAG,CAAC,CAAC,CAAC;iBACN,QAAQ,CAAC,4DAA4D,CAAC;YACzE,MAAM,EAAE,CAAC;iBACN,MAAM,EAAE;iBACR,GAAG,CAAC,CAAC,CAAC;iBACN,OAAO,CAAC,mBAAmB,CAAC;iBAC5B,QAAQ,CAAC,mFAAmF,CAAC;SACjG;QACD,WAAW,EAAE;YACX,KAAK,EAAE,kBAAkB;YACzB,YAAY,EAAE,KAAK;YACnB,cAAc,EAAE,KAAK;SACtB;KACF,EACD,KAAK,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE;QAC/B,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAEhC,6EAA6E;QAC7E,oEAAoE;QACpE,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,EAAE,cAAc,EAAE,UAAU,CAAC,CAAC,CAAC;QAC7E,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE;;gBAEJ,UAAU;;mBAEP,KAAK;oBACJ,MAAM;;;;;gKAKsI;qBACnJ;iBACF;gBACD,OAAO,EAAE,KAAK,EAAE,WAAW;aAC5B,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,WAAW,CAC9B,KAAK,EACL,CAAC,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,KAAK,EAAE,EAAE,YAAY,MAAM,EAAE,CAAC,EAC9E,EAAE,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,CACrC,CAAC;QAEF,yDAAyD;QACzD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE;;gBAEJ,UAAU;SACjB,KAAK;UACJ,MAAM;WACL,MAAM,CAAC,OAAO;aACZ,MAAM,CAAC,QAAQ;;;;EAI1B,MAAM,CAAC,MAAM;;;EAGb,MAAM,CAAC,MAAM;;;;;;4FAM6E;qBAC/E;iBACF;gBACD,OAAO,EAAE,IAAI,EAAE,WAAW;aAC3B,CAAC;QACJ,CAAC;QAED,0EAA0E;QAC1E,2FAA2F;QAC3F,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE;;gBAEF,UAAU;SACjB,KAAK;UACJ,MAAM;;;;EAId,MAAM,CAAC,MAAM;;;;;;;+HAOgH;iBACpH;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerCodegenGetDashboardCatalog(server: McpServer): void;
@@ -0,0 +1,213 @@
1
+ import { z } from 'zod';
2
+ import { access } from 'node:fs/promises';
3
+ import { resolve, join } from 'node:path';
4
+ import { execProcess } from '../../lib/exec.js';
5
+ export function registerCodegenGetDashboardCatalog(server) {
6
+ server.registerTool('codegen_get_dashboard_catalog', {
7
+ title: 'Get Dashboard Catalog',
8
+ description: `Get authoritative JSON catalog of dashboard payload spec (payload shape with discriminator, widget structure with mutex \`query\`/\`queries\`, params contract with allowed types, scalar collapse rules, naming convention with \`dash-\` prefix, URL pattern \`POST /api/{project}/{name}/dashboard\`, file reference convention, placeholder convention with \`:paramName\`).
9
+
10
+ USE WHEN:
11
+ - The user asks about dashboard payload structure, widget definition, or how dashboard endpoints work
12
+ - The user mentions specific dashboard concepts: \`widgets\`, \`params\`, \`query\` vs \`queries\`, scalar collapse, dashboard prefix \`dash-\`
13
+ - Pertanyaan dalam bentuk seperti "bagaimana struktur payload dashboard", "apa beda dashboard dengan endpoint biasa", "kapan pakai query vs queries", "kenapa nama dashboard harus pakai dash-"
14
+ - The user asks about the URL pattern for dashboard endpoints (\`POST /api/{project}/{name}/dashboard\`)
15
+ - The user asks why dashboard names must start with \`dash-\` prefix
16
+ - The user asks about response shape: when is value a scalar, when is it object, when is it array (scalar collapse rules)
17
+ - The user asks about placeholder \`:paramName\` in widget SQL — declaration requirements, escaping (\`::\` Postgres cast)
18
+ - Before authoring a dashboard payload manually (via Write tool) — to ground field naming, allowed/forbidden fields, widget structure
19
+ - Before invoking 'codegen_validate_dashboard_payload' or 'codegen_create_dashboard' — to verify payload conforms to schema
20
+ - The user is unsure whether their use case is a dashboard or a CRUD endpoint
21
+
22
+ DO NOT USE FOR:
23
+ - Validating an actual dashboard payload file -> use 'codegen_validate_dashboard_payload'
24
+ - Generating a dashboard module from a payload -> use 'codegen_create_dashboard'
25
+ - Looking up CRUD payload field validation rules -> use 'codegen_get_field_validation_catalog'
26
+ - Looking up CRUD query declarative spec (\`datatablesQuery\`, \`viewQuery\`, \`viewName\`, \`exportQuery\`, \`detailQuery\`) -> use 'codegen_get_query_declarative_catalog'
27
+ - Generating a CRUD payload from a database table -> use 'codegen_generate_payload'
28
+ - Validating CRUD payload drift against the database -> use 'codegen_validate_payload'
29
+ - Common widget patterns examples (Metric+Donut, Metric+Sparkline, Metric+Goal) — not in catalog scope; refer to the documentationUrl returned in the response
30
+ - Frontend integration examples (Metronic, AdminLTE, etc.) — not in catalog scope; refer to documentationUrl
31
+ - Separation of Concerns rationale for forbidden frontend fields — not in catalog scope; refer to documentationUrl
32
+ - Multi-database SQL dialect adaptation inside widget queries — not in catalog scope; refer to documentationUrl
33
+ - Performance characteristics (Promise.allSettled execution, in-memory SQL embedding) — not in catalog scope; refer to documentationUrl
34
+
35
+ This tool runs: npx restforge dashboard:catalog in the given cwd.
36
+ The catalog is sourced from restforge (single source of truth) so it stays in sync with
37
+ the restforge runtime version installed in the project.
38
+
39
+ PRESENTATION GUIDANCE:
40
+ - Match the user's language. If the user writes in Indonesian, respond in Indonesian.
41
+ - Never mention internal tool names in the reply to the user. Describe actions by what they do (e.g. "look up the dashboard catalog", "edit the dashboard payload", "install the package").
42
+ - Speak in plain language. Summarise the catalog (number of allowed top-level fields, forbidden frontend fields, param types, scalar collapse rules); do not paste the entire JSON unless the user explicitly asks for it.
43
+ - When the user is unsure whether their use case is dashboard or CRUD, briefly explain the discriminator: \`widgets\` array means dashboard (multi-query aggregator), \`tableName\` means CRUD (single-table REST endpoint). They cannot mix.
44
+ - When a precondition is not met (e.g. the package is not installed), frame it as a question or next-step suggestion rather than an error.`,
45
+ inputSchema: {
46
+ cwd: z
47
+ .string()
48
+ .min(1)
49
+ .describe('Absolute path of the project folder (must contain node_modules/@restforgejs/platform)'),
50
+ },
51
+ annotations: {
52
+ title: 'Get Dashboard Catalog',
53
+ readOnlyHint: true,
54
+ idempotentHint: true,
55
+ },
56
+ }, async ({ cwd }) => {
57
+ const projectCwd = resolve(cwd);
58
+ // Precondition check: @restforgejs/platform must be installed before this CLI command can run.
59
+ // Treated as a non-error precondition per the authoring guide §3.4.
60
+ try {
61
+ await access(join(projectCwd, 'node_modules', '@restforgejs', 'platform'));
62
+ }
63
+ catch {
64
+ return {
65
+ content: [
66
+ {
67
+ type: 'text',
68
+ text: `Precondition not met: the RESTForge package is not installed in this project.
69
+
70
+ Project path: ${projectCwd}
71
+ Expected location: node_modules/@restforgejs/platform
72
+
73
+ For the assistant:
74
+ - The dashboard catalog can only be retrieved once the RESTForge package is installed locally.
75
+ - Suggest installing the package first, then retry getting the catalog.
76
+ - When explaining to the user, say something like "the RESTForge package isn't installed yet — should I install it first?". Do not mention internal tool names.`,
77
+ },
78
+ ],
79
+ isError: false, // per §3.4
80
+ };
81
+ }
82
+ // Run subprocess with NODE_ENV=production to suppress legacy banner output
83
+ // (mirrors the pattern used by setup_get_config_schema and other catalog tools).
84
+ const result = await execProcess('npx', ['restforge', 'catalog', 'dashboard'], {
85
+ cwd: projectCwd,
86
+ timeout: 15_000,
87
+ env: { NODE_ENV: 'production' },
88
+ stripFinalNewline: true,
89
+ });
90
+ // CLI failure: real error per §3.4; structured per §3.5.
91
+ if (!result.success) {
92
+ return {
93
+ content: [
94
+ {
95
+ type: 'text',
96
+ text: `Failed to retrieve the dashboard catalog.
97
+
98
+ Project path: ${projectCwd}
99
+ Command: ${result.command}
100
+ Exit code: ${result.exitCode}
101
+
102
+ --- CLI output ---
103
+ stdout:
104
+ ${result.stdout}
105
+
106
+ stderr:
107
+ ${result.stderr}
108
+ --- end CLI output ---
109
+
110
+ For the assistant:
111
+ - Tell the user that the dashboard catalog could not be retrieved.
112
+ - A common cause is an older RESTForge version that does not yet expose this command. If the CLI output mentions an unknown command, suggest upgrading the package as a likely fix.
113
+ - Do not paste the raw stdout/stderr unless the user explicitly asks. Do not mention internal tool names.`,
114
+ },
115
+ ],
116
+ isError: true, // per §3.4
117
+ };
118
+ }
119
+ // Validate JSON output. Parse failure is a real error per §3.4 (CLI succeeded but produced invalid output).
120
+ let parsed;
121
+ try {
122
+ parsed = JSON.parse(result.stdout);
123
+ }
124
+ catch (err) {
125
+ const msg = err instanceof Error ? err.message : String(err);
126
+ return {
127
+ content: [
128
+ {
129
+ type: 'text',
130
+ text: `Failed to parse dashboard catalog JSON.
131
+
132
+ Project path: ${projectCwd}
133
+ Reason: ${msg}
134
+
135
+ --- Raw stdout ---
136
+ ${result.stdout}
137
+ --- end Raw stdout ---
138
+
139
+ For the assistant:
140
+ - The CLI returned output that is not valid JSON.
141
+ - Summarise this to the user in plain language; do not paste the raw stdout unless they explicitly ask.
142
+ - Suggest checking that the installed package version is compatible. Do not mention internal tool names.`,
143
+ },
144
+ ],
145
+ isError: true, // per §3.4
146
+ };
147
+ }
148
+ // Extract summary counts for labeled facts. Use defensive access — if the catalog shape
149
+ // changes upstream, we still produce a sensible response rather than crash.
150
+ const root = (parsed ?? {});
151
+ const summary = (root.summary ?? {});
152
+ const totalAllowedTopLevelFields = typeof summary.totalAllowedTopLevelFields === 'number'
153
+ ? summary.totalAllowedTopLevelFields
154
+ : 'unknown';
155
+ const totalForbiddenFrontendFields = typeof summary.totalForbiddenFrontendFields === 'number'
156
+ ? summary.totalForbiddenFrontendFields
157
+ : 'unknown';
158
+ const totalParamTypes = typeof summary.totalParamTypes === 'number' ? summary.totalParamTypes : 'unknown';
159
+ const totalScalarCollapseRules = typeof summary.totalScalarCollapseRules === 'number'
160
+ ? summary.totalScalarCollapseRules
161
+ : 'unknown';
162
+ const sourceLabel = typeof root.source === 'string' ? root.source : 'dashboard-catalog';
163
+ // Re-stringify for consistent pretty formatting (independent of CLI --pretty flag).
164
+ const prettyJson = JSON.stringify(parsed, null, 2);
165
+ // Success: one-line summary + labeled facts + fenced JSON output per §3.5.
166
+ return {
167
+ content: [
168
+ {
169
+ type: 'text',
170
+ text: `Dashboard catalog retrieved successfully.
171
+
172
+ Project path: ${projectCwd}
173
+ Source: restforge (${sourceLabel}) — single source of truth for the installed runtime version
174
+ totalAllowedTopLevelFields: ${totalAllowedTopLevelFields}
175
+ totalForbiddenFrontendFields: ${totalForbiddenFrontendFields}
176
+ totalParamTypes: ${totalParamTypes}
177
+ totalScalarCollapseRules: ${totalScalarCollapseRules}
178
+
179
+ --- Dashboard Catalog (JSON) ---
180
+ ${prettyJson}
181
+ --- end Dashboard Catalog (JSON) ---
182
+
183
+ For the assistant:
184
+ - Confirm to the user that the catalog is available. Summarise in plain language: how many allowed top-level fields, forbidden frontend fields, param types, and scalar collapse rules are included.
185
+ - Do not paste the full JSON block unless the user explicitly asks for it. If the user only asked to "see the catalog", offer to drill into a specific aspect (widget structure, params contract, naming convention, scalar collapse rules) instead of dumping everything.
186
+ - Use this catalog as ground truth when the user is:
187
+ * Asking "how is a dashboard payload structured?"
188
+ * Authoring a dashboard payload manually (via the Write tool)
189
+ * Confused between dashboard payload (\`widgets\`) and CRUD payload (\`tableName\`)
190
+ * Asking about the \`dash-\` prefix in dashboard names
191
+ * Asking when to use \`query\` vs \`queries\`
192
+ * Asking about response shape (scalar collapse rules)
193
+ * Asking about \`:paramName\` placeholders in widget SQL
194
+ - Filter notes for catalog consumers (avoid common pitfalls):
195
+ * \`payloadShape.discriminator\` is the way to tell whether a payload is a dashboard or a CRUD endpoint. \`widgets\` present means dashboard. \`tableName\` present means CRUD. A payload with both is rejected by the validator.
196
+ * \`widgetSpec.exclusiveQueryFields\` is a mutex rule: every widget MUST declare exactly one of \`query\` (singular, response always wraps as \`{ items: [...] }\`) OR \`queries\` (object, per-key shape determined by scalar collapse rules). Both or neither is rejected.
197
+ * \`paramSpec.perEntryFields[0].allowedValues\` is a closed enum of four values: \`string\`, \`number\`, \`boolean\`, \`date\`. Other type strings are rejected by the validator.
198
+ * \`scalarCollapseRules\` apply ONLY to \`widget.queries.<key>\`. For \`widget.query\` (singular) the response is ALWAYS wrapped as \`{ items: [...] }\` regardless of SQL result shape.
199
+ * \`namingConvention.dashboardName.regex\` is \`^dash-[a-zA-Z0-9_-]+$\`. minLength is 6 because \`dash-\` is 5 characters and at least one suffix character is required.
200
+ * \`placeholderConvention.regex\` uses a negative lookbehind \`(?<!:):\` so Postgres cast syntax \`::\` is NOT scanned as a placeholder. Every placeholder used in widget SQL must be declared in the top-level \`params\` object, otherwise the validator rejects the payload.
201
+ - Knowledge boundary — the catalog does NOT cover the following; refer the user to \`documentationUrl\` (in the response JSON) instead of fabricating from training data:
202
+ * Common widget patterns with concrete SQL examples (Metric+Donut, Metric+Sparkline, Metric+Goal).
203
+ * Frontend mapping examples — how the response is rendered in Metronic, AdminLTE, or other UI frameworks.
204
+ * Separation of Concerns rationale for the forbidden frontend fields (\`widgetType\`, \`layout\`, \`title\`, \`subtitle\`, \`color\`).
205
+ * Multi-database SQL dialect adaptation inside widget queries.
206
+ * Performance characteristics (Promise.allSettled execution, in-memory SQL embedding, zero disk I/O at request time).
207
+ - Do not mention internal tool names.`,
208
+ },
209
+ ],
210
+ };
211
+ });
212
+ }
213
+ //# sourceMappingURL=get-dashboard-catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-dashboard-catalog.js","sourceRoot":"","sources":["../../../src/tools/codegen/get-dashboard-catalog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerCodegenGetDbschemaCatalog(server: McpServer): void;
@@ -0,0 +1,244 @@
1
+ import { z } from 'zod';
2
+ import { access } from 'node:fs/promises';
3
+ import { resolve, join } from 'node:path';
4
+ import { execProcess } from '../../lib/exec.js';
5
+ export function registerCodegenGetDbschemaCatalog(server) {
6
+ server.registerTool('codegen_get_dbschema_catalog', {
7
+ title: 'Get dbschema-kit Catalog',
8
+ description: `Get authoritative JSON catalog of the dbschema-kit defineModel API: defineModel options, field types (with modifier formats), constraints (standalone vs value-bearing), relation types (belongsTo, hasMany, hasOne), referential actions (cascade/restrict/setNull/noAction), check operations (in/gt/gte/lt/lte/eq/neq), shorthand syntax rules and examples, naming rules (table/constraint), and dialect support (postgres/mysql/oracle/sqlite). The catalog is the single source of truth for schema-as-code authoring.
9
+
10
+ USE WHEN:
11
+ - The user asks how to define a database schema with dbschema-kit, the factory function pattern, or the \`defineModel\` API
12
+ - Pertanyaan dalam bentuk: "bagaimana sintaks defineModel", "apa saja field type yang didukung", "bagaimana cara declare foreign key di schema", "constraint apa saja yang ada di shorthand"
13
+ - The user mentions dbschema-kit concepts: \`defineModel\`, factory function, shorthand syntax, \`belongsTo\`/\`hasMany\`/\`hasOne\`, \`pk\`/\`fk:\`/\`unique\`, \`checks\`, \`primaryKey\`, \`relations\`, \`referentialActions\`, \`onDelete\`/\`onUpdate\`
14
+ - Before authoring a schema file (via Write/Edit tools) — to ground field types, constraint syntax, and relation declarations
15
+ - Before invoking 'codegen_dbschema_init' or 'codegen_dbschema_validate' — to verify the planned approach matches the API
16
+ - The user asks about referential actions: \`cascade\`, \`restrict\`, \`setNull\`, \`noAction\`
17
+ - The user asks about check operations: \`in\`, \`gt\`, \`gte\`, \`lt\`, \`lte\`, \`eq\`, \`neq\`
18
+ - The user asks about audit columns: \`created_at\`, \`created_by\`, \`updated_at\`, \`updated_by\` — the 4-column RESTForge convention shared between SDF and RDF. Trigger phrases: "audit columns", "kolom audit", "kolom created_by updated_by", "konvensi audit"
19
+ - The user asks which dialects are supported (postgres, mysql, oracle, sqlite)
20
+ - The user is unsure about field shorthand like \`string:36 pk\` or \`decimal:15,2 default:0\`
21
+
22
+ DO NOT USE FOR:
23
+ - Validating an actual schema definition file -> use 'codegen_dbschema_validate'
24
+ - Listing models from existing schema files -> use 'codegen_dbschema_models'
25
+ - Generating DDL from schema files -> use 'codegen_dbschema_generate_ddl'
26
+ - Migrating schema to a database -> use 'codegen_dbschema_migrate'
27
+ - Introspecting an existing database into schema files -> use 'codegen_dbschema_introspect'
28
+ - Looking up CRUD payload field validation rules -> use 'codegen_get_field_validation_catalog'
29
+ - Looking up dashboard payload spec -> use 'codegen_get_dashboard_catalog'
30
+ - Looking up CRUD query declarative spec -> use 'codegen_get_query_declarative_catalog'
31
+ - Querying live database tables -> use 'codegen_list_tables' / 'codegen_describe_table'
32
+
33
+ This tool runs: npx restforge catalog dbschema [--section=<X>] [--name=<Y>] [--kind=<Z>] in the given cwd.
34
+ The catalog is sourced from restforge (single source of truth) so it stays in sync with
35
+ the dbschema-kit version installed in the project.
36
+
37
+ PRESENTATION GUIDANCE:
38
+ - Match the user's language. If the user writes in Indonesian, respond in Indonesian.
39
+ - Never mention internal tool names in the reply to the user. Describe actions by what they do (e.g. "look up the schema catalog", "create a new schema file", "validate the schema").
40
+ - Speak in plain language. Summarise the catalog (number of field types, constraints, relations, dialects); do not paste the entire JSON unless the user explicitly asks for it.
41
+ - The catalog is sourced from restforge (single source of truth) so it stays in sync with the dbschema-kit version installed in the project.
42
+ - When the user asks about a specific construct (e.g. "how does belongsTo work"), use the catalog as ground truth and match the API exactly. Do not invent flags or behaviors not present in the catalog.
43
+ - When a precondition is not met (e.g. the package is not installed), frame it as a question or next-step suggestion rather than an error.`,
44
+ inputSchema: {
45
+ cwd: z
46
+ .string()
47
+ .min(1)
48
+ .describe('Absolute path of the project folder (must contain node_modules/@restforgejs/platform)'),
49
+ section: z
50
+ .enum([
51
+ 'defineModelOptions',
52
+ 'fieldTypes',
53
+ 'constraints',
54
+ 'relationTypes',
55
+ 'referentialActions',
56
+ 'checkOperations',
57
+ 'auditColumns',
58
+ 'shorthandSyntax',
59
+ 'namingRules',
60
+ 'dialectSupport',
61
+ ])
62
+ .optional()
63
+ .describe('Filter to a single catalog section. When omitted, the full catalog is returned.'),
64
+ name: z
65
+ .string()
66
+ .min(1)
67
+ .optional()
68
+ .describe('Filter array sections by exact name (e.g. "string", "belongsTo", "cascade"). Use together with section.'),
69
+ kind: z
70
+ .enum(['standalone', 'value'])
71
+ .optional()
72
+ .describe('Filter constraints by kind. Only valid with section=constraints.'),
73
+ },
74
+ annotations: {
75
+ title: 'Get dbschema-kit Catalog',
76
+ readOnlyHint: true,
77
+ idempotentHint: true,
78
+ },
79
+ }, async ({ cwd, section, name, kind }) => {
80
+ const projectCwd = resolve(cwd);
81
+ // Precondition check: @restforgejs/platform must be installed before this CLI command can run.
82
+ // Treated as a non-error precondition per the authoring guide §3.4.
83
+ try {
84
+ await access(join(projectCwd, 'node_modules', '@restforgejs', 'platform'));
85
+ }
86
+ catch {
87
+ return {
88
+ content: [
89
+ {
90
+ type: 'text',
91
+ text: `Precondition not met: the RESTForge package is not installed in this project.
92
+
93
+ Project path: ${projectCwd}
94
+ Expected location: node_modules/@restforgejs/platform
95
+ Requested section: ${section ?? 'all'}
96
+ Requested name filter: ${name ?? 'none'}
97
+ Requested kind filter: ${kind ?? 'none'}
98
+
99
+ For the assistant:
100
+ - The dbschema-kit catalog can only be retrieved once the RESTForge package is installed locally.
101
+ - Suggest installing the package first, then retry getting the catalog.
102
+ - When explaining to the user, say something like "the RESTForge package isn't installed yet — should I install it first?". Do not mention internal tool names.`,
103
+ },
104
+ ],
105
+ isError: false, // per §3.4
106
+ };
107
+ }
108
+ // Forward only the arguments the user supplied. CLI defaults remain in
109
+ // effect when the user does not specify them. per §3.5
110
+ const cliArgs = ['restforge', 'catalog', 'dbschema'];
111
+ if (section !== undefined)
112
+ cliArgs.push(`--section=${section}`);
113
+ if (name !== undefined)
114
+ cliArgs.push(`--name=${name}`);
115
+ if (kind !== undefined)
116
+ cliArgs.push(`--kind=${kind}`);
117
+ const result = await execProcess('npx', cliArgs, {
118
+ cwd: projectCwd,
119
+ timeout: 15_000,
120
+ env: { NODE_ENV: 'production' },
121
+ stripFinalNewline: true,
122
+ });
123
+ // CLI failure: real error per §3.4; structured per §3.5.
124
+ if (!result.success) {
125
+ return {
126
+ content: [
127
+ {
128
+ type: 'text',
129
+ text: `Failed to retrieve the dbschema-kit catalog.
130
+
131
+ Project path: ${projectCwd}
132
+ Section filter: ${section ?? 'all'}
133
+ Name filter: ${name ?? 'none'}
134
+ Kind filter: ${kind ?? 'none'}
135
+ Command: ${result.command}
136
+ Exit code: ${result.exitCode}
137
+
138
+ --- CLI output ---
139
+ stdout:
140
+ ${result.stdout}
141
+
142
+ stderr:
143
+ ${result.stderr}
144
+ --- end CLI output ---
145
+
146
+ For the assistant:
147
+ - Tell the user that the schema catalog could not be retrieved.
148
+ - A common cause is an older RESTForge version that does not yet expose this command. If the CLI output mentions an unknown command, suggest upgrading the package as a likely fix.
149
+ - Another common cause is an invalid filter combination (e.g. kind without section=constraints). The CLI surfaces the rule in its error message.
150
+ - Do not paste the raw stdout/stderr unless the user explicitly asks. Do not mention internal tool names.`,
151
+ },
152
+ ],
153
+ isError: true, // per §3.4
154
+ };
155
+ }
156
+ // Validate JSON output. Parse failure is a real error per §3.4 (CLI succeeded but produced invalid output).
157
+ let parsed;
158
+ try {
159
+ parsed = JSON.parse(result.stdout);
160
+ }
161
+ catch (err) {
162
+ const msg = err instanceof Error ? err.message : String(err);
163
+ return {
164
+ content: [
165
+ {
166
+ type: 'text',
167
+ text: `Failed to parse dbschema-kit catalog JSON.
168
+
169
+ Project path: ${projectCwd}
170
+ Reason: ${msg}
171
+
172
+ --- Raw stdout ---
173
+ ${result.stdout}
174
+ --- end Raw stdout ---
175
+
176
+ For the assistant:
177
+ - The CLI returned output that is not valid JSON.
178
+ - Summarise this to the user in plain language; do not paste the raw stdout unless they explicitly ask.
179
+ - Suggest checking that the installed package version is compatible. Do not mention internal tool names.`,
180
+ },
181
+ ],
182
+ isError: true, // per §3.4
183
+ };
184
+ }
185
+ // Defensive labeled facts: tolerate shape changes upstream.
186
+ const root = (parsed ?? {});
187
+ const summary = (root.summary ?? {});
188
+ const totalFieldTypes = typeof summary.totalFieldTypes === 'number' ? summary.totalFieldTypes : 'unknown';
189
+ const totalConstraints = typeof summary.totalConstraints === 'number' ? summary.totalConstraints : 'unknown';
190
+ const totalRelationTypes = typeof summary.totalRelationTypes === 'number' ? summary.totalRelationTypes : 'unknown';
191
+ const totalReferentialActions = typeof summary.totalReferentialActions === 'number'
192
+ ? summary.totalReferentialActions
193
+ : 'unknown';
194
+ const totalCheckOperations = typeof summary.totalCheckOperations === 'number' ? summary.totalCheckOperations : 'unknown';
195
+ const totalAuditColumns = typeof summary.totalAuditColumns === 'number' ? summary.totalAuditColumns : 'unknown';
196
+ const totalDialects = typeof summary.totalDialects === 'number' ? summary.totalDialects : 'unknown';
197
+ const sourceLabel = typeof root.source === 'string' ? root.source : 'dbschema-catalog';
198
+ const prettyJson = JSON.stringify(parsed, null, 2);
199
+ // Success: one-line summary + labeled facts + fenced JSON output per §3.5.
200
+ return {
201
+ content: [
202
+ {
203
+ type: 'text',
204
+ text: `dbschema-kit catalog retrieved successfully.
205
+
206
+ Project path: ${projectCwd}
207
+ Source: restforge (${sourceLabel}) — single source of truth for the installed runtime version
208
+ Section filter: ${section ?? 'all'}
209
+ Name filter: ${name ?? 'none'}
210
+ Kind filter: ${kind ?? 'none'}
211
+ totalFieldTypes: ${totalFieldTypes}
212
+ totalConstraints: ${totalConstraints}
213
+ totalRelationTypes: ${totalRelationTypes}
214
+ totalReferentialActions: ${totalReferentialActions}
215
+ totalCheckOperations: ${totalCheckOperations}
216
+ totalAuditColumns: ${totalAuditColumns}
217
+ totalDialects: ${totalDialects}
218
+
219
+ --- dbschema-kit Catalog (JSON) ---
220
+ ${prettyJson}
221
+ --- end dbschema-kit Catalog (JSON) ---
222
+
223
+ For the assistant:
224
+ - Confirm to the user that the catalog is available. Summarise in plain language: how many field types, constraints, relation types, referential actions, check operations, and dialects are listed.
225
+ - Do not paste the full JSON unless the user explicitly asks. If the user only asked to "see the catalog", offer to drill into a specific section (field types, constraints, relations, shorthand syntax, naming rules) instead of dumping everything.
226
+ - Use this catalog as ground truth when the user is:
227
+ * Asking "how is a schema file structured?" or "what does defineModel accept?"
228
+ * Authoring a schema file manually (via the Write/Edit tools)
229
+ * Asking about a specific construct (a field type, a constraint, a relation, a referential action, a check operation)
230
+ * Asking about shorthand syntax like \`string:36 pk\` or \`decimal:15,2 default:0\`
231
+ * Asking which dialects are supported and what differs between them
232
+ - The catalog is dialect-agnostic (it describes the API). Dialect-specific differences (column type rendering, identifier quoting, FK syntax) are applied at DDL generation time, not at schema authoring time.
233
+ - Match the API exactly. Do not invent flags, options, or behaviors that are not present in the catalog. If something the user wants is not in the catalog, say so honestly rather than fabricating.
234
+ - After grounding from the catalog, the natural next step depends on user intent:
235
+ * Author a new file -> the schema-init action.
236
+ * Validate existing files -> the schema-validate action.
237
+ * Apply schema to DB -> dry-run first, then migrate.
238
+ - Match the user's language.`,
239
+ },
240
+ ],
241
+ };
242
+ });
243
+ }
244
+ //# sourceMappingURL=get-dbschema-catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-dbschema-catalog.js","sourceRoot":"","sources":["../../../src/tools/codegen/get-dbschema-catalog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerCodegenGetFieldValidationCatalog(server: McpServer): void;