Skip to main content
Glama
fkesheh

Skill Management MCP Server

by fkesheh

skill_files_crud

Perform CRUD operations on skill files to read, create, update, or delete content within skill directories, supporting both single and bulk file management.

Instructions

Unified CRUD tool for skill file operations. Supports both single and bulk operations.

IMPORTANT PATH NOTES:

  • All file paths are RELATIVE to the skill directory (e.g., 'main.py', 'scripts/utils.py')

  • NEVER use absolute paths (e.g., NOT '/Users/username/.skill-mcp/skills/my-skill/main.py')

  • To execute scripts, use the 'run_skill_script' tool, NOT external bash/shell tools

Operations:

  • read: Read a file's content

  • create: Create one or more files (supports atomic mode for bulk)

  • update: Update one or more files

  • delete: Delete a file (SKILL.md is protected and cannot be deleted)

Single File Examples:

// Read a file
{"operation": "read", "skill_name": "my-skill", "file_path": "script.py"}

// Create a single file
{"operation": "create", "skill_name": "my-skill", "file_path": "new.py", "content": "print('hello')"}

// Update a single file
{"operation": "update", "skill_name": "my-skill", "file_path": "script.py", "content": "print('updated')"}

// Delete a file
{"operation": "delete", "skill_name": "my-skill", "file_path": "old.py"}

Bulk File Examples:

// Read multiple files
{
  "operation": "read",
  "skill_name": "my-skill",
  "file_paths": ["file1.py", "file2.py", "file3.py"]
}

// Create multiple files atomically (all-or-nothing)
{
  "operation": "create",
  "skill_name": "my-skill",
  "files": [
    {"path": "src/main.py", "content": "# Main"},
    {"path": "src/utils.py", "content": "# Utils"},
    {"path": "README.md", "content": "# Docs"}
  ],
  "atomic": true
}

// Update multiple files
{
  "operation": "update",
  "skill_name": "my-skill",
  "files": [
    {"path": "file1.py", "content": "new content 1"},
    {"path": "file2.py", "content": "new content 2"}
  ]
}

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
operationYesOperation to perform: 'read', 'create', 'update', 'delete'
skill_nameYesName of the skill
file_pathNoRelative path to file (for single file operations)
contentNoFile content (for single create/update)
filesNoList of files for bulk create/update operations
file_pathsNoList of file paths for bulk read operations
atomicNoAtomic mode: rollback all on error (for bulk create)

Implementation Reference

  • Primary handler method `skill_files_crud` that dispatches CRUD operations (read, create, update, delete) based on input.operation and handles errors.
    async def skill_files_crud(input_data: SkillFilesCrudInput) -> list[types.TextContent]:
        """Handle file CRUD operations."""
        operation = input_data.operation
    
        try:
            if operation == "read":
                return await SkillFilesCrud._handle_read(input_data)
            elif operation == "create":
                return await SkillFilesCrud._handle_create(input_data)
            elif operation == "update":
                return await SkillFilesCrud._handle_update(input_data)
            elif operation == "delete":
                return await SkillFilesCrud._handle_delete(input_data)
            else:
                return [
                    types.TextContent(
                        type="text",
                        text=f"Unknown operation: {operation}. Valid operations: read, create, update, delete",
                    )
                ]
        except Exception as e:
            return [types.TextContent(type="text", text=f"Error: {str(e)}")]
  • Pydantic `BaseModel` defining the input schema for the `skill_files_crud` tool, including fields for operation, skill_name, single/bulk file paths, content, and atomic flag.
    class SkillFilesCrudInput(BaseModel):
        """Unified input for skill file CRUD operations."""
    
        operation: str = Field(description="Operation to perform: 'read', 'create', 'update', 'delete'")
        skill_name: str = Field(description="Name of the skill")
    
        # Single file operations
        file_path: Optional[str] = Field(
            default=None, description="Relative path to file (for single file operations)"
        )
        content: Optional[str] = Field(
            default=None, description="File content (for single create/update)"
        )
    
        # Bulk file operations
        files: Optional[List[FileSpec]] = Field(
            default=None, description="List of files for bulk create/update operations"
        )
        file_paths: Optional[List[str]] = Field(
            default=None, description="List of file paths for bulk read operations"
        )
        atomic: bool = Field(
            default=True, description="Atomic mode: rollback all on error (for bulk create)"
        )
  • `get_tool_definition()` method returning the `mcp.types.Tool` object for 'skill_files_crud' with name, detailed description, and inputSchema from `SkillFilesCrudInput.model_json_schema()`.
        @staticmethod
        def get_tool_definition() -> list[types.Tool]:
            """Get tool definition."""
            return [
                types.Tool(
                    name="skill_files_crud",
                    description="""Unified CRUD tool for skill file operations. Supports both single and bulk operations.
    
    IMPORTANT PATH NOTES:
    - All file paths are RELATIVE to the skill directory (e.g., 'main.py', 'scripts/utils.py')
    - NEVER use absolute paths (e.g., NOT '/Users/username/.skill-mcp/skills/my-skill/main.py')
    - To execute scripts, use the 'run_skill_script' tool, NOT external bash/shell tools
    
    **Operations:**
    - **read**: Read a file's content
    - **create**: Create one or more files (supports atomic mode for bulk)
    - **update**: Update one or more files
    - **delete**: Delete a file (SKILL.md is protected and cannot be deleted)
    
    **Single File Examples:**
    ```json
    // Read a file
    {"operation": "read", "skill_name": "my-skill", "file_path": "script.py"}
    
    // Create a single file
    {"operation": "create", "skill_name": "my-skill", "file_path": "new.py", "content": "print('hello')"}
    
    // Update a single file
    {"operation": "update", "skill_name": "my-skill", "file_path": "script.py", "content": "print('updated')"}
    
    // Delete a file
    {"operation": "delete", "skill_name": "my-skill", "file_path": "old.py"}
    ```
    
    **Bulk File Examples:**
    ```json
    // Read multiple files
    {
      "operation": "read",
      "skill_name": "my-skill",
      "file_paths": ["file1.py", "file2.py", "file3.py"]
    }
    
    // Create multiple files atomically (all-or-nothing)
    {
      "operation": "create",
      "skill_name": "my-skill",
      "files": [
        {"path": "src/main.py", "content": "# Main"},
        {"path": "src/utils.py", "content": "# Utils"},
        {"path": "README.md", "content": "# Docs"}
      ],
      "atomic": true
    }
    
    // Update multiple files
    {
      "operation": "update",
      "skill_name": "my-skill",
      "files": [
        {"path": "file1.py", "content": "new content 1"},
        {"path": "file2.py", "content": "new content 2"}
      ]
    }
    ```""",
                    inputSchema=SkillFilesCrudInput.model_json_schema(),
                )
            ]
  • MCP server `list_tools()` handler that extends the tools list with `SkillFilesCrud.get_tool_definition()`, registering the tool.
    @app.list_tools()  # type: ignore[misc]
    async def list_tools() -> list[types.Tool]:
        """List available tools."""
        tools = []
        tools.extend(SkillCrud.get_tool_definition())
        tools.extend(SkillFilesCrud.get_tool_definition())
        tools.extend(SkillEnvCrud.get_tool_definition())
        tools.extend(ScriptTools.get_script_tools())
        return tools
  • Dispatch branch in top-level `@app.call_tool()` handler that parses arguments into `SkillFilesCrudInput` and invokes `SkillFilesCrud.skill_files_crud()`.
    elif name == "skill_files_crud":
        files_input = SkillFilesCrudInput(**arguments)
        return await SkillFilesCrud.skill_files_crud(files_input)
Behavior4/5

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

With no annotations provided, the description carries full burden and does an excellent job disclosing behavioral traits. It explains atomic mode behavior ('all-or-nothing'), file path constraints (relative only), protection rules ('SKILL.md is protected'), and operational scope (single vs bulk). The only minor gap is lack of explicit mention about permissions or error handling specifics.

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?

The description is well-structured with clear sections (important notes, operations, examples) and every sentence adds value. While somewhat lengthy due to comprehensive examples, the information is front-loaded with critical constraints first, and the examples are necessary for understanding this multi-operation tool's usage patterns.

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

Completeness4/5

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

For a complex 7-parameter CRUD tool with no annotations and no output schema, the description provides excellent coverage of operations, constraints, and usage patterns. It explains what the tool does, how to use it, and important behavioral aspects. The only gap is lack of information about return values or error formats, but given the comprehensive operational guidance, this is a minor omission.

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 description coverage is 100%, so baseline is 3. The description adds significant value by clarifying parameter usage patterns through detailed examples showing how parameters combine for different operations (single vs bulk, atomic mode). It explains the relationship between operation type and which parameters to use, which goes beyond the schema's individual parameter descriptions.

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 this is a 'Unified CRUD tool for skill file operations' with specific verbs (read, create, update, delete) and resource (skill files). It distinguishes itself from sibling tools by explicitly mentioning 'run_skill_script' as the alternative for execution and not using external bash/shell 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?

The description provides explicit guidance on when to use this tool vs alternatives: 'To execute scripts, use the 'run_skill_script' tool, NOT external bash/shell tools.' It also specifies path requirements (relative vs absolute) and includes important operational constraints like SKILL.md protection and atomic mode for bulk operations.

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/fkesheh/skill-mcp'

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