load_skill_metadata
Retrieves metadata for all available skills to identify and access capabilities within the AgentSkills MCP server for financial research tasks.
Instructions
Load metadata (name and description) for all available skills from the skills directory.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- The main handler function that executes the load_skill_metadata tool. It scans the skills directory for SKILL.md files, parses YAML frontmatter to extract name and description, builds a formatted string listing all available skills, and sets it as the tool output.async def async_execute(self): """Execute the load skill metadata operation. Scans the skills directory recursively for all SKILL.md files, extracts their metadata from YAML frontmatter, and builds a dictionary mapping skill names to their metadata (description and directory path). The method: 1. Gets the skills directory path from the context 2. Recursively searches for all SKILL.md files 3. Parses each file's frontmatter to extract metadata 4. Builds a dictionary with skill names as keys 5. Sets the output with the complete metadata dictionary Returns: None: The result is set via `self.set_output()` with a dictionary in the format: { "skill_name_1": { "description": "Description of skill 1", "skill_dir": "/path/to/skill1" }, "skill_name_2": { "description": "Description of skill 2", "skill_dir": "/path/to/skill2" }, ... } Note: Only skills with valid metadata (both name and description) are included in the result. Invalid or missing metadata is logged as a warning but does not stop the process. """ # Get the skills directory path from context skill_dir = Path(C.service_config.metadata["skill_dir"]) logger.info(f"🔧 Tool called: load_skill_metadata(path={skill_dir})") # Recursively find all SKILL.md files in the skills directory skill_files = list(skill_dir.rglob("SKILL.md")) assert skill_files, "No SKILL.md files found in skills directory" # Build dictionary mapping skill names to their metadata # skill_metadata_dict = {} skill_num = 0 skill_metadata_context = "Available skills (each line is \"- <skill_name>: <skill_description>\"):" for skill_file in skill_files: # Read the SKILL.md file content content = skill_file.read_text(encoding="utf-8") # Parse metadata from the file's frontmatter metadata = await self.parse_skill_metadata(content, str(skill_file)) if metadata: # Get the parent directory of the SKILL.md file as the skill directory skill_dir = skill_file.parent.as_posix() # Store metadata with skill name as key name = metadata["name"] description = metadata["description"] # skill_metadata_dict[name] = { # "description": description, # "skill_dir": skill_dir, # } skill_num += 1 skill_metadata_context += f"\n- {name}: {description}" logger.info(f"✅ Loaded skill {name} metadata skill_dir={skill_dir}") logger.info(f"✅ Loaded {skill_num} skill metadata entries") # Set the output with the complete metadata dictionary self.set_output(skill_metadata_context)
- Defines the tool schema including name 'load_skill_metadata', description, and empty input schema (no parameters required).def build_tool_call(self) -> ToolCall: """Build the tool call definition for load_skill_metadata. Creates and returns a ToolCall object that defines the load_skill_metadata tool. This tool requires no input parameters and will scan the skills directory to load all available skill metadata. Returns: ToolCall: A ToolCall object defining the load_skill_metadata tool with the following properties: - name: "load_skill_metadata" - description: Description of what the tool does - input_schema: Empty dict (no input parameters required) """ tool_params = { "name": "load_skill_metadata", "description": "Load metadata (name and description) for all available skills from the skills directory.", "input_schema": {}, } return ToolCall(**tool_params)
- agentskills_mcp/core/tools/load_skill_metadata_op.py:18-41 (registration)Registers the LoadSkillMetadataOp class as an operation using the @C.register_op() decorator, making the 'load_skill_metadata' tool available in the MCP context.@C.register_op() class LoadSkillMetadataOp(BaseAsyncToolOp): """Operation for loading metadata from all available skills. This tool scans the skills directory recursively for SKILL.md files and extracts their metadata (name and description) from YAML frontmatter. The metadata is returned as a dictionary where keys are skill names and values contain the description and skill directory path. Returns: dict: A dictionary mapping skill names to their metadata. Each entry has the format: { "skill_name": { "description": "Skill description text", "skill_dir": "/path/to/skill/directory" } } Note: The skills directory path is obtained from `self.context.skill_dir`. Only SKILL.md files with valid YAML frontmatter containing both 'name' and 'description' fields will be included in the results. """
- Helper function to parse YAML frontmatter from SKILL.md files, extracting 'name' and 'description' fields.@staticmethod async def parse_skill_metadata(content: str, path: str) -> dict[str, str] | None: """Extract skill metadata (name and description) from SKILL.md content. Parses YAML frontmatter from SKILL.md files to extract the skill name and description. The frontmatter should be in the format: ``` --- name: skill_name description: skill description --- ``` The method splits the content by "---" delimiters to extract the frontmatter section, then parses each line to find the 'name' and 'description' fields. Values can be quoted or unquoted. Args: content: The full content of the SKILL.md file as a string. path: The file path (used for logging purposes when parsing fails). Returns: dict[str, str] | None: A dictionary with 'name' and 'description' keys containing the extracted values, or None if: - No YAML frontmatter is found (less than 3 parts after splitting) - The 'name' field is missing or empty - The 'description' field is missing or empty """ # Split content by YAML frontmatter delimiters (---) # Expected format: "---\n...frontmatter...\n---\n...content..." # This should result in at least 3 parts: [before, frontmatter, after] parts = content.split("---") if len(parts) < 3: logger.warning(f"No YAML frontmatter found in skill from {path}") return None # Extract the frontmatter section (between the first two "---" delimiters) frontmatter_text = parts[1].strip() name = None description = None # Parse each line in the frontmatter to find name and description for line in frontmatter_text.split("\n"): line = line.strip() if line.startswith("name:"): # Extract value after "name:", remove quotes if present name = line.split(":", 1)[1].strip().strip("\"'") elif line.startswith("description:"): # Extract value after "description:", remove quotes if present description = line.split(":", 1)[1].strip().strip("\"'") # Validate that both required fields are present if not name or not description: logger.warning(f"Missing name or description in skill from {path}") return None return { "name": name, "description": description, }