Have you seen chirpstack-network-server/main.go at master 路 brocaar/chirpstack-network-server 路 GitHub? The adr.HandleRequest
param provides you with the uplink context, the adr.HandleResponse
return value defines the desired state of the device. Everything in-between is up to you to implement 
This is the default ADR implementation which is already embedded: