Pumpkin is in early development and bugs can happen. If you find any, report them on our GitHub.

Build plugins
without the pain.

No NMS. No reflection. No version-specific hacks. Just clean, type-safe APIs.

Version-specific NMS
// Sending a title packet
Object packet = Class.forName("net.minecraft.server."
    + VERSION + ".PacketPlayOutTitle")
    .getConstructor(...).newInstance(...);

player.getClass().getMethod("getHandle")
    .invoke(player).getClass()
    .getField("playerConnection").get(...)
    .getClass().getMethod("sendPacket", ...)
    .invoke(connection, packet);

// Breaks every update. Good luck.
Pumpkin plugin API
// Rewriting chat in a plugin
context.register_event_handler::<PlayerChatEvent, _>(
    PrefixChat,
    EventPriority::Normal,
    true,
)?;

impl EventHandler<PlayerChatEvent> for PrefixChat {
    fn handle(&self, _server: Server, mut event: PlayerChatEventData) -> PlayerChatEventData {
        event.message = format!("[Pumpkin] {}", event.message);
        event
    }
}

Every Player, One Plugin

Native Java + Bedrock support. Multi-version built in. Write once, reach everyone.

Typed Commands & Events

Register commands and hook typed plugin events without reflection, NMS, or version-specific hacks.

Async by Default

Built on Tokio. No main thread bottleneck. Heavy tasks don't freeze the server.

Memory Safe

Rust guarantees. No null pointers, no memory leaks, no data races.

0 NMS Classes
0 Reflection Calls
100% Type Safe

Quick Start Guide

Creating a new project

Pumpkin plugins use the Cargo build system.

The complete code for this plugin can be found as a template on GitHub.

Installing the toolchain

Before we can compile a plugin, we have to have the wasm32-wasip2 target installed. You can install the target by running:

rustup target add wasm32-wasip2

Initializing a new crate

First we need to create a new project folder. You can do this by running this command in the folder you created:

cargo new <project-name> --lib

After adding this, we want to create a new directory called .cargo and add in a config.toml file with the following contents:

[build]
target = "wasm32-wasip2"

Altogether your new folder structure should look like this:

├── .cargo/
│   └── config.toml
├── src/
│   └── lib.rs
├── Cargo.toml
└── Cargo.lock

Configuring the crate

Since Pumpkin plugins are loaded at runtime as dynamic libraries, we need to tell Cargo to build this crate as one.

Cargo.toml

[package]
name = "hello-pumpkin-wasm"
version = "0.1.0"
edition = "2024"

[lib] 
crate-type = ["cdylib"]

[dependencies]

Next we need to add some basic dependencies. Since Pumpkin is still in early development, the internal crates aren't published to crates.io, so we need to tell Cargo to download the dependencies directly from GitHub.

Cargo.toml

[package]
name = "hello-pumpkin"
version = "0.1.0"
edition = "2024"

[lib]
crate-type = ["cdylib"]

[dependencies]
# This is the api crate that makes creating plugins easier, and has wit definitions
pumpkin-plugin-api = { version = "0.1.0", git = "https://github.com/Pumpkin-MC/Pumpkin", package = "pumpkin-plugin-api" }
tracing = "0.1"

Refer to the documentation for more.

Installation

First, you need to install the pumpkin-api-py library:

pip install pumpkin-api-py

Creating your first plugin

Create a file named main.py and add the following content:

from pumpkin_api import (
    Plugin, PluginMetadata, register_plugin, 
    server, event, command, text, context
)

class MyPlugin(Plugin):
    def metadata(self) -> PluginMetadata:
        return PluginMetadata(
            name="my-plugin",
            version="0.1.0",
            authors=["you"],
            description="An example plugin."
        )

    def on_load(self, ctx: context.Context) -> None:
        print("Python plugin loaded!")
        
        # Register an event handler
        self.register_event(ctx, event.EventType.PLAYER_JOIN_EVENT, self.on_player_join)

    def on_player_join(self, srv: server.Server, evt: event.PlayerJoinEventData) -> event.PlayerJoinEventData:
        print(f"Player {evt.player.get_name()} joined!")
        return evt

register_plugin(MyPlugin)

Building the plugin

Build your plugin into a WebAssembly component using the provided build tool:

pumpkin-api-build main -o my_plugin.wasm

This will generate a my_plugin.wasm file that you can place in the plugins folder of your Pumpkin server.

Refer to the documentation for more.

Installation

You will need the .NET SDK and the WASI workload to compile C# plugins for Pumpkin.

dotnet workload install wasi-experimental

Creating your first plugin

Create a new class library and add the following code:

using Pumpkin.API;

public class MyPlugin : IPlugin {
    public PluginMetadata GetMetadata() => new() {
        Name = "my-csharp-plugin",
        Version = "0.1.0",
        Authors = new[] { "you" },
        Description = "A simple C# plugin for Pumpkin"
    };

    public void OnLoad(IContext ctx) {
        Console.WriteLine("C# plugin loaded!");
    }
}

Building the plugin

Compile the plugin to WebAssembly using the WASI runtime identifier:

dotnet build -c Release /p:RuntimeIdentifier=wasi-wasm

This will generate a .wasm file in your output directory that can be loaded by Pumpkin.

Refer to the documentation for more.

Installation

You will need the wasi-sdk to compile C/C++ plugins for Pumpkin. Download the latest release from the wasi-sdk repository.

The complete code for this plugin can be found in the pumpkin-api-c repository.

Creating your first plugin

Create a file named main.c and add the following content:

#include "pumpkin_api.h"
#include <stdio.h>

// Define the plugin's metadata
pumpkin_metadata_t get_meta(void) {
    static const char* authors[] = {"you"};
    return (pumpkin_metadata_t) {
        .name = "my-c-plugin",
        .version = "0.1.0",
        .authors = authors,
        .authors_count = 1,
        .description = "A simple C plugin for Pumpkin",
        .dependencies_count = 0
    };
}

// Callback executed when the plugin is loaded
void on_load(plugin_own_context_t ctx) {
    printf("C plugin loaded!\n");
}

// Register the plugin with the API
REGISTER_PUMPKIN_PLUGIN(((pumpkin_plugin_t){
    .get_metadata = get_meta,
    .on_load = on_load
}))

Building the plugin

To compile this plugin into a WebAssembly component, use clang from the wasi-sdk:

/path/to/wasi-sdk/bin/clang -O3 \
 -Iinclude -Isrc/gen \
 src/gen/plugin.c src/pumpkin_api.c main.c \
 -o my_plugin.wasm \
 -mexec-model=reactor

This will generate a my_plugin.wasm file that can be loaded by Pumpkin.

Refer to the GitHub repository for more.

Installation

You will need Go 1.23 or later and tinygo to compile Go plugins for Pumpkin.

brew tap tinygo-org/tools && brew install tinygo

Creating your first plugin

Create a file named main.go and add the following content:

package main

import (
    "fmt"
    "github.com/pumpkin-mc/pumpkin-api-go"
)

type MyPlugin struct{}

func (p *MyPlugin) Metadata() pumpkin.PluginMetadata {
    return pumpkin.PluginMetadata{
        Name:        "my-go-plugin",
        Version:     "0.1.0",
        Authors:     []string{"you"},
        Description: "A simple Go plugin for Pumpkin",
    }
}

func (p *MyPlugin) OnLoad(ctx pumpkin.Context) {
    fmt.Println("Go plugin loaded!")
}

func main() {
    pumpkin.RegisterPlugin(&MyPlugin{})
}

Building the plugin

Compile the plugin to WebAssembly using tinygo:

tinygo build -o my_plugin.wasm -target=wasi main.go

This will generate a my_plugin.wasm file that can be loaded by Pumpkin.

Refer to the documentation for more.

Ready to build?