Spaces:
Running
Running
| """ | |
| Skill Forge — a Gradio app + MCP server for authoring Agent Skills. | |
| Tabs: validate a SKILL.md, score its `description` for trigger reliability, and | |
| scaffold a new skill. The same three functions are exposed as MCP tools | |
| (`skill_validate`, `skill_lint_description`, `skill_scaffold`) so an agent can | |
| call them while it writes skills for itself. | |
| Run locally: python app.py (UI on :7860, MCP at /gradio_api/mcp/sse) | |
| """ | |
| import gradio as gr | |
| from skillforge import validate_skill, lint_description, scaffold_skill, package_skill | |
| EXAMPLE = """--- | |
| name: changelog-writer | |
| description: Drafts a release changelog from merged PRs. Use when the user asks to \ | |
| "write the changelog", "summarize what shipped", or prep release notes for a tag. | |
| --- | |
| # Changelog Writer | |
| ## When to use this skill | |
| - The user is cutting a release and wants notes grouped by type. | |
| ## Instructions | |
| 1. Collect merged PRs since the last tag. | |
| 2. Group as Features / Fixes / Internal and write one line each. | |
| """ | |
| def skill_validate(skill_md: str) -> str: | |
| """Validate a SKILL.md against the Agent Skill format. | |
| Args: | |
| skill_md: Full text of a SKILL.md file (YAML frontmatter + Markdown body). | |
| Returns: | |
| A Markdown report listing errors, warnings, and info. | |
| """ | |
| return validate_skill(skill_md).as_markdown() | |
| def skill_lint_description(description: str) -> str: | |
| """Score a skill `description` for how reliably an agent will trigger on it. | |
| Args: | |
| description: The frontmatter `description` string on its own. | |
| Returns: | |
| A Markdown report ending with 'Trigger score: N/100'. | |
| """ | |
| return lint_description(description).as_markdown() | |
| def skill_scaffold(name: str, description: str, when_to_use: str = "") -> str: | |
| """Generate a ready-to-edit SKILL.md for a new Agent Skill. | |
| Args: | |
| name: kebab-case skill name, e.g. 'pdf-form-filler'. | |
| description: What the skill does and when to use it. | |
| when_to_use: Optional extra trigger examples. | |
| Returns: | |
| The full text of a SKILL.md file. | |
| """ | |
| return scaffold_skill(name, description, when_to_use) | |
| def _package(skill_md: str): | |
| data = package_skill(skill_md) | |
| path = "skill.zip" | |
| with open(path, "wb") as f: | |
| f.write(data) | |
| return path | |
| with gr.Blocks(title="Skill Forge") as demo: | |
| gr.Markdown( | |
| "# 🛠️ Skill Forge\n" | |
| "Validate, lint, and scaffold **Agent Skills** (`SKILL.md`). " | |
| "Also an MCP server — point your agent at `/gradio_api/mcp/sse`." | |
| ) | |
| with gr.Tab("Validate"): | |
| md_in = gr.Code(value=EXAMPLE, language="yaml", label="SKILL.md", lines=20) | |
| with gr.Row(): | |
| v_btn = gr.Button("Validate", variant="primary") | |
| z_btn = gr.Button("Package as .zip") | |
| v_out = gr.Markdown() | |
| z_out = gr.File(label="Packaged skill", visible=True) | |
| v_btn.click(skill_validate, md_in, v_out, api_name="skill_validate") | |
| z_btn.click(_package, md_in, z_out) | |
| with gr.Tab("Lint description"): | |
| d_in = gr.Textbox( | |
| label="Frontmatter `description`", lines=4, | |
| value=('Drafts a release changelog from merged PRs. Use when the user ' | |
| 'asks to "write the changelog" or prep release notes.')) | |
| d_btn = gr.Button("Score it", variant="primary") | |
| d_out = gr.Markdown() | |
| d_btn.click(skill_lint_description, d_in, d_out, | |
| api_name="skill_lint_description") | |
| with gr.Tab("Scaffold"): | |
| s_name = gr.Textbox(label="name (kebab-case)", value="terraform-plan-reviewer") | |
| s_desc = gr.Textbox(label="description", lines=3, | |
| value="Reviews a Terraform plan and summarizes drift and risk.") | |
| s_when = gr.Textbox(label="when to use (optional)", | |
| value='the user runs "terraform plan" and wants a risk summary') | |
| s_btn = gr.Button("Generate SKILL.md", variant="primary") | |
| s_out = gr.Code(language="yaml", label="SKILL.md") | |
| s_btn.click(skill_scaffold, [s_name, s_desc, s_when], s_out, | |
| api_name="skill_scaffold") | |
| gr.Markdown( | |
| "---\nRules checked: frontmatter parses as YAML · `name` kebab-case ≤64 · " | |
| "`description` present ≤1024 with a trigger cue · non-empty structured body · " | |
| "relative bundled-file links. MIT licensed." | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch(mcp_server=True) | |