generate-cli: auto-generate SKILL.md agent skill#3115
Conversation
generate-cli now produces a SKILL.md agent skill file next to the CLI script, documenting every tool's exact invocation syntax, parameter flags, and types. Agents can use the CLI immediately without discovery.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 48a38e172b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| f"{description} (JSON string)" if description else "JSON string" | ||
| ) | ||
| description = description.replace("|", "\\|") | ||
| rows.append(f"| {flag} | {type_label} | {is_required} | {description} |") |
There was a problem hiding this comment.
Escape union type labels in SKILL.md tables
When a parameter schema uses a union type (e.g., {"type": ["string", "null"]}), _schema_type_label returns a string containing " | ". In _tool_skill_section, that type_label is inserted directly into the markdown table while only the description is escaped. The unescaped pipe characters split the table into extra columns, producing malformed SKILL.md output for any tool with union-typed parameters. Escaping type_label the same way as description, or rendering union types without |, would avoid the formatting break.
Useful? React with 👍 / 👎.
WalkthroughThe CLI generator now produces a companion SKILL.md by default and will refuse to overwrite if either the CLI file or its companion SKILL.md already exists (unless forced). Generation of SKILL.md can be skipped with the Possibly related PRs
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
- Escape pipe chars in union type labels so markdown tables render - Boolean params omit <value> placeholder in example invocations - Quote YAML frontmatter values to handle special chars in names - Match cyclopts camelCase→snake_case in flag derivation - Use four-backtick fence for nested code block in docs
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/fastmcp/cli/generate.py (1)
525-533:_JSON_SCHEMA_TYPE_LABELSis an identity mapping — consider simplifying.Every key equals its value. You could replace
_JSON_SCHEMA_TYPE_LABELS.get(t, t)with justt(or a set membership check if the intent is validation). If you plan to diverge keys from values in the future (e.g.,"integer"→"int"), then keeping the dict as a forward-looking mapping is fine.
| invocation = f"uv run --with fastmcp python {cli_filename} call-tool {tool.name}" | ||
| if flag_parts: | ||
| invocation += f" {flag_parts}" |
There was a problem hiding this comment.
Tool names containing spaces or shell metacharacters will produce broken invocation examples.
tool.name is interpolated directly into the bash example without quoting. While MCP tool names are typically simple identifiers, the spec doesn't forbid special characters. Consider quoting the tool name in the invocation.
Proposed fix
- invocation = f"uv run --with fastmcp python {cli_filename} call-tool {tool.name}"
+ invocation = f"uv run --with fastmcp python {cli_filename} call-tool '{tool.name}'"
generate-clinow produces aSKILL.mdalongside the CLI script — a Claude Code agent skill that pre-computes every tool's exact invocation syntax. An agent reading the skill can immediately call tools without running--helpor experimenting with flag names.The generated skill includes typed parameter tables, example invocations, and utility commands:
Skill generation is on by default; pass
--no-skillto opt out. Both files are protected by the existing-foverwrite check.