class QueryOutboundDetailTool: name = 'query_outbound_detail' route_path = '/mcp/tools/queryOutboundDetail' def __init__(self, api_client=None): self.api_client = api_client def metadata(self): return { 'name': self.name, 'description': ( '使用场景:用户明确要查看一张排舱单的排舱详情,并明确提供排舱单号时' '使用。返回第一层11项汇总和第二层34项订单明细,包括明细表中的报关资料。' '只接受排舱单号,不接受订单号、柜号、SO号、提单号或数据库ID。用户明确' '要看排舱详情但只提供订单号时,应先用query_outbound_list按订单号定位;' '多条命中必须让用户选择。号码类型不明确时必须先询问用户。' '禁止使用:用户要看排舱列表、订单资料、物流轨迹或仅查看报关资料文件链接' '时不得使用本工具。不得根据号码格式猜测,不得跨字段或跨工具试查,' '查询无结果后不得把同一号码改作其他类型重试。' '公司、员工和权限范围由当前设备会话确定。参数名仅用于工具调用;' '向用户回答时只能展示中文业务名称,不得展示内部参数名。' ), 'input_schema': { 'type': 'object', 'properties': { 'outbound_number': { 'type': 'string', 'minLength': 1, 'maxLength': 100, 'description': '排舱单号,不是订单号、柜号、SO号或数据库ID。', }, 'page': { 'type': 'integer', 'minimum': 1, 'maximum': 100, 'default': 1, }, 'limit': { 'type': 'integer', 'minimum': 1, 'maximum': 20, 'default': 10, }, }, 'required': ['outbound_number'], 'additionalProperties': False, }, } def call( self, outbound_number=None, page=1, limit=10, request_id='rq_query_outbound_detail', ): if self.api_client is None: raise RuntimeError('api client is required for query_outbound_detail') if not isinstance(outbound_number, str): raise ValueError('outbound_number is required') outbound_number = outbound_number.strip() if not outbound_number or len(outbound_number) > 100: raise ValueError('outbound_number is required') page = self._bounded_integer(page, 'page', 100) limit = self._bounded_integer(limit, 'limit', 20) return self.api_client.call_tool( self.name, self.route_path, { 'outbound_number': outbound_number, 'page': page, 'limit': limit, }, request_id, ) @staticmethod def _bounded_integer(value, field, maximum): if isinstance(value, bool): raise ValueError('{0} is invalid'.format(field)) try: value = int(value) except (TypeError, ValueError): raise ValueError('{0} is invalid'.format(field)) if value < 1 or value > maximum: raise ValueError('{0} is invalid'.format(field)) return value