UpPetto

Write a course with the AI you already use.

Connect Claude or ChatGPT to your UpPetto account. Describe the course you want, and the model writes the lessons and saves them here, in your account. UpPetto checks every draft and tells the model what to fix.

Server address

https://uppeto.com/mcp/

No token, no API key. You sign in to UpPetto in your browser the first time the app connects.

You

Write a five-lesson course on reading nutrition labels, for new parents.

Claude checks the draft with UpPetto

5 lessons, 14 links between them, none broken.
Lesson 3: unknown box type “warnign”

Claude

Fixed the typo in lesson 3 and checked again. Nothing flagged.

Claude saves it to UpPetto

Saved “Reading nutrition labels” as a private course in your account.

An example session. The check comes from UpPetto; the writing is the model's.

Three steps, once.

  1. Add the address

    Paste the server address into your app's connector settings.

  2. Sign in and press Allow

    Your browser opens UpPetto. Check which app is asking and where it will send you back, then press Allow.

  3. Ask for a course

    Describe it in your own words. The model reads our format guide, checks its draft and saves the course.

Set up your app.

Pick the app you use. You do this once; after that UpPetto is there in every conversation.

Claude on the web and in the desktop app

  1. Open SettingsConnectorsAdd custom connector.
  2. Name it UpPetto and paste the server address.
  3. Press Connect. UpPetto opens in your browser: sign in and press Allow.
  4. In a conversation, turn UpPetto on from the tools menu and ask for a course.

Claude Code

  1. In your terminal, run:
    claude mcp add --transport http uppetto https://uppeto.com/mcp/
  2. Start Claude Code, type /mcp, choose uppetto and then Authenticate.
  3. UpPetto opens in your browser: sign in and press Allow.

ChatGPT

Not yet verified end to end with UpPetto. The steps below follow ChatGPT's own instructions; if something doesn't match, tell us.

  1. Open SettingsAppsAdvanced settings and turn on Developer mode.
  2. Create an app: name it UpPetto, paste the server address, and choose OAuth for authentication.
  3. UpPetto opens in your browser: sign in and press Allow.

Signing in with a link from your email? Open it in the same browser the connection started in, or the app won't recognise the reply.

What to ask.

Start with this message and fill in the brackets. It points the model at the format guide and makes it check the draft before saving.

Your first message
Use the UpPetto connector to write a course in my account.
Topic: [your topic]. For: [who it is for]. Length: about [number] lessons.
First read uppetto://guide/authoring and start from uppetto://template/course.
Check the draft with validate_course and fix everything the report flags.
Then save it with write_course and give me the link.

Later, ask for changes the same way

  • Add a module on budgeting to my course “Money for first-time renters”.
  • Lesson 4 is too long. Split it into two lessons and keep everything else.
  • Share my course by link, but don't make it public.

Edits keep each lesson's place, so anyone already taking the course keeps their progress.

Your account stays yours.

Only your account
The app works as you, after you allow it. It can't see anyone else's courses, and nobody else's app can touch yours.
Private by default
A new course is visible only to you until you share it. It has not been through UpPetto's fact check: we store it and show it, but the model wrote it.
Your model does the thinking
UpPetto's side of the connection never calls a language model. It checks the format, saves the course and reports back.
Disconnect any time
Every app you allowed is listed on Connected apps. Disconnect stops its access at once.

Questions.

Which apps can connect?

Claude on the web, the Claude desktop app and Claude Code. ChatGPT is supported but not yet verified end to end. Other apps can't connect yet: UpPetto only accepts apps it knows.

Do I need a token or an API key?

No. You sign in to UpPetto in your browser and press Allow. The app gets its own access, which you can take back from Connected apps.

Which account do the courses go to?

The one you are signed in to when you press Allow. The consent screen shows it, with a way to switch accounts before you allow anything.

What if the model gets something wrong?

Before saving, the model checks its draft with UpPetto and gets a report: unknown formatting, broken links between lessons, missing fields. For the content itself, read the course before you share it. Nobody at UpPetto reviews it.

A page asked me to press Allow, but I didn't start anything.

Press Deny. Only allow an app you connected yourself, just now. If an email or a link brought you to that page, it wasn't you who started it.

Technical details MCP 2025-06-18, Streamable HTTP, OAuth 2.1
Endpoint
https://uppeto.com/mcp/
Resource metadata
https://uppeto.com/.well-known/oauth-protected-resource
Authorization
OAuth 2.1 with PKCE. Apps identify themselves with a Client ID Metadata Document from claude.ai or chatgpt.com.

Tools the model can call

  • list_courses Courses in this account: slug, title, visibility, size.
  • read_course A course in exactly the format write_course accepts -- so a new session can pick up where the last one stopped.
  • validate_course Check a course and get the render report while writing NOTHING: which callouts were recognised and which names were not, which links resolved and which dangled, which figures were refused. Call this before write_course.
  • write_course Create a course, or update an existing one (update=true: items are matched by path, so learner progress survives). The answer is the same render report validate_course returns, plus awaiting_review: true means the account owner will see an 'awaiting review' notice instead of the course until a reviewer approves this version. One call can carry the whole course or just a part of it.
  • delete_items Delete course items by path. Learner progress goes with them, and the answer says how much. Deletion never happens as a side effect of a write.
  • set_visibility Course visibility: private, link or public.
  • upload_image Upload an image as base64 (up to 1.5 MB; use request_image_upload for files on disk). It is converted to AVIF: lossless sources such as PNG stay lossless, JPEG stays lossy. Returns the image's url and a markdown line to put in a lesson body. The url works for anyone who has it, even for a private course, until the image is revoked.
  • request_image_upload Get a single-use address (valid 15 minutes) to send one image file to with curl, so the bytes do not pass through the conversation. The answer includes the curl command; the upload's response is the same description upload_image returns.
  • list_images Images in this account: url, markdown, size, declared source, whether each is still served, which lessons use it, and the account's limits.
  • revoke_image Stop serving an image now. Its address stops working at once, lessons that use it show 'image unavailable', and the record of the upload stays. Cannot be undone: upload the file again for a new address.

None of them calls a language model on UpPetto's side.

Resources the model reads on its own

  • uppetto://guide/authoring The course format: a folder of markdown
  • uppetto://guide/vocabulary The vocabulary of a lesson body
  • uppetto://template/course A minimal course that actually works
  • uppetto://schema/course The format as a machine-readable schema