All posts

What I Wish I Knew About Building ChatGPT Apps

Abe Wheeler
ChatGPT Apps MCP Developer Tools
sunpeak ChatGPT App simulator running locally.

sunpeak ChatGPT App simulator running locally.

After building several ChatGPT Apps, I’ve learned some important lessons that aren’t covered in the official documentation. Here are the three biggest takeaways that would have saved me hours of debugging and frustration.

TL;DR: Architect around MCP (Resources + Tools), cache-bust resource URIs on every build, and know that the runtime API has more undocumented fields.

Lesson 1: Embrace MCP

The ChatGPT App documentation makes Apps sound like they use MCP, but they’re not MCP themselves. That’s not quite right. Think of these apps as a GUI feature of MCP, and architect your apps entirely according to MCP concepts. Every UI/page is just a Resource and every API is just a Tool. Get comfortable with those abstractions. An App has one or more Resources, a Resource has one or more Tools.

My original toy apps didn’t properly adhere to those boundaries, and I found the abstractions I naturally built broke down when they came in contact with production ChatGPT. It’s a bit easier to recognize the core abstraction now that MCP started adding these interfaces to the protocol, but it’s only been a week and a half since they started, and the interfaces are still highly unstable.

Lesson 2: Invalidate all the caches

When deploying your App to ChatGPT, it can be difficult to tell if your Resource changes have been picked up. To make sure you’re always interacting with the latest version, you have to update the Resource URI on your MCP server AND “Refresh” your App from the ChatGPT Connector modal on every single change. I set up my project to append a base-32 timestamp to Resource URIs on every build so they always cache-bust on the ChatGPT side, but I still always have to refresh the connection on every UI change.

Lesson 3: But Wait! There’s More!

The official OpenAI documentation lists only about 2/3 of the actual runtime API. I’m not God or sama, so I can’t say that these undocumented fields are here to stay, but you can build more functionality than currently explained. Here’s the complete global runtime list that I just queried from my app running in ChatGPT:

callCompletion: (...i) => {…}
callTool: (...i) => {…}
displayMode: "inline"
downloadFile: (...i) => {…}
locale: "en-US"
maxHeight: undefined
notifyEscapeKey: (...i) => {…}
notifyIntrinsicHeight: (...i) => {…}
notifyNavigation: (...i) => {…}
notifySecurityPolicyViolation: (...i) => {…}
openExternal: (...i) => {…}
openPromptInput: (...i) => {…}
requestCheckout: (...i) => {…}
requestClose: (...i) => {…}
requestDisplayMode: (...i) => {…}
requestLinkToConnector: (...i) => {…}
requestModal: (...i) => {…}
safeArea: { insets: { … } }
sendFollowUpMessage: (...i) => {…}
sendInstrument: (...i) => {…}
setWidgetState: u => {…}
streamCompletion: (...l) => {…}
subjectId: "v1/…"
theme: "dark"
toolInput: {}
toolOutput: { text: 'Rendered Show a simple counter tool!' }
toolResponseMetadata: null
updateWidgetState: (...i) => {…}
uploadFile: (...i) => {…}
userAgent: { device: { … }, capabilities: { … } }
view: { params: null, mode: 'inline' }
widget: { state: { … }, props: { … }, setState: ƒ }
widgetState: { count: 0 }

Be careful with the example apps. They don’t respect all of these platform globals, documented or not. They also still don’t use the apps-sdk-ui React component library (as of this writing), so they’re already pretty outdated.

Try It Yourself

Hope that was helpful! If you’re interested in playing around with ChatGPT Apps, I built an open-source quickstart & local ChatGPT simulator that I’ve found really helpful for visualizing the runtime & iterating quickly.

Try the interactive ChatGPT simulator:

https://sunpeak.ai/simulator

Would really appreciate a star on GitHub if you can spare one!

Frequently Asked Questions

What is the relationship between ChatGPT Apps and MCP?

ChatGPT Apps are built on the Model Context Protocol (MCP). Think of ChatGPT Apps as the GUI layer of MCP. Every UI page is an MCP Resource, and every API endpoint is an MCP Tool. Architect your apps around these MCP concepts for best results.

Why aren't my ChatGPT App changes showing up after deployment?

ChatGPT aggressively caches MCP resources. You must update the Resource URI on your MCP server AND click "Refresh" in the ChatGPT Connector modal for every change. Use sunpeak's built-in cache-busting which appends timestamps to Resource URIs on every build.

Is the ChatGPT Apps runtime API fully documented by OpenAI?

No. The official OpenAI documentation covers only about two-thirds of the actual runtime API. Undocumented fields include callCompletion, downloadFile, notifyEscapeKey, requestModal, streamCompletion, and more that enable additional functionality.

What is the correct architecture for a ChatGPT App?

Structure your app according to MCP concepts: an App contains one or more Resources (UI pages/views), and each Resource can have one or more Tools (API actions). This architecture aligns with how ChatGPT expects to interact with your app.

How do I avoid caching issues when developing ChatGPT Apps?

Use sunpeak for development, which includes hot module replacement (HMR) and automatic cache-busting. Sunpeak appends unique identifiers to Resource URIs on every build, eliminating the need for manual cache invalidation.

What undocumented ChatGPT runtime APIs are available?

Undocumented APIs include callCompletion, streamCompletion, downloadFile, uploadFile, notifyEscapeKey, requestModal, requestCheckout, openExternal, sendFollowUpMessage, and more. These may change without notice but enable powerful features.

Should I use the official OpenAI example apps as reference?

Be cautious with the official openai-apps-sdk-examples. They don't use all platform globals and don't use the apps-sdk-ui React component library. Consider using sunpeak instead, which provides up-to-date, production-ready patterns.

sunpeak mountain
© 2026 sunpeak
Made in Austin, TX