CodeGym /Courses /ChatGPT Apps /Dev Mode in ChatGPT...

Dev Mode in ChatGPT: connecting a local app

ChatGPT Apps
Level 2 , Lesson 3
Available

1. What Developer Mode is “in practical terms”

You already know a bit about Dev Mode, but now it’s important to assemble a complete picture grounded in real practice.

Developer Mode in ChatGPT is a special mode in which the platform lets you plug in your app directly, without publishing to the Store. You tell ChatGPT: “Here’s the URL of my MCP server,” and ChatGPT treats it as an external tool with a UI—it can call its tools, load widgets, and do all of that within a regular chat.

Architecturally, in Dev Mode ChatGPT acts as an MCP client, and your Next.js template—as an MCP server. ChatGPT establishes a connection to /mcp, asks “What can you do?” (a list of tools and resources), and then during the conversation can invoke these tools and display your widgets in an iframe.

Important to separate Dev Mode from the Store:

  • Dev Mode is your personal little “garage”: you can break things, experiment, and change the tool schema every five minutes without worrying about users.
  • Store is the showcase: it’s for stable versions after review, with proper policies, descriptions, etc. We’ll get there at the end of the course; for now, we’re playing in the garage.

As of late 2025, Dev Mode with the Apps SDK is available on all ChatGPT plans, but in enterprise accounts you may need an administrator to enable it at the workspace level. If the Developer Mode toggle doesn’t appear in your settings, that’s the first thing to check.

2. What we already have at the start of the lecture

Before clicking anything in the ChatGPT UI, make sure your local setup is ready.

First, a Next.js dev server. In your project root you’ve already run:

npm run dev

By default, Next.js 16 listens on port 3000, so your UI is available at http://localhost:3000.

Second, the MCP route. In the CodeGym Labs template, the MCP server is implemented as a route handler at app/mcp/route.ts. That’s where tools and resources are registered; that’s also where the first requests from ChatGPT will arrive when you connect the app in Dev Mode.

From an architectural perspective, it currently looks like this:

Your browser ──> http://localhost:3000 (Next.js dev, UI)
                           │
                           └── /mcp (MCP server inside Next.js)

There’s no connection to ChatGPT yet—it lives in the cloud, and your localhost isn’t visible to it. Detailed tunnel setup is the topic of the next lecture. For simplicity here, we’ll assume you already have some public HTTPS URL to /mcp (for example, via ngrok or Cloudflare Tunnel configured per the template’s README).

If you haven’t brought up a tunnel yet—that’s fine. For now, at least walk through the whole Dev Mode chain with your eyes and see exactly what you’ll need to do once you have an HTTPS URL.

If you already have an HTTPS URL to /mcp, you can go ahead and perform all the steps hands-on.
If not yet—treat this lecture as a “UI tour”: it’s important to understand the sequence of steps; we’ll do a real run in the next lecture when we set up the tunnel.

3. Enabling Developer Mode in the ChatGPT interface

The first step is simply getting ChatGPT to show the settings we need. Do the following:

First, open the web version of ChatGPT with the account you’ll use for development. Click your profile icon in the lower left (or upper right—the UI evolves constantly) and choose Settings.

In Settings, find the section related to apps: it’s usually called Apps & Connectors or Connected apps. Open that section. At the bottom of the page (or under Advanced) you’ll see a Developer Mode toggle. That’s what you need to enable.

After turning on Dev Mode, ChatGPT usually shows a notice that developer mode is enabled. In the same section, a button like Create, Create connector, New app will appear—the wording may vary slightly, but the idea is the same: there’s now a way to create your own connected app.

If your settings have neither an Apps & Connectors section nor a Developer Mode toggle, check:

  • you’re actually logged into the ChatGPT account you intend to use;
  • on an enterprise account, this mode may be enabled by a workspace administrator.

Sometimes simply signing out and back in is enough (the classic “reconnect the internet” for Dev Mode).

4. Creating your app/connector and specifying the MCP URL

Now that Dev Mode is enabled, let’s register your GiftGenius in ChatGPT. Below is the “how to do it for real” scenario. If the HTTPS URL isn’t set up yet, treat the steps as a dry run: just see what exactly we’ll do once the tunnel is available.

Everything is done from the ChatGPT settings section where you just were. The flow will be roughly as follows.

Open Settings again → Apps & Connectors. Inside, you’ll see a list of connected apps (likely empty for now) and a Create / Add connector button. Click it—a form to create an app will open.

The form usually has three key fields:

  1. Name. A human-readable name visible to you and ChatGPT. For this course, it’s convenient to name the app, for example, GiftGenius (dev)—so it’s immediately clear it’s a local dev version.
  2. Description. A brief explanation of what the app does and when it should be used. Example: “Picks gift ideas based on a person’s interests.” This line later influences discovery—the model uses it to decide when to suggest your App in chat.
  3. MCP server URL (sometimes labeled Connector URL, MCP endpoint, App URL, etc.). This is the most important field: paste a public HTTPS URL that points to your app’s /mcp.

For example:

https://my-giftgenius-dev.ngrok.app/mcp

or

https://giftgenius-dev.trycloudflare.com/mcp

Key nuances for this field:

  • it must be https://, otherwise ChatGPT simply won’t connect;
  • make sure the path ends with /mcp, because that’s where the MCP server lives inside the template; this exact path is specified in the official Apps SDK documentation.

We’ll go over where to get this URL in the next lecture (tunnels, Cloudflare, ngrok). For now, the important idea: your local http://localhost:3000/mcp must somehow become a public https://…/mcp, and that public address is what you paste into the form.

After filling out the fields, click Create / Save. At this moment, ChatGPT performs a “handshake” with your server: it sends HTTP requests to the specified URL, expects to receive a capability manifest (a list of tools/resources, metadata), and verifies that the server responds using the MCP protocol. If everything is fine, the connector will appear in the list and you’ll see which tools ChatGPT discovered. In the next section we’ll break down what exactly happens during this handshake and how to view it in logs.

If you haven’t set up a tunnel and you pasted a dummy URL, ChatGPT will frankly report that it couldn’t reach the server. That’s useful too: you’ll immediately see where and how errors are shown.

5. What’s happening “under the hood”: the MCP handshake in plain terms

From the outside, it looks like a simple “add an app by URL” form. Inside, it’s a bit more interesting, and understanding it now helps a lot later when debugging.

You’ve already seen that when creating a connector, ChatGPT calls your /mcp and expects a manifest. Let’s unpack that conversation a bit more—this helps tremendously when debugging.

When you press Create, ChatGPT takes several steps.

First, it requests the provided URL with /mcp, acting as an MCP client. Per the MCP protocol, it expects that an HTTP endpoint hosts a server implementing baseline capabilities: list tools (list tools), provide resources (widgets), and handle tool invocations.

The server, in turn, responds with a JSON structure describing:

  • the server name and version;
  • a list of tools: name, title, description, inputSchema, etc.;
  • a list of resources: where to fetch HTML for your widgets, which MIME types, how to render them.

In the CodeGym Next.js template, all of this is already implemented in app/mcp/route.ts: using the SDK, it does something like server.registerTool(...) and server.registerResource(...).

If you want to see this handshake with your own eyes, you can add a simple log in app/mcp/route.ts. This is more of a debug trick for developers; you can skip it and come back later when you want to dig deeper:

// app/mcp/route.ts
import { NextRequest, NextResponse } from "next/server";
// import your already existing server / buildManifest

export async function GET(req: NextRequest) {
  console.log("[MCP] Handshake from ChatGPT:", req.headers.get("user-agent"));
  const manifest = buildManifestSomehow(); // this already exists in the template
  return NextResponse.json(manifest);
}

This function is a bit schematic (the template’s structure may differ), but the idea is simple: app/mcp/route.ts is an ordinary Next.js route handler, and you can log incoming requests. On a successful Dev Mode connection, you’ll see this log in the terminal where npm run dev is running.

Protocol-wise, you can draw it as a small diagram:

sequenceDiagram
    participant ChatGPT
    participant Tunnel as HTTPS URL (/mcp)
    participant NextDev as Next.js dev + MCP

    ChatGPT->>Tunnel: HTTP(S) request to https://.../mcp
    Tunnel->>NextDev: Proxies to http://localhost:3000/mcp
    NextDev-->>Tunnel: JSON with tools and resources
    Tunnel-->>ChatGPT: Forwards the response
    ChatGPT->>ChatGPT: Caches the list of tools/resources

The fact that you entered “just a URL” in the Dev Mode form actually triggers a full protocol conversation.

6. How ChatGPT “sees” your app after connection

Assume the handshake was successful. What now?

First, in Settings under Apps & Connectors, your GiftGenius (dev) will appear in the connected apps list. Inside the card you’ll see the name, description, and the list of discovered tools. There are usually buttons like Refresh, Delete, etc. The Refresh button will be useful later when you change the tool schema.

Second, the app becomes available in chats. Open a new chat, click the “+” next to the input field. There’s a “More”, “Apps”, or “Tools” menu—depending on the current UI version. Your GiftGenius (dev) should appear in the list, and you can explicitly select it for that conversation.

After selection, the app becomes “connected” to that chat. It looks like this to you:

  • you write a natural request, for example: “Pick a gift for a space fan for 50$”;
  • ChatGPT decides (based on the description and the dialogue history) that it can use GiftGenius, and invokes one of your MCP tools;
  • the result of that call may contain an HTML widget, which is rendered right in the chat as a card/panel.

In Dev Mode, you’ll often start by invoking the app explicitly—via the menu or by mentioning it by name. But it’s important to understand: in production, ChatGPT can “suggest” your App on its own, guided by its description and tool metadata.

For clarity, another small table helps:

Where you are now What you see What it means
Settings GiftGenius (dev) in the app list Connector created, MCP is alive
Chat → “+ GiftGenius (dev) in the Apps/Tools list Can connect it to the current chat
Conversation Text + a GiftGenius widget/card A tool was invoked via MCP

7. The developer loop: change code → see it in ChatGPT

Connecting an App is half the job. The other half is understanding how to live with Dev Mode day to day.

There are two broad types of changes: UI changes (the widget) and MCP logic/tool changes.

If you only change the UI, for example you edit a heading or styles in app/page.tsx, this is a standard frontend workflow for Next.js. The dev server hot-reloads the module, and you see the hot reload in the browser. In ChatGPT, your UI opens in an iframe, but the behavior is similar: on the next invocation of the tool that renders this widget, ChatGPT will load the updated HTML. Sometimes HMR reaches the iframe directly; other times it’s enough to just invoke the tool again in chat. CACHING

Try making a small widget change. Suppose in app/page.tsx you have something like:

export default function GiftGeniusWidget() {
  return (
    <main style={{ padding: 16 }}>
      <h1>GiftGenius</h1>
      <p>Gift selection will be here.</p>
    </main>
  );
}

Change the heading and the text:

export default function GiftGeniusWidget() {
  return (
    <main style={{ padding: 16 }}>
      <h1>GiftGenius (dev)</h1>
      <p>This version runs in Dev Mode. Not for production gifts.</p>
    </main>
  );
}

Save the file, return to the chat with GiftGenius connected, and invoke the app again (for example, with the same gift request). You should see the updated heading inside the widget—that’s a good sign that the chain Next.js → tunnel → ChatGPT is working.

If you change the MCP part—add a new tool, modify an inputSchema, rename tools—then ChatGPT caching comes into play. On the first Dev Mode connection, ChatGPT remembers the tool list and won’t always pick up changes automatically. In that case, go back to Apps & Connectors, select your GiftGenius (dev), and click something like Refresh schema / Refresh. After that, ChatGPT will poll your /mcp again and update the tool list.

It seems minor, but without this it’s easy to end up in a situation where you’ve updated the tool code but ChatGPT stubbornly doesn’t see the new parameters.

8. Mini practice: the first full GiftGenius scenario in Dev Mode

Let’s put it all together in a practical scenario. Here I’ll assume you have some working public HTTPS URL for /mcp (via a tunnel or a deploy). If not—just read through; in the next lecture you’ll repeat the steps with a real URL.

  1. Make sure npm run dev is running and logs show no errors. It’s especially nice to see something like “MCP server running at http://localhost:3000/mcp” in the terminal if the template logs it.
  2. Open ChatGPT, enable Developer Mode via Settings → Apps & Connectors → Advanced settings.
  3. Create a new connector GiftGenius (dev) with a short description (“Helper for choosing gifts”) and a URL like https://<your-domain>/mcp.
  4. Verify that ChatGPT could connect: you’ll see a new item in the app list. If there’s no connection—check the dev server and tunnel logs; that’s useful in itself.
  5. Open a new chat, click “+”, select your GiftGenius (dev), then phrase a request: “Pick a gift for a developer who loves space and coffee, budget 40$.”
  6. See what your current template does: in its basic form, it may show a simple card/widget. It’s not “smart gift selection” yet, but the fact that something from your code appears in the chat is already a huge step.

As an extra exercise, you can add a dedicated test tool in the MCP server just to verify Dev Mode. Example (no need to implement right now—just look at the idea):

// inside app/mcp/route.ts, next to other tools
server.registerTool(
  "ping_dev",
  {
    title: "Ping GiftGenius dev",
    description: "Checks that the dev server is alive.",
    inputSchema: { type: "object", properties: {} },
  },
  async () => ({
    content: [{ type: "text", text: "GiftGenius dev is alive ✅" }],
    structuredContent: {},
  })
);

We’ll dive into server.registerTool in detail in the module about tools; for now just remember: with MCP, you describe “what your App can do,” and Dev Mode is the way to give ChatGPT the URL where those capabilities are declared.

9. Where to look for errors and how to tell “it broke on my side” from “it broke on ChatGPT’s side”

Nobody likes to spend half an hour hunting bugs “in the wrong half of the system,” so it’s useful to build the habit of looking in the right place from the start.

If an error occurs while creating the connector. If, when creating the connector, ChatGPT says it can’t connect the App, first check the logs of your dev server and tunnel. If the terminal running npm run dev shows no incoming requests to /mcp at all—the problem lies on the ChatGPT → tunnel path. If requests arrive but the server returns 500 or crashes with an error in the console—the issue is in your MCP code.

If the connector is created but things break in chat. When the connector already exists but the chat occasionally shows “App unavailable / App broken,” that almost always means:

  • the dev server crashed (Next.js stopped listening on port 3000);
  • the tunnel is off or the URL changed;
  • the MCP endpoint returns an error, times out, or responds too slowly.

Separately about the UI/widget. For UI issues (widget not rendering, blank screen, odd styles), open your browser DevTools as well. The widget loads in an iframe, and the console of that iframe shows JavaScript/React errors—exactly like in a regular web app.

With experience, you’ll start distinguishing “smells like the tunnel” from “smells like Next.js” by the nature of the error, but for now it’s enough to remember: you have three potential points of failure—your code, the tunnel, and ChatGPT—and the likelihood that the problem is in ChatGPT is usually the lowest.

Insight

If you’re reading this and you don’t have a paid tunnel, you can buy one right now. You’ll end up doing it in the next couple of days anyway. So just save yourself the trouble.

10. Common mistakes when working with Dev Mode

Error #1: forgot to enable Developer Mode and spent half an hour looking for the Create button.
Sometimes developers go straight into ChatGPT, open Settings → Apps & Connectors, and don’t see anything interesting. Without Developer Mode enabled, the connector creation button may simply be missing. Always start by checking that Dev Mode is enabled in Advanced settings, especially on new accounts or in a different browser.

Error #2: pasted a URL without /mcp or not an MCP endpoint at all.
A classic: in the URL field they paste https://myapp-dev.ngrok.app without the /mcp path, or even a landing page/another service URL. ChatGPT politely knocks there using the MCP protocol, doesn’t find the expected interface, and reports a connection error. The Next.js starter template clearly says: connect to the URL that points to /mcp—and that’s exactly what you should specify in Dev Mode.

Error #3: trying to use http://localhost:3000/mcp directly.
It’s intuitive to paste into the URL field the same http://localhost:3000/mcp you see in the dev server logs. But ChatGPT runs in the cloud, not on your laptop, and it has no access to your localhost. Besides, ChatGPT requires HTTPS. Without a tunnel or remote deploy, nothing will work. This isn’t a ChatGPT bug; it’s normal network isolation.

Error #4: forgetting to Refresh after changing the MCP schema.
After a successful handshake, ChatGPT caches the list of tools and metadata to avoid hitting your server on every turn. If you added a new tool or changed its inputSchema, but ChatGPT continues to behave as before, you almost certainly need to Refresh the connector in Apps & Connectors. Without this, the model simply doesn’t know the tools have changed.

Error #5: trying to debug Dev Mode when the dev server isn’t running.
Sounds obvious, but it happens a lot: a student configures Dev Mode and a tunnel remotely while npm run dev hasn’t been running for a while or the project fails to build due to a syntax error. As long as the local dev server is down, chasing Dev Mode errors is pointless. Always first ensure http://localhost:3000 works in your browser, and only then connect ChatGPT.

Error #6: expecting Dev Mode to be “a different model that understands everything”.
Sometimes it seems that since we enabled Dev Mode, the model now “knows” everything about our app. In reality, Dev Mode doesn’t change the model itself; it simply gives it access to your MCP server and tools. If your tools are described vaguely, your App description is unclear, or the server logic is odd, the model will be confused just like any developer opening a poorly documented API. Good metadata and tools are topics for later modules, but it’s worth keeping in mind already.

Error #7: using Dev Mode as production.
It’s tempting: “Well, everything works fine in Dev Mode, let’s just give users a link so they can connect the App via this URL.” The problem is that Dev Mode isn’t intended for mass use: tunnels are unstable, configurations may break, and ChatGPT itself may change Dev Mode behavior without backward compatibility. For real users there’s the Store and production deploy. Dev Mode is your lab only.

1
Task
ChatGPT Apps, level 2, lesson 3
Locked
MCP endpoint card
MCP endpoint card
1
Task
ChatGPT Apps, level 2, lesson 3
Locked
MCP handshake logging (visible in the terminal when a request to /mcp arrives)
MCP handshake logging (visible in the terminal when a request to /mcp arrives)
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION