Model Context Protocol

Greyhound racing,
inside your assistant.

Connect GreyhoundAPI to Claude or ChatGPT and ask in plain English. Twenty-three tools over real GB and Australian racing — cards, results, form, sectionals, prices and trainer records. Your key, your data, no code.

23 tools 7 on the free key 0 lines of code
Get a free key How to connect Works with any MCP client.
Claude · connected to greyhoundapi
You
Which trainers did best at Romford over 575m last month?
Claude
find_trainer · track_statistics
Over 575m at Romford in the last 30 days, M E Wiley leads on strike rate at 18.3% from 71 runners, ahead of P W Young on 13.9%. Trap 1 won 24% of those races against an expected 16.7%.

Connect it

Two minutes in Claude.

The server is hosted — nothing to install and nothing to run. Six fields, and one of them catches people out, so it is called out below.

  1. Get a key. Free, no card, from your dashboard. It starts gapi_test_ and reaches 7 of the tools straight away.
  2. Open Settings → Connectors → Add custom connector. In Claude, on web or desktop.
  3. Name and URL. Call it anything — Greyhound API is fine. The URL is https://greyhoundapi.com/mcp
  4. Authentication: choose None. This is the step that catches people. Claude also offers two OAuth options; picking either one will fail to connect. This server authenticates with an API key header, not OAuth, and Claude usually detects that and marks None as Detected — take it.
  5. Add a request header. Under Additional request headers, add name x-api-key with your key as the value. This is what identifies you; it is stored securely by Claude and never shown again.
  6. Transport: leave it alone. Streamable HTTP is set automatically from the URL and is correct. Only change it if you are told to.
What you are filling in
URL
https://greyhoundapi.com/mcp
Authentication
None — not OAuth
Header name
x-api-key
Header value
gapi_test_… or gapi_live_…
Transport
Streamable HTTP (automatic)

Other MCP clients work the same way: the address above, and your key in an x-api-key header. Authorization: Bearer is accepted too, for clients that only offer that.

Then ask it something. No prompt engineering — the tools describe themselves, so the assistant picks the right one: “What won the 19:28 at Monmore on Tuesday?” · “Show me A Bad Winter’s last six runs.”

The tools

Twenty-three, not sixty-two.

Curated on purpose. A model given every endpoint chooses badly; these map to the questions people actually ask. The full REST API is still there for anything else.

Works on a free key Needs Live Needs Live Plus
todays_racecardsFree key

Every race card scheduled today across Great Britain and Australia, with runners, trap draws and scheduled off times.

arguments region, track_id, grade, distance_m, summary

required none

upcoming_racesFree key

Races due off shortly, nearest first. Use this for "what is running next".

arguments hours, region, track_id, grade, limit

required none

latest_resultsFree key

The most recently settled races, newest first, with finishing order and times.

arguments since, region, limit

required none

find_racesFree key

Search the race archive by date range, region, track, grade, distance or status. The general-purpose way to locate races.

arguments ids, date_from, date_to, region, track_id

required none

get_raceFree key

One race in full: conditions, going, distance, grade and its runners.

arguments race_id

required race_id

get_race_resultLive

The finishing order for one race, with times, sectionals and starting prices where published. Requires a Live key.

arguments race_id

required race_id

dog_layoffLive Plus

How a greyhound has run after different lengths of time off, beside how greyhounds generally run after the same break. Rates are suppressed where the dog has too few runs; counts are always shown. Requires a Live Plus key.

arguments dog_id

required dog_id

dog_trendLive Plus

Whether a greyhound is running quicker or slower lately, each run measured against par for that track and distance, with the change shown beside the dog's own run-to-run variation so noise is not mistaken for a trend. Requires a Live Plus key.

arguments dog_id, track_id, distance_m, window

required dog_id

meeting_analysisLive Plus

A whole card as one unit: how fast the track actually ran against par for each distance, and whether the published going agreed. Trap wins are counts only — a single card cannot show bias. Requires a Live Plus key.

arguments meeting_id

required meeting_id

race_precedentsLive Plus

Races from the archive that ran under matching conditions at this track and distance, with what happened in them. Each row says what it matched on and where it differs. History, never a forecast. Requires a Live Plus key.

arguments race_id, limit

required race_id

race_fieldLive Plus

Every runner in one race with its record at this track and trip, its grade record, days since it last ran and how it has run off that break, beside the strike rate of the trap it has drawn. Replaces a call per runner per measure. Measurements only, never a forecast; runners short of history are named, not omitted. Requires a Live Plus key.

arguments race_id

required race_id

race_analysisLive Plus

Conditions and early pace for one race in a single call, joined per runner — trap record, winning times, field experience and each runner's early split with its sample size. Measurements only, never a forecast. Requires a Live Plus key.

arguments race_id

required race_id

race_paceLive Plus

Each runner's measured early split from past runs at this track and distance, with the run count behind every figure. Runners with too little data are named, not omitted. Measurements only, never a forecast. Requires a Live Plus key.

arguments race_id

required race_id

race_conditionsLive Plus

The context one race runs in: trap strike rates at this track and distance, typical winning time, and how experienced the field is. Every figure carries its sample size. Historical context, never a forecast. Requires a Live Plus key.

arguments race_id

required race_id

get_race_marketLive

Market data for one race: each runner's starting price and the best Betfair back and lay prices taken seconds before the off. Factual prices only, never a prediction. Requires a Live key.

arguments race_id

required race_id

find_dogLive

Find a greyhound by name. Use this first when someone names a dog, to get its dog_id. Requires a Live key.

arguments ids, name, sire, dam, sex

required none

get_dog_formLive

A greyhound's recent runs — the form line: date, track, distance, grade, finishing position, time and price. Requires a Live key.

arguments dog_id, limit

required dog_id

compare_dogsLive

Every time two greyhounds have met, with how each finished. Needs both dog ids. Requires a Live key.

arguments dog_id, rival_id

required dog_id, rival_id

dog_statisticsLive Plus

A greyhound's record split by distance, track, trap, grade and going — what tends to happen rather than what happened once. Requires a Live Plus key.

arguments dog_id, track_id, distance_m

required dog_id

find_trainerLive

Find a trainer by name to get their trainer_id. Requires a Live key.

arguments name, limit

required name

trainer_statisticsLive Plus

A trainer's strike rate split by track, distance, trap and grade over a rolling window. Requires a Live Plus key.

arguments trainer_id, months, track_id

required trainer_id

list_tracksFree key

Every track covered, with region and the distances raced there.

arguments ids, region

required none

track_statisticsFree key

Trap bias and winning-time distribution for a track, by distance.

arguments track_id

required track_id

In practice

What you can actually ask.

You do not name the tool. You ask the question, and the assistant works out which of the 23 to call and how to fill it in. These are real questions and the tools they trigger.

What won the 19:28 at Monmore on Tuesday?

find_races → get_race_result

Resolves the meeting and time to a race, then reads the finishing order, times and SPs.

Show me A Bad Winter’s last six runs.

find_dog → get_dog_form

Looks the name up to get an id first, then pulls the form line. You never see the two-step.

Which trap wins most over 575m at Romford?

list_tracks → track_statistics

Trap bias by distance, straight from the archive rather than a rule of thumb.

Have these two dogs ever met?

find_dog ×2 → compare_dogs

Two lookups then the head-to-head record, with how each finished every time.

Who is running tonight at Sheffield?

todays_racecards

Tonight’s card with runners, trap draws and scheduled off times.

How has this trainer done over the last three months?

find_trainer → trainer_statistics

Strike rate split by track, distance, trap and grade over a rolling window.

The chaining is the point. Nearly every useful question needs a name turned into an id first. Writing that yourself is two API calls and some error handling; here the assistant does it because the tool descriptions tell it to.

How it works

Three methods, and no magic.

The Model Context Protocol is JSON-RPC 2.0 over HTTP. Worth understanding if you are going to build on it, and reassuring if you are wondering what your assistant is sending us.

1

initialize

On connecting, the client asks what protocol we speak and what we are. We answer with a short brief telling the model this is factual race data, that names must be resolved to ids first, and that dates are the track’s own calendar date.

2

tools/list

The client asks what it can do. It gets 23 tools, each with a JSON Schema for its arguments — types, which are required, and an example value. This is generated from the same registry that builds our documentation, so it cannot drift.

3

tools/call

When your question needs data, the model picks a tool and fills in the arguments. We forward that to the REST API with your key, and hand back the JSON plus a line of context — how fresh it is, what was truncated, or why a list came back empty.

# see it yourself — no key needed to list the tools
curl -X POST https://greyhoundapi.com/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

# and a real call, with your key
curl -X POST https://greyhoundapi.com/mcp \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $GAPI_KEY" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call",
       "params":{"name":"list_tracks","arguments":{"region":"GB"}}}'

From your own code

ChatGPT, Claude, or something you built.

A chat window is the quickest way in, not the only one. Any model runtime that speaks MCP can use this, and what you build on top is yours.

OpenAI — Responses API

Pass the server in tools with type: "mcp". OpenAI fetches the tool list itself, then calls whatever the model chooses. Your key travels in headers on every request.

from openai import OpenAI
client = OpenAI()

resp = client.responses.create(
    model="gpt-4.1",
    tools=[{
        "type": "mcp",
        "server_label": "greyhoundapi",
        "server_url": "https://greyhoundapi.com/mcp",
        "headers": {"x-api-key": os.environ["GAPI_KEY"]},
        "require_approval": "never",
    }],
    input="Which trap wins most over 575m at Romford?",
)
print(resp.output_text)

Narrow what the model sees with allowed_tools if you only want a few. Note that OpenAI does not retain your headers between requests, so the key goes on every call.

Anything else — talk to it directly

There is no SDK to install. It is one HTTP endpoint and three methods, so a client is about fifteen lines in any language.

import requests, os

URL = "https://greyhoundapi.com/mcp"
H   = {"X-API-Key": os.environ["GAPI_KEY"]}

def rpc(method, params=None, _id=[0]):
    _id[0] += 1
    r = requests.post(URL, headers=H, json={
        "jsonrpc": "2.0", "id": _id[0],
        "method": method, "params": params or {},
    })
    return r.json()

tools = rpc("tools/list")["result"]["tools"]
out   = rpc("tools/call", {
    "name": "get_dog_form",
    "arguments": {"dog_id": 655044},
})
print(out["result"]["content"][0]["text"])

Hand tools to whichever model you like as its function definitions — the schemas are already in the right shape.

Claude, in the app. No code at all — add it as a custom connector with the four fields above. Anthropic’s API also accepts remote MCP servers through its mcp_servers parameter if you are building rather than chatting; their documentation has the current shape.

Make it yours

Build something on top.

Narrow it to your job

Most clients let you restrict which tools a model can see. A form-analysis assistant might only need find_dog, get_dog_form and dog_statistics; a results bot needs latest_results and nothing else. Fewer tools means better choices and fewer wasted calls.

Wrap it in your own server

Nothing stops you running your own MCP server that calls this one, adds your own tools, and presents a single surface to your team — your database alongside our racing data. The REST API is there for anything the 23 tools do not cover.

Give it to non-technical people

The reason this is worth doing at all: somebody who would never write a script can ask a question and get an answer out of the archive. No spreadsheet exports, no asking a developer, no waiting.

Prototype before you commit

Working out whether the data suits you takes minutes in a chat window instead of an afternoon of throwaway code. The response shapes are identical to the REST API, so nothing you learn is wasted when you do build properly.

What it is and is not

Worth being clear about.

Your key, your limits

Every tool call goes through the same API as any other client, with your key. The same rate limits, the same quota, the same tier scope. Nothing is bypassed, and MCP usage appears in your dashboard alongside everything else.

Data, not tips

This returns factual race data — results, times, form and published prices. It contains no predictions, ratings or selections, and the server tells the assistant so. If a model offers you a tip from this, that is the model, not us.