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/mcpTwo 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