Skip to content

Conversation

@rahmanunver
Copy link
Contributor

Pull request type

New feature (non-breaking change which adds functionality)


Description

@mendix/pluggable-widgets-mcp — AI-Assisted Widget Development

A new MCP server that lets AI assistants (Claude, GPT, etc.) scaffold and build Mendix widgets on your behalf.

The Goal

Lower the barrier to widget development. Getting started with widgets takes too many hurdles. This server gives you a first working version of the widget you describe, something you can iterate on later, without needing to know the scaffolding steps or our XML schema.

The AI follows our conventions because we provide guidelines as MCP resources. The only limit is the LLM's intelligence; everything else happens the way we do it as the web-content team.

Key Points

  • Transport modes: STDIO (Claude Desktop, Claude Code) or HTTP (web clients)
  • Output: Widgets are generated in a generations/ folder; build-widget produces .mpk files
  • Security: Path traversal blocked, extension whitelist enforced
  • Progress notifications don't appear in chat — this is per MCP spec, not a bug. Use MCP Inspector to see them.

What should be covered while testing?

cd packages/pluggable-widgets-mcp
pnpm install && pnpm build

Link globally for easier access:

   npm link  # Use npm, not pnpm, for better client compatibility

Claude Desktop config (On Mac: ~/Library/Application Support/Claude/claude_desktop_config.json):

{
    "mcpServers": {
        "pluggable-widgets-mcp": {
            "type": "stdio",
            "command": "pluggable-widgets-mcp"
        }
    }
}

Restart Claude Desktop and try: "Create a widget called ProgressCircle that shows a percentage in a circular progress bar"

For debugging, use MCP Inspector:

npx @modelcontextprotocol/inspector node dist/index.js stdio

Example test flow

  1. "Create a widget called ColorPicker with a color attribute property"
  2. "List the files in the ColorPicker widget"
  3. "Read the ColorPicker.xml file"
  4. "Update the widget to add an onChange action property"
  5. "Build the ColorPicker widget"
    (In this example every step and tool is explicitly prompted. You won't acutally have to be this verbose with a decent LLM)

See packages/pluggable-widgets-mcp/README.md for full docs.

@rahmanunver rahmanunver requested a review from a team as a code owner January 20, 2026 08:27
Comment on lines +300 to +310
### entity

Entity selector.

```json
{
"key": "targetEntity",
"type": "entity",
"caption": "Target entity"
}
```
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type doesn't exist

Comment on lines +276 to +281
```xml
<property key="dataSource" type="datasource" isList="true" required="false">
<caption>Data source</caption>
<description>Source of items to display</description>
</property>
```
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to let it know about XML? If we have high level definition of how properties look like, we might just treat XML as black box, so LLM doesn't need to dive into it. Let's discuss this.

Comment on lines +480 to +484
```json
{
"systemProperties": ["Name", "TabIndex", "Visibility"]
}
```
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can define every system property as a standalone property of particular shape, similar to other properties.

Something like:

{
    type: "system",
    name: "TabIndex"
}

Comment on lines +494 to +502
```xml
<propertyGroup caption="Common">
<systemProperty key="Name" />
<systemProperty key="TabIndex" />
</propertyGroup>
<propertyGroup caption="Visibility">
<systemProperty key="Visibility" />
</propertyGroup>
```
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Property groups have to be defined separately, they are not autogenerated. But we probably don't want to expose XML if we see it as implementation details.


---

## Full Widget Definition Example
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not clear how Property Groups are defined, are they part of this JSON, or supplied in a different was somehow?

Comment on lines +46 to +47
type WriteWidgetFileInput = z.infer<typeof writeWidgetFileSchema>;
type BatchWriteWidgetFilesInput = z.infer<typeof batchWriteWidgetFilesSchema>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those are two ways for doing essentially the same, can this confuse LLM more that it helps?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this file is empty

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we use this? I see currently LLM is able to read XML file directly, I didn't find where it communicates properties in json format.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants