kill-switch-mcp 1.1.8 → 1.1.9
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/dist/server.js +209 -14
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -7,7 +7,9 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
7
7
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
8
8
|
import {
|
|
9
9
|
CallToolRequestSchema,
|
|
10
|
-
ListToolsRequestSchema
|
|
10
|
+
ListToolsRequestSchema,
|
|
11
|
+
ListResourcesRequestSchema,
|
|
12
|
+
ReadResourceRequestSchema
|
|
11
13
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
12
14
|
import { existsSync as existsSync3 } from "fs";
|
|
13
15
|
import { readFile as readFile2 } from "fs/promises";
|
|
@@ -4131,8 +4133,11 @@ Actions are loaded from your bot's actions/ directory at login. Default actions:
|
|
|
4131
4133
|
|
|
4132
4134
|
### IMPORTANT NOTES:
|
|
4133
4135
|
- Blocking UI is auto-dismissed before every execute_code call — you do NOT need to call bot.dismissBlockingUI()
|
|
4136
|
+
- bot methods THROW on failure — use try/catch if you want to handle errors gracefully
|
|
4134
4137
|
- bot.walkTo() uses server pathfinding (can be slow). For quick movement, use sdk.sendWalk(x, z) + sdk.waitForTicks(5)
|
|
4135
|
-
- State
|
|
4138
|
+
- State path: sdk.getState().player.worldX / .worldZ / .hp / .maxHp (NOT .localPlayer, NOT .hitpoints)
|
|
4139
|
+
- Ground items use .x / .z (NOT .worldX / .worldZ): sdk.getGroundItems()[0].x
|
|
4140
|
+
- Players use .x / .z for nearby players, .worldX / .worldZ for your own player
|
|
4136
4141
|
- Keep execute_code calls to 15-30 seconds, then check state and adapt
|
|
4137
4142
|
|
|
4138
4143
|
## Key Tips
|
|
@@ -4140,7 +4145,183 @@ Actions are loaded from your bot's actions/ directory at login. Default actions:
|
|
|
4140
4145
|
- Grab a weapon first, then food, then armor
|
|
4141
4146
|
- Risk vs reward: center has the best loot but everyone converges there
|
|
4142
4147
|
- The human gives you strategy ("rush center", "play safe", "grab and run") — you turn it into code`;
|
|
4143
|
-
var server = new Server({ name: "kill-switch", version: "3.0.0" }, { capabilities: { tools: {} } });
|
|
4148
|
+
var server = new Server({ name: "kill-switch", version: "3.0.0" }, { capabilities: { tools: {}, resources: {} } });
|
|
4149
|
+
var SDK_REFERENCE = `# Kill Switch SDK Reference
|
|
4150
|
+
|
|
4151
|
+
This is the DEFINITIVE API reference. Do NOT guess method names or property paths.
|
|
4152
|
+
If a method or property is not listed here, it does not exist.
|
|
4153
|
+
|
|
4154
|
+
## Globals available in execute_code
|
|
4155
|
+
|
|
4156
|
+
Three objects are available in every execute_code call:
|
|
4157
|
+
- \`bot\` — High-level game actions (all async, all throw on failure)
|
|
4158
|
+
- \`sdk\` — Low-level state access and direct commands
|
|
4159
|
+
- \`actions\` — Pre-built strategy functions loaded from your bot's actions/ directory
|
|
4160
|
+
|
|
4161
|
+
---
|
|
4162
|
+
|
|
4163
|
+
## bot methods
|
|
4164
|
+
|
|
4165
|
+
All bot methods are async. They THROW an error if they fail — you do NOT need to check return values.
|
|
4166
|
+
Wrap in try/catch if you want to handle failures gracefully.
|
|
4167
|
+
|
|
4168
|
+
### Movement
|
|
4169
|
+
- \`await bot.walkTo(x, z)\` — Pathfind and walk to coordinates. Uses server-side pathfinding. Can be slow and may fail if path is blocked by walls/doors.
|
|
4170
|
+
|
|
4171
|
+
### Items
|
|
4172
|
+
- \`await bot.pickupItem(pattern)\` — Walk to and pick up a ground item matching the pattern. Example: \`await bot.pickupItem(/rune scimitar/i)\`
|
|
4173
|
+
- \`await bot.equipItem(pattern)\` — Equip an item from inventory. Example: \`await bot.equipItem(/rune scimitar/i)\`
|
|
4174
|
+
- \`await bot.eatFood(pattern)\` — Eat food from inventory. Example: \`await bot.eatFood(/lobster/i)\`
|
|
4175
|
+
|
|
4176
|
+
### Combat
|
|
4177
|
+
- \`await bot.attackPlayer(nameOrPattern)\` — Attack a player. Example: \`await bot.attackPlayer("Arwen")\` or \`await bot.attackPlayer(/arwen/i)\`
|
|
4178
|
+
- \`await bot.attackNpc(nameOrPattern)\` — Attack an NPC.
|
|
4179
|
+
|
|
4180
|
+
### NPCs & Objects
|
|
4181
|
+
- \`await bot.talkTo(nameOrPattern)\` — Talk to an NPC.
|
|
4182
|
+
- \`await bot.interactLoc(nameOrPattern, option)\` — Interact with a game object.
|
|
4183
|
+
- \`await bot.interactNpc(nameOrPattern, option)\` — Interact with an NPC.
|
|
4184
|
+
- \`await bot.openDoor(x, z)\` — Open a door at coordinates.
|
|
4185
|
+
|
|
4186
|
+
### Dialog
|
|
4187
|
+
- \`await bot.navigateDialog(choices)\` — Navigate through NPC dialog.
|
|
4188
|
+
- \`await bot.waitForDialogClose()\` — Wait for dialog to close.
|
|
4189
|
+
|
|
4190
|
+
### Other
|
|
4191
|
+
- \`await bot.dismissBlockingUI()\` — Dismiss modals/dialogs. NOTE: This is called automatically before every execute_code — you do NOT need to call it yourself.
|
|
4192
|
+
- \`await bot.waitForIdle()\` — Wait until the bot is idle (not moving/acting).
|
|
4193
|
+
|
|
4194
|
+
---
|
|
4195
|
+
|
|
4196
|
+
## sdk methods
|
|
4197
|
+
|
|
4198
|
+
### State (instant, not async)
|
|
4199
|
+
- \`sdk.getState()\` — Returns the full game state object. See "State Object Shape" below.
|
|
4200
|
+
- \`sdk.getInventory()\` — Array of inventory items. Each has: \`.name\`, \`.id\`, \`.count\`, \`.slot\`
|
|
4201
|
+
- \`sdk.getEquipment()\` — Array of equipped items. Each has: \`.name\`, \`.id\`, \`.slot\`
|
|
4202
|
+
- \`sdk.getNearbyPlayers()\` — Array of nearby players. Each has: \`.name\`, \`.combatLevel\`, \`.distance\`, \`.x\`, \`.z\`
|
|
4203
|
+
- \`sdk.getGroundItems()\` — Array of ground items. Each has: \`.name\`, \`.id\`, \`.count\`, \`.x\`, \`.z\`, \`.distance\`
|
|
4204
|
+
- \`sdk.getNearbyLocs()\` — Array of nearby game objects.
|
|
4205
|
+
- \`sdk.getNearbyNpcs()\` — Array of nearby NPCs.
|
|
4206
|
+
|
|
4207
|
+
### Search (instant, not async)
|
|
4208
|
+
- \`sdk.findInventoryItem(pattern)\` — Find first matching inventory item. Returns item or null.
|
|
4209
|
+
- \`sdk.findGroundItem(pattern)\` — Find first matching ground item. Returns item or null.
|
|
4210
|
+
- \`sdk.findNearbyPlayer(pattern)\` — Find a nearby player. Returns player or null.
|
|
4211
|
+
- \`sdk.findNearbyNpc(pattern)\` — Find a nearby NPC. Returns NPC or null.
|
|
4212
|
+
- \`sdk.findNearbyLoc(pattern)\` — Find a nearby game object. Returns loc or null.
|
|
4213
|
+
|
|
4214
|
+
### Direct Commands (instant, fire-and-forget)
|
|
4215
|
+
- \`sdk.sendWalk(x, z)\` — Click a tile to walk there. Fast, no pathfinding. Use for quick movement during combat.
|
|
4216
|
+
- \`sdk.sendPickup(itemId, x, z)\` — Send raw pickup command.
|
|
4217
|
+
- \`sdk.sendInteractPlayer(playerIndex, option)\` — Interact with a player directly.
|
|
4218
|
+
- \`sdk.sendInteractNpc(npcId, option)\` — Interact with an NPC directly.
|
|
4219
|
+
- \`sdk.sendInteractLoc(locId, x, z, option)\` — Interact with a game object directly.
|
|
4220
|
+
- \`sdk.sendUseItem(slot)\` — Use an inventory item (e.g., eat food).
|
|
4221
|
+
- \`sdk.sendSetCombatStyle(style)\` — Change combat style (0-3).
|
|
4222
|
+
- \`sdk.sendTogglePrayer(prayerId)\` — Toggle a prayer on/off.
|
|
4223
|
+
|
|
4224
|
+
### Timing (async)
|
|
4225
|
+
- \`await sdk.waitForTicks(n)\` — Wait n game ticks. Each tick ≈ 0.6 seconds.
|
|
4226
|
+
- \`await sdk.waitForStateChange(timeoutMs)\` — Wait for any state update.
|
|
4227
|
+
- \`await sdk.waitForCondition(fn, timeoutMs)\` — Wait until fn(state) returns true.
|
|
4228
|
+
|
|
4229
|
+
---
|
|
4230
|
+
|
|
4231
|
+
## State Object Shape
|
|
4232
|
+
|
|
4233
|
+
\`\`\`
|
|
4234
|
+
sdk.getState() returns:
|
|
4235
|
+
{
|
|
4236
|
+
tick: number, // Current game tick
|
|
4237
|
+
player: {
|
|
4238
|
+
name: string,
|
|
4239
|
+
worldX: number, // Your X coordinate
|
|
4240
|
+
worldZ: number, // Your Z coordinate
|
|
4241
|
+
level: number, // Floor level (0 = ground)
|
|
4242
|
+
hp: number, // Current hitpoints
|
|
4243
|
+
maxHp: number, // Max hitpoints
|
|
4244
|
+
combatLevel: number,
|
|
4245
|
+
animation: number, // Current animation ID (-1 = idle)
|
|
4246
|
+
},
|
|
4247
|
+
skills: [...], // Array of skill objects
|
|
4248
|
+
inventory: [...], // Array of inventory slots
|
|
4249
|
+
equipment: [...], // Array of equipment slots
|
|
4250
|
+
groundItems: [...], // Nearby ground items (each has .name, .x, .z, .id, .count)
|
|
4251
|
+
nearbyPlayers: [...], // Nearby players
|
|
4252
|
+
nearbyNpcs: [...], // Nearby NPCs
|
|
4253
|
+
dialog: { isOpen, ... }, // Dialog state
|
|
4254
|
+
modalOpen: boolean, // Whether a modal is open
|
|
4255
|
+
}
|
|
4256
|
+
\`\`\`
|
|
4257
|
+
|
|
4258
|
+
IMPORTANT PROPERTY NAMES:
|
|
4259
|
+
- Player position: \`.player.worldX\`, \`.player.worldZ\` (NOT .localPlayer, NOT .x/.z)
|
|
4260
|
+
- Player HP: \`.player.hp\`, \`.player.maxHp\` (NOT .hitpoints, NOT .hitpointsBase)
|
|
4261
|
+
- Ground item position: \`.x\`, \`.z\` (NOT .worldX, NOT .worldZ)
|
|
4262
|
+
- Nearby player position: \`.x\`, \`.z\` (NOT .worldX, NOT .worldZ)
|
|
4263
|
+
|
|
4264
|
+
---
|
|
4265
|
+
|
|
4266
|
+
## Common Patterns
|
|
4267
|
+
|
|
4268
|
+
### Quick loot (walk + pick up):
|
|
4269
|
+
\`\`\`
|
|
4270
|
+
sdk.sendWalk(3106, 3353); // Click tile to walk there
|
|
4271
|
+
await sdk.waitForTicks(5); // Wait to arrive
|
|
4272
|
+
await bot.pickupItem(/lobster/i); // Pick up item at feet
|
|
4273
|
+
await bot.equipItem(/scimitar/i); // Equip from inventory
|
|
4274
|
+
\`\`\`
|
|
4275
|
+
|
|
4276
|
+
### Combat loop:
|
|
4277
|
+
\`\`\`
|
|
4278
|
+
const endTime = Date.now() + 15000;
|
|
4279
|
+
while (Date.now() < endTime) {
|
|
4280
|
+
const state = sdk.getState();
|
|
4281
|
+
if (state.player.hp < 30) {
|
|
4282
|
+
try { await bot.eatFood(/lobster|swordfish|salmon/i); } catch(e) {}
|
|
4283
|
+
}
|
|
4284
|
+
const players = sdk.getNearbyPlayers();
|
|
4285
|
+
if (players.length > 0) {
|
|
4286
|
+
const target = players.sort((a, b) => a.distance - b.distance)[0];
|
|
4287
|
+
try { await bot.attackPlayer(target.name); } catch(e) {}
|
|
4288
|
+
}
|
|
4289
|
+
await sdk.waitForTicks(2);
|
|
4290
|
+
}
|
|
4291
|
+
\`\`\`
|
|
4292
|
+
|
|
4293
|
+
### Movement tip:
|
|
4294
|
+
For combat/arena play, use \`sdk.sendWalk(x, z)\` + \`await sdk.waitForTicks(n)\` instead of \`bot.walkTo()\`.
|
|
4295
|
+
\`bot.walkTo()\` uses server pathfinding which can be slow or fail on complex terrain.
|
|
4296
|
+
\`sdk.sendWalk()\` just clicks the tile directly — fast and reliable for short distances.
|
|
4297
|
+
`;
|
|
4298
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
4299
|
+
return {
|
|
4300
|
+
resources: [
|
|
4301
|
+
{
|
|
4302
|
+
uri: "killswitch://sdk-reference",
|
|
4303
|
+
name: "Kill Switch SDK Reference",
|
|
4304
|
+
description: "Complete API reference for bot, sdk, and actions objects used in execute_code. READ THIS FIRST before writing any game code.",
|
|
4305
|
+
mimeType: "text/markdown"
|
|
4306
|
+
}
|
|
4307
|
+
]
|
|
4308
|
+
};
|
|
4309
|
+
});
|
|
4310
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
4311
|
+
const { uri } = request.params;
|
|
4312
|
+
if (uri === "killswitch://sdk-reference") {
|
|
4313
|
+
return {
|
|
4314
|
+
contents: [
|
|
4315
|
+
{
|
|
4316
|
+
uri: "killswitch://sdk-reference",
|
|
4317
|
+
mimeType: "text/markdown",
|
|
4318
|
+
text: SDK_REFERENCE
|
|
4319
|
+
}
|
|
4320
|
+
]
|
|
4321
|
+
};
|
|
4322
|
+
}
|
|
4323
|
+
throw new Error(`Unknown resource: ${uri}`);
|
|
4324
|
+
});
|
|
4144
4325
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
4145
4326
|
return {
|
|
4146
4327
|
tools: [
|
|
@@ -4165,16 +4346,17 @@ ${GAME_DESCRIPTION}`,
|
|
|
4165
4346
|
},
|
|
4166
4347
|
{
|
|
4167
4348
|
name: "execute_code",
|
|
4168
|
-
description: `Execute TypeScript code on your connected bot.
|
|
4169
|
-
- bot: High-level actions (await bot.pickupItem(/name/i), bot.equipItem(), bot.eatFood(), bot.attackPlayer(), bot.walkTo())
|
|
4170
|
-
- sdk: Low-level state/commands (sdk.getState(), sdk.sendWalk(x,z), sdk.getNearbyPlayers(), sdk.getInventory(), sdk.findGroundItem())
|
|
4171
|
-
- actions: Pre-built strategy functions from bot's actions/ directory (listed at login)
|
|
4349
|
+
description: `Execute TypeScript code on your connected bot. Three globals available: bot, sdk, actions.
|
|
4172
4350
|
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
Timing: await sdk.waitForTicks(n) — each tick is ~0.6 seconds
|
|
4351
|
+
IMPORTANT: Read the "Kill Switch SDK Reference" resource (killswitch://sdk-reference) for the complete API.
|
|
4352
|
+
Do NOT guess method names or property paths — only use what is documented in the SDK reference.
|
|
4176
4353
|
|
|
4177
|
-
|
|
4354
|
+
Quick reminders:
|
|
4355
|
+
- bot methods are async and THROW on failure
|
|
4356
|
+
- sdk.getState().player.worldX / .worldZ / .hp / .maxHp
|
|
4357
|
+
- Ground items use .x / .z (NOT .worldX)
|
|
4358
|
+
- sdk.sendWalk(x, z) for fast movement, bot.walkTo(x, z) for pathfinding
|
|
4359
|
+
- Blocking UI is auto-dismissed — do NOT call bot.dismissBlockingUI()
|
|
4178
4360
|
|
|
4179
4361
|
You MUST call login before using this tool.`,
|
|
4180
4362
|
inputSchema: {
|
|
@@ -4572,6 +4754,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
|
4572
4754
|
"",
|
|
4573
4755
|
"After joining a game, call wait_for_game_start to wait for the game to begin."
|
|
4574
4756
|
];
|
|
4757
|
+
parts.push("");
|
|
4758
|
+
parts.push("── IMPORTANT: Read the SDK Reference ──");
|
|
4759
|
+
parts.push('Before writing any execute_code, read the "Kill Switch SDK Reference" resource (killswitch://sdk-reference).');
|
|
4760
|
+
parts.push("It contains the complete API for bot, sdk, and actions. Do NOT guess method names — use only what is documented.");
|
|
4575
4761
|
if (activeActionDescriptions.length > 0) {
|
|
4576
4762
|
parts.push("");
|
|
4577
4763
|
parts.push("── Loaded Actions ──");
|
|
@@ -4654,14 +4840,23 @@ server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
|
4654
4840
|
reject(new Error(typeof signal.reason === "string" ? signal.reason : "Code execution cancelled"));
|
|
4655
4841
|
}, { once: true });
|
|
4656
4842
|
});
|
|
4657
|
-
const cancellable = (target) => new Proxy(target, {
|
|
4843
|
+
const cancellable = (target, throwOnFailure = false) => new Proxy(target, {
|
|
4658
4844
|
get(obj, prop, receiver) {
|
|
4659
4845
|
const value = Reflect.get(obj, prop, receiver);
|
|
4660
4846
|
if (typeof value === "function") {
|
|
4661
4847
|
return (...args2) => {
|
|
4662
4848
|
if (signal.aborted)
|
|
4663
4849
|
throw new Error("Execution cancelled");
|
|
4664
|
-
|
|
4850
|
+
const ret = value.apply(obj, args2);
|
|
4851
|
+
if (throwOnFailure && ret && typeof ret.then === "function") {
|
|
4852
|
+
return ret.then((result2) => {
|
|
4853
|
+
if (result2 && typeof result2 === "object" && result2.success === false) {
|
|
4854
|
+
throw new Error(result2.message || `${String(prop)} failed`);
|
|
4855
|
+
}
|
|
4856
|
+
return result2;
|
|
4857
|
+
});
|
|
4858
|
+
}
|
|
4859
|
+
return ret;
|
|
4665
4860
|
};
|
|
4666
4861
|
}
|
|
4667
4862
|
return value;
|
|
@@ -4670,7 +4865,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
|
4670
4865
|
await connection.bot.dismissBlockingUI();
|
|
4671
4866
|
let result;
|
|
4672
4867
|
try {
|
|
4673
|
-
result = await Promise.race([fn(cancellable(connection.bot), cancellable(connection.sdk), activeActions), timeoutPromise, cancelPromise]);
|
|
4868
|
+
result = await Promise.race([fn(cancellable(connection.bot, true), cancellable(connection.sdk), activeActions), timeoutPromise, cancelPromise]);
|
|
4674
4869
|
} finally {
|
|
4675
4870
|
clearTimeout(timeoutId);
|
|
4676
4871
|
if (!signal.aborted)
|