Skip to content

MrApik/MinecraftServerMCP

Repository files navigation

MinecraftServerMCP

CI JitPack Quality Gate Status GitHub release License: MIT Java Spigot / Paper

Javadoc: v1.0.1

Spigot/Paper plugin that runs an embedded Model Context Protocol server over HTTP(S): tools and resources for the world directory, console, logs, and players, gated by bearer tokens and per-tool policies. Uses the MCP Java SDK (streamable HTTP).


Features

  • MCP over HTTP(S) (Jetty); bind address, port, and path in config
  • Bearer token or X-MCP-Token; per-profile YAML under access.<profile>.tools.<toolId>
  • Built-in tools/resources: fs_read, fs_list, fs_write, server_command, server_logs, players_list, player_get
  • Other plugins can register MCP tools via the Bukkit service MinecraftServerMcp
  • /mcp reload reloads tokens and policies (does not unregister tools)

Requirements

Version
Paper or Spigot 1.21+
Java 21

Server operator setup

  1. Install the shaded JAR from Releases (not *-plain.jar) into plugins/.
  2. Start once, then edit plugins/MinecraftServerMCP/config.yml.
  3. Set at least one access.<name>.token to a long random secret. The plugin disables itself if no tokens are configured.
  4. Point MCP clients at http://<host>:<port><mcpPath> (defaults: 8765, /mcp) with header Authorization: Bearer <token> or X-MCP-Token: <token>.
  5. Prefer bindAddress: "127.0.0.1" unless the client runs on another machine. Optional HTTPS is configured under ssl (requires a full restart to change).

Example listener + token:

bindAddress: "127.0.0.1"
port: 8765
mcpPath: "/mcp"

access:
  prod:
    token: "<use openssl rand -hex 32 or similar>"

Full keys: see config.yml (inline comments).

Example MCP client snippet

Don't forget to update the URL and credentials.

{
  "mcpServers": {
    "minecraft-server-mcp": {
      "url": "http://127.0.0.1:8765/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_TOKEN"
      }
    }
  }
}

Built-in tools and resources

Policy YAML: access.<profile>.tools.<id>.

Id Type Notes
fs_read Resource minecraft-server-mcp://fs/read{?path}
fs_list Resource minecraft-server-mcp://fs/list{?path}
fs_write Tool
server_command Tool commandWhitelist / commandBlacklist
server_logs Tool maxLogLines, maxLogBytes, …
players_list Resource minecraft-server-mcp://players/list
player_get Resource minecraft-server-mcp://player/get{?name}

Use a prefix on custom tool names (e.g. myplugin_action) so they do not collide with built-ins.


Extending with another plugin

API reference: Javadoc v1.0.1 (MinecraftServerMcp, built-ins, config types).

1. Depend on this plugin

plugin.yml:

name: MyPlugin
# ...
softdepend: [MinecraftServerMCP]

Use depend if MCP must be present before yours loads.

2. Add compile-only dependencies (JitPack)

The library is built from this repo as eu.mrapik:minecraft-server-mcp. The published POM declares api dependencies (MCP Java SDK BOM + mcp + JetBrains annotations), so Gradle and Maven pull MCP / Reactor / etc. transitively—you do not list those yourself.

You still need compileOnly Spigot API (Paper repo or Spigot snapshots).

Gradle (Kotlin DSL)

repositories {
    mavenCentral()
    maven { url = uri("https://jitpack.io") }
    // maven("https://repo.papermc.io/repository/maven-public/")  // or Spigot snapshots — your usual setup
}

dependencies {
    compileOnly("eu.mrapik:minecraft-server-mcp:VERSION")
    compileOnly("org.spigotmc:spigot-api:1.21.11-R0.1-SNAPSHOT")
}

Gradle (Groovy)

repositories {
    mavenCentral()
    maven { url 'https://jitpack.io' }
}

dependencies {
    compileOnly 'eu.mrapik:minecraft-server-mcp:VERSION'
    compileOnly 'org.spigotmc:spigot-api:1.21.11-R0.1-SNAPSHOT'
}

Use a Git tag (e.g. v1.0.1) or commit hash as VERSION—see JitPack.

Maven

<repositories>
  <repository>
    <id>jitpack.io</id>
    <url>https://jitpack.io</url>
  </repository>
</repositories>

<dependencies>
  <dependency>
    <groupId>eu.mrapik</groupId>
    <artifactId>minecraft-server-mcp</artifactId>
    <version>VERSION</version>
    <scope>provided</scope>
  </dependency>
  <dependency>
    <groupId>org.spigotmc</groupId>
    <artifactId>spigot-api</artifactId>
    <version>1.21.11-R0.1-SNAPSHOT</version>
    <scope>provided</scope>
  </dependency>
</dependencies>

Do not bundle the shaded MinecraftServerMCP plugin inside your plugin JAR. At runtime only the server’s plugins/ copy is used.

3. Register a tool

Resolve MinecraftServerMcp after this plugin has enabled, implement McpToolDefinition, and unregister when your plugin disables. Tool id() must match McpSchema.Tool#name() and your access.*.tools.<id> key.

import eu.mrapik.minecraftservermcp.api.MinecraftServerMcp;
import eu.mrapik.minecraftservermcp.api.McpToolDefinition;
import eu.mrapik.minecraftservermcp.api.McpToolInvocation;
import eu.mrapik.minecraftservermcp.util.ToolResults;
import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.spec.McpSchema;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import reactor.core.publisher.Mono;

import java.util.Map;

public final class MyPlugin extends JavaPlugin {

    private final McpJsonMapper json = McpJsonDefaults.getMapper();

    @Override
    public void onEnable() {
        var reg = Bukkit.getServicesManager().getRegistration(MinecraftServerMcp.class);
        if (reg == null) {
            getLogger().warning("MinecraftServerMCP not loaded; skipping MCP tool.");
            return;
        }
        var mcp = reg.getProvider();
        var def = new McpToolDefinition() {
            @Override
            public @NotNull String id() {
                return "myplugin_greeting";
            }

            @Override
            public @NotNull org.bukkit.plugin.Plugin owningPlugin() {
                return MyPlugin.this;
            }

            @Override
            public @NotNull McpSchema.Tool tool() {
                return McpSchema.Tool.builder()
                        .name("myplugin_greeting")
                        .description("Returns a short greeting")
                        .inputSchema(json, """
                                {"type":"object","properties":{"name":{"type":"string"}},"required":[]}
                                """)
                        .build();
            }

            @Override
            public @NotNull Mono<McpSchema.CallToolResult> call(@NotNull McpToolInvocation invocation) {
                return Mono.just(ToolResults.ok(Map.of("greeting", "Hello from MyPlugin")));
            }
        };
        mcp.registerTool(def).subscribe();
    }
}

McpToolInvocation runs off the server thread; use Bukkit.getScheduler() or patterns from eu.mrapik.minecraftservermcp.builtin for main-thread work.


Building from source

chmod +x gradlew   # Unix if needed
./gradlew build
  • Server: build/libs/MinecraftServerMCP-*.jar without -plain in the name.
  • API only: *-plain.jar for local compile tests.

Security tips

Treat tokens as root-access token/password. Never commit or share your tokens. Be careful!


License

MIT License.

About

A bundled MCP server delivered as a Spigot plugin for Minecraft servers.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages