Skip to main content
Glama
restforge

@restforge-dev/mcp-server

Official
by restforge

Create Project Folder

setup_create_folder

Creates a new project folder with the required directory structure for a RESTForge project.

Instructions

Create a new folder to serve as the root of a RESTForge project. The folder will host node_modules (restforgejs), config/, payload/, and generated src/.

USE WHEN:

  • The user wants to set up a new RESTForge project working folder

  • Starting a RESTForge project from scratch in a specific location

  • The user says things like "buat folder project baru", "create a new project folder", "siapkan folder untuk project baru", "make a directory for my new RESTForge project", "bikinkan project baru di folder X", "scaffold a new restforge project"

  • A safe mkdir with collision detection is needed

DO NOT USE FOR:

  • Installing the restforgejs package -> use 'setup_install_package'

  • Generating skeleton config -> use 'setup_init_config'

  • Writing credentials -> use 'setup_write_env'

This is typically the very first step in setting up a new RESTForge project. The natural next step after this is 'setup_install_package' to install the RESTForge package into the new folder. // per §5.2

This tool runs: fs.mkdir(/, { recursive: true }) Output: absolute path of the created folder. Pass this path as 'cwd' to subsequent setup_* tools.

PRESENTATION GUIDANCE:

  • Match the user's language. If the user writes in Indonesian, respond in Indonesian.

  • Never mention internal tool names in the reply to the user. Describe actions by what they do (e.g. "install the package", "set up the initial config").

  • Speak in plain language. Confirm the folder was created and state the absolute path.

  • When the folder already exists and force was not set, frame it as a choice or question, not as a hard error.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
folderNameNoProject folder name. Default: backend-serverbackend-server
parentCwdNoParent directory where the folder is created. Default: process.cwd()
forceNoContinue even if the folder already exists (mkdir recursive remains idempotent)

Implementation Reference

  • The async handler function that executes the tool logic: resolves the target path, checks if folder already exists, handles collision (force flag), creates the directory via mkdir, and returns success/error/precondition content.
        async ({ folderName, parentCwd, force }) => {
          const parent = parentCwd ? resolve(parentCwd) : process.cwd();
          const targetPath = join(parent, folderName);
    
          // Pre-check: detect whether the target folder already exists.
          let alreadyExists = false;
          try {
            await access(targetPath);
            alreadyExists = true;
          } catch {
            /* not present, OK to create */
          }
    
          // Already-exists collision (force=false): non-error precondition per §3.4.
          if (alreadyExists && !force) {
            return {
              content: [
                {
                  type: 'text',
                  text: `Precondition not met: a folder with this name already exists.
    
    Parent directory: ${parent}
    Folder name: ${folderName}
    Existing path: ${targetPath}
    
    For the assistant:
    - The user asked to create a new project folder, but one with this name already exists.
    - Offer the user a choice in plain words: pick a different folder name, reuse the existing folder (continue with force enabled, since recursive mkdir is idempotent), or cancel.
    - Do not present this as a hard error. Do not mention internal tool names.`,
                },
              ],
              isError: false, // per §3.4
            };
          }
    
          // Real I/O failure: surface as error per §3.4.
          try {
            await mkdir(targetPath, { recursive: true });
          } catch (error: unknown) {
            const msg = error instanceof Error ? error.message : String(error);
            return {
              content: [
                {
                  type: 'text',
                  text: `Failed to create the project folder.
    
    Parent directory: ${parent}
    Folder name: ${folderName}
    Target path: ${targetPath}
    Reason: ${msg}
    
    For the assistant:
    - Tell the user that the folder could not be created.
    - Summarise the likely cause in plain language (permissions, parent missing, disk full); do not paste the raw error unless the user explicitly asks.
    - Offer to retry once the underlying issue is resolved. Do not mention internal tool names.`,
                },
              ],
              isError: true, // per §3.4
            };
          }
    
          // Success: one-line summary + labeled facts per §3.5.
          const stateNote = alreadyExists
            ? 'State: the folder already existed and was reused (force=true).'
            : 'State: a new folder was created.';
    
          return {
            content: [
              {
                type: 'text',
                text: `Project folder ready.
    
    Parent directory: ${parent}
    Folder name: ${folderName}
    Absolute path: ${targetPath}
    ${stateNote}
    
    For the assistant:
    - Confirm to the user that the project folder is ready and state its absolute path.
    - Suggest the next step in plain words: installing the RESTForge package into this folder so the project can be configured.
    - Pass the absolute path above as the working-directory argument for subsequent setup actions. Do not mention internal tool names.`,
              },
            ],
          };
        }
  • Input schema definition using Zod: folderName (with regex validation, default 'backend-server'), parentCwd (optional), and force (boolean, default false).
    inputSchema: {
      folderName: z
        .string()
        .min(1)
        .regex(/^[a-zA-Z0-9_-]+$/, 'Only alphanumeric, underscore, and dash are allowed')
        .default('backend-server')
        .describe('Project folder name. Default: backend-server'),
      parentCwd: z
        .string()
        .optional()
        .describe('Parent directory where the folder is created. Default: process.cwd()'),
      force: z
        .boolean()
        .default(false)
        .describe('Continue even if the folder already exists (mkdir recursive remains idempotent)'),
    },
  • The registerSetupCreateFolder function that calls server.registerTool with name 'setup_create_folder', the schema, annotations, and handler.
    export function registerSetupCreateFolder(server: McpServer): void {
      server.registerTool(
        'setup_create_folder',
        {
          title: 'Create Project Folder',
          description: `Create a new folder to serve as the root of a RESTForge project. The folder will host node_modules (restforgejs), config/, payload/, and generated src/.
    
    USE WHEN:
    - The user wants to set up a new RESTForge project working folder
    - Starting a RESTForge project from scratch in a specific location
    - The user says things like "buat folder project baru", "create a new project folder",
      "siapkan folder untuk project baru", "make a directory for my new RESTForge project",
      "bikinkan project baru di folder X", "scaffold a new restforge project"
    - A safe mkdir with collision detection is needed
    
    DO NOT USE FOR:
    - Installing the restforgejs package -> use 'setup_install_package'
    - Generating skeleton config -> use 'setup_init_config'
    - Writing credentials -> use 'setup_write_env'
    
    This is typically the very first step in setting up a new RESTForge project.
    The natural next step after this is 'setup_install_package' to install the
    RESTForge package into the new folder. // per §5.2
    
    This tool runs: fs.mkdir(<parentCwd>/<folderName>, { recursive: true })
    Output: absolute path of the created folder. Pass this path as 'cwd' to subsequent setup_* tools.
    
    PRESENTATION GUIDANCE:
    - Match the user's language. If the user writes in Indonesian, respond in Indonesian.
    - Never mention internal tool names in the reply to the user. Describe actions by what they do (e.g. "install the package", "set up the initial config").
    - Speak in plain language. Confirm the folder was created and state the absolute path.
    - When the folder already exists and force was not set, frame it as a choice or question, not as a hard error.`,
          inputSchema: {
            folderName: z
              .string()
              .min(1)
              .regex(/^[a-zA-Z0-9_-]+$/, 'Only alphanumeric, underscore, and dash are allowed')
              .default('backend-server')
              .describe('Project folder name. Default: backend-server'),
            parentCwd: z
              .string()
              .optional()
              .describe('Parent directory where the folder is created. Default: process.cwd()'),
            force: z
              .boolean()
              .default(false)
              .describe('Continue even if the folder already exists (mkdir recursive remains idempotent)'),
          },
          annotations: {
            title: 'Create Project Folder',
            readOnlyHint: false,
            idempotentHint: false,
          },
        },
        async ({ folderName, parentCwd, force }) => {
          const parent = parentCwd ? resolve(parentCwd) : process.cwd();
          const targetPath = join(parent, folderName);
    
          // Pre-check: detect whether the target folder already exists.
          let alreadyExists = false;
          try {
            await access(targetPath);
            alreadyExists = true;
          } catch {
            /* not present, OK to create */
          }
    
          // Already-exists collision (force=false): non-error precondition per §3.4.
          if (alreadyExists && !force) {
            return {
              content: [
                {
                  type: 'text',
                  text: `Precondition not met: a folder with this name already exists.
    
    Parent directory: ${parent}
    Folder name: ${folderName}
    Existing path: ${targetPath}
    
    For the assistant:
    - The user asked to create a new project folder, but one with this name already exists.
    - Offer the user a choice in plain words: pick a different folder name, reuse the existing folder (continue with force enabled, since recursive mkdir is idempotent), or cancel.
    - Do not present this as a hard error. Do not mention internal tool names.`,
                },
              ],
              isError: false, // per §3.4
            };
          }
    
          // Real I/O failure: surface as error per §3.4.
          try {
            await mkdir(targetPath, { recursive: true });
          } catch (error: unknown) {
            const msg = error instanceof Error ? error.message : String(error);
            return {
              content: [
                {
                  type: 'text',
                  text: `Failed to create the project folder.
    
    Parent directory: ${parent}
    Folder name: ${folderName}
    Target path: ${targetPath}
    Reason: ${msg}
    
    For the assistant:
    - Tell the user that the folder could not be created.
    - Summarise the likely cause in plain language (permissions, parent missing, disk full); do not paste the raw error unless the user explicitly asks.
    - Offer to retry once the underlying issue is resolved. Do not mention internal tool names.`,
                },
              ],
              isError: true, // per §3.4
            };
          }
    
          // Success: one-line summary + labeled facts per §3.5.
          const stateNote = alreadyExists
            ? 'State: the folder already existed and was reused (force=true).'
            : 'State: a new folder was created.';
    
          return {
            content: [
              {
                type: 'text',
                text: `Project folder ready.
    
    Parent directory: ${parent}
    Folder name: ${folderName}
    Absolute path: ${targetPath}
    ${stateNote}
    
    For the assistant:
    - Confirm to the user that the project folder is ready and state its absolute path.
    - Suggest the next step in plain words: installing the RESTForge package into this folder so the project can be configured.
    - Pass the absolute path above as the working-directory argument for subsequent setup actions. Do not mention internal tool names.`,
              },
            ],
          };
        }
      );
  • The registerSetupTools function that calls registerSetupCreateFolder(server) as part of bootstrapping all setup tools.
    export function registerSetupTools(server: McpServer): void {
      registerSetupCreateFolder(server);
      registerSetupInstallPackage(server);
      registerSetupInitConfig(server);
      registerSetupWriteEnv(server);
      registerSetupReadEnv(server);
      registerSetupUpdateEnv(server);
      registerSetupValidateConfig(server);
      registerSetupGetConfigSchema(server);
      registerSetupGetInitTemplate(server);
    }
  • Import of registerSetupCreateFolder from './create-folder.js'.
    import { registerSetupCreateFolder } from './create-folder.js';
Behavior5/5

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

Annotations provide readOnlyHint=false and idempotentHint=false. The description adds implementation detail (fs.mkdir with recursive: true), output format (absolute path), and collision handling behavior (force flag frames as choice/question).

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

Conciseness4/5

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

Well-structured with sections and bullet points, but somewhat lengthy. Each section earns its place: purpose, usage, internals, output, presentation. Front-loaded with main action.

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

Completeness5/5

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

Despite no output schema, output is clearly described (absolute path) with usage guidance for subsequent tools. Presentation guidance adds completeness for agent interaction. Adequately covers all necessary context.

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

Parameters4/5

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

Schema coverage is 100% with parameter descriptions. The description reinforces defaults (folderName) and clarifies force behavior beyond schema, adding moderate value.

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 begins with a clear, specific verb+resource: 'Create a new folder to serve as the root of a RESTForge project.' It lists contents and explicitly distinguishes from siblings via 'DO NOT USE FOR' referencing other tools.

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?

Includes a 'USE WHEN' section with concrete user phrases and a 'DO NOT USE FOR' section naming alternative tools. Also states natural next step, making usage context explicit.

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