Skip to main content
Glama

patch_apply

Apply unified diff patches to files on remote servers via SSH to modify configurations, fix bugs, or update code without manual editing.

Instructions

Applies a patch to a file

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
sessionIdYesSSH session ID
pathYesFile path to patch
patchYesPatch content (unified diff format)

Implementation Reference

  • The `applyPatch` function handles the logic for applying a unified diff patch to a remote file. It performs a dry run first and handles temporary file cleanup.
    export async function applyPatch(
      sessionId: string,
      filePath: string,
      diff: string,
      sudoPassword?: string
    ): Promise<PatchResult> {
      logger.debug('Applying patch to file', { sessionId, filePath });
    
      try {
        const osInfo = await sessionManager.getOSInfo(sessionId);
        // Check if patch command is available
        const hasPatch = await commandExists(sessionId, 'patch');
        if (!hasPatch) {
          throw createPatchError(
            'patch command not found on remote system',
            'Install patch utility or apply changes manually'
          );
        }
    
        // Write patch to temporary file
        const tempDir = resolveRemoteTempDir(osInfo);
        const baseTempDir = tempDir.replace(/\/+$/, '');
        const tempPatchFile = `${baseTempDir}/ssh-mcp-patch-${Date.now()}.patch`;
        await writeFile(sessionId, tempPatchFile, diff);
    
        try {
          // Test patch first (dry run)
          const testResult = await execCommand(
            sessionId,
            `patch --dry-run -p0 ${filePath} < ${tempPatchFile}`
          );
    
          if (testResult.code !== 0) {
            throw createPatchError(
              'Patch would fail to apply',
              `Patch test failed: ${testResult.stderr}`
            );
          }
    
          // Apply patch
          const applyCommand = `patch -p0 ${filePath} < ${tempPatchFile}`;
          let result;
    
          if (sudoPassword) {
            result = await execSudo(sessionId, applyCommand, sudoPassword);
          } else {
            result = await execCommand(sessionId, applyCommand);
          }
    
          const patchResult: PatchResult = {
            ok: result.code === 0,
            changed: result.code === 0
          };
    
          if (result.code === 0) {
            logger.info('Patch applied successfully', { sessionId, filePath });
          } else {
            logger.error('Patch application failed', {
              sessionId,
              filePath,
              code: result.code,
              stderr: result.stderr
            });
          }
    
          return patchResult;
    
        } finally {
          // Clean up temporary patch file
          try {
            const cleanupCommand = osInfo.platform === 'windows'
              ? `Remove-Item -Path ${tempPatchFile} -Force -ErrorAction SilentlyContinue`
              : `rm -f ${tempPatchFile}`;
            await execCommand(sessionId, cleanupCommand);
          } catch (error) {
            logger.warn('Failed to clean up temporary patch file', { tempPatchFile, error });
          }
        }
    
      } catch (error) {
        logger.error('Failed to apply patch', { sessionId, filePath, error });
        throw error;
      }
    }
  • Schema definition for the "patch_apply" tool inputs.
    export const PatchApplySchema = z.object({
      sessionId: z.string().min(1),
      path: z.string().min(1),
      diff: z.string(),
      sudoPassword: z.string().optional()
    });
  • src/mcp.ts:496-501 (registration)
    Tool handler registration for "patch_apply" in `src/mcp.ts`.
    case 'patch_apply': {
      const params = PatchApplySchema.parse(args);
      const result = await applyPatch(params.sessionId, params.path, params.diff, params.sudoPassword);
      logger.info('Patch applied', { sessionId: params.sessionId, path: params.path });
      return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
    }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/oaslananka/mcp-ssh-tool'

If you have feedback or need assistance with the MCP directory API, please join our Discord server