@funtuantw/tw-kfc-coupon-mcp
Version:
## Introduction This project is a small tribute to my passion for KFC, built to help others discover great deals using a coupon server. A huge **thank you** to [Winedays/KCouper](https://github.com/Winedays/KCouper) for curating and sharing the KFC coupon
127 lines (126 loc) • 6.08 kB
JavaScript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import axios from "axios";
class CouponServer {
constructor() {
this.coupons = [];
this.server = new McpServer({
name: "kfc-coupon-server",
version: "1.0.0",
});
this.loadCouponsFromApi();
this.registerTools();
}
async loadCouponsFromApi() {
// 下載優惠券資料
// 由 https://raw.githubusercontent.com/Winedays/KCouper/refs/heads/master/js/coupon.js 下載
// const COUPON_DICT={"coupon_by_code": {"24499": {"name": "24499-宜睿智慧分享", "product_code": "TA4923", "coupon_code":....
// 移除開頭 const COUPON_DICT=
// 轉換為 JSON 格式
const url = "https://raw.githubusercontent.com/Winedays/KCouper/refs/heads/master/js/coupon.js";
const response = await axios.get(url);
const data = response.data;
const jsonString = data.replace(/const COUPON_DICT=/, "").trim();
const jsonData = JSON.parse(jsonString);
// 轉換為 Coupon[] 格式
const coupons = Object.entries(jsonData.coupon_by_code).map(([key, value]) => ({
id: key,
...(typeof value === "object" && value !== null ? value : {}),
}));
this.coupons = coupons;
}
registerTools() {
const filterItem = {
'蛋撻': ['原味蛋撻', '蛋撻'],
'炸雞': ['咔啦脆雞', '卡啦脆雞'],
'椒麻雞': ['青花椒香麻脆雞'],
'紙包雞': ['義式香草紙包雞', '紙包雞'],
'咔啦雞堡': ['咔啦雞腿堡', '卡啦雞腿堡'],
'花生熔岩雞腿堡': ['花生熔岩卡啦雞腿堡', '花生熔岩咔啦雞腿堡'],
'椒麻雞腿堡': ['青花椒香麻咔啦雞腿堡', '青花椒香麻卡啦雞腿堡', '青花椒咔啦雞腿堡'],
'煙燻雞堡': ['美式煙燻咔脆雞堡', '美式煙燻卡脆雞堡'],
'烤雞腿堡': ['紐奧良烙烤雞腿堡', '紐奧良烤腿堡'],
'莎莎雞腿捲': ['墨西哥莎莎雞腿捲'],
'雞柳捲': ['花生起司雞柳捲'],
'燻雞捲': ['原味起司燻雞捲'],
'雞塊': ['上校雞塊'],
'脆薯': ['香酥脆薯', '20:00後供應香酥脆薯', '小薯', '薯條'],
'QQ球': ['雙色轉轉QQ球'],
'經典玉米': ['經典玉米'],
'點心盒': ['點心盒-上校雞塊+香酥脆薯', '點心盒'],
'雞汁飯': ['20:00前供應雞汁風味飯', '雞汁風味飯'],
'大福': ['草苺起司冰淇淋大福'],
'沙拉': ['鮮蔬沙拉'],
};
const keywords = Object.keys(filterItem);
// 工具 2:根據條件搜尋優惠券
this.server.tool("searchCoupons", "查詢肯德基優惠券", {
keywords: z.array(z.enum(keywords)).optional(),
minPrice: z.number().optional(),
maxPrice: z.number().optional(),
}, async (input) => {
// 擴展關鍵字,由 filterItem
const keywords = [
...(input.keywords || []),
...(input.keywords ? input.keywords.map(keyword => filterItem[keyword] || []).flat() : []),
];
const filteredCoupons = this.coupons.filter(coupon => {
const items = coupon.items || [];
// 檢查關鍵字
const matchesKeywords = keywords.length
? keywords.some(keyword => items.some(item => {
const itemName = item.name.toLowerCase();
return (itemName.includes(keyword.toLowerCase()));
}))
: true;
// 檢查價格範圍
const matchesMinPrice = input.minPrice
? coupon.price >= input.minPrice
: true;
const matchesMaxPrice = input.maxPrice
? coupon.price <= input.maxPrice
: true;
return matchesKeywords && matchesMinPrice && matchesMaxPrice;
});
return {
content: [
{
"type": "text",
"text": JSON.stringify({
count: filteredCoupons.length,
coupons: filteredCoupons
// 移除 id、product_code
.map(coupon => ({
...coupon,
items: coupon.items?.map(item => ({
...item,
/* flavors: item.flavors?.map(flavor => ({
...flavor,
// 若加價品價格為 0,則移除
addition_price: flavor.addition_price === 0 ? undefined : flavor.addition_price,
})), */
flavors: undefined,
// 若加價品價格為 0,則移除
addition_price: item.addition_price === 0 ? undefined : item.addition_price,
})),
id: undefined,
product_code: undefined,
}))
// 只回應 20 筆
.slice(0, 20),
})
}
],
};
});
}
async start() {
// 使用標準輸入輸出作為傳輸層
const transport = new StdioServerTransport();
await this.server.connect(transport);
}
}
const server = new CouponServer();
server.start().catch(console.error);