@falzz1010/laravel-mcp-server 1.0.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.
Files changed (76) hide show
  1. package/CHANGELOG.md +100 -0
  2. package/LICENSE +21 -0
  3. package/README.md +866 -0
  4. package/build/index.d.ts +2 -0
  5. package/build/index.d.ts.map +1 -0
  6. package/build/index.js +101 -0
  7. package/build/index.js.map +1 -0
  8. package/build/prompts/laravel-prompts.d.ts +4 -0
  9. package/build/prompts/laravel-prompts.d.ts.map +1 -0
  10. package/build/prompts/laravel-prompts.js +81 -0
  11. package/build/prompts/laravel-prompts.js.map +1 -0
  12. package/build/resources/laravel-info.d.ts +4 -0
  13. package/build/resources/laravel-info.d.ts.map +1 -0
  14. package/build/resources/laravel-info.js +99 -0
  15. package/build/resources/laravel-info.js.map +1 -0
  16. package/build/tests/full-security-audit.test.d.ts +2 -0
  17. package/build/tests/full-security-audit.test.d.ts.map +1 -0
  18. package/build/tests/full-security-audit.test.js +226 -0
  19. package/build/tests/full-security-audit.test.js.map +1 -0
  20. package/build/tests/security.test.d.ts +2 -0
  21. package/build/tests/security.test.d.ts.map +1 -0
  22. package/build/tests/security.test.js +124 -0
  23. package/build/tests/security.test.js.map +1 -0
  24. package/build/tools/list-routes.d.ts +4 -0
  25. package/build/tools/list-routes.d.ts.map +1 -0
  26. package/build/tools/list-routes.js +68 -0
  27. package/build/tools/list-routes.js.map +1 -0
  28. package/build/tools/read-env.d.ts +4 -0
  29. package/build/tools/read-env.d.ts.map +1 -0
  30. package/build/tools/read-env.js +51 -0
  31. package/build/tools/read-env.js.map +1 -0
  32. package/build/tools/read-file.d.ts +4 -0
  33. package/build/tools/read-file.d.ts.map +1 -0
  34. package/build/tools/read-file.js +60 -0
  35. package/build/tools/read-file.js.map +1 -0
  36. package/build/tools/read-logs.d.ts +4 -0
  37. package/build/tools/read-logs.d.ts.map +1 -0
  38. package/build/tools/read-logs.js +60 -0
  39. package/build/tools/read-logs.js.map +1 -0
  40. package/build/tools/run-artisan.d.ts +5 -0
  41. package/build/tools/run-artisan.d.ts.map +1 -0
  42. package/build/tools/run-artisan.js +130 -0
  43. package/build/tools/run-artisan.js.map +1 -0
  44. package/build/tools/run-tinker.d.ts +4 -0
  45. package/build/tools/run-tinker.d.ts.map +1 -0
  46. package/build/tools/run-tinker.js +75 -0
  47. package/build/tools/run-tinker.js.map +1 -0
  48. package/build/tools/write-file.d.ts +4 -0
  49. package/build/tools/write-file.d.ts.map +1 -0
  50. package/build/tools/write-file.js +103 -0
  51. package/build/tools/write-file.js.map +1 -0
  52. package/build/utils/audit.d.ts +23 -0
  53. package/build/utils/audit.d.ts.map +1 -0
  54. package/build/utils/audit.js +52 -0
  55. package/build/utils/audit.js.map +1 -0
  56. package/build/utils/config.d.ts +12 -0
  57. package/build/utils/config.d.ts.map +1 -0
  58. package/build/utils/config.js +63 -0
  59. package/build/utils/config.js.map +1 -0
  60. package/build/utils/file.d.ts +8 -0
  61. package/build/utils/file.d.ts.map +1 -0
  62. package/build/utils/file.js +96 -0
  63. package/build/utils/file.js.map +1 -0
  64. package/build/utils/process.d.ts +16 -0
  65. package/build/utils/process.d.ts.map +1 -0
  66. package/build/utils/process.js +78 -0
  67. package/build/utils/process.js.map +1 -0
  68. package/build/utils/rate-limiter.d.ts +19 -0
  69. package/build/utils/rate-limiter.d.ts.map +1 -0
  70. package/build/utils/rate-limiter.js +57 -0
  71. package/build/utils/rate-limiter.js.map +1 -0
  72. package/build/utils/security.d.ts +23 -0
  73. package/build/utils/security.d.ts.map +1 -0
  74. package/build/utils/security.js +282 -0
  75. package/build/utils/security.js.map +1 -0
  76. package/package.json +61 -0
@@ -0,0 +1,57 @@
1
+ export class RateLimiter {
2
+ config;
3
+ timestamps = [];
4
+ lastRequestTime = 0;
5
+ constructor(config = {
6
+ maxRequestsPerMinute: 30,
7
+ maxRequestsPerHour: 500,
8
+ cooldownMs: 2000,
9
+ }) {
10
+ this.config = config;
11
+ }
12
+ checkRateLimit() {
13
+ const now = Date.now();
14
+ // Check cooldown
15
+ const elapsedSinceLast = now - this.lastRequestTime;
16
+ if (this.lastRequestTime > 0 && elapsedSinceLast < this.config.cooldownMs) {
17
+ const waitMs = this.config.cooldownMs - elapsedSinceLast;
18
+ return {
19
+ allowed: false,
20
+ retryAfterMs: waitMs,
21
+ reason: `Rate Limiter: Please wait ${Math.ceil(waitMs / 1000)}s before sending another request (cooldown: ${this.config.cooldownMs}ms).`,
22
+ };
23
+ }
24
+ // Clean timestamps older than 1 hour
25
+ const oneHourAgo = now - 3600 * 1000;
26
+ this.timestamps = this.timestamps.filter((ts) => ts > oneHourAgo);
27
+ // Check requests in last 1 minute
28
+ const oneMinuteAgo = now - 60 * 1000;
29
+ const requestsLastMinute = this.timestamps.filter((ts) => ts > oneMinuteAgo).length;
30
+ if (requestsLastMinute >= this.config.maxRequestsPerMinute) {
31
+ return {
32
+ allowed: false,
33
+ retryAfterMs: 60000,
34
+ reason: `Rate Limiter: Maximum limit of ${this.config.maxRequestsPerMinute} requests per minute exceeded.`,
35
+ };
36
+ }
37
+ // Check requests in last 1 hour
38
+ if (this.timestamps.length >= this.config.maxRequestsPerHour) {
39
+ return {
40
+ allowed: false,
41
+ retryAfterMs: 3600000,
42
+ reason: `Rate Limiter: Maximum limit of ${this.config.maxRequestsPerHour} requests per hour exceeded.`,
43
+ };
44
+ }
45
+ return { allowed: true };
46
+ }
47
+ recordRequest() {
48
+ const now = Date.now();
49
+ this.timestamps.push(now);
50
+ this.lastRequestTime = now;
51
+ }
52
+ reset() {
53
+ this.timestamps = [];
54
+ this.lastRequestTime = 0;
55
+ }
56
+ }
57
+ //# sourceMappingURL=rate-limiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/utils/rate-limiter.ts"],"names":[],"mappings":"AAMA,MAAM,OAAO,WAAW;IAKZ;IAJF,UAAU,GAAa,EAAE,CAAC;IAC1B,eAAe,GAAG,CAAC,CAAC;IAE5B,YACU,SAA4B;QAClC,oBAAoB,EAAE,EAAE;QACxB,kBAAkB,EAAE,GAAG;QACvB,UAAU,EAAE,IAAI;KACjB;QAJO,WAAM,GAAN,MAAM,CAIb;IACA,CAAC;IAEG,cAAc;QACnB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEvB,iBAAiB;QACjB,MAAM,gBAAgB,GAAG,GAAG,GAAG,IAAI,CAAC,eAAe,CAAC;QACpD,IAAI,IAAI,CAAC,eAAe,GAAG,CAAC,IAAI,gBAAgB,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;YAC1E,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,GAAG,gBAAgB,CAAC;YACzD,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,YAAY,EAAE,MAAM;gBACpB,MAAM,EAAE,6BAA6B,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,+CAA+C,IAAI,CAAC,MAAM,CAAC,UAAU,MAAM;aACzI,CAAC;QACJ,CAAC;QAED,qCAAqC;QACrC,MAAM,UAAU,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC;QACrC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,UAAU,CAAC,CAAC;QAElE,kCAAkC;QAClC,MAAM,YAAY,GAAG,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC;QACrC,MAAM,kBAAkB,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,YAAY,CAAC,CAAC,MAAM,CAAC;QAEpF,IAAI,kBAAkB,IAAI,IAAI,CAAC,MAAM,CAAC,oBAAoB,EAAE,CAAC;YAC3D,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,YAAY,EAAE,KAAK;gBACnB,MAAM,EAAE,kCAAkC,IAAI,CAAC,MAAM,CAAC,oBAAoB,gCAAgC;aAC3G,CAAC;QACJ,CAAC;QAED,gCAAgC;QAChC,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC;YAC7D,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,YAAY,EAAE,OAAO;gBACrB,MAAM,EAAE,kCAAkC,IAAI,CAAC,MAAM,CAAC,kBAAkB,8BAA8B;aACvG,CAAC;QACJ,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAEM,aAAa;QAClB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC1B,IAAI,CAAC,eAAe,GAAG,GAAG,CAAC;IAC7B,CAAC;IAEM,KAAK;QACV,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;QACrB,IAAI,CAAC,eAAe,GAAG,CAAC,CAAC;IAC3B,CAAC;CACF"}
@@ -0,0 +1,23 @@
1
+ export type CommandTier = "READ_ONLY" | "CAUTIOUS" | "DANGEROUS";
2
+ export declare function validateLaravelPath(laravelPath: string): void;
3
+ export declare function checkEnvironment(laravelPath: string): void;
4
+ export declare function classifyCommand(command: string): CommandTier;
5
+ export declare function isCommandAllowed(command: string): {
6
+ allowed: boolean;
7
+ tier: CommandTier;
8
+ reason: string;
9
+ };
10
+ export declare function sanitizeArgs(args: string[]): string[];
11
+ export declare function validateDangerousFlags(command: string, args: string[]): void;
12
+ export declare function sanitizeTinkerCode(code: string): {
13
+ safe: boolean;
14
+ blocked: string[];
15
+ };
16
+ export declare function isPathSafe(relativePath: string, rootPath: string): string;
17
+ export declare function isWriteAllowed(relativePath: string): {
18
+ allowed: boolean;
19
+ reason: string;
20
+ };
21
+ export declare function maskEnvValues(content: string): string;
22
+ export declare function computeFileHash(content: string): string;
23
+ //# sourceMappingURL=security.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../src/utils/security.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,UAAU,GAAG,WAAW,CAAC;AAkHjE,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAQ7D;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAc1D;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAY5D;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAczG;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAmBrD;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAkB5E;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAmBrF;AAED,wBAAgB,UAAU,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAiBzE;AAED,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAqCzF;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAqBrD;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvD"}
@@ -0,0 +1,282 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import crypto from "node:crypto";
4
+ const READ_ONLY_COMMANDS = new Set([
5
+ "about",
6
+ "env",
7
+ "route:list",
8
+ "migrate:status",
9
+ "schedule:list",
10
+ "config:show",
11
+ ]);
12
+ const CAUTIOUS_COMMANDS = new Set([
13
+ "route:cache",
14
+ "route:clear",
15
+ "config:cache",
16
+ "config:clear",
17
+ "cache:clear",
18
+ "view:clear",
19
+ "optimize",
20
+ "optimize:clear",
21
+ "migrate",
22
+ "db:seed",
23
+ "key:generate",
24
+ "storage:link",
25
+ ]);
26
+ const DANGEROUS_COMMANDS = new Set([
27
+ "migrate:fresh",
28
+ "migrate:reset",
29
+ "migrate:rollback",
30
+ "migrate:refresh",
31
+ "db:wipe",
32
+ "down",
33
+ "up",
34
+ "tinker",
35
+ "serve",
36
+ "queue:restart",
37
+ "event:generate",
38
+ "vendor:publish",
39
+ "schedule:run",
40
+ "notifications:table",
41
+ "session:table",
42
+ "queue:table",
43
+ "cache:table",
44
+ "package:discover",
45
+ "stub:publish",
46
+ ]);
47
+ const DANGEROUS_FNS_TINKER = [
48
+ "exec",
49
+ "system",
50
+ "passthru",
51
+ "shell_exec",
52
+ "popen",
53
+ "proc_open",
54
+ "unlink",
55
+ "rmdir",
56
+ "mkdir",
57
+ "rename",
58
+ "copy",
59
+ "chmod",
60
+ "chown",
61
+ "file_put_contents",
62
+ "fwrite",
63
+ "fopen",
64
+ "curl_exec",
65
+ "eval",
66
+ "assert",
67
+ "ini_set",
68
+ "putenv",
69
+ "dl",
70
+ "truncate",
71
+ "forceDelete",
72
+ "DB::statement",
73
+ "DB::unprepared",
74
+ "Schema::drop",
75
+ "Schema::dropIfExists",
76
+ ];
77
+ const ALLOWED_WRITE_EXTENSIONS = new Set([
78
+ ".php",
79
+ ".json",
80
+ ".yaml",
81
+ ".yml",
82
+ ".xml",
83
+ ".stub",
84
+ ".md",
85
+ ".txt",
86
+ ]);
87
+ const ALLOWED_WRITE_DIRS = [
88
+ "app",
89
+ "routes",
90
+ "database/migrations",
91
+ "database/seeders",
92
+ "database/factories",
93
+ "resources/views",
94
+ "config",
95
+ "tests",
96
+ ];
97
+ const BLOCKED_WRITE_PATHS = [
98
+ ".env",
99
+ "vendor",
100
+ "node_modules",
101
+ "storage",
102
+ "public",
103
+ "bootstrap",
104
+ "artisan",
105
+ "composer.json",
106
+ "composer.lock",
107
+ ".git",
108
+ ];
109
+ export function validateLaravelPath(laravelPath) {
110
+ if (!fs.existsSync(laravelPath)) {
111
+ throw new Error(`Directory does not exist: ${laravelPath}`);
112
+ }
113
+ const artisanPath = path.join(laravelPath, "artisan");
114
+ if (!fs.existsSync(artisanPath)) {
115
+ throw new Error(`Target directory is not a valid Laravel project (missing 'artisan' file): ${laravelPath}`);
116
+ }
117
+ }
118
+ export function checkEnvironment(laravelPath) {
119
+ const envPath = path.join(laravelPath, ".env");
120
+ if (fs.existsSync(envPath)) {
121
+ const envContent = fs.readFileSync(envPath, "utf-8");
122
+ const match = envContent.match(/^APP_ENV\s*=\s*(.*)$/m);
123
+ if (match) {
124
+ const envValue = match[1].trim().replace(/^["']|["']$/g, "");
125
+ if (envValue.toLowerCase() === "production") {
126
+ throw new Error("SECURITY BLOCK: Laravel MCP Server refuses to start when APP_ENV=production.");
127
+ }
128
+ else if (envValue.toLowerCase() === "staging") {
129
+ console.error("[WARNING] Server running in STAGING environment. Exercise caution.");
130
+ }
131
+ }
132
+ }
133
+ }
134
+ export function classifyCommand(command) {
135
+ const normalized = command.trim().toLowerCase();
136
+ if (DANGEROUS_COMMANDS.has(normalized)) {
137
+ return "DANGEROUS";
138
+ }
139
+ if (READ_ONLY_COMMANDS.has(normalized)) {
140
+ return "READ_ONLY";
141
+ }
142
+ if (CAUTIOUS_COMMANDS.has(normalized) || normalized.startsWith("make:")) {
143
+ return "CAUTIOUS";
144
+ }
145
+ return "DANGEROUS";
146
+ }
147
+ export function isCommandAllowed(command) {
148
+ const tier = classifyCommand(command);
149
+ if (tier === "DANGEROUS") {
150
+ return {
151
+ allowed: false,
152
+ tier,
153
+ reason: `Command '${command}' is classified as DANGEROUS or UNKNOWN and is permanently blocked for safety.`,
154
+ };
155
+ }
156
+ return {
157
+ allowed: true,
158
+ tier,
159
+ reason: `Command '${command}' is permitted in tier ${tier}.`,
160
+ };
161
+ }
162
+ export function sanitizeArgs(args) {
163
+ if (args.length > 20) {
164
+ throw new Error("Security Error: Too many arguments (max 20).");
165
+ }
166
+ const injectionRegex = /[;&|`$><\r\n\0]|^\.\.\/|^\.\.\\/;
167
+ return args.map((arg) => {
168
+ if (arg.length > 255) {
169
+ throw new Error(`Security Error: Argument exceeds 255 characters limit: '${arg.substring(0, 20)}...'`);
170
+ }
171
+ if (injectionRegex.test(arg)) {
172
+ throw new Error(`Security Error: Argument contains illegal characters or injection attempt: '${arg}'`);
173
+ }
174
+ if (arg.includes("../") || arg.includes("..\\")) {
175
+ throw new Error(`Security Error: Path traversal detected in argument: '${arg}'`);
176
+ }
177
+ return arg.trim();
178
+ });
179
+ }
180
+ export function validateDangerousFlags(command, args) {
181
+ const lowerArgs = args.map((a) => a.toLowerCase());
182
+ if (lowerArgs.includes("--force")) {
183
+ if (["migrate", "db:seed", "key:generate"].includes(command.toLowerCase())) {
184
+ throw new Error(`Security Error: '--force' flag is strictly blocked on command '${command}'.`);
185
+ }
186
+ }
187
+ if (lowerArgs.includes("--seed") && command.toLowerCase() === "migrate") {
188
+ throw new Error("Security Error: '--seed' flag is blocked on 'migrate'. Use 'db:seed' tool explicitly.");
189
+ }
190
+ for (const arg of lowerArgs) {
191
+ if (arg.startsWith("--drop-") || arg.startsWith("--wipe")) {
192
+ throw new Error(`Security Error: Destructive flag '${arg}' is prohibited.`);
193
+ }
194
+ }
195
+ }
196
+ export function sanitizeTinkerCode(code) {
197
+ if (code.length > 2000) {
198
+ return { safe: false, blocked: ["Code length exceeds max limit of 2000 characters"] };
199
+ }
200
+ const blocked = [];
201
+ for (const fn of DANGEROUS_FNS_TINKER) {
202
+ // Check regex pattern for fn occurrence
203
+ const pattern = new RegExp(`\\b${fn.replace(/::/g, "::")}\\b`, "i");
204
+ if (pattern.test(code)) {
205
+ blocked.push(fn);
206
+ }
207
+ }
208
+ return {
209
+ safe: blocked.length === 0,
210
+ blocked,
211
+ };
212
+ }
213
+ export function isPathSafe(relativePath, rootPath) {
214
+ const resolvedRoot = path.resolve(rootPath);
215
+ const resolvedTarget = path.resolve(resolvedRoot, relativePath);
216
+ if (!resolvedTarget.startsWith(resolvedRoot)) {
217
+ throw new Error(`Security Error: Path traversal attempt blocked: '${relativePath}'`);
218
+ }
219
+ // Check for symlink outside root if target exists
220
+ if (fs.existsSync(resolvedTarget)) {
221
+ const realPath = fs.realpathSync(resolvedTarget);
222
+ if (!realPath.startsWith(resolvedRoot)) {
223
+ throw new Error(`Security Error: Symlink points outside project root: '${relativePath}'`);
224
+ }
225
+ }
226
+ return resolvedTarget;
227
+ }
228
+ export function isWriteAllowed(relativePath) {
229
+ const normalized = relativePath.replace(/\\/g, "/").replace(/^\.\//, "");
230
+ // Check blocked paths
231
+ for (const blocked of BLOCKED_WRITE_PATHS) {
232
+ if (normalized === blocked || normalized.startsWith(`${blocked}/`)) {
233
+ return {
234
+ allowed: false,
235
+ reason: `Writing to '${blocked}' is strictly prohibited.`,
236
+ };
237
+ }
238
+ }
239
+ // Check extension whitelist
240
+ const ext = path.extname(normalized).toLowerCase();
241
+ const isBlade = normalized.endsWith(".blade.php");
242
+ if (!isBlade && !ALLOWED_WRITE_EXTENSIONS.has(ext)) {
243
+ return {
244
+ allowed: false,
245
+ reason: `File extension '${ext}' is not in the whitelist for write operations.`,
246
+ };
247
+ }
248
+ // Check directory whitelist
249
+ const isInAllowedDir = ALLOWED_WRITE_DIRS.some((dir) => normalized === dir || normalized.startsWith(`${dir}/`));
250
+ if (!isInAllowedDir) {
251
+ return {
252
+ allowed: false,
253
+ reason: `Target path '${normalized}' is outside allowed directories (${ALLOWED_WRITE_DIRS.join(", ")}).`,
254
+ };
255
+ }
256
+ return { allowed: true, reason: "Path is permitted for writing." };
257
+ }
258
+ export function maskEnvValues(content) {
259
+ const sensitivePattern = /(PASSWORD|SECRET|KEY|TOKEN|HASH|PRIVATE|CREDENTIAL|API_KEY|AUTH|MAIL_PASSWORD|AWS_|REDIS_PASSWORD|DB_PASSWORD|PUSHER_|MIX_PUSHER_)/i;
260
+ return content
261
+ .split("\n")
262
+ .map((line) => {
263
+ const trimmed = line.trim();
264
+ if (!trimmed || trimmed.startsWith("#")) {
265
+ return line;
266
+ }
267
+ const eqIndex = line.indexOf("=");
268
+ if (eqIndex === -1) {
269
+ return line;
270
+ }
271
+ const key = line.substring(0, eqIndex).trim();
272
+ if (sensitivePattern.test(key)) {
273
+ return `${key}=***MASKED***`;
274
+ }
275
+ return line;
276
+ })
277
+ .join("\n");
278
+ }
279
+ export function computeFileHash(content) {
280
+ return crypto.createHash("sha256").update(content).digest("hex");
281
+ }
282
+ //# sourceMappingURL=security.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.js","sourceRoot":"","sources":["../../src/utils/security.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@falzz1010/laravel-mcp-server",
3
+ "version": "1.0.0",
4
+ "description": "Secure MCP Server for Laravel development — AI-powered artisan commands, log inspection, and code management with 10-layer security",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "keywords": [
9
+ "laravel",
10
+ "mcp",
11
+ "model-context-protocol",
12
+ "ai",
13
+ "claude",
14
+ "cursor",
15
+ "artisan",
16
+ "development",
17
+ "php",
18
+ "typescript"
19
+ ],
20
+ "author": "Laravel MCP Server Contributors",
21
+ "license": "MIT",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/Falzz1010/laravel-mcp-server.git"
25
+ },
26
+ "bugs": {
27
+ "url": "https://github.com/Falzz1010/laravel-mcp-server/issues"
28
+ },
29
+ "homepage": "https://github.com/Falzz1010/laravel-mcp-server#readme",
30
+ "type": "module",
31
+ "main": "build/index.js",
32
+ "bin": {
33
+ "laravel-mcp": "build/index.js"
34
+ },
35
+ "files": [
36
+ "build/**/*",
37
+ "README.md",
38
+ "LICENSE",
39
+ "CHANGELOG.md"
40
+ ],
41
+ "engines": {
42
+ "node": ">=18.0.0"
43
+ },
44
+ "scripts": {
45
+ "dev": "tsx watch src/index.ts",
46
+ "build": "tsc",
47
+ "start": "node build/index.js",
48
+ "test": "npm run build && node --test build/tests/security.test.js build/tests/full-security-audit.test.js",
49
+ "inspect": "npx @modelcontextprotocol/inspector node build/index.js",
50
+ "prepublishOnly": "npm run build"
51
+ },
52
+ "dependencies": {
53
+ "@modelcontextprotocol/sdk": "^1.30.0",
54
+ "zod": "^3.23.0"
55
+ },
56
+ "devDependencies": {
57
+ "typescript": "^5.5.0",
58
+ "@types/node": "^22.0.0",
59
+ "tsx": "^4.19.0"
60
+ }
61
+ }