[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6EZNC33ZGS9VKQPK49E07HX":3,"skill-same:01M6EZNC33ZGS9VKQPK49E07HX":103},{"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":63,"commitSha":64,"skillDirectory":65,"forksCount":66,"repositoryHtmlUrl":67,"repositoryHomepageUrl":6,"ownerHtmlUrl":68,"ownerBlogUrl":6,"ownerDescription":69,"updatedAt":70,"install":71,"resources":84},"01M6EZNC33ZGS9VKQPK49E07HX","mcp-integration-patterns",null,"Builds MCP (Model Context Protocol) servers and clients for extending AI assistants with custom tools, resources, and prompts.","luokai0\u002Fai-agent-skills-by-luo-kai","luokai0","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F266954973?v=4","01M6E16VNT42JB8B3X3254QWJ7","luo kai","01M6E16VTFVP6S5XJF1V1MPV90",14,"MIT","https:\u002F\u002Fgithub.com\u002Fluokai0\u002Fai-agent-skills-by-luo-kai\u002Fblob\u002Fmain\u002Fai-agent-skills\u002F21-external-registries\u002F18-organvm-skills\u002Fintegrations\u002Fmcp-integration-patterns\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],"mcp integration patterns","integration","MCP Integration","patterns","MCP","prompts","with","about","clients","client","resources","build","builder","orchestrator","model","Tools","Meta","server","protocol","model context protocol","2026-11-10 10:12:30",false,"---\nname: mcp-integration-patterns\ndescription: Builds MCP (Model Context Protocol) servers and clients for extending AI assistants with custom tools, resources, and prompts.\nlicense: MIT\ngovernance_phases: [build]\norgan_affinity: [organ-iv, meta]\ntriggers: [user-asks-about-mcp, user-asks-about-mcp-client, context:mcp-integration]\ncomplements: [mcp-builder, mcp-server-orchestrator]\n---\n\n# MCP Integration Patterns\n\nThis skill provides guidance for building Model Context Protocol (MCP) servers and clients that extend AI assistants with custom capabilities.\n\n## Core Competencies\n\n- **MCP Server Development**: Exposing tools, resources, and prompts\n- **MCP Client Integration**: Connecting to MCP servers\n- **Transport Protocols**: stdio, HTTP\u002FSSE, WebSocket\n- **Security**: Authentication, authorization, sandboxing\n\n## MCP Fundamentals\n\n### What MCP Provides\n\n```\n┌─────────────────────────────────────────────────────────────────────┐\n│                         AI Assistant (Claude)                        │\n├─────────────────────────────────────────────────────────────────────┤\n│                                                                     │\n│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐                 │\n│  │   Tools     │  │  Resources  │  │   Prompts   │                 │\n│  │  (Actions)  │  │   (Data)    │  │ (Templates) │                 │\n│  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘                 │\n│         │                │                │                         │\n│         └────────────────┼────────────────┘                         │\n│                          │                                          │\n│                    MCP Protocol                                     │\n│                          │                                          │\n├──────────────────────────┼──────────────────────────────────────────┤\n│                          │                                          │\n│  ┌───────────────────────┼───────────────────────────────────────┐ │\n│  │                   MCP Servers                                  │ │\n│  │                                                                │ │\n│  │  ┌─────────┐   ┌─────────┐   ┌─────────┐   ┌─────────┐       │ │\n│  │  │Database │   │   Git   │   │  Slack  │   │ Custom  │       │ │\n│  │  │ Server  │   │ Server  │   │ Server  │   │ Server  │       │ │\n│  │  └─────────┘   └─────────┘   └─────────┘   └─────────┘       │ │\n│  └────────────────────────────────────────────────────────────────┘ │\n└─────────────────────────────────────────────────────────────────────┘\n```\n\n### MCP Primitives\n\n| Primitive | Purpose | Direction |\n|-----------|---------|-----------|\n| Tools | Execute actions | Client → Server |\n| Resources | Expose data | Client ← Server |\n| Prompts | Template interactions | Client ← Server |\n| Sampling | Request completions | Client ← Server |\n\n## Building an MCP Server\n\n### Python SDK Server\n\n```python\nfrom mcp.server import Server\nfrom mcp.server.stdio import stdio_server\nfrom mcp.types import Tool, TextContent, Resource\n\n# Initialize server\nserver = Server(\"my-custom-server\")\n\n# Define tools\n@server.list_tools()\nasync def list_tools():\n    return [\n        Tool(\n            name=\"search_documents\",\n            description=\"Search internal documents by query\",\n            inputSchema={\n                \"type\": \"object\",\n                \"properties\": {\n                    \"query\": {\n                        \"type\": \"string\",\n                        \"description\": \"Search query\"\n                    },\n                    \"limit\": {\n                        \"type\": \"integer\",\n                        \"description\": \"Max results\",\n                        \"default\": 10\n                    }\n                },\n                \"required\": [\"query\"]\n            }\n        ),\n        Tool(\n            name=\"create_ticket\",\n            description=\"Create a support ticket\",\n            inputSchema={\n                \"type\": \"object\",\n                \"properties\": {\n                    \"title\": {\"type\": \"string\"},\n                    \"description\": {\"type\": \"string\"},\n                    \"priority\": {\n                        \"type\": \"string\",\n                        \"enum\": [\"low\", \"medium\", \"high\"]\n                    }\n                },\n                \"required\": [\"title\", \"description\"]\n            }\n        )\n    ]\n\n@server.call_tool()\nasync def call_tool(name: str, arguments: dict):\n    if name == \"search_documents\":\n        results = await search_documents(\n            arguments[\"query\"],\n            arguments.get(\"limit\", 10)\n        )\n        return [TextContent(\n            type=\"text\",\n            text=format_results(results)\n        )]\n\n    elif name == \"create_ticket\":\n        ticket = await create_ticket(\n            arguments[\"title\"],\n            arguments[\"description\"],\n            arguments.get(\"priority\", \"medium\")\n        )\n        return [TextContent(\n            type=\"text\",\n            text=f\"Created ticket #{ticket.id}\"\n        )]\n\n    raise ValueError(f\"Unknown tool: {name}\")\n\n# Run server\nasync def main():\n    async with stdio_server() as (read_stream, write_stream):\n        await server.run(read_stream, write_stream)\n\nif __name__ == \"__main__\":\n    import asyncio\n    asyncio.run(main())\n```\n\n### TypeScript SDK Server\n\n```typescript\nimport { Server } from \"@modelcontextprotocol\u002Fsdk\u002Fserver\u002Findex.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol\u002Fsdk\u002Fserver\u002Fstdio.js\";\nimport { ListToolsRequestSchema, CallToolRequestSchema } from \"@modelcontextprotocol\u002Fsdk\u002Ftypes.js\";\n\nconst server = new Server(\n  { name: \"my-custom-server\", version: \"1.0.0\" },\n  { capabilities: { tools: {} } }\n);\n\n\u002F\u002F List available tools\nserver.setRequestHandler(ListToolsRequestSchema, async () => ({\n  tools: [\n    {\n      name: \"execute_query\",\n      description: \"Execute a SQL query against the database\",\n      inputSchema: {\n        type: \"object\",\n        properties: {\n          query: { type: \"string\", description: \"SQL query to execute\" },\n          database: { type: \"string\", description: \"Target database\" }\n        },\n        required: [\"query\"]\n      }\n    }\n  ]\n}));\n\n\u002F\u002F Handle tool calls\nserver.setRequestHandler(CallToolRequestSchema, async (request) => {\n  const { name, arguments: args } = request.params;\n\n  if (name === \"execute_query\") {\n    const results = await executeQuery(args.query, args.database);\n    return {\n      content: [{ type: \"text\", text: JSON.stringify(results, null, 2) }]\n    };\n  }\n\n  throw new Error(`Unknown tool: ${name}`);\n});\n\n\u002F\u002F Start server\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\n```\n\n## Resources\n\nExpose data that the AI can read.\n\n```python\nfrom mcp.types import Resource, ResourceTemplate\n\n@server.list_resources()\nasync def list_resources():\n    return [\n        Resource(\n            uri=\"file:\u002F\u002F\u002Fconfig\u002Fsettings.json\",\n            name=\"Application Settings\",\n            description=\"Current application configuration\",\n            mimeType=\"application\u002Fjson\"\n        ),\n        Resource(\n            uri=\"db:\u002F\u002Fusers\u002Fschema\",\n            name=\"Users Table Schema\",\n            description=\"Database schema for users table\",\n            mimeType=\"text\u002Fplain\"\n        )\n    ]\n\n@server.list_resource_templates()\nasync def list_resource_templates():\n    return [\n        ResourceTemplate(\n            uriTemplate=\"file:\u002F\u002F\u002Flogs\u002F{date}.log\",\n            name=\"Daily Logs\",\n            description=\"Application logs for a specific date\"\n        ),\n        ResourceTemplate(\n            uriTemplate=\"db:\u002F\u002Ftables\u002F{table_name}\u002Fschema\",\n            name=\"Table Schema\",\n            description=\"Schema for any database table\"\n        )\n    ]\n\n@server.read_resource()\nasync def read_resource(uri: str):\n    if uri == \"file:\u002F\u002F\u002Fconfig\u002Fsettings.json\":\n        settings = await load_settings()\n        return settings\n\n    if uri.startswith(\"db:\u002F\u002F\"):\n        # Parse URI and fetch from database\n        return await fetch_db_resource(uri)\n\n    if uri.startswith(\"file:\u002F\u002F\u002Flogs\u002F\"):\n        date = uri.split(\"\u002F\")[-1].replace(\".log\", \"\")\n        return await read_log_file(date)\n\n    raise ValueError(f\"Unknown resource: {uri}\")\n```\n\n## Prompts\n\nProvide reusable prompt templates.\n\n```python\nfrom mcp.types import Prompt, PromptArgument, PromptMessage\n\n@server.list_prompts()\nasync def list_prompts():\n    return [\n        Prompt(\n            name=\"code_review\",\n            description=\"Review code for best practices and bugs\",\n            arguments=[\n                PromptArgument(\n                    name=\"code\",\n                    description=\"The code to review\",\n                    required=True\n                ),\n                PromptArgument(\n                    name=\"language\",\n                    description=\"Programming language\",\n                    required=False\n                )\n            ]\n        ),\n        Prompt(\n            name=\"summarize_document\",\n            description=\"Summarize a document with key points\",\n            arguments=[\n                PromptArgument(\n                    name=\"document_uri\",\n                    description=\"URI of document to summarize\",\n                    required=True\n                ),\n                PromptArgument(\n                    name=\"max_points\",\n                    description=\"Maximum key points to extract\",\n                    required=False\n                )\n            ]\n        )\n    ]\n\n@server.get_prompt()\nasync def get_prompt(name: str, arguments: dict):\n    if name == \"code_review\":\n        code = arguments[\"code\"]\n        language = arguments.get(\"language\", \"unknown\")\n\n        return {\n            \"description\": f\"Code review for {language}\",\n            \"messages\": [\n                PromptMessage(\n                    role=\"user\",\n                    content={\n                        \"type\": \"text\",\n                        \"text\": f\"\"\"Review this {language} code for:\n1. Bugs and potential issues\n2. Security vulnerabilities\n3. Performance concerns\n4. Best practice violations\n\nCode:\n```{language}\n{code}\n```\n\nProvide specific, actionable feedback.\"\"\"\n                    }\n                )\n            ]\n        }\n\n    raise ValueError(f\"Unknown prompt: {name}\")\n```\n\n## Transport Protocols\n\n### stdio (Default)\n\nUsed when the MCP server runs as a subprocess.\n\n```json\n\u002F\u002F claude_desktop_config.json\n{\n  \"mcpServers\": {\n    \"my-server\": {\n      \"command\": \"python\",\n      \"args\": [\"-m\", \"my_mcp_server\"],\n      \"env\": {\n        \"DATABASE_URL\": \"postgresql:\u002F\u002F...\"\n      }\n    }\n  }\n}\n```\n\n### HTTP with SSE\n\nFor remote servers:\n\n```python\nfrom mcp.server.sse import SseServerTransport\nfrom starlette.applications import Starlette\nfrom starlette.routing import Route\n\nsse = SseServerTransport(\"\u002Fmessages\")\n\nasync def handle_sse(request):\n    async with sse.connect_sse(\n        request.scope, request.receive, request._send\n    ) as streams:\n        await server.run(streams[0], streams[1])\n\napp = Starlette(routes=[\n    Route(\"\u002Fsse\", endpoint=handle_sse),\n    Route(\"\u002Fmessages\", endpoint=sse.handle_post_message, methods=[\"POST\"])\n])\n```\n\n## Server Patterns\n\n### Database Integration\n\n```python\nimport asyncpg\n\nclass DatabaseMCPServer:\n    def __init__(self, database_url):\n        self.database_url = database_url\n        self.pool = None\n\n    async def initialize(self):\n        self.pool = await asyncpg.create_pool(self.database_url)\n\n    @server.call_tool()\n    async def call_tool(self, name: str, arguments: dict):\n        if name == \"query\":\n            # Validate query (prevent dangerous operations)\n            query = arguments[\"query\"]\n            if self._is_dangerous_query(query):\n                return [TextContent(\n                    type=\"text\",\n                    text=\"Error: Query contains disallowed operations\"\n                )]\n\n            async with self.pool.acquire() as conn:\n                results = await conn.fetch(query)\n                return [TextContent(\n                    type=\"text\",\n                    text=self._format_results(results)\n                )]\n\n    def _is_dangerous_query(self, query):\n        \"\"\"Block destructive queries\"\"\"\n        dangerous = ['DROP', 'DELETE', 'TRUNCATE', 'UPDATE', 'INSERT']\n        query_upper = query.upper()\n        return any(d in query_upper for d in dangerous)\n```\n\n### File System Access\n\n```python\nimport os\nfrom pathlib import Path\n\nclass FileSystemMCPServer:\n    def __init__(self, allowed_paths):\n        self.allowed_paths = [Path(p).resolve() for p in allowed_paths]\n\n    def _validate_path(self, path_str):\n        \"\"\"Ensure path is within allowed directories\"\"\"\n        path = Path(path_str).resolve()\n        for allowed in self.allowed_paths:\n            try:\n                path.relative_to(allowed)\n                return path\n            except ValueError:\n                continue\n        raise PermissionError(f\"Access denied: {path_str}\")\n\n    @server.list_resources()\n    async def list_resources(self):\n        resources = []\n        for allowed_path in self.allowed_paths:\n            for file in allowed_path.rglob(\"*\"):\n                if file.is_file():\n                    resources.append(Resource(\n                        uri=f\"file:\u002F\u002F{file}\",\n                        name=file.name,\n                        mimeType=self._get_mimetype(file)\n                    ))\n        return resources\n\n    @server.read_resource()\n    async def read_resource(self, uri: str):\n        if uri.startswith(\"file:\u002F\u002F\"):\n            path = self._validate_path(uri[7:])\n            return path.read_text()\n        raise ValueError(f\"Unknown URI scheme: {uri}\")\n```\n\n### External API Integration\n\n```python\nimport httpx\n\nclass APIIntegrationServer:\n    def __init__(self, api_key):\n        self.api_key = api_key  # allow-secret\n        self.client = httpx.AsyncClient()\n\n    @server.call_tool()\n    async def call_tool(self, name: str, arguments: dict):\n        if name == \"fetch_weather\":\n            response = await self.client.get(\n                \"https:\u002F\u002Fapi.weather.com\u002Fcurrent\",\n                params={\"city\": arguments[\"city\"]},\n                headers={\"Authorization\": f\"Bearer {self.api_key}\"}\n            )\n            return [TextContent(type=\"text\", text=response.text)]\n\n        if name == \"send_notification\":\n            response = await self.client.post(\n                \"https:\u002F\u002Fapi.notifications.com\u002Fsend\",\n                json={\n                    \"to\": arguments[\"recipient\"],\n                    \"message\": arguments[\"message\"]\n                },\n                headers={\"Authorization\": f\"Bearer {self.api_key}\"}\n            )\n            return [TextContent(\n                type=\"text\",\n                text=f\"Notification sent: {response.json()['id']}\"\n            )]\n```\n\n## Security Considerations\n\n### Input Validation\n\n```python\nfrom pydantic import BaseModel, validator\n\nclass QueryInput(BaseModel):\n    query: str\n    limit: int = 10\n\n    @validator('query')\n    def validate_query(cls, v):\n        # Prevent SQL injection\n        dangerous = [';', '--', '\u002F*', '*\u002F', 'DROP', 'DELETE']\n        for d in dangerous:\n            if d.lower() in v.lower():\n                raise ValueError(f\"Query contains disallowed pattern: {d}\")\n        return v\n\n    @validator('limit')\n    def validate_limit(cls, v):\n        if v \u003C 1 or v > 100:\n            raise ValueError(\"Limit must be between 1 and 100\")\n        return v\n\n@server.call_tool()\nasync def call_tool(name: str, arguments: dict):\n    if name == \"search\":\n        # Validate input\n        validated = QueryInput(**arguments)\n        return await execute_search(validated.query, validated.limit)\n```\n\n### Rate Limiting\n\n```python\nfrom datetime import datetime, timedelta\nfrom collections import defaultdict\n\nclass RateLimiter:\n    def __init__(self, requests_per_minute=60):\n        self.requests_per_minute = requests_per_minute\n        self.requests = defaultdict(list)\n\n    def check(self, client_id: str):\n        now = datetime.now()\n        cutoff = now - timedelta(minutes=1)\n\n        # Clean old requests\n        self.requests[client_id] = [\n            t for t in self.requests[client_id] if t > cutoff\n        ]\n\n        if len(self.requests[client_id]) >= self.requests_per_minute:\n            raise RateLimitError(\"Too many requests\")\n\n        self.requests[client_id].append(now)\n\nrate_limiter = RateLimiter()\n\n@server.call_tool()\nasync def call_tool(name: str, arguments: dict):\n    rate_limiter.check(\"default\")  # Or use actual client ID\n    # ... process request\n```\n\n### Authentication\n\n```python\nimport os\n\nclass AuthenticatedServer:\n    def __init__(self):\n        self.api_key = os.environ.get(\"MCP_API_KEY\")  # allow-secret\n        if not self.api_key:\n            raise ValueError(\"MCP_API_KEY not set\")\n\n    def authenticate(self, request_headers: dict):\n        provided_key = request_headers.get(\"Authorization\", \"\").replace(\"Bearer \", \"\")\n        if not provided_key or provided_key != self.api_key:\n            raise AuthenticationError(\"Invalid API key\")\n```\n\n## Testing MCP Servers\n\n```python\nimport pytest\nfrom mcp.client import Client\nfrom mcp.client.stdio import stdio_client\n\n@pytest.fixture\nasync def mcp_client():\n    \"\"\"Create test client connected to server\"\"\"\n    async with stdio_client(\n        command=\"python\",\n        args=[\"-m\", \"my_mcp_server\"]\n    ) as (read, write):\n        client = Client(\"test-client\", \"1.0.0\")\n        await client.connect(read, write)\n        yield client\n\n@pytest.mark.asyncio\nasync def test_list_tools(mcp_client):\n    tools = await mcp_client.list_tools()\n    assert len(tools) > 0\n    assert any(t.name == \"search_documents\" for t in tools)\n\n@pytest.mark.asyncio\nasync def test_call_tool(mcp_client):\n    result = await mcp_client.call_tool(\n        \"search_documents\",\n        {\"query\": \"test\", \"limit\": 5}\n    )\n    assert result.content\n    assert result.content[0].type == \"text\"\n```\n\n## References\n\n- `references\u002Fmcp-specification.md` - Full MCP protocol specification\n- `references\u002Fserver-examples.md` - Complete server implementations\n- `references\u002Fdeployment-patterns.md` - Production deployment strategies\n","# MCP Integration Patterns\n\nThis skill provides guidance for building Model Context Protocol (MCP) servers and clients that extend AI assistants with custom capabilities.\n\n## Core Competencies\n\n- **MCP Server Development**: Exposing tools, resources, and prompts\n- **MCP Client Integration**: Connecting to MCP servers\n- **Transport Protocols**: stdio, HTTP\u002FSSE, WebSocket\n- **Security**: Authentication, authorization, sandboxing\n\n## MCP Fundamentals\n\n### What MCP Provides\n\n```\n┌─────────────────────────────────────────────────────────────────────┐\n│                         AI Assistant (Claude)                        │\n├─────────────────────────────────────────────────────────────────────┤\n│                                                                     │\n│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐                 │\n│  │   Tools     │  │  Resources  │  │   Prompts   │                 │\n│  │  (Actions)  │  │   (Data)    │  │ (Templates) │                 │\n│  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘                 │\n│         │                │                │                         │\n│         └────────────────┼────────────────┘                         │\n│                          │                                          │\n│                    MCP Protocol                                     │\n│                          │                                          │\n├──────────────────────────┼──────────────────────────────────────────┤\n│                          │                                          │\n│  ┌───────────────────────┼───────────────────────────────────────┐ │\n│  │                   MCP Servers                                  │ │\n│  │                                                                │ │\n│  │  ┌─────────┐   ┌─────────┐   ┌─────────┐   ┌─────────┐       │ │\n│  │  │Database │   │   Git   │   │  Slack  │   │ Custom  │       │ │\n│  │  │ Server  │   │ Server  │   │ Server  │   │ Server  │       │ │\n│  │  └─────────┘   └─────────┘   └─────────┘   └─────────┘       │ │\n│  └────────────────────────────────────────────────────────────────┘ │\n└─────────────────────────────────────────────────────────────────────┘\n```\n\n### MCP Primitives\n\n| Primitive | Purpose | Direction |\n|-----------|---------|-----------|\n| Tools | Execute actions | Client → Server |\n| Resources | Expose data | Client ← Server |\n| Prompts | Template interactions | Client ← Server |\n| Sampling | Request completions | Client ← Server |\n\n## Building an MCP Server\n\n### Python SDK Server\n\n```python\nfrom mcp.server import Server\nfrom mcp.server.stdio import stdio_server\nfrom mcp.types import Tool, TextContent, Resource\n\n# Initialize server\nserver = Server(\"my-custom-server\")\n\n# Define tools\n@server.list_tools()\nasync def list_tools():\n    return [\n        Tool(\n            name=\"search_documents\",\n            description=\"Search internal documents by query\",\n            inputSchema={\n                \"type\": \"object\",\n                \"properties\": {\n                    \"query\": {\n                        \"type\": \"string\",\n                        \"description\": \"Search query\"\n                    },\n                    \"limit\": {\n                        \"type\": \"integer\",\n                        \"description\": \"Max results\",\n                        \"default\": 10\n                    }\n                },\n                \"required\": [\"query\"]\n            }\n        ),\n        Tool(\n            name=\"create_ticket\",\n            description=\"Create a support ticket\",\n            inputSchema={\n                \"type\": \"object\",\n                \"properties\": {\n                    \"title\": {\"type\": \"string\"},\n                    \"description\": {\"type\": \"string\"},\n                    \"priority\": {\n                        \"type\": \"string\",\n                        \"enum\": [\"low\", \"medium\", \"high\"]\n                    }\n                },\n                \"required\": [\"title\", \"description\"]\n            }\n        )\n    ]\n\n@server.call_tool()\nasync def call_tool(name: str, arguments: dict):\n    if name == \"search_documents\":\n        results = await search_documents(\n            arguments[\"query\"],\n            arguments.get(\"limit\", 10)\n        )\n        return [TextContent(\n            type=\"text\",\n            text=format_results(results)\n        )]\n\n    elif name == \"create_ticket\":\n        ticket = await create_ticket(\n            arguments[\"title\"],\n            arguments[\"description\"],\n            arguments.get(\"priority\", \"medium\")\n        )\n        return [TextContent(\n            type=\"text\",\n            text=f\"Created ticket #{ticket.id}\"\n        )]\n\n    raise ValueError(f\"Unknown tool: {name}\")\n\n# Run server\nasync def main():\n    async with stdio_server() as (read_stream, write_stream):\n        await server.run(read_stream, write_stream)\n\nif __name__ == \"__main__\":\n    import asyncio\n    asyncio.run(main())\n```\n\n### TypeScript SDK Server\n\n```typescript\nimport { Server } from \"@modelcontextprotocol\u002Fsdk\u002Fserver\u002Findex.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol\u002Fsdk\u002Fserver\u002Fstdio.js\";\nimport { ListToolsRequestSchema, CallToolRequestSchema } from \"@modelcontextprotocol\u002Fsdk\u002Ftypes.js\";\n\nconst server = new Server(\n  { name: \"my-custom-server\", version: \"1.0.0\" },\n  { capabilities: { tools: {} } }\n);\n\n\u002F\u002F List available tools\nserver.setRequestHandler(ListToolsRequestSchema, async () => ({\n  tools: [\n    {\n      name: \"execute_query\",\n      description: \"Execute a SQL query against the database\",\n      inputSchema: {\n        type: \"object\",\n        properties: {\n          query: { type: \"string\", description: \"SQL query to execute\" },\n          database: { type: \"string\", description: \"Target database\" }\n        },\n        required: [\"query\"]\n      }\n    }\n  ]\n}));\n\n\u002F\u002F Handle tool calls\nserver.setRequestHandler(CallToolRequestSchema, async (request) => {\n  const { name, arguments: args } = request.params;\n\n  if (name === \"execute_query\") {\n    const results = await executeQuery(args.query, args.database);\n    return {\n      content: [{ type: \"text\", text: JSON.stringify(results, null, 2) }]\n    };\n  }\n\n  throw new Error(`Unknown tool: ${name}`);\n});\n\n\u002F\u002F Start server\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\n```\n\n## Resources\n\nExpose data that the AI can read.\n\n```python\nfrom mcp.types import Resource, ResourceTemplate\n\n@server.list_resources()\nasync def list_resources():\n    return [\n        Resource(\n            uri=\"file:\u002F\u002F\u002Fconfig\u002Fsettings.json\",\n            name=\"Application Settings\",\n            description=\"Current application configuration\",\n            mimeType=\"application\u002Fjson\"\n        ),\n        Resource(\n            uri=\"db:\u002F\u002Fusers\u002Fschema\",\n            name=\"Users Table Schema\",\n            description=\"Database schema for users table\",\n            mimeType=\"text\u002Fplain\"\n        )\n    ]\n\n@server.list_resource_templates()\nasync def list_resource_templates():\n    return [\n        ResourceTemplate(\n            uriTemplate=\"file:\u002F\u002F\u002Flogs\u002F{date}.log\",\n            name=\"Daily Logs\",\n            description=\"Application logs for a specific date\"\n        ),\n        ResourceTemplate(\n            uriTemplate=\"db:\u002F\u002Ftables\u002F{table_name}\u002Fschema\",\n            name=\"Table Schema\",\n            description=\"Schema for any database table\"\n        )\n    ]\n\n@server.read_resource()\nasync def read_resource(uri: str):\n    if uri == \"file:\u002F\u002F\u002Fconfig\u002Fsettings.json\":\n        settings = await load_settings()\n        return settings\n\n    if uri.startswith(\"db:\u002F\u002F\"):\n        # Parse URI and fetch from database\n        return await fetch_db_resource(uri)\n\n    if uri.startswith(\"file:\u002F\u002F\u002Flogs\u002F\"):\n        date = uri.split(\"\u002F\")[-1].replace(\".log\", \"\")\n        return await read_log_file(date)\n\n    raise ValueError(f\"Unknown resource: {uri}\")\n```\n\n## Prompts\n\nProvide reusable prompt templates.\n\n```python\nfrom mcp.types import Prompt, PromptArgument, PromptMessage\n\n@server.list_prompts()\nasync def list_prompts():\n    return [\n        Prompt(\n            name=\"code_review\",\n            description=\"Review code for best practices and bugs\",\n            arguments=[\n                PromptArgument(\n                    name=\"code\",\n                    description=\"The code to review\",\n                    required=True\n                ),\n                PromptArgument(\n                    name=\"language\",\n                    description=\"Programming language\",\n                    required=False\n                )\n            ]\n        ),\n        Prompt(\n            name=\"summarize_document\",\n            description=\"Summarize a document with key points\",\n            arguments=[\n                PromptArgument(\n                    name=\"document_uri\",\n                    description=\"URI of document to summarize\",\n                    required=True\n                ),\n                PromptArgument(\n                    name=\"max_points\",\n                    description=\"Maximum key points to extract\",\n                    required=False\n                )\n            ]\n        )\n    ]\n\n@server.get_prompt()\nasync def get_prompt(name: str, arguments: dict):\n    if name == \"code_review\":\n        code = arguments[\"code\"]\n        language = arguments.get(\"language\", \"unknown\")\n\n        return {\n            \"description\": f\"Code review for {language}\",\n            \"messages\": [\n                PromptMessage(\n                    role=\"user\",\n                    content={\n                        \"type\": \"text\",\n                        \"text\": f\"\"\"Review this {language} code for:\n1. Bugs and potential issues\n2. Security vulnerabilities\n3. Performance concerns\n4. Best practice violations\n\nCode:\n```{language}\n{code}\n```\n\nProvide specific, actionable feedback.\"\"\"\n                    }\n                )\n            ]\n        }\n\n    raise ValueError(f\"Unknown prompt: {name}\")\n```\n\n## Transport Protocols\n\n### stdio (Default)\n\nUsed when the MCP server runs as a subprocess.\n\n```json\n\u002F\u002F claude_desktop_config.json\n{\n  \"mcpServers\": {\n    \"my-server\": {\n      \"command\": \"python\",\n      \"args\": [\"-m\", \"my_mcp_server\"],\n      \"env\": {\n        \"DATABASE_URL\": \"postgresql:\u002F\u002F...\"\n      }\n    }\n  }\n}\n```\n\n### HTTP with SSE\n\nFor remote servers:\n\n```python\nfrom mcp.server.sse import SseServerTransport\nfrom starlette.applications import Starlette\nfrom starlette.routing import Route\n\nsse = SseServerTransport(\"\u002Fmessages\")\n\nasync def handle_sse(request):\n    async with sse.connect_sse(\n        request.scope, request.receive, request._send\n    ) as streams:\n        await server.run(streams[0], streams[1])\n\napp = Starlette(routes=[\n    Route(\"\u002Fsse\", endpoint=handle_sse),\n    Route(\"\u002Fmessages\", endpoint=sse.handle_post_message, methods=[\"POST\"])\n])\n```\n\n## Server Patterns\n\n### Database Integration\n\n```python\nimport asyncpg\n\nclass DatabaseMCPServer:\n    def __init__(self, database_url):\n        self.database_url = database_url\n        self.pool = None\n\n    async def initialize(self):\n        self.pool = await asyncpg.create_pool(self.database_url)\n\n    @server.call_tool()\n    async def call_tool(self, name: str, arguments: dict):\n        if name == \"query\":\n            # Validate query (prevent dangerous operations)\n            query = arguments[\"query\"]\n            if self._is_dangerous_query(query):\n                return [TextContent(\n                    type=\"text\",\n                    text=\"Error: Query contains disallowed operations\"\n                )]\n\n            async with self.pool.acquire() as conn:\n                results = await conn.fetch(query)\n                return [TextContent(\n                    type=\"text\",\n                    text=self._format_results(results)\n                )]\n\n    def _is_dangerous_query(self, query):\n        \"\"\"Block destructive queries\"\"\"\n        dangerous = ['DROP', 'DELETE', 'TRUNCATE', 'UPDATE', 'INSERT']\n        query_upper = query.upper()\n        return any(d in query_upper for d in dangerous)\n```\n\n### File System Access\n\n```python\nimport os\nfrom pathlib import Path\n\nclass FileSystemMCPServer:\n    def __init__(self, allowed_paths):\n        self.allowed_paths = [Path(p).resolve() for p in allowed_paths]\n\n    def _validate_path(self, path_str):\n        \"\"\"Ensure path is within allowed directories\"\"\"\n        path = Path(path_str).resolve()\n        for allowed in self.allowed_paths:\n            try:\n                path.relative_to(allowed)\n                return path\n            except ValueError:\n                continue\n        raise PermissionError(f\"Access denied: {path_str}\")\n\n    @server.list_resources()\n    async def list_resources(self):\n        resources = []\n        for allowed_path in self.allowed_paths:\n            for file in allowed_path.rglob(\"*\"):\n                if file.is_file():\n                    resources.append(Resource(\n                        uri=f\"file:\u002F\u002F{file}\",\n                        name=file.name,\n                        mimeType=self._get_mimetype(file)\n                    ))\n        return resources\n\n    @server.read_resource()\n    async def read_resource(self, uri: str):\n        if uri.startswith(\"file:\u002F\u002F\"):\n            path = self._validate_path(uri[7:])\n            return path.read_text()\n        raise ValueError(f\"Unknown URI scheme: {uri}\")\n```\n\n### External API Integration\n\n```python\nimport httpx\n\nclass APIIntegrationServer:\n    def __init__(self, api_key):\n        self.api_key = api_key  # allow-secret\n        self.client = httpx.AsyncClient()\n\n    @server.call_tool()\n    async def call_tool(self, name: str, arguments: dict):\n        if name == \"fetch_weather\":\n            response = await self.client.get(\n                \"https:\u002F\u002Fapi.weather.com\u002Fcurrent\",\n                params={\"city\": arguments[\"city\"]},\n                headers={\"Authorization\": f\"Bearer {self.api_key}\"}\n            )\n            return [TextContent(type=\"text\", text=response.text)]\n\n        if name == \"send_notification\":\n            response = await self.client.post(\n                \"https:\u002F\u002Fapi.notifications.com\u002Fsend\",\n                json={\n                    \"to\": arguments[\"recipient\"],\n                    \"message\": arguments[\"message\"]\n                },\n                headers={\"Authorization\": f\"Bearer {self.api_key}\"}\n            )\n            return [TextContent(\n                type=\"text\",\n                text=f\"Notification sent: {response.json()['id']}\"\n            )]\n```\n\n## Security Considerations\n\n### Input Validation\n\n```python\nfrom pydantic import BaseModel, validator\n\nclass QueryInput(BaseModel):\n    query: str\n    limit: int = 10\n\n    @validator('query')\n    def validate_query(cls, v):\n        # Prevent SQL injection\n        dangerous = [';', '--', '\u002F*', '*\u002F', 'DROP', 'DELETE']\n        for d in dangerous:\n            if d.lower() in v.lower():\n                raise ValueError(f\"Query contains disallowed pattern: {d}\")\n        return v\n\n    @validator('limit')\n    def validate_limit(cls, v):\n        if v \u003C 1 or v > 100:\n            raise ValueError(\"Limit must be between 1 and 100\")\n        return v\n\n@server.call_tool()\nasync def call_tool(name: str, arguments: dict):\n    if name == \"search\":\n        # Validate input\n        validated = QueryInput(**arguments)\n        return await execute_search(validated.query, validated.limit)\n```\n\n### Rate Limiting\n\n```python\nfrom datetime import datetime, timedelta\nfrom collections import defaultdict\n\nclass RateLimiter:\n    def __init__(self, requests_per_minute=60):\n        self.requests_per_minute = requests_per_minute\n        self.requests = defaultdict(list)\n\n    def check(self, client_id: str):\n        now = datetime.now()\n        cutoff = now - timedelta(minutes=1)\n\n        # Clean old requests\n        self.requests[client_id] = [\n            t for t in self.requests[client_id] if t > cutoff\n        ]\n\n        if len(self.requests[client_id]) >= self.requests_per_minute:\n            raise RateLimitError(\"Too many requests\")\n\n        self.requests[client_id].append(now)\n\nrate_limiter = RateLimiter()\n\n@server.call_tool()\nasync def call_tool(name: str, arguments: dict):\n    rate_limiter.check(\"default\")  # Or use actual client ID\n    # ... process request\n```\n\n### Authentication\n\n```python\nimport os\n\nclass AuthenticatedServer:\n    def __init__(self):\n        self.api_key = os.environ.get(\"MCP_API_KEY\")  # allow-secret\n        if not self.api_key:\n            raise ValueError(\"MCP_API_KEY not set\")\n\n    def authenticate(self, request_headers: dict):\n        provided_key = request_headers.get(\"Authorization\", \"\").replace(\"Bearer \", \"\")\n        if not provided_key or provided_key != self.api_key:\n            raise AuthenticationError(\"Invalid API key\")\n```\n\n## Testing MCP Servers\n\n```python\nimport pytest\nfrom mcp.client import Client\nfrom mcp.client.stdio import stdio_client\n\n@pytest.fixture\nasync def mcp_client():\n    \"\"\"Create test client connected to server\"\"\"\n    async with stdio_client(\n        command=\"python\",\n        args=[\"-m\", \"my_mcp_server\"]\n    ) as (read, write):\n        client = Client(\"test-client\", \"1.0.0\")\n        await client.connect(read, write)\n        yield client\n\n@pytest.mark.asyncio\nasync def test_list_tools(mcp_client):\n    tools = await mcp_client.list_tools()\n    assert len(tools) > 0\n    assert any(t.name == \"search_documents\" for t in tools)\n\n@pytest.mark.asyncio\nasync def test_call_tool(mcp_client):\n    result = await mcp_client.call_tool(\n        \"search_documents\",\n        {\"query\": \"test\", \"limit\": 5}\n    )\n    assert result.content\n    assert result.content[0].type == \"text\"\n```\n\n## References\n\n- `references\u002Fmcp-specification.md` - Full MCP protocol specification\n- `references\u002Fserver-examples.md` - Complete server implementations\n- `references\u002Fdeployment-patterns.md` - Production deployment strategies\n",{"name":5,"license":15,"triggers":52,"complements":56,"description":7,"organ_affinity":59,"governance_phases":62},[53,54,55],"user-asks-about-mcp","user-asks-about-mcp-client","context:mcp-integration",[57,58],"mcp-builder","mcp-server-orchestrator",[60,61],"organ-iv","meta",[38],"main","4d2fb89cdfb75f3f6fd3c6c5ec9ad90ea129eb3c","ai-agent-skills\u002F21-external-registries\u002F18-organvm-skills\u002Fintegrations\u002Fmcp-integration-patterns",1,"https:\u002F\u002Fgithub.com\u002Fluokai0\u002Fai-agent-skills-by-luo-kai","https:\u002F\u002Fgithub.com\u002Fluokai0","a solo builder.","2026-05-06 04:29:04",{"source":8,"skillName":5,"commands":72,"prompt":82,"zipAvailable":83},[73,76,79],{"tool":74,"command":75},"npx","npx skills add luokai0\u002Fai-agent-skills-by-luo-kai --skill mcp-integration-patterns",{"tool":77,"command":78},"bunx","bunx skills add luokai0\u002Fai-agent-skills-by-luo-kai --skill mcp-integration-patterns",{"tool":80,"command":81},"pnpm","pnpm dlx skills add luokai0\u002Fai-agent-skills-by-luo-kai --skill mcp-integration-patterns","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fluokai0\u002Fai-agent-skills-by-luo-kai\u002Fblob\u002Fmain\u002Fai-agent-skills\u002F21-external-registries\u002F18-organvm-skills\u002Fintegrations\u002Fmcp-integration-patterns\u002FSKILL.md",true,[85,91,95,99],{"path":86,"resourceType":87,"resourceTypeDesc":88,"sizeBytes":89,"sourceHtmlUrl":90},"references\u002Fdeployment-patterns.md","REFERENCE","参考文档",7600,"https:\u002F\u002Fgithub.com\u002Fluokai0\u002Fai-agent-skills-by-luo-kai\u002Fblob\u002Fmain\u002Fai-agent-skills\u002F21-external-registries\u002F18-organvm-skills\u002Fintegrations\u002Fmcp-integration-patterns\u002Freferences\u002Fdeployment-patterns.md",{"path":92,"resourceType":87,"resourceTypeDesc":88,"sizeBytes":93,"sourceHtmlUrl":94},"references\u002Fmcp-specification.md",5741,"https:\u002F\u002Fgithub.com\u002Fluokai0\u002Fai-agent-skills-by-luo-kai\u002Fblob\u002Fmain\u002Fai-agent-skills\u002F21-external-registries\u002F18-organvm-skills\u002Fintegrations\u002Fmcp-integration-patterns\u002Freferences\u002Fmcp-specification.md",{"path":96,"resourceType":87,"resourceTypeDesc":88,"sizeBytes":97,"sourceHtmlUrl":98},"references\u002Fserver-examples.md",10823,"https:\u002F\u002Fgithub.com\u002Fluokai0\u002Fai-agent-skills-by-luo-kai\u002Fblob\u002Fmain\u002Fai-agent-skills\u002F21-external-registries\u002F18-organvm-skills\u002Fintegrations\u002Fmcp-integration-patterns\u002Freferences\u002Fserver-examples.md",{"path":100,"resourceType":87,"resourceTypeDesc":88,"sizeBytes":101,"sourceHtmlUrl":102},"references\u002Fworkflow-integration.md",5658,"https:\u002F\u002Fgithub.com\u002Fluokai0\u002Fai-agent-skills-by-luo-kai\u002Fblob\u002Fmain\u002Fai-agent-skills\u002F21-external-registries\u002F18-organvm-skills\u002Fintegrations\u002Fmcp-integration-patterns\u002Freferences\u002Fworkflow-integration.md",[104,130,147,171,203,238],{"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":110,"publishedAt":47},"01M6F2SKTE208174C7S7JJCZC7","write-contracts","Generates secure Aptos Move V2 smart contracts with Object model, Digital Asset integration, security patterns, and storage type guidance. Includes comprehensive storage decision framework for optimal data structure selection. Triggers on: 'write contract', 'create NFT collection', 'build marketplace', 'implement minting', 'generate Move module', 'create token contract', 'build DAO', 'implement staking'. Ask storage questions when: 'store', 'track', 'registry', 'mapping', 'list', 'collection'.","https:\u002F\u002Fgithub.com\u002Fluokai0\u002Fai-agent-skills-by-luo-kai\u002Fblob\u002Fmain\u002Fai-agent-skills\u002F22-clawhub-skills\u002Fwrite-contracts\u002FSKILL.md",[],[111,112,113,114,115,116,117,118,41,119,120,121,122,123,124,125,126,127,128,129],"write","contracts","write contracts","storage","secure","create","generate","collection","decision","ask","smart-contracts","selection","objects","structure","nft","token","aptos","critical","move",{"skillNo":131,"name":132,"nameZh":6,"description":133,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":134,"categories":135,"keywords":136,"publishedAt":47},"01M6F2RFXJ6T9MKW0A7N7GM45B","web-search","通用网络搜索技能，支持多引擎搜索（百度、必应、DuckDuckGo），无需API密钥即可获取实时信息","https:\u002F\u002Fgithub.com\u002Fluokai0\u002Fai-agent-skills-by-luo-kai\u002Fblob\u002Fmain\u002Fai-agent-skills\u002F22-clawhub-skills\u002Fweb-search-ex-skill\u002FSKILL.md",[],[137,138,139,140,141,142,143,144,145,146],"web","search","web search","搜索","baidu","bing","duckduckgo","百度","多引擎","internet",{"skillNo":148,"name":149,"nameZh":6,"description":150,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":151,"categories":152,"keywords":154,"publishedAt":47},"01M6F2K968G1FZEZFPW2E6B222","solo-build","Execute implementation plan tasks with TDD workflow, auto-commit, and phase gates. Use when user says \"build it\", \"start building\", \"execute plan\", \"implement tasks\", \"ship it\", or references a track ID. Do NOT use for planning (use \u002Fplan) or scaffolding (use \u002Fscaffold).","https:\u002F\u002Fgithub.com\u002Fluokai0\u002Fai-agent-skills-by-luo-kai\u002Fblob\u002Fmain\u002Fai-agent-skills\u002F22-clawhub-skills\u002Fsolo-build\u002FSKILL.md",[153],{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},[38,155,156,31,157,158,159,160,138,161,162,163,111,164,165,166,167,168,169,170],"solo","solo build","workflow","commit","tasks","code","Bash","plan","read","auto","references","context7","query","scaffolding","ship it","project",{"skillNo":172,"name":173,"nameZh":6,"description":174,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":175,"categories":176,"keywords":183,"publishedAt":47},"01M6F2GKN39SGHSPWYB3662YC8","react-email","Use when building HTML email templates with React components, adding a visual email editor to an application using the React Email visual editor, rendering emails to HTML, or sending emails with Resend. Covers welcome emails, password resets, notifications, order confirmations, newsletters, transactional emails, and the embeddable email editor component.","https:\u002F\u002Fgithub.com\u002Fluokai0\u002Fai-agent-skills-by-luo-kai\u002Fblob\u002Fmain\u002Fai-agent-skills\u002F22-clawhub-skills\u002Freact-email-skills\u002FSKILL.md",[177,180],{"categoryNo":178,"categoryName":179,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000005","邮件与沟通",{"categoryNo":181,"categoryName":182,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000009","前端开发",[184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,33],"react","email","react email","github","editor","components","react components","component","welcome","https","notifications","password","node","use","html","resend","visual","emails","rendering",{"skillNo":204,"name":205,"nameZh":6,"description":206,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":207,"categories":208,"keywords":219,"publishedAt":47},"01M6F2FBVGVDFSG8SSFJGXA40C","APITester Agent-Driven API Testing","Test API endpoints and document responses. Define tests in plain English, run them, get formatted results. Agent-driven Postman alternative.","https:\u002F\u002Fgithub.com\u002Fluokai0\u002Fai-agent-skills-by-luo-kai\u002Fblob\u002Fmain\u002Fai-agent-skills\u002F22-clawhub-skills\u002Fopenclaw-api-tester\u002FSKILL.md",[209,212,213,214],{"categoryNo":210,"categoryName":211,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":215,"categoryName":216,"taxonomyType":217,"taxonomyTypeDesc":218},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237],"testing","api","api testing","driven","APITester Agent Driven API Testing","test","run","postman","results","plain english","tester","endpoints","document","get","define","tests","english","api-tester",{"skillNo":239,"name":240,"nameZh":6,"description":241,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":242,"categories":243,"keywords":244,"publishedAt":47},"01M6F273Y3NGAPVJZ608BC0G9G","hubspot-implementation-plan","Generate a phased implementation plan from a HubSpot audit report. Creates prioritized, sequenced cleanup processes with effort estimates, dependencies, and automation feasibility. Use after running \u002Fhubspot-audit.","https:\u002F\u002Fgithub.com\u002Fluokai0\u002Fai-agent-skills-by-luo-kai\u002Fblob\u002Fmain\u002Fai-agent-skills\u002F22-clawhub-skills\u002Fhubspot-implementation-plan\u002FSKILL.md",[],[162,245,246,247,248,249,250,117,251,252,253,254,255,197,256,257,33,258],"implementation","hubspot","hubspot implementation plan","automation","feasibility","cleanup","planning","report","audit","audit report","phased implementation","dependencies","processes","hubspot audit"]