[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6DAP3VP0BK0THG689RCCCNE":3,"skill-same:01M6DAP3VP0BK0THG689RCCCNE":82},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":26,"publishedAt":47,"linkOnly":48,"markdownContent":49,"markdownBody":50,"frontMatter":51,"refName":52,"commitSha":53,"skillDirectory":54,"forksCount":14,"repositoryHtmlUrl":55,"repositoryHomepageUrl":6,"ownerHtmlUrl":56,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":57,"install":58,"resources":71},"01M6DAP3VP0BK0THG689RCCCNE","tooluniverse-custom-tool",null,"Add custom local tools to ToolUniverse and use them alongside the 1000+ built-in tools. Use this skill when a user wants to: create their own tool for a private or custom API, add a local tool to their workspace, integrate an internal service with ToolUniverse, or use a custom tool via the MCP server or Python API. Covers both the JSON config approach (easiest, no Python needed) and the Python class approach (full control). Also covers how to verify tools loaded correctly and how to call them. Also covers the plugin package approach for reusable, shareable, pip-installable tool sets.","Prekzursil\u002Fagent-skills-toolchain","Prekzursil","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F54636077?v=4","01M6DACZ1PCQHD99SCR1YXG28B","Andrei Mihai Visalon","01M6DACZ670WZF535V3WYYSS4Z",0,"MIT","https:\u002F\u002Fgithub.com\u002FPrekzursil\u002Fagent-skills-toolchain\u002Fblob\u002Fmain\u002F.agents\u002Flibrary\u002Fskills\u002Ftooluniverse-custom-tool\u002FSKILL.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000010","后端与接口","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],"tooluniverse custom tool","tool","how","control","local","call","reusable","use","workspace","json","MCP","verify","api","server","package","create","plugin","config","mcp server","python","2026-11-10 10:12:30",false,"---\nname: tooluniverse-custom-tool\ndescription: >\n  Add custom local tools to ToolUniverse and use them alongside the 1000+ built-in tools.\n  Use this skill when a user wants to: create their own tool for a private or custom API,\n  add a local tool to their workspace, integrate an internal service with ToolUniverse,\n  or use a custom tool via the MCP server or Python API. Covers both the JSON config\n  approach (easiest, no Python needed) and the Python class approach (full control).\n  Also covers how to verify tools loaded correctly and how to call them.\n  Also covers the plugin package approach for reusable, shareable, pip-installable tool sets.\n---\n\n# Adding Custom Tools to ToolUniverse\n\n**When to create a custom tool:** Create one if you need to access an API that ToolUniverse\ndoesn't cover, or if you need a specialized data transformation that no existing tool provides.\nStart with the JSON config approach (simplest — no Python needed); escalate to a Python class\nonly if you need custom response parsing or stateful logic.\n\nThree ways to add tools — pick the one that fits your needs:\n\n| Approach | When to use |\n|---|---|\n| **JSON config** | REST API with standard request\u002Fresponse — no coding needed |\n| **Python class (workspace)** | Custom logic for local\u002Fprivate use only |\n| **Plugin package** | Reusable tools you want to share or install via pip |\n\n---\n\n## Option A — Workspace tools (local use)\n\nTools in `.tooluniverse\u002Ftools\u002F` are auto-discovered at startup. No installation needed.\n\n```bash\nmkdir -p .tooluniverse\u002Ftools\n```\n\n### JSON config\n\nCreate `.tooluniverse\u002Ftools\u002Fmy_tools.json`:\n\n```json\n[\n  {\n    \"name\": \"MyAPI_search\",\n    \"description\": \"Search my internal database. Returns matching records with id, title, and score.\",\n    \"type\": \"BaseRESTTool\",\n    \"fields\": {\n      \"endpoint\": \"https:\u002F\u002Fmy-api.example.com\u002Fsearch\"\n    },\n    \"parameter\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"q\": {\n          \"type\": \"string\",\n          \"description\": \"Search query\"\n        },\n        \"limit\": {\n          \"type\": [\"integer\", \"null\"],\n          \"description\": \"Max results to return (default 10)\"\n        }\n      },\n      \"required\": [\"q\"]\n    }\n  }\n]\n```\n\nOne JSON file can define multiple tools — just add more objects to the array.\n\nFor the full JSON field reference, see [references\u002Fjson-tool.md](references\u002Fjson-tool.md).\n\n### Python class\n\nCreate `.tooluniverse\u002Ftools\u002Fmy_tool.py`:\n\n```python\nfrom tooluniverse.tool_registry import register_tool\n\n@register_tool\nclass MyAPI_search:\n    name = \"MyAPI_search\"\n    description = \"Search my internal database. Returns matching records with id, title, and score.\"\n    input_schema = {\n        \"type\": \"object\",\n        \"properties\": {\n            \"q\": {\"type\": \"string\", \"description\": \"Search query\"},\n            \"limit\": {\"type\": \"integer\", \"description\": \"Max results (default 10)\"}\n        },\n        \"required\": [\"q\"]\n    }\n\n    def run(self, q: str, limit: int = 10) -> dict:\n        import requests\n        resp = requests.get(\n            \"https:\u002F\u002Fmy-api.example.com\u002Fsearch\",\n            params={\"q\": q, \"limit\": limit},\n            timeout=30,\n        )\n        resp.raise_for_status()\n        return {\"status\": \"success\", \"data\": resp.json()}\n```\n\nNote: workspace Python tools use `run(self, **named_params)` — arguments are unpacked as keyword\narguments matching the `input_schema` properties.\n\nFor the full Python class reference, see [references\u002Fpython-tool.md](references\u002Fpython-tool.md).\n\n### Test workspace tools\n\n```bash\n# Uses test_examples from the tool's JSON config — zero config needed\ntu test MyAPI_search\n\n# Single ad-hoc call\ntu test MyAPI_search '{\"q\": \"test\"}'\n\n# Full config with assertions\ntu test --config my_tool_tests.json\n```\n\n`tu test` automatically runs these checks on every call:\n- Result is not None or empty\n- `return_schema` validation — validates `result[\"data\"]` against the JSON Schema defined in `return_schema` (if present)\n- `expect_status` and `expect_keys` — only if set in the config file\n\n**Gotchas:** (1) `tu test` does NOT verify non-empty results — `[]` passes schema validation. Use test_examples args that return real data. (2) Verify test_examples manually first with urllib (not curl) to confirm the API returns JSON, not HTML. Use 2-4 broad keywords.\n\nAdd `test_examples` and `return_schema` to JSON config for best coverage. `tu test` validates `result[\"data\"]` against `return_schema` (match `\"type\": \"array\"` or `\"type\": \"object\"` to your data shape).\n\nOptional `my_tool_tests.json` for extra assertions (`expect_status`, `expect_keys`).\n\n### Use with MCP server\n\nTools in `.tooluniverse\u002Ftools\u002F` are auto-available via `tu serve`. Workspace priority: `--workspace` flag → `TOOLUNIVERSE_HOME` env → `.\u002F.tooluniverse\u002F` → `~\u002F.tooluniverse\u002F`.\n\nTo use a different tools directory, add `sources: [.\u002Fmy-custom-tools\u002F]` in `.tooluniverse\u002Fprofile.yaml` and start with `tooluniverse --load .tooluniverse\u002Fprofile.yaml`.\n\n---\n\n## Option B — Plugin package (shareable, pip-installable)\n\nUse this when you want to distribute tools as a reusable Python package that other users can\ninstall with `pip install`. The plugin package has the same directory layout as a workspace, plus a\n`pyproject.toml` that declares the entry point.\n\n### Package layout\n\n```\nmy_project_root\u002F           # directory containing pyproject.toml\n    pyproject.toml\n    my_tools_package\u002F      # importable Python package (matches entry-point value)\n        __init__.py        # minimal — one-line docstring, no registration code\n        my_api_tool.py     # tool class(es) with @register_tool\n        data\u002F\n            my_api_tools.json  # JSON tool configs (type must match registered class name)\n        profile.yaml       # optional: name, description, required_env\n```\n\nJSON config files are discovered from both `data\u002F` and the package root directory. The convention is `data\u002F`.\n\n### `pyproject.toml` entry point\n\n```toml\n[project.entry-points.\"tooluniverse.plugins\"]\nmy-tools = \"my_tools_package\"\n```\n\nThe value (`my_tools_package`) must be the importable Python package name.\n\n### Python class in a plugin package\n\nPlugin package tools use `BaseTool` and receive all arguments as a single `Dict`:\n\n```python\nimport requests\nfrom typing import Dict, Any\nfrom tooluniverse.base_tool import BaseTool\nfrom tooluniverse.tool_registry import register_tool\n\n@register_tool(\"MyAPITool\")\nclass MyAPITool(BaseTool):\n    \"\"\"Tool description here.\"\"\"\n\n    def __init__(self, tool_config: Dict[str, Any]):\n        super().__init__(tool_config)\n        self.timeout = tool_config.get(\"timeout\", 30)\n        fields = tool_config.get(\"fields\", {})\n        self.operation = fields.get(\"operation\", \"search\")\n\n    def run(self, arguments: Dict[str, Any]) -> Dict[str, Any]:\n        query = arguments.get(\"query\", \"\")\n        if not query:\n            return {\"error\": \"query parameter is required\"}\n        try:\n            resp = requests.get(\n                \"https:\u002F\u002Fmy-api.example.com\u002Fsearch\",\n                params={\"q\": query},\n                timeout=self.timeout,\n            )\n            resp.raise_for_status()\n            return {\"status\": \"success\", \"data\": resp.json()}\n        except requests.exceptions.RequestException as e:\n            return {\"error\": str(e)}\n```\n\nKey differences from the workspace pattern:\n- Inherit from `BaseTool` (from `tooluniverse.base_tool`)\n- `@register_tool(\"ClassName\")` takes the class name as a string argument\n- `run(self, arguments: Dict)` receives all arguments in a single dict — extract them with `.get()`\n- `__init__` receives `tool_config` dict; call `super().__init__(tool_config)` first\n\n### JSON config in a plugin package\n\nPlace configs in `data\u002Fmy_api_tools.json`. The `\"type\"` field must match the string passed to\n`@register_tool(...)`:\n\n```json\n[\n  {\n    \"name\": \"MyAPI_search\",\n    \"description\": \"Search my API. Returns matching records.\",\n    \"type\": \"MyAPITool\",\n    \"fields\": { \"operation\": \"search\" },\n    \"parameter\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"query\": { \"type\": \"string\", \"description\": \"Search query\" },\n        \"limit\": { \"type\": [\"integer\", \"null\"], \"description\": \"Max results\" }\n      },\n      \"required\": [\"query\"]\n    }\n  }\n]\n```\n\n### `__init__.py`\n\nKeep minimal — just a docstring. The plugin system auto-imports all `.py` files via `_discover_entry_point_plugins()`, so `@register_tool` decorators fire automatically. Optional: add `from . import my_api_tool` for IDE support (idempotent). Do NOT add registration logic or JSON loading here.\n\n### Install and verify\n\n```bash\npip install -e \u002Fpath\u002Fto\u002Fmy_project_root\ncd \u002Fpath\u002Fto\u002Fmy_project_root   # MUST run from plugin repo directory\ntu test MyAPI_search '{\"query\": \"test\"}'\n```\n\nMust `pip install -e` first. Run `tu test` from plugin repo dir (workspace auto-detection needs `.tooluniverse\u002F`). Add `test_examples` to JSON config for zero-config testing. Use `tu info MyAPI_search` to confirm the tool loaded.\n\n---\n\n## Offline \u002F pure-computation tools\n\nCalculator tools (no HTTP) follow the plugin-package pattern but skip the HTTP layer. Key design patterns:\n\n- **Preset lookup tables**: Define `Dict[str, float]` at module level. Resolution priority: explicit value → preset name → default. Include presets in `metadata` for discoverability.\n- **Bidirectional equations**: Expose as separate `operation` values in a single tool. Use `\"fields\": {\"operation\": \"default_op\"}` in JSON config.\n- **Physical constants**: Define at module level (`_MU0 = 4*pi*1e-7`, etc.). Material-specific values as named dicts.\n- **Multi-output**: Return all related results in `data` (e.g., temperature + headroom + pass\u002Ffail) rather than forcing multiple calls.\n\nFor complete patterns, see [references\u002Fpython-tool.md](references\u002Fpython-tool.md).\n","# Adding Custom Tools to ToolUniverse\n\n**When to create a custom tool:** Create one if you need to access an API that ToolUniverse\ndoesn't cover, or if you need a specialized data transformation that no existing tool provides.\nStart with the JSON config approach (simplest — no Python needed); escalate to a Python class\nonly if you need custom response parsing or stateful logic.\n\nThree ways to add tools — pick the one that fits your needs:\n\n| Approach | When to use |\n|---|---|\n| **JSON config** | REST API with standard request\u002Fresponse — no coding needed |\n| **Python class (workspace)** | Custom logic for local\u002Fprivate use only |\n| **Plugin package** | Reusable tools you want to share or install via pip |\n\n---\n\n## Option A — Workspace tools (local use)\n\nTools in `.tooluniverse\u002Ftools\u002F` are auto-discovered at startup. No installation needed.\n\n```bash\nmkdir -p .tooluniverse\u002Ftools\n```\n\n### JSON config\n\nCreate `.tooluniverse\u002Ftools\u002Fmy_tools.json`:\n\n```json\n[\n  {\n    \"name\": \"MyAPI_search\",\n    \"description\": \"Search my internal database. Returns matching records with id, title, and score.\",\n    \"type\": \"BaseRESTTool\",\n    \"fields\": {\n      \"endpoint\": \"https:\u002F\u002Fmy-api.example.com\u002Fsearch\"\n    },\n    \"parameter\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"q\": {\n          \"type\": \"string\",\n          \"description\": \"Search query\"\n        },\n        \"limit\": {\n          \"type\": [\"integer\", \"null\"],\n          \"description\": \"Max results to return (default 10)\"\n        }\n      },\n      \"required\": [\"q\"]\n    }\n  }\n]\n```\n\nOne JSON file can define multiple tools — just add more objects to the array.\n\nFor the full JSON field reference, see [references\u002Fjson-tool.md](references\u002Fjson-tool.md).\n\n### Python class\n\nCreate `.tooluniverse\u002Ftools\u002Fmy_tool.py`:\n\n```python\nfrom tooluniverse.tool_registry import register_tool\n\n@register_tool\nclass MyAPI_search:\n    name = \"MyAPI_search\"\n    description = \"Search my internal database. Returns matching records with id, title, and score.\"\n    input_schema = {\n        \"type\": \"object\",\n        \"properties\": {\n            \"q\": {\"type\": \"string\", \"description\": \"Search query\"},\n            \"limit\": {\"type\": \"integer\", \"description\": \"Max results (default 10)\"}\n        },\n        \"required\": [\"q\"]\n    }\n\n    def run(self, q: str, limit: int = 10) -> dict:\n        import requests\n        resp = requests.get(\n            \"https:\u002F\u002Fmy-api.example.com\u002Fsearch\",\n            params={\"q\": q, \"limit\": limit},\n            timeout=30,\n        )\n        resp.raise_for_status()\n        return {\"status\": \"success\", \"data\": resp.json()}\n```\n\nNote: workspace Python tools use `run(self, **named_params)` — arguments are unpacked as keyword\narguments matching the `input_schema` properties.\n\nFor the full Python class reference, see [references\u002Fpython-tool.md](references\u002Fpython-tool.md).\n\n### Test workspace tools\n\n```bash\n# Uses test_examples from the tool's JSON config — zero config needed\ntu test MyAPI_search\n\n# Single ad-hoc call\ntu test MyAPI_search '{\"q\": \"test\"}'\n\n# Full config with assertions\ntu test --config my_tool_tests.json\n```\n\n`tu test` automatically runs these checks on every call:\n- Result is not None or empty\n- `return_schema` validation — validates `result[\"data\"]` against the JSON Schema defined in `return_schema` (if present)\n- `expect_status` and `expect_keys` — only if set in the config file\n\n**Gotchas:** (1) `tu test` does NOT verify non-empty results — `[]` passes schema validation. Use test_examples args that return real data. (2) Verify test_examples manually first with urllib (not curl) to confirm the API returns JSON, not HTML. Use 2-4 broad keywords.\n\nAdd `test_examples` and `return_schema` to JSON config for best coverage. `tu test` validates `result[\"data\"]` against `return_schema` (match `\"type\": \"array\"` or `\"type\": \"object\"` to your data shape).\n\nOptional `my_tool_tests.json` for extra assertions (`expect_status`, `expect_keys`).\n\n### Use with MCP server\n\nTools in `.tooluniverse\u002Ftools\u002F` are auto-available via `tu serve`. Workspace priority: `--workspace` flag → `TOOLUNIVERSE_HOME` env → `.\u002F.tooluniverse\u002F` → `~\u002F.tooluniverse\u002F`.\n\nTo use a different tools directory, add `sources: [.\u002Fmy-custom-tools\u002F]` in `.tooluniverse\u002Fprofile.yaml` and start with `tooluniverse --load .tooluniverse\u002Fprofile.yaml`.\n\n---\n\n## Option B — Plugin package (shareable, pip-installable)\n\nUse this when you want to distribute tools as a reusable Python package that other users can\ninstall with `pip install`. The plugin package has the same directory layout as a workspace, plus a\n`pyproject.toml` that declares the entry point.\n\n### Package layout\n\n```\nmy_project_root\u002F           # directory containing pyproject.toml\n    pyproject.toml\n    my_tools_package\u002F      # importable Python package (matches entry-point value)\n        __init__.py        # minimal — one-line docstring, no registration code\n        my_api_tool.py     # tool class(es) with @register_tool\n        data\u002F\n            my_api_tools.json  # JSON tool configs (type must match registered class name)\n        profile.yaml       # optional: name, description, required_env\n```\n\nJSON config files are discovered from both `data\u002F` and the package root directory. The convention is `data\u002F`.\n\n### `pyproject.toml` entry point\n\n```toml\n[project.entry-points.\"tooluniverse.plugins\"]\nmy-tools = \"my_tools_package\"\n```\n\nThe value (`my_tools_package`) must be the importable Python package name.\n\n### Python class in a plugin package\n\nPlugin package tools use `BaseTool` and receive all arguments as a single `Dict`:\n\n```python\nimport requests\nfrom typing import Dict, Any\nfrom tooluniverse.base_tool import BaseTool\nfrom tooluniverse.tool_registry import register_tool\n\n@register_tool(\"MyAPITool\")\nclass MyAPITool(BaseTool):\n    \"\"\"Tool description here.\"\"\"\n\n    def __init__(self, tool_config: Dict[str, Any]):\n        super().__init__(tool_config)\n        self.timeout = tool_config.get(\"timeout\", 30)\n        fields = tool_config.get(\"fields\", {})\n        self.operation = fields.get(\"operation\", \"search\")\n\n    def run(self, arguments: Dict[str, Any]) -> Dict[str, Any]:\n        query = arguments.get(\"query\", \"\")\n        if not query:\n            return {\"error\": \"query parameter is required\"}\n        try:\n            resp = requests.get(\n                \"https:\u002F\u002Fmy-api.example.com\u002Fsearch\",\n                params={\"q\": query},\n                timeout=self.timeout,\n            )\n            resp.raise_for_status()\n            return {\"status\": \"success\", \"data\": resp.json()}\n        except requests.exceptions.RequestException as e:\n            return {\"error\": str(e)}\n```\n\nKey differences from the workspace pattern:\n- Inherit from `BaseTool` (from `tooluniverse.base_tool`)\n- `@register_tool(\"ClassName\")` takes the class name as a string argument\n- `run(self, arguments: Dict)` receives all arguments in a single dict — extract them with `.get()`\n- `__init__` receives `tool_config` dict; call `super().__init__(tool_config)` first\n\n### JSON config in a plugin package\n\nPlace configs in `data\u002Fmy_api_tools.json`. The `\"type\"` field must match the string passed to\n`@register_tool(...)`:\n\n```json\n[\n  {\n    \"name\": \"MyAPI_search\",\n    \"description\": \"Search my API. Returns matching records.\",\n    \"type\": \"MyAPITool\",\n    \"fields\": { \"operation\": \"search\" },\n    \"parameter\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"query\": { \"type\": \"string\", \"description\": \"Search query\" },\n        \"limit\": { \"type\": [\"integer\", \"null\"], \"description\": \"Max results\" }\n      },\n      \"required\": [\"query\"]\n    }\n  }\n]\n```\n\n### `__init__.py`\n\nKeep minimal — just a docstring. The plugin system auto-imports all `.py` files via `_discover_entry_point_plugins()`, so `@register_tool` decorators fire automatically. Optional: add `from . import my_api_tool` for IDE support (idempotent). Do NOT add registration logic or JSON loading here.\n\n### Install and verify\n\n```bash\npip install -e \u002Fpath\u002Fto\u002Fmy_project_root\ncd \u002Fpath\u002Fto\u002Fmy_project_root   # MUST run from plugin repo directory\ntu test MyAPI_search '{\"query\": \"test\"}'\n```\n\nMust `pip install -e` first. Run `tu test` from plugin repo dir (workspace auto-detection needs `.tooluniverse\u002F`). Add `test_examples` to JSON config for zero-config testing. Use `tu info MyAPI_search` to confirm the tool loaded.\n\n---\n\n## Offline \u002F pure-computation tools\n\nCalculator tools (no HTTP) follow the plugin-package pattern but skip the HTTP layer. Key design patterns:\n\n- **Preset lookup tables**: Define `Dict[str, float]` at module level. Resolution priority: explicit value → preset name → default. Include presets in `metadata` for discoverability.\n- **Bidirectional equations**: Expose as separate `operation` values in a single tool. Use `\"fields\": {\"operation\": \"default_op\"}` in JSON config.\n- **Physical constants**: Define at module level (`_MU0 = 4*pi*1e-7`, etc.). Material-specific values as named dicts.\n- **Multi-output**: Return all related results in `data` (e.g., temperature + headroom + pass\u002Ffail) rather than forcing multiple calls.\n\nFor complete patterns, see [references\u002Fpython-tool.md](references\u002Fpython-tool.md).\n",{"name":5,"description":7},"main","a298c929b6cbd662e1fce54302ce520d5ceea1a5",".agents\u002Flibrary\u002Fskills\u002Ftooluniverse-custom-tool","https:\u002F\u002Fgithub.com\u002FPrekzursil\u002Fagent-skills-toolchain","https:\u002F\u002Fgithub.com\u002FPrekzursil","2026-11-02 14:30:57",{"source":8,"skillName":5,"commands":59,"prompt":69,"zipAvailable":70},[60,63,66],{"tool":61,"command":62},"npx","npx skills add Prekzursil\u002Fagent-skills-toolchain --skill tooluniverse-custom-tool",{"tool":64,"command":65},"bunx","bunx skills add Prekzursil\u002Fagent-skills-toolchain --skill tooluniverse-custom-tool",{"tool":67,"command":68},"pnpm","pnpm dlx skills add Prekzursil\u002Fagent-skills-toolchain --skill tooluniverse-custom-tool","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FPrekzursil\u002Fagent-skills-toolchain\u002Fblob\u002Fmain\u002F.agents\u002Flibrary\u002Fskills\u002Ftooluniverse-custom-tool\u002FSKILL.md",true,[72,78],{"path":73,"resourceType":74,"resourceTypeDesc":75,"sizeBytes":76,"sourceHtmlUrl":77},"references\u002Fjson-tool.md","REFERENCE","参考文档",9227,"https:\u002F\u002Fgithub.com\u002FPrekzursil\u002Fagent-skills-toolchain\u002Fblob\u002Fmain\u002F.agents\u002Flibrary\u002Fskills\u002Ftooluniverse-custom-tool\u002Freferences\u002Fjson-tool.md",{"path":79,"resourceType":74,"resourceTypeDesc":75,"sizeBytes":80,"sourceHtmlUrl":81},"references\u002Fpython-tool.md",22032,"https:\u002F\u002Fgithub.com\u002FPrekzursil\u002Fagent-skills-toolchain\u002Fblob\u002Fmain\u002F.agents\u002Flibrary\u002Fskills\u002Ftooluniverse-custom-tool\u002Freferences\u002Fpython-tool.md",[83,104,127,154,168,184],{"skillNo":84,"name":85,"nameZh":6,"description":86,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":87,"categories":88,"keywords":89,"publishedAt":47},"01M6DF7D7478R55P46REYH4QAC","clarify-requirements","Resolve genuine pre-execution ambiguity by scanning repo context, generating 1-6 grounded options, and asking 1-3 focused questions via AskUserQuestion. NOT for mid-task use (injection risk); NOT when the goal is already unambiguous; use to disambiguate vague prompts before any file edits.","https:\u002F\u002Fgithub.com\u002FPrekzursil\u002Fagent-skills-toolchain\u002Fblob\u002Fmain\u002Ftools\u002Fworkspace-hooks\u002Fskills\u002Fclarify-requirements\u002FSKILL.md",[],[90,91,92,93,94,95,96,97,98,34,99,100,101,102,103],"clarify requirements","clarify","requirements","risk","options","task","prompts","goal","scanning","context","repo","injection","execution","file",{"skillNo":105,"name":106,"nameZh":6,"description":107,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":108,"categories":109,"keywords":111,"publishedAt":47},"01M6DF79CA4BHJS66J8EZDBPWJ","openmm-md","Run FREE, open-source, Windows-native GPU molecular dynamics via the openmm-md MCP (OpenMM + CUDA on the local NVIDIA GPU). Use for protein \u002F protein-ligand MD when you want a free stack or are on Windows without a Schrodinger license. Covers the full workflow (prepare, solvate, minimize, equilibrate, production, analyze, mmgbsa) AND an honest decision guide vs Schrodinger Desmond, including how to run Desmond legitimately on Linux or a cloud GPU with a real license. This is a deliberately LESSER free alternative and does NOT replace the schrodinger MCP tools. Do NOT use it to pick a free tool when a validated FEP+, WaterMap, IFD-MD, or Prime MM-GBSA result is actually required.","https:\u002F\u002Fgithub.com\u002FPrekzursil\u002Fagent-skills-toolchain\u002Fblob\u002Fmain\u002Ftools\u002Fmcp\u002Fopenmm-md-mcp\u002Fskill\u002Fopenmm-md\u002FSKILL.md",[110],{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},[112,29,113,114,115,116,28,117,118,119,120,121,122,123,34,124,125,31,126,37],"openmm md","decision","pick","linux","analyze","stack","open","NVIDIA","gpu","license","workflow","windows","free","molecular dynamics","do",{"skillNo":128,"name":129,"nameZh":6,"description":130,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":131,"categories":132,"keywords":139,"publishedAt":47},"01M6DF76C1MG85VEWP8VZCBNMN","visual-review","Take screenshots of web pages and UI using Playwright for visual review and iteration","https:\u002F\u002Fgithub.com\u002FPrekzursil\u002Fagent-skills-toolchain\u002Fblob\u002Fmain\u002Ftools\u002Feditor\u002Fmetaswarm\u002Fskills\u002Fvisual-review\u002FSKILL.md",[133,136],{"categoryNo":134,"categoryName":135,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000003","演示文稿",{"categoryNo":137,"categoryName":138,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量",[140,141,142,143,144,145,146,147,148,149,29,150,151,152,153],"review","visual","visual review","pages","web","false","iteration","take","check","slides","ui","screenshot","playwright","screenshots",{"skillNo":155,"name":156,"nameZh":6,"description":157,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":158,"categories":159,"keywords":160,"publishedAt":47},"01M6DF73AQVCBZKEN0YXEX9FXP","status","Diagnostic status report — shows metaswarm installation state, project setup, and potential issues","https:\u002F\u002Fgithub.com\u002FPrekzursil\u002Fagent-skills-toolchain\u002Fblob\u002Fmain\u002Ftools\u002Feditor\u002Fmetaswarm\u002Fskills\u002Fstatus\u002FSKILL.md",[],[156,161,162,163,164,165,166,167],"setup","report","project","installation","project setup","issues","state",{"skillNo":169,"name":170,"nameZh":6,"description":171,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":172,"categories":173,"keywords":175,"publishedAt":47},"01M6DF6X6C2XB0P6GX76P7TTYV","start","Use when starting work on any task, when the user mentions metaswarm, or when the user wants to begin tracked development work","https:\u002F\u002Fgithub.com\u002FPrekzursil\u002Fagent-skills-toolchain\u002Fblob\u002Fmain\u002Ftools\u002Feditor\u002Fmetaswarm\u002Fskills\u002Fstart\u002FSKILL.md",[174],{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},[170,176,95,177,178,179,34,180,181,182,183],"start issue","issue","ready","work on issue","user","work","work on","development",{"skillNo":185,"name":161,"nameZh":6,"description":186,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":187,"categories":188,"keywords":189,"publishedAt":47},"01M6DF6QMJ9AJKFKHHKRT005PQ","Interactive project setup — detects your project, configures metaswarm, writes project-local files","https:\u002F\u002Fgithub.com\u002FPrekzursil\u002Fagent-skills-toolchain\u002Fblob\u002Fmain\u002Ftools\u002Feditor\u002Fmetaswarm\u002Fskills\u002Fsetup\u002FSKILL.md",[],[161,163,31,190,165,191],"files","interactive"]