[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6C542VFA8PSB6XSNMA1XXSN":3,"skill-same:01M6C542VFA8PSB6XSNMA1XXSN":68},{"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":31,"publishedAt":41,"linkOnly":42,"markdownContent":43,"markdownBody":44,"frontMatter":45,"refName":46,"commitSha":47,"skillDirectory":48,"forksCount":49,"repositoryHtmlUrl":50,"repositoryHomepageUrl":6,"ownerHtmlUrl":51,"ownerBlogUrl":52,"ownerDescription":6,"updatedAt":53,"install":54,"resources":67},"01M6C542VFA8PSB6XSNMA1XXSN","mcp-api-tool",null,"Use this skill when adding or changing a ctl-api MCP tool (RegisterMCPTools, mcp_*.go handlers).","nuonco\u002Fnuon","nuonco","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F106342559?v=4","01M6C53R8SPZA7YK156S9ACRQF","Nuon","01M6C53RCHABZERTBA66H7KYZV",125,"AGPL-3.0","https:\u002F\u002Fgithub.com\u002Fnuonco\u002Fnuon\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fmcp-api-tool\u002FSKILL.md",[18,23,26],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000010","后端与接口","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",{"categoryNo":27,"categoryName":28,"taxonomyType":29,"taxonomyTypeDesc":30},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[32,33,34,35,36,37,38,39,40],"MCP","api","tool","mcp api tool","go","use","sonnet","blue","when","2026-11-10 10:12:30",false,"---\nname: mcp-api-tool\ndescription: Use this skill when adding or changing a ctl-api MCP tool (RegisterMCPTools, mcp_*.go handlers).\nmodel: sonnet\ncolor: blue\n---\n\nThis skill enforces the ctl-api MCP tool registration pattern for the stateless Streamable HTTP server.\n\n## Steps\n\n1. Pick the domain service under `services\u002Fctl-api\u002Finternal\u002Fapp\u002F\u003Cdomain>\u002Fservice\u002F` that already implements `api.Service` and is in FX `group:\"services\"`.\n2. Add `mcp_\u003Cname>.go` with an input struct (`json` + `jsonschema` tags) and a handler matching `func(ctx, *mcp.CallToolRequest, in T) (*mcp.CallToolResult, any, error)`.\n3. Read org\u002Faccount\u002Ftoken role from `keys.*FromContext(ctx)` — never Gin context.\n4. Return payloads via `api.MCPJSONResult(...)` (compact JSON text content).\n5. Register the tool in that domain’s `mcp_register.go` with `mcp.AddTool(server, api.MCPReadTool(...)|api.MCPWriteTool(...), handler)` so `Title` and `Annotations` are always set.\n6. For mutating tools: prefix `Description` with `WRITE OPERATION:`, use `api.MCPWriteTool(..., destructive, idempotent)`, and call `require.Write(ctx)` at the start of the handler.\n7. For read tools scoped to an org: use `api.MCPReadTool(...)` and call `require.Read(ctx)` at the start of the handler.\n8. Prefer trimmed response shapes over full GORM models when the payload would be large for LLM context. Format times with `api.MCPTime` (UTC RFC3339 `…Z`) — do not serialize `time.Time`, add relative age strings, or localize on the server.\n9. List tools must use `api.MCPListPage` (default 20, max 100), `Limit(limit+1)`, and `api.MCPClipList`. Return `has_more` \u002F `next_offset`. Append `api.MCPListToolHint` to the description. Do not loop until the full set is loaded.\n10. No new MCP-specific FX wiring — `RegisterMCPTools` is discovered via type assert on `api.MCPService`.\n11. Update the tool tables in `docs\u002Fguides\u002Fagents\u002Ftools.mdx` and `bins\u002Fcli\u002Fcmd\u002Fagents_context.md`. Add a prompt to `docs\u002Fguides\u002Fagents\u002Fsample-queries.mdx` if the tool is part of a user-facing flow.\n\nReference examples: `apps\u002Fservice\u002Fmcp_list_apps.go`, `apps\u002Fservice\u002Fmcp_register.go`, `installs\u002Fservice\u002Fmcp_approve_step.go`.\n\n## Anti-Patterns\n\n- **Do not** implement tools only in the CLI proxy — tools live in ctl-api; the CLI forwards them.\n- **Do not** skip `require.Write` on write tools — description prefix \u002F annotations alone are not enough.\n- **Do not** skip `require.Read` on org-scoped read tools.\n- **Do not** register tools with bare `&mcp.Tool{Name, Description}` — always use `MCPReadTool` \u002F `MCPWriteTool`.\n- **Do not** key request state on `Mcp-Session-Id` — the server is `Stateless: true`; use bearer token + per-request `X-Nuon-Org-ID`. Do not store an org on the token.\n- **Do not** print to stdout from tool handlers — MCP protocol owns the stream.\n- **Do not** serialize `time.Time`, add `*_relative` age fields, or render local timestamps — use `MCPTime`; agents convert UTC to local.\n- **Do not** `Find` a collection without `api.MCPListPage` \u002F `Limit(limit+1)` \u002F `MCPClipList`. Return `has_more` and `next_offset`; do not loop until the full set is loaded.\n","This skill enforces the ctl-api MCP tool registration pattern for the stateless Streamable HTTP server.\n\n## Steps\n\n1. Pick the domain service under `services\u002Fctl-api\u002Finternal\u002Fapp\u002F\u003Cdomain>\u002Fservice\u002F` that already implements `api.Service` and is in FX `group:\"services\"`.\n2. Add `mcp_\u003Cname>.go` with an input struct (`json` + `jsonschema` tags) and a handler matching `func(ctx, *mcp.CallToolRequest, in T) (*mcp.CallToolResult, any, error)`.\n3. Read org\u002Faccount\u002Ftoken role from `keys.*FromContext(ctx)` — never Gin context.\n4. Return payloads via `api.MCPJSONResult(...)` (compact JSON text content).\n5. Register the tool in that domain’s `mcp_register.go` with `mcp.AddTool(server, api.MCPReadTool(...)|api.MCPWriteTool(...), handler)` so `Title` and `Annotations` are always set.\n6. For mutating tools: prefix `Description` with `WRITE OPERATION:`, use `api.MCPWriteTool(..., destructive, idempotent)`, and call `require.Write(ctx)` at the start of the handler.\n7. For read tools scoped to an org: use `api.MCPReadTool(...)` and call `require.Read(ctx)` at the start of the handler.\n8. Prefer trimmed response shapes over full GORM models when the payload would be large for LLM context. Format times with `api.MCPTime` (UTC RFC3339 `…Z`) — do not serialize `time.Time`, add relative age strings, or localize on the server.\n9. List tools must use `api.MCPListPage` (default 20, max 100), `Limit(limit+1)`, and `api.MCPClipList`. Return `has_more` \u002F `next_offset`. Append `api.MCPListToolHint` to the description. Do not loop until the full set is loaded.\n10. No new MCP-specific FX wiring — `RegisterMCPTools` is discovered via type assert on `api.MCPService`.\n11. Update the tool tables in `docs\u002Fguides\u002Fagents\u002Ftools.mdx` and `bins\u002Fcli\u002Fcmd\u002Fagents_context.md`. Add a prompt to `docs\u002Fguides\u002Fagents\u002Fsample-queries.mdx` if the tool is part of a user-facing flow.\n\nReference examples: `apps\u002Fservice\u002Fmcp_list_apps.go`, `apps\u002Fservice\u002Fmcp_register.go`, `installs\u002Fservice\u002Fmcp_approve_step.go`.\n\n## Anti-Patterns\n\n- **Do not** implement tools only in the CLI proxy — tools live in ctl-api; the CLI forwards them.\n- **Do not** skip `require.Write` on write tools — description prefix \u002F annotations alone are not enough.\n- **Do not** skip `require.Read` on org-scoped read tools.\n- **Do not** register tools with bare `&mcp.Tool{Name, Description}` — always use `MCPReadTool` \u002F `MCPWriteTool`.\n- **Do not** key request state on `Mcp-Session-Id` — the server is `Stateless: true`; use bearer token + per-request `X-Nuon-Org-ID`. Do not store an org on the token.\n- **Do not** print to stdout from tool handlers — MCP protocol owns the stream.\n- **Do not** serialize `time.Time`, add `*_relative` age fields, or render local timestamps — use `MCPTime`; agents convert UTC to local.\n- **Do not** `Find` a collection without `api.MCPListPage` \u002F `Limit(limit+1)` \u002F `MCPClipList`. Return `has_more` and `next_offset`; do not loop until the full set is loaded.\n",{"name":5,"color":39,"model":38,"description":7},"main","b76b8fb3092f72149e05b1985e22bb73d3c441b2",".agents\u002Fskills\u002Fmcp-api-tool",14,"https:\u002F\u002Fgithub.com\u002Fnuonco\u002Fnuon","https:\u002F\u002Fgithub.com\u002Fnuonco","https:\u002F\u002Fnuon.co","2026-11-14 08:44:19",{"source":8,"skillName":5,"commands":55,"prompt":65,"zipAvailable":66},[56,59,62],{"tool":57,"command":58},"npx","npx skills add nuonco\u002Fnuon --skill mcp-api-tool",{"tool":60,"command":61},"bunx","bunx skills add nuonco\u002Fnuon --skill mcp-api-tool",{"tool":63,"command":64},"pnpm","pnpm dlx skills add nuonco\u002Fnuon --skill mcp-api-tool","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fnuonco\u002Fnuon\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fmcp-api-tool\u002FSKILL.md",true,[],[69,80,92,101,113,124],{"skillNo":70,"name":71,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":72,"categories":73,"keywords":74,"publishedAt":41},"01M6C5482J0YMYJQQDG5W5VKV8","temporal-workflow-builder","https:\u002F\u002Fgithub.com\u002Fnuonco\u002Fnuon\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Ftemporal-workflow-builder\u002FSKILL.md",[],[75,76,77,78,79],"temporal","builder","temporal workflow builder","workflow builder","workflow",{"skillNo":81,"name":82,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":83,"categories":84,"keywords":88,"publishedAt":41},"01M6C546EQYS5YH93W43M482HW","product-engineer","https:\u002F\u002Fgithub.com\u002Fnuonco\u002Fnuon\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fproduct-engineer\u002FSKILL.md",[85],{"categoryNo":86,"categoryName":87,"taxonomyType":29,"taxonomyTypeDesc":30},"01JBSEEDCAT000000000000031","产品经理",[89,90,91],"product engineer","engineer","product",{"skillNo":93,"name":94,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":95,"categories":96,"keywords":97,"publishedAt":41},"01M6C544K942V8Y491KX4SBVY9","oapi-spec-helper","https:\u002F\u002Fgithub.com\u002Fnuonco\u002Fnuon\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Foapi-spec-helper\u002FSKILL.md",[],[98,99,100],"helper","oapi spec helper","spec",{"skillNo":102,"name":103,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":104,"categories":105,"keywords":106,"publishedAt":41},"01M6C540XR7A6XPSEY4WD3DHKZ","git-worktree-manager","https:\u002F\u002Fgithub.com\u002Fnuonco\u002Fnuon\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fgit-worktree-manager\u002FSKILL.md",[],[107,108,109,110,111,112],"git worktree","manager","git worktree manager","worktree","worktree manager","git",{"skillNo":114,"name":115,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":116,"categories":117,"keywords":121,"publishedAt":41},"01M6C53ZGTM1YG42268XPW9BRR","frontend-builder","https:\u002F\u002Fgithub.com\u002Fnuonco\u002Fnuon\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Ffrontend-builder\u002FSKILL.md",[118],{"categoryNo":119,"categoryName":120,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000009","前端开发",[76,122,123],"frontend builder","frontend",{"skillNo":125,"name":126,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":127,"categories":128,"keywords":133,"publishedAt":41},"01M6C53XE3H9GPVT3SMFYK8AXB","api-integration-test-builder","https:\u002F\u002Fgithub.com\u002Fnuonco\u002Fnuon\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fapi-integration-test-builder\u002FSKILL.md",[129,132],{"categoryNo":130,"categoryName":131,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[134,135,136,76,137,138,33,139],"test","integration test builder","api integration","api integration test builder","integration test","integration"]