SURIAPRAKASH1 commited on
Commit
ca32e0f
·
1 Parent(s): b66a0d6

tools for cricket

Browse files
Files changed (1) hide show
  1. main.py +98 -7
main.py CHANGED
@@ -1,8 +1,9 @@
1
- from typing import Any
2
  from mcp.server.fastmcp import FastMCP
3
  import httpx
4
 
5
- import logging, os
 
 
6
  from dotenv import load_dotenv
7
  load_dotenv()
8
 
@@ -11,23 +12,24 @@ load_dotenv()
11
  # Logging
12
  # ------------
13
  logger = logging.getLogger(__name__)
 
14
 
15
  # formatter
16
  fmt = logging.Formatter("%(asctime)s -- %(name)s -- %(levelname)s -- %(message)s")
17
 
18
  # handlers
19
- console_handler = logging.StreamHandler()
20
- file_handler = logging.FileHandler()
21
 
22
  # add to logger
23
- logger.addHandler(console_handler)
24
  logger.addHandler(file_handler.setFormatter(fmt))
25
 
26
 
27
  # --------------
28
  # Configuration
29
  #---------------
30
- BASE_CRICKET_URI = os.environ.get("BASE_CRICKET_URI", "False")
31
 
32
 
33
  # -------------------------
@@ -38,4 +40,93 @@ mcp = FastMCP("multitools-server")
38
 
39
  # ----------------------
40
  # Available tools for LLM
41
- # -----------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  from mcp.server.fastmcp import FastMCP
2
  import httpx
3
 
4
+ from typing import Any, Literal
5
+ from bs4 import BeautifulSoup
6
+ import logging, os, json
7
  from dotenv import load_dotenv
8
  load_dotenv()
9
 
 
12
  # Logging
13
  # ------------
14
  logger = logging.getLogger(__name__)
15
+ logger.setLevel(logger.debug)
16
 
17
  # formatter
18
  fmt = logging.Formatter("%(asctime)s -- %(name)s -- %(levelname)s -- %(message)s")
19
 
20
  # handlers
21
+ # console_handler = logging.StreamHandler()
22
+ file_handler = logging.FileHandler(filename= "multitools-server.log")
23
 
24
  # add to logger
25
+ # logger.addHandler(console_handler)
26
  logger.addHandler(file_handler.setFormatter(fmt))
27
 
28
 
29
  # --------------
30
  # Configuration
31
  #---------------
32
+ BASE_CRICKET_URL = os.environ.get("BASE_CRICKET_URI", "False")
33
 
34
 
35
  # -------------------------
 
40
 
41
  # ----------------------
42
  # Available tools for LLM
43
+ # -----------------------
44
+
45
+ async def cricket_source(mode: str) -> str:
46
+ """Fetches whole html from source url then extracts html container that contains necessary details"""
47
+
48
+ if mode == "live":
49
+ url = f"{BASE_CRICKET_URL}/cricket-match/live-scores"
50
+ elif mode == 'upcomming':
51
+ url = f"{BASE_CRICKET_URL}/cricket-match/live-scores/upcoming-matches"
52
+ else:
53
+ error = f"Not Implemented: Currently there's no implementation to handle {mode}. Only handels live, upcomming"
54
+ logger.error(msg= error)
55
+ return json.dumps({"error": error})
56
+
57
+ try:
58
+ async with httpx.AsyncClient(timeout= 10.0) as client:
59
+ response = await client.get(url= url)
60
+ response.raise_for_status() # if not 2xx it will raise HTTP error
61
+ except httpx.HTTPError as e:
62
+ logger.error("\n%s", e)
63
+ return json.dumps({'error': str(e)})
64
+ except Exception as e:
65
+ logger.error("\n%s", e)
66
+ return json.dumps({'error': str(e)})
67
+
68
+ if response:
69
+ # convert htmldoc content to proper html form using bs
70
+ html = BeautifulSoup(response.content, "html.parser")
71
+ # find where the content is
72
+ content = html.find("div", class_= 'cb-col cb-col-100 cb-rank-tabs')
73
+ return content
74
+ else:
75
+ return json.dumps({"error": "No Available details right now!"})
76
+
77
+ @mcp.tool()
78
+ async def fetch_live_cricket_details(mode: Literal["live", "upcomming"])-> str:
79
+ """ Get cricket live or upcomming match details
80
+ Args:
81
+ mode : Either "live" or "upcomming"
82
+ """
83
+
84
+ response = await cricket_source(mode.strip().lower())
85
+ if response['error']:
86
+ return response
87
+ live_details = response.get_text(separator = "\n", strip = True)
88
+ return json.dumps({'output': str(live_details)})
89
+
90
+ @mcp.resource("resource://scorecard_herf")
91
+ async def live_cricket_scorecard_herf()-> str:
92
+ """Returns string of comma separated anchor tags contains herf attributes that pointing to live cricket scorecards """
93
+
94
+ response = await cricket_source("live")
95
+ if response['error']:
96
+ return response
97
+ herfs_list = response.find_all("a", class_ = "cb-text-link cb-mtch-lnks")
98
+ herfs_string = ",".join(str(tag) for tag in herfs_list)
99
+ return json.dumps({'output': herfs_string})
100
+
101
+
102
+ @mcp.tool()
103
+ async def live_cricket_scorecard(herf: str)-> str:
104
+ """Live cricket match scorecard details for given herf.
105
+ (e.g, herf = "/live-cricket-scorecard/119495/cd-vs-hbh-7th-match-global-super-league-2025")
106
+
107
+ Args:
108
+ herf (str): herf for scorescard endpoint
109
+ """
110
+ scorecard_url = f"{BASE_CRICKET_URL}{herf}"
111
+
112
+ try:
113
+ with httpx.AsyncClient(timeout= 10.0) as client:
114
+ response = client.get(url = scorecard_url)
115
+ response.raise_for_status()
116
+ except httpx.HTTPError as e:
117
+ logger.error("\n%s", e)
118
+ return json.dumps({"error": str(e)})
119
+ except Exception as e:
120
+ logger.error("\n%s", e)
121
+ return json.dumps({'error': str(e)})
122
+
123
+ # extract html container
124
+ if response:
125
+ html = BeautifulSoup(response.content, "html.parser")
126
+ live_scorecard = html.find("div", timeout = "30000")
127
+ details = live_scorecard.get_text(separator="\n", strip=True)
128
+ return json.dumps({'output': str(details)})
129
+ else:
130
+ return json.dumps({'error': "No Available details right now"})
131
+
132
+