@@ -19,16 +19,24 @@ This package implements an MCP server that enables AI assistants to scaffold and
1919src/
2020├── index.ts # Entry point - transport mode selection
2121├── config.ts # Server configuration and constants
22+ ├── security/
23+ │ ├── guardrails.ts # Security validation (path traversal, extension whitelist)
24+ │ └── index.ts # Security module exports
2225├── server/
23- │ ├── server.ts # MCP server factory and tool registration
26+ │ ├── server.ts # MCP server factory and tool/resource registration
2427│ ├── http.ts # HTTP transport setup (Express)
2528│ ├── stdio.ts # STDIO transport setup
2629│ ├── routes.ts # Express route handlers
2730│ └── session.ts # HTTP session management
31+ ├── resources/
32+ │ ├── index.ts # Resource registration
33+ │ └── guidelines.ts # Widget development guidelines
2834└── tools/
29- ├── index.ts # Tool aggregation
35+ ├── index.ts # Tool registration aggregation
3036 ├── types.ts # MCP tool type definitions
31- ├── scaffolding.tools.ts # Widget creation tool
37+ ├── scaffolding.tools.ts # Widget creation (create-widget)
38+ ├── file-operations.tools.ts # File read/write/list operations
39+ ├── build.tools.ts # Widget building and validation
3240 └── utils/
3341 ├── generator.ts # Widget generator PTY wrapper
3442 ├── progress-tracker.ts # Progress/logging helper
4250
4351The server supports two transport modes selected via CLI argument:
4452
45- - ** HTTP ** (default): Multi -session Express server on port 3100
46- - ** STDIO ** : Single -session stdin/stdout for CLI integration
53+ - ** STDIO ** (default): Single -session stdin/stdout for CLI integration (Claude Code, Claude Desktop)
54+ - ** HTTP ** : Multi -session Express server on port 3100 for web clients and testing
4755
4856### Tool Registration
4957
50- Tools are defined using the ` ToolDefinition<T> ` interface :
58+ Tools are registered directly with the MCP server using the SDK's ` server.tool() ` method. The current architecture uses category-based registration functions :
5159
5260``` typescript
53- interface ToolDefinition <T > {
54- name: string ; // Tool identifier
55- title: string ; // Human-readable name
56- description: string ; // LLM-facing description
57- inputSchema: ZodType <T >; // Zod schema for validation
58- handler: ToolHandler <T >; // Async handler function
61+ // src/tools/index.ts
62+ export function registerAllTools(server : McpServer ): void {
63+ registerScaffoldingTools (server ); // Widget creation
64+ registerFileOperationTools (server ); // File operations
65+ registerBuildTools (server ); // Building & validation
5966}
6067```
6168
62- New tools should be :
69+ ** Available Tools ** :
6370
64- 1 . Created in ` src/tools/ ` with a ` *.tools.ts ` suffix
65- 2 . Export a ` get*Tools() ` function returning ` ToolDefinition[] `
66- 3 . Registered in ` src/tools/index.ts `
71+ - ** Scaffolding** : ` create-widget ` - Scaffolds new widgets via PTY interaction
72+ - ** File Operations** :
73+ - ` list-widget-files ` - Lists files in widget directory
74+ - ` read-widget-file ` - Reads widget file contents
75+ - ` write-widget-file ` - Writes single file
76+ - ` batch-write-widget-files ` - Writes multiple files atomically
77+ - ** Build** : ` build-widget ` - Compiles widget and parses errors (TypeScript, XML, dependencies)
78+
79+ ### Resources
80+
81+ MCP resources provide read-only documentation that clients can fetch on-demand:
82+
83+ ``` typescript
84+ // src/resources/index.ts
85+ export function registerResources(server : McpServer ): void {
86+ registerGuidelineResources (server ); // Widget development guidelines
87+ }
88+ ```
89+
90+ Resources are loaded from ` docs/ ` directory and exposed via URIs like ` resource://guidelines/property-types ` .
6791
6892### Widget Generator Integration
6993
@@ -78,53 +102,57 @@ The `create-widget` tool uses `node-pty` to interact with the Mendix widget gene
78102
79103``` bash
80104pnpm dev # Development mode with hot reload (tsx watch)
81- pnpm build # TypeScript compilation + path alias resolution
82- pnpm start # Build and run (HTTP mode)
105+ pnpm build # TypeScript compilation + path alias resolution (preserves shebang)
106+ pnpm start # Build and run (HTTP mode on port 3100 )
83107pnpm start:stdio # Build and run (STDIO mode)
84- pnpm lint # ESLint + Prettier check
108+ pnpm lint # ESLint check
85109```
86110
87111## Adding New Tools
88112
891131 . ** Create tool file** : ` src/tools/my-feature.tools.ts `
90114
91115``` typescript
116+ import type { McpServer } from " @modelcontextprotocol/sdk/server/mcp.js" ;
92117import { z } from " zod" ;
93- import type { ToolDefinition , ToolResponse } from " @/tools/types" ;
94- import { createToolResponse , createErrorResponse } from " @/tools/utils/response" ;
95118
96- const mySchema = z .object ({
119+ const myToolSchema = z .object ({
97120 param: z .string ().describe (" Parameter description for LLM" )
98121});
99122
100- type MyInput = z .infer <typeof mySchema >;
101-
102- export function getMyTools(): ToolDefinition <MyInput >[] {
103- return [
104- {
105- name: " my-tool" ,
106- title: " My Tool" ,
107- description: " What this tool does (shown to LLM)" ,
108- inputSchema: mySchema ,
109- handler : async (args , context ) => {
110- // Implementation
111- return createToolResponse (" Success message" );
112- }
123+ export function registerMyTools(server : McpServer ): void {
124+ server .tool (
125+ " my-tool" , // Tool name
126+ " Description shown to LLM" , // Tool description
127+ myToolSchema , // Input validation schema
128+ async ({ param }) => {
129+ // Handler with typed args
130+ // Implementation
131+ return {
132+ content: [
133+ {
134+ type: " text" ,
135+ text: " Success message"
136+ }
137+ ]
138+ };
113139 }
114- ];
140+ );
141+
142+ console .error (" [my-feature] Registered 1 tool" );
115143}
116144```
117145
1181462 . ** Register in index** : Update ` src/tools/index.ts `
119147
120148``` typescript
121- import { getMyTools } from " ./my-feature.tools" ;
149+ import { registerMyTools } from " ./my-feature.tools" ;
122150
123- export function getAllTools( ): AnyToolDefinition [] {
124- return [
125- ... getScaffoldingTools (),
126- ... getMyTools () // Add here
127- ];
151+ export function registerAllTools( server : McpServer ): void {
152+ registerScaffoldingTools ( server );
153+ registerFileOperationTools ( server );
154+ registerBuildTools ( server );
155+ registerMyTools ( server ); // Add here
128156}
129157```
130158
@@ -145,8 +173,8 @@ export function getAllTools(): AnyToolDefinition[] {
145173### Type Safety
146174
147175- All tool inputs must have Zod schemas
148- - Use ` ToolContext ` for MCP-provided context (notifications, progress)
149- - Avoid ` any ` except in ` AnyToolDefinition ` (required for heterogeneous tool arrays)
176+ - Tool handlers receive fully typed arguments via Zod inference
177+ - Use ` McpServer ` methods directly for type-safe tool registration
150178
151179## Testing
152180
@@ -162,14 +190,38 @@ npx @modelcontextprotocol/inspector
162190# Connect to http://localhost:3100/mcp
163191```
164192
193+ ## Security
194+
195+ All security validation is centralized in ` src/security/guardrails.ts ` for easy auditing:
196+
197+ ``` typescript
198+ import { validateFilePath , ALLOWED_EXTENSIONS } from " @/security" ;
199+
200+ // Validates path traversal and extension whitelist
201+ validateFilePath (widgetPath , filePath , true ); // true = check extension
202+ ```
203+
204+ ### Security Measures
205+
206+ | Protection | Function | Description |
207+ | ------------------- | ------------------------- | ------------------------------------------------------------------- |
208+ | Path Traversal | ` validateFilePath() ` | Blocks ` .. ` sequences and resolved path escapes |
209+ | Extension Whitelist | ` isExtensionAllowed() ` | Only allows: ` .tsx ` , ` .ts ` , ` .xml ` , ` .scss ` , ` .css ` , ` .json ` , ` .md ` |
210+ | Directory Boundary | ` isPathWithinDirectory() ` | Ensures files stay within widget directory |
211+
212+ When adding file operation tools, always use ` validateFilePath() ` from the security module.
213+
165214## Key Files Reference
166215
167- | File | Purpose |
168- | -------------------------- | -------------------------------------- |
169- | ` config.ts ` | All constants (ports, timeouts, paths) |
170- | ` tools/types.ts ` | MCP tool type definitions |
171- | ` tools/utils/generator.ts ` | Widget generator prompts and defaults |
172- | ` server/session.ts ` | HTTP session lifecycle management |
216+ | File | Purpose |
217+ | -------------------------- | ------------------------------------------------ |
218+ | ` config.ts ` | Server constants (ports, timeouts, paths) |
219+ | ` security/guardrails.ts ` | Security validation (path traversal, extensions) |
220+ | ` tools/index.ts ` | Tool registration aggregation |
221+ | ` tools/utils/generator.ts ` | Widget generator PTY prompts and defaults |
222+ | ` resources/guidelines.ts ` | Widget development guideline resources |
223+ | ` server/session.ts ` | HTTP session lifecycle management |
224+ | ` server/server.ts ` | MCP server factory and registration entry point |
173225
174226## Common Patterns
175227
0 commit comments