Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Openfield MCP Server

An MCP (Model Context Protocol) server that gives AI agents direct access to the Catapult Openfield Connect API v6. Query athlete GPS sensor data, session analytics, team rosters, performance stats, and more - all through natural language.

81 tools covering activities, athletes, 10Hz sensor data, aggregated stats, teams, periods, parameters, annotations, venues, live tracking, threshold sets, and webhooks.

Recommended clients: Claude Code or OpenClaw. This server exposes 81 tools and can make multiple API calls per query. Claude Desktop has a per-conversation tool usage cap that is easy to hit during analytics-heavy sessions. Claude Code and OpenClaw handle high tool volumes without issue.


Prerequisites

  • Python 3.11 or higher
  • A Catapult Openfield account with API access
  • An Openfield API token (generated in the OpenField UI)

Installation

1. Clone or download the project

git clone https://github.com/MatthewLeeWilcox/OpenfieldMCP.git
cd OpenfieldMCP

2. Install dependencies

pip install -e .

This installs the openfield-mcp package and its dependencies (mcp, httpx, pydantic-settings, uvicorn).

3. Generate an API token

  1. Log into your Openfield account
  2. Go to Settings → API Tokens
  3. Create a new token and copy it

4. Configure your credentials

Create a .env file in the project root (or export as shell environment variables):

CATAPULT_API_TOKEN=your_token_here
CATAPULT_REGION=us   # us | eu | au
Variable Required Description
CATAPULT_API_TOKEN Yes Long-lived token from Openfield Settings
CATAPULT_REGION Yes us (Americas), eu (EMEA), au (Asia-Pacific)
CATAPULT_TIMEOUT No HTTP timeout in seconds (default: 30)
CATAPULT_SENSOR_PAGE_SIZE No Rows per page for 10Hz sensor data (default: 5000)

5. Verify the connection

CATAPULT_API_TOKEN=your_token CATAPULT_REGION=us python -c "
import asyncio
from openfield_mcp.settings import OpenfieldSettings
from openfield_mcp.client import OpenfieldClient

async def test():
    s = OpenfieldSettings()
    c = OpenfieldClient(s)
    result = await c.request('GET', '/athletes', params={'page': 1, 'page_size': 1})
    print('Connected -', result)
    await c.aclose()

asyncio.run(test())
"

Integration Guides


Claude Code (CLI)

Claude Code automatically picks up .mcp.json from the project directory.

Step 1: Export your credentials in your shell (add to ~/.bashrc or ~/.zshrc):

export CATAPULT_API_TOKEN=your_token_here
export CATAPULT_REGION=us

Step 2: The .mcp.json file is already included in this repo:

{
  "mcpServers": {
    "openfield": {
      "type": "stdio",
      "command": "python",
      "args": ["-m", "openfield_mcp.server"],
      "env": {
        "CATAPULT_API_TOKEN": "${CATAPULT_API_TOKEN}",
        "CATAPULT_REGION": "${CATAPULT_REGION}"
      }
    }
  }
}

Step 3: Open a Claude Code session from inside this project folder:

cd /path/to/OpenfieldMCP
claude

The openfield MCP server will register automatically. Verify with /mcp - you should see openfield listed as connected.

Step 4: Ask questions naturally:

Who had the highest player load in yesterday's session?
Show me all activities from last week.
What was the mean HSD by position group today?

OpenClaw

OpenClaw manages MCP servers via its CLI. Run these commands once - the config persists across sessions.

Step 1: Export your credentials in your shell (add to ~/.bashrc or ~/.zshrc):

export CATAPULT_API_TOKEN=your_token_here
export CATAPULT_REGION=us

Step 2: Register the server with OpenClaw:

openclaw mcp set openfield '{
  "command": "python",
  "args": ["-m", "openfield_mcp.server"],
  "workingDirectory": "/absolute/path/to/OpenfieldMCP",
  "env": {
    "CATAPULT_API_TOKEN": "your_token_here",
    "CATAPULT_REGION": "us"
  }
}'

Step 3: Verify it registered:

openclaw mcp list
openclaw mcp show openfield

That's it - OpenClaw will launch the server automatically on demand. To remove it later:

openclaw mcp unset openfield

Claude Desktop (Mac / Windows)

Mac: Edit ~/Library/Application Support/Claude/claude_desktop_config.json

Windows: Edit %APPDATA%\Claude\claude_desktop_config.json

Add the following inside "mcpServers":

{
  "mcpServers": {
    "openfield": {
      "type": "stdio",
      "command": "python",
      "args": ["-m", "openfield_mcp.server"],
      "cwd": "/absolute/path/to/OpenfieldMCP",
      "env": {
        "CATAPULT_API_TOKEN": "your_token_here",
        "CATAPULT_REGION": "us"
      }
    }
  }
}

Replace /absolute/path/to/OpenfieldMCP with the actual path where you cloned the repo. On Windows use double backslashes: C:\\Users\\you\\OpenfieldMCP

Restart Claude Desktop. The openfield server will appear in the tools panel (hammer icon).


Cursor

Project-level (only active in this project): create .cursor/mcp.json in your project root:

{
  "mcpServers": {
    "openfield": {
      "type": "stdio",
      "command": "python",
      "args": ["-m", "openfield_mcp.server"],
      "cwd": "/absolute/path/to/OpenfieldMCP",
      "env": {
        "CATAPULT_API_TOKEN": "your_token_here",
        "CATAPULT_REGION": "us"
      }
    }
  }
}

Global (active in all Cursor projects): edit ~/.cursor/mcp.json with the same structure.

Restart Cursor. Navigate to Settings → MCP to confirm the server is listed as active.


Windsurf (Codeium)

Edit ~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "openfield": {
      "type": "stdio",
      "command": "python",
      "args": ["-m", "openfield_mcp.server"],
      "cwd": "/absolute/path/to/OpenfieldMCP",
      "env": {
        "CATAPULT_API_TOKEN": "your_token_here",
        "CATAPULT_REGION": "us"
      }
    }
  }
}

Reload Windsurf. The server will appear under Cascade → MCP Servers.


Running the Server

All integrations above launch the server automatically - you do not need to run it manually.

openfield-mcp
# or
python -m openfield_mcp.server

Available Tools

Category Tools
Activities list_activities, get_activity, get_activity_athletes, get_activity_periods, get_activity_annotations, get_activity_tags, get_activity_devices, update_activity, delete_activities, create_injected_activity, update_injected_activity, get_injection_template, inject_stats, delete_injected_stats
Athletes list_athletes, get_athlete, create_athlete, update_athlete, get_athlete_annotations
Sensor Data get_sensor_data, get_period_sensor_data, get_athlete_events, get_period_events, get_athlete_efforts, get_period_efforts
Stats query_stats
Teams list_teams, get_team, create_team, get_team_athletes, move_athletes
Periods list_periods, get_period, get_period_athletes, get_positions
Parameters list_parameters, list_parameter_types, get_parameter, create_parameter, update_parameter, delete_parameter
Tags list_tags, create_tag, update_tag, list_tag_types, get_tag_type, create_tag_type, update_tag_type, add_entity_tags, remove_entity_tags
Annotations get_annotation, create_annotation, update_annotation, delete_annotation, list_annotation_categories, get_annotation_category, create_annotation_category, update_annotation_category, delete_annotation_category
Venues list_venues, get_venue, create_venue
Live get_live_athletes, get_live_info
Threshold Sets list_threshold_sets, get_threshold_set, create_threshold_set, update_threshold_set, delete_threshold_sets, restore_threshold_sets, get_threshold_alerts, update_threshold_alerts
Webhooks list_webhook_configs, get_webhook_config, create_webhook_config, update_webhook_config, delete_webhook_config, list_webhook_events, list_webhook_events_for_config
Settings get_settings, set_default_athlete_profile

Example Queries

Once connected, ask in natural language:

Who had the highest player load in the last session?
What was the mean and median HSD across all sessions today?
Which athletes had outlier high-speed distance relative to their position group?
List all activities from the past week for the varsity team.
Show me 10Hz GPS data for athlete [name] in yesterday's morning session.
Which striker covered the most distance in the last game?
Create an annotation on activity [id] at the 32-minute mark.

Project Structure

OpenfieldMCP/
├── pyproject.toml
├── .env.example
├── .mcp.json                    # Claude Code / Cursor project config
└── src/
    └── openfield_mcp/
        ├── server.py            # FastMCP entry point
        ├── settings.py          # Environment config (CATAPULT_*)
        ├── client.py            # Authenticated httpx wrapper
        └── tools/               # 81 MCP tools across 14 modules

Troubleshooting

Server not appearing in Claude Code:

  • Confirm CATAPULT_API_TOKEN is exported in your shell (echo $CATAPULT_API_TOKEN)
  • Run /mcp in Claude Code to see server status and error messages

422 Unprocessable Entity errors:

  • Check the filters format for query_stats - each filter needs name, comparison (=, >, <, >=, <=, <>), and values (array)

Sensor data timeouts:

  • Reduce CATAPULT_SENSOR_PAGE_SIZE (default 5000) and paginate using the page parameter

Wrong region:

  • Confirm CATAPULT_REGION matches your account: us, eu, or au

About

An MCP (Model Context Protocol) server that gives AI agents direct access to the Catapult Openfield Connect API v6. Query athlete GPS sensor data, session analytics, team rosters, performance stats, and more.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages