Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 142 additions & 0 deletions .github/ISSUE_TEMPLATE/new_method_or_notification_suggesetion.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
name: 'New Method/Notification Suggestion'
description: Suggest a new MSMP RPC method or notification, along with the functionality it should provide.
title: '[Suggestion] '
labels: ['enhancement']
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to suggest a new method/notification!

Please follow the existing naming and structure conventions where possible, ex.:
- `console:foo` - get current state
- `console:foo/set` - partially update state
- `console:foo/changed`, `console:foo/changed/add`, `console:foo/changed/remove` - manage the notification tracker
- `console:notification/foo/changed` - the actual pushed event

You don't need to fill out every field perfectly - just give us as much detail as you can.

- type: dropdown
id: kind
attributes:
label: 'What are you suggesting?'
description: |
Methods are request/response (called by the client). Notifications are pushed by the server when something happens.

options:
- 'New method (request/response)'
- 'New notification (server-pushed event)'
- 'Both a method and a matching notification'
- 'Not sure/something else'

validations:
required: true

- type: textarea
id: kind-other
attributes:
label: 'If "Not sure/something else" - please elaborate'
description: |
Leave this empty if it doesn't apply to you.

placeholder: ex. a config option, a change to an existing method, something else entirely...

validations:
required: false

- type: textarea
id: use-case
attributes:
label: 'Use Case'
description: |
Why do you want this? What benefit would that have for you? What tooling, dashboard, or automation would this enable?

validations:
required: true

- type: input
id: name
attributes:
label: 'Proposed Name'
description: |
Follow the existing naming convention if this fits an existing family (ex. foo, bar, bazz).

placeholder: 'console:foo, console:bar, console:bazz, ...'

validations:
required: true

- type: textarea
id: description
attributes:
label: 'What should it do?'
description: |
Describe the functionality in detail. What data does it return or accept? Or, for a notification, what event does it represent and when should it fire?

placeholder: |
- `console:foo` - Get current state of foo
- `console:foo/set` - Set current state of foo
- `console:foo/changed` - Returns a list of all tracked entities for the foo changed event
- `console:foo/changed/add` - Add entities to the foo change notification tracker
- `console:foo/changed/remove` - Remove entities from the foo change notification tracker

validations:
required: true

- type: textarea
id: example-payload
attributes:
label: 'Example request/response/notification payload'
render: json
description: |
If you have an idea of the JSON shape, share it here. Not required, but it helps a lot.

placeholder: |
{
"jsonrpc": "2.0",
"method": "console:foo/set",
"params": [{
"name": "Steve",
"foo": 15
}],
"id": 1
}

validations:
required: false

- type: textarea
id: related
attributes:
label: 'Related existing methods or notifications'
description: |
Is there a similar existing method/notification this should be modeled after (ex. `console:health/changed`, `console:position/set`)?

validations:
required: false

- type: dropdown
id: needs-config
attributes:
label: 'Would this need configurable settings?'
description: |
Some change-notifications use polling with a configurable interval/threshold (ex. position's `block-delta`), while others are purely event-driven with no settings.

options:
- 'No, it should just work without configuration'
- 'Yes, it would need some configurable settings'
- 'Not sure'

validations:
required: true

- type: checkboxes
id: checks
attributes:
label: 'Checks'
options:
- label: "I searched existing issues and this hasn't been suggested yet"
required: true

- label: 'This is a request for this mod specifically (not Minecraft itself or another mod)'
required: false
77 changes: 54 additions & 23 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@ env:
on:
workflow_call: {}
workflow_dispatch: {}

push:
paths:
- 'build.gradle'
- 'gradle.properties'
- 'gradlew'
- 'gradlew.bat'
- 'settings.gradle'
- '.github/workflows/build.yml'
- 'gradle/**'
- 'src/**'
- build.gradle
- gradle.properties
- gradlew
- gradlew.bat
- settings.gradle
- .github/workflows/build.yml
- gradle/**
- src/**

pull_request:
branches:
- main
Expand All @@ -26,32 +27,62 @@ permissions:

jobs:
build:
runs-on: ubuntu-latest
name: 'Build'
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: 'Checkout Repository'
uses: actions/checkout@v6

- name: 'Setup JDK'
uses: actions/setup-java@v4
uses: actions/setup-java@v5
with:
java-version: '25'
distribution: 'temurin'
distribution: temurin
java-version: "25"

- name: 'Setup Gradle'
uses: gradle/actions/setup-gradle@v4
uses: gradle/actions/setup-gradle@v6
with:
build-scan-publish: true
build-scan-terms-of-use-agree: 'yes'
build-scan-terms-of-use-agree: "yes"
build-scan-terms-of-use-url: 'https://gradle.com/terms-of-service'

- name: 'Build with Gradle Wrapper'
run: |-
run: |
./gradlew build --scan

echo "Files:"
ls -la build/libs/

- name: 'Upload Artifact'
uses: actions/upload-artifact@v4
id: save-artifact
- name: 'Upload Workflow Artifact'
uses: actions/upload-artifact@v7
with:
name: ${{ env.ARTIFACT_NAME }}
path: build/libs/*.jar

- name: 'Read mod version'
id: version
run: |
VERSION=$(grep '^mod_version=' gradle.properties | cut -d= -f2)
echo "version=$VERSION" >> "$GITHUB_OUTPUT"

- name: 'Check if tag exists'
id: tag
run: |
if git ls-remote --exit-code --tags origin "refs/tags/v${{ steps.version.outputs.version }}" > /dev/null 2>&1; then
echo "exists=true" >> "$GITHUB_OUTPUT"
else
echo "exists=false" >> "$GITHUB_OUTPUT"
fi

- name: 'Create GitHub Release'
if: >
github.event_name == 'push' &&
github.ref == 'refs/heads/main' &&
steps.tag.outputs.exists == 'false'
uses: softprops/action-gh-release@v3
with:
name: '${{ env.ARTIFACT_NAME }}'
path: '${{ github.workspace }}/build/libs/*.jar'
tag_name: v${{ steps.version.outputs.version }}
name: v${{ steps.version.outputs.version }}
generate_release_notes: true
files: build/libs/*.jar
93 changes: 72 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,54 +2,105 @@

# MSMP Console

A server-side Fabric mod that extends the [Minecraft Server Management Protocol](https://minecraft.wiki/w/Minecraft_Server_Management_Protocol) (MSMP) by forwarding every server console log event.
A server-side Fabric mod that extends the [Minecraft Server Management Protocol](https://minecraft.wiki/w/Minecraft_Server_Management_Protocol) (MSMP) by providing additional functions for interacting with the console.

This mod is designed for tooling, dashboards, automation systems, external monitoring tools, and integrations that need structured access to the server console without relying on RCON or log-file tailing.


## Installation

1. Download the mod `.jar` and place it in your server's `mods/` folder.
2. Enable the Management Server in `server.properties`:
```properties
```properties
management-server-enabled=true
```
```
3. Start the server. The Management Server will listen on `localhost:25576` by default.

## Notification

Once a client connects to the WebSocket endpoint, it will receive a notification for every log event produced by the server.
## Configuration

On first start, the mod generates a configuration file at `<server_root_dir>/config/msmp/console/config.yml`:

```yaml
# Main configuration file for MSMP Entity.

# Configuration for log related settings.
log:
# The minimum log level that gets forwarded as a console:notification/log_event.
# Events below this level are ignored entirely and never sent to connected clients.
# @possible: TRACE | DEBUG | INFO | WARN | ERROR | FATAL
# @default: 'INFO'
level: INFO
# Configuration for send related settings.
send:
# Enable logging for the execution of a command in the console, this prevents echoing the send command.
# @default: true
log-command-execution: true
```

## RPC Methods

The mod currently provides the following MSMP RPC methods. All of these methods are also automatically discoverable through the standard `rpc.discover` MSMP endpoint.

| Method | Description |
|:---------------|:--------------------------------------------------------------------------------------|
| `console:send` | Executes a command on the server console with full permissions and returns its output |

> If you want more methods or notifications for other purposes, please [open an issue](https://github.com/MinecraftPlayground/msmp-console-mod/issues/new?template=new_method_or_notification_suggesetion.yml)


**Method:** `console:notification/log_event`
## RPC Notifications

The mod also provides the following MSMP RPC notification that clients can subscribe to:

| Method | Description |
|:---------------------------------|:--------------------------------------------------------------------------------|
| `console:notification/log/event` | Fired for every server console log event at or above the configured `log.level` |


## Method Reference

### `console:send`

Executes an arbitrary command as if typed by an operator (full permissions) and returns its textual feedback/error output together with a success indicator. The command may be sent with or without a leading `/`.

```jsonc
// Request
{ "command": "say Hello" }

// Response
{
"command": "say Hello",
"result": "",
"success": true
}
```

### Payload
---

| Field | Type | Description |
|-------------|--------|---------------------------------------------------------------------------|
| `timestamp` | string | ISO-8601 timestamp of when the log event occurred |
| `level` | string | Log level: `TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR` or `FATAL` |
| `thread` | string | Name of the thread that produced the log event |
| `logger` | string | Fully qualified name of the originating logger (e.g. the class name) |
| `message` | string | The fully interpolated log message |
| `throwable` | string | Serialized stacktrace if an exception was attached, omitted otherwise |
### `console:notification/log/event`

### Example
Fired for every server console log event whose level is at or above the configured `log.level`. Events below that level are dropped before ever reaching connected clients.

```json
```jsonc
{
"jsonrpc": "2.0",
"method": "console:notification/log_event",
"method": "console:notification/log/event",
"params": [{
"timestamp": "2026-03-21T15:06:06.146Z",
"level": "INFO",
"thread": "Server thread",
"logger": "net.minecraft.server.MinecraftServer",
"message": "Done (1.019s)! For help, type \"help\""
"message": "Done (1.019s)! For help, type \"help\"",
"throwable": ""
}]
}
```

```json
```jsonc
{
"jsonrpc": "2.0",
"method": "console:notification/log_event",
"method": "console:notification/log/event",
"params": [{
"timestamp": "2026-03-21T15:06:07.212Z",
"level": "ERROR",
Expand Down
Loading