Welcome to the ChatGPT Plugin Quickstart repository. This boilerplate is designed to kickstart your journey to develop custom ChatGPT plugins. This version is built using JavaScript and Express.js, providing a robust and scalable foundation for your plugin development.
This sample plugin is designed to interact with the API-Ninja's API, showcasing how ChatGPT can seamlessly integrate with external APIs to enhance its capabilities.
The plugin is equipped with a single endpoint that fetches airport data based on a city name provided by the user. This serves as a simple yet functional example to demonstrate the potential of ChatGPT plugins.
- Clone the repository:
git clone https://github.com/soos3d/chatgpt-plugin-development-quickstart-express.git
- Install dependencies:
npm install
- Edit
.env.sample
file:
Edit the .env.sample
file to add your API Ninjas API key, then rename it to .env
.
Get your API key on the API Ninjas website.
- Serve the plugin:
node index
The plugin is now running on http://localhost:3333
- Optional: I recommend utilizing Nodemon for your server applications for a smoother development process. This tool offers the convenience of automatic server restarts whenever changes are saved, enhancing your efficiency and productivity.
npm install -g nodemon # or using yarn: yarn global add nodemon
- Serve the plugin with
nodemon index
- Install the plugin in ChatGPT:
Navigate to the Plugin Store and select the Develop your own plugin option. In the provided field, enter localhost:3333
. The system will then locate the manifest and the OpenAPI schema, installing the plugin for you.
The operation of a ChatGPT plugin is straightforward and can be broken down into four key components:
-
An application: There is an application that performs a specific function. This could range from executing an API call to retrieve data or interact with other services to implementing various types of logic, such as performing arithmetic operations or even handling more complex tasks.
-
A server: There is a server with endpoints that facilitate communication with your application and invoke its functions. ChatGPT interacts with the plugin through this server.
-
OpenAPI Schema: This is a comprehensive documentation of the available server endpoints. ChatGPT uses this schema to understand the plugin's capabilities and determine when to call a specific endpoint.
-
Plugin manifest: A JSON file that contains detailed information about the plugin. It provides ChatGPT with a clear understanding of the plugin's purpose and functionality and the URLs needed to locate the server and the logo.
Upon installing a plugin via the ChatGPT user interface, the system establishes a connection to the server, locates the manifest and the OpenAPI schema, and subsequently prepares the plugin for use.
The fundamental structure of this plugin is outlined below. Please note that it can be tailored to meet your specific requirements.
root-directory
│
├── .well-known
│ └── ai-plugin.json
│
├── src
│ └── app.js
│
├── .env
│
├── index.js
│
├── openapi.yaml
│
└── logo.png
In this structure:
- .well-known/ai-plugin.json is the plugin manifest.
- src/app.js is the main application file.
- .env is the environment variables file.
- index.js is the main server file.
- openapi.yaml is the OpenAPI schema.
- logo.png is the logo of the plugin.
In this example, the application is straightforward and is the app.js
file. It is a simple Node.js module that fetches airport data for a given city using the API Ninjas Airports API. Here's a step-by-step breakdown:
-
require('dotenv').config();
- This line loads environment variables from a.env
file intoprocess.env
. This is a common practice to keep sensitive data, like API keys, out of the code. -
const axios = require('axios');
- This line imports the Axios library, a popular, promise-based HTTP client for making requests. -
const API_KEY = process.env.API_KEY
- This line retrieves the API key from the environment variables and assigns it toAPI_KEY
. -
async function getAirportData(city) {...}
- This is an asynchronous function that fetches airport data for a given city.- Inside this function, an
options
object is created with the necessary details for the API request: the HTTP method, the URL (which includes the city name), and the headers (which includes the API key). - A
try/catch
block is used to handle potential errors during the API request. If the request is successful, the function returns the data from the response. If an error occurs, it logs the error message to the console.
- Inside this function, an
-
module.exports = { getAirportData }
- This line exports thegetAirportData
function so it can be imported and used in the server application.
This is the application itself.
The server is the index.js
file.
This code sets up a simple Express.js server with various endpoints to serve a ChatGPT plugin. Here's a step-by-step breakdown:
-
The code begins by importing the necessary modules, including Express, path, cors (for handling Cross-Origin Resource Sharing neessery for ChatGPT to find the plugin), fs (for file system operations), and body-parser (for parsing incoming request bodies). It also imports a custom module,
getAirportData
, from./src/app
. -
The Express application is initialized, and the port number is set based on the environment variable
PORT
or defaults to 3000 ifPORT
is not set. -
The application is configured to parse JSON in the body of incoming requests using
bodyParser.json()
. -
CORS is configured to allow requests from
https://chat.openai.com
and to send a 200 status code for successful preflight requests for compatibility with some older browsers. -
A helper function,
readFileAndSend
, is defined. This function reads a file and sends its contents as a response with the appropriate content type. -
Several routes are set up:
- The
/.well-known/ai-plugin.json
route serves the plugin manifest. - The
/openapi.yaml
route serves the OpenAPI schema. - The
/logo.jpg
route serves the plugin's logo image. - The
/airportData
route accepts POST requests and fetches airport data for the city specified in the request body. If an error occurs while fetching the data, it sends a 500 status code and an error message.
- The
-
A catch-all route is set up to handle any other requests. This route sends a 501 status code and a message indicating that the requested method and path are not implemented.
-
Finally, the server is started and listens for requests on the specified port. A message is logged to the console indicating that the server is running and on which port.
This serves as the heart of the plugin, enabling ChatGPT to establish a connection, locate the manifest and OpenAPI schema to comprehend its functionality, and ultimately access the endpoints that interact with the application.
The OpenAPI schema, also known as an OpenAPI specification, is a powerful tool for describing and documenting APIs. It's a standard, language-agnostic specification for RESTful APIs, which allows both humans and computers to understand the capabilities of a service without needing to access the source code, additional documentation, or network traffic inspection.
In an OpenAPI schema, you define all the aspects of your API. This includes:
-
Endpoints (Paths): These are the routes or URLs where your API can be accessed. For example, in a weather API, you might have an endpoint like
/weather
to get the current weather. -
Operations: These are the actions that can be performed on each endpoint, such as GET, POST, PUT, DELETE, etc. Each operation will have its parameters, request body, and responses defined.
-
Parameters and Request Body: These define what data can be passed to the API, either as part of the URL, as query parameters, or in the body of a POST or PUT request.
-
Response: This defines what the API returns after an operation, including various status codes, headers, and the body of the response.
-
Models (Schemas): These are definitions of the data structures that the API uses. For example, a User model might include fields for the user's name, email, and password.
By using an OpenAPI schema, developers can understand how to use your API without having to read through all your code or rely on extensive external documentation. It also enables the use of automated tools for tasks like generating code, testing, or creating interactive API documentation.
The 'description' field of the endpoint serves as a prompt for ChatGPT, providing an area where you can include additional details. Please be aware that this field has a character limit of 300.
The manifest file is a JSON file that provides essential information about the plugin to ChatGPT. Here's a breakdown of what each field represents:
-
schema_version
: This field indicates the version of the schema that the plugin is using. In this case, it's "v1". -
name_for_human
: This is the name of the plugin as it should be displayed to humans. Here, it's the "Airport info plugin". -
name_for_model
: This is the name of the plugin as it should be referred to by the model. Here, it's "AirportInfo". -
description_for_human
: This is a description of the plugin for humans. It should provide a clear explanation of what the plugin does. In this case, it's "ChatGPT plugin for airport data API. Returns airport info by city name. Aids developers in ChatGPT plugin development." -
description_for_model
: This is a description of the plugin for the model. It should provide a clear explanation of what the plugin does. In this case, "This plugin interacts with the Ninja API and returns airports info based on the city the user inputs." -
auth
: This field describes the type of authentication required by the plugin. In this case, it's "none", meaning no authentication is required. -
api
: This field provides information about the API used by the plugin. It includes the type of API (in this case, "openapi"), the URL where the OpenAPI schema can be found, and a boolean indicating whether user authentication is required. -
logo_url
: This is the URL where the logo for the plugin can be found. -
contact_email
: This is the contact email for the developer or team responsible for the plugin. -
legal_info_url
: This is the URL where legal information about the plugin can be found. In this case, it's empty.
Find more information on the OpenAI docs.
In conclusion, this tutorial provides a comprehensive guide to developing custom plugins for ChatGPT using JavaScript and Express.js. It offers a practical example of how to create a plugin that interacts with an external API (in this case, the API-Ninjas Airports API) to fetch and return airport data based on a city name provided by the user.
The tutorial covers all the key components of a ChatGPT plugin, including the application that performs the specific function, the server with endpoints that facilitate communication with the application, the OpenAPI schema that documents the available server endpoints, and the plugin manifest that provides essential information about the plugin to ChatGPT.
By following this guide, developers can gain a solid understanding of how to create a functional ChatGPT plugin, from setting up the server and defining the endpoints, to creating the OpenAPI schema and the plugin manifest. The tutorial also provides valuable tips and best practices for developing plugins, such as using Nodemon for automatic server restarts during development, and the importance of providing clear and concise descriptions in the OpenAPI schema and the plugin manifest.
This knowledge can be extremely useful for developers looking to extend the capabilities of ChatGPT and create more interactive and dynamic conversational experiences. Whether you're looking to integrate ChatGPT with external APIs, databases, or other services, developing custom plugins can open up a world of possibilities for enhancing the functionality and versatility of ChatGPT.