Skill: malinguo/liuduoduo-life-skill (version 0.1.0)

--- name: liuduoduo-life-skill description: liuduoduo - local life service skill: find handyman, find restaurant, find hotel. version: 0.1.0 alwaysApply: false keywords: - liuduoduo - local-life - handyman - restaurant - hotel --- > **⚠️ AI Agent 必读** > > When user mentions "liuduoduo", activate this Skill immediately. **Must call MCP tools to get data**, never make up merchant info, phone numbers, or prices. > > **MCP 调用方式**：通过 MCP 协议（JSON-RPC 2.0 POST）调用。端点地址见 `skill.json` 中 `mcp_server.url` 字段。 # liuduoduo · Skill ## 功能 | 用户可能会问 | 调用什么工具 | |---|---| | "下水道堵了" / "找个水电师傅" / "开锁" / "搬家" | `find_service` | | "请客吃饭" / "浏阳特色餐厅" / "找个农庄" / "吃蒸菜" | `find_restaurant` | | "订酒店" / "天空剧院附近住哪" / "推荐住宿" | `find_hotel` | ## 使用说明 ### 找师傅 1. 用户描述问题（如"家里下水道堵了"） 2. AI 判断服务类别，调用 `find_service` 工具 3. 返回师傅的姓名、电话、价格、评价、服务时间 4. AI 直接展示给用户，用户打电话联系 ### 找餐厅 1. 用户说需求（如"6个人500块预算，要有风景"） 2. AI 算好人均，调用 `find_restaurant` 工具 3. 返回餐厅名称、地址、人均价格、特色菜、电话 4. AI 推荐3-5家，并说明每家的特色 ### 找酒店 1. 用户说需求（如"天空剧院附近400块的双人间"） 2. AI 调用 `find_hotel` 工具，传入价格和位置 3. 返回酒店名称、价格、设施、距离、电话 4. AI 按需求排序推荐 ## 重要规则 - **电话号码必须直接展示给用户**，不能省略 - **价格信息必须如实展示**，不能编造 - 如果用户需求不够具体，先引导用户说清楚：几个人？预算多少？在哪个位置？ - 目前覆盖浏阳市区及周边乡镇（官渡、大围山、古港、沙市等） ## 品牌调性 - 自称"liuduoduo"，像一个热心的本地朋友 - 熟悉每条街、每个店 - 不啰嗦，直接给答案 - 主动帮用户省钱、少走弯路 ## 维护者参考 - MCP 端点：以 `skill.json` 中 `mcp_server.url` 为准 - 部署：腾讯云轻量服务器，端口 8002 - 数据：当前为示范数据，后期替换为真实商家信息

path: README.md
content: # liuduoduo

Local life service skill: find handyman, find restaurant, find hotel. Ask and get results with phone numbers.

## Features

- **Find Handyman**: plumbing, electrician, locksmith, moving, appliance repair, AC cleaning, waterproofing
- **Find Restaurant**: local cuisine, farmhouse dining, group dinner recommendations (filter by budget, party size, scenery)
- **Find Hotel**: filter by price, location, breakfast included

## Usage

Install this Skill in CodeBuddy / WorkBuddy, then ask AI:

- "My drain is clogged, find me a plumber"
- "6 people, 500 yuan budget, where to eat? Want nice scenery"
- "Recommend a hotel near Sky Theater, 400/night, with breakfast"

AI will call tools automatically and return merchant name, phone, price, address.

## Tech Stack

- Framework: FastAPI + Uvicorn
- Protocol: MCP (JSON-RPC 2.0)
- License: MIT

## Author

haishuAI


path: backend/data.py
content: # -*- coding: utf-8 -*-
"""
浏阳本地生活 Skill - 商家数据库
包含：生活服务师傅、餐厅农庄、酒店住宿
数据说明：这是示范数据，后期可以替换为真实商家信息
"""

# ============================================================
# 生活服务师傅（水电维修、疏通、开锁、搬家等）
# ============================================================
SERVICE_WORKERS = [
    # --- 疏通下水道 ---
    {
        "id": "sw001",
        "name": "老陈管道疏通",
        "category": "疏通下水道",
        "contact": "陈师傅",
        "phone": "138-7498-XXXX",
        "service_area": "浏阳全市区",
        "price_range": "80-300元",
        "work_hours": "24小时上门",
        "rating": 4.8,
        "review_count": 326,
        "highlight": "干了15年，马桶、厨房、地漏都能通，半小时到",
        "address": "浏阳市淮川街道"
    },
    {
        "id": "sw002",
        "name": "浏阳管道疏通王",
        "category": "疏通下水道",
        "contact": "王师傅",
        "phone": "159-7312-XXXX",
        "service_area": "淮川、集里、关口、荷花",
        "price_range": "60-200元",
        "work_hours": "早7点-晚11点",
        "rating": 4.6,
        "review_count": 198,
        "highlight": "价格实在，小问题60块搞定，通不了不收钱",
        "address": "浏阳市集里街道"
    },
    # --- 水电维修 ---
    {
        "id": "sw003",
        "name": "李师傅水电维修",
        "category": "水电维修",
        "contact": "李师傅",
        "phone": "186-8498-XXXX",
        "service_area": "浏阳全市区",
        "price_range": "50-500元",
        "work_hours": "早8点-晚9点",
        "rating": 4.9,
        "review_count": 412,
        "highlight": "持证电工，水管漏水、电路跳闸、灯具安装都做",
        "address": "浏阳市淮川街道才常路"
    },
    {
        "id": "sw004",
        "name": "急修哥水电",
        "category": "水电维修",
        "contact": "张师傅",
        "phone": "135-0731-XXXX",
        "service_area": "淮川、集里、荷花",
        "price_range": "30-300元",
        "work_hours": "24小时（夜间加50元）",
        "rating": 4.7,
        "review_count": 267,
        "highlight": "修不好不收钱，上门快，一般20分钟到",
        "address": "浏阳市荷花街道"
    },
    # --- 开锁换锁 ---
    {
        "id": "sw005",
        "name": "浏阳速开锁",
        "category": "开锁换锁",
        "contact": "刘师傅",
        "phone": "131-8710-XXXX",
        "service_area": "浏阳全市区",
        "price_range": "80-500元",
        "work_hours": "24小时",
        "rating": 4.8,
        "review_count": 531,
        "highlight": "公安备案正规开锁，15分钟到场，开不了不收费",
        "address": "浏阳市淮川街道人民中路"
    },
    # --- 搬家 ---
    {
        "id": "sw006",
        "name": "浏阳兄弟搬家",
        "category": "搬家",
        "contact": "周师傅",
        "phone": "150-7317-XXXX",
        "service_area": "浏阳全市区及周边乡镇",
        "price_range": "200-800元",
        "work_hours": "早7点-晚8点",
        "rating": 4.7,
        "review_count": 189,
        "highlight": "两个壮小伙上门，家具打包拆装都包，不加价",
        "address": "浏阳市关口街道"
    },
    # --- 家电维修 ---
    {
        "id": "sw007",
        "name": "小刘家电维修",
        "category": "家电维修",
        "contact": "刘师傅",
        "phone": "180-7313-XXXX",
        "service_area": "浏阳市区",
        "price_range": "50-400元",
        "work_hours": "早8点-晚7点",
        "rating": 4.6,
        "review_count": 156,
        "highlight": "空调、洗衣机、热水器、冰箱都修，先报价再修",
        "address": "浏阳市集里街道白沙路"
    },
    # --- 空调清洗 ---
    {
        "id": "sw008",
        "name": "洁净到家",
        "category": "空调清洗",
        "contact": "谭师傅",
        "phone": "173-8493-XXXX",
        "service_area": "浏阳全市区",
        "price_range": "80-150元/台",
        "work_hours": "早8点-晚6点",
        "rating": 4.8,
        "review_count": 203,
        "highlight": "专业拆洗，挂机80、柜机120、中央空调150/台",
        "address": "浏阳市荷花街道"
    },
    # --- 防水补漏 ---
    {
        "id": "sw009",
        "name": "固盾防水",
        "category": "防水补漏",
        "contact": "赵师傅",
        "phone": "199-7498-XXXX",
        "service_area": "浏阳全市区",
        "price_range": "200-2000元",
        "work_hours": "早8点-晚6点",
        "rating": 4.5,
        "review_count": 87,
        "highlight": "屋顶、卫生间、阳台防水，质保5年，漏了免费修",
        "address": "浏阳市淮川街道"
    },
]

# ============================================================
# 餐厅农庄（浏阳特色、农庄、饭店）
# ============================================================
RESTAURANTS = [
    # --- 特色农庄（有风景） ---
    {
        "id": "r001",
        "name": "官渡嗨渔庄",
        "category": "特色农庄",
        "cuisine": "浏阳蒸菜、河鲜、烧烤",
        "phone": "139-7312-XXXX",
        "address": "浏阳市官渡镇（浏阳河边）",
        "avg_price": 60,
        "avg_price_desc": "人均60元左右",
        "capacity": "可接待50人以上",
        "has_scenery": True,
        "scenery_desc": "靠着浏阳河，有露天河景位，吃饭看河景",
        "has_parking": True,
        "specialties": ["浏阳蒸菜", "河鲜鱼", "土鸡汤", "烧烤"],
        "highlight": "浏阳河边吃鱼，风景一流，本地人周末常去的农庄",
        "rating": 4.7,
        "nav_keyword": "官渡嗨渔庄 浏阳"
    },
    {
        "id": "r002",
        "name": "道官冲生态农庄",
        "category": "特色农庄",
        "cuisine": "农家菜、蒸菜、土菜",
        "phone": "136-8731-XXXX",
        "address": "浏阳市荷花街道道官冲",
        "avg_price": 55,
        "avg_price_desc": "人均55元左右",
        "capacity": "可接待30人",
        "has_scenery": True,
        "scenery_desc": "山里面的农庄，有鱼塘可以钓鱼，空气好",
        "has_parking": True,
        "specialties": ["土鸡", "腊肉", "浏阳蒸菜", "自种蔬菜"],
        "highlight": "山里农庄，可以钓鱼、摘菜，小孩也有地方玩",
        "rating": 4.6,
        "nav_keyword": "道官冲生态农庄 浏阳"
    },
    {
        "id": "r003",
        "name": "大围山峡谷漂流农庄",
        "category": "特色农庄",
        "cuisine": "大围山土菜",
        "phone": "158-7498-XXXX",
        "address": "浏阳市大围山镇",
        "avg_price": 70,
        "avg_price_desc": "人均70元左右",
        "capacity": "可接待80人以上",
        "has_scenery": True,
        "scenery_desc": "大围山脚下，森林环绕，夏天可以漂流",
        "has_parking": True,
        "specialties": ["大围山笋", "烟熏腊肉", "溪水鱼", "土鸡"],
        "highlight": "夏天漂流+吃饭一条龙，外地朋友来必去",
        "rating": 4.8,
        "nav_keyword": "大围山峡谷漂流 浏阳"
    },
    {
        "id": "r004",
        "name": "田螺小镇",
        "category": "特色农庄",
        "cuisine": "田螺、浏阳菜",
        "phone": "137-5517-XXXX",
        "address": "浏阳市沙市镇",
        "avg_price": 50,
        "avg_price_desc": "人均50元左右",
        "capacity": "可接待40人",
        "has_scenery": True,
        "scenery_desc": "田园风光，有荷花池和小溪",
        "has_parking": True,
        "specialties": ["田螺", "浏阳蒸菜", "米豆腐", "农家小炒"],
        "highlight": "吃田螺的好地方，田园风光，拍照好看",
        "rating": 4.5,
        "nav_keyword": "田螺小镇 浏阳"
    },
    # --- 市区餐厅 ---
    {
        "id": "r005",
        "name": "文家市大碗菜",
        "category": "浏阳蒸菜",
        "cuisine": "浏阳蒸菜",
        "phone": "150-7491-XXXX",
        "address": "浏阳市人民中路（步行街附近）",
        "avg_price": 35,
        "avg_price_desc": "人均35元左右",
        "capacity": "可接待20人",
        "has_scenery": False,
        "scenery_desc": "",
        "has_parking": False,
        "specialties": ["蒸腊肉", "蒸鱼头", "蒸鸡蛋", "蒸排骨"],
        "highlight": "正宗浏阳蒸菜，量大实惠，本地人天天吃",
        "rating": 4.6,
        "nav_keyword": "文家市大碗菜 浏阳"
    },
    {
        "id": "r006",
        "name": "浏阳古风楼",
        "category": "浏阳菜馆",
        "cuisine": "浏阳菜、湘菜",
        "phone": "189-7498-XXXX",
        "address": "浏阳市圭斋东路",
        "avg_price": 65,
        "avg_price_desc": "人均65元左右",
        "capacity": "可接待60人，有包厢",
        "has_scenery": False,
        "scenery_desc": "",
        "has_parking": True,
        "specialties": ["浏阳黑山羊", "蒸菜拼盘", "口味虾", "剁椒鱼头"],
        "highlight": "请客有面子，有包厢，菜品精致，环境好",
        "rating": 4.7,
        "nav_keyword": "浏阳古风楼"
    },
    {
        "id": "r007",
        "name": "蒸浏记",
        "category": "浏阳蒸菜",
        "cuisine": "蒸菜快餐",
        "phone": "173-0731-XXXX",
        "address": "浏阳市才常路",
        "avg_price": 20,
        "avg_price_desc": "人均20元左右",
        "capacity": "快餐店，10人左右",
        "has_scenery": False,
        "scenery_desc": "",
        "has_parking": False,
        "specialties": ["蒸菜套餐", "蒸排骨", "蒸鱼", "蒸南瓜"],
        "highlight": "快餐蒸菜，便宜好吃，一个人也能吃",
        "rating": 4.4,
        "nav_keyword": "蒸浏记 浏阳"
    },
    {
        "id": "r008",
        "name": "湘水源农庄",
        "category": "特色农庄",
        "cuisine": "农家菜、柴火灶",
        "phone": "155-7498-XXXX",
        "address": "浏阳市古港镇",
        "avg_price": 55,
        "avg_price_desc": "人均55元左右",
        "capacity": "可接待40人",
        "has_scenery": True,
        "scenery_desc": "竹林环绕，有小溪，环境清幽",
        "has_parking": True,
        "specialties": ["柴火土鸡", "腊肉炒笋", "米粉肉", "手工豆腐"],
        "highlight": "柴火灶做菜，原汁原味，吃完还能在竹林散步",
        "rating": 4.6,
        "nav_keyword": "湘水源农庄 浏阳古港"
    },
]

# ============================================================
# 酒店住宿
# ============================================================
HOTELS = [
    {
        "id": "h001",
        "name": "浏阳国际大酒店",
        "category": "商务酒店",
        "stars": "四星级",
        "phone": "0731-8386-XXXX",
        "address": "浏阳市淮川街道人民中路",
        "price_range": "380-680元/晚",
        "avg_price": 450,
        "has_breakfast": True,
        "breakfast_desc": "自助早餐，中西式都有，品种丰富",
        "has_parking": True,
        "wifi": True,
        "distance_to_center": "市中心，步行街旁边",
        "nearby_landmark": "步行街、天空剧院步行10分钟",
        "highlight": "浏阳最老牌的酒店，地段最好，出门就是步行街",
        "rating": 4.5,
        "room_types": ["大床房", "双床房", "豪华套房"],
        "nav_keyword": "浏阳国际大酒店"
    },
    {
        "id": "h002",
        "name": "维也纳酒店(浏阳天空剧院店)",
        "category": "连锁酒店",
        "stars": "四星级",
        "phone": "0731-8398-XXXX",
        "address": "浏阳市金沙北路（天空剧院对面）",
        "price_range": "320-520元/晚",
        "avg_price": 380,
        "has_breakfast": True,
        "breakfast_desc": "自助早餐，干净卫生，味道不错",
        "has_parking": True,
        "wifi": True,
        "distance_to_center": "天空剧院对面，市中心5分钟车程",
        "nearby_landmark": "天空剧院对面，走路2分钟",
        "highlight": "天空剧院看烟花最方便的酒店，出门就到",
        "rating": 4.6,
        "room_types": ["大床房", "双床房", "家庭房"],
        "nav_keyword": "维也纳酒店 浏阳天空剧院"
    },
    {
        "id": "h003",
        "name": "浏阳恒邦开元酒店",
        "category": "高端酒店",
        "stars": "五星标准",
        "phone": "0731-8388-XXXX",
        "address": "浏阳市花炮大道",
        "price_range": "480-1200元/晚",
        "avg_price": 580,
        "has_breakfast": True,
        "breakfast_desc": "五星级自助早餐，品种最全，有湖南特色早点",
        "has_parking": True,
        "wifi": True,
        "distance_to_center": "市中心10分钟车程",
        "nearby_landmark": "花炮观礼台附近",
        "highlight": "浏阳最高档的酒店，设施新，服务好，适合商务接待",
        "rating": 4.8,
        "room_types": ["豪华大床房", "行政双床房", "总统套房"],
        "nav_keyword": "浏阳恒邦开元酒店"
    },
    {
        "id": "h004",
        "name": "汉庭酒店(浏阳步行街店)",
        "category": "经济连锁",
        "stars": "三星级",
        "phone": "0731-8381-XXXX",
        "address": "浏阳市北正南路（步行街附近）",
        "price_range": "180-280元/晚",
        "avg_price": 220,
        "has_breakfast": True,
        "breakfast_desc": "简单早餐，包子粥面条",
        "has_parking": False,
        "wifi": True,
        "distance_to_center": "步行街旁边",
        "nearby_landmark": "步行街走路3分钟",
        "highlight": "便宜干净，连锁品牌有保障，适合预算有限的朋友",
        "rating": 4.3,
        "room_types": ["大床房", "双床房"],
        "nav_keyword": "汉庭酒店 浏阳步行街"
    },
    {
        "id": "h005",
        "name": "如家酒店(浏阳才常路店)",
        "category": "经济连锁",
        "stars": "三星级",
        "phone": "0731-8382-XXXX",
        "address": "浏阳市才常路",
        "price_range": "160-260元/晚",
        "avg_price": 200,
        "has_breakfast": True,
        "breakfast_desc": "简单早餐",
        "has_parking": False,
        "wifi": True,
        "distance_to_center": "市中心，交通方便",
        "nearby_landmark": "天空剧院15分钟车程",
        "highlight": "性价比最高，干净整洁，适合短住",
        "rating": 4.2,
        "room_types": ["大床房", "双床房"],
        "nav_keyword": "如家酒店 浏阳才常路"
    },
    {
        "id": "h006",
        "name": "锦江之星(浏阳金沙路店)",
        "category": "经济连锁",
        "stars": "三星级",
        "phone": "0731-8385-XXXX",
        "address": "浏阳市金沙北路",
        "price_range": "200-320元/晚",
        "avg_price": 250,
        "has_breakfast": True,
        "breakfast_desc": "自助早餐，品种还行",
        "has_parking": True,
        "wifi": True,
        "distance_to_center": "天空剧院5分钟车程",
        "nearby_landmark": "天空剧院5分钟车程",
        "highlight": "离天空剧院近，有停车位，性价比不错",
        "rating": 4.4,
        "room_types": ["大床房", "双床房"],
        "nav_keyword": "锦江之星 浏阳金沙路"
    },
    {
        "id": "h007",
        "name": "大围山森林度假酒店",
        "category": "度假酒店",
        "stars": "四星级",
        "phone": "0731-8396-XXXX",
        "address": "浏阳市大围山镇",
        "price_range": "350-600元/晚",
        "avg_price": 420,
        "has_breakfast": True,
        "breakfast_desc": "山里特色早餐，有当地米粉和手工包子",
        "has_parking": True,
        "wifi": True,
        "distance_to_center": "距市区40分钟车程",
        "nearby_landmark": "大围山国家森林公园门口",
        "highlight": "住在山里，空气好，夏天凉快，适合带家人度假",
        "rating": 4.7,
        "room_types": ["山景大床房", "家庭房", "独栋木屋"],
        "nav_keyword": "大围山森林度假酒店 浏阳"
    },
]


# ============================================================
# 搜索和推荐函数
# ============================================================

def search_services(category=None, keyword=None):
    """搜索生活服务师傅"""
    results = SERVICE_WORKERS

    if category:
        category = category.strip()
        results = [s for s in results if category in s["category"]]

    if keyword:
        keyword = keyword.strip().lower()
        results = [s for s in results if
                   keyword in s["category"].lower() or
                   keyword in s["name"].lower() or
                   keyword in s["highlight"].lower()]

    if not results:
        # 返回所有可用分类
        all_cats = list(set(s["category"] for s in SERVICE_WORKERS))
        return {
            "found": False,
            "message": f"没有找到相关服务。目前支持的服务类型有：{', '.join(all_cats)}",
            "available_categories": all_cats
        }

    return {
        "found": True,
        "count": len(results),
        "services": results
    }


def search_restaurants(budget_per_person=None, people_count=None, want_scenery=False, keyword=None):
    """搜索餐厅农庄"""
    results = RESTAURANTS

    if keyword:
        keyword = keyword.strip().lower()
        results = [r for r in results if
                   keyword in r["name"].lower() or
                   keyword in r["category"].lower() or
                   keyword in r["cuisine"].lower() or
                   keyword in " ".join(r["specialties"]).lower() or
                   keyword in r.get("highlight", "").lower() or
                   keyword in r.get("address", "").lower()]

    if want_scenery:
        results = [r for r in results if r.get("has_scenery")]

    if budget_per_person:
        # budget_per_person 就是人均预算（元），直接用来筛选
        results = [r for r in results if r["avg_price"] <= budget_per_person * 1.2]

    if not results:
        return {
            "found": False,
            "message": "没有找到符合条件的餐厅。试试放宽预算或去掉风景要求？",
            "tip": "浏阳特色推荐：蒸菜、黑山羊、河鲜、大围山土菜"
        }

    # 按评分排序
    results.sort(key=lambda x: x["rating"], reverse=True)
    return {
        "found": True,
        "count": len(results),
        "restaurants": results
    }


def search_hotels(max_price=None, need_breakfast=False, near_landmark=None, room_type=None):
    """搜索酒店"""
    results = HOTELS

    if max_price:
        results = [h for h in results if h["avg_price"] <= max_price * 1.1]

    if need_breakfast:
        results = [h for h in results if h.get("has_breakfast")]

    if near_landmark:
        landmark = near_landmark.strip().lower()
        results = [h for h in results if
                   landmark in h.get("nearby_landmark", "").lower() or
                   landmark in h.get("address", "").lower() or
                   landmark in h.get("distance_to_center", "").lower()]

    if room_type:
        room_type = room_type.strip()
        results = [h for h in results if
                   any(room_type in rt for rt in h.get("room_types", []))]

    if not results:
        all_hotels_summary = [
            f"{h['name']}（{h['price_range']}，{h['nearby_landmark']}）"
            for h in HOTELS
        ]
        return {
            "found": False,
            "message": "没有找到完全符合条件的酒店。以下是浏阳所有推荐酒店：",
            "all_hotels": all_hotels_summary
        }

    # 按评分排序
    results.sort(key=lambda x: x["rating"], reverse=True)
    return {
        "found": True,
        "count": len(results),
        "hotels": results
    }


# 所有服务类别汇总（给AI看的）
SERVICE_CATEGORIES = list(set(s["category"] for s in SERVICE_WORKERS))
RESTAURANT_CATEGORIES = list(set(r["category"] for r in RESTAURANTS))


path: backend/main.py
content: # -*- coding: utf-8 -*-
"""
浏阳本地生活 Skill - MCP 后端服务
功能：找师傅（疏通/水电/开锁/搬家等）、找餐厅农庄、找酒店
端口：8002
"""

import sys
import json
from typing import Optional
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from fastapi.middleware.cors import CORSMiddleware

from data import (
    search_services, search_restaurants, search_hotels,
    SERVICE_CATEGORIES, RESTAURANT_CATEGORIES,
    SERVICE_WORKERS, RESTAURANTS, HOTELS
)

sys.stdout.reconfigure(encoding="utf-8")

app = FastAPI(
    title="浏阳本地生活 Skill",
    description="浏阳本地生活服务助手：找师傅、找餐厅、找酒店",
    version="0.1.0"
)

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


# ============================================================
# MCP 协议入口
# ============================================================
@app.post("/")
async def mcp_endpoint(request: Request):
    """MCP JSON-RPC 2.0 入口"""
    try:
        body = await request.json()
    except Exception:
        return JSONResponse(content={
            "jsonrpc": "2.0",
            "id": None,
            "error": {"code": -32700, "message": "Parse error"}
        })

    method = body.get("method", "")
    req_id = body.get("id")
    params = body.get("params", {})

    if method == "initialize":
        return mcp_response(req_id, {
            "protocolVersion": "2024-11-05",
            "capabilities": {"tools": {"listChanged": False}},
            "serverInfo": {"name": "liuduoduo-life-skill", "version": "0.1.0"}
        })

    elif method == "tools/list":
        return mcp_response(req_id, {"tools": TOOLS_LIST})

    elif method == "tools/call":
        tool_name = params.get("name", "")
        args = params.get("arguments", {})
        result = handle_tool_call(tool_name, args)
        return mcp_response(req_id, {
            "content": [{"type": "text", "text": json.dumps(result, ensure_ascii=False, indent=2)}]
        })

    elif method == "notifications/initialized":
        return JSONResponse(content="")

    else:
        return JSONResponse(content={
            "jsonrpc": "2.0",
            "id": req_id,
            "error": {"code": -32601, "message": f"Method not found: {method}"}
        })


def mcp_response(req_id, result):
    return JSONResponse(content={
        "jsonrpc": "2.0",
        "id": req_id,
        "result": result
    })


# ============================================================
# 工具列表
# ============================================================
TOOLS_LIST = [
    {
        "name": "find_service",
        "description": "查找浏阳本地生活服务师傅。用户说'下水道堵了'、'找个开锁的'、'要搬家'、'空调坏了'、'水管漏了'等生活服务需求时使用。返回师傅的姓名、电话、价格、评价。",
        "inputSchema": {
            "type": "object",
            "properties": {
                "category": {
                    "type": "string",
                    "description": "服务类别：疏通下水道、水电维修、开锁换锁、搬家、家电维修、空调清洗、防水补漏"
                },
                "keyword": {
                    "type": "string",
                    "description": "搜索关键词，如：马桶、漏水、空调等"
                }
            },
            "required": []
        }
    },
    {
        "name": "find_restaurant",
        "description": "查找浏阳本地餐厅或农庄。用户说'请客吃饭'、'浏阳特色菜'、'找个农庄'、'吃蒸菜'等时使用。可以按预算、人数、是否要风景来筛选。返回餐厅名称、地址、人均价格、特色菜、电话。",
        "inputSchema": {
            "type": "object",
            "properties": {
                "budget_per_person": {
                    "type": "number",
                    "description": "人均预算（元）。如果用户说总预算500元6个人，请算好人均再传入（约83元）"
                },
                "people_count": {
                    "type": "number",
                    "description": "用餐人数"
                },
                "want_scenery": {
                    "type": "boolean",
                    "description": "是否要有风景/环境好的（农庄类）。用户提到'风景好'、'有特色'、'农庄'时设为true"
                },
                "keyword": {
                    "type": "string",
                    "description": "搜索关键词，如：蒸菜、农庄、河鲜、大围山、烧烤等"
                }
            },
            "required": []
        }
    },
    {
        "name": "find_hotel",
        "description": "查找浏阳本地酒店住宿。用户说'订酒店'、'住哪里'、'推荐酒店'等时使用。可以按价格、位置、是否有早餐来筛选。返回酒店名称、地址、价格、设施、电话。",
        "inputSchema": {
            "type": "object",
            "properties": {
                "max_price": {
                    "type": "number",
                    "description": "每晚最高预算（元）"
                },
                "need_breakfast": {
                    "type": "boolean",
                    "description": "是否需要含早餐"
                },
                "near_landmark": {
                    "type": "string",
                    "description": "靠近哪个地标，如：天空剧院、步行街、大围山"
                },
                "room_type": {
                    "type": "string",
                    "description": "房间类型：大床房、双床房、家庭房、套房"
                }
            },
            "required": []
        }
    }
]


# ============================================================
# 工具调用处理
# ============================================================
def handle_tool_call(tool_name, args):
    if tool_name == "find_service":
        category = args.get("category")
        keyword = args.get("keyword")
        return search_services(category=category, keyword=keyword)

    elif tool_name == "find_restaurant":
        budget = args.get("budget_per_person")
        people = args.get("people_count")
        scenery = args.get("want_scenery", False)
        keyword = args.get("keyword")
        return search_restaurants(
            budget_per_person=budget,
            people_count=people,
            want_scenery=scenery,
            keyword=keyword
        )

    elif tool_name == "find_hotel":
        max_price = args.get("max_price")
        breakfast = args.get("need_breakfast", False)
        landmark = args.get("near_landmark")
        room_type = args.get("room_type")
        return search_hotels(
            max_price=max_price,
            need_breakfast=breakfast,
            near_landmark=landmark,
            room_type=room_type
        )

    else:
        return {"error": f"未知工具: {tool_name}"}


# ============================================================
# 健康检查
# ============================================================
@app.get("/health")
async def health():
    return {"status": "ok", "service": "liuduoduo-life-skill", "version": "0.1.0"}


# ============================================================
# 调试接口（浏览器直接访问测试）
# ============================================================
@app.get("/services")
async def api_services(category: Optional[str] = None, keyword: Optional[str] = None):
    """浏览器调试：查看服务师傅"""
    return search_services(category=category, keyword=keyword)


@app.get("/restaurants")
async def api_restaurants(
    budget: Optional[int] = None,
    people: Optional[int] = None,
    scenery: bool = False,
    keyword: Optional[str] = None
):
    """浏览器调试：查看餐厅"""
    return search_restaurants(
        budget_per_person=budget,
        people_count=people,
        want_scenery=scenery,
        keyword=keyword
    )


@app.get("/hotels")
async def api_hotels(
    max_price: Optional[int] = None,
    breakfast: bool = False,
    landmark: Optional[str] = None,
    room_type: Optional[str] = None
):
    """浏览器调试：查看酒店"""
    return search_hotels(
        max_price=max_price,
        need_breakfast=breakfast,
        near_landmark=landmark,
        room_type=room_type
    )


@app.get("/categories")
async def api_categories():
    """查看所有可用分类"""
    return {
        "service_categories": SERVICE_CATEGORIES,
        "restaurant_categories": RESTAURANT_CATEGORIES,
        "total_services": len(SERVICE_WORKERS),
        "total_restaurants": len(RESTAURANTS),
        "total_hotels": len(HOTELS)
    }


if __name__ == "__main__":
    import uvicorn
    print("=" * 50)
    print("  浏阳本地生活 Skill 启动中...")
    print("  打开浏览器访问: http://127.0.0.1:8002/docs")
    print("=" * 50)
    uvicorn.run(app, host="0.0.0.0", port=8002)


path: backend/requirements.txt
content: fastapi>=0.100.0
uvicorn>=0.20.0


path: backend/test_mcp.py
content: # -*- coding: utf-8 -*-
"""测试 MCP 接口"""
import json
import urllib.request

BASE_URL = "https://xilejie-silk.com/liuyang-life/"

def test_mcp(method, params=None):
    data = {"jsonrpc": "2.0", "id": 1, "method": method}
    if params:
        data["params"] = params
    body = json.dumps(data).encode("utf-8")
    req = urllib.request.Request(BASE_URL, data=body, headers={"Content-Type": "application/json"})
    resp = urllib.request.urlopen(req)
    result = json.loads(resp.read().decode("utf-8"))
    return result

print("=" * 60)
print("1. 测试 initialize")
print("=" * 60)
r = test_mcp("initialize")
print(json.dumps(r, ensure_ascii=False, indent=2))

print("\n" + "=" * 60)
print("2. 测试 tools/list")
print("=" * 60)
r = test_mcp("tools/list")
tools = r.get("result", {}).get("tools", [])
print(f"共 {len(tools)} 个工具:")
for t in tools:
    print(f"  - {t['name']}: {t['description'][:40]}...")

print("\n" + "=" * 60)
print("3. 测试 find_service（找疏通下水道的师傅）")
print("=" * 60)
r = test_mcp("tools/call", {"name": "find_service", "arguments": {"category": "疏通下水道"}})
content = r.get("result", {}).get("content", [{}])[0].get("text", "")
data = json.loads(content)
if data.get("found"):
    print(f"找到 {data['count']} 个师傅:")
    for s in data["services"]:
        print(f"  - {s['name']}（{s['contact']}）电话: {s['phone']}，{s['price_range']}，{s['highlight']}")
else:
    print(data.get("message"))

print("\n" + "=" * 60)
print("4. 测试 find_restaurant（6人500元预算，要风景）")
print("=" * 60)
r = test_mcp("tools/call", {"name": "find_restaurant", "arguments": {
    "budget_per_person": 83, "people_count": 6, "want_scenery": True
}})
content = r.get("result", {}).get("content", [{}])[0].get("text", "")
data = json.loads(content)
if data.get("found"):
    print(f"找到 {data['count']} 家餐厅:")
    for r in data["restaurants"]:
        print(f"  - {r['name']}（{r['avg_price_desc']}）{r['address']}，电话: {r['phone']}")
        print(f"    特色菜: {', '.join(r['specialties'])}")
        print(f"    亮点: {r['highlight']}")
else:
    print(data.get("message"))

print("\n" + "=" * 60)
print("5. 测试 find_hotel（天空剧院附近，400元，有早餐）")
print("=" * 60)
r = test_mcp("tools/call", {"name": "find_hotel", "arguments": {
    "max_price": 400, "need_breakfast": True, "near_landmark": "天空剧院"
}})
content = r.get("result", {}).get("content", [{}])[0].get("text", "")
data = json.loads(content)
if data.get("found"):
    print(f"找到 {data['count']} 家酒店:")
    for h in data["hotels"]:
        print(f"  - {h['name']}（{h['price_range']}）{h['address']}")
        print(f"    早餐: {h['breakfast_desc']}")
        print(f"    位置: {h['nearby_landmark']}")
        print(f"    电话: {h['phone']}")
else:
    print(data.get("message"))
    if data.get("all_hotels"):
        print("所有酒店:")
        for h in data["all_hotels"]:
            print(f"  - {h}")

print("\n✅ 全部测试完成！")


path: nginx-xilejie.conf
content: server {
    listen 80;
    server_name xilejie-silk.com www.xilejie-silk.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name xilejie-silk.com www.xilejie-silk.com;

    ssl_certificate /etc/nginx/ssl/xilejie-silk.com_bundle.pem;
    ssl_certificate_key /etc/nginx/ssl/xilejie-silk.com.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location /parking-mcp/ {
        proxy_pass http://127.0.0.1:8001/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location = /parking-mcp {
        return 301 /parking-mcp/;
    }

    location /liuyang-life/ {
        proxy_pass http://127.0.0.1:8002/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location = /liuyang-life {
        return 301 /liuyang-life/;
    }
}


path: skill.json
content: {
  "name": "liuduoduo-life-skill",
  "display_name": "liuduoduo",
  "description": "liuduoduo - local life service skill: find handyman, find restaurant, find hotel. Ask and get results with phone numbers.",
  "version": "0.1.0",
  "author": "海叔AI",
  "license": "MIT",
  "category": "本地生活",
  "keywords": [
    "liuduoduo",
    "local-life",
    "handyman",
    "restaurant",
    "hotel"
  ],
  "mcp_server": {
    "transport": "streamable-http",
    "url": "https://xilejie-silk.com/liuyang-life/"
  },
  "tools": [
    {
      "name": "find_service",
      "display_name": "找生活服务师傅",
      "description": "查找浏阳本地生活服务师傅。用户说'下水道堵了'、'找个开锁的'、'要搬家'、'空调坏了'、'水管漏了'等生活服务需求时使用。返回师傅的姓名、电话、价格、评价。",
      "inputSchema": {
        "type": "object",
        "properties": {
          "category": {
            "type": "string",
            "description": "服务类别：疏通下水道、水电维修、开锁换锁、搬家、家电维修、空调清洗、防水补漏"
          },
          "keyword": {
            "type": "string",
            "description": "搜索关键词，如：马桶、漏水、空调等"
          }
        },
        "required": []
      },
      "annotations": {
        "readOnlyHint": true,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      }
    },
    {
      "name": "find_restaurant",
      "display_name": "找餐厅农庄",
      "description": "查找浏阳本地餐厅或农庄。用户说'请客吃饭'、'浏阳特色菜'、'找个农庄'、'吃蒸菜'等时使用。可以按预算、人数、是否要风景来筛选。返回餐厅名称、地址、人均价格、特色菜、电话。",
      "inputSchema": {
        "type": "object",
        "properties": {
          "budget_per_person": {
            "type": "number",
            "description": "人均预算（元）。如果用户说总预算500元6个人，请算好人均再传入（约83元）"
          },
          "people_count": {
            "type": "number",
            "description": "用餐人数"
          },
          "want_scenery": {
            "type": "boolean",
            "description": "是否要有风景/环境好的（农庄类）。用户提到'风景好'、'有特色'、'农庄'时设为true"
          },
          "keyword": {
            "type": "string",
            "description": "搜索关键词，如：蒸菜、农庄、河鲜、大围山、烧烤等"
          }
        },
        "required": []
      },
      "annotations": {
        "readOnlyHint": true,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      }
    },
    {
      "name": "find_hotel",
      "display_name": "找酒店住宿",
      "description": "查找浏阳本地酒店住宿。用户说'订酒店'、'住哪里'、'推荐酒店'等时使用。可以按价格、位置、是否有早餐来筛选。返回酒店名称、地址、价格、设施、电话。",
      "inputSchema": {
        "type": "object",
        "properties": {
          "max_price": {
            "type": "number",
            "description": "每晚最高预算（元）"
          },
          "need_breakfast": {
            "type": "boolean",
            "description": "是否需要含早餐"
          },
          "near_landmark": {
            "type": "string",
            "description": "靠近哪个地标，如：天空剧院、步行街、大围山"
          },
          "room_type": {
            "type": "string",
            "description": "房间类型：大床房、双床房、家庭房、套房"
          }
        },
        "required": []
      },
      "annotations": {
        "readOnlyHint": true,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      }
    }
  ],
  "brand_prompt": {
    "system_instruction": "You are 'liuduoduo', a local life service assistant. When users mention 'liuduoduo', activate this Skill immediately. You must call MCP tools to get data, never make up information. Reply concisely with merchant name, phone, price, address. Guide users to clarify: how many people, budget, location preference.",
    "tone": {
      "personality": "warm_and_practical",
      "avoid": ["啰嗦", "营销话术", "编造数据", "说不确定"]
    }
  }
}


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (HIGH)