Skip to content

Developer API

shvquu edited this page Jun 22, 2026 · 4 revisions

Developer API

ServerDoctor exposes a small, platform-neutral API so other plugins can read analysis results, subscribe to events, and register their own scanners.

Adding the dependency

The serverdoctor-common and serverdoctor-api modules are published via JitPack (see jitpack.yml). Depend on the API module and treat the plugin as a runtime soft-dependency:

repositories {
    maven("https://jitpack.io")
}
dependencies {
    compileOnly("com.github.Shvquu.server-doctor:serverdoctor-api:<tag>")
}

Replace <tag> with a released tag or commit. Exact artifact coordinates depend on your JitPack build — verify on the JitPack page for the repo.

On Paper, add ServerDoctor as a softdepend in your plugin.yml so it loads first.

Getting the API

import com.serverdoctor.api.ServerDoctorProvider;
import com.serverdoctor.api.ServerDoctorApi;

if (ServerDoctorProvider.isAvailable()) {
    ServerDoctorApi api = ServerDoctorProvider.get();
    // ...
}

get() throws ApiNotInitializedException (an unchecked ServerDoctorException) if ServerDoctor hasn't initialized yet — guard with isAvailable() or call it after both plugins are enabled.

Reading results

ServerDoctorApi api = ServerDoctorProvider.get();

double tps          = api.getPerformanceSnapshot().tps1m();
var latest          = api.getLatestReport();          // Optional<DiagnosticReport>
var conflicts       = api.getConflicts();             // List<ConflictReport>
var risks           = api.getSecurityRisks();         // List<SecurityRisk>
var recommendations = api.getRecommendations();       // List<Recommendation>

DiagnosticReport fresh = api.runDiagnostics();        // run a full analysis now

Subscribing to events

All events implement ServerDoctorEvent and are delivered on a thread-safe bus.

import com.serverdoctor.api.event.PluginConflictDetectedEvent;

api.events().subscribe(PluginConflictDetectedEvent.class,
        e -> getLogger().warning("Conflict: " + e.conflict().description()));

Available events:

Event Payload
AnalysisFinishedEvent DiagnosticReport report, Instant timestamp
PerformanceThresholdReachedEvent PerformanceSnapshot, Severity, String reason, Instant
PluginConflictDetectedEvent ConflictReport conflict, Instant
SecurityRiskDetectedEvent SecurityRisk risk, Instant

Registering your own scanner

Implement AnalysisModule and register it. The engine calls analyze(...) with a read-only ServerContext and only if your declared capabilities are met.

import com.serverdoctor.api.module.*;
import com.serverdoctor.common.model.*;

api.registerModule(new AnalysisModule() {
    public String id() { return "my-scanner"; }

    // optional: declare platform requirements; default = runs everywhere
    public java.util.Set<Capability> requiredCapabilities() {
        return java.util.Set.of(Capability.HAS_PLUGINS);
    }

    public AnalysisResult analyze(ServerContext ctx) {
        return AnalysisResult.builder(id())
                .finding(new Finding(id(), Severity.INFO,
                        ctx.plugins().size() + " plugins seen"))
                .build();
    }
});

// later, if needed:
api.unregisterModule("my-scanner");

AnalysisResult.Builder automatically raises the result's overall severity to the highest of its findings/conflicts/risks. ServerContext exposes plugins(), performance(), serverInfo(), capabilities() and has(Capability) — and nothing that writes.

Exceptions

All ServerDoctor errors share one unchecked base, so you can catch them in one place:

import com.serverdoctor.common.exception.ServerDoctorException;

try {
    var api = ServerDoctorProvider.get();
    // ...
} catch (ServerDoctorException ex) {
    // ApiNotInitializedException, ConfigurationException, StorageException, AnalysisException
}

ServerDoctorProvider.get() throws ApiNotInitializedException; configuration/settings problems throw ConfigurationException; the persistence layer throws StorageException; a failing scanner is wrapped in AnalysisException (logged by the engine, which keeps the rest of the scan running).

Design guarantees

  • The API never exposes platform-specific or mutating operations.
  • Everything ServerDoctor does is read-only; your module is expected to be read-only too.

Clone this wiki locally