@hyperfixi/mcp-server 2.11.1 → 3.1.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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,14 @@ All notable changes to `@hyperfixi/mcp-server` will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ > **Superseded by the root changelog.** Every package in this monorepo publishes
9
+ > in lockstep at the root version, and the entries below use an older
10
+ > per-package numbering that no published version ever matched. They are kept
11
+ > for the migration notes they carry; they are not a record of recent releases.
12
+ > **For anything since, see
13
+ > [the monorepo CHANGELOG](https://github.com/codetalcott/hyperfixi/blob/main/CHANGELOG.md)**
14
+ > and [GitHub Releases](https://github.com/codetalcott/hyperfixi/releases).
15
+
8
16
  ## [Unreleased]
9
17
 
10
18
  ### Changed
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @hyperfixi/mcp-server
2
2
 
3
- MCP (Model Context Protocol) server for hyperscript and multilingual DSL development. Provides **108 tools**, **9 resources**, and **9 prompts** spanning: GRAIL workflow orchestration, validation, compilation, analysis, patterns, LSP bridge, language profiles, code generation, route extraction, 9 domain DSLs, IR conversion, cross-domain dispatch, MCP sampling (opt-in), AI-assisted debugging, template inventory, and the LSE round-trip pipeline.
3
+ MCP (Model Context Protocol) server for hyperscript and multilingual DSL development. Provides **103 tools** by default (**108** defined — the 5 MCP-sampling tools are opt-in and hidden unless `LOKASCRIPT_MCP_LLM_TOOLS=1`), **9 resources**, and **9 prompts** spanning: GRAIL workflow orchestration, validation, compilation, analysis, patterns, LSP bridge, language profiles, code generation, route extraction, 9 domain DSLs, IR conversion, cross-domain dispatch, MCP sampling (opt-in), AI-assisted debugging, template inventory, and the LSE round-trip pipeline.
4
4
 
5
5
  ## The agent loop
6
6
 
@@ -80,7 +80,7 @@ See **[GRAIL.md](GRAIL.md)** for full documentation, schema reference, and examp
80
80
 
81
81
  ## Available Tools
82
82
 
83
- The **103** tools below, plus the **5** GRAIL tools above, total **108**.
83
+ The **103** tools below, plus the **5** GRAIL tools above, total **108** defined. The 5 MCP-sampling tools among them are hidden from `tools/list` unless `LOKASCRIPT_MCP_LLM_TOOLS=1`, so a default connection sees **103**.
84
84
 
85
85
  ### Validation & Semantic Tools (8)
86
86
 
package/dist/index.js CHANGED
@@ -2145,12 +2145,8 @@ function getAdapterBundle(languages) {
2145
2145
  }
2146
2146
  function getBundleConfig(commands, blocks, languages, positional, runtime = "auto") {
2147
2147
  const needsMultilingual = languages.length > 1 || languages.some((l) => l !== "en");
2148
- let bundle = "hyperfixi-lite.js";
2149
- let bundleSize = "1.9 KB";
2150
- if (blocks.length > 0 || positional) {
2151
- bundle = "hyperfixi-hybrid-complete.js";
2152
- bundleSize = "6.7 KB";
2153
- }
2148
+ let bundle = "hyperfixi-hx.js";
2149
+ let bundleSize = "21.5 KB";
2154
2150
  if (needsMultilingual) {
2155
2151
  bundle = "hyperfixi-multilingual.js";
2156
2152
  bundleSize = "250 KB";
@@ -2811,8 +2807,40 @@ try {
2811
2807
  "[mcp:lsp-bridge] @lokascript/framework not available \u2014 LSE bracket notation in hover disabled"
2812
2808
  );
2813
2809
  }
2810
+ var roleInferrer = null;
2811
+ try {
2812
+ ({ schemaRoleInferrer: roleInferrer } = await import("@hyperfixi/core/multilingual"));
2813
+ } catch {
2814
+ console.error(
2815
+ "[mcp:lsp-bridge] @hyperfixi/core/multilingual not available \u2014 hover role inference limited to `set` and `go`"
2816
+ );
2817
+ }
2818
+ function parseToInterchange(code) {
2819
+ if (!astToolkit?.fromCoreAST || !parseFunction) return null;
2820
+ const result = parseFunction(code);
2821
+ const errors = Array.isArray(result?.errors) ? result.errors : [];
2822
+ const ast = result?.node ?? null;
2823
+ if (!ast || ast.type === "identifier" && ast.name === "__ERROR__") return { nodes: [], errors };
2824
+ try {
2825
+ const opts = roleInferrer ? { inferRoles: roleInferrer } : void 0;
2826
+ const statements = ast.type === "Program" && Array.isArray(ast.statements) ? ast.statements : [ast];
2827
+ const interchange = statements.flatMap((stmt) => {
2828
+ const converted = astToolkit.fromCoreAST(stmt, opts);
2829
+ return Array.isArray(converted) ? converted : [converted];
2830
+ });
2831
+ const nodes = interchange.filter(
2832
+ // `fromCoreAST` emits an `error` node for a kind it cannot represent
2833
+ // (`def`, `behavior`, …) rather than throwing. That is a converter limit,
2834
+ // not a user error: it must not become a diagnostic or a hover.
2835
+ (n) => n?.type !== "error"
2836
+ );
2837
+ return { nodes, errors };
2838
+ } catch {
2839
+ return { nodes: [], errors };
2840
+ }
2841
+ }
2814
2842
  console.error(
2815
- `[mcp:lsp-bridge] capabilities: ast=${!!astToolkit}, parse=${!!parseFunction}, semantic=${!!semanticPackage2}, framework=${!!frameworkIR}`
2843
+ `[mcp:lsp-bridge] capabilities: ast=${!!astToolkit}, parse=${!!parseFunction}, semantic=${!!semanticPackage2}, framework=${!!frameworkIR}, roles=${!!roleInferrer}`
2816
2844
  );
2817
2845
  var cachedAnalyzer2 = null;
2818
2846
  function getSemanticAnalyzer2() {
@@ -3036,12 +3064,25 @@ async function getDiagnostics(code, language, _uri) {
3036
3064
  } catch {
3037
3065
  }
3038
3066
  }
3039
- if (diagnostics.length === 0 && astToolkit && parseFunction) {
3067
+ if (diagnostics.length === 0 && astToolkit?.interchangeToLSPDiagnostics && parseFunction) {
3040
3068
  try {
3041
- const ast = parseFunction(code);
3042
- if (ast && astToolkit.astToLSPDiagnostics) {
3043
- const astDiagnostics = astToolkit.astToLSPDiagnostics(ast);
3044
- diagnostics.push(...astDiagnostics);
3069
+ const parsed = parseToInterchange(code);
3070
+ for (const err of parsed?.errors ?? []) {
3071
+ const line = Math.max(0, (err.line ?? 1) - 1);
3072
+ const character = Math.max(0, err.column ?? 0);
3073
+ diagnostics.push({
3074
+ range: { start: { line, character }, end: { line, character: character + 10 } },
3075
+ severity: 1,
3076
+ // Error
3077
+ code: "parse-error",
3078
+ source: "hyperfixi-mcp",
3079
+ message: err.message
3080
+ });
3081
+ }
3082
+ if (parsed?.nodes.length) {
3083
+ diagnostics.push(
3084
+ ...astToolkit.interchangeToLSPDiagnostics(parsed.nodes, { source: "hyperfixi-mcp" })
3085
+ );
3045
3086
  }
3046
3087
  } catch (parseError) {
3047
3088
  diagnostics.push({
@@ -3291,12 +3332,13 @@ function runSimpleDiagnostics(code, language = "en") {
3291
3332
  }
3292
3333
  async function getCompletions(code, line, character, language, context) {
3293
3334
  const completions = [];
3294
- if (astToolkit && parseFunction) {
3335
+ if (astToolkit?.interchangeToLSPCompletions && parseFunction) {
3295
3336
  try {
3296
- const ast = parseFunction(code);
3297
- if (ast && astToolkit.astToLSPCompletions) {
3298
- const astCompletions = astToolkit.astToLSPCompletions(ast, { line, character });
3299
- completions.push(...astCompletions);
3337
+ const parsed = parseToInterchange(code);
3338
+ if (parsed?.nodes.length) {
3339
+ completions.push(
3340
+ ...astToolkit.interchangeToLSPCompletions(parsed.nodes, { line, character })
3341
+ );
3300
3342
  }
3301
3343
  } catch {
3302
3344
  }
@@ -3453,10 +3495,9 @@ function inferContext(beforeCursor) {
3453
3495
  async function getHoverInfo(code, line, character, language) {
3454
3496
  if (astToolkit && parseFunction && astToolkit.fromCoreAST && astToolkit.interchangeToLSPHover) {
3455
3497
  try {
3456
- const ast = parseFunction(code);
3457
- if (ast) {
3458
- const interchange = astToolkit.fromCoreAST(ast);
3459
- const nodes = Array.isArray(interchange) ? interchange : [interchange];
3498
+ const parsed = parseToInterchange(code);
3499
+ if (parsed?.nodes.length) {
3500
+ const nodes = parsed.nodes;
3460
3501
  const hoverOptions = {};
3461
3502
  if (frameworkIR) {
3462
3503
  hoverOptions.renderLSE = (node) => frameworkIR.renderExplicit(frameworkIR.fromInterchangeNode(node));
@@ -3579,12 +3620,11 @@ function getHoverDocumentation(word, language = "en") {
3579
3620
  }
3580
3621
  async function getDocumentSymbols(code, language) {
3581
3622
  const symbols = [];
3582
- if (astToolkit && parseFunction) {
3623
+ if (astToolkit?.interchangeToLSPSymbols && parseFunction) {
3583
3624
  try {
3584
- const ast = parseFunction(code);
3585
- if (ast && astToolkit.astToLSPSymbols) {
3586
- const astSymbols = astToolkit.astToLSPSymbols(ast);
3587
- symbols.push(...astSymbols);
3625
+ const parsed = parseToInterchange(code);
3626
+ if (parsed?.nodes.length) {
3627
+ symbols.push(...astToolkit.interchangeToLSPSymbols(parsed.nodes));
3588
3628
  }
3589
3629
  } catch {
3590
3630
  }
@@ -5621,12 +5661,15 @@ var compilationTools = [
5621
5661
  }
5622
5662
  ];
5623
5663
  var REPAIR_HINT = "Next step: apply the diagnostics above and re-run validate_and_compile. If an error names a code (e.g. MISSING.ARGUMENT), get_code_fixes returns concrete fixes for it; get_command_docs lists the roles each command accepts.";
5664
+ var REVIEW_HINT = "This parsed, but the diagnostics above are non-empty. A warning such as UNCONSUMED_INPUT means tokens were parsed but bound to no role, so a role may have fallen back to a default (often `me`) \u2014 the result can look valid while doing something other than you intended. Compare the returned action/roles/trigger against your intent before compiling; score_fidelity can prove a rewrite kept the original meaning.";
5624
5665
  function compileResult(result) {
5625
5666
  const content = [
5626
5667
  { type: "text", text: JSON.stringify(result, null, 2) }
5627
5668
  ];
5628
5669
  if (!result.ok) {
5629
5670
  content.push({ type: "text", text: REPAIR_HINT });
5671
+ } else if (result.diagnostics?.some((d) => d.severity === "warning")) {
5672
+ content.push({ type: "text", text: REVIEW_HINT });
5630
5673
  }
5631
5674
  return { content, isError: !result.ok };
5632
5675
  }
@@ -10567,6 +10610,7 @@ function readResource(uri) {
10567
10610
  var registry = createDomainRegistry();
10568
10611
  var { version: pkgVersion } = createRequire2(import.meta.url)("../package.json");
10569
10612
  var LLM_SAMPLING_ENABLED = process.env.LOKASCRIPT_MCP_LLM_TOOLS === "1";
10613
+ var SAMPLING_TOOL_NAMES = new Set(samplingTools.map((t) => t.name));
10570
10614
  var SERVER_INSTRUCTIONS = `Deterministic tooling for hyperscript (a compact DOM-behavior DSL) in 24 human languages. No tool here calls an LLM \u2014 every check is a real parser/compiler you can trust.
10571
10615
 
10572
10616
  The core loop for GENERATING hyperscript:
@@ -10633,7 +10677,7 @@ function buildServer() {
10633
10677
  if (stale.length > 0) {
10634
10678
  return staleToolError(stale);
10635
10679
  }
10636
- if (name.startsWith("analyze_") || name === "explain_code" || name === "recognize_intent") {
10680
+ if (name.startsWith("analyze_") && !SAMPLING_TOOL_NAMES.has(name) || name === "explain_code" || name === "recognize_intent") {
10637
10681
  return handleAnalysisTool(name, args);
10638
10682
  }
10639
10683
  if (name === "search_patterns" || name === "translate_hyperscript" || name === "get_pattern_stats") {
@@ -10674,7 +10718,7 @@ function buildServer() {
10674
10718
  if (name === "extract_routes" || name === "generate_server_routes") {
10675
10719
  return handleRouteTool(name, args);
10676
10720
  }
10677
- if (name === "ask_claude" || name === "summarize_content" || name === "analyze_content" || name === "translate_content" || name === "execute_llm") {
10721
+ if (SAMPLING_TOOL_NAMES.has(name)) {
10678
10722
  if (!LLM_SAMPLING_ENABLED) {
10679
10723
  return {
10680
10724
  content: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperfixi/mcp-server",
3
- "version": "2.11.1",
3
+ "version": "3.1.0",
4
4
  "description": "Model Context Protocol server for HyperFixi hyperscript development",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -37,22 +37,22 @@
37
37
  "author": "LokaScript Contributors",
38
38
  "license": "MIT",
39
39
  "dependencies": {
40
- "@hyperfixi/patterns-reference": "^2.11.1",
41
- "@lokascript/compilation-service": "^2.11.1",
40
+ "@hyperfixi/patterns-reference": "^3.1.0",
41
+ "@lokascript/compilation-service": "^3.1.0",
42
42
  "@lokascript/domains": "^2.11.1",
43
- "@lokascript/framework": "^2.11.1",
44
- "@lokascript/planner": "^2.11.1",
45
- "@lokascript/semantic": "^2.11.1",
43
+ "@lokascript/framework": "^3.1.0",
44
+ "@lokascript/planner": "^3.1.0",
45
+ "@lokascript/semantic": "^3.1.0",
46
46
  "@modelcontextprotocol/server": "^2.0.0",
47
47
  "yaml": "^2.8.3"
48
48
  },
49
49
  "peerDependencies": {
50
- "@hyperfixi/core": "^2.11.1",
51
- "@hyperfixi/patterns-reference": "^2.11.1",
52
- "@hyperfixi/server-bridge": "^2.11.1",
53
- "@lokascript/compilation-service": "^2.11.1",
54
- "@lokascript/framework": "^2.11.1",
55
- "@lokascript/semantic": "^2.11.1"
50
+ "@hyperfixi/core": "^3.1.0",
51
+ "@hyperfixi/patterns-reference": "^3.1.0",
52
+ "@hyperfixi/server-bridge": "^3.1.0",
53
+ "@lokascript/compilation-service": "^3.1.0",
54
+ "@lokascript/framework": "^3.1.0",
55
+ "@lokascript/semantic": "^3.1.0"
56
56
  },
57
57
  "peerDependenciesMeta": {
58
58
  "@lokascript/compilation-service": {
@@ -75,12 +75,12 @@
75
75
  }
76
76
  },
77
77
  "devDependencies": {
78
- "@hyperfixi/core": "^2.11.1",
79
- "@hyperfixi/patterns-reference": "^2.11.1",
80
- "@hyperfixi/server-bridge": "^2.11.1",
81
- "@lokascript/compilation-service": "^2.11.1",
82
- "@lokascript/framework": "^2.11.1",
83
- "@lokascript/semantic": "^2.11.1",
78
+ "@hyperfixi/core": "^3.1.0",
79
+ "@hyperfixi/patterns-reference": "^3.1.0",
80
+ "@hyperfixi/server-bridge": "^3.1.0",
81
+ "@lokascript/compilation-service": "^3.1.0",
82
+ "@lokascript/framework": "^3.1.0",
83
+ "@lokascript/semantic": "^3.1.0",
84
84
  "@types/node": "^26.1.2",
85
85
  "tsup": "^8.0.0",
86
86
  "tsx": "^4.23.1",