#
tokens: 2144/50000 6/6 files
lines: on (toggle) GitHub
raw markdown copy reset
# Directory Structure

```
├── .gitignore
├── .python-version
├── main.py
├── odds.py
├── pyproject.toml
├── README.md
└── uv.lock
```

# Files

--------------------------------------------------------------------------------
/.python-version:
--------------------------------------------------------------------------------

```
1 | 3.12
2 | 
```

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
 1 | # Python-generated files
 2 | __pycache__/
 3 | *.py[oc]
 4 | build/
 5 | dist/
 6 | wheels/
 7 | *.egg-info
 8 | 
 9 | # Virtual environments
10 | .venv
11 | 
12 | .env
13 | 
```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
1 | degen claude. 
2 | just need a way for llms to have access to money and place bets...
3 | 
4 | 
```

--------------------------------------------------------------------------------
/main.py:
--------------------------------------------------------------------------------

```python
1 | def main():
2 |     print("Hello from degen-mcp!")
3 | 
4 | 
5 | if __name__ == "__main__":
6 |     main()
7 | 
```

--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------

```toml
 1 | [project]
 2 | name = "degen-mcp"
 3 | version = "0.1.0"
 4 | description = "Add your description here"
 5 | readme = "README.md"
 6 | requires-python = ">=3.12"
 7 | dependencies = [
 8 |     "httpx>=0.28.1",
 9 |     "mcp[cli]>=1.3.0",
10 | ]
11 | 
```

--------------------------------------------------------------------------------
/odds.py:
--------------------------------------------------------------------------------

```python
  1 | import httpx
  2 | import os
  3 | from mcp.server.fastmcp import FastMCP
  4 | from dotenv import load_dotenv
  5 | from typing import Any
  6 | 
  7 | load_dotenv()
  8 | 
  9 | API_KEY = os.getenv("api_key")
 10 | 
 11 | API_BASE_URL = "https://api.the-odds-api.com/v4/sports"
 12 | USER_AGENT = "the-odds-api/1.0"
 13 | SPORT = 'upcoming' # use the sport_key from the /sports endpoint below, or use 'upcoming' to see the next 8 games across all sports
 14 | REGIONS = 'us' # uk | us | eu | au. Multiple can be specified if comma delimited
 15 | MARKETS = 'h2h,spreads' # h2h | spreads | totals. Multiple can be specified if comma delimited
 16 | ODDS_FORMAT = 'decimal' # decimal | american
 17 | DATE_FORMAT = 'iso' # iso | unix
 18 | HEADERS = {
 19 |         "User-Agent": USER_AGENT,
 20 |         "Accept": "application/json"
 21 |     }
 22 | 
 23 | #mcp server
 24 | mcp = FastMCP("odds")
 25 | 
 26 | async def make_sports_request() -> dict[str, Any] | None:
 27 |     params = {"api_key": API_KEY}
 28 | 
 29 |     async with httpx.AsyncClient() as client:
 30 |         try:
 31 |             response = await client.get(API_BASE_URL, headers=HEADERS, params=params, timeout=30.0)
 32 |             response.raise_for_status()
 33 |             return response.json()
 34 |         except Exception:
 35 |             return None
 36 | 
 37 | async def make_odds_request(sport: str, params: dict) -> dict[str, Any] | None:
 38 |     url = f'{API_BASE_URL}/{sport}/odds' # corrected url formatting  
 39 |     print('url:: ', url)
 40 | 
 41 |     async with httpx.AsyncClient() as client:
 42 |       try:
 43 |             response = await client.get(url, headers=HEADERS, params=params, timeout=30.0)
 44 |             response.raise_for_status()
 45 |             odds_json = response.json()
 46 |             print('Remaining requests', response.headers['x-requests-remaining'])
 47 |             print('Used requests', response.headers['x-requests-used'])
 48 |             return response.json()
 49 |       except Exception:
 50 |             return None
 51 | 
 52 | def print_formatted_odds(odds_data: list[dict]):
 53 |     """Prints the odds data in a formatted and readable way."""
 54 |     for game in odds_data:
 55 |         print(f"Game ID: {game['id']}")
 56 |         print(f"Sport: {game['sport_title']} ({game['sport_key']})")
 57 |         print(f"Commence Time: {game['commence_time']}")
 58 |         print(f"Home Team: {game['home_team']}")
 59 |         print(f"Away Team: {game['away_team']}")
 60 |         print("Bookmakers:")
 61 | 
 62 |         for bookmaker in game['bookmakers']:
 63 |             print(f"  {bookmaker['title']} ({bookmaker['key']}):")
 64 |             for market in bookmaker['markets']:
 65 |                 print(f"    Market: {market['key']}")
 66 |                 for outcome in market['outcomes']:
 67 |                     if 'point' in outcome:
 68 |                         print(f"      {outcome['name']}: Price: {outcome['price']}, Point: {outcome['point']}")
 69 |                     else:
 70 |                         print(f"      {outcome['name']}: Price: {outcome['price']}")
 71 |         print("-" * 40) # Separator between games
 72 | 
 73 | def format_sports_data(sports_data: dict) -> str:
 74 |     """Format sports data into a readable string."""
 75 |     return f"""
 76 | Key: {sports_data.get('key', 'Unknown')}
 77 | Group: {sports_data.get('group', 'Unknown')}
 78 | Title: {sports_data.get('title', 'Unknown')}
 79 | Description: {sports_data.get('description', 'Unknown')}
 80 | Active: {sports_data.get('active', 'Unknown')}
 81 | Has Outrights: {sports_data.get('has_outrights', 'Unknown')}
 82 | """
 83 | 
 84 | def format_odds_data(odds_data: list[dict]) -> str:
 85 |     """Formats the odds data into a readable string, similar to the provided example."""
 86 |     formatted_games = []
 87 |     for game in odds_data:
 88 |         game_forecast = f"""
 89 | Sport: {game['sport_title']} ({game['sport_key']})
 90 | Home Team: {game['home_team']}
 91 | Away Team: {game['away_team']}
 92 | Commence Time: {game['commence_time']}
 93 | """
 94 | 
 95 |         bookmaker_forecasts = []
 96 |         for bookmaker in game['bookmakers']:
 97 |             bookmaker_info = f"  {bookmaker['title']} ({bookmaker['key']}):"
 98 |             market_forecasts = []
 99 |             for market in bookmaker['markets']:
100 |                 market_info = f"    Market: {market['key']}"
101 |                 outcome_forecasts = []
102 |                 for outcome in market['outcomes']:
103 |                     if 'point' in outcome:
104 |                         outcome_info = f"      {outcome['name']}: Price: {outcome['price']}, Point: {outcome['point']}"
105 |                     else:
106 |                         outcome_info = f"      {outcome['name']}: Price: {outcome['price']}"
107 |                     outcome_forecasts.append(outcome_info)
108 |                 market_forecast = f"{market_info}\n" + "\n".join(outcome_forecasts)
109 |                 market_forecasts.append(market_forecast)
110 |             bookmaker_forecast = f"{bookmaker_info}\n" + "\n".join(market_forecasts)
111 |             bookmaker_forecasts.append(bookmaker_forecast)
112 | 
113 |         game_forecast += "\n".join(bookmaker_forecasts)
114 |         formatted_games.append(game_forecast)
115 |         # print_formatted_odds(odds_data)
116 |         print(formatted_games)
117 | 
118 |     return "\n---\n".join(formatted_games)
119 | 
120 | 
121 | @mcp.tool()
122 | async def get_in_season_sports() -> str:
123 | 
124 |     sports = await make_sports_request()
125 | 
126 |     if not sports:
127 |         return "failed to get sports" 
128 | 
129 |     results = [format_sports_data(sport) for sport in sports]
130 |     return "\n---\n".join(results)
131 | 
132 | @mcp.tool()
133 | async def get_odds(sport: str, params: dict) -> str:
134 | 
135 |     odds_json = await make_odds_request(sport, params)
136 | 
137 |     if not odds_json:
138 |         return "failed to get odds" 
139 | 
140 |     return "\n---\n".join(format_odds_data(odds_json))
141 | 
142 | 
143 | import asyncio
144 | if __name__ == "__main__":
145 |         mcp.run(transport='stdio')
```