How to Test an OpenAI Plugin Locally: A Complete Developer Guide
To test an OpenAI plugin locally, run your plugin server on localhost, expose it via an HTTPS tunnel using ngrok, update the manifest’s host field to the public URL, and register that URL in the OpenAI developer console to invoke the plugin through the ChatGPT UI.
OpenAI plugins are standard web services that expose an HTTP API described by a manifest file. Testing these plugins locally requires bridging your development environment to the OpenAI platform through a secure tunnel. This guide walks through the exact workflow used in the openai/plugins repository to test plugins on your own machine before deploying to production.
Start the Local Plugin Server
Every plugin begins with a runnable server that implements the endpoints defined in its manifest. According to the source code in the openai/plugins repository, the plugin-creator skill generates this scaffold from .agents/skills/plugin-creator/scripts/create_basic_plugin.py, creating either a Python Flask or Node.js Express server.
Below is a minimal Flask implementation that serves a list_items endpoint:
# server.py – start a local plugin server
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route("/openai/v1/operations/list_items", methods=["POST"])
def list_items():
# Your business logic here
return jsonify({"items": ["Item 1", "Item 2"]})
if __name__ == "__main__":
app.run(port=5000) # http://localhost:5000
Run the server with:
python server.py
Your plugin will now be available at http://localhost:5000, but the OpenAI platform requires HTTPS endpoints, so you must tunnel this local address to the public internet.
Expose localhost via HTTPS with ngrok
The OpenAI platform only accepts secure HTTPS URLs, rejecting plain http://localhost addresses. As documented in plugins/zoom/skills/zoom-apps-sdk/references/full-guide.md, the standard approach is using ngrok to create a secure tunnel.
Install ngrok, then expose your local port:
ngrok http 5000
Ngrok will generate a public URL such as https://a1b2c3d4.ngrok.io. This URL remains active as long as the ngrok process runs, routing all traffic to your local server. The ngrok web interface (http://localhost:4040) provides a request inspector for debugging, as noted in plugins/zoom/skills/zoom-apps-sdk/troubleshooting/debugging.md.
Update the Plugin Manifest
Each plugin contains a manifest at .codex-plugin/plugin.json that declares its API location and authentication settings. According to the repository layout in README.md, you must edit the host field and api.url field to point to your ngrok tunnel.
Update your manifest to match the tunnel URL:
{
"schema_version": "v1",
"name_for_human": "Example Plugin",
"name_for_model": "example_plugin",
"description_for_human": "Demo plugin used for local testing.",
"description_for_model": "Provides a list of example items.",
"auth": {
"type": "none"
},
"api": {
"type": "openapi",
"url": "https://a1b2c3d4.ngrok.io/openai.yaml"
},
"host": "https://a1b2c3d4.ngrok.io"
}
Ensure the host value exactly matches the ngrok HTTPS URL, including the protocol. If your plugin uses OAuth, the redirect URL configured in your OAuth provider must also match this tunnel address.
Register the Tunnel URL in the OpenAI Developer Console
With your server running and manifest updated, you must register the public URL with the OpenAI platform to test the plugin in ChatGPT.
- Navigate to OpenAI Platform → Plugins → Create a plugin → Add a custom plugin.
- Paste your ngrok URL (e.g.,
https://a1b2c3d4.ngrok.io) into the Plugin URL field. - Click Fetch to validate the manifest and load the plugin definition.
The console will verify that the manifest is accessible and that the API endpoints respond correctly. Once validated, the Test tab becomes available for live invocation.
Test and Debug via the Console
After registration, the OpenAI developer console provides a Test tab where you can invoke plugin actions directly. Requests sent from the ChatGPT UI travel through the ngrok tunnel to your local server, allowing you to see real-time logs and debug output.
To debug effectively:
- Monitor the ngrok request inspector at
http://localhost:4040to see raw HTTP requests and responses. - Check your local server logs for stack traces or validation errors.
- Iterate by modifying your plugin code, restarting the local server, and re-running test calls without changing the manifest (provided the ngrok URL remains constant).
Handle OAuth Redirects (if applicable)
If your plugin uses OAuth authentication, the authorization callback must redirect to your ngrok tunnel URL. As referenced in plugins/zoom/skills/oauth/references/oauth-errors.md, your local server must exchange the temporary code for an access token and store it securely.
Never store OAuth tokens in frontend storage or browser localStorage during local testing. Instead, maintain them in your server's memory or a local database until the testing session ends.
Summary
- HTTPS is mandatory – The OpenAI platform rejects plain HTTP URLs, requiring a secure tunnel like ngrok for local development.
- Update the manifest – Set the
hostandapi.urlfields in.codex-plugin/plugin.jsonto your public ngrok address. - Use the console Test tab – Register the tunnel URL in the OpenAI developer console to invoke your plugin through the ChatGPT UI.
- Monitor ngrok inspector – Use the ngrok web interface to debug requests and verify payload structures.
- Match OAuth URLs – Ensure OAuth redirect URLs point to the same tunnel address specified in the manifest.
Frequently Asked Questions
Do I need a public server to test an OpenAI plugin?
No, you can test entirely on localhost using an HTTPS tunnel. The OpenAI platform requires a public HTTPS URL to reach your endpoints, but you can create this temporarily using ngrok or similar tunneling services while keeping the actual server code on your local machine.
Why does my local plugin fail with "manifest not found" errors?
This error occurs when the host field in .codex-plugin/plugin.json does not match the URL you registered in the OpenAI console, or when the server is not running. Verify that your tunnel is active, the manifest is accessible at {your-ngrok-url}/.codex-plugin/plugin.json, and the host value uses the exact HTTPS URL including the protocol.
Can I use alternatives to ngrok for local testing?
Yes, any service that provides a public HTTPS tunnel to localhost will work, such as Cloudflare Tunnel, localtunnel, or Pagekite. However, ngrok is explicitly referenced in the openai/plugins repository documentation (particularly in plugins/zoom/skills/zoom-apps-sdk/references/full-guide.md) as the standard tool for local development.
How do I debug OAuth flows during local testing?
Configure your OAuth provider to use the ngrok URL as the redirect URI, then ensure your local server handles the callback at the correct path. Use the ngrok request inspector to verify that the authorization code is being transmitted correctly, and reference plugins/zoom/skills/oauth/references/oauth-errors.md for specific error handling patterns. Store tokens server-side only, never in the browser.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →