MCP Server
Expose any configured Opensport provider as an MCP (Model Context Protocol) server. Any MCP-compatible host can then call six tools to query events, read odds, and find value bets.
Overview
The MCP server ships as an optional extra. It runs over stdio and is configured entirely via environment variables using the same ProviderRegistry.from_env() mechanism as the Python SDK. No additional configuration is required.
| Tool | Description |
|---|---|
list_providers | List configured providers and their enabled/disabled status. |
get_events | List upcoming events. Filter by sport, competition, or status. |
find_events | Search for events by team or player name (substring match). |
get_odds | Fetch current odds for a specific event ID. |
get_value_bets | Scan all upcoming events and return positive-EV outcomes sorted by edge. |
get_live_score | Get the current in-play score for a live event. |
Installation
pip install 'opensport[mcp]'This installs the mcp package alongside Opensport and registers the opensport-mcp command.
Running the server
# Set whichever provider env vars you need (see Providers reference)
export MASSEY_SPORTS=nfl,nba
export CLOUDBET_API_KEY=your-key
# Start the stdio MCP server
opensport-mcp
# Or run as a Python module
python -m opensport.mcp_serverWith no env vars set, MockProvider is always available, so the server starts and responds to all six tools immediately, with no API keys and no network access.
Claude Desktop configuration
Add the server to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"opensport": {
"command": "opensport-mcp",
"env": {
"MASSEY_SPORTS": "nfl,nba,mlb",
"CLOUDBET_API_KEY": "your-cloudbet-key",
"POLYMARKET_ENABLED": "1"
}
}
}
}Restart Claude Desktop after saving. The six Opensport tools will appear in the tools panel.
Tool reference
list_providers
Returns the name and enabled status of every registered provider.
# No parameters required
# Example response:
{
"providers": [
{ "name": "mock", "enabled": true },
{ "name": "massey", "enabled": true },
{ "name": "cloudbet","enabled": false }
]
}get_events
| Parameter | Type | Description |
|---|---|---|
sport | string | Sport slug, e.g. soccer, nfl. Omit for all sports. |
competition | string | Competition name filter, e.g. Premier League. |
status | string | scheduled, live, or completed. |
limit | integer | Max events to return (default: 20). |
# Example response:
{
"count": 3,
"total": 12,
"events": [
{
"id": "mock_soccer_000",
"summary": "Arsenal vs Chelsea | Premier League | 2024-03-15 20:00 UTC | SCHEDULED",
"sport": "soccer",
"competition": "Premier League",
"start_time": "2024-03-15T20:00:00",
"status": "scheduled"
}
]
}find_events
| Parameter | Type | Description |
|---|---|---|
team (required) | string | Team or player name fragment, e.g. Arsenal, Lakers. |
sport | string | Restrict to a sport slug. |
limit | integer | Max events to return (default: 10). |
get_odds
| Parameter | Type | Description |
|---|---|---|
event_id (required) | string | Event ID from get_events or find_events. |
# Example response:
{
"event_id": "mock_soccer_000",
"fetched_at": "2024-03-15T19:55:00",
"markets": [
{
"market_type": "winner",
"overround": 1.048,
"margin_pct": 4.8,
"outcomes": [
{ "label": "Home", "decimal_odds": 2.10, "implied_prob": 0.476, "bookmaker": "mock", "is_available": true },
{ "label": "Draw", "decimal_odds": 3.40, "implied_prob": 0.294, "bookmaker": "mock", "is_available": true },
{ "label": "Away", "decimal_odds": 4.20, "implied_prob": 0.238, "bookmaker": "mock", "is_available": true }
]
}
]
}get_value_bets
| Parameter | Type | Description |
|---|---|---|
sport | string | Restrict scan to a sport slug. Omit for all sports. |
min_edge_pct | number | Minimum edge as a percentage (default: 3.0 = 3%). |
market_type | string | Market to scan (default: winner). |
limit | integer | Max results (default: 10). |
# Example response:
{
"count": 2,
"total": 2,
"value_bets": [
{
"event_id": "mock_soccer_002",
"event_summary": "Liverpool vs Man United | Premier League | 2024-03-16 15:00 UTC | SCHEDULED",
"sport": "soccer",
"competition": "Premier League",
"start_time": "2024-03-16T15:00:00",
"market_type": "winner",
"outcome_label": "Home",
"decimal_odds": 2.20,
"bookmaker": "mock",
"fair_prob": 0.4762,
"implied_prob": 0.4545,
"edge_pct": 4.76
}
]
}get_live_score
| Parameter | Type | Description |
|---|---|---|
event_id (required) | string | Event ID of a live (in-play) event. |
Returns a provider-specific score dict. Providers that do not support live scores return an empty object. See the Providers reference for per-provider live score support.
Utility functions
The same logic used by the MCP server is available directly from Python without running a server process.
Event.summary()
Returns a compact one-line string for any Event, suitable for pasting into an LLM context window.
from opensport.providers.mock import MockProvider
provider = MockProvider(seed=42)
events = provider.get_events(sport="soccer")
print(events[0].summary())
# Arsenal vs Chelsea | Premier League | 2024-03-15 20:00 UTC | SCHEDULEDBaseProvider.find_events()
Every provider inherits find_events(), which performs a case-insensitive substring search across all participant names.
events = provider.find_events(team="arsenal", sport="soccer")
for e in events:
print(e.summary())get_value_bets()
Scans all upcoming events from a provider (or MultiProvider) and returns outcomes where the offered odds imply positive expected value vs the no-vig fair price.
from opensport.utils import get_value_bets
from opensport.providers.mock import MockProvider
bets = get_value_bets(MockProvider(seed=42), sport="soccer", min_edge_pct=0.02)
for b in bets:
print(f"{b['event_summary']}")
print(f" {b['outcome_label']} @ {b['decimal_odds']:.2f} edge={b['edge_pct']:.1f}%")