@tsrx/mcp 0.0.35 → 0.0.37
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/package.json +3 -3
- package/src/analyze.js +12 -1
- package/src/format.js +1 -1
- package/src/generated/docs.js +12 -4
- package/src/server.js +2 -1
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "MCP server for TSRX documentation and project context",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Dominic Gannaway",
|
|
6
|
-
"version": "0.0.
|
|
6
|
+
"version": "0.0.37",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
38
38
|
"prettier": "^3.8.3",
|
|
39
39
|
"zod": "^4.3.6",
|
|
40
|
-
"@tsrx/core": "0.1.
|
|
41
|
-
"@tsrx/prettier-plugin": "0.3.
|
|
40
|
+
"@tsrx/core": "0.1.24",
|
|
41
|
+
"@tsrx/prettier-plugin": "0.3.76"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/node": "^24.3.0",
|
package/src/analyze.js
CHANGED
|
@@ -87,6 +87,17 @@ function create_advice(input) {
|
|
|
87
87
|
});
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
if (error_codes.has(DIAGNOSTIC_CODES.FORGOTTEN_STATEMENT_CONTAINER)) {
|
|
91
|
+
advice.push({
|
|
92
|
+
kind: 'forgotten-statement-container',
|
|
93
|
+
severity: 'error',
|
|
94
|
+
title: 'Add @ before statement-container braces',
|
|
95
|
+
message:
|
|
96
|
+
'A function body with TypeScript setup followed by bare TSRX output must use a JSX statement container. Change the opening `{` to `@{`, or use an ordinary `return` when the function only returns JSX.',
|
|
97
|
+
documentation: ['tsrx://docs/components.md', 'tsrx://docs/expression-values.md'],
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
90
101
|
if (
|
|
91
102
|
error_messages.has(TSRX_LOOP_RETURN_ERROR) ||
|
|
92
103
|
error_messages.has(TSRX_LOOP_BREAK_ERROR) ||
|
|
@@ -97,7 +108,7 @@ function create_advice(input) {
|
|
|
97
108
|
severity: 'error',
|
|
98
109
|
title: 'Filter before TSRX for...of loops',
|
|
99
110
|
message:
|
|
100
|
-
'Direct continue, break, and return statements are not valid inside TSRX @for loops. Filter the iterable before rendering, use
|
|
111
|
+
'Direct continue, break, and return statements are not valid inside TSRX @for loops. Filter the iterable before rendering, use @empty { ... } for the no-items fallback, and keep ordinary JavaScript control flow inside nested functions.',
|
|
101
112
|
documentation: ['tsrx://docs/control-flow.md'],
|
|
102
113
|
});
|
|
103
114
|
}
|
package/src/format.js
CHANGED
package/src/generated/docs.js
CHANGED
|
@@ -19,7 +19,7 @@ export const documentation_sections = [
|
|
|
19
19
|
use_cases:
|
|
20
20
|
'components, functions, props, authoring .tsrx files, jsx return syntax',
|
|
21
21
|
content:
|
|
22
|
-
'# Function Components\n\nAuthor UI as ordinary TypeScript functions. Components can return JSX directly, or use a JSX statement container when setup and output should live together.\n\n```tsx\nexport function Button({ label }: { label: string }) @{\n <button>{label}</button>\n}\n```\n\nInside `@{ ... }`, put any setup statements first and end with one rendered output node. No JavaScript setup can appear after that output.\n\nSource: website-tsrx/src/pages/specification.tsrx#components',
|
|
22
|
+
'# Function Components\n\nAuthor UI as ordinary TypeScript functions. Components can return JSX directly, or use a JSX statement container when setup and output should live together.\n\n```tsx\nexport function Button({ label }: { label: string }) @{\n <button>{label}</button>\n}\n```\n\nInside `@{ ... }`, put any setup statements first and end with one rendered output node. No JavaScript setup can appear after that output.\n\nIf a normal function body contains setup statements followed by bare TSRX output, add the missing `@` before the opening brace. Plain `{ ... }` is JavaScript; `@{ ... }` is the statement-container form.\n\nSource: website-tsrx/src/pages/specification.tsrx#components',
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
25
|
slug: 'text-and-template-expressions',
|
|
@@ -27,7 +27,7 @@ export const documentation_sections = [
|
|
|
27
27
|
use_cases:
|
|
28
28
|
'text children, jsx text, comments, string literals, expression containers',
|
|
29
29
|
content:
|
|
30
|
-
'# Text and Template Expressions\n\nStatic text is JSXText and can be written directly between tags. Dynamic values use normal JSX expression containers.\n\n```tsx\nfunction Greeting({ name }: { name: string }) @{\n <>\n <h1>Hello</h1>\n <p>{name}</p>\n </>\n}\n```\n\nJavaScript comments are also allowed between template children and are not rendered. Use braces for JavaScript expressions, including string literals that should be evaluated as JavaScript.\n\nSpecification grammar:\n\n```text\nJSXTextChild :\n JSXTextCharacters\n\nJSXExpressionContainer :\n { AssignmentExpression }\n\nJSXCodeBlock :\n @{ StatementListItemListopt TemplateOutput }\n\nTemplateBlock :\n { TemplateChildrenopt }\n { StatementListItemList TemplateOutput }\n\nJSXIfExpression :\n @if ( Expression ) TemplateBlock\n @if ( Expression ) TemplateBlock else TemplateBlock\n\nJSXForExpression :\n @for ( ForHeader TemplateForOptionsopt ) TemplateBlock\n @for ( ForHeader TemplateForOptionsopt ) TemplateBlock empty TemplateBlock\n\nJSXSwitchExpression :\n @switch ( Expression ) { JSXSwitchCaseListopt }\n\nJSXSwitchCase :\n case Expression : TemplateBlock\n default : TemplateBlock\n\nJSXTryExpression :\n @try TemplateBlock pending TemplateBlock\n @try TemplateBlock catch ( CatchParameteropt ) TemplateBlock\n
|
|
30
|
+
'# Text and Template Expressions\n\nStatic text is JSXText and can be written directly between tags. Dynamic values use normal JSX expression containers.\n\n```tsx\nfunction Greeting({ name }: { name: string }) @{\n <>\n <h1>Hello</h1>\n <p>{name}</p>\n </>\n}\n```\n\nJavaScript comments are also allowed between template children and are not rendered. Use braces for JavaScript expressions, including string literals that should be evaluated as JavaScript.\n\nSpecification grammar:\n\n```text\nJSXTextChild :\n JSXTextCharacters\n\nJSXExpressionContainer :\n { AssignmentExpression }\n\nJSXCodeBlock :\n @{ StatementListItemListopt TemplateOutput }\n\nTemplateBlock :\n { TemplateChildrenopt }\n { StatementListItemList TemplateOutput }\n\nJSXIfExpression :\n @if ( Expression ) TemplateBlock\n @if ( Expression ) TemplateBlock @else TemplateBlock\n @if ( Expression ) TemplateBlock @else JSXIfExpression\n\nJSXForExpression :\n @for ( ForHeader TemplateForOptionsopt ) TemplateBlock\n @for ( ForHeader TemplateForOptionsopt ) TemplateBlock @empty TemplateBlock\n\nJSXSwitchExpression :\n @switch ( Expression ) { JSXSwitchCaseListopt }\n\nJSXSwitchCase :\n @case Expression : TemplateBlock\n @default : TemplateBlock\n\nJSXTryExpression :\n @try TemplateBlock @pending TemplateBlock\n @try TemplateBlock @catch ( CatchParameteropt ) TemplateBlock\n```\n\nSource: website-tsrx/src/pages/specification.tsrx#templates',
|
|
31
31
|
},
|
|
32
32
|
{
|
|
33
33
|
slug: 'expression-values',
|
|
@@ -35,7 +35,7 @@ export const documentation_sections = [
|
|
|
35
35
|
use_cases:
|
|
36
36
|
'fragments, pass template as prop, return template from helper, render props, expression position jsx',
|
|
37
37
|
content:
|
|
38
|
-
'# Expression Values\n\nTSRX uses JSX-shaped expression values. A single JSXElement can be assigned, passed, or returned directly. Use a JSXFragment when the value needs multiple children, or use a JSX statement container when setup needs to produce one final output.\n\n```tsx\nfunction App() @{\n const title = <span class="title">Settings</span>;\n const badge = (label: string) => @{\n const normalized = label.trim();\n\n <span class="badge">{normalized}</span>\n };\n\n <Card title={title}>{badge(\'New\')}</Card>\n}\n```\n\n`@{ ... }` is a JSX statement container. A normal JSX fragment, element body, or control-flow branch can also contain setup before output, but that scope must still end with one output node. Use a fragment when the output is text, an expression container, or multiple siblings.\n\nSpecification grammar:\n\n```text\nPrimaryExpression :\n JSXElement\n JSXFragment\n JSXStyleElement\n JSXCodeBlock\n JSXIfExpression\n JSXForExpression\n JSXSwitchExpression\n JSXTryExpression\n```\n\nSource: website-tsrx/src/pages/specification.tsrx#expression-values',
|
|
38
|
+
'# Expression Values\n\nTSRX uses JSX-shaped expression values. A single JSXElement can be assigned, passed, or returned directly. Use a JSXFragment when the value needs multiple children, or use a JSX statement container when setup needs to produce one final output.\n\n```tsx\nfunction App() @{\n const title = <span class="title">Settings</span>;\n const badge = (label: string) => @{\n const normalized = label.trim();\n\n <span class="badge">{normalized}</span>\n };\n\n <Card title={title}>{badge(\'New\')}</Card>\n}\n```\n\n`@{ ... }` is a JSX statement container. A normal JSX fragment, element body, or control-flow branch can also contain setup before output, but that scope must still end with one output node. Use a fragment when the output is text, an expression container, or multiple siblings.\n\nWhen generating code, prefer `function Component(props) @{ ... }` for component bodies that need hooks, setup, guard returns, and final template output together. Do not silently drop the `@`; the compiler treats plain braces as a normal JavaScript function body.\n\nSpecification grammar:\n\n```text\nPrimaryExpression :\n JSXElement\n JSXFragment\n JSXStyleElement\n JSXCodeBlock\n JSXIfExpression\n JSXForExpression\n JSXSwitchExpression\n JSXTryExpression\n```\n\nSource: website-tsrx/src/pages/specification.tsrx#expression-values',
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
41
|
slug: 'control-flow',
|
|
@@ -43,7 +43,7 @@ export const documentation_sections = [
|
|
|
43
43
|
use_cases:
|
|
44
44
|
'if else, for loops, switch, try catch, conditional rendering, lists, guard returns',
|
|
45
45
|
content:
|
|
46
|
-
'# Control Flow\n\nTemplate control flow uses directive-prefixed expressions inside JSX children.\n\n```tsx\nfunction List({ items }: { items: string[] }) @{\n <>\n @if (items.length === 0) {\n <p>No items</p>\n } @else {\n <ul>\n @for (const item of items.filter(Boolean); index i; key item) {\n <li>{item}</li>\n } @empty {\n <li>No items</li>\n }\n </ul>\n }\n </>\n}\n```\n\nUse normal function returns for guard exits before entering template output. Filter a collection before passing it to `@for` when some items should not render, and use
|
|
46
|
+
'# Control Flow\n\nTemplate control flow uses directive-prefixed expressions inside JSX children.\n\n```tsx\nfunction List({ items }: { items: string[] }) @{\n <>\n @if (items.length === 0) {\n <p>No items</p>\n } @else {\n <ul>\n @for (const item of items.filter(Boolean); index i; key item) {\n <li>{item}</li>\n } @empty {\n <li>No items</li>\n }\n </ul>\n }\n </>\n}\n```\n\nUse normal function returns for guard exits before entering template output. Filter a collection before passing it to `@for` when some items should not render, and use `@empty { ... }` for the no-items fallback.\n\n`return` statements are not template output. Put guard returns before the JSX statement container or return value, or render conditionally with `@if`. Inside TSRX `@if` branches and `@for ... of` loops, direct `continue`, `break`, and `return` statements are invalid. Inside a TSRX `@switch` case body, both `break` and `return` are invalid because cases are isolated template blocks.\n\nTSRX rendering supports `@for ... of` list loops. Regular `for`, `for...in`, `while`, and `do...while` loops are not rendering constructs. Move imperative loops into setup code, a nested function, event handler, effect, or helper where normal JavaScript control-flow rules apply.\n\nSource: website-tsrx/src/pages/features.tsrx#for',
|
|
47
47
|
},
|
|
48
48
|
{
|
|
49
49
|
slug: 'lazy-destructuring',
|
|
@@ -60,6 +60,14 @@ export const documentation_sections = [
|
|
|
60
60
|
content:
|
|
61
61
|
'# Style and Server Extensions\n\nAssign a `<style>` expression to expose scoped CSS class names declared in the current module.\n\n```tsx\nconst styles = <style>\n .card { padding: 1rem; }\n</style>;\n\nexport function ChildCard() @{\n <>\n <Child class={styles.card} />\n </>\n}\n```\n\n`module server { ... }` declares a server-oriented submodule in the Ripple host profile. Import exported functions with `import { load } from server` before use.\n\nSpecification grammar:\n\n```text\nJSXStyleElement :\n <style JSXAttributesopt> CSSSource </style>\n\nSubmoduleDeclaration :\n module Identifier { ModuleItemListopt }\n\nSubmoduleImportDeclaration :\n import ImportClause from Identifier ;\n\n```\n\nSource: website-tsrx/src/pages/specification.tsrx#style',
|
|
62
62
|
},
|
|
63
|
+
{
|
|
64
|
+
slug: 'dynamic-elements-and-components',
|
|
65
|
+
title: 'Dynamic Elements and Components',
|
|
66
|
+
use_cases:
|
|
67
|
+
'dynamic elements, dynamic components, Dynamic component, is prop, runtime tag, runtime component, removed <@tag syntax',
|
|
68
|
+
content:
|
|
69
|
+
"# Dynamic Elements and Components\n\nUse the target runtime `Dynamic` component when the element tag or component constructor is chosen at runtime. The source form is ordinary JSX: `<Dynamic is={value} />`.\n\nImport `Dynamic` from the active target runtime module:\n\n| Target | Import |\n| --- | --- |\n| React | `import { Dynamic } from '@tsrx/react/dynamic';` |\n| Preact | `import { Dynamic } from '@tsrx/preact/dynamic';` |\n| Solid | `import { Dynamic } from '@tsrx/solid/dynamic';` |\n| Vue | `import { Dynamic } from '@tsrx/vue/dynamic';` |\n| Ripple | `import { Dynamic } from 'ripple';` |\n\n```tsx\nimport { Dynamic } from '@tsrx/react/dynamic';\n\ntype Tag = 'section' | 'article';\n\nexport function Panel({ as = 'section', title }: { as?: Tag; title: string }) @{\n <Dynamic is={as} className=\"panel\">\n <h2>{title}</h2>\n </Dynamic>\n}\n```\n\nThe `is` prop can be a string tag name or a component value:\n\n```tsx\nconst Body = expanded ? ExpandedBody : CompactBody;\n\n<Dynamic is={Body} item={item} />\n```\n\nFor React host classes, use `className`. For Preact, Solid, Vue, and Ripple host classes, use `class`.\n\nDo not use removed dynamic tag syntax such as `<@tag />` or `<@Component />`. Use `<Dynamic is={...} />` instead.\n\nSource: website-tsrx/src/pages/features.tsrx#dynamic",
|
|
70
|
+
},
|
|
63
71
|
{
|
|
64
72
|
slug: 'target-integration',
|
|
65
73
|
title: 'Target Integration',
|
package/src/server.js
CHANGED
|
@@ -307,8 +307,9 @@ ${project_context_step}
|
|
|
307
307
|
3. For syntax uncertainty, use \`list-sections\`, \`get-documentation\`, or read \`tsrx://docs/{slug}.md\`.
|
|
308
308
|
4. Keep core TSRX advice target-neutral: component functions, JSX expression values, JSX statement containers \`@{ ... }\`, JSX text, directive control flow, lazy destructuring, style identifiers, and submodule declarations.
|
|
309
309
|
5. Use \`tsrx://targets/{target}.md\` as the handoff point for target-specific responsibilities.
|
|
310
|
-
5a. In template output, render lists with \`@for (... of ...)\`; filter the iterable before rendering when items should be skipped, and use
|
|
310
|
+
5a. In template output, render lists with \`@for (... of ...)\`; filter the iterable before rendering when items should be skipped, and use \`@empty { ... }\` for the no-items fallback; use \`@if\`, \`@switch\`, and \`@try\` for rendering control flow. Every directive body uses a \`{...}\` template block. When a scope mixes setup with output, setup comes first and the scope ends with exactly one JSX element, JSX fragment, or JSX control-flow expression.
|
|
311
311
|
5b. \`return\` is JavaScript function control flow, not template output. Use guard returns before a JSX statement container or return value, or render conditionally with \`@if\`. Do not use \`continue\`, \`break\`, or \`return\` inside \`@if\` template branches or \`@for\` template loops. \`@switch\` cases are isolated blocks and do not use \`break\` or \`return\`.
|
|
312
|
+
5c. If a component body has setup statements followed by bare JSX/template output, use \`@{ ... }\`, not plain \`{ ... }\`. Plain braces are an ordinary JavaScript function body; the missing \`@\` is the common fix.
|
|
312
313
|
${file_validation_step}
|
|
313
314
|
${compile_step}
|
|
314
315
|
${authoring_step}
|