Tutorials

How to Make a ChatGPT Plugin With Rust and Rocket

Sean Moriarity
#openai#chatgpt#rust#rust rocket#chatgpt plugins

ChatGPT plugins provide a new medium for developers to take advantage of OpenAI’s powerful GPT-4 model. plugins give ChatGPT access to tools via a REST API. When a plugin is installed in a user’s ChatGPT session, the model may decide to use the plugin as a part of it’s response.

You can develop plugins that enable ChatGPT to plan travel, go shopping, or do complex mathematics. In this tutorial, you’ll learn the basics of developing a ChatGPT plugin using Rust and Rocket.

This tutorial assumes you have Rust and Rocket installed. For information about how to create a plugin in other languages, see:

Step 1: Set up the Rust project

Create a new Rust project by running:

cargo new rust-chatgpt-plugin --bin
cd rust-chatgpt-plugin

This will generate a new Rust project. Next, add Rocket to your dependencies in Cargo.toml:

[dependencies.rocket]
version = "=0.5.0-rc.3"

Now, edit src/main.rs to look like:

#[macro_use] extern crate rocket;

#[get("/")]
fn index() -> &'static str {
    "Hello, world!"
}

#[launch]
fn rocket() -> _ {
    rocket::build().mount("/", routes![index])
}

You can confirm your Rocket application is setup properly by running cargo run from the project directory and navigating to the localhost:8000:

Rocket Hello World

Now you’re ready to create the plugin API!

Step 2: Create the plugin API

ChatGPT interacts with plugins via a defined REST API. Before you can begin defining your REST API, you need to configure Rocket with JSON features. You can do so by editing your Rocket dependency with the following features:

[dependencies.rocket]
version = "=0.5.0-rc.3"
features = ["json"]

Next, add the following to src/main.rs:

use rocket::serde::json::{json, Value};

Now you create a new route which returns JSON:

#[get("/api/hello")]
fn hello() -> Value {
    json!({
      "message": "Hello from the plugin!"
    })
}

And finally you can register your route in rocket:

#[launch]
fn rocket() -> _ {
    rocket::build()
        .mount("/api/hello", routes![hello])
}

This will create a new route at /api/hello which dispatches to the hello method. hello will return a JSON response from the server with the message Hello from the plugin!. Your entire server will now look like this:

#[macro_use] extern crate rocket;

#[get("/api/hello")]
fn hello() -> Value {
    json!({
      "message": "Hello from the plugin!"
    })
}

#[launch]
fn rocket() -> _ {
    rocket::build()
        .mount("/api/hello", routes![hello])
}

With your API defined, you need to define an OpenAPI Spec. Rocket doesn’t automatically generate OpenAPI specs, so you need to generate them yourself.

Step 3: Create the OpenAPI Spec

The OpenAPI Spec is how your ChatGPT plugin knows which endpoints are available to interact with. ChatGPT will use your OpenAPI spec to structure its requests and parse the responses from your plugin. For your Rust plugin, create a new file static/openapi.yaml. Next, open up openapi.yaml and add the following:

openapi: 3.0.0
info:
  title: Rust ChatGPT Plugin
  version: 1.0.0
servers:
  - url: http://localhost:8000/api
paths:
  /hello:
    get:
      summary: Say hello
      description: Says hello from the plugin
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
      operationId: sayHello

This spec defines your single /hello endpoint which is available from the url http://localhost:8000/api/hello. Now you’re ready to define the ai-plugin.json for your Rust plugin.

Step 4: Create the plugin manifest

Every ChatGPT plugin must ship with a plugin manifest hosted on the same domain as the API. ChatGPT looks for the plugin specifically at the path /.well-known/ai-plugin.json. You can read more about the specifics of the plugin manifest in our What is the ChatGPT plugin manifest? post.

For your plugin, start by creating a new directory static/.well-known. Next, create a new file in that directory called ai-plugin.json. Then, add the following to ai-plugin.json:

{
  "schema_version": "v1",
  "name_for_human": "My First plugin",
  "name_for_model": "rust_plugin",
  "description_for_human": "My first ChatGPT plugin",
  "description_for_model": "plugin which says hello.",
  "auth": {
    "type": "none"
  },
  "api": {
    "type": "openapi",
    "url": "http://localhost:8000/openapi.yaml",
    "is_user_authenticated": false
  },
  "logo_url": "http://localhost:8000/logo.png",
  "contact_email": "support@example.com",
  "legal_info_url": "http://www.example.com/legal"
}

In this example, the “auth” field is set to “none” because this plugin doesn’t require authentication. However, depending on your use case, you might need your plugin to handle authentication. For more information about how to implement authentication in a ChatGPT plugin, you can refer to our ChatGPT Plugin Authentication Guide.

Now you need to configure your application to serve static files from the static directory at the root path. You can do so by using a Rocket FileServer. First, add the following at the top of src/main.rs:

use rocket::fs::{FileServer, relative};

Next, edit your rocket implementation to look like this:

#[launch]
fn rocket() -> _ {
    rocket::build()
        .mount("/api/hello", routes![hello])
        .mount("/.well-known", FileServer::from(relative!("static/.well-known")).rank(1))
        .mount("/", FileServer::from(relative!("static")).rank(2))
}

Now both openapi.yaml and .well-known/ai-plugin.json should be served from your application. You can verify it worked by starting your server and accessing both files from the browser.

Step 5: Set up CORS for development

In order to test your plugin locally before deploying to production, you need to configure your application to allow Cross-Origin Resource Sharing (CORS) from the ChatGPT website. CORS enables ChatGPT to request access to resources from your locally running webserver. To setup CORS with Rust and Rocket, you can use the rocket_cors crate. Start by adding rocket_cors to your dependencies:

rocket_cors = "0.6.0-alpha2"

Now, add the following imports to src/main.rs:

use rocket::http::Method;
use rocket_cors::{AllowedOrigins, AllowedHeaders, CorsOptions};

Next, edit your rocket method to look like:

#[launch]
fn rocket() -> _ {
    let allowed_origins = AllowedOrigins::some_exact(&["http://localhost:8000", "https://chat.openai.com"]);
    let cors = CorsOptions::default()
        .allowed_origins(allowed_origins)
        .allowed_methods(
            vec![Method::Get, Method::Post].into_iter().map(From::from).collect(),
        )
        .allowed_headers(AllowedHeaders::all())
        .allow_credentials(true)
        .to_cors()
        .unwrap();

    rocket::build()
        .attach(cors)
        .mount("/api/hello", routes![hello])
        .mount("/.well-known", FileServer::from(relative!("static/.well-known")).rank(1))
        .mount("/", FileServer::from(relative!("static")).rank(2));
}

This will configure CORS correctly in your application for local development. Now you’re all set for testing!

Step 5: Install and test your plugin

First, start your plugin server locally by running:

cargo run

Next, navigate to the ChatGPT UI and select the plugin model:

Selecting the plugin model

Then, you’ll want to select the plugins dropdown, navigate to the plugin store, and click “Develop your own plugin” in the bottom right:

Selecting develop your own plugin

Finally, type your localhost URL into the plugin form:

Typing the address of your plugin

After awhile, you’ll see the following:

Successfully adding your plugin

Click “Install localhost plugin” to continue. With your plugin enabled, you can start to interact with it using ChatGPT. For example, try typing in “Say hello from my plugin” into the chat window:

Successfully using the plugin

Congratulations! You’ve successfully made your first ChatGPT plugin with Rust and Rocket and confirmed it works locally. Next, check out our deployment and hosting guide to learn about deploying your plugin to production.

Enjoyed this post?
Subscribe for more!

Get updates on new content, exclusive offers, and exclusive materials by subscribing to our newsletter.

← Back to Blog