@golemui/gui-mcp 0.16.0 → 0.16.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/CHANGELOG.md +26 -0
- package/README.md +49 -5
- package/cli.js +76 -0
- package/{index.js → get-concept-CHgtnDXr.js} +1480 -1543
- package/lib.d.ts +7 -0
- package/lib.js +13 -0
- package/lint/reactive-expressions.d.ts +18 -0
- package/lint/string-interpolation.d.ts +16 -0
- package/mapping/json-schema-to-gui.d.ts +56 -0
- package/mapping/validator.d.ts +29 -0
- package/package.json +21 -11
- package/schemas/ajv.d.ts +5 -0
- package/schemas/index.d.ts +16 -0
- package/schemas/shallow-validators.d.ts +13 -0
- package/tools/generate-from-json-schema.d.ts +48 -0
- package/tools/generate-from-openapi.d.ts +81 -0
- package/tools/get-concept.d.ts +30 -0
- package/tools/get-widget-spec.d.ts +28 -0
- package/tools/validate-form-definition.d.ts +29 -0
- package/utils/errors.d.ts +28 -0
- /package/{index.d.ts → cli.d.ts} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
## 0.16.1 (2026-05-30)
|
|
2
|
+
|
|
3
|
+
### 🚀 Features
|
|
4
|
+
|
|
5
|
+
- **mcp:** expose tool functions as an importable library alongside the CLI ([#146](https://github.com/golemui/golemui/pull/146))
|
|
6
|
+
|
|
7
|
+
### ❤️ Thank You
|
|
8
|
+
|
|
9
|
+
- Mud Scientist
|
|
10
|
+
|
|
11
|
+
## 0.16.0 (2026-05-30)
|
|
12
|
+
|
|
13
|
+
### 🚀 Features
|
|
14
|
+
|
|
15
|
+
- **core:** improved string interpolation with full expression support ([#143](https://github.com/golemui/golemui/pull/143))
|
|
16
|
+
- **mcp:** add get_concept tool and fix reactive-expression lint ([#138](https://github.com/golemui/golemui/pull/138))
|
|
17
|
+
|
|
18
|
+
### 🩹 Fixes
|
|
19
|
+
|
|
20
|
+
- **schemas:** clean up and enrich JSON schema definitions ([#145](https://github.com/golemui/golemui/pull/145))
|
|
21
|
+
|
|
22
|
+
### ❤️ Thank You
|
|
23
|
+
|
|
24
|
+
- mudscientist
|
|
25
|
+
- Raúl Jiménez @Elecash
|
|
26
|
+
|
|
1
27
|
## 0.15.1 (2026-05-27)
|
|
2
28
|
|
|
3
29
|
This was a version bump only for gui-mcp to align it with other projects, there were no code changes.
|
package/README.md
CHANGED
|
@@ -82,6 +82,50 @@ single GolemUI widget. Cheaper than dumping the whole API into the model's conte
|
|
|
82
82
|
**Input:** `{ widgetType }` (one of the widget `type` constants — `textinput`,
|
|
83
83
|
`dropdown`, `repeater`, `flex`, etc.)
|
|
84
84
|
|
|
85
|
+
### `get_concept`
|
|
86
|
+
|
|
87
|
+
Returns a detailed guide for a cross-cutting concept - things that span multiple widgets
|
|
88
|
+
and affect the whole form. Use it when you need state-suffixed props
|
|
89
|
+
(`"label.stateName": "..."`) or to reuse a condition across multiple widgets via
|
|
90
|
+
`include`/`exclude`. Currently supported: `"states"`, `"string-interpolation"`.
|
|
91
|
+
|
|
92
|
+
**Input:** `{ concept }` - one of `"states"`, `"string-interpolation"`
|
|
93
|
+
|
|
94
|
+
## Library usage
|
|
95
|
+
|
|
96
|
+
The package also exports all tools as plain functions, so you can call them directly
|
|
97
|
+
from Node.js apps, scripts, or other libraries without running an MCP server.
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
npm install @golemui/gui-mcp
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
import {
|
|
105
|
+
validateFormDefinition,
|
|
106
|
+
generateFromJsonSchema,
|
|
107
|
+
generateFromOpenapi,
|
|
108
|
+
getWidgetSpec,
|
|
109
|
+
getConcept,
|
|
110
|
+
} from '@golemui/gui-mcp';
|
|
111
|
+
|
|
112
|
+
// Validate a form definition
|
|
113
|
+
const result = validateFormDefinition({ formDefinition: myForm });
|
|
114
|
+
if (!result.valid) console.error(result.errors);
|
|
115
|
+
|
|
116
|
+
// Generate a form from a JSON Schema
|
|
117
|
+
const { form, unmapped } = generateFromJsonSchema({ jsonSchema: mySchema });
|
|
118
|
+
|
|
119
|
+
// Generate a form from an OpenAPI spec
|
|
120
|
+
const { form } = await generateFromOpenapi({
|
|
121
|
+
documentUrl: 'https://example.com/openapi.json',
|
|
122
|
+
operation: 'POST /users',
|
|
123
|
+
});
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
The tool descriptor objects (`VALIDATE_FORM_DEFINITION_TOOL`, `GENERATE_FROM_JSON_SCHEMA_TOOL`, ...)
|
|
127
|
+
are also exported if you want to register the tools in your own MCP server.
|
|
128
|
+
|
|
85
129
|
## How it stays accurate
|
|
86
130
|
|
|
87
131
|
The server ships a frozen snapshot of the GolemUI JSON Schemas inside its npm package,
|
|
@@ -97,7 +141,7 @@ _grounding layer_ the host IDE's model calls into.
|
|
|
97
141
|
|
|
98
142
|
### Interactive testing with MCP Inspector
|
|
99
143
|
|
|
100
|
-
Start the MCP server and open a local web UI at http://localhost:5173
|
|
144
|
+
Start the MCP server and open a local web UI at <http://localhost:5173>
|
|
101
145
|
|
|
102
146
|
```bash
|
|
103
147
|
npm run start:mcp
|
|
@@ -105,17 +149,17 @@ npm run start:mcp
|
|
|
105
149
|
|
|
106
150
|
To use the server from within Claude Code conversations, register with local Claude Code:
|
|
107
151
|
|
|
108
|
-
#### With the
|
|
152
|
+
#### With the Claude code CLI
|
|
109
153
|
|
|
110
154
|
```bash
|
|
111
|
-
claude mcp add golemui-local -- node /Users/{USER}/{...}/golem/golemui/dist/libs/gui/mcp/
|
|
155
|
+
claude mcp add golemui-local -- node /Users/{USER}/{...}/golem/golemui/dist/libs/gui/mcp/cli.js
|
|
112
156
|
```
|
|
113
157
|
|
|
114
158
|
Then restart or reload the session. The tools appear in Claude's tool list.
|
|
115
159
|
|
|
116
160
|
Remove with claude mcp remove golemui-local when done.
|
|
117
161
|
|
|
118
|
-
#### With the
|
|
162
|
+
#### With the Claude code extension
|
|
119
163
|
|
|
120
164
|
Create or edit the project-level MCP config at .mcp.json in the workspace root:
|
|
121
165
|
|
|
@@ -124,7 +168,7 @@ Create or edit the project-level MCP config at .mcp.json in the workspace root:
|
|
|
124
168
|
"mcpServers": {
|
|
125
169
|
"golemui-local": {
|
|
126
170
|
"command": "node",
|
|
127
|
-
"args": ["/Users/{USER}/{...}/golem/golemui/dist/libs/gui/mcp/
|
|
171
|
+
"args": ["/Users/{USER}/{...}/golem/golemui/dist/libs/gui/mcp/cli.js"]
|
|
128
172
|
}
|
|
129
173
|
}
|
|
130
174
|
}
|
package/cli.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
6
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
7
|
+
import { ListToolsRequestSchema, CallToolRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
8
|
+
import { V as VALIDATE_FORM_DEFINITION_TOOL, G as GENERATE_FROM_JSON_SCHEMA_TOOL, b as GENERATE_FROM_OPENAPI_TOOL, d as GET_WIDGET_SPEC_TOOL, f as GET_CONCEPT_TOOL, e as getConcept, c as getWidgetSpec, a as generateFromOpenapi, g as generateFromJsonSchema, v as validateFormDefinition } from "./get-concept-CHgtnDXr.js";
|
|
9
|
+
function readPackageMeta() {
|
|
10
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
for (const candidate of [join(here, "package.json"), join(here, "..", "package.json")]) {
|
|
12
|
+
try {
|
|
13
|
+
const pkg = JSON.parse(readFileSync(candidate, "utf-8"));
|
|
14
|
+
if (pkg.name && pkg.version) return { name: pkg.name, version: pkg.version };
|
|
15
|
+
} catch {
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return { name: "@golemui/gui-mcp", version: "0.0.0" };
|
|
19
|
+
}
|
|
20
|
+
const { name: PKG_NAME, version: PKG_VERSION } = readPackageMeta();
|
|
21
|
+
const TOOLS = [
|
|
22
|
+
VALIDATE_FORM_DEFINITION_TOOL,
|
|
23
|
+
GENERATE_FROM_JSON_SCHEMA_TOOL,
|
|
24
|
+
GENERATE_FROM_OPENAPI_TOOL,
|
|
25
|
+
GET_WIDGET_SPEC_TOOL,
|
|
26
|
+
GET_CONCEPT_TOOL
|
|
27
|
+
];
|
|
28
|
+
const SERVER_INSTRUCTIONS = 'This server builds and validates GolemUI form definitions — declarative, JSON-serializable forms shaped as `{ form: [...widgets], states?: {...} }`. Its job is to help you produce a form definition that is guaranteed correct before the user pastes it into their codebase.\n\nRecommended workflow:\n1. Starting from an existing schema? Use a generator — both return a pre-validated definition, so check the returned `unmapped` list and surface anything left over to the user. For a raw JSON Schema (e.g. an API request body), call `generate_from_json_schema`. For an OpenAPI 3.x spec, call `generate_from_openapi`: pass `operation` as "METHOD /path" (e.g. "POST /users") or an exact operationId, plus the spec as a parsed `document` or a `documentUrl` to fetch — it resolves the operation\'s request body, dereferences `$ref`s, and falls back to the operation\'s parameters when there is no request body.\n2. Building or editing by hand? Look up a single widget with `get_widget_spec` (its `kind`, `props`, and `validator` shape), and cross-cutting behavior that spans widgets — conditional rendering, per-state prop overrides — with `get_concept`.\n3. ALWAYS finish by calling `validate_form_definition`. It checks the definition against the bundled JSON Schemas and returns `{ valid, errors, warnings, expressionWarnings }`. Treat `errors` as blocking: fix them and re-validate until `valid` is true. `warnings` (likely-custom widgets) and `expressionWarnings` (linted reactive expressions) are advisory — surface them, but they do not flip `valid`.\n\nDo not hand a form definition to the user until `validate_form_definition` reports `valid: true`.';
|
|
29
|
+
const server = new Server(
|
|
30
|
+
{ name: PKG_NAME, version: PKG_VERSION },
|
|
31
|
+
{ capabilities: { tools: {} }, instructions: SERVER_INSTRUCTIONS }
|
|
32
|
+
);
|
|
33
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));
|
|
34
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
35
|
+
const { name, arguments: args } = request.params;
|
|
36
|
+
try {
|
|
37
|
+
switch (name) {
|
|
38
|
+
case "validate_form_definition":
|
|
39
|
+
return ok(validateFormDefinition(args));
|
|
40
|
+
case "generate_from_json_schema":
|
|
41
|
+
return ok(generateFromJsonSchema(args));
|
|
42
|
+
case "generate_from_openapi":
|
|
43
|
+
return ok(await generateFromOpenapi(args));
|
|
44
|
+
case "get_widget_spec":
|
|
45
|
+
return ok(getWidgetSpec(args));
|
|
46
|
+
case "get_concept":
|
|
47
|
+
return ok(getConcept(args));
|
|
48
|
+
default:
|
|
49
|
+
return err(`Unknown tool: ${name}`);
|
|
50
|
+
}
|
|
51
|
+
} catch (e) {
|
|
52
|
+
return err(e.message);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
function ok(payload) {
|
|
56
|
+
return {
|
|
57
|
+
content: [{ type: "text", text: JSON.stringify(payload, null, 2) }]
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function err(message) {
|
|
61
|
+
return {
|
|
62
|
+
isError: true,
|
|
63
|
+
content: [{ type: "text", text: message }]
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
async function main() {
|
|
67
|
+
const transport = new StdioServerTransport();
|
|
68
|
+
await server.connect(transport);
|
|
69
|
+
process.stderr.write(`${PKG_NAME} v${PKG_VERSION} ready on stdio
|
|
70
|
+
`);
|
|
71
|
+
}
|
|
72
|
+
main().catch((e) => {
|
|
73
|
+
process.stderr.write(`${PKG_NAME} failed to start: ${e.stack ?? e}
|
|
74
|
+
`);
|
|
75
|
+
process.exit(1);
|
|
76
|
+
});
|