Connect your app to cliply
Let coaches authorize your app to read their cliply match data over MCP and OAuth 2.1.
On this page
Your app can read a coach's cliply data the same way Claude and ChatGPT do: through the cliply MCP server, with the coach's own authorization. You don't need an API key from us and you don't have to ask to be registered. Your app registers itself, the coach approves it, and you call the tools with the token you get back.
Your app receives data as JSON: matches, tags, facts, stats, sequences, players and clip ids. It never receives video. Video plays in cliply, and every clip id becomes a link that opens the cliply workbench on that play.
At a glance
| What | Value |
|---|---|
| MCP server | https://cliply.video/api/mcp (Streamable HTTP, stateless) |
| Authorization server metadata | https://cliply.video/.well-known/oauth-authorization-server/api/auth |
| Protected resource metadata | https://cliply.video/.well-known/oauth-protected-resource/api/mcp |
| Client registration | POST https://cliply.video/api/auth/oauth2/register (open, RFC 7591) |
| Authorize | https://cliply.video/api/auth/oauth2/authorize |
| Token | https://cliply.video/api/auth/oauth2/token |
| Revoke | https://cliply.video/api/auth/oauth2/revoke |
| Grants | authorization_code, refresh_token |
| PKCE | required, S256 |
| Scopes | cliply:read, cliply:write (optional), offline_access |
Quick start with the MCP SDK
The official MCP SDKs ship a client that discovers the endpoints, registers your app and runs the OAuth flow for you. In TypeScript (@modelcontextprotocol/sdk):
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
// authProvider implements OAuthClientProvider: it stores the client
// registration, the PKCE verifier and the tokens per coach, and redirects
// the coach's browser to the authorize URL.
const transport = new StreamableHTTPClientTransport(
new URL("https://cliply.video/api/mcp"),
{ authProvider },
);
const client = new Client({ name: "your-app", version: "1.0.0" });
await client.connect(transport);
const { tools } = await client.listTools();
const result = await client.callTool({
name: "list_matches",
arguments: {},
});
Your side of the work: a Connect cliply button, a callback route, token storage per coach, and the provider above. The rest of this page describes what the SDK does, for teams that build the flow themselves.
The OAuth flow, step by step
1. Discover
GET https://cliply.video/.well-known/oauth-protected-resource/api/mcp names the authorization server, and its metadata document lists every endpoint in the table above. A 401 from /api/mcp carries the same pointer in its WWW-Authenticate header.
2. Register your app (once)
POST https://cliply.video/api/auth/oauth2/register
Content-Type: application/json
{
"client_name": "Your App",
"redirect_uris": ["https://yourapp.example/cliply/callback"],
"grant_types": ["authorization_code", "refresh_token"],
"response_types": ["code"],
"token_endpoint_auth_method": "none"
}
Store the returned client_id and use the same one for every coach. Don't register again for each coach. Registration is rate limited.
3. Send the coach to cliply
When the coach chooses Connect cliply, redirect their browser to:
https://cliply.video/api/auth/oauth2/authorize
?response_type=code
&client_id=<client_id>
&redirect_uri=https://yourapp.example/cliply/callback
&scope=cliply:read cliply:write offline_access
&code_challenge=<S256 challenge>
&code_challenge_method=S256
&state=<random>
&resource=https://cliply.video/api/mcp
cliply handles the rest of this step. The coach signs in (or creates an account and an organization), picks the organization the connection will read, and approves.
4. Exchange the code
cliply redirects back to redirect_uri with code and your state. Check that state matches the one you sent, then exchange the code:
POST https://cliply.video/api/auth/oauth2/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=<code>
&redirect_uri=https://yourapp.example/cliply/callback
&client_id=<client_id>
&code_verifier=<PKCE verifier>
&resource=https://cliply.video/api/mcp
The response carries an access_token and, when you asked for offline_access, a refresh_token. Store both against the coach.
5. Refresh
When the access token expires, request a new one with grant_type=refresh_token, your client_id and the refresh token. The coach doesn't see this step. Keep the refresh token the response returns; it may differ from the one you sent.
Scopes and what the coach approves
cliply:read: read everything the coach can see in the organization they picked.cliply:write: optional. Lets your app create collections and presentations and comment on clips. It can never edit or delete anything. The consent screen shows it as a checkbox the coach can untick. When they do, the token is read-only and the create tools are not listed.offline_access: issues a refresh token.
A token is bound to one coach and one organization. It sees what that coach sees there, private projects included only when the coach can open them, and it never falls back to another membership. Player accounts cannot authorize. To read a second organization, the coach connects again and picks it.
The consent screen shows the client_name you registered next to the host of your redirect_uri. Register a name coaches will recognize.
Calling tools
Every call is a JSON-RPC request to /api/mcp with the coach's token:
POST https://cliply.video/api/mcp
Authorization: Bearer <access_token>
Content-Type: application/json
Accept: application/json, text/event-stream
{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"match_analysis","arguments":{"matchId":"<id>"}}}
The server is stateless, so you don't need a session id. A revoked token is refused on the very next request. Call tools/list for the live schema of every tool. Each tool also returns its own input schema there.
| Tool | Reads |
|---|---|
whoami | The coach, the organization, its sport and which features it has |
list_projects, list_matches | Where to start: projects and matches with their urls |
match_analysis | One match as facts with F-ids, a tagMeaning map (whose action each tag is, good or bad for the team, its opposite) and a baseline of comparable matches |
match_report | The stored AI report of a match, when the organization generated one |
find_clips | Clips by match, tag, player or period |
find_sequences | One action followed by another within a window, for example a recovery that becomes a circle entry |
compare_matches | Up to 8 matches side by side |
cliply_read | Everything else by name: players, player stats, teams, season stats such as team_tag_season, events, lineups, GPS, comments, collections, share views, calendar, activity |
cliply_describe | The exact input of a cliply_read name |
search, fetch | Search across matches, players, teams and help articles, then fetch one by id |
cliply_help_search, cliply_help_article, cliply_whats_new | This help center and the release notes |
create_collection, create_presentation, comment_clip | Only on cliply:write tokens |
Some reads depend on features the organization has turned on, such as GPS, bench stats or season stats. When one is off, the tool says so instead of returning data.
Links and citations
- Times are seconds from the start of the video.
- A match links to its
url. One play links to the match url plus?clip=<clipId>, and any clip id from any read works there. - Facts from
match_analysiscarry ids (F1,F2…). Cite them so the coach can trace each claim back to the match. - Links open the cliply workbench and need the coach to be signed in to cliply. To show clips to players, create a collection with
cliply:writeand the coach shares it from cliply. - Your model reads tags, not video. Answers are only as complete as the coach's tagging.
Limits, credits and errors
- Rate limits: 120 requests per minute per coach and 300 per minute per IP. Over the limit,
/api/mcpanswers429withRetry-After: 60. - Credits: reads through the connector don't consume cliply credits.
401: the token is missing, expired or revoked. Refresh it, or send the coach through the flow again.- Tool errors come back as a normal tool result with
isError: trueand a message your model can read.
Disconnecting
A coach disconnects your app in cliply under Account → Sessions → AI apps. Organization owners and admins can disconnect any member's app under Organization settings → General → AI apps, and the organization's audit log records every connection. Your app can also revoke its own tokens at the revoke endpoint. In every case, the next call with that token gets a 401.
For questions, write to hi@cliply.video.
Building on cliply?
Tell us what you are building and we will help you get it working.
Contact support

