Skip to main content
Glama
wrdan

MCP Canteen Server

by wrdan

get_canteen_data

Retrieve cafeteria dining attendance data, including breakfast and lunch counts, within a specified date range using the MCP Canteen Server.

Instructions

获取餐厅就餐人数数据

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
end_dateNo
periodNo
start_dateNo

Implementation Reference

  • Main handler function implementing the 'get_canteen_data' tool logic: processes input dates/period, fetches data from external API, formats and returns canteen attendance statistics.
    @mcp.tool()
    async def get_canteen_data(start_date: str = None, end_date: str = None, period: str = None) -> str:
        """获取餐厅就餐人数数据"""
        valid_periods = ['today', 'yesterday', 'day_before_yesterday', 'this_week', 'last_week', 'this_month', 'last_month']
        
        if period and period in valid_periods:
            start_date, end_date = get_relative_dates(period)
        elif period:
            logger.warning(f"不支持的时间范围: {period},将使用指定的日期范围")
            if not start_date or not end_date:
                # 如果没有指定日期范围,则使用今天
                start_date, end_date = get_relative_dates('today')
        elif not start_date or not end_date:
            # 如果没有提供日期参数,默认查询今天的数据
            start_date, end_date = get_relative_dates('today')
        
        # 转换日期格式
        try:
            start_date = convert_date_format(start_date)
            end_date = convert_date_format(end_date)
        except ValueError as e:
            raise ValueError(f"日期格式转换失败: {str(e)}")
        
        # 验证转换后的日期格式
        if not all(validate_date(date) for date in [start_date, end_date]):
            raise ValueError("日期格式不正确,请使用YYYYMMDD格式")
        
        url = f"{API_BASE}/rsdata/totalnumberofconsumers?startTime={start_date}&endTime={end_date}"
        
        try:
            data = await make_api_request(url)
            
            if not data or "success" not in data or not data["success"]:
                error_msg = data.get("error", "未知错误") if isinstance(data, dict) else "请求失败"
                raise CanteenAPIError(f"API返回错误: {error_msg}")
            
            morning_count = data["data"]["morningCount"]
            afternoon_count = data["data"]["afternoonCount"]
            total_count = morning_count + afternoon_count
            
            period_titles = {
                'today': '今日',
                'yesterday': '昨日',
                'day_before_yesterday': '前天',
                'this_week': '本周',
                'last_week': '上周',
                'this_month': '本月',
                'last_month': '上月'
            }
            
            title = period_titles.get(period, f"{start_date} 至 {end_date}")
            
            return f"""
    餐厅就餐人数统计 ({title}):
    日期范围: {start_date} 至 {end_date}
    早餐人数: {morning_count} 人
    午餐人数: {afternoon_count} 人
    总计: {total_count} 人
    """
        except CanteenAPIError as e:
            logger.error(f"获取餐厅数据失败: {str(e)}")
            raise
        except Exception as e:
            logger.error(f"处理餐厅数据时发生错误: {str(e)}")
            raise CanteenAPIError(f"处理数据失败: {str(e)}")
  • FastMCP decorator registering the get_canteen_data function as a tool.
    @mcp.tool()
  • Helper function to calculate start and end dates based on relative periods like 'today', 'this_week', etc.
    def get_relative_dates(period: str) -> Tuple[str, str]:
        """获取相对时间范围的开始和结束日期"""
        today = datetime.now()
        
        if period == 'today':
            return (today.strftime('%Y%m%d'), today.strftime('%Y%m%d'))
        elif period == 'yesterday':
            yesterday = today - timedelta(days=1)
            return (yesterday.strftime('%Y%m%d'), yesterday.strftime('%Y%m%d'))
        elif period == 'day_before_yesterday':
            day_before_yesterday = today - timedelta(days=2)
            return (day_before_yesterday.strftime('%Y%m%d'), day_before_yesterday.strftime('%Y%m%d'))
        elif period == 'this_week':
            monday = today - timedelta(days=today.weekday())
            return (monday.strftime('%Y%m%d'), today.strftime('%Y%m%d'))
        elif period == 'last_week':
            last_monday = today - timedelta(days=today.weekday() + 7)
            last_sunday = last_monday + timedelta(days=6)
            return (last_monday.strftime('%Y%m%d'), last_sunday.strftime('%Y%m%d'))
        elif period == 'this_month':
            first_day = today.replace(day=1)
            return (first_day.strftime('%Y%m%d'), today.strftime('%Y%m%d'))
        elif period == 'last_month':
            first_day_last_month = (today.replace(day=1) - timedelta(days=1)).replace(day=1)
            last_day_last_month = today.replace(day=1) - timedelta(days=1)
            return (first_day_last_month.strftime('%Y%m%d'), last_day_last_month.strftime('%Y%m%d'))
        else:
            logger.warning(f"不支持的时间范围: {period},将使用今天的数据")
            return (today.strftime('%Y%m%d'), today.strftime('%Y%m%d'))
  • Helper function to make authenticated HTTP GET requests to the canteen API with error handling.
    async def make_api_request(url: str) -> Dict[str, Any]:
        """向API发送请求并处理错误"""
        headers = {
            "Authorization": AUTH_TOKEN,
            "Accept": "application/json"
        }
        
        try:
            async with httpx.AsyncClient(timeout=TIMEOUT) as client:
                response = await client.get(url, headers=headers)
                response.raise_for_status()
                return response.json()
        except httpx.HTTPError as e:
            logger.error(f"HTTP请求错误: {str(e)}")
            raise CanteenAPIError(f"HTTP请求失败: {str(e)}")
        except Exception as e:
            logger.error(f"未知错误: {str(e)}")
            raise CanteenAPIError(f"请求失败: {str(e)}")
  • Helper function to parse and convert various natural language and formatted date strings to standardized YYYYMMDD format.
    def convert_date_format(date_str: str) -> str:
        """将各种日期格式转换为YYYYMMDD格式"""
        if not date_str:
            return None
            
        # 如果已经是YYYYMMDD格式,直接返回
        if len(date_str) == 8 and date_str.isdigit():
            return date_str
            
        # 处理相对日期(只处理简单的相对日期)
        today = datetime.now()
        if date_str.lower() == 'today':
            return today.strftime('%Y%m%d')
        elif date_str.lower() == 'yesterday':
            yesterday = today - timedelta(days=1)
            return yesterday.strftime('%Y%m%d')
        elif date_str.lower() == 'day_before_yesterday':
            day_before_yesterday = today - timedelta(days=2)
            return day_before_yesterday.strftime('%Y%m%d')
            
        # 清理输入字符串
        date_str = date_str.strip()
        
        # 处理"号"的情况
        if "号" in date_str:
            date_str = date_str.replace("号", "日")
        
        # 尝试不同的日期格式
        date_formats = [
            # 完整日期格式
            "%Y-%m-%d",  # 2024-04-01
            "%Y/%m/%d",  # 2024/04/01
            "%Y.%m.%d",  # 2024.04.01
            "%Y年%m月%d日",  # 2024年04月01日
            # 无年份格式
            "%m月%d日",  # 04月01日
            "%m-%d",  # 04-01
            "%m/%d",  # 04/01
            "%m.%d",  # 04.01
            # 年月格式
            "%Y-%m",  # 2024-04
            "%Y/%m",  # 2024/04
            "%Y年%m月",  # 2024年04月
        ]
        
        current_year = datetime.now().year
        
        for fmt in date_formats:
            try:
                date = datetime.strptime(date_str, fmt)
                # 如果是无年份格式,添加当前年份
                if fmt in ["%m月%d日", "%m-%d", "%m/%d", "%m.%d"]:
                    date = date.replace(year=current_year)
                # 如果是年月格式,添加当月第一天
                elif fmt in ["%Y-%m", "%Y/%m", "%Y年%m月"]:
                    date = date.replace(day=1)
                return date.strftime("%Y%m%d")
            except ValueError:
                continue
                
        # 如果所有格式都失败,尝试直接解析数字
        try:
            # 移除所有非数字字符
            clean_date = ''.join(filter(str.isdigit, date_str))
            if len(clean_date) == 8:
                # 验证日期是否有效
                datetime.strptime(clean_date, "%Y%m%d")
                return clean_date
        except ValueError:
            pass
                
        raise ValueError(f"无法识别的日期格式: {date_str}")
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. The description only states it 'gets data' without revealing whether this is a read-only operation, whether it requires authentication, what rate limits might apply, what format the data returns in, or any error conditions. For a data retrieval tool with 3 parameters and no annotation coverage, this is insufficient behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise - a single Chinese phrase that directly states the tool's function. There's no wasted language or unnecessary elaboration. While it may be too brief for complete understanding, as a standalone statement it's efficiently structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has 3 parameters with 0% schema coverage, no annotations, no output schema, and no sibling tools, the description is incomplete. It doesn't explain what the parameters mean, what data format is returned, any behavioral constraints, or usage context. For a data retrieval tool with multiple filtering parameters, this minimal description leaves too many unanswered questions.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema description coverage is 0%, meaning none of the 3 parameters (start_date, end_date, period) have descriptions in the schema. The tool description provides absolutely no information about these parameters - it doesn't mention date ranges, time periods, or any filtering criteria. The description fails to compensate for the complete lack of schema documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description '获取餐厅就餐人数数据' (Get canteen dining population data) states a clear purpose - retrieving data about restaurant/canteen attendance. It includes a verb ('获取' - get) and resource ('餐厅就餐人数数据' - canteen dining population data). However, it's somewhat vague about what specific data is returned (just 'data' without specifying format or granularity) and since there are no sibling tools, we cannot assess differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. There are no sibling tools mentioned, so no comparison is possible, but the description doesn't indicate any prerequisites, constraints, or typical use cases. It simply states what the tool does without context about appropriate usage scenarios.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/wrdan/mcp-canteen-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server