Filesystem MCP Server
by bsmi021
- src
- operations
import { promises as fs } from 'fs';
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
/**
* Interface for file permissions
*/
export interface FilePermissions {
owner: {
read: boolean;
write: boolean;
execute: boolean;
};
group: {
read: boolean;
write: boolean;
execute: boolean;
};
others: {
read: boolean;
write: boolean;
execute: boolean;
};
}
/**
* Convert mode number to permissions object
*/
export function modeToPermissions(mode: number): FilePermissions {
return {
owner: {
read: Boolean(mode & 0o400),
write: Boolean(mode & 0o200),
execute: Boolean(mode & 0o100)
},
group: {
read: Boolean(mode & 0o40),
write: Boolean(mode & 0o20),
execute: Boolean(mode & 0o10)
},
others: {
read: Boolean(mode & 0o4),
write: Boolean(mode & 0o2),
execute: Boolean(mode & 0o1)
}
};
}
/**
* Convert permissions object to mode number
*/
export function permissionsToMode(permissions: FilePermissions): number {
let mode = 0;
// Owner permissions
if (permissions.owner.read) mode |= 0o400;
if (permissions.owner.write) mode |= 0o200;
if (permissions.owner.execute) mode |= 0o100;
// Group permissions
if (permissions.group.read) mode |= 0o40;
if (permissions.group.write) mode |= 0o20;
if (permissions.group.execute) mode |= 0o10;
// Others permissions
if (permissions.others.read) mode |= 0o4;
if (permissions.others.write) mode |= 0o2;
if (permissions.others.execute) mode |= 0o1;
return mode;
}
/**
* Get file permissions
*/
export async function getPermissions(filePath: string): Promise<FilePermissions> {
try {
const stats = await fs.stat(filePath);
return modeToPermissions(stats.mode);
} catch (error: any) {
throw new McpError(
ErrorCode.InternalError,
`Failed to get permissions: ${error.message}`
);
}
}
/**
* Set file permissions
*/
export async function setPermissions(filePath: string, permissions: FilePermissions): Promise<void> {
try {
const mode = permissionsToMode(permissions);
await fs.chmod(filePath, mode);
} catch (error: any) {
throw new McpError(
ErrorCode.InternalError,
`Failed to set permissions: ${error.message}`
);
}
}
/**
* Check if current process has read access
*/
export async function checkReadAccess(filePath: string): Promise<boolean> {
try {
await fs.access(filePath, fs.constants.R_OK);
return true;
} catch {
return false;
}
}
/**
* Check if current process has write access
*/
export async function checkWriteAccess(filePath: string): Promise<boolean> {
try {
await fs.access(filePath, fs.constants.W_OK);
return true;
} catch {
return false;
}
}
/**
* Check if current process has execute access
*/
export async function checkExecuteAccess(filePath: string): Promise<boolean> {
try {
await fs.access(filePath, fs.constants.X_OK);
return true;
} catch {
return false;
}
}
/**
* Make file executable
*/
export async function makeExecutable(filePath: string): Promise<void> {
try {
const stats = await fs.stat(filePath);
const newMode = stats.mode | 0o111; // Add execute permission for all
await fs.chmod(filePath, newMode);
} catch (error: any) {
throw new McpError(
ErrorCode.InternalError,
`Failed to make file executable: ${error.message}`
);
}
}