Whyzit MCP connector
The connector's contract, as the server at app.whyzit.com enforces it.
Whyzit turns a question into a short narrated video lesson, about one minute long. This connector lets an agent list a person's lessons, read one, and find the lessons that already answer a question. An agent can also start a new lesson on the person's behalf, and start buying a plan. It is a Model Context Protocol server with five tools, behind OAuth 2.1.
Endpoint
| MCP endpoint | https://app.whyzit.com/mcp |
| Transport | Streamable HTTP: one POST carrying JSON-RPC 2.0 |
| Protocol version | 2025-06-18 |
| Protected resource metadata | https://app.whyzit.com/.well-known/oauth-protected-resource |
| Authorization server metadata | https://app.whyzit.com/.well-known/oauth-authorization-server |
A call with no token, or an expired one, answers 401 with a
WWW-Authenticate: Bearer resource_metadata="…" header. That header is how a
client discovers where to send the person to sign in.
Authorization
The server is an OAuth 2.1 authorization server as well as the resource.
- Authorization code flow with PKCE.
S256is the only challenge method. - Tokens are bound to the resource
https://app.whyzit.com/mcp. Sendresource=https://app.whyzit.com/mcpon the authorization and token requests. - Dynamic client registration is not offered. A client identifies itself with
a client metadata document. Its
client_idis anhttpsURL it controls. The JSON document at that URL carriesclient_nameandredirect_uris, and the redirect URI on every request must appear in that list. - Refresh tokens are issued and rotated.
The person signs in once, at connect time, on https://app.whyzit.com/connect,
with Google or with email and password, and approves the client by name. After
that the client holds a token and calls without asking again.
Scopes
| Scope | What the person sees | Tools it unlocks |
|---|---|---|
films:read |
See the films you have made | list_films, get_film, find_films |
films:make |
Make new films on your account | make_film, start_plan |
films:make spends the person's own film allowance. It is shown to them as a
separate line on the consent screen, and it can be refused on its own. A token
that lacks a tool's scope is not offered that tool in tools/list. A call to
it anyway answers a JSON-RPC error with code -32002, naming the missing
scope.
Tools
Every tool answers with MCP content blocks. A result that carries data also
carries structuredContent with the same object. A refusal has
isError: true and one sentence of plain text meant to be read to the person.
list_films
Lists the lessons this person has made, newest first, up to 200. Films in
state finished and rendering are listed; a film whose render stopped early
is not.
Input: {}
Result, when there are films:
{
"films": [
{
"id": "b5395bc6-5b05-4f73-8f95-147147254ce5",
"question": "Why is the sky blue?",
"style": "photoreal",
"state": "finished",
"createdAt": "2026-09-21T23:39:38.000Z",
"finishedAt": "2026-09-21T23:40:41.000Z",
"threadId": "b5395bc6-5b05-4f73-8f95-147147254ce5",
"title": "Why the Sky Is Blue",
"publishedAt": "2026-09-22T08:12:04.611Z",
"public": true,
"views": 14,
"likes": 3,
"opener": "/api/session/b5395bc6-5b05-4f73-8f95-147147254ce5/beat/0.mp4",
"url": "https://app.whyzit.com/f/b5395bc6-5b05-4f73-8f95-147147254ce5"
}
]
}
public says whether the person published the film on Explore, and
publishedAt is when they first did. views counts one viewer once a day, and
likes counts the people who pressed like. opener is the film's opening clip,
a path under https://app.whyzit.com that a page plays as the film's picture.
When there are none, the text This person has not made any films yet.
get_film
Reads one lesson. Only the person's own films are readable through the connector. A film belonging to someone else is refused, even though its public address plays for anyone holding the link.
Input:
{ "id": "b5395bc6-5b05-4f73-8f95-147147254ce5" }
id is required and is a UUID.
Result:
{
"id": "b5395bc6-5b05-4f73-8f95-147147254ce5",
"question": "Why is the sky blue?",
"state": "finished",
"style": "photoreal",
"threadId": "b5395bc6-5b05-4f73-8f95-147147254ce5",
"title": "Why the Sky Is Blue",
"seconds": 59.4,
"public": true,
"views": 14,
"likes": 3,
"url": "https://app.whyzit.com/f/b5395bc6-5b05-4f73-8f95-147147254ce5"
}
threadId is the id of the first film in the thread this film belongs to.
A film that started its own thread carries its own id. title and seconds are
null until the film has rendered something.
state is one of created, rendering, finished, gone.
public, views and likes mean what they mean in list_films.
Refusals: get_film needs the film id., There is no film at that id.,
That film belongs to somebody else.
find_films
Finds the lessons that already answer a question: this person's own films, and
the public films other people published. Call it before make_film, because
watching a film that exists costs the person nothing and a new film spends one
of their films.
Input:
{ "query": "why is the sky blue" }
query is required. The search keeps the words of three letters or more and
drops the common ones, such as why, how and the.
Result:
{
"films": [
{
"id": "b5395bc6-5b05-4f73-8f95-147147254ce5",
"question": "Why is the sky blue?",
"title": "Why the Sky Is Blue",
"style": "photoreal",
"seconds": 59.4,
"url": "https://app.whyzit.com/f/b5395bc6-5b05-4f73-8f95-147147254ce5",
"public": true,
"mine": false,
"views": 14,
"likes": 3,
"match": 1
}
],
"suggested": ["b5395bc6-5b05-4f73-8f95-147147254ce5"]
}
Up to ten films come back, the closest first. match is the share of the
query's kept words that the film's question and title hold, from 0 to 1.
mine is true on this person's own film, and those are found while they are
private and while they are still rendering. Every other film is public and
finished.
suggested holds at most three ids, each with match of 0.6 or more, in the
same order. Offer those to the person before making a new film. Every id in
suggested has its film in films.
When nothing matches, the text No film answers that question yet.
Refusals: find_films needs some words to look for. for an empty query, and
Every word in that query is too short or too common to search for.
make_film
Starts a new lesson answering a question. This spends one of the person's films. Ask them before calling it.
Input:
{ "question": "Why do cats purr?", "style": "cartoon" }
questionis required, at most 300 characters.styleis optional. Accepted values arephotorealandcartoon. When it is left out the film usesphotoreal.
Result:
{
"id": "9596f069-8a50-47dc-9e4e-556ca479e035",
"question": "Why do cats purr?",
"style": "cartoon",
"url": "https://app.whyzit.com/f/9596f069-8a50-47dc-9e4e-556ca479e035",
"note": "The film is being made now and is shown to the person, where it updates by itself. Do not call another tool to check on it."
}
The tool writes the film, starts making it, and returns its address. The film
starts playing within seconds, and the rest of it is made while it plays, over
about a minute. Give the person the url. In an app that draws the Whyzit
player, such as ChatGPT or Claude, the film also plays in the conversation.
Refusals, each one sentence: a question is required, that question is too
long, unknown style, and when the allowance is spent, This account has used
its 2 free films. A film that failed does not count. Explorer gives 12 films a
month and Polymath gives 40. A subscriber who has used the month's films reads
a different sentence. It names the plan and the date the count resets. In
ChatGPT the sentence says only that the films are used up.
start_plan
Starts buying a monthly plan, or changes the plan a subscriber is on. This call charges nothing. It returns a Stripe Checkout address where the person pays. The plan then renews every month until the person cancels it under Manage billing on the Whyzit settings screen. Tell the person the price and the monthly renewal, and ask them, before calling it.
Input:
{ "plan": "explorer" }
plan is required and is explorer (12 films a month, $7.99) or polymath
(40 films a month, $19.99).
ChatGPT is not offered this tool, following OpenAI's rule for apps in ChatGPT on purchases. There, a call to it is refused, and no answer from any tool names a plan, a price or a place to buy.
Result, for a new subscriber:
{
"plan": "explorer",
"url": "https://checkout.stripe.com/c/pay/cs_live_…",
"note": "Open the url to pay for Explorer, $7.99 a month, 12 films a month. It renews every month until cancelled under Manage billing on the Whyzit settings screen."
}
For a subscriber on the other plan the url is the Stripe billing portal's
confirm page. The note says Stripe shows the prorated amount there.
Refusals, each one sentence: Unknown plan. The plans are Explorer and
Polymath., This account is already on Explorer., This account has its own
film allowance and needs no plan.
The Checkout page is Stripe's and needs no Whyzit sign-in. An agent may hand the address to the person. An agent that pays with Stripe Link may complete it itself, after the person approves the total. Whyzit accepts Link.
Access requirements
- The person needs a Whyzit account. Sign in with Google, or with email and password, is offered on the connect screen.
- Each account may render two films for free. A film is counted when its render starts, and a film made through the connector starts at once. A render that fails is refunded.
- Two paid plans, bought on the Whyzit settings screen, raise the allowance: Explorer, 12 films a month for $7.99, and Polymath, 40 films a month for $19.99. The count resets on the billing date and unused films do not carry over. The connector needs no change for a subscriber; the same tools apply.
- Rendering runs one film at a time per account and takes about a minute.
- There are no regional restrictions.
Errors
| Situation | Answer |
|---|---|
| No or bad bearer token | HTTP 401, WWW-Authenticate challenge, JSON-RPC error -32002 |
| Unknown method | JSON-RPC error -32601 |
| Unknown tool | JSON-RPC error -32602 |
| Tool the token's scopes do not cover | JSON-RPC error -32002, naming the scope |
| A tool refusing its input | result.isError: true with one sentence |