@morphllm/morphmcp 0.8.43 → 0.8.44

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.
@@ -1,91 +1 @@
1
- import path from "path";
2
- import os from 'os';
3
- /**
4
- * Converts WSL or Unix-style Windows paths to Windows format
5
- * @param p The path to convert
6
- * @returns Converted Windows path
7
- */
8
- export function convertToWindowsPath(p) {
9
- // Handle WSL paths (/mnt/c/...)
10
- if (p.startsWith('/mnt/')) {
11
- const driveLetter = p.charAt(5).toUpperCase();
12
- const pathPart = p.slice(6).replace(/\//g, '\\');
13
- return `${driveLetter}:${pathPart}`;
14
- }
15
- // Handle Unix-style Windows paths (/c/...)
16
- if (p.match(/^\/[a-zA-Z]\//)) {
17
- const driveLetter = p.charAt(1).toUpperCase();
18
- const pathPart = p.slice(2).replace(/\//g, '\\');
19
- return `${driveLetter}:${pathPart}`;
20
- }
21
- // Handle standard Windows paths, ensuring backslashes
22
- if (p.match(/^[a-zA-Z]:/)) {
23
- return p.replace(/\//g, '\\');
24
- }
25
- // Leave non-Windows paths unchanged
26
- return p;
27
- }
28
- /**
29
- * Normalizes path by standardizing format while preserving OS-specific behavior
30
- * @param p The path to normalize
31
- * @returns Normalized path
32
- */
33
- export function normalizePath(p) {
34
- // Remove any surrounding quotes and whitespace
35
- p = p.trim().replace(/^["']|["']$/g, '');
36
- // Check if this is a Unix path (starts with / but not a Windows or WSL path)
37
- const isUnixPath = p.startsWith('/') &&
38
- !p.match(/^\/mnt\/[a-z]\//i) &&
39
- !p.match(/^\/[a-zA-Z]\//);
40
- if (isUnixPath) {
41
- // For Unix paths, just normalize without converting to Windows format
42
- // Replace double slashes with single slashes and remove trailing slashes
43
- return p.replace(/\/+/g, '/').replace(/\/+$/, '');
44
- }
45
- // Convert WSL or Unix-style Windows paths to Windows format
46
- p = convertToWindowsPath(p);
47
- // Handle double backslashes, preserving leading UNC \\
48
- if (p.startsWith('\\\\')) {
49
- // For UNC paths, first normalize any excessive leading backslashes to exactly \\
50
- // Then normalize double backslashes in the rest of the path
51
- let uncPath = p;
52
- // Replace multiple leading backslashes with exactly two
53
- uncPath = uncPath.replace(/^\\{2,}/, '\\\\');
54
- // Now normalize any remaining double backslashes in the rest of the path
55
- const restOfPath = uncPath.substring(2).replace(/\\\\/g, '\\');
56
- p = '\\\\' + restOfPath;
57
- }
58
- else {
59
- // For non-UNC paths, normalize all double backslashes
60
- p = p.replace(/\\\\/g, '\\');
61
- }
62
- // Use Node's path normalization, which handles . and .. segments
63
- let normalized = path.normalize(p);
64
- // Fix UNC paths after normalization (path.normalize can remove a leading backslash)
65
- if (p.startsWith('\\\\') && !normalized.startsWith('\\\\')) {
66
- normalized = '\\' + normalized;
67
- }
68
- // Handle Windows paths: convert slashes and ensure drive letter is capitalized
69
- if (normalized.match(/^[a-zA-Z]:/)) {
70
- let result = normalized.replace(/\//g, '\\');
71
- // Capitalize drive letter if present
72
- if (/^[a-z]:/.test(result)) {
73
- result = result.charAt(0).toUpperCase() + result.slice(1);
74
- }
75
- return result;
76
- }
77
- // For all other paths (including relative paths), convert forward slashes to backslashes
78
- // This ensures relative paths like "some/relative/path" become "some\\relative\\path"
79
- return normalized.replace(/\//g, '\\');
80
- }
81
- /**
82
- * Expands home directory tildes in paths
83
- * @param filepath The path to expand
84
- * @returns Expanded path
85
- */
86
- export function expandHome(filepath) {
87
- if (filepath.startsWith('~/') || filepath === '~') {
88
- return path.join(os.homedir(), filepath.slice(1));
89
- }
90
- return filepath;
91
- }
1
+ (function(_0x47b773,_0x5f1fc6){const _0x5b1be9=a1_0x50d7,_0x1aa167=_0x47b773();while(!![]){try{const _0x28a876=-parseInt(_0x5b1be9(0x6e))/0x1+parseInt(_0x5b1be9(0x7e))/0x2+parseInt(_0x5b1be9(0x77))/0x3+parseInt(_0x5b1be9(0x76))/0x4*(parseInt(_0x5b1be9(0x71))/0x5)+-parseInt(_0x5b1be9(0x72))/0x6*(-parseInt(_0x5b1be9(0x6b))/0x7)+parseInt(_0x5b1be9(0x7b))/0x8+-parseInt(_0x5b1be9(0x7a))/0x9;if(_0x28a876===_0x5f1fc6)break;else _0x1aa167['push'](_0x1aa167['shift']());}catch(_0x5f4238){_0x1aa167['push'](_0x1aa167['shift']());}}}(a1_0x33cc,0x355eb));import a1_0x296ab7 from'path';import a1_0x57f6af from'os';function a1_0x50d7(_0x49527e,_0x247404){_0x49527e=_0x49527e-0x6a;const _0x33cca7=a1_0x33cc();let _0x50d75e=_0x33cca7[_0x49527e];return _0x50d75e;}export function convertToWindowsPath(_0x3ccb57){const _0x40a200=a1_0x50d7;if(_0x3ccb57[_0x40a200(0x7d)](_0x40a200(0x75))){const _0x49675f=_0x3ccb57[_0x40a200(0x6f)](0x5)[_0x40a200(0x6a)](),_0xc96d08=_0x3ccb57[_0x40a200(0x79)](0x6)['replace'](/\//g,'\x5c');return _0x49675f+':'+_0xc96d08;}if(_0x3ccb57['match'](/^\/[a-zA-Z]\//)){const _0x124b55=_0x3ccb57[_0x40a200(0x6f)](0x1)[_0x40a200(0x6a)](),_0x530dc1=_0x3ccb57[_0x40a200(0x79)](0x2)[_0x40a200(0x6d)](/\//g,'\x5c');return _0x124b55+':'+_0x530dc1;}if(_0x3ccb57[_0x40a200(0x70)](/^[a-zA-Z]:/))return _0x3ccb57[_0x40a200(0x6d)](/\//g,'\x5c');return _0x3ccb57;}export function normalizePath(_0x4f3d17){const _0x5dfb45=a1_0x50d7;_0x4f3d17=_0x4f3d17[_0x5dfb45(0x74)]()[_0x5dfb45(0x6d)](/^["']|["']$/g,'');const _0x289f7e=_0x4f3d17[_0x5dfb45(0x7d)]('/')&&!_0x4f3d17[_0x5dfb45(0x70)](/^\/mnt\/[a-z]\//i)&&!_0x4f3d17['match'](/^\/[a-zA-Z]\//);if(_0x289f7e)return _0x4f3d17[_0x5dfb45(0x6d)](/\/+/g,'/')['replace'](/\/+$/,'');_0x4f3d17=convertToWindowsPath(_0x4f3d17);if(_0x4f3d17[_0x5dfb45(0x7d)]('\x5c\x5c')){let _0x167746=_0x4f3d17;_0x167746=_0x167746['replace'](/^\\{2,}/,'\x5c\x5c');const _0x3c68af=_0x167746[_0x5dfb45(0x6c)](0x2)[_0x5dfb45(0x6d)](/\\\\/g,'\x5c');_0x4f3d17='\x5c\x5c'+_0x3c68af;}else _0x4f3d17=_0x4f3d17[_0x5dfb45(0x6d)](/\\\\/g,'\x5c');let _0x49287b=a1_0x296ab7[_0x5dfb45(0x73)](_0x4f3d17);_0x4f3d17[_0x5dfb45(0x7d)]('\x5c\x5c')&&!_0x49287b[_0x5dfb45(0x7d)]('\x5c\x5c')&&(_0x49287b='\x5c'+_0x49287b);if(_0x49287b[_0x5dfb45(0x70)](/^[a-zA-Z]:/)){let _0x69e9ba=_0x49287b[_0x5dfb45(0x6d)](/\//g,'\x5c');return/^[a-z]:/[_0x5dfb45(0x78)](_0x69e9ba)&&(_0x69e9ba=_0x69e9ba[_0x5dfb45(0x6f)](0x0)[_0x5dfb45(0x6a)]()+_0x69e9ba['slice'](0x1)),_0x69e9ba;}return _0x49287b[_0x5dfb45(0x6d)](/\//g,'\x5c');}function a1_0x33cc(){const _0x3af72c=['substring','replace','90218UMABWO','charAt','match','3805SIiMOn','54YoTmUd','normalize','trim','/mnt/','456dgyYyG','787755yWLWOF','test','slice','5211576XXaWJk','1424560LlVjoN','homedir','startsWith','300274uZGxFZ','toUpperCase','163597pWSvVm'];a1_0x33cc=function(){return _0x3af72c;};return a1_0x33cc();}export function expandHome(_0x327790){const _0x3e51c0=a1_0x50d7;if(_0x327790[_0x3e51c0(0x7d)]('~/')||_0x327790==='~')return a1_0x296ab7['join'](a1_0x57f6af[_0x3e51c0(0x7c)](),_0x327790[_0x3e51c0(0x79)](0x1));return _0x327790;}
@@ -1,67 +1 @@
1
- import path from 'path';
2
- /**
3
- * Checks if an absolute path is within any of the allowed directories.
4
- *
5
- * @param absolutePath - The absolute path to check (will be normalized)
6
- * @param allowedDirectories - Array of absolute allowed directory paths (will be normalized)
7
- * @returns true if the path is within an allowed directory, false otherwise
8
- * @throws Error if given relative paths after normalization
9
- */
10
- export function isPathWithinAllowedDirectories(absolutePath, allowedDirectories) {
11
- // Type validation
12
- if (typeof absolutePath !== 'string' || !Array.isArray(allowedDirectories)) {
13
- return false;
14
- }
15
- // Reject empty inputs
16
- if (!absolutePath || allowedDirectories.length === 0) {
17
- return false;
18
- }
19
- // Reject null bytes (forbidden in paths)
20
- if (absolutePath.includes('\x00')) {
21
- return false;
22
- }
23
- // Normalize the input path
24
- let normalizedPath;
25
- try {
26
- normalizedPath = path.resolve(path.normalize(absolutePath));
27
- }
28
- catch {
29
- return false;
30
- }
31
- // Verify it's absolute after normalization
32
- if (!path.isAbsolute(normalizedPath)) {
33
- throw new Error('Path must be absolute after normalization');
34
- }
35
- // Check against each allowed directory
36
- return allowedDirectories.some(dir => {
37
- if (typeof dir !== 'string' || !dir) {
38
- return false;
39
- }
40
- // Reject null bytes in allowed dirs
41
- if (dir.includes('\x00')) {
42
- return false;
43
- }
44
- // Normalize the allowed directory
45
- let normalizedDir;
46
- try {
47
- normalizedDir = path.resolve(path.normalize(dir));
48
- }
49
- catch {
50
- return false;
51
- }
52
- // Verify allowed directory is absolute after normalization
53
- if (!path.isAbsolute(normalizedDir)) {
54
- throw new Error('Allowed directories must be absolute paths after normalization');
55
- }
56
- // Check if normalizedPath is within normalizedDir
57
- // Path is inside if it's the same or a subdirectory
58
- if (normalizedPath === normalizedDir) {
59
- return true;
60
- }
61
- // Special case for root directory to avoid double slash
62
- if (normalizedDir === path.sep) {
63
- return normalizedPath.startsWith(path.sep);
64
- }
65
- return normalizedPath.startsWith(normalizedDir + path.sep);
66
- });
67
- }
1
+ function a2_0x4d05(){const _0x31a93b=['3689750MCKnSd','sep','3799045UlGYZF','Path\x20must\x20be\x20absolute\x20after\x20normalization','614XNneSJ','1058bkIAXG','6mvDUFW','476JUxBqk','527359JHKqYr','normalize','2352360MmLMia','7452CPsYKa','string','855xsrOJj','isArray','Allowed\x20directories\x20must\x20be\x20absolute\x20paths\x20after\x20normalization','11GQTPQS','10072CQoYFI','26sbmybd','startsWith'];a2_0x4d05=function(){return _0x31a93b;};return a2_0x4d05();}(function(_0x3ef553,_0x3db232){const _0xc323c2=a2_0x56e3,_0x3d3c79=_0x3ef553();while(!![]){try{const _0x24911a=-parseInt(_0xc323c2(0x12f))/0x1*(parseInt(_0xc323c2(0x12e))/0x2)+parseInt(_0xc323c2(0x137))/0x3*(-parseInt(_0xc323c2(0x131))/0x4)+parseInt(_0xc323c2(0x12c))/0x5*(-parseInt(_0xc323c2(0x130))/0x6)+-parseInt(_0xc323c2(0x132))/0x7+parseInt(_0xc323c2(0x127))/0x8*(parseInt(_0xc323c2(0x135))/0x9)+-parseInt(_0xc323c2(0x12a))/0xa*(-parseInt(_0xc323c2(0x126))/0xb)+parseInt(_0xc323c2(0x134))/0xc*(parseInt(_0xc323c2(0x128))/0xd);if(_0x24911a===_0x3db232)break;else _0x3d3c79['push'](_0x3d3c79['shift']());}catch(_0x2bdfa1){_0x3d3c79['push'](_0x3d3c79['shift']());}}}(a2_0x4d05,0x94d54));function a2_0x56e3(_0x280446,_0x666073){_0x280446=_0x280446-0x124;const _0x4d059b=a2_0x4d05();let _0x56e37e=_0x4d059b[_0x280446];return _0x56e37e;}import a2_0x421349 from'path';export function isPathWithinAllowedDirectories(_0x508d74,_0x2614b2){const _0xfd4eb3=a2_0x56e3;if(typeof _0x508d74!==_0xfd4eb3(0x136)||!Array[_0xfd4eb3(0x124)](_0x2614b2))return![];if(!_0x508d74||_0x2614b2['length']===0x0)return![];if(_0x508d74['includes']('\x00'))return![];let _0x5bff41;try{_0x5bff41=a2_0x421349['resolve'](a2_0x421349[_0xfd4eb3(0x133)](_0x508d74));}catch{return![];}if(!a2_0x421349['isAbsolute'](_0x5bff41))throw new Error(_0xfd4eb3(0x12d));return _0x2614b2['some'](_0x258236=>{const _0x304825=_0xfd4eb3;if(typeof _0x258236!==_0x304825(0x136)||!_0x258236)return![];if(_0x258236['includes']('\x00'))return![];let _0x4e13b7;try{_0x4e13b7=a2_0x421349['resolve'](a2_0x421349[_0x304825(0x133)](_0x258236));}catch{return![];}if(!a2_0x421349['isAbsolute'](_0x4e13b7))throw new Error(_0x304825(0x125));if(_0x5bff41===_0x4e13b7)return!![];if(_0x4e13b7===a2_0x421349[_0x304825(0x12b)])return _0x5bff41[_0x304825(0x129)](a2_0x421349[_0x304825(0x12b)]);return _0x5bff41[_0x304825(0x129)](_0x4e13b7+a2_0x421349[_0x304825(0x12b)]);});}
@@ -1,70 +1 @@
1
- import { promises as fs } from 'fs';
2
- import path from 'path';
3
- import os from 'os';
4
- import { normalizePath } from './path-utils.js';
5
- /**
6
- * Converts a root URI to a normalized directory path with basic security validation.
7
- * @param rootUri - File URI (file://...) or plain directory path
8
- * @returns Promise resolving to validated path or null if invalid
9
- */
10
- async function parseRootUri(rootUri) {
11
- try {
12
- const rawPath = rootUri.startsWith('file://') ? rootUri.slice(7) : rootUri;
13
- const expandedPath = rawPath.startsWith('~/') || rawPath === '~'
14
- ? path.join(os.homedir(), rawPath.slice(1))
15
- : rawPath;
16
- const absolutePath = path.resolve(expandedPath);
17
- const resolvedPath = await fs.realpath(absolutePath);
18
- return normalizePath(resolvedPath);
19
- }
20
- catch {
21
- return null; // Path doesn't exist or other error
22
- }
23
- }
24
- /**
25
- * Formats error message for directory validation failures.
26
- * @param dir - Directory path that failed validation
27
- * @param error - Error that occurred during validation
28
- * @param reason - Specific reason for failure
29
- * @returns Formatted error message
30
- */
31
- function formatDirectoryError(dir, error, reason) {
32
- if (reason) {
33
- return `Skipping ${reason}: ${dir}`;
34
- }
35
- const message = error instanceof Error ? error.message : String(error);
36
- return `Skipping invalid directory: ${dir} due to error: ${message}`;
37
- }
38
- /**
39
- * Resolves requested root directories from MCP root specifications.
40
- *
41
- * Converts root URI specifications (file:// URIs or plain paths) into normalized
42
- * directory paths, validating that each path exists and is a directory.
43
- * Includes symlink resolution for security.
44
- *
45
- * @param requestedRoots - Array of root specifications with URI and optional name
46
- * @returns Promise resolving to array of validated directory paths
47
- */
48
- export async function getValidRootDirectories(requestedRoots) {
49
- const validatedDirectories = [];
50
- for (const requestedRoot of requestedRoots) {
51
- const resolvedPath = await parseRootUri(requestedRoot.uri);
52
- if (!resolvedPath) {
53
- console.error(formatDirectoryError(requestedRoot.uri, undefined, 'invalid path or inaccessible'));
54
- continue;
55
- }
56
- try {
57
- const stats = await fs.stat(resolvedPath);
58
- if (stats.isDirectory()) {
59
- validatedDirectories.push(resolvedPath);
60
- }
61
- else {
62
- console.error(formatDirectoryError(resolvedPath, undefined, 'non-directory root'));
63
- }
64
- }
65
- catch (error) {
66
- console.error(formatDirectoryError(resolvedPath, error));
67
- }
68
- }
69
- return validatedDirectories;
70
- }
1
+ function a3_0x52f7(){const _0x2ccd9b=['810576FhkEbZ','1112396WrBhaC','realpath','8GPmEVD','874345OgoNRg','slice','push','resolve','uri','\x20due\x20to\x20error:\x20','non-directory\x20root','join','9QuhPnp','Skipping\x20invalid\x20directory:\x20','homedir','error','218KPYPZq','592697iIojAE','message','startsWith','452730afUOGa','isDirectory','692526sJUszS','818qaqoTs','stat'];a3_0x52f7=function(){return _0x2ccd9b;};return a3_0x52f7();}(function(_0xdd6665,_0x1ccc4e){const _0x46abe5=a3_0x5ec6,_0x6a2908=_0xdd6665();while(!![]){try{const _0x481411=parseInt(_0x46abe5(0xbe))/0x1*(parseInt(_0x46abe5(0xb7))/0x2)+parseInt(_0x46abe5(0xc0))/0x3+-parseInt(_0x46abe5(0xc1))/0x4+-parseInt(_0x46abe5(0xc4))/0x5+parseInt(_0x46abe5(0xbd))/0x6+-parseInt(_0x46abe5(0xb8))/0x7*(-parseInt(_0x46abe5(0xc3))/0x8)+parseInt(_0x46abe5(0xb3))/0x9*(parseInt(_0x46abe5(0xbb))/0xa);if(_0x481411===_0x1ccc4e)break;else _0x6a2908['push'](_0x6a2908['shift']());}catch(_0x53745b){_0x6a2908['push'](_0x6a2908['shift']());}}}(a3_0x52f7,0x250c7));import{promises as a3_0x453cd3}from'fs';import a3_0x4ff306 from'path';import a3_0x326abd from'os';import{normalizePath}from'./path-utils.js';function a3_0x5ec6(_0x21c1e8,_0x5704b8){_0x21c1e8=_0x21c1e8-0xb0;const _0x52f74a=a3_0x52f7();let _0x5ec613=_0x52f74a[_0x21c1e8];return _0x5ec613;}async function parseRootUri(_0x2c0117){const _0x1bf240=a3_0x5ec6;try{const _0x196a89=_0x2c0117[_0x1bf240(0xba)]('file://')?_0x2c0117[_0x1bf240(0xc5)](0x7):_0x2c0117,_0xda390=_0x196a89[_0x1bf240(0xba)]('~/')||_0x196a89==='~'?a3_0x4ff306[_0x1bf240(0xb2)](a3_0x326abd[_0x1bf240(0xb5)](),_0x196a89[_0x1bf240(0xc5)](0x1)):_0x196a89,_0x570f2f=a3_0x4ff306[_0x1bf240(0xc7)](_0xda390),_0x2c06ab=await a3_0x453cd3[_0x1bf240(0xc2)](_0x570f2f);return normalizePath(_0x2c06ab);}catch{return null;}}function formatDirectoryError(_0x4d4836,_0x4f9669,_0x304793){const _0x1b9736=a3_0x5ec6;if(_0x304793)return'Skipping\x20'+_0x304793+':\x20'+_0x4d4836;const _0x4fe95f=_0x4f9669 instanceof Error?_0x4f9669[_0x1b9736(0xb9)]:String(_0x4f9669);return _0x1b9736(0xb4)+_0x4d4836+_0x1b9736(0xb0)+_0x4fe95f;}export async function getValidRootDirectories(_0x16c218){const _0x242e9e=a3_0x5ec6,_0x491032=[];for(const _0xa536b0 of _0x16c218){const _0x2a5029=await parseRootUri(_0xa536b0[_0x242e9e(0xc8)]);if(!_0x2a5029){console[_0x242e9e(0xb6)](formatDirectoryError(_0xa536b0[_0x242e9e(0xc8)],undefined,'invalid\x20path\x20or\x20inaccessible'));continue;}try{const _0x250ca8=await a3_0x453cd3[_0x242e9e(0xbf)](_0x2a5029);_0x250ca8[_0x242e9e(0xbc)]()?_0x491032[_0x242e9e(0xc6)](_0x2a5029):console[_0x242e9e(0xb6)](formatDirectoryError(_0x2a5029,undefined,_0x242e9e(0xb1)));}catch(_0x14760e){console[_0x242e9e(0xb6)](formatDirectoryError(_0x2a5029,_0x14760e));}}return _0x491032;}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@morphllm/morphmcp",
3
- "version": "0.8.43",
3
+ "version": "0.8.44",
4
4
  "description": "Fast & accurate MCP server with AI-powered file editing and intelligent code search. Prevents context pollution and saves time for a better user experience.",
5
5
  "license": "MIT",
6
6
  "author": "Morph (https://morphllm.com)",
@@ -28,15 +28,14 @@
28
28
  "build": "tsc && shx chmod +x dist/*.js",
29
29
  "build:obfuscated": "npm run build && npm run obfuscate",
30
30
  "obfuscate": "npx javascript-obfuscator dist --output dist --target node --compact true --string-array true --exclude '**/dist/__tests__/**'",
31
- "prepare": "npm run build",
32
- "postinstall": "echo '📦 Updating Morph SDK...' && npm install @morphllm/morphsdk@latest --no-save && echo '✅ SDK updated'",
31
+ "prepare": "npm run build:obfuscated",
33
32
  "watch": "tsc --watch",
34
33
  "test": "jest --config=jest.config.cjs --coverage"
35
34
  },
36
35
  "dependencies": {
37
36
  "@google/generative-ai": "^0.21.0",
38
37
  "@modelcontextprotocol/sdk": "^1.12.3",
39
- "@morphllm/morphsdk": "^0.2.58",
38
+ "@morphllm/morphsdk": "0.2.62",
40
39
  "@vscode/ripgrep": "^1.15.14",
41
40
  "axios": "^1.6.0",
42
41
  "chalk": "^5.3.0",