Skip to content

MCP

Point an agent at one MCP endpoint and it can list your Apps, read what a Function is running, deploy a new version, roll it back, and read the invocations that followed.

POST https://api.wawesome.io/v1/mcp

It is POST only. There is no server-to-client stream and no session to open or delete, because identity arrives with every request instead. Clients open GET and DELETE on it anyway, read the 405, and carry on over POST.

Nothing here takes a workspace as an argument. The credential the client presents decides which workspace every call acts inside.

Start from the buttons below, or follow the steps after them.

Claude Code

claude mcp add --transport http wawesome https://api.wawesome.io/v1/mcp

wawesome is listed in the Claude Connectors Directory:

  1. Open wawesome in the Connectors Directory.
  2. Click Connect. A tab opens on auth.wawesome.io.
  3. Sign in, pick what the connector may do, and approve.

The manual route still works. On Free, Pro and Max, you add it for yourself as a custom connector:

  1. Open Settings. In the browser, click your profile picture and then Settings. In the desktop app, press ⌘⇧, on macOS or Ctrl+, on Windows.
  2. Under Customize, click Connectors.
  3. Click Add custom connector.
  4. Paste https://api.wawesome.io/v1/mcp into the URL field.
  5. Leave Advanced settings closed. There is no client ID and no client secret to enter: the endpoint registers the client itself.
  6. Click Add. A tab opens on auth.wawesome.io.
  7. Sign in, pick what the connector may do, and approve. The tab closes and the connector is connected.

On Team and Enterprise, an Owner may need to allow wawesome before members can connect it from the directory. Some organizations only allow connectors an Owner has added. There, an Owner adds it once for everybody, from Organization settings, then Connectors, then Add, then Custom, then Web. Everyone else picks it up at Customize, then Connectors, then Connect, and signs in as above.

Custom connectors run through developer mode, which is on the Pro, Team, Enterprise and Edu plans.

  1. Open Settings, click Security and login, and turn on Developer mode. OpenAI has moved this toggle before. If it is not there, look under Connectors and then Advanced.
  2. Go to chatgpt.com/plugins and click the plus button.
  3. Give it a name and a description. Both are yours to write and neither reaches us.
  4. Under Connection, paste https://api.wawesome.io/v1/mcp as the MCP server URL.
  5. Create the connection. ChatGPT sends you to auth.wawesome.io to sign in and approve.
  6. Read the tools it lists back. That list is the endpoint’s own, so it is the check that the connection is live.

Authorization runs on auth.wawesome.io. The endpoint answers a client with no token by naming that address, so nothing about it has to be typed in.

You are never asked to paste a secret into a chat. The connector registers itself, either by declaring an address of its own that we read its metadata from, or through dynamic client registration. Claude and ChatGPT both do one of the two without being configured. Proof of possession is PKCE with S256, so no client secret exists anywhere in the flow.

What you do see is one screen, on the wawesome dashboard, after you sign in with GitHub or Google. It names the product asking, and it offers named jobs rather than a page of checkboxes:

  • Ship and read back, which reads the workspace, creates Apps, deploys Functions, sets environment variables and runs Functions.
  • Build in the workspace, which adds pausing schedules and creating previews.
  • Read and investigate, which writes nothing. It cannot publish, so every deploy made with it is refused.

None of those attaches a custom domain. A connector that asked for something no job matches gets a fourth choice, the words it named.

When the product asking is Claude, Claude Code or ChatGPT, one choice carries a “Recommended for” badge, sits first, and is the one the screen opens on. It is the words the product named where you get that fourth choice, and Ship and read back otherwise. Any other product gets no badge, and the screen opens on Ship and read back. The screen opens on the first choice your role lets you grant.

Below the job you can name the Apps the connector reaches. Leave it alone and it reaches every App, including the ones you create later. You can only grant what your own role in the workspace carries, and a job carrying a word you do not hold cannot be picked.

If you have never used wawesome before, that same screen creates the workspace. Installing the connector is the whole of signing up.

The access token the connector ends up with is good for an hour and it refreshes itself. That refresh replaces the credential’s secret where it stands rather than minting a second one, so a connector running daily for a year is one row in your workspace with its last-used date moving. It is listed for the workspace owner at Settings, then Credentials, marked Connector. Revoke it there and the connector’s very next call is refused.

A tool asks for the capability words behind the routes it calls, so the groups below are also the words to grant.

Reading is the largest group. whoami answers what the credential may do and where the workspace is administered, and it asks for nothing at all. Your Apps need read:apps. Your Functions, their versions, the source a version is running and the files it carries need read:functions. Invocations, their logs and a diagnosis of the latest failure need read:invocations. This month’s usage against what your plan includes needs read:tenant.

Deploying is write:functions. One call sends a Function’s code, the static files it serves beside it, or both, and promotes what it made. rollback_function puts an earlier version back. Code and files move together, because they are one version. list_versions says how many files each version carries, so you can see whether a rollback takes the pages off the address before you do it.

The deploy call also takes an optional message, one line about what this version carries, in words you would recognise it by. The version keeps it, and list_versions gives it back beside each number. It is at most 200 characters and one line. A longer one turns the deploy down rather than cutting it.

Running a Function is write:runs, and there are two ways to do it. invoke_function calls the handler. fetch_function asks the live version for one path and answers the bytes it served. That is how an agent checks a page without asking you to open a browser and describe what you saw.

read_function_file reads one file a version carries, by its path: a page, a stylesheet, a private file or the code. It reads the file as you deployed it, so nothing runs and no invocation is left. It reads the live version unless you name another. A long file comes back in parts the same way as fetch_function, and a file that is not text answers its type and size with no body.

A draft is a private copy of a Function’s files that an agent can change before anything goes live. deploy_function makes a change live as soon as it lands, and a draft keeps it off the live address until promote_draft. open_draft opens one on the live version, or on a version you name, and gives it a short name. A draft never shows in the Function’s versions, its source or its file list, and the Function’s own address never serves its files. Only its preview link does. read_function_file reads a draft’s files when you pass its draft_id. list_drafts shows every open draft on a Function and who owns it, and discard_draft ends one. Opening, editing, previewing, discarding and promoting need write:functions. Listing, reading and showing changes need read:functions.

edit_draft changes a draft. One call can carry several operations on several files: add a file from its text or from the hash of a file you uploaded, write a whole file, replace one piece of text, and delete a file. The operations run in order. Either all of them apply or none do, and the draft’s revision goes up by one. A replace names the exact text to find. If that text is not in the file, or is in it more than once, the whole edit is refused and the error says which.

get_draft_changes lists the paths a draft added, changed and deleted compared with the version it started from, and its revision. An agent in a new conversation uses it to see where the work stands.

preview_draft gives a preview link for a draft. It uses the same kind of hostname as a version’s preview, {tenant}--{app}--prev-{token}, and anyone holding the link can open it. The link shows the draft as it is at each request, so after another edit a reload shows the new content. You do not need a new link. If the draft changes the code, the link runs the draft’s code, and the Function’s own address keeps running the live code. The link lasts 24 hours unless you pass ttl_hours, at most a week. It stops working when the draft ends and then answers 404, the same as a link that never existed. Anyone in the workspace can preview a draft, not only its owner.

promote_draft makes a draft live as a new version, with a message, and ends the draft. It names the revision the person approved. If the draft changed after that, the promote is refused with draft-moved-on. If the live version changed since the draft was opened, the promote keeps both sides where it can: a file only the draft changed takes the draft’s copy, and a file only the live version changed keeps the live copy. A file both changed is refused with draft-conflicts, and the error names it. The text inside a file is never merged, and nothing goes live. A promote that changes nothing is refused, the same as a deploy of a version that already exists.

A draft belongs to whoever opened it: a person, or a deploy credential. Anyone in the workspace can list it, see its changes and preview it, but only its owner can edit, discard or promote it. Each owner can have at most 5 open drafts on one Function. A draft does not expire. Its files count toward your storage allowance until it ends, and an edit that would go past the allowance is refused the same way a deploy is.

A draft ends when it is discarded or promoted. It also ends when its Function is deleted, when the person who opened it is removed from the workspace, and when the deploy credential that opened it is deleted. Its preview link stops working, and its files stop counting toward your storage.

The Function’s page in the dashboard lists its open drafts, with each one’s name and owner, and makes a preview link on request. Only the owner can discard a draft there. If the dashboard assistant opened the draft, the page links to that conversation. Continue in a new conversation starts one that already knows the draft, so the assistant picks it up. A draft opened by a deploy credential has no conversation to link to.

If the live version was deployed with the CLI, every draft tool says so and adds a warning: the next CLI deploy, most likely from your repository, replaces what the draft changes. It is a warning, and the tool still does what you asked.

A body longer than 64 KB comes back in parts. Each answer gives next_offset, the byte where the next part starts, and the agent passes it back as offset to read on. Every part is a new request, so it runs the Function again and leaves its own invocation. A page that changes between two calls can come back as parts that disagree. The tool reads at most 1 MB of one answer.

Environment variables are write:env. A value set this way travels through the conversation, and through whatever the chat product keeps of it. That is fine for a feature flag and wrong for an API key. Set a real secret yourself at the dashboard. The tool’s own description states where a value passes, so the agent reads that too.

Custom domains are write:domains. attach_domain answers the DNS records to add, per half of the name, in the order to add them. Nobody but you can add them, because they go in at your DNS provider.

The template catalogue is public, so list_templates and get_template ask for nothing. Each template says needs_build. Every template except landing-page says true: it is written in TypeScript, and most import npm packages. deploy_function runs no build and no npm install, so it can’t ship those files as they are. For those, get_template says to scaffold and deploy the template with the CLI, on a machine with Node.js: npx wawesome init --template <name>, then npx wawesome deploy from its directory.

When the work needs a file only you have, request_upload answers a link to hand you. You open it signed in and drop the files in. list_uploads then tells the agent what landed and how to declare it in the next deploy. read_upload reads a text file you sent, such as a CSV, a page at a time.

The upload page takes images, fonts, video, audio, stylesheets, scripts, PDFs and reference data: .csv, .tsv, .md, .ics, .json and .txt. It refuses .html, .htm, .svg and .xml, because those are served as markup and markup is the agent’s to write. It also refuses any extension the platform does not serve. The page says why before the file uploads, and the server refuses the same files.

Each file takes a short description of where it belongs. There is also one field for instructions about the whole set, such as “the photos for the gallery, in this order”, up to 1,000 characters. You can change it until the link expires. The agent reads both, and for a png, jpeg, gif, webp or avif it also gets the width and height, read from the file itself.

Each file has its own Send button. With two or more files waiting, Send all sends them all, a few at a time, each with its own description. A file that fails stays on the page with its error and its own Send button, and the others still go.

A deployed .csv is served as text/csv, .tsv as text/tab-separated-values, .md as text/markdown and .ics as text/calendar, each with charset=utf-8.

A credential carries capability words. A tool the credential does not cover refuses, and the refusal names every word it is short of at once:

{
  "status": "error",
  "reason": "credential-missing-capability",
  "error": "This deploy credential does not carry the 'read:invocations' and 'read:functions' capabilities, which the 'diagnose_latest_failure' tool requires.",
  "missing_capability": "read:invocations",
  "missing_capabilities": ["read:invocations", "read:functions"],
  "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}

Both words are named at once, so you widen the credential once rather than being sent back for each missing word in turn.

That is an answer, not a failure to retry. Calling it again with the same credential refuses again, and it will refuse a year from now. The way past it is a wider credential. Add the connector again and approve a job that carries the words.

A member calling the endpoint on their own session reads a different sentence, naming the role they hold rather than a credential. That one is not theirs to widen. Somebody in the workspace who can hand out roles has to do it.

The tool list never shrinks to match the credential. Every tool is listed for every caller, so an agent that cannot deploy still knows deploying exists and can tell you what to grant. That is why whoami is worth calling first. It answers the words the credential holds, and it marks which of them a tool here actually asks for.

One kind of project still belongs in the CLI, and it is a common one. Anything that runs a framework build. There is no build step and no bundler here, and a deploy ships exactly what it declared. So a Next.js or Astro or Vite project has to be built on your own machine. The CLI runs that build and uploads what it produced.

It needs Node 22.13 or newer, and nothing else. Two commands, from the project’s directory:

npx wawesome login
npx wawesome deploy

login opens your browser and saves a token. deploy builds, uploads and promotes. Both are walked through in getting started, and every command the CLI has is in the CLI reference.

Files off your machine are not on this list. A logo, a photograph, a font or a video does not need the CLI. Ask the agent for them and it calls request_upload, which answers a link that opens for you and for nobody else.