Files
myeasycms-v2/packages/mcp-server/src/tools/status/index.ts
Giancarlo Buomprisco ca585e09be 2.24.1 (#453)
* 2.24.1

- Updated dependencies
- MCP Server: better compatibility with Windows
- MCP Server: allow using a custom root for better flexibility
- Version Check: use package.json version instead of number of commits
- Prettier: reformatted some files
- Add SSH_AUTH_SOCK to dev passThroughEnv to solve SSH issues; handle execSync errors
- Use GIT_SSH to fix SSH issues on Windows
- Updated Stripe version
- Updated application version from 2.24.0 to 2.24.1 in package.json.
- Enhanced error handling in billing services to include error causes for better debugging.
2026-02-26 18:22:35 +08:00

140 lines
3.2 KiB
TypeScript

import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { access, readFile, stat } from 'node:fs/promises';
import { Socket } from 'node:net';
import { join } from 'node:path';
import { execFileAsync } from '../../lib/process-utils';
import {
type KitStatusDeps,
createKitStatusService,
} from './kit-status.service';
import { KitStatusInputSchema, KitStatusOutputSchema } from './schema';
export function registerKitStatusTool(server: McpServer, rootPath?: string) {
return server.registerTool(
'kit_status',
{
description: 'Project status with variant context',
inputSchema: KitStatusInputSchema,
outputSchema: KitStatusOutputSchema,
},
async (input) => {
const parsedInput = KitStatusInputSchema.parse(input);
try {
const service = createKitStatusService(createKitStatusDeps(rootPath));
const status = await service.getStatus(parsedInput);
return {
structuredContent: status,
content: [
{
type: 'text',
text: JSON.stringify(status),
},
],
};
} catch (error) {
const message = toErrorMessage(error);
return {
isError: true,
content: [
{
type: 'text',
text: `kit_status failed: ${message}`,
},
],
};
}
},
);
}
function createKitStatusDeps(rootPath = process.cwd()): KitStatusDeps {
return {
rootPath,
async readJsonFile(path: string): Promise<unknown> {
const filePath = join(rootPath, path);
const content = await readFile(filePath, 'utf8');
return JSON.parse(content) as unknown;
},
async pathExists(path: string) {
const fullPath = join(rootPath, path);
try {
await access(fullPath);
return true;
} catch {
return false;
}
},
async isDirectory(path: string) {
const fullPath = join(rootPath, path);
try {
const stats = await stat(fullPath);
return stats.isDirectory();
} catch {
return false;
}
},
async executeCommand(command: string, args: string[]) {
const result = await execFileAsync(command, args, {
cwd: rootPath,
});
return {
stdout: result.stdout,
stderr: result.stderr,
exitCode: 0,
};
},
async isPortOpen(port: number) {
return checkPort(port);
},
getNodeVersion() {
return process.version;
},
};
}
async function checkPort(port: number) {
return new Promise<boolean>((resolve) => {
const socket = new Socket();
socket.setTimeout(200);
socket.once('connect', () => {
socket.destroy();
resolve(true);
});
socket.once('timeout', () => {
socket.destroy();
resolve(false);
});
socket.once('error', () => {
socket.destroy();
resolve(false);
});
socket.connect(port, '127.0.0.1');
});
}
function toErrorMessage(error: unknown) {
if (error instanceof Error) {
return error.message;
}
return 'Unknown error';
}
export {
createKitStatusService,
type KitStatusDeps,
} from './kit-status.service';
export type { KitStatusOutput } from './schema';