# Directory Structure
```
├── .gitignore
├── package-lock.json
├── package.json
├── src
│   └── index.ts
└── tsconfig.json
```
# Files
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
```
 1 | # Dependencies
 2 | node_modules/
 3 | npm-debug.log*
 4 | yarn-debug.log*
 5 | yarn-error.log*
 6 | 
 7 | # TypeScript build output
 8 | build/
 9 | dist/
10 | *.tsbuildinfo
11 | 
12 | # IDE
13 | .idea/
14 | .vscode/
15 | *.swp
16 | *.swo
17 | 
18 | # Environment variables
19 | .env
20 | .env.local
21 | .env.*.local
22 | 
23 | # OS
24 | .DS_Store
25 | Thumbs.db
26 | 
```
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
```json
 1 | {
 2 |   "compilerOptions": {
 3 |     "target": "ES2022",
 4 |     "module": "Node16",
 5 |     "moduleResolution": "Node16",
 6 |     "outDir": "./build",
 7 |     "rootDir": "./src",
 8 |     "strict": true,
 9 |     "esModuleInterop": true,
10 |     "skipLibCheck": true,
11 |     "forceConsistentCasingInFileNames": true
12 |   },
13 |   "include": ["src/**/*"]
14 | }
15 | 
```
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
```json
 1 | {
 2 |   "name": "mcp-flutter-server",
 3 |   "version": "1.0.0",
 4 |   "type": "module",
 5 |   "bin": {
 6 |     "mcp-flutter-server": "./build/index.js"
 7 |   },
 8 |   "scripts": {
 9 |     "build": "tsc",
10 |     "start": "node build/index.js",
11 |     "dev": "tsc --watch",
12 |     "prepublishOnly": "npm run build"
13 |   },
14 |   "dependencies": {
15 |     "@modelcontextprotocol/sdk": "^1.5.0",
16 |     "zod": "^3.22.4"
17 |   },
18 |   "devDependencies": {
19 |     "@types/node": "^20.11.20",
20 |     "typescript": "^5.3.3"
21 |   }
22 | }
```
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
```typescript
  1 | #!/usr/bin/env node
  2 | 
  3 | import { Server } from "@modelcontextprotocol/sdk/server/index.js";
  4 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
  5 | import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
  6 | import { z } from "zod";
  7 | import { exec } from "child_process";
  8 | import { promisify } from "util";
  9 | 
 10 | const execAsync = promisify(exec);
 11 | 
 12 | // Configuration schema
 13 | const ConfigSchema = z.object({
 14 |   repoPath: z.string().min(1, "Repository path is required")
 15 | });
 16 | 
 17 | // Tool execution function
 18 | async function executeCommand(command: string, repoPath: string): Promise<string> {
 19 |   try {
 20 |     const { stdout, stderr } = await execAsync(command, { cwd: repoPath });
 21 |     if (stderr) {
 22 |       return `Error: ${stderr}`;
 23 |     }
 24 |     return stdout;
 25 |   } catch (error) {
 26 |     return `Execution failed: ${(error as Error).message}`;
 27 |   }
 28 | }
 29 | 
 30 | async function startServer(repoPath: string) {
 31 |   // Validate configuration
 32 |   const configResult = ConfigSchema.safeParse({ repoPath });
 33 |   if (!configResult.success) {
 34 |     console.error("Configuration error:", configResult.error.message);
 35 |     process.exit(1);
 36 |   }
 37 | 
 38 |   const config = configResult.data;
 39 | 
 40 |   // Initialize MCP server
 41 |   const server = new Server(
 42 |     {
 43 |       name: "flutter-dart-server",
 44 |       version: "1.0.0",
 45 |     },
 46 |     {
 47 |       capabilities: {
 48 |         tools: {}
 49 |       }
 50 |     }
 51 |   );
 52 | 
 53 |   // Define available tools
 54 |   server.setRequestHandler(ListToolsRequestSchema, async () => {
 55 |     return {
 56 |       tools: [
 57 |         {
 58 |           name: "flutter_run",
 59 |           description: "Run a Flutter application",
 60 |           inputSchema: {
 61 |             type: "object",
 62 |             properties: {
 63 |               target: { type: "string", description: "Target file to run (default: lib/main.dart)" }
 64 |             }
 65 |           }
 66 |         },
 67 |         {
 68 |           name: "flutter_generate",
 69 |           description: "Generate Dart files using build_runner",
 70 |           inputSchema: {
 71 |             type: "object",
 72 |             properties: {}
 73 |           }
 74 |         },
 75 |         {
 76 |           name: "dart_fix",
 77 |           description: "Automatically fix Dart style issues",
 78 |           inputSchema: {
 79 |             type: "object",
 80 |             properties: {
 81 |               folder: { type: "string", description: "Target folder (default: lib)" }
 82 |             }
 83 |           }
 84 |         },
 85 |         {
 86 |           name: "dart_run",
 87 |           description: "Run a Dart file",
 88 |           inputSchema: {
 89 |             type: "object",
 90 |             properties: {
 91 |               file: { type: "string", description: "Dart file to run" }
 92 |             },
 93 |             required: ["file"]
 94 |           }
 95 |         },
 96 |         {
 97 |           name: "flutter_build",
 98 |           description: "Build a Flutter application",
 99 |           inputSchema: {
100 |             type: "object",
101 |             properties: {
102 |               platform: { 
103 |                 type: "string", 
104 |                 enum: ["apk", "ios", "web"], 
105 |                 description: "Target platform"
106 |               }
107 |             }
108 |           }
109 |         },
110 |         {
111 |           name: "flutter_analyze",
112 |           description: "Run Flutter analyzer to find issues",
113 |           inputSchema: {
114 |             type: "object",
115 |             properties: {}
116 |           }
117 |         },
118 |         {
119 |           name: "flutter_test",
120 |           description: "Run Flutter tests",
121 |           inputSchema: {
122 |             type: "object",
123 |             properties: {
124 |               test: { type: "string", description: "Specific test file to run (optional)" }
125 |             }
126 |           }
127 |         }
128 |       ]
129 |     };
130 |   });
131 | 
132 |   // Handle tool calls
133 |   server.setRequestHandler(CallToolRequestSchema, async (request) => {
134 |     const args = request.params.arguments || {};
135 |     
136 |     switch (request.params.name) {
137 |       case "flutter_run": {
138 |         const target = args.target || "lib/main.dart";
139 |         const result = await executeCommand(`flutter run ${target}`, config.repoPath);
140 |         return { toolResult: result };
141 |       }
142 |       
143 |       case "flutter_generate": {
144 |         const result = await executeCommand(
145 |           "flutter pub run build_runner build --delete-conflicting-outputs",
146 |           config.repoPath
147 |         );
148 |         return { toolResult: result };
149 |       }
150 |       
151 |       case "dart_fix": {
152 |         const folder = args.folder || "lib";
153 |         const result = await executeCommand(`dart fix --apply ${folder}`, config.repoPath);
154 |         return { toolResult: result };
155 |       }
156 |       
157 |       case "dart_run": {
158 |         const file = args.file;
159 |         const result = await executeCommand(`dart run ${file}`, config.repoPath);
160 |         return { toolResult: result };
161 |       }
162 |       
163 |       case "flutter_build": {
164 |         const platform = args.platform || "apk";
165 |         const result = await executeCommand(`flutter build ${platform}`, config.repoPath);
166 |         return { toolResult: result };
167 |       }
168 |       
169 |       case "flutter_analyze": {
170 |         const result = await executeCommand("flutter analyze", config.repoPath);
171 |         return { toolResult: result };
172 |       }
173 | 
174 |       case "flutter_test": {
175 |         const testFile = args.test ? args.test : "";
176 |         const result = await executeCommand(`flutter test ${testFile}`, config.repoPath);
177 |         return { toolResult: result };
178 |       }
179 |       
180 |       default:
181 |         throw new Error(`Unknown tool: ${request.params.name}`);
182 |     }
183 |   });
184 | 
185 |   // Connect server to transport
186 |   const transport = new StdioServerTransport();
187 |   await server.connect(transport);
188 |   
189 |   console.log(`Flutter/Dart MCP server running with repo: ${config.repoPath}`);
190 | }
191 | 
192 | // Handle command line execution
193 | if (require.main === module) {
194 |   const args = process.argv.slice(2);
195 |   const repoPath = args[0];
196 |   
197 |   if (!repoPath) {
198 |     console.error("Usage: npx mcp-flutter-server <repo-path>");
199 |     process.exit(1);
200 |   }
201 |   
202 |   startServer(repoPath).catch((error) => {
203 |     console.error("Server error:", error);
204 |     process.exit(1);
205 |   });
206 | }
207 | 
208 | export { startServer };
```