mcp-server-return-to-dark-tower 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/LICENSE +21 -0
- package/README.md +729 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +133 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts/index.d.ts +3 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +250 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/resources/index.d.ts +4 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +228 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/tools/audio.d.ts +4 -0
- package/dist/tools/audio.d.ts.map +1 -0
- package/dist/tools/audio.js +59 -0
- package/dist/tools/audio.js.map +1 -0
- package/dist/tools/connection.d.ts +4 -0
- package/dist/tools/connection.d.ts.map +1 -0
- package/dist/tools/connection.js +111 -0
- package/dist/tools/connection.js.map +1 -0
- package/dist/tools/drums.d.ts +4 -0
- package/dist/tools/drums.d.ts.map +1 -0
- package/dist/tools/drums.js +70 -0
- package/dist/tools/drums.js.map +1 -0
- package/dist/tools/lights.d.ts +4 -0
- package/dist/tools/lights.d.ts.map +1 -0
- package/dist/tools/lights.js +86 -0
- package/dist/tools/lights.js.map +1 -0
- package/dist/tools/seals.d.ts +4 -0
- package/dist/tools/seals.d.ts.map +1 -0
- package/dist/tools/seals.js +60 -0
- package/dist/tools/seals.js.map +1 -0
- package/dist/tools/state.d.ts +4 -0
- package/dist/tools/state.d.ts.map +1 -0
- package/dist/tools/state.js +64 -0
- package/dist/tools/state.js.map +1 -0
- package/dist/tower-controller.d.ts +87 -0
- package/dist/tower-controller.d.ts.map +1 -0
- package/dist/tower-controller.js +355 -0
- package/dist/tower-controller.js.map +1 -0
- package/dist/utils/logger.d.ts +11 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +29 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/lookups.d.ts +14 -0
- package/dist/utils/lookups.d.ts.map +1 -0
- package/dist/utils/lookups.js +33 -0
- package/dist/utils/lookups.js.map +1 -0
- package/dist/utils/schemas.d.ts +165 -0
- package/dist/utils/schemas.d.ts.map +1 -0
- package/dist/utils/schemas.js +70 -0
- package/dist/utils/schemas.js.map +1 -0
- package/package.json +69 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { TowerState, ConnectionStatus, DeviceInformation, Lights, TowerSide, SealIdentifier, Glyphs, LogOutput } from "ultimatedarktower";
|
|
2
|
+
export interface TowerSnapshot {
|
|
3
|
+
connected: boolean;
|
|
4
|
+
calibrated: boolean;
|
|
5
|
+
performingLongCommand: boolean;
|
|
6
|
+
performingCalibration: boolean;
|
|
7
|
+
battery: {
|
|
8
|
+
currentMillivolts: number;
|
|
9
|
+
previousMillivolts: number;
|
|
10
|
+
currentPercentage: number;
|
|
11
|
+
previousPercentage: number;
|
|
12
|
+
};
|
|
13
|
+
skullDropCount: number;
|
|
14
|
+
connectionStatus: ConnectionStatus | null;
|
|
15
|
+
deviceInfo: DeviceInformation | null;
|
|
16
|
+
towerState: TowerState | null;
|
|
17
|
+
brokenSeals: SealIdentifier[];
|
|
18
|
+
glyphs: Record<string, TowerSide | null>;
|
|
19
|
+
drumPositions: Record<string, TowerSide | null>;
|
|
20
|
+
}
|
|
21
|
+
export declare class TowerController {
|
|
22
|
+
private static instance;
|
|
23
|
+
private tower;
|
|
24
|
+
private lastTowerState;
|
|
25
|
+
private lastDeviceInfo;
|
|
26
|
+
private lastConnectionStatus;
|
|
27
|
+
private skullCount;
|
|
28
|
+
private connected;
|
|
29
|
+
private calibrated;
|
|
30
|
+
private calibrationCompleteResolve;
|
|
31
|
+
private bufferOutput;
|
|
32
|
+
private constructor();
|
|
33
|
+
static getInstance(): TowerController;
|
|
34
|
+
private ensureTower;
|
|
35
|
+
setLoggerOutputs(outputs: LogOutput[]): void;
|
|
36
|
+
get isConnected(): boolean;
|
|
37
|
+
get isCalibrated(): boolean;
|
|
38
|
+
get performingLongCommand(): boolean;
|
|
39
|
+
get performingCalibration(): boolean;
|
|
40
|
+
connect(): Promise<void>;
|
|
41
|
+
disconnect(): Promise<void>;
|
|
42
|
+
cleanup(): Promise<void>;
|
|
43
|
+
isConnectedAndResponsive(): Promise<boolean>;
|
|
44
|
+
getConnectionStatus(): ConnectionStatus | null;
|
|
45
|
+
getDeviceInformation(): DeviceInformation | null;
|
|
46
|
+
setConnectionMonitoring(enabled: boolean): void;
|
|
47
|
+
configureConnectionMonitoring(frequency?: number, timeout?: number): void;
|
|
48
|
+
configureBatteryHeartbeatMonitoring(enabled?: boolean, timeout?: number, verifyConnection?: boolean): void;
|
|
49
|
+
calibrate(): Promise<void>;
|
|
50
|
+
playSoundStateful(soundIndex: number, loop?: boolean, volume?: number): Promise<void>;
|
|
51
|
+
lights(lights: Lights): Promise<void>;
|
|
52
|
+
setLED(layerIndex: number, lightIndex: number, effect: number, loop?: boolean): Promise<void>;
|
|
53
|
+
allLightsOn(effect?: number): Promise<void>;
|
|
54
|
+
allLightsOff(): Promise<void>;
|
|
55
|
+
lightOverrides(sequence: number, soundIndex?: number): Promise<void>;
|
|
56
|
+
rotateWithState(top: TowerSide, middle: TowerSide, bottom: TowerSide, soundIndex?: number): Promise<void>;
|
|
57
|
+
rotateDrumStateful(drumIndex: number, position: number, playSound?: boolean): Promise<void>;
|
|
58
|
+
randomRotateLevels(level?: number): Promise<void>;
|
|
59
|
+
getCurrentDrumPosition(level: "top" | "middle" | "bottom"): TowerSide;
|
|
60
|
+
breakSeal(seal: SealIdentifier, volume?: number): Promise<void>;
|
|
61
|
+
isSealBroken(seal: SealIdentifier): boolean;
|
|
62
|
+
getBrokenSeals(): SealIdentifier[];
|
|
63
|
+
resetBrokenSeals(): void;
|
|
64
|
+
getRandomUnbrokenSeal(): SealIdentifier | null;
|
|
65
|
+
getCurrentTowerState(): TowerState | null;
|
|
66
|
+
sendTowerState(state: TowerState): Promise<void>;
|
|
67
|
+
getGlyphPosition(glyph: Glyphs): TowerSide | null;
|
|
68
|
+
getAllGlyphPositions(): Record<string, TowerSide | null>;
|
|
69
|
+
getGlyphsFacingDirection(direction: TowerSide): Glyphs[];
|
|
70
|
+
get towerSkullDropCount(): number;
|
|
71
|
+
resetTowerSkullCount(): Promise<void>;
|
|
72
|
+
getSnapshot(): TowerSnapshot;
|
|
73
|
+
private getDrumPositionsMap;
|
|
74
|
+
private requireConnected;
|
|
75
|
+
private requireCalibrated;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Wraps a tool handler to catch UDT errors and return MCP-friendly error responses.
|
|
79
|
+
*/
|
|
80
|
+
export declare function wrapToolHandler<T>(fn: () => Promise<T>): Promise<{
|
|
81
|
+
content: Array<{
|
|
82
|
+
type: "text";
|
|
83
|
+
text: string;
|
|
84
|
+
}>;
|
|
85
|
+
isError?: boolean;
|
|
86
|
+
}>;
|
|
87
|
+
//# sourceMappingURL=tower-controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tower-controller.d.ts","sourceRoot":"","sources":["../src/tower-controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import { UltimateDarkTower, BluetoothPlatform, BluetoothConnectionError, BluetoothDeviceNotFoundError, BluetoothTimeoutError, BluetoothUserCancelledError, BufferOutput, } from "ultimatedarktower";
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// TowerState helpers
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
function buildDefaultTowerState() {
|
|
6
|
+
const makeLight = () => ({ effect: 0, loop: false });
|
|
7
|
+
const makeLayer = () => ({ light: [makeLight(), makeLight(), makeLight(), makeLight()] });
|
|
8
|
+
const makeDrum = () => ({
|
|
9
|
+
jammed: false,
|
|
10
|
+
calibrated: false,
|
|
11
|
+
position: 0,
|
|
12
|
+
playSound: false,
|
|
13
|
+
reverse: false,
|
|
14
|
+
});
|
|
15
|
+
return {
|
|
16
|
+
drum: [makeDrum(), makeDrum(), makeDrum()],
|
|
17
|
+
layer: [makeLayer(), makeLayer(), makeLayer(), makeLayer(), makeLayer(), makeLayer()],
|
|
18
|
+
audio: { sample: 0, loop: false, volume: 0 },
|
|
19
|
+
beam: { count: 0, fault: false },
|
|
20
|
+
led_sequence: 0,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export class TowerController {
|
|
24
|
+
static instance = null;
|
|
25
|
+
tower = null;
|
|
26
|
+
lastTowerState = null;
|
|
27
|
+
lastDeviceInfo = null;
|
|
28
|
+
lastConnectionStatus = null;
|
|
29
|
+
skullCount = 0;
|
|
30
|
+
connected = false;
|
|
31
|
+
calibrated = false;
|
|
32
|
+
calibrationCompleteResolve = null;
|
|
33
|
+
bufferOutput;
|
|
34
|
+
constructor() {
|
|
35
|
+
this.bufferOutput = new BufferOutput(500);
|
|
36
|
+
}
|
|
37
|
+
static getInstance() {
|
|
38
|
+
if (!TowerController.instance) {
|
|
39
|
+
TowerController.instance = new TowerController();
|
|
40
|
+
}
|
|
41
|
+
return TowerController.instance;
|
|
42
|
+
}
|
|
43
|
+
ensureTower() {
|
|
44
|
+
if (!this.tower) {
|
|
45
|
+
const platformEnv = process.env.TOWER_PLATFORM;
|
|
46
|
+
const config = platformEnv === "node"
|
|
47
|
+
? { platform: BluetoothPlatform.NODE }
|
|
48
|
+
: platformEnv === "web"
|
|
49
|
+
? { platform: BluetoothPlatform.WEB }
|
|
50
|
+
: undefined;
|
|
51
|
+
this.tower = new UltimateDarkTower(config);
|
|
52
|
+
this.tower.onTowerConnect = () => {
|
|
53
|
+
this.connected = true;
|
|
54
|
+
};
|
|
55
|
+
this.tower.onTowerDisconnect = () => {
|
|
56
|
+
this.connected = false;
|
|
57
|
+
};
|
|
58
|
+
this.tower.onCalibrationComplete = () => {
|
|
59
|
+
this.calibrated = true;
|
|
60
|
+
if (this.calibrationCompleteResolve) {
|
|
61
|
+
this.calibrationCompleteResolve();
|
|
62
|
+
this.calibrationCompleteResolve = null;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
this.tower.onSkullDrop = (count) => {
|
|
66
|
+
this.skullCount = count;
|
|
67
|
+
};
|
|
68
|
+
this.tower.onBatteryLevelNotify = (_millivolts) => {
|
|
69
|
+
// Battery values are tracked by the UDT instance properties
|
|
70
|
+
};
|
|
71
|
+
this.tower.onTowerStateUpdate = (newState, _oldState, _source) => {
|
|
72
|
+
this.lastTowerState = newState;
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
return this.tower;
|
|
76
|
+
}
|
|
77
|
+
setLoggerOutputs(outputs) {
|
|
78
|
+
this.ensureTower();
|
|
79
|
+
this.tower.setLoggerOutputs([...outputs, this.bufferOutput]);
|
|
80
|
+
}
|
|
81
|
+
get isConnected() {
|
|
82
|
+
return this.tower?.isConnected ?? false;
|
|
83
|
+
}
|
|
84
|
+
get isCalibrated() {
|
|
85
|
+
return this.tower?.isCalibrated ?? false;
|
|
86
|
+
}
|
|
87
|
+
get performingLongCommand() {
|
|
88
|
+
return this.tower?.performingLongCommand ?? false;
|
|
89
|
+
}
|
|
90
|
+
get performingCalibration() {
|
|
91
|
+
return this.tower?.performingCalibration ?? false;
|
|
92
|
+
}
|
|
93
|
+
// --- Connection methods ---
|
|
94
|
+
async connect() {
|
|
95
|
+
const t = this.ensureTower();
|
|
96
|
+
await t.connect();
|
|
97
|
+
this.connected = true;
|
|
98
|
+
this.lastDeviceInfo = t.getDeviceInformation();
|
|
99
|
+
this.lastConnectionStatus = t.getConnectionStatus();
|
|
100
|
+
}
|
|
101
|
+
async disconnect() {
|
|
102
|
+
if (this.tower) {
|
|
103
|
+
await this.tower.disconnect();
|
|
104
|
+
this.connected = false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async cleanup() {
|
|
108
|
+
if (this.tower) {
|
|
109
|
+
await this.tower.cleanup();
|
|
110
|
+
this.connected = false;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
async isConnectedAndResponsive() {
|
|
114
|
+
if (!this.tower)
|
|
115
|
+
return false;
|
|
116
|
+
return this.tower.isConnectedAndResponsive();
|
|
117
|
+
}
|
|
118
|
+
getConnectionStatus() {
|
|
119
|
+
if (!this.tower)
|
|
120
|
+
return null;
|
|
121
|
+
this.lastConnectionStatus = this.tower.getConnectionStatus();
|
|
122
|
+
return this.lastConnectionStatus;
|
|
123
|
+
}
|
|
124
|
+
getDeviceInformation() {
|
|
125
|
+
if (!this.tower)
|
|
126
|
+
return null;
|
|
127
|
+
this.lastDeviceInfo = this.tower.getDeviceInformation();
|
|
128
|
+
return this.lastDeviceInfo;
|
|
129
|
+
}
|
|
130
|
+
setConnectionMonitoring(enabled) {
|
|
131
|
+
this.ensureTower();
|
|
132
|
+
this.tower.setConnectionMonitoring(enabled);
|
|
133
|
+
}
|
|
134
|
+
configureConnectionMonitoring(frequency, timeout) {
|
|
135
|
+
this.ensureTower();
|
|
136
|
+
this.tower.configureConnectionMonitoring(frequency, timeout);
|
|
137
|
+
}
|
|
138
|
+
configureBatteryHeartbeatMonitoring(enabled, timeout, verifyConnection) {
|
|
139
|
+
this.ensureTower();
|
|
140
|
+
this.tower.configureBatteryHeartbeatMonitoring(enabled, timeout, verifyConnection);
|
|
141
|
+
}
|
|
142
|
+
// --- Calibration ---
|
|
143
|
+
async calibrate() {
|
|
144
|
+
this.requireConnected();
|
|
145
|
+
const calibrationDone = new Promise((resolve) => {
|
|
146
|
+
this.calibrationCompleteResolve = resolve;
|
|
147
|
+
});
|
|
148
|
+
await this.tower.calibrate();
|
|
149
|
+
await calibrationDone;
|
|
150
|
+
}
|
|
151
|
+
// --- Audio ---
|
|
152
|
+
async playSoundStateful(soundIndex, loop, volume) {
|
|
153
|
+
this.requireConnected();
|
|
154
|
+
await this.tower.playSoundStateful(soundIndex, loop, volume);
|
|
155
|
+
}
|
|
156
|
+
// --- Lights ---
|
|
157
|
+
async lights(lights) {
|
|
158
|
+
this.requireConnected();
|
|
159
|
+
await this.tower.lights(lights);
|
|
160
|
+
}
|
|
161
|
+
async setLED(layerIndex, lightIndex, effect, loop) {
|
|
162
|
+
this.requireConnected();
|
|
163
|
+
await this.tower.setLED(layerIndex, lightIndex, effect, loop);
|
|
164
|
+
}
|
|
165
|
+
async allLightsOn(effect) {
|
|
166
|
+
this.requireConnected();
|
|
167
|
+
await this.tower.allLightsOn(effect);
|
|
168
|
+
}
|
|
169
|
+
async allLightsOff() {
|
|
170
|
+
this.requireConnected();
|
|
171
|
+
await this.tower.allLightsOff();
|
|
172
|
+
}
|
|
173
|
+
async lightOverrides(sequence, soundIndex) {
|
|
174
|
+
this.requireConnected();
|
|
175
|
+
await this.tower.lightOverrides(sequence, soundIndex);
|
|
176
|
+
}
|
|
177
|
+
// --- Drums ---
|
|
178
|
+
async rotateWithState(top, middle, bottom, soundIndex) {
|
|
179
|
+
this.requireConnected();
|
|
180
|
+
this.requireCalibrated();
|
|
181
|
+
await this.tower.rotateWithState(top, middle, bottom, soundIndex);
|
|
182
|
+
}
|
|
183
|
+
async rotateDrumStateful(drumIndex, position, playSound) {
|
|
184
|
+
this.requireConnected();
|
|
185
|
+
this.requireCalibrated();
|
|
186
|
+
await this.tower.rotateDrumStateful(drumIndex, position, playSound);
|
|
187
|
+
}
|
|
188
|
+
async randomRotateLevels(level) {
|
|
189
|
+
this.requireConnected();
|
|
190
|
+
this.requireCalibrated();
|
|
191
|
+
await this.tower.randomRotateLevels(level);
|
|
192
|
+
}
|
|
193
|
+
getCurrentDrumPosition(level) {
|
|
194
|
+
this.requireConnected();
|
|
195
|
+
return this.tower.getCurrentDrumPosition(level);
|
|
196
|
+
}
|
|
197
|
+
// --- Seals ---
|
|
198
|
+
async breakSeal(seal, volume) {
|
|
199
|
+
this.requireConnected();
|
|
200
|
+
this.requireCalibrated();
|
|
201
|
+
await this.tower.breakSeal(seal, volume);
|
|
202
|
+
}
|
|
203
|
+
isSealBroken(seal) {
|
|
204
|
+
if (!this.tower)
|
|
205
|
+
return false;
|
|
206
|
+
return this.tower.isSealBroken(seal);
|
|
207
|
+
}
|
|
208
|
+
getBrokenSeals() {
|
|
209
|
+
if (!this.tower)
|
|
210
|
+
return [];
|
|
211
|
+
return this.tower.getBrokenSeals();
|
|
212
|
+
}
|
|
213
|
+
resetBrokenSeals() {
|
|
214
|
+
if (this.tower) {
|
|
215
|
+
this.tower.resetBrokenSeals();
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
getRandomUnbrokenSeal() {
|
|
219
|
+
if (!this.tower)
|
|
220
|
+
return null;
|
|
221
|
+
return this.tower.getRandomUnbrokenSeal();
|
|
222
|
+
}
|
|
223
|
+
// --- State & Glyphs ---
|
|
224
|
+
getCurrentTowerState() {
|
|
225
|
+
if (!this.tower)
|
|
226
|
+
return null;
|
|
227
|
+
this.lastTowerState = this.tower.getCurrentTowerState();
|
|
228
|
+
return this.lastTowerState;
|
|
229
|
+
}
|
|
230
|
+
async sendTowerState(state) {
|
|
231
|
+
this.requireConnected();
|
|
232
|
+
// Guard against null/undefined or partially-shaped state objects.
|
|
233
|
+
// rtdt_pack_state crashes if state.drum is missing — merge with current
|
|
234
|
+
// state (or a safe default) so all required fields are always present.
|
|
235
|
+
const base = this.getCurrentTowerState() ?? buildDefaultTowerState();
|
|
236
|
+
const complete = {
|
|
237
|
+
drum: state?.drum ?? base.drum,
|
|
238
|
+
layer: state?.layer ?? base.layer,
|
|
239
|
+
audio: state?.audio ?? base.audio,
|
|
240
|
+
beam: state?.beam ?? base.beam,
|
|
241
|
+
led_sequence: state?.led_sequence ?? base.led_sequence,
|
|
242
|
+
};
|
|
243
|
+
await this.tower.sendTowerState(complete);
|
|
244
|
+
}
|
|
245
|
+
getGlyphPosition(glyph) {
|
|
246
|
+
if (!this.tower)
|
|
247
|
+
return null;
|
|
248
|
+
return this.tower.getGlyphPosition(glyph);
|
|
249
|
+
}
|
|
250
|
+
getAllGlyphPositions() {
|
|
251
|
+
if (!this.tower) {
|
|
252
|
+
return { cleanse: null, quest: null, battle: null, banner: null, reinforce: null };
|
|
253
|
+
}
|
|
254
|
+
return this.tower.getAllGlyphPositions();
|
|
255
|
+
}
|
|
256
|
+
getGlyphsFacingDirection(direction) {
|
|
257
|
+
if (!this.tower)
|
|
258
|
+
return [];
|
|
259
|
+
return this.tower.getGlyphsFacingDirection(direction);
|
|
260
|
+
}
|
|
261
|
+
get towerSkullDropCount() {
|
|
262
|
+
return this.tower?.towerSkullDropCount ?? this.skullCount;
|
|
263
|
+
}
|
|
264
|
+
async resetTowerSkullCount() {
|
|
265
|
+
this.requireConnected();
|
|
266
|
+
await this.tower.resetTowerSkullCount();
|
|
267
|
+
this.skullCount = 0;
|
|
268
|
+
}
|
|
269
|
+
// --- Snapshot for resources ---
|
|
270
|
+
getSnapshot() {
|
|
271
|
+
return {
|
|
272
|
+
connected: this.isConnected,
|
|
273
|
+
calibrated: this.isCalibrated,
|
|
274
|
+
performingLongCommand: this.performingLongCommand,
|
|
275
|
+
performingCalibration: this.performingCalibration,
|
|
276
|
+
battery: {
|
|
277
|
+
currentMillivolts: this.tower?.currentBattery ?? 0,
|
|
278
|
+
previousMillivolts: this.tower?.previousBattery ?? 0,
|
|
279
|
+
currentPercentage: this.tower?.currentBatteryPercent ?? 0,
|
|
280
|
+
previousPercentage: this.tower?.previousBatteryPercent ?? 0,
|
|
281
|
+
},
|
|
282
|
+
skullDropCount: this.towerSkullDropCount,
|
|
283
|
+
connectionStatus: this.getConnectionStatus(),
|
|
284
|
+
deviceInfo: this.lastDeviceInfo,
|
|
285
|
+
towerState: this.lastTowerState,
|
|
286
|
+
brokenSeals: this.getBrokenSeals(),
|
|
287
|
+
glyphs: this.getAllGlyphPositions(),
|
|
288
|
+
drumPositions: this.getDrumPositionsMap(),
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
getDrumPositionsMap() {
|
|
292
|
+
if (!this.tower || !this.isConnected) {
|
|
293
|
+
return { top: null, middle: null, bottom: null };
|
|
294
|
+
}
|
|
295
|
+
try {
|
|
296
|
+
return {
|
|
297
|
+
top: this.tower.getCurrentDrumPosition("top"),
|
|
298
|
+
middle: this.tower.getCurrentDrumPosition("middle"),
|
|
299
|
+
bottom: this.tower.getCurrentDrumPosition("bottom"),
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
catch {
|
|
303
|
+
return { top: null, middle: null, bottom: null };
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
// --- Precondition checks ---
|
|
307
|
+
requireConnected() {
|
|
308
|
+
if (!this.tower || !this.isConnected) {
|
|
309
|
+
throw new BluetoothConnectionError("Tower is not connected. Call tower_connect first.");
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
requireCalibrated() {
|
|
313
|
+
this.requireConnected();
|
|
314
|
+
if (!this.isCalibrated) {
|
|
315
|
+
throw new BluetoothConnectionError("Tower is not calibrated. Call tower_calibrate first.");
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Wraps a tool handler to catch UDT errors and return MCP-friendly error responses.
|
|
321
|
+
*/
|
|
322
|
+
export function wrapToolHandler(fn) {
|
|
323
|
+
return fn()
|
|
324
|
+
.then((result) => ({
|
|
325
|
+
content: [
|
|
326
|
+
{
|
|
327
|
+
type: "text",
|
|
328
|
+
text: typeof result === "string" ? result : JSON.stringify(result, null, 2),
|
|
329
|
+
},
|
|
330
|
+
],
|
|
331
|
+
}))
|
|
332
|
+
.catch((err) => {
|
|
333
|
+
let message = "Unknown error";
|
|
334
|
+
if (err instanceof BluetoothDeviceNotFoundError) {
|
|
335
|
+
message = `Tower not found: ${err.message}`;
|
|
336
|
+
}
|
|
337
|
+
else if (err instanceof BluetoothTimeoutError) {
|
|
338
|
+
message = `Bluetooth timeout: ${err.message}`;
|
|
339
|
+
}
|
|
340
|
+
else if (err instanceof BluetoothUserCancelledError) {
|
|
341
|
+
message = `Operation cancelled: ${err.message}`;
|
|
342
|
+
}
|
|
343
|
+
else if (err instanceof BluetoothConnectionError) {
|
|
344
|
+
message = `Connection error: ${err.message}`;
|
|
345
|
+
}
|
|
346
|
+
else if (err instanceof Error) {
|
|
347
|
+
message = err.message;
|
|
348
|
+
}
|
|
349
|
+
return {
|
|
350
|
+
content: [{ type: "text", text: message }],
|
|
351
|
+
isError: true,
|
|
352
|
+
};
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
//# sourceMappingURL=tower-controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tower-controller.js","sourceRoot":"","sources":["../src/tower-controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { LogOutput, LogLevel } from "ultimatedarktower";
|
|
3
|
+
/**
|
|
4
|
+
* Custom LogOutput that forwards UDT log messages to the MCP server.
|
|
5
|
+
*/
|
|
6
|
+
export declare class McpLogOutput implements LogOutput {
|
|
7
|
+
private server;
|
|
8
|
+
constructor(server: McpServer);
|
|
9
|
+
write(level: LogLevel, message: string, _timestamp: Date): void;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAqB7D;;GAEG;AACH,qBAAa,YAAa,YAAW,SAAS;IAChC,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,SAAS;IAErC,KAAK,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,GAAG,IAAI;CAWhE"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Map UDT log levels to MCP log levels
|
|
2
|
+
const LOG_LEVEL_MAP = {
|
|
3
|
+
debug: "debug",
|
|
4
|
+
info: "info",
|
|
5
|
+
warn: "warning",
|
|
6
|
+
error: "error",
|
|
7
|
+
all: "debug",
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Custom LogOutput that forwards UDT log messages to the MCP server.
|
|
11
|
+
*/
|
|
12
|
+
export class McpLogOutput {
|
|
13
|
+
server;
|
|
14
|
+
constructor(server) {
|
|
15
|
+
this.server = server;
|
|
16
|
+
}
|
|
17
|
+
write(level, message, _timestamp) {
|
|
18
|
+
const mcpLevel = LOG_LEVEL_MAP[level] ?? "info";
|
|
19
|
+
this.server
|
|
20
|
+
.sendLoggingMessage({
|
|
21
|
+
level: mcpLevel,
|
|
22
|
+
data: message,
|
|
23
|
+
})
|
|
24
|
+
.catch(() => {
|
|
25
|
+
// Ignore errors from logging (e.g., disconnected client)
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAaA,uCAAuC;AACvC,MAAM,aAAa,GAAgC;IACjD,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,SAAS;IACf,KAAK,EAAE,OAAO;IACd,GAAG,EAAE,OAAO;CACb,CAAC;AAEF;;GAEG;AACH,MAAM,OAAO,YAAY;IACH;IAApB,YAAoB,MAAiB;QAAjB,WAAM,GAAN,MAAM,CAAW;IAAG,CAAC;IAEzC,KAAK,CAAC,KAAe,EAAE,OAAe,EAAE,UAAgB;QACtD,MAAM,QAAQ,GAAgB,aAAa,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC;QAC7D,IAAI,CAAC,MAAM;aACR,kBAAkB,CAAC;YAClB,KAAK,EAAE,QAAQ;YACf,IAAI,EAAE,OAAO;SACd,CAAC;aACD,KAAK,CAAC,GAAG,EAAE;YACV,yDAAyD;QAC3D,CAAC,CAAC,CAAC;IACP,CAAC;CACF"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
type AudioEntry = {
|
|
2
|
+
name: string;
|
|
3
|
+
value: number;
|
|
4
|
+
category: string;
|
|
5
|
+
};
|
|
6
|
+
export declare const soundNameToIndex: Map<string, number>;
|
|
7
|
+
export declare const soundIndexToEntry: Map<number, AudioEntry>;
|
|
8
|
+
export declare const soundCategoryIndex: Map<string, AudioEntry[]>;
|
|
9
|
+
export declare const lightSequenceNameToValue: Map<string, number>;
|
|
10
|
+
export declare const lightEffectNameToValue: Map<string, number>;
|
|
11
|
+
export declare function getSoundCategories(): string[];
|
|
12
|
+
export declare function getAudioLibrary(): AudioEntry[];
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=lookups.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lookups.d.ts","sourceRoot":"","sources":["../../src/utils/lookups.ts"],"names":[],"mappings":"AAEA,KAAK,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAGpE,eAAO,MAAM,gBAAgB,qBAA4B,CAAC;AAE1D,eAAO,MAAM,iBAAiB,yBAAgC,CAAC;AAE/D,eAAO,MAAM,kBAAkB,2BAAkC,CAAC;AAYlE,eAAO,MAAM,wBAAwB,qBAA4B,CAAC;AAMlE,eAAO,MAAM,sBAAsB,qBAA4B,CAAC;AAMhE,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAE7C;AAGD,wBAAgB,eAAe,IAAI,UAAU,EAAE,CAE9C"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { TOWER_AUDIO_LIBRARY, TOWER_LIGHT_SEQUENCES, LIGHT_EFFECTS } from "ultimatedarktower";
|
|
2
|
+
// Sound name → index lookup (case-insensitive key → value)
|
|
3
|
+
export const soundNameToIndex = new Map();
|
|
4
|
+
// Sound index → entry lookup
|
|
5
|
+
export const soundIndexToEntry = new Map();
|
|
6
|
+
// Sounds grouped by category
|
|
7
|
+
export const soundCategoryIndex = new Map();
|
|
8
|
+
for (const [, entry] of Object.entries(TOWER_AUDIO_LIBRARY)) {
|
|
9
|
+
soundNameToIndex.set(entry.name.toLowerCase(), entry.value);
|
|
10
|
+
soundIndexToEntry.set(entry.value, entry);
|
|
11
|
+
const categoryList = soundCategoryIndex.get(entry.category) ?? [];
|
|
12
|
+
categoryList.push(entry);
|
|
13
|
+
soundCategoryIndex.set(entry.category, categoryList);
|
|
14
|
+
}
|
|
15
|
+
// Light sequence name → value lookup
|
|
16
|
+
export const lightSequenceNameToValue = new Map();
|
|
17
|
+
for (const [name, value] of Object.entries(TOWER_LIGHT_SEQUENCES)) {
|
|
18
|
+
lightSequenceNameToValue.set(name.toLowerCase(), value);
|
|
19
|
+
}
|
|
20
|
+
// Light effect name → value lookup
|
|
21
|
+
export const lightEffectNameToValue = new Map();
|
|
22
|
+
for (const [name, value] of Object.entries(LIGHT_EFFECTS)) {
|
|
23
|
+
lightEffectNameToValue.set(name.toLowerCase(), value);
|
|
24
|
+
}
|
|
25
|
+
// Get all unique sound categories
|
|
26
|
+
export function getSoundCategories() {
|
|
27
|
+
return [...soundCategoryIndex.keys()].sort();
|
|
28
|
+
}
|
|
29
|
+
// Get the full audio library as a serializable array
|
|
30
|
+
export function getAudioLibrary() {
|
|
31
|
+
return [...soundIndexToEntry.values()].sort((a, b) => a.value - b.value);
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=lookups.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lookups.js","sourceRoot":"","sources":["../../src/utils/lookups.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAI9F,2DAA2D;AAC3D,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAkB,CAAC;AAC1D,6BAA6B;AAC7B,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAsB,CAAC;AAC/D,6BAA6B;AAC7B,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAwB,CAAC;AAElE,KAAK,MAAM,CAAC,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,mBAAiD,CAAC,EAAE,CAAC;IAC1F,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAC5D,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAE1C,MAAM,YAAY,GAAG,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IAClE,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACzB,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;AACvD,CAAC;AAED,qCAAqC;AACrC,MAAM,CAAC,MAAM,wBAAwB,GAAG,IAAI,GAAG,EAAkB,CAAC;AAClE,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,qBAA+C,CAAC,EAAE,CAAC;IAC5F,wBAAwB,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,KAAK,CAAC,CAAC;AAC1D,CAAC;AAED,mCAAmC;AACnC,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,GAAG,EAAkB,CAAC;AAChE,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAuC,CAAC,EAAE,CAAC;IACpF,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,KAAK,CAAC,CAAC;AACxD,CAAC;AAED,kCAAkC;AAClC,MAAM,UAAU,kBAAkB;IAChC,OAAO,CAAC,GAAG,kBAAkB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AAC/C,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,eAAe;IAC7B,OAAO,CAAC,GAAG,iBAAiB,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;AAC3E,CAAC"}
|