Skip to main content
Glama
restforge

@restforge-dev/mcp-server

Official
by restforge

Check Launcher File Existence

runtime_check_launcher_exists
Read-onlyIdempotent

Checks if launcher files exist in the project root to prevent unintended overwrites during generation. Returns a list of existing files without creating anything.

Instructions

Check whether the launcher files that would be produced by 'runtime_generate_launcher' already exist in the project root. Read-only — does not create or overwrite anything.

USE WHEN:

  • Before invoking 'runtime_generate_launcher' — to detect potential overwrites and ask the user for confirmation

  • The user wants to know which files would be created without committing

  • The user is debugging an existing setup and wants to confirm what files exist

DO NOT USE FOR:

  • Generating launcher files -> use 'runtime_generate_launcher'

  • Reading the content of an existing launcher -> use generic Read tools

  • Checking if the server is currently running -> use 'runtime_check_status'

The list of files depends on os + mode (file names are FIXED, not user-customisable):

  • windows + host: server-start.bat, server-stop.bat

  • windows + pm2: server-start.bat, server-stop.bat, ecosystem.config.js

  • linux + host: server-start.sh, server-stop.sh

  • linux + pm2: server-start.sh, server-stop.sh, ecosystem.config.js

PRESENTATION GUIDANCE:

  • Match the user's language.

  • Never mention internal tool names.

  • When at least one file already exists, ask the user whether to overwrite (then call generate with overwrite=true).

  • Do not echo the JSON unless explicitly asked.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
cwdYesAbsolute path of the project folder root
osYesTarget OS for the launcher
modeYesRuntime mode

Implementation Reference

  • The async handler function that checks if launcher files exist. Uses fs.access to check each file and returns existence status.
        async ({ cwd, os, mode }) => {
          const projectCwd = resolve(cwd);
          const files = getLauncherFiles(os, mode);
          const checked = await Promise.all(
            files.map(async (f) => {
              const path = join(projectCwd, f);
              let exists = false;
              try {
                await access(path);
                exists = true;
              } catch {
                exists = false;
              }
              return { path, exists };
            })
          );
          const anyExists = checked.some((c) => c.exists);
    
          const envelope = {
            cwd: projectCwd,
            os,
            mode,
            files: checked,
            any_exists: anyExists,
          };
          const prettyJson = JSON.stringify(envelope, null, 2);
    
          const summary = anyExists
            ? 'One or more launcher files already exist in the project root.'
            : 'No conflicting launcher files. Safe to generate.';
    
          return {
            content: [
              {
                type: 'text',
                text: `${summary}
    
    Project path: ${projectCwd}
    OS: ${os}
    Mode: ${mode}
    
    --- Existence Check (JSON) ---
    ${prettyJson}
    --- end Existence Check (JSON) ---
    
    For the assistant:
    - ${
                  anyExists
                    ? 'Some files would be overwritten. Ask the user whether to overwrite (then call generate with overwrite: true).'
                    : 'No files would be overwritten. The user can proceed to generate.'
                }
    - File names are fixed: server-start.{bat|sh}, server-stop.{bat|sh}, plus ecosystem.config.js for PM2 mode.
    - Match the user's language.`,
              },
            ],
            isError: false,
          };
        }
      );
    }
  • Input schema validation using zod: cwd (string), os (enum windows/linux), mode (enum host/pm2).
    inputSchema: {
      cwd: z.string().min(1).describe('Absolute path of the project folder root'),
      os: z.enum(['windows', 'linux']).describe('Target OS for the launcher'),
      mode: z.enum(['host', 'pm2']).describe('Runtime mode'),
    },
    annotations: {
      title: 'Check Launcher Files',
      readOnlyHint: true,
      idempotentHint: true,
    },
  • The registerRuntimeCheckLauncherExists function registers the tool 'runtime_check_launcher_exists' on the MCP server.
    export function registerRuntimeCheckLauncherExists(server: McpServer): void {
      server.registerTool(
        'runtime_check_launcher_exists',
        {
          title: 'Check Launcher File Existence',
          description: `Check whether the launcher files that would be produced by 'runtime_generate_launcher' already exist in the project root. Read-only — does not create or overwrite anything.
    
    USE WHEN:
    - Before invoking 'runtime_generate_launcher' — to detect potential overwrites and ask the user for confirmation
    - The user wants to know which files would be created without committing
    - The user is debugging an existing setup and wants to confirm what files exist
    
    DO NOT USE FOR:
    - Generating launcher files -> use 'runtime_generate_launcher'
    - Reading the content of an existing launcher -> use generic Read tools
    - Checking if the server is currently running -> use 'runtime_check_status'
    
    The list of files depends on os + mode (file names are FIXED, not user-customisable):
    - windows + host: server-start.bat, server-stop.bat
    - windows + pm2:  server-start.bat, server-stop.bat, ecosystem.config.js
    - linux + host:   server-start.sh, server-stop.sh
    - linux + pm2:    server-start.sh, server-stop.sh, ecosystem.config.js
    
    PRESENTATION GUIDANCE:
    - Match the user's language.
    - Never mention internal tool names.
    - When at least one file already exists, ask the user whether to overwrite (then call generate with overwrite=true).
    - Do not echo the JSON unless explicitly asked.`,
          inputSchema: {
            cwd: z.string().min(1).describe('Absolute path of the project folder root'),
            os: z.enum(['windows', 'linux']).describe('Target OS for the launcher'),
            mode: z.enum(['host', 'pm2']).describe('Runtime mode'),
          },
          annotations: {
            title: 'Check Launcher Files',
            readOnlyHint: true,
            idempotentHint: true,
          },
        },
        async ({ cwd, os, mode }) => {
          const projectCwd = resolve(cwd);
          const files = getLauncherFiles(os, mode);
          const checked = await Promise.all(
            files.map(async (f) => {
              const path = join(projectCwd, f);
              let exists = false;
              try {
                await access(path);
                exists = true;
              } catch {
                exists = false;
              }
              return { path, exists };
            })
          );
          const anyExists = checked.some((c) => c.exists);
    
          const envelope = {
            cwd: projectCwd,
            os,
            mode,
            files: checked,
            any_exists: anyExists,
          };
          const prettyJson = JSON.stringify(envelope, null, 2);
    
          const summary = anyExists
            ? 'One or more launcher files already exist in the project root.'
            : 'No conflicting launcher files. Safe to generate.';
    
          return {
            content: [
              {
                type: 'text',
                text: `${summary}
    
    Project path: ${projectCwd}
    OS: ${os}
    Mode: ${mode}
    
    --- Existence Check (JSON) ---
    ${prettyJson}
    --- end Existence Check (JSON) ---
    
    For the assistant:
    - ${
                  anyExists
                    ? 'Some files would be overwritten. Ask the user whether to overwrite (then call generate with overwrite: true).'
                    : 'No files would be overwritten. The user can proceed to generate.'
                }
    - File names are fixed: server-start.{bat|sh}, server-stop.{bat|sh}, plus ecosystem.config.js for PM2 mode.
    - Match the user's language.`,
              },
            ],
            isError: false,
          };
        }
      );
    }
  • Helper function getLauncherFiles that returns the list of file names based on OS (windows/linux) and mode (host/pm2).
    function getLauncherFiles(os: 'windows' | 'linux', mode: 'host' | 'pm2'): string[] {
      const files: string[] = [LAUNCHER_FILES[os].start, LAUNCHER_FILES[os].stop];
      if (mode === 'pm2') {
        files.push(ECOSYSTEM_FILE);
      }
      return files;
    }
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint and idempotentHint; the description adds behavioral details like read-only, no creation/overwrite, and fixed file names per os+mode, but doesn't cover return format.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with clear sections and bullet points, each sentence adds value; no unnecessary verbiage despite moderate length.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema and description doesn't explain what the tool returns (e.g., list of files or boolean), which is a gap for a simple check tool. Otherwise complete for usage context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Input schema covers 100% of parameter descriptions, so baseline is 3. The description adds file name details but doesn't enhance parameter understanding beyond schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool checks existence of launcher files produced by runtime_generate_launcher, uses specific verbs, and distinguishes from sibling tools like runtime_generate_launcher and runtime_check_status.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit USE WHEN and DO NOT USE FOR sections provide clear context and alternatives, such as using runtime_generate_launcher for generation and generic Read tools for reading content.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/restforge/restforge-mcp'

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