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.
Files changed (2) hide show
  1. package/dist/server.js +209 -14
  2. 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 uses .player (NOT .localPlayer): sdk.getState().player.worldX (NOT state.localPlayer.x)
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. The code runs in an async context with three globals:
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
- State object: sdk.getState().player.worldX, .worldZ, .hp, .maxHp
4174
- Movement: sdk.sendWalk(x, z) for quick moves, bot.walkTo(x, z) for pathfinding
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
- Blocking UI is auto-dismissed before your code runs — do NOT call bot.dismissBlockingUI().
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
- return value.apply(obj, args2);
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)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kill-switch-mcp",
3
- "version": "1.1.8",
3
+ "version": "1.1.9",
4
4
  "description": "Kill Switch MCP Server — AI battle royale powered by Claude Code",
5
5
  "type": "module",
6
6
  "bin": {