wlmaker 1.5.0 → 1.6.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.
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/mcp-install.ts
4
+ import * as fs from "fs";
5
+ import * as path from "path";
6
+ import * as os from "os";
7
+ import { fileURLToPath } from "url";
8
+ async function installMcpServer() {
9
+ const homeDir = os.homedir();
10
+ const isMac = process.platform === "darwin";
11
+ const isWin = process.platform === "win32";
12
+ const __filename = fileURLToPath(import.meta.url);
13
+ const __dirname = path.dirname(__filename);
14
+ const cliPath = path.resolve(__dirname, "cli.mjs");
15
+ const wlmakerConfig = {
16
+ command: process.execPath,
17
+ args: [cliPath, "mcp"]
18
+ };
19
+ const configs = [
20
+ {
21
+ name: "Claude Desktop",
22
+ paths: isMac ? [path.join(homeDir, "Library/Application Support/Claude/claude_desktop_config.json")] : isWin ? [path.join(homeDir, "AppData/Roaming/Claude/claude_desktop_config.json")] : []
23
+ },
24
+ {
25
+ name: "Claude Code",
26
+ paths: [path.join(homeDir, ".claude.json")]
27
+ },
28
+ {
29
+ name: "Gemini CLI",
30
+ paths: [path.join(homeDir, ".gemini/settings.json")]
31
+ },
32
+ {
33
+ name: "Cursor",
34
+ paths: [path.join(homeDir, ".cursor/mcp.json")]
35
+ },
36
+ {
37
+ name: "Cline / RooCode (VSCode)",
38
+ paths: isMac ? [
39
+ path.join(homeDir, "Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json"),
40
+ path.join(homeDir, "Library/Application Support/Code/User/globalStorage/rooveterinaryinc.roo-cline/settings/cline_mcp_settings.json")
41
+ ] : isWin ? [
42
+ path.join(homeDir, "AppData/Roaming/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json"),
43
+ path.join(homeDir, "AppData/Roaming/Code/User/globalStorage/rooveterinaryinc.roo-cline/settings/cline_mcp_settings.json")
44
+ ] : [
45
+ path.join(homeDir, ".config/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json"),
46
+ path.join(homeDir, ".config/Code/User/globalStorage/rooveterinaryinc.roo-cline/settings/cline_mcp_settings.json")
47
+ ]
48
+ }
49
+ ];
50
+ let anyInstalled = false;
51
+ for (const client of configs) {
52
+ for (const configPath of client.paths) {
53
+ if (fs.existsSync(configPath)) {
54
+ try {
55
+ const content = fs.readFileSync(configPath, "utf8");
56
+ const json = JSON.parse(content);
57
+ json.mcpServers = json.mcpServers || {};
58
+ json.mcpServers["wlmaker-cli"] = wlmakerConfig;
59
+ fs.writeFileSync(configPath, JSON.stringify(json, null, 2));
60
+ console.log(`\u2705 Successfully added wlmaker-cli to ${client.name} configuration.`);
61
+ anyInstalled = true;
62
+ } catch (error) {
63
+ console.error(`\u274C Failed to update ${client.name} configuration at ${configPath}:`, error);
64
+ }
65
+ }
66
+ }
67
+ }
68
+ if (!anyInstalled) {
69
+ console.log("\u26A0\uFE0F No supported MCP clients (Claude Desktop, Cursor, Cline) found to auto-configure.");
70
+ console.log("You can manually add the following configuration to your client:");
71
+ console.log(JSON.stringify({
72
+ mcpServers: {
73
+ "wlmaker-cli": wlmakerConfig
74
+ }
75
+ }, null, 2));
76
+ }
77
+ }
78
+
79
+ export {
80
+ installMcpServer
81
+ };
package/dist/cli.mjs CHANGED
@@ -1,4 +1,7 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ installMcpServer
4
+ } from "./chunk-OXBECDQE.mjs";
2
5
 
3
6
  // src/cli.ts
4
7
  import { createRequire } from "module";
@@ -3814,6 +3817,288 @@ async function interactiveMode() {
3814
3817
  }
3815
3818
  }
3816
3819
 
3820
+ // src/mcp-server.ts
3821
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3822
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3823
+ import {
3824
+ CallToolRequestSchema,
3825
+ ErrorCode,
3826
+ ListToolsRequestSchema,
3827
+ McpError
3828
+ } from "@modelcontextprotocol/sdk/types.js";
3829
+ async function runMcpServer() {
3830
+ const server = new Server(
3831
+ {
3832
+ name: "wlmaker-cli",
3833
+ version: "1.5.0"
3834
+ },
3835
+ {
3836
+ capabilities: {
3837
+ tools: {}
3838
+ }
3839
+ }
3840
+ );
3841
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
3842
+ return {
3843
+ tools: [
3844
+ {
3845
+ name: "create_bloc",
3846
+ description: "Create a new BLoC with Freezed sealed classes in the Flutter project",
3847
+ inputSchema: {
3848
+ type: "object",
3849
+ properties: {
3850
+ name: {
3851
+ type: "string",
3852
+ description: "BLoC name in snake_case (e.g. user_login)"
3853
+ },
3854
+ dir: {
3855
+ type: "string",
3856
+ description: "Target directory for the BLoC"
3857
+ }
3858
+ },
3859
+ required: ["name"]
3860
+ }
3861
+ },
3862
+ {
3863
+ name: "create_widget",
3864
+ description: "Create a new widget in the design system",
3865
+ inputSchema: {
3866
+ type: "object",
3867
+ properties: {
3868
+ name: {
3869
+ type: "string",
3870
+ description: "Widget name in snake_case (e.g. toggle)"
3871
+ },
3872
+ tier: {
3873
+ type: "string",
3874
+ description: "Tier: atom, molecule, organism, template",
3875
+ enum: ["atom", "molecule", "organism", "template"]
3876
+ },
3877
+ dir: {
3878
+ type: "string",
3879
+ description: "Project root directory (optional)"
3880
+ }
3881
+ },
3882
+ required: ["name", "tier"]
3883
+ }
3884
+ },
3885
+ {
3886
+ name: "create_page",
3887
+ description: "Create a new page (GoRoute + View) with barrel updates",
3888
+ inputSchema: {
3889
+ type: "object",
3890
+ properties: {
3891
+ name: {
3892
+ type: "string",
3893
+ description: "Page name in snake_case (e.g. profile, order_detail)"
3894
+ },
3895
+ path: {
3896
+ type: "string",
3897
+ description: "Absolute path to the pages directory"
3898
+ }
3899
+ },
3900
+ required: ["name", "path"]
3901
+ }
3902
+ },
3903
+ {
3904
+ name: "create_usecase",
3905
+ description: "Create a Widgetbook use-case for an existing widget",
3906
+ inputSchema: {
3907
+ type: "object",
3908
+ properties: {
3909
+ name: {
3910
+ type: "string",
3911
+ description: "Widget name in snake_case (e.g. toggle)"
3912
+ },
3913
+ tier: {
3914
+ type: "string",
3915
+ description: "Tier: atom, molecule, organism, template",
3916
+ enum: ["atom", "molecule", "organism", "template"]
3917
+ },
3918
+ dir: {
3919
+ type: "string",
3920
+ description: "Project root directory (optional)"
3921
+ }
3922
+ },
3923
+ required: ["name", "tier"]
3924
+ }
3925
+ },
3926
+ {
3927
+ name: "create_endpoint",
3928
+ description: "Generate Clean Architecture stack for a BFF endpoint",
3929
+ inputSchema: {
3930
+ type: "object",
3931
+ properties: {
3932
+ projectRoot: { type: "string", description: "Root directory of the BFF package" },
3933
+ projectName: { type: "string", description: "Name of the BFF package" },
3934
+ httpMethod: {
3935
+ type: "string",
3936
+ enum: ["GET", "POST", "PUT", "DELETE", "PATCH"],
3937
+ description: "HTTP method"
3938
+ },
3939
+ endpointPath: { type: "string", description: "Endpoint path (e.g. /api/users/{id})" },
3940
+ bffApiFile: { type: "string", description: "Absolute or relative path to the BFF API dart file" },
3941
+ useCaseName: { type: "string", description: "UseCase name in snake_case" },
3942
+ diTarget: { type: "string", description: "DI target (e.g. app_base, none)", default: "none" },
3943
+ diLazySingleton: { type: "boolean", description: "Use @lazySingleton", default: true }
3944
+ },
3945
+ required: ["projectRoot", "projectName", "httpMethod", "endpointPath", "bffApiFile", "useCaseName"]
3946
+ }
3947
+ },
3948
+ {
3949
+ name: "create_package",
3950
+ description: "Create a new package in the monorepo",
3951
+ inputSchema: {
3952
+ type: "object",
3953
+ properties: {
3954
+ monorepoRoot: { type: "string", description: "Root directory of the monorepo" },
3955
+ packageName: { type: "string", description: "Package name in snake_case" }
3956
+ },
3957
+ required: ["monorepoRoot", "packageName"]
3958
+ }
3959
+ },
3960
+ {
3961
+ name: "create_env_var",
3962
+ description: "Add an environment variable across the Flutter monorepo",
3963
+ inputSchema: {
3964
+ type: "object",
3965
+ properties: {
3966
+ monorepoRoot: { type: "string", description: "Root directory of the monorepo" },
3967
+ variableName: { type: "string", description: "Variable name in SCREAMING_SNAKE_CASE" },
3968
+ dartType: {
3969
+ type: "string",
3970
+ enum: ["String", "int", "bool", "List<String>"],
3971
+ description: "Dart type"
3972
+ },
3973
+ defaultValue: { type: "string", description: "Default value (optional)" },
3974
+ selectedApps: { type: "array", items: { type: "string" }, description: "List of apps to update" },
3975
+ vendorsTargets: { type: "array", items: { type: "string" }, description: "List of vendor module packages" },
3976
+ includeInRemoteConfig: { type: "boolean", description: "Include in Remote Config" },
3977
+ includeInAppConfig: { type: "boolean", description: "Include in AppConfig entity" }
3978
+ },
3979
+ required: ["monorepoRoot", "variableName", "dartType", "selectedApps", "vendorsTargets", "includeInRemoteConfig", "includeInAppConfig"]
3980
+ }
3981
+ },
3982
+ {
3983
+ name: "docs_commands",
3984
+ description: "Show Makefile & melos commands reference",
3985
+ inputSchema: {
3986
+ type: "object",
3987
+ properties: {
3988
+ dir: { type: "string", description: "Project root directory" }
3989
+ },
3990
+ required: ["dir"]
3991
+ }
3992
+ },
3993
+ {
3994
+ name: "docs_architecture",
3995
+ description: "Display monorepo architecture info as JSON",
3996
+ inputSchema: {
3997
+ type: "object",
3998
+ properties: {
3999
+ dir: { type: "string", description: "Project root directory" }
4000
+ },
4001
+ required: ["dir"]
4002
+ }
4003
+ }
4004
+ ]
4005
+ };
4006
+ });
4007
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
4008
+ try {
4009
+ if (request.params.name === "create_bloc") {
4010
+ const { name, dir } = request.params.arguments;
4011
+ const targetDir = dir || process.cwd();
4012
+ await createBloc(name, { dir: targetDir, buildRunner: false });
4013
+ return {
4014
+ content: [{ type: "text", text: `Successfully created BLoC ${name} in ${targetDir}` }]
4015
+ };
4016
+ }
4017
+ if (request.params.name === "create_widget") {
4018
+ const { name, tier, dir } = request.params.arguments;
4019
+ const projectRoot = dir || process.cwd();
4020
+ await createWidget(name, tier, { projectRoot, pattern: void 0 });
4021
+ try {
4022
+ await createUseCase(name, tier, { projectRoot, buildRunner: false });
4023
+ return {
4024
+ content: [{ type: "text", text: `Successfully created Widget ${name} (${tier}) and its UseCase in ${projectRoot}` }]
4025
+ };
4026
+ } catch {
4027
+ return {
4028
+ content: [{ type: "text", text: `Successfully created Widget ${name} (${tier}) in ${projectRoot} (UseCase creation skipped/failed)` }]
4029
+ };
4030
+ }
4031
+ }
4032
+ if (request.params.name === "create_page") {
4033
+ const { name, path: path16 } = request.params.arguments;
4034
+ await createPage(name, { pagesPath: path16 });
4035
+ return {
4036
+ content: [{ type: "text", text: `Successfully created Page ${name} in ${path16}` }]
4037
+ };
4038
+ }
4039
+ if (request.params.name === "create_usecase") {
4040
+ const { name, tier, dir } = request.params.arguments;
4041
+ const projectRoot = dir || process.cwd();
4042
+ await createUseCase(name, tier, { projectRoot, buildRunner: false });
4043
+ return {
4044
+ content: [{ type: "text", text: `Successfully created UseCase for ${name} (${tier}) in ${projectRoot}` }]
4045
+ };
4046
+ }
4047
+ if (request.params.name === "create_endpoint") {
4048
+ const args = request.params.arguments;
4049
+ await createEndpoint({
4050
+ ...args,
4051
+ diTarget: args.diTarget || "none",
4052
+ diLazySingleton: args.diLazySingleton ?? true
4053
+ });
4054
+ return {
4055
+ content: [{ type: "text", text: `Successfully generated endpoint stack for ${args.useCaseName}` }]
4056
+ };
4057
+ }
4058
+ if (request.params.name === "create_package") {
4059
+ const { monorepoRoot, packageName } = request.params.arguments;
4060
+ await createPackage({ monorepoRoot, packageName });
4061
+ return {
4062
+ content: [{ type: "text", text: `Successfully created package ${packageName} in ${monorepoRoot}/packages` }]
4063
+ };
4064
+ }
4065
+ if (request.params.name === "create_env_var") {
4066
+ const args = request.params.arguments;
4067
+ await createEnvVar(args);
4068
+ return {
4069
+ content: [{ type: "text", text: `Successfully added environment variable ${args.variableName}` }]
4070
+ };
4071
+ }
4072
+ if (request.params.name === "docs_commands") {
4073
+ const { dir } = request.params.arguments;
4074
+ const commands = discoverCommands(dir || process.cwd());
4075
+ return {
4076
+ content: [{ type: "text", text: JSON.stringify(commands, null, 2) }]
4077
+ };
4078
+ }
4079
+ if (request.params.name === "docs_architecture") {
4080
+ const { dir } = request.params.arguments;
4081
+ const info = discoverArchitecture(dir || process.cwd());
4082
+ if (!info) {
4083
+ return { content: [{ type: "text", text: "No monorepo detected." }] };
4084
+ }
4085
+ return {
4086
+ content: [{ type: "text", text: JSON.stringify(info, null, 2) }]
4087
+ };
4088
+ }
4089
+ throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`);
4090
+ } catch (error) {
4091
+ return {
4092
+ content: [{ type: "text", text: `Error: ${error?.message || String(error)}` }],
4093
+ isError: true
4094
+ };
4095
+ }
4096
+ });
4097
+ const transport = new StdioServerTransport();
4098
+ await server.connect(transport);
4099
+ console.error("wlmaker-cli MCP server running on stdio");
4100
+ }
4101
+
3817
4102
  // src/cli.ts
3818
4103
  var require2 = createRequire(import.meta.url);
3819
4104
  var pkg = require2("../package.json");
@@ -3885,9 +4170,7 @@ program.command("page").description("Create a new page (GoRoute + View) with bar
3885
4170
  }
3886
4171
  );
3887
4172
  program.command("endpoint").description("Generate Clean Architecture stack for a BFF endpoint").action(async () => {
3888
- const project = await resolveProject();
3889
- if (!project) return;
3890
- await endpointFlow(project);
4173
+ await endpointFlow();
3891
4174
  });
3892
4175
  program.command("package").description("Create a new package in the monorepo").action(async () => {
3893
4176
  await packageFlow();
@@ -3923,6 +4206,12 @@ docsCmd.command("architecture").description("Display monorepo architecture tree"
3923
4206
  }
3924
4207
  displayArchitecture(info);
3925
4208
  });
4209
+ program.command("mcp").description("Start the wlmaker MCP server (used automatically by AI clients)").action(async () => {
4210
+ await runMcpServer();
4211
+ });
4212
+ program.command("mcp-install").description("Manually install/register the wlmaker MCP server into compatible clients (Claude, Cursor, Cline)").action(async () => {
4213
+ await installMcpServer();
4214
+ });
3926
4215
  docsCmd.action(async () => {
3927
4216
  await docsInteractiveMode();
3928
4217
  });
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ installMcpServer
4
+ } from "./chunk-OXBECDQE.mjs";
5
+
6
+ // src/postinstall.ts
7
+ async function main() {
8
+ console.log("Registering wlmaker-cli as an MCP server...");
9
+ await installMcpServer();
10
+ }
11
+ main().catch(console.error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wlmaker",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "Create Flutter BLoCs with Freezed sealed classes from the terminal",
5
5
  "keywords": [
6
6
  "flutter",
@@ -24,10 +24,12 @@
24
24
  ],
25
25
  "scripts": {
26
26
  "build": "tsup",
27
- "dev": "tsup --watch"
27
+ "dev": "tsup --watch",
28
+ "postinstall": "node ./dist/postinstall.mjs"
28
29
  },
29
30
  "dependencies": {
30
31
  "@clack/prompts": "^1.2.0",
32
+ "@modelcontextprotocol/sdk": "^1.0.4",
31
33
  "chalk": "^5.3.0",
32
34
  "change-case": "^5.4.0",
33
35
  "commander": "^12.0.0",