@morphllm/morphmcp 0.8.35 → 0.8.37
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.
- package/dist/index.js +142 -0
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -6,10 +6,12 @@ import fs from "fs/promises";
|
|
|
6
6
|
import path from "path";
|
|
7
7
|
import os from 'os';
|
|
8
8
|
import { randomBytes } from 'crypto';
|
|
9
|
+
import { spawn } from 'child_process';
|
|
9
10
|
import { z } from "zod";
|
|
10
11
|
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
11
12
|
import { createTwoFilesPatch } from 'diff';
|
|
12
13
|
import { minimatch } from 'minimatch';
|
|
14
|
+
import semver from 'semver';
|
|
13
15
|
import { getValidRootDirectories } from './roots-utils.js';
|
|
14
16
|
import { executeEditFile } from '@morphllm/morphsdk/tools/fastapply';
|
|
15
17
|
import { runWarpGrep, LocalRipgrepProvider } from '@morphllm/morphsdk/tools/warp-grep';
|
|
@@ -72,6 +74,144 @@ if (args.length === 0 && !ENABLE_WORKSPACE_MODE) {
|
|
|
72
74
|
console.error(" 3. Workspace mode (default behavior, set ENABLE_WORKSPACE_MODE=false to disable)");
|
|
73
75
|
console.error("At least one directory must be provided by EITHER method for the server to operate.");
|
|
74
76
|
}
|
|
77
|
+
// =============================================================================
|
|
78
|
+
// Auto-Update System
|
|
79
|
+
// Checks for SDK updates periodically and installs them automatically
|
|
80
|
+
// =============================================================================
|
|
81
|
+
const AUTO_UPDATE_INTERVAL_MS = parseInt(process.env.AUTO_UPDATE_INTERVAL_MS || '3600000', 10); // Default: 1 hour
|
|
82
|
+
const DISABLE_AUTO_UPDATE = process.env.DISABLE_AUTO_UPDATE === 'true';
|
|
83
|
+
// Get current installed version from package.json
|
|
84
|
+
async function getInstalledVersion(packageName) {
|
|
85
|
+
try {
|
|
86
|
+
// For @morphllm/morphsdk, check the node_modules
|
|
87
|
+
const packageJsonPath = path.join(path.dirname(new URL(import.meta.url).pathname), '..', 'node_modules', ...packageName.split('/'), 'package.json');
|
|
88
|
+
const content = await fs.readFile(packageJsonPath, 'utf-8');
|
|
89
|
+
const pkg = JSON.parse(content);
|
|
90
|
+
return pkg.version || null;
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
// Try alternative path (when running from dist)
|
|
94
|
+
try {
|
|
95
|
+
const altPath = path.join(path.dirname(new URL(import.meta.url).pathname), 'node_modules', ...packageName.split('/'), 'package.json');
|
|
96
|
+
const content = await fs.readFile(altPath, 'utf-8');
|
|
97
|
+
const pkg = JSON.parse(content);
|
|
98
|
+
return pkg.version || null;
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// Fetch latest version from npm registry
|
|
106
|
+
async function getLatestVersion(packageName) {
|
|
107
|
+
try {
|
|
108
|
+
const response = await axios.get(`https://registry.npmjs.org/${packageName}/latest`, { timeout: 10000 });
|
|
109
|
+
return response.data?.version || null;
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Check if update is available for a package
|
|
116
|
+
async function checkPackageUpdate(packageName) {
|
|
117
|
+
const currentVersion = await getInstalledVersion(packageName);
|
|
118
|
+
const latestVersion = await getLatestVersion(packageName);
|
|
119
|
+
let updateAvailable = false;
|
|
120
|
+
if (currentVersion && latestVersion) {
|
|
121
|
+
try {
|
|
122
|
+
updateAvailable = semver.lt(currentVersion, latestVersion);
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// Invalid semver, skip
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
name: packageName,
|
|
130
|
+
currentVersion: currentVersion || 'unknown',
|
|
131
|
+
latestVersion,
|
|
132
|
+
updateAvailable,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
// Run npm/bun update and wait for completion
|
|
136
|
+
function runPackageUpdate(packageName) {
|
|
137
|
+
return new Promise((resolve) => {
|
|
138
|
+
// Determine package manager (prefer bun if available)
|
|
139
|
+
const packageManager = process.env.npm_execpath?.includes('bun') ? 'bun' : 'npm';
|
|
140
|
+
const args = packageManager === 'bun'
|
|
141
|
+
? ['add', packageName + '@latest']
|
|
142
|
+
: ['install', packageName + '@latest'];
|
|
143
|
+
const packageDir = path.dirname(new URL(import.meta.url).pathname);
|
|
144
|
+
const child = spawn(packageManager, args, {
|
|
145
|
+
cwd: packageDir,
|
|
146
|
+
stdio: 'pipe', // Capture output for debugging
|
|
147
|
+
env: { ...process.env, npm_config_fund: 'false', npm_config_audit: 'false' }, // Skip fund/audit for speed
|
|
148
|
+
});
|
|
149
|
+
let stderr = '';
|
|
150
|
+
child.stderr?.on('data', (data) => { stderr += data.toString(); });
|
|
151
|
+
child.on('error', (err) => {
|
|
152
|
+
console.error(`Update error: ${err.message}`);
|
|
153
|
+
resolve(false);
|
|
154
|
+
});
|
|
155
|
+
child.on('close', (code) => {
|
|
156
|
+
if (code !== 0 && stderr) {
|
|
157
|
+
console.error(`Update failed: ${stderr.slice(0, 200)}`);
|
|
158
|
+
}
|
|
159
|
+
resolve(code === 0);
|
|
160
|
+
});
|
|
161
|
+
// Timeout after 60 seconds
|
|
162
|
+
setTimeout(() => {
|
|
163
|
+
child.kill();
|
|
164
|
+
resolve(false);
|
|
165
|
+
}, 60000);
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
// Main auto-update check function
|
|
169
|
+
async function checkAndUpdatePackages() {
|
|
170
|
+
const packagesToCheck = [
|
|
171
|
+
'@morphllm/morphsdk',
|
|
172
|
+
'@morphllm/morphmcp',
|
|
173
|
+
];
|
|
174
|
+
for (const packageName of packagesToCheck) {
|
|
175
|
+
try {
|
|
176
|
+
const info = await checkPackageUpdate(packageName);
|
|
177
|
+
if (info.updateAvailable) {
|
|
178
|
+
console.error(`🔄 Update available for ${packageName}: ${info.currentVersion} → ${info.latestVersion}`);
|
|
179
|
+
console.error(`📦 Installing ${packageName}@${info.latestVersion}...`);
|
|
180
|
+
// Attempt to update and wait for completion
|
|
181
|
+
const updateSucceeded = await runPackageUpdate(packageName);
|
|
182
|
+
if (updateSucceeded) {
|
|
183
|
+
console.error(`✅ Updated ${packageName} to ${info.latestVersion} (will take effect on next restart)`);
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
console.error(`⚠️ Failed to update ${packageName}`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
// Silently ignore update check failures - don't disrupt the server
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// Start auto-update interval
|
|
196
|
+
let autoUpdateInterval = null;
|
|
197
|
+
function startAutoUpdate() {
|
|
198
|
+
if (DISABLE_AUTO_UPDATE) {
|
|
199
|
+
console.error('Auto-update disabled via DISABLE_AUTO_UPDATE=true');
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
console.error(`Auto-update enabled: checking every ${Math.round(AUTO_UPDATE_INTERVAL_MS / 60000)} minutes`);
|
|
203
|
+
// Check immediately on startup (after a short delay to not block initialization)
|
|
204
|
+
setTimeout(() => {
|
|
205
|
+
checkAndUpdatePackages().catch(() => { });
|
|
206
|
+
}, 5000);
|
|
207
|
+
// Then check periodically
|
|
208
|
+
autoUpdateInterval = setInterval(() => {
|
|
209
|
+
checkAndUpdatePackages().catch(() => { });
|
|
210
|
+
}, AUTO_UPDATE_INTERVAL_MS);
|
|
211
|
+
// Don't keep process alive just for updates
|
|
212
|
+
autoUpdateInterval.unref();
|
|
213
|
+
}
|
|
214
|
+
// =============================================================================
|
|
75
215
|
// Normalize all paths consistently
|
|
76
216
|
function normalizePath(p) {
|
|
77
217
|
return path.normalize(p);
|
|
@@ -1077,6 +1217,8 @@ async function runServer() {
|
|
|
1077
1217
|
if (allowedDirectories.length === 0) {
|
|
1078
1218
|
console.error("Started without allowed directories - waiting for client to provide roots via MCP protocol");
|
|
1079
1219
|
}
|
|
1220
|
+
// Start auto-update system
|
|
1221
|
+
startAutoUpdate();
|
|
1080
1222
|
}
|
|
1081
1223
|
runServer().catch((error) => {
|
|
1082
1224
|
console.error("Fatal error running server:", error);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@morphllm/morphmcp",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.37",
|
|
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)",
|
|
@@ -33,9 +33,10 @@
|
|
|
33
33
|
"test": "jest --config=jest.config.cjs --coverage"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
+
"@google/generative-ai": "^0.21.0",
|
|
36
37
|
"@modelcontextprotocol/sdk": "^1.12.3",
|
|
37
|
-
"@vscode/ripgrep": "^1.15.14",
|
|
38
38
|
"@morphllm/morphsdk": "*",
|
|
39
|
+
"@vscode/ripgrep": "^1.15.14",
|
|
39
40
|
"axios": "^1.6.0",
|
|
40
41
|
"chalk": "^5.3.0",
|
|
41
42
|
"diff": "^5.1.0",
|