@morphllm/morphmcp 0.8.43 → 0.8.46

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 a1_0x5bd2(){const _0x2294fd=['46328nqdfKc','match','6950010qjxcZk','8qSQDKG','/mnt/','startsWith','10106173NEARTC','test','homedir','182815yzMYJg','toUpperCase','2229618VdhiVG','trim','8iPgyAD','657eHSBjN','2576804OwcyNz','replace','601910EPPbZU','slice','substring'];a1_0x5bd2=function(){return _0x2294fd;};return a1_0x5bd2();}(function(_0x874f7d,_0x2ca87b){const _0x127ab9=a1_0x2106,_0x5b6d71=_0x874f7d();while(!![]){try{const _0xfcc187=-parseInt(_0x127ab9(0x1d6))/0x1+parseInt(_0x127ab9(0x1e5))/0x2+-parseInt(_0x127ab9(0x1e1))/0x3*(-parseInt(_0x127ab9(0x1e3))/0x4)+-parseInt(_0x127ab9(0x1df))/0x5+parseInt(_0x127ab9(0x1d8))/0x6+-parseInt(_0x127ab9(0x1dc))/0x7*(-parseInt(_0x127ab9(0x1d9))/0x8)+parseInt(_0x127ab9(0x1e4))/0x9*(-parseInt(_0x127ab9(0x1e7))/0xa);if(_0xfcc187===_0x2ca87b)break;else _0x5b6d71['push'](_0x5b6d71['shift']());}catch(_0x5ce1ca){_0x5b6d71['push'](_0x5b6d71['shift']());}}}(a1_0x5bd2,0xdbbd6));import a1_0x1f2bf7 from'path';import a1_0x3e8db6 from'os';export function convertToWindowsPath(_0x526982){const _0x24c153=a1_0x2106;if(_0x526982[_0x24c153(0x1db)](_0x24c153(0x1da))){const _0x467078=_0x526982['charAt'](0x5)['toUpperCase'](),_0x469653=_0x526982[_0x24c153(0x1e8)](0x6)['replace'](/\//g,'\x5c');return _0x467078+':'+_0x469653;}if(_0x526982[_0x24c153(0x1d7)](/^\/[a-zA-Z]\//)){const _0x287a19=_0x526982['charAt'](0x1)[_0x24c153(0x1e0)](),_0x3f4141=_0x526982[_0x24c153(0x1e8)](0x2)[_0x24c153(0x1e6)](/\//g,'\x5c');return _0x287a19+':'+_0x3f4141;}if(_0x526982[_0x24c153(0x1d7)](/^[a-zA-Z]:/))return _0x526982[_0x24c153(0x1e6)](/\//g,'\x5c');return _0x526982;}function a1_0x2106(_0x4e08b3,_0x3339f3){_0x4e08b3=_0x4e08b3-0x1d5;const _0x5bd2a5=a1_0x5bd2();let _0x21063b=_0x5bd2a5[_0x4e08b3];return _0x21063b;}export function normalizePath(_0x5e1995){const _0x2436d7=a1_0x2106;_0x5e1995=_0x5e1995[_0x2436d7(0x1e2)]()['replace'](/^["']|["']$/g,'');const _0x321c40=_0x5e1995['startsWith']('/')&&!_0x5e1995[_0x2436d7(0x1d7)](/^\/mnt\/[a-z]\//i)&&!_0x5e1995['match'](/^\/[a-zA-Z]\//);if(_0x321c40)return _0x5e1995[_0x2436d7(0x1e6)](/\/+/g,'/')['replace'](/\/+$/,'');_0x5e1995=convertToWindowsPath(_0x5e1995);if(_0x5e1995[_0x2436d7(0x1db)]('\x5c\x5c')){let _0x3ab5e7=_0x5e1995;_0x3ab5e7=_0x3ab5e7[_0x2436d7(0x1e6)](/^\\{2,}/,'\x5c\x5c');const _0x534c83=_0x3ab5e7[_0x2436d7(0x1d5)](0x2)['replace'](/\\\\/g,'\x5c');_0x5e1995='\x5c\x5c'+_0x534c83;}else _0x5e1995=_0x5e1995[_0x2436d7(0x1e6)](/\\\\/g,'\x5c');let _0x36c08b=a1_0x1f2bf7['normalize'](_0x5e1995);_0x5e1995['startsWith']('\x5c\x5c')&&!_0x36c08b['startsWith']('\x5c\x5c')&&(_0x36c08b='\x5c'+_0x36c08b);if(_0x36c08b['match'](/^[a-zA-Z]:/)){let _0x1d9609=_0x36c08b[_0x2436d7(0x1e6)](/\//g,'\x5c');return/^[a-z]:/[_0x2436d7(0x1dd)](_0x1d9609)&&(_0x1d9609=_0x1d9609['charAt'](0x0)['toUpperCase']()+_0x1d9609[_0x2436d7(0x1e8)](0x1)),_0x1d9609;}return _0x36c08b[_0x2436d7(0x1e6)](/\//g,'\x5c');}export function expandHome(_0xc72608){const _0x215e3b=a1_0x2106;if(_0xc72608['startsWith']('~/')||_0xc72608==='~')return a1_0x1f2bf7['join'](a1_0x3e8db6[_0x215e3b(0x1de)](),_0xc72608[_0x215e3b(0x1e8)](0x1));return _0xc72608;}
@@ -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(_0x4c692c,_0x18fd77){const _0x45d41d=a2_0x5904,_0x5cdf1f=_0x4c692c();while(!![]){try{const _0x13d3cd=parseInt(_0x45d41d(0xd7))/0x1*(-parseInt(_0x45d41d(0xc9))/0x2)+parseInt(_0x45d41d(0xdc))/0x3+-parseInt(_0x45d41d(0xd4))/0x4*(parseInt(_0x45d41d(0xd3))/0x5)+-parseInt(_0x45d41d(0xd0))/0x6+parseInt(_0x45d41d(0xda))/0x7+parseInt(_0x45d41d(0xcf))/0x8+parseInt(_0x45d41d(0xdb))/0x9;if(_0x13d3cd===_0x18fd77)break;else _0x5cdf1f['push'](_0x5cdf1f['shift']());}catch(_0x4d096c){_0x5cdf1f['push'](_0x5cdf1f['shift']());}}}(a2_0x138e,0xaf15b));function a2_0x138e(){const _0x519dcc=['3197929CVlDBO','2224404cDSSAb','2471025EaAmOR','normalize','42JqJOqS','startsWith','isArray','string','resolve','Path\x20must\x20be\x20absolute\x20after\x20normalization','10315536XIarMu','1869480BNMsSb','some','includes','10eaBeKA','1011720QsyNMa','Allowed\x20directories\x20must\x20be\x20absolute\x20paths\x20after\x20normalization','sep','61073IWCsDt','isAbsolute','length'];a2_0x138e=function(){return _0x519dcc;};return a2_0x138e();}function a2_0x5904(_0x5128b7,_0x9c95d3){_0x5128b7=_0x5128b7-0xc8;const _0x138e0e=a2_0x138e();let _0x5904a2=_0x138e0e[_0x5128b7];return _0x5904a2;}import a2_0x4cc276 from'path';export function isPathWithinAllowedDirectories(_0xb389a0,_0x1e4c65){const _0x4c058b=a2_0x5904;if(typeof _0xb389a0!==_0x4c058b(0xcc)||!Array[_0x4c058b(0xcb)](_0x1e4c65))return![];if(!_0xb389a0||_0x1e4c65[_0x4c058b(0xd9)]===0x0)return![];if(_0xb389a0[_0x4c058b(0xd2)]('\x00'))return![];let _0x14b166;try{_0x14b166=a2_0x4cc276[_0x4c058b(0xcd)](a2_0x4cc276[_0x4c058b(0xc8)](_0xb389a0));}catch{return![];}if(!a2_0x4cc276[_0x4c058b(0xd8)](_0x14b166))throw new Error(_0x4c058b(0xce));return _0x1e4c65[_0x4c058b(0xd1)](_0x4d446f=>{const _0x1fc235=_0x4c058b;if(typeof _0x4d446f!==_0x1fc235(0xcc)||!_0x4d446f)return![];if(_0x4d446f[_0x1fc235(0xd2)]('\x00'))return![];let _0x38cfbd;try{_0x38cfbd=a2_0x4cc276['resolve'](a2_0x4cc276[_0x1fc235(0xc8)](_0x4d446f));}catch{return![];}if(!a2_0x4cc276[_0x1fc235(0xd8)](_0x38cfbd))throw new Error(_0x1fc235(0xd5));if(_0x14b166===_0x38cfbd)return!![];if(_0x38cfbd===a2_0x4cc276[_0x1fc235(0xd6)])return _0x14b166[_0x1fc235(0xca)](a2_0x4cc276['sep']);return _0x14b166[_0x1fc235(0xca)](_0x38cfbd+a2_0x4cc276[_0x1fc235(0xd6)]);});}
@@ -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(_0x4b23fb,_0x1a436d){const _0x504002=a3_0x4adc,_0x5bbfbe=_0x4b23fb();while(!![]){try{const _0x36beb0=parseInt(_0x504002(0x156))/0x1*(parseInt(_0x504002(0x145))/0x2)+-parseInt(_0x504002(0x152))/0x3+-parseInt(_0x504002(0x14c))/0x4+parseInt(_0x504002(0x14b))/0x5+-parseInt(_0x504002(0x148))/0x6+-parseInt(_0x504002(0x150))/0x7*(-parseInt(_0x504002(0x147))/0x8)+parseInt(_0x504002(0x143))/0x9;if(_0x36beb0===_0x1a436d)break;else _0x5bbfbe['push'](_0x5bbfbe['shift']());}catch(_0x4809fa){_0x5bbfbe['push'](_0x5bbfbe['shift']());}}}(a3_0x2e9f,0x6f4dc));import{promises as a3_0x3d91b2}from'fs';function a3_0x4adc(_0x2d721c,_0x56f539){_0x2d721c=_0x2d721c-0x143;const _0x2e9f91=a3_0x2e9f();let _0x4adcc5=_0x2e9f91[_0x2d721c];return _0x4adcc5;}import a3_0x4f7a4f from'path';import a3_0x570cf4 from'os';function a3_0x2e9f(){const _0x5a7d9d=['\x20due\x20to\x20error:\x20','151655AiVkWs','error','2534433KzRgrF','Skipping\x20invalid\x20directory:\x20','startsWith','push','1bIPOXe','realpath','file://','message','1059183enwSNW','slice','1689166rWBOFm','stat','256YaLRZD','3816516hIzYNN','uri','join','2956545qCpVpt','1240248fgznvN','non-directory\x20root','invalid\x20path\x20or\x20inaccessible'];a3_0x2e9f=function(){return _0x5a7d9d;};return a3_0x2e9f();}import{normalizePath}from'./path-utils.js';async function parseRootUri(_0x2a79ba){const _0x3f01c0=a3_0x4adc;try{const _0x3413d6=_0x2a79ba[_0x3f01c0(0x154)](_0x3f01c0(0x158))?_0x2a79ba[_0x3f01c0(0x144)](0x7):_0x2a79ba,_0x48a96c=_0x3413d6[_0x3f01c0(0x154)]('~/')||_0x3413d6==='~'?a3_0x4f7a4f[_0x3f01c0(0x14a)](a3_0x570cf4['homedir'](),_0x3413d6[_0x3f01c0(0x144)](0x1)):_0x3413d6,_0x8df750=a3_0x4f7a4f['resolve'](_0x48a96c),_0x3686bb=await a3_0x3d91b2[_0x3f01c0(0x157)](_0x8df750);return normalizePath(_0x3686bb);}catch{return null;}}function formatDirectoryError(_0x31b710,_0x4f8f5e,_0x2d4f31){const _0xb3941d=a3_0x4adc;if(_0x2d4f31)return'Skipping\x20'+_0x2d4f31+':\x20'+_0x31b710;const _0x860d1f=_0x4f8f5e instanceof Error?_0x4f8f5e[_0xb3941d(0x159)]:String(_0x4f8f5e);return _0xb3941d(0x153)+_0x31b710+_0xb3941d(0x14f)+_0x860d1f;}export async function getValidRootDirectories(_0x4ab8d4){const _0x30334f=a3_0x4adc,_0x51085c=[];for(const _0x25bb4e of _0x4ab8d4){const _0x4043eb=await parseRootUri(_0x25bb4e[_0x30334f(0x149)]);if(!_0x4043eb){console[_0x30334f(0x151)](formatDirectoryError(_0x25bb4e['uri'],undefined,_0x30334f(0x14e)));continue;}try{const _0x5e100e=await a3_0x3d91b2[_0x30334f(0x146)](_0x4043eb);_0x5e100e['isDirectory']()?_0x51085c[_0x30334f(0x155)](_0x4043eb):console[_0x30334f(0x151)](formatDirectoryError(_0x4043eb,undefined,_0x30334f(0x14d)));}catch(_0x9866da){console[_0x30334f(0x151)](formatDirectoryError(_0x4043eb,_0x9866da));}}return _0x51085c;}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@morphllm/morphmcp",
3
- "version": "0.8.43",
3
+ "version": "0.8.46",
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.65",
40
39
  "@vscode/ripgrep": "^1.15.14",
41
40
  "axios": "^1.6.0",
42
41
  "chalk": "^5.3.0",