PPTGO

The interface for agents

Let an AI write the decks in here

PPTGo ships an MCP server. Point a client like Claude Code or Codex at it and an agent can create decks in your account and write them a page at a time, while you watch the deck take shape in a browser — no copy-paste, and no generating a file somewhere else to upload afterwards.

01

Get a token first

An MCP client has no browser and cannot sign in, so it carries an API token instead. Create one on the tokens page and name it after the machine it will live on. The plaintext is shown once and is unrecoverable after you close the dialog.

02

One endpoint, this one

Every client connects to the same address. Self-hosting: swap in your own domain.

MCP endpoint
https://pptgo.dev/api/mcp
03

Configure the client

Authentication is a plain Bearer header, so any client that lets you set one will work. Three that do are below, verified against their current docs. Replace pptgo_YOUR_TOKEN with the token you just created.

Claude CodeOne command, and it is available in your next session.
claude mcp add --transport http pptgo https://pptgo.dev/api/mcp \
  --header "Authorization: Bearer pptgo_YOUR_TOKEN"
Generic JSON configThe same shape whether it goes in .mcp.json or an Agent SDK's mcpServers.
{
  "mcpServers": {
    "pptgo": {
      "type": "http",
      "url": "https://pptgo.dev/api/mcp",
      "headers": {
        "Authorization": "Bearer pptgo_YOUR_TOKEN"
      }
    }
  }
}
Codex CLICodex keeps secrets in the environment and stores only the variable name.
export PPTGO_TOKEN=pptgo_YOUR_TOKEN

codex mcp add pptgo --url https://pptgo.dev/api/mcp \
  --bearer-token-env-var PPTGO_TOKEN
~/.codex/config.tomlThe same thing by hand, if you would rather not use the CLI.
[mcp_servers.pptgo]
url = "https://pptgo.dev/api/mcp"
bearer_token_env_var = "PPTGO_TOKEN"

What the agent can do once it is connected

Sixteen tools, at the granularity the work actually arrives in: a page for writing, an element for adjusting. There is deliberately no write-the-whole-deck tool — that would let a model buffer everything and emit it at the end, and a deck appearing a page at a time is the part a person is watching.

Lay out
Eighteen page types and eight themes. The model fills named slots — a title and up to six points, four cards, a chart and its takeaway — and the grid, the type sizes that make them fit and the contrast-checked colours happen here. It never sees the render, so that half was never its to guess. What lands is ordinary elements, which the person who opens the deck drags around like anything else.
Read
List decks, read a deck's structure (including elements that have ended up somewhere wrong), read one slide in full. Read before writing, and again afterwards to check the result.
Write
Replace a page, append one, add or change a single element, set the theme. Every write carries the version it started from and is refused if that is no longer current, so two writers cannot bury each other.
Preview
Hand back a link, so a person can watch the deck being written.
Share
Publish a link anyone can open without signing in, check what it currently allows, and revoke it. Read-only unless you ask for more; a password is optional. The link lasts until it is revoked, so have the agent ask you before it publishes one.

About the preview link it returns

Every writing tool returns a previewUrl. That link carries its own read-only access, needs no sign-in and lasts a week — anyone it reaches can open it, so keep it out of public places. For a link you can revoke, lock with a password, or hand out with edit rights, use Share in your deck list instead.

When it will not connect

Everything comes back 401
The token is missing, or is not travelling in an Authorization: Bearer header. It may also have expired or been revoked — check Last used on the tokens page: a token stuck on “never used” means the requests are not carrying it at all.
The preview links point at the wrong host
Links are built from AUTH_URL. Under docker compose the container sees itself as web:3000, which is not an address anyone else can open, so a self-hosted deployment has to set that variable to the address people actually use.
The client connects but shows no tools
When authentication fails the server answers with a server that has no tools rather than an error. So “connected, but there is nothing there” is an authentication problem until proven otherwise.