Skip to content

for people who went looking

Connect an AI assistant.

Uplora speaks the Model Context Protocol. An assistant that speaks it can ask what’s waiting for you and act on it — with exactly the permissions you have, and no others. 58 tools, one workspace, your live role checked on every call.

Point it here

https://www.uplora.io/api/mcp

Two ways in, and they end in the same place. An assistant that speaks OAuth will find its own way: this address answers an unauthenticated call with 401 and a WWW-Authenticate challenge, which points at the discovery document, which points back here. You’ll land on a page that names the app, shows the address it gets sent back to, and asks how much of you it gets. Nothing is granted until you say so.

Or create a token in Uplora under Settings and send it as Authorization: Bearer …. Either way you end up holding the same kind of key: it names you and one workspace, it carries no permissions of its own, and it sits in the same list under Settings whether you pasted it or an app asked for it.

Plain HTTP JSON-RPC, protocol revision 2025-06-18: one POST in, one JSON response out. There is no SSE stream and no session handshake, so a client that insists on either will need its manual HTTP transport rather than its automatic one. In most of them that is one entry:

{
  "mcpServers": {
    "uplora": {
      "url": "https://www.uplora.io/api/mcp",
      "headers": { "Authorization": "Bearer <your token>" }
    }
  }
}

Drop the headers line and an assistant that speaks OAuth finds its own way in. Keep it, and the key is one you made under Settings and can revoke there. If your client only speaks stdio it needs a bridge process in front of it — point the bridge at the same address, and nothing else changes.

A key is pinned to one workspace. “Which workspace is that video in” is a question only Uplora itself and Telegram answer.

For whoever is wiring the client

Uplora is its own authorization server. Everything below is live; the first address is the only one a client needs to be told about.

https://www.uplora.io/.well-known/oauth-protected-resource
https://www.uplora.io/.well-known/oauth-authorization-server
https://www.uplora.io/oauth/authorize
https://www.uplora.io/oauth/token
https://www.uplora.io/oauth/register
https://www.uplora.io/oauth/revoke
protected resource
RFC 9728. Start here — it names the authorization server and the scopes. It is also what the 401 challenge points at.
authorization server
RFC 8414. The endpoints below, plus proof that PKCE S256 is required.
authorize
The consent screen. A human signs in, picks a scope and approves — or doesn't.
token
Form-urlencoded. Exchange the code and the verifier for a key.
register
RFC 7591, for clients without a metadata document. JSON, public clients only.
revoke
RFC 7009. Hand the key back when you're done with it.

Authorization code with PKCE S256, public clients only. The three OAuth scopes are the three below. Send resource (RFC 8707) on both requests: a key is bound to https://www.uplora.io/api/mcp and is refused anywhere else, and a key issued anywhere else is refused here.

Identify yourself with a Client ID Metadata Document if you have one — that is the path we prefer and the one the specification prefers. Dynamic registration works too, and issues public clients with no secret.

No refresh tokens, on purpose. A key is opaque and checked against the database on every call, so revoking one takes effect on the next call rather than at the next expiry — which is worth more than an hour-long token that cannot be taken back. When the 90 days are up you get a 401 and authorize again.

How much of you it gets

You pick one of three — when you create the key yourself, or on the screen where you approve an app. An app may ask for one; you are the one who answers. Whichever you pick can only ever narrow what you can already do.

read
Look at anything you can look at. Changes nothing, ever.
review
The day’s work: approve, send back, comment, schedule, assign, archive.
full
The above, plus workspace settings, disconnecting YouTube and deleting cuts.

Keys expire — 90 days unless you say otherwise. Nothing renews itself, no key can create another, and asking for a narrow one and then reaching past it gets you a 403 naming the scope that would have been enough, never the thing you asked for.

Look things up

list_waiting_on_me
Tell you what needs your eyes
find_videos
Look up a video by title
get_video
Open one video's details
list_my_videos
See your own cuts, and what came back
list_in_flight
See everything moving right now
list_scheduled
See what's going out, and when
list_archived_videos
See what's been put away
get_video_history
See what changed between versions
get_video_notes
Read the review thread
get_video_links
Get a link to watch or download one cut
get_version_link
Download an older cut of the same video
get_workspace_summary
See where the workspace stands, in one line
get_workspace_settings
See who may approve, and what approving does
list_team
See who's in this workspace
list_pending_invites
See which invites are still waiting
get_channel_status
See your YouTube connection and storage
get_billing_status
See your plan, and what still works
get_billing_link
Get the link that starts or manages a plan
get_notifications
Read your own notifications

Review a cut

approve_video
Approve one, once you've watched it
approve_own_video
Approve your own cut, when it's your channel
send_video_back
Send one back with a note
reopen_video
Unlock an approved cut, and say why
submit_video_for_review
Send a cut in for approval
comment_on_video
Leave a comment pinned to a second
nudge_video
Chase a cut that's sitting with someone else
resolve_thread
Close a note that's been dealt with

Get it out of the door

schedule_video
Give an approved cut a date
reschedule_video
Move a date that's already promised
publish_video_now
Send an approved cut to the channel now
retry_publish
Try a failed publish again
cancel_video
Call off a scheduled post

Tidy up

assign_video
Say whose turn it is
edit_video_metadata
Rewrite the title, description and tags
restore_version_metadata
Put an older version's wording back
archive_videos
Put cuts away without erasing them
unarchive_videos
Bring cuts back from the archive
delete_videos
Erase cuts, and the masters with them
create_draft_video
Start an empty cut for a file to land in

The workspace

invite_member
Invite a manager or an editor
revoke_invite
Take back an invitation you sent
resend_invite
Send a pending invitation again
change_member_role
Make someone a manager, or an editor
remove_member
Take somebody off this workspace
set_member_approval
Let one manager approve, or stop them
set_workspace_settings
Change who may approve, and what approving does
save_publishing_preset
Set what every new cut starts with
request_upload_permission
Ask permission to start an upload
decide_permission_request
Answer someone's ask to upload
set_email_notifications
Turn your own email notifications on or off
mark_notifications_read
Clear your own unread count
send_test_ping
Check that pings actually reach you
link_telegram
Get the link that connects Telegram
send_feedback
Tell us something is wrong

Take access away

list_agent_tokens
See which assistants are connected
revoke_agent_token
Cut off a connected assistant
disconnect_channel
Disconnect YouTube
unlink_telegram
Disconnect Telegram from this account

What each of the 7 loud ones asks for first

None of these takes a bare yes. Each one refuses the first time and says exactly what it would do.

publish_video_now
A second call, after a refusal that names the video and the channel it would go to, publicly, now.
cancel_video
A second call, after a refusal that names the video and the date it was promised for.
delete_videos
The exact title, typed back. The refusal names the title first, and how many bytes go with it.
remove_member
The person's name, typed back. The refusal names them first, and says what they lose: their access everywhere at once, anything assigned to them, and any permission to approve.
revoke_agent_token
Nothing to type — but if it is not its own key, the person who owns that key gets an email.
disconnect_channel
Your channel's name, typed back exactly.
unlink_telegram
Nothing to type — but that chat gets one last message and you get an email, whatever your email settings say.

These all keep working when a plan lapses: revoking a key, disconnecting YouTube, deleting a master, unlinking Telegram, taking somebody off the team, and stopping an invite you sent to the wrong address. Taking access away is never something you have to pay us for.

What it is never handed

A role above yours
read from your membership on every single call
A way around approval
publishing still waits for a yes from a person
A way to watch the video for you
only you can do that
What you earn
we never asked Google for it
A way to promote itself
a token can be narrower than you; it can never be wider, and it never mints another
Anyone's email address
the team list is names and roles, on purpose

Your assistant’s role is read from your team membership on every single call — it is never stored on the token. Take someone off your team and their assistant loses access in the same second, with nothing else to revoke.

Questions, or something not working? contact@uplora.io · How access works