@regle/mcp-server 1.14.0 → 1.14.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -22,7 +22,9 @@ Add to your `claude_desktop_config.json`:
22
22
 
23
23
  ### Cursor
24
24
 
25
- Add to your MCP settings:
25
+ [![Install MCP Server](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=regle&config=eyJjb21tYW5kIjoibnB4IEByZWdsZS9tY3Atc2VydmVyIn0%3D)
26
+
27
+ Or add to your MCP settings:
26
28
 
27
29
  ```json
28
30
  {
@@ -21,7 +21,7 @@ var docs_data_default = {
21
21
  },
22
22
  {
23
23
  "id": "advanced-usage-immutable-constructors",
24
- "title": "immutable-constructors",
24
+ "title": "markStatic",
25
25
  "category": "advanced-usage",
26
26
  "path": "advanced-usage/immutable-constructors.md",
27
27
  "content": "# Handling immutable constructors\n\nRegle works by tracking changes in the state and updating the validation rules accordingly.\n\nThis works great for objects and arrays, but not for immutable constructors (like `Decimal` from `decimal.js` or `Moment` from `moment.js`, etc...).\n\nThis constructors will be interpreted as regular objects and their properties treated as nested fields.\n\n## Default Usage\n\nTo handle these cases, you can use the `markStatic` helper to mark the value as static and treat the constructor as a regular raw Field.\n\n```vue\n<template>\n <input :value=\"r$.decimal.$value?.toString()\" @input=\"handleDecimalInput\" />\n</template>\n\n```\n\n## Schema Usage\n\nWhen using Regle with `@regle/schemas`, you will have to also declare the static constructor in the schema.\n\n```ts\nimport { markStatic, useRegleSchema } from '@regle/core'\nimport { z } from 'zod'\n\nconst StaticDecimal = markStatic(Decimal)\n\nconst schema = z.object({\n decimal: z.instanceof(StaticDecimal).refine((value) => value.toNumber() > 10),\n})\n\nconst { r$ } = useRegleSchema({ decimal: new StaticDecimal(0) }, schema)\n\n```\n\n## `isStatic` helper\n\nYou can use the `isStatic` helper to check if a value is a static value.\n\n```ts\nimport { isStatic } from '@regle/core';\n\nconst isStatic = isStatic(r$.$value.decimal); // true\n```\n\n## `UnwrapStatic` type helper\n\nYou can use the `UnwrapStatic` type to unwrap a static value.\n\n```ts\nimport { type UnwrapStatic } from '@regle/core';\n\ntype value = UnwrapStatic<typeof r$.$value.decimal>; // Decimal\n```\n\n## `isRegleStatic` type helper\n\nYou can use the `isRegleStatic` type helper to check if a value is a static value.\n\n```ts\nimport { type isRegleStatic } from '@regle/core';\n\ntype isStatic = isRegleStatic<typeof state.decimal>; // true\n```"
@@ -236,6 +236,13 @@ var docs_data_default = {
236
236
  "path": "index.md",
237
237
  "content": "<h2 class=\"hidden-title\">Vue validation library</h2>\n<h2 class=\"hidden-title\">Vue form library</h2>\n<h2 class=\"hidden-title\">Vue zod forms</h2>\n<h2 class=\"hidden-title\">Vue zod</h2>\n<h2 class=\"hidden-title\">Vuelidate Zod</h2>\n<h2 class=\"hidden-title\">Vuelidate alternative</h2>\n<h2 class=\"hidden-title\">Veevalidate alternative</h2>\n<h2 class=\"hidden-title\">Vueforms alternative</h2>\n<h2 class=\"hidden-title\">Tanstack forms alternative</h2>"
238
238
  },
239
+ {
240
+ "id": "integrations-mcp-server",
241
+ "title": "Regle MCP server",
242
+ "category": "integrations",
243
+ "path": "integrations/mcp-server.md",
244
+ "content": "# MCP Server\n\nRegle offers an MCP server that can be used to get documentation and autocomplete in your favorite AI assistant editor.\n\nThe MCP server provides the following features:\n\n- Create form validation rules\n- Search documentation\n- Get precise information on any rule\n- Create custom rules\n- API information on every Regle helper\n\n## Cursor\n\n<a href=\"https://cursor.com/en-US/install-mcp?name=regle&config=eyJjb21tYW5kIjoibnB4IEByZWdsZS9tY3Atc2VydmVyIn0%3D\">\n <div class=\"light-only\">\n <img src=\"https://cursor.com/deeplink/mcp-install-dark.svg\" alt=\"Install MCP Server\" />\n </div>\n <div class=\"dark-only\">\n <img src=\"https://cursor.com/deeplink/mcp-install-light.svg\" alt=\"Install MCP Server\" />\n </div>\n</a>\n\nOr add to your `.cursor/mcp.json`\n```json\n{\n \"mcpServers\": {\n \"regle\": {\n \"command\": \"npx\",\n \"args\": [\"@regle/mcp-server\"]\n }\n }\n}\n```\n\n## Claude Desktop\n\nAdd to your `claude_desktop_config.json`:\n\n```json\n{\n \"mcpServers\": {\n \"regle\": {\n \"command\": \"npx\",\n \"args\": [\"@regle/mcp-server\"]\n }\n }\n}\n```"
245
+ },
239
246
  {
240
247
  "id": "integrations-nuxt",
241
248
  "title": "Nuxt",
@@ -259,7 +266,7 @@ var docs_data_default = {
259
266
  },
260
267
  {
261
268
  "id": "introduction-devtools",
262
- "title": "devtools",
269
+ "title": "Devtools",
263
270
  "category": "introduction",
264
271
  "path": "introduction/devtools.md",
265
272
  "content": "# Regle Devtools\n\nRegle offers a devtools extension for [Vue Devtools](https://devtools.vuejs.org/) to help you debug your validation tree.\n\n![Regle Devtools Screenshot](/screenshots/devtools.png)\n\n## Installation\n\nTo enable devtools, you need to install the Regle plugin in your app.\n\n:::tip\nIf you use the `@regle/nuxt` module, the devtools will be automatically enabled.\n:::\n\n```ts [main.ts]\nimport { createApp } from 'vue';\nimport App from './App.vue';\nimport { RegleVuePlugin } from '@regle/core';\n\nconst app = createApp(App);\n\napp.use(RegleVuePlugin); // <--\n\napp.mount('#app');\n```\n\n## Usage\n\nRegle devtools can inspect every variation of `useRegle`:\n\n- `useRegle`\n- `useRules`\n- `useRegleSchema`\n- `useScopedRegle`\n- `useScopedRegleSchema`\n\nYou can inspect every nested properties and rules of the `r$` instance.\n\n:::warning\nRules details inspection is not available for `useRegleSchema`\n:::\n\n### Actions\n\nYou can perform actions on the `r$` instance by clicking on the actions buttons in the devtools.\n\n![Devtools Actions Screenshot](/screenshots/devtools-actions.png)\n\n- Validate: Validate the `r$` instance (with `$validate` method)\n- Reset validation state: Reset the validation state of the `r$` instance (with `$reset` method)\n- Restore to original state: Restore the `r$` instance to the original state (with `$reset` method)\n\n## Providing custom `r$` ids to devtools\n\nBy default, the devtools will use a generic name to display the `r$` instance. \n\nYou can provide a custom name to the `useRegle` composable to display a more descriptive name in the devtools.\n\n```ts [App.vue]\nimport { useRegle } from '@regle/core';\n\nconst { r$ } = useRegle({ name: '' }, {\n name: { required }\n}, {\n id: 'my-form'\n});\n```\n\n## Devtools demo\n\nYou can go in any of the [Stablitz exemples](/examples/index) and open the devtools by clicking on the <span data-title=\"vue\"></span> \"Open Devtools\" button in the bottom middle of the page.\n\n### Vite Devtools Integration\n\nRegle devtools also integrate cleanly with [Vite](https://vitejs.dev/) when you're running your app in development mode.\n\nYou should see the Regle panel show up automatically in the Vite devtools if you've installed the plugin correctly.\n\n<img src=\"/screenshots/vite-devtools.png\" alt=\"Vite Devtools with Regle panel\" width=\"100\"/>\n\nYou will see the Regle icon showing in the devtools. Just click on it!\n\n<img src=\"/screenshots/vite-devtools-regle.png\" alt=\"Vite Devtools with Regle panel\" />"
@@ -412,21 +419,21 @@ var docs_data_default = {
412
419
  {
413
420
  "name": "flatErrors",
414
421
  "kind": "function",
415
- "description": "Converts a nested $errors object to a flat array of string errors\n\nCan also flatten to an array containing the path of each error with the options.includePath",
422
+ "description": "Converts a nested `$errors` object to a flat array of error strings.\nUseful for displaying a complete list of form errors or counting total errors.\n\nWith the `includePath` option, returns errors in Standard Schema Issue format\nincluding the path to each error field.",
416
423
  "parameters": [{
417
424
  "name": "errors",
418
425
  "type": "$InternalRegleErrors",
419
- "description": "",
426
+ "description": "- The `$errors` object from a Regle instance (e.g., `r$.$errors`)",
420
427
  "optional": false
421
428
  }, {
422
429
  "name": "options",
423
430
  "type": "{ includePath: true; }",
424
- "description": "",
431
+ "description": "- Configuration options",
425
432
  "optional": false
426
433
  }],
427
434
  "returnType": "StandardSchemaV1.Issue[]",
428
- "example": "",
429
- "tags": {}
435
+ "example": "import { flatErrors, useRegle } from '@regle/core';\nimport { required, email, minLength } from '@regle/rules';\n\nconst { r$ } = useRegle(\n { name: '', email: 'invalid' },\n { name: { required, minLength: minLength(3) }, email: { email } }\n);\n\nawait r$.$validate();\n\n// Get flat array of error messages\nconst errors = flatErrors(r$.$errors);\n// ['This field is required', 'Value must be a valid email address']\n\n// Get errors with paths (Standard Schema format)\nconst issues = flatErrors(r$.$errors, { includePath: true });\n// [{ message: 'This field is required', path: ['name'] }, ...]",
436
+ "tags": { "see": "://reglejs.dev/core-concepts/displaying-errors#display-flat-errors Documentation" }
430
437
  },
431
438
  {
432
439
  "name": "inferRules",
@@ -539,11 +546,11 @@ var docs_data_default = {
539
546
  {
540
547
  "name": "RegleVuePlugin",
541
548
  "kind": "const",
542
- "description": "",
549
+ "description": "Vue plugin to enable Regle devtools integration with Vue Devtools.\nProvides debugging capabilities for inspecting validation trees, states, and actions.\n\nSupports inspection of: `useRegle`, `useRules`, `useRegleSchema`, `useScopedRegle`, `useScopedRegleSchema`.\n\nNote: If using `@regle/nuxt`, devtools are automatically enabled.",
543
550
  "parameters": [],
544
551
  "returnType": "",
545
- "example": "",
546
- "tags": {}
552
+ "example": "// main.ts\nimport { createApp } from 'vue';\nimport { RegleVuePlugin } from '@regle/core';\nimport App from './App.vue';\n\nconst app = createApp(App);\napp.use(RegleVuePlugin);\napp.mount('#app');",
553
+ "tags": { "see": "://reglejs.dev/introduction/devtools Documentation" }
547
554
  },
548
555
  {
549
556
  "name": "unwrapRuleParameters",
@@ -562,16 +569,16 @@ var docs_data_default = {
562
569
  {
563
570
  "name": "useCollectScope",
564
571
  "kind": "function",
565
- "description": "",
572
+ "description": "Composable to collect and merge all Regle instances created with the default `useScopedRegle` within the same scope.\nReturns a merged `r$` object allowing validation across multiple components simultaneously.\n\nChildren properties like `$value` and `$errors` are converted to arrays instead of objects.\nYou have access to all validation properties like `$error`, `$invalid`, `$validate()`, etc.",
566
573
  "parameters": [{
567
574
  "name": "namespace",
568
575
  "type": "MaybeRefOrGetter<string | string[]>",
569
- "description": "",
576
+ "description": "- Optional namespace or array of namespaces to filter which scoped instances to collect",
570
577
  "optional": true
571
578
  }],
572
- "returnType": "{\n r$: MergedScopedRegles<Record<string, unknown>[]> | MergedRegles<Record<string, SuperCompatibleRegleRoot>>;\n }",
573
- "example": "",
574
- "tags": {}
579
+ "returnType": "{ r$: MergedScopedRegles<TValue>; }",
580
+ "example": "// ParentComponent.vue\nimport { useCollectScope } from '@regle/core';\n\nconst { r$ } = useCollectScope();\n// Or with namespace filtering\nconst { r$ } = useCollectScope('contacts');\n\n// Validate all collected forms\nconst { result, data } = await r$.$validate();\n// Access collected errors\nconsole.log(r$.$errors);",
581
+ "tags": { "see": "://reglejs.dev/advanced-usage/scoped-validation Documentation" }
575
582
  },
576
583
  {
577
584
  "name": "useRegle",
@@ -594,7 +601,7 @@ var docs_data_default = {
594
601
  "parameters": [],
595
602
  "returnType": "{ regle: $InternalRegleStatusType; }",
596
603
  "example": "",
597
- "tags": {}
604
+ "tags": { "internal": "This is the internal function that creates the root storage for the Regle instance.\nThis allows shared logic between all `useRegle` like composables" }
598
605
  },
599
606
  {
600
607
  "name": "useRules",
@@ -617,17 +624,17 @@ var docs_data_default = {
617
624
  },
618
625
  {
619
626
  "name": "useScopedRegle",
620
- "kind": "const",
621
- "description": "",
627
+ "kind": "function",
628
+ "description": "Clone of `useRegle` that automatically registers its instance for collection by `useCollectScope`.\nEvery time it's called, a new instance is added for the parent scope to collect.\n\nCan be called multiple times anywhere in your app - not restricted to components or DOM.\nWhen the component is unmounted or scope is disposed, the instance is automatically unregistered.",
622
629
  "parameters": [{
623
630
  "name": "params",
624
631
  "type": "[state: MaybeRef<TState> | DeepReactiveState<TState>, rulesFactory: TState extends PrimitiveTypes ? MaybeRefOrGetter<TDecl> : TState extends Record<...> ? MaybeRefOrComputedRef<...> | ((...args: any[]...",
625
632
  "description": "",
626
633
  "optional": false
627
634
  }],
628
- "returnType": "NonNullable<TState> extends PrimitiveTypes ? { r$: Raw<RegleFieldStatus<PrimitiveTypes & TState & {}, TDecl, any>>; } : { ...; }",
629
- "example": "",
630
- "tags": {}
635
+ "returnType": "NonNullable<TState> extends PrimitiveTypes ? RegleSingleField<PrimitiveTypes & TState & {}, TDecl, never, { ...; }> : Regle<...>",
636
+ "example": "// ChildComponent.vue\nimport { useScopedRegle } from '@regle/core';\n\nconst { r$ } = useScopedRegle(\n { email: '' },\n { email: { required, email } },\n { namespace: 'contacts' }\n);",
637
+ "tags": { "see": "://reglejs.dev/advanced-usage/scoped-validation Documentation" }
631
638
  },
632
639
  {
633
640
  "name": "variantToRef",
@@ -1656,9 +1663,23 @@ function searchApi(query) {
1656
1663
  return results;
1657
1664
  }
1658
1665
 
1659
- var version = "1.14.0";
1666
+ var version = "1.14.2";
1660
1667
 
1661
- const categories = getCategories();
1668
+ function jsonResponse(data$1) {
1669
+ return { content: [{
1670
+ type: "text",
1671
+ text: JSON.stringify(data$1, null, 2)
1672
+ }] };
1673
+ }
1674
+ function errorResponse(error, extra) {
1675
+ return {
1676
+ ...jsonResponse({
1677
+ error,
1678
+ ...extra
1679
+ }),
1680
+ isError: true
1681
+ };
1682
+ }
1662
1683
  const server = new McpServer({
1663
1684
  name: "regle-mcp-server",
1664
1685
  version,
@@ -1666,55 +1687,66 @@ const server = new McpServer({
1666
1687
  title: "Regle MCP Server",
1667
1688
  websiteUrl: "https://reglejs.dev"
1668
1689
  });
1669
- server.registerTool("regle-list-docs", {
1690
+ server.registerTool("regle-list-documentation", {
1670
1691
  title: "List all available Regle documentation pages",
1671
1692
  inputSchema: z.object({ category: z.string().optional().describe("Filter by category (e.g., \"rules\", \"core-concepts\", \"introduction\")") })
1672
1693
  }, async ({ category }) => {
1673
1694
  const filteredDocs = category ? getDocsByCategory(category) : docs;
1674
- return { content: [{
1675
- type: "text",
1676
- text: JSON.stringify({
1677
- message: "Available Regle documentation pages",
1678
- category: category || "all",
1679
- count: filteredDocs.length,
1680
- docs: filteredDocs.map((doc) => ({
1681
- id: doc.id,
1682
- title: doc.title
1683
- }))
1684
- }, null, 2)
1685
- }] };
1695
+ return jsonResponse({
1696
+ message: "Available Regle documentation pages",
1697
+ category: category || "all",
1698
+ count: filteredDocs.length,
1699
+ docs: filteredDocs.map((doc) => ({
1700
+ id: doc.id,
1701
+ title: doc.title
1702
+ }))
1703
+ });
1686
1704
  });
1687
- server.registerTool("regle-get-doc", {
1705
+ server.registerTool("regle-get-documentation", {
1688
1706
  title: "Get the full content of a specific Regle documentation page",
1689
1707
  inputSchema: z.object({ id: z.string().describe("The documentation page ID (e.g., \"core-concepts-rules-built-in-rules\")") })
1690
1708
  }, async ({ id }) => {
1691
1709
  const doc = getDocById(id);
1692
- if (!doc) {
1693
- const availableIds = docs.map((d) => d.id);
1694
- return {
1695
- content: [{
1696
- type: "text",
1697
- text: JSON.stringify({
1698
- error: "Documentation page not found",
1699
- requestedId: id,
1700
- availableIds
1701
- }, null, 2)
1702
- }],
1703
- isError: true
1704
- };
1705
- }
1706
- return { content: [{
1707
- type: "text",
1708
- text: JSON.stringify({
1709
- id: doc.id,
1710
- title: doc.title,
1711
- category: doc.category,
1712
- path: doc.path,
1713
- content: doc.content
1714
- }, null, 2)
1715
- }] };
1710
+ if (!doc) return errorResponse("Documentation page not found", {
1711
+ requestedId: id,
1712
+ availableIds: docs.map((d) => d.id)
1713
+ });
1714
+ return jsonResponse({
1715
+ id: doc.id,
1716
+ title: doc.title,
1717
+ category: doc.category,
1718
+ path: doc.path,
1719
+ content: doc.content
1720
+ });
1716
1721
  });
1717
- server.registerTool("regle-search-docs", {
1722
+ server.registerTool("regle-get-usage-guide", {
1723
+ title: "Get a comprehensive guide on how to use the useRegle composable",
1724
+ inputSchema: z.object({})
1725
+ }, async () => {
1726
+ const doc = getDocById("core-concepts-index");
1727
+ if (!doc) return errorResponse("useRegle guide not found");
1728
+ return jsonResponse({
1729
+ id: doc.id,
1730
+ title: doc.title,
1731
+ category: doc.category,
1732
+ content: doc.content
1733
+ });
1734
+ });
1735
+ server.registerTool("regle-get-vuelidate-migration-guide", {
1736
+ title: "Get a guide on how to migrate from Vuelidate to Regle",
1737
+ inputSchema: z.object({})
1738
+ }, async () => {
1739
+ const doc = getDocById("introduction-migrate-from-vuelidate");
1740
+ if (!doc) return errorResponse("Vuelidate migration guide not found");
1741
+ return jsonResponse({
1742
+ id: doc.id,
1743
+ title: doc.title,
1744
+ category: doc.category,
1745
+ content: doc.content
1746
+ });
1747
+ });
1748
+ const categories = getCategories();
1749
+ server.registerTool("regle-search-documentation", {
1718
1750
  title: "Search Regle documentation for specific topics, rules, or concepts",
1719
1751
  inputSchema: z.object({
1720
1752
  query: z.string().describe("Search query (e.g., \"required\", \"async validation\", \"useRegle\")"),
@@ -1722,53 +1754,39 @@ server.registerTool("regle-search-docs", {
1722
1754
  })
1723
1755
  }, async ({ query, limit }) => {
1724
1756
  const results = searchDocs(query).slice(0, limit);
1725
- if (results.length === 0) return { content: [{
1726
- type: "text",
1727
- text: JSON.stringify({
1728
- query,
1729
- resultCount: 0,
1730
- results: [],
1731
- suggestions: categories
1732
- }, null, 2)
1733
- }] };
1757
+ if (results.length === 0) return jsonResponse({
1758
+ query,
1759
+ resultCount: 0,
1760
+ results: [],
1761
+ suggestions: categories
1762
+ });
1734
1763
  const formattedResults = results.map((doc) => ({
1735
1764
  id: doc.id,
1736
1765
  title: doc.title,
1737
1766
  category: doc.category,
1738
1767
  preview: doc.content.substring(0, 300) + "..."
1739
1768
  }));
1740
- return { content: [{
1741
- type: "text",
1742
- text: JSON.stringify({
1743
- query,
1744
- resultCount: results.length,
1745
- results: formattedResults
1746
- }, null, 2)
1747
- }] };
1769
+ return jsonResponse({
1770
+ query,
1771
+ resultCount: results.length,
1772
+ results: formattedResults
1773
+ });
1748
1774
  });
1749
- server.registerTool("regle-get-rules-reference", {
1775
+ server.registerTool("regle-list-rules", {
1750
1776
  title: "Get a quick reference of all built-in validation rules in Regle",
1751
1777
  inputSchema: z.object({})
1752
1778
  }, async () => {
1753
1779
  const rules = getRulesFromDocs();
1754
- if (rules.length === 0) return {
1755
- content: [{
1756
- type: "text",
1757
- text: JSON.stringify({ error: "Built-in rules documentation not found" }, null, 2)
1758
- }],
1759
- isError: true
1760
- };
1761
- return { content: [{
1762
- type: "text",
1763
- text: JSON.stringify({
1764
- title: "Built-in Rules",
1765
- package: "@regle/rules",
1766
- count: rules.length,
1767
- rules: rules.map((r) => ({
1768
- name: r.name,
1769
- description: r.description
1770
- })),
1771
- usageExample: `import { useRegle } from '@regle/core';
1780
+ if (rules.length === 0) return errorResponse("Built-in rules documentation not found");
1781
+ return jsonResponse({
1782
+ title: "Built-in Rules",
1783
+ package: "@regle/rules",
1784
+ count: rules.length,
1785
+ rules: rules.map((r) => ({
1786
+ name: r.name,
1787
+ description: r.description
1788
+ })),
1789
+ usageExample: `import { useRegle } from '@regle/core';
1772
1790
  import { required, email, minLength } from '@regle/rules';
1773
1791
 
1774
1792
  const { r$ } = useRegle(
@@ -1778,44 +1796,45 @@ const { r$ } = useRegle(
1778
1796
  password: { required, minLength: minLength(8) }
1779
1797
  }
1780
1798
  );`,
1781
- fullDocId: "core-concepts-rules-built-in-rules"
1782
- }, null, 2)
1783
- }] };
1799
+ fullDocId: "core-concepts-rules-built-in-rules"
1800
+ });
1801
+ });
1802
+ server.registerTool("regle-get-rule-reference", {
1803
+ title: "Get details about a specific built-in validation rule",
1804
+ inputSchema: z.object({ name: z.string().describe("The rule name (e.g., \"required\", \"email\", \"minLength\")") })
1805
+ }, async ({ name }) => {
1806
+ const rule = getApiByName(name);
1807
+ if (!rule) {
1808
+ const allRules = getRulesFromDocs();
1809
+ return errorResponse(`Rule "${name}" not found`, { availableRules: allRules.map((r) => r.name) });
1810
+ }
1811
+ return jsonResponse({
1812
+ name: rule.name,
1813
+ description: rule.description,
1814
+ package: "@regle/rules",
1815
+ usageExample: rule.example,
1816
+ fullDocId: "core-concepts-rules-built-in-rules"
1817
+ });
1784
1818
  });
1785
- server.registerTool("regle-get-validation-properties", {
1819
+ server.registerTool("regle-list-validation-properties", {
1786
1820
  title: "Get documentation on all validation properties available on r$ and field objects",
1787
1821
  inputSchema: z.object({})
1788
1822
  }, async () => {
1789
1823
  const doc = getDocById("core-concepts-validation-properties");
1790
- if (!doc) return {
1791
- content: [{
1792
- type: "text",
1793
- text: JSON.stringify({ error: "Validation properties documentation not found" }, null, 2)
1794
- }],
1795
- isError: true
1796
- };
1797
- return { content: [{
1798
- type: "text",
1799
- text: JSON.stringify({
1800
- id: doc.id,
1801
- title: doc.title,
1802
- category: doc.category,
1803
- content: doc.content
1804
- }, null, 2)
1805
- }] };
1824
+ if (!doc) return errorResponse("Validation properties documentation not found");
1825
+ return jsonResponse({
1826
+ id: doc.id,
1827
+ title: doc.title,
1828
+ category: doc.category,
1829
+ content: doc.content
1830
+ });
1806
1831
  });
1807
- server.registerTool("regle-get-helpers-reference", {
1832
+ server.registerTool("regle-list-helpers", {
1808
1833
  title: "Get a reference of all validation helper utilities available in Regle",
1809
1834
  inputSchema: z.object({})
1810
1835
  }, async () => {
1811
1836
  const helpers = getHelpersFromDocs();
1812
- if (helpers.length === 0) return {
1813
- content: [{
1814
- type: "text",
1815
- text: JSON.stringify({ error: "Validation helpers documentation not found" }, null, 2)
1816
- }],
1817
- isError: true
1818
- };
1837
+ if (helpers.length === 0) return errorResponse("Validation helpers documentation not found");
1819
1838
  const guards = helpers.filter((h) => h.category === "guard");
1820
1839
  const operations = helpers.filter((h) => h.category === "operation");
1821
1840
  const coerces = helpers.filter((h) => h.category === "coerce");
@@ -1823,27 +1842,25 @@ server.registerTool("regle-get-helpers-reference", {
1823
1842
  name: h.name,
1824
1843
  description: h.description
1825
1844
  }));
1826
- return { content: [{
1827
- type: "text",
1828
- text: JSON.stringify({
1829
- title: "Validation Helpers",
1830
- package: "@regle/rules",
1831
- totalCount: helpers.length,
1832
- categories: {
1833
- guards: {
1834
- description: "Runtime and Type Guards",
1835
- helpers: formatHelpers(guards)
1836
- },
1837
- operations: {
1838
- description: "Operations Utils",
1839
- helpers: formatHelpers(operations)
1840
- },
1841
- coerces: {
1842
- description: "Coerce Utils",
1843
- helpers: formatHelpers(coerces)
1844
- }
1845
- },
1846
- usageExample: `import { createRule, type Maybe } from '@regle/core';
1845
+ return jsonResponse({
1846
+ title: "Validation Helpers",
1847
+ package: "@regle/rules",
1848
+ totalCount: helpers.length,
1849
+ categories: {
1850
+ guards: {
1851
+ description: "Runtime and Type Guards",
1852
+ helpers: formatHelpers(guards)
1853
+ },
1854
+ operations: {
1855
+ description: "Operations Utils",
1856
+ helpers: formatHelpers(operations)
1857
+ },
1858
+ coerces: {
1859
+ description: "Coerce Utils",
1860
+ helpers: formatHelpers(coerces)
1861
+ }
1862
+ },
1863
+ usageExample: `import { createRule, type Maybe } from '@regle/core';
1847
1864
  import { isFilled, getSize } from '@regle/rules';
1848
1865
 
1849
1866
  const rule = createRule({
@@ -1855,31 +1872,26 @@ const rule = createRule({
1855
1872
  },
1856
1873
  message: 'Error'
1857
1874
  });`,
1858
- fullDocId: "core-concepts-rules-validations-helpers"
1859
- }, null, 2)
1860
- }] };
1875
+ fullDocId: "core-concepts-rules-validations-helpers"
1876
+ });
1861
1877
  });
1862
- server.registerTool("regle-get-useregle-guide", {
1863
- title: "Get a comprehensive guide on how to use the useRegle composable",
1864
- inputSchema: z.object({})
1865
- }, async () => {
1866
- const doc = getDocById("core-concepts-index");
1867
- if (!doc) return {
1868
- content: [{
1869
- type: "text",
1870
- text: JSON.stringify({ error: "useRegle guide not found" }, null, 2)
1871
- }],
1872
- isError: true
1873
- };
1874
- return { content: [{
1875
- type: "text",
1876
- text: JSON.stringify({
1877
- id: doc.id,
1878
- title: doc.title,
1879
- category: doc.category,
1880
- content: doc.content
1881
- }, null, 2)
1882
- }] };
1878
+ server.registerTool("regle-get-helper-reference", {
1879
+ title: "Get details about a specific validation helper utility",
1880
+ inputSchema: z.object({ name: z.string().describe("The helper name (e.g., \"isFilled\", \"getSize\", \"toNumber\")") })
1881
+ }, async ({ name }) => {
1882
+ const helper = getApiByName(name);
1883
+ if (!helper) {
1884
+ const allHelpers = getHelpersFromDocs();
1885
+ return errorResponse(`Helper "${name}" not found`, { availableHelpers: allHelpers.map((h) => h.name) });
1886
+ }
1887
+ return jsonResponse({
1888
+ name: helper.name,
1889
+ description: helper.description,
1890
+ category: helper.tags,
1891
+ package: "@regle/rules",
1892
+ usageExample: helper.example,
1893
+ fullDocId: "core-concepts-rules-validations-helpers"
1894
+ });
1883
1895
  });
1884
1896
  const apiPackages = getApiPackages();
1885
1897
  server.registerTool("regle-get-api-reference", {
@@ -1892,84 +1904,53 @@ server.registerTool("regle-get-api-reference", {
1892
1904
  }, async ({ package: packageName, name, search }) => {
1893
1905
  if (name) {
1894
1906
  const apiItem = getApiByName(name, packageName);
1895
- if (!apiItem) return {
1896
- content: [{
1897
- type: "text",
1898
- text: JSON.stringify({
1899
- error: `API export "${name}" not found`,
1900
- availablePackages: apiPackages
1901
- }, null, 2)
1902
- }],
1903
- isError: true
1904
- };
1905
- return { content: [{
1906
- type: "text",
1907
- text: JSON.stringify({
1908
- name: apiItem.name,
1909
- kind: apiItem.kind,
1910
- description: apiItem.description,
1911
- parameters: apiItem.parameters,
1912
- returnType: apiItem.returnType,
1913
- example: apiItem.example,
1914
- tags: apiItem.tags
1915
- }, null, 2)
1916
- }] };
1907
+ if (!apiItem) return errorResponse(`API export "${name}" not found`, { availablePackages: apiPackages });
1908
+ return jsonResponse({
1909
+ name: apiItem.name,
1910
+ kind: apiItem.kind,
1911
+ description: apiItem.description,
1912
+ parameters: apiItem.parameters,
1913
+ returnType: apiItem.returnType,
1914
+ example: apiItem.example,
1915
+ tags: apiItem.tags
1916
+ });
1917
1917
  }
1918
1918
  if (search) {
1919
1919
  const results = searchApi(search);
1920
- return { content: [{
1921
- type: "text",
1922
- text: JSON.stringify({
1923
- query: search,
1924
- resultCount: results.length,
1925
- results: results.map((r) => ({
1926
- name: r.name,
1927
- package: r.package,
1928
- kind: r.kind,
1929
- description: r.description.substring(0, 200) + (r.description.length > 200 ? "..." : "")
1930
- }))
1931
- }, null, 2)
1932
- }] };
1920
+ return jsonResponse({
1921
+ query: search,
1922
+ resultCount: results.length,
1923
+ results: results.map((r) => ({
1924
+ name: r.name,
1925
+ package: r.package,
1926
+ kind: r.kind,
1927
+ description: r.description.substring(0, 200) + (r.description.length > 200 ? "..." : "")
1928
+ }))
1929
+ });
1933
1930
  }
1934
1931
  if (packageName) {
1935
1932
  const apis = getApiByPackage(packageName);
1936
- if (apis.length === 0) return {
1937
- content: [{
1938
- type: "text",
1939
- text: JSON.stringify({
1940
- error: `Package "${packageName}" not found or has no exports`,
1941
- availablePackages: apiPackages
1942
- }, null, 2)
1943
- }],
1944
- isError: true
1945
- };
1946
- return { content: [{
1947
- type: "text",
1948
- text: JSON.stringify({
1949
- package: packageName,
1950
- exportCount: apis.length,
1951
- exports: apis.map((a) => ({
1952
- name: a.name,
1953
- kind: a.kind,
1954
- description: a.description.substring(0, 150) + (a.description.length > 150 ? "..." : ""),
1955
- hasExample: !!a.example,
1956
- parameterCount: a.parameters.length
1957
- }))
1958
- }, null, 2)
1959
- }] };
1933
+ if (apis.length === 0) return errorResponse(`Package "${packageName}" not found or has no exports`, { availablePackages: apiPackages });
1934
+ return jsonResponse({
1935
+ package: packageName,
1936
+ exportCount: apis.length,
1937
+ exports: apis.map((a) => ({
1938
+ name: a.name,
1939
+ kind: a.kind,
1940
+ description: a.description.substring(0, 150) + (a.description.length > 150 ? "..." : ""),
1941
+ hasExample: !!a.example,
1942
+ parameterCount: a.parameters.length
1943
+ }))
1944
+ });
1960
1945
  }
1961
- const packageSummary = apiPackages.map((pkg) => ({
1962
- package: pkg,
1963
- exportCount: getApiByPackage(pkg).length
1964
- }));
1965
- return { content: [{
1966
- type: "text",
1967
- text: JSON.stringify({
1968
- message: "Available Regle API packages",
1969
- packages: packageSummary,
1970
- usage: "Use \"package\" to list exports, \"name\" to get specific export details, or \"search\" to find exports"
1971
- }, null, 2)
1972
- }] };
1946
+ return jsonResponse({
1947
+ message: "Available Regle API packages",
1948
+ packages: apiPackages.map((pkg) => ({
1949
+ package: pkg,
1950
+ exportCount: getApiByPackage(pkg).length
1951
+ })),
1952
+ usage: "Use \"package\" to list exports, \"name\" to get specific export details, or \"search\" to find exports"
1953
+ });
1973
1954
  });
1974
1955
  async function main() {
1975
1956
  const transport = new StdioServerTransport();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@regle/mcp-server",
3
- "version": "1.14.0",
3
+ "version": "1.14.2",
4
4
  "description": "MCP Server for Regle",
5
5
  "dependencies": {
6
6
  "@modelcontextprotocol/sdk": "1.24.3",