mcp-server-return-to-dark-tower

mcp-server-return-to-dark-tower

Lets AI assistants control the physical Return to Dark Tower board game tower via Bluetooth, enabling connection, calibration, sound, lights, drum rotation, seal breaking, and game sequences through natural language.

Category
Visit Server

README

Return to Dark Tower — AI MCP Server

License: MIT Node.js npm

An MCP server that lets AI assistants like Claude, ChatGPT, and Gemini control the physical Return to Dark Tower board game tower via Bluetooth. Connect, calibrate, play sounds, animate lights, rotate drums, break seals, and run dramatic game sequences — all through natural language.

Features <!-- omit in toc -->

  • 31 MCP tools across 6 domains — connection, audio, lights, drums, seals, state & glyphs
  • 15 tower state resources — connection status, battery, drum positions, glyphs, seals, audio library, light effects
  • 8 game knowledge resources — rules, heroes, items, quests, adversaries, buildings, lore, glossary
  • 8 prompt templates — dramatic entrance, victory/defeat sequences, monthly transitions, dungeon runs, battle starts, game master setup, sound browser
  • Dual transport — stdio for desktop AI tools, Streamable HTTP for web apps
  • Zero custom BLE code — built on UltimateDarkTower adapter pattern

AI Agents <!-- omit in toc -->

Ready-to-use AI agents for this server and the ultimatedarktower library: 👉 return-to-dark-tower-agents

  • Return to Dark Tower agent — system prompt for Claude.ai, ChatGPT, and other web AI tools; knows all 31 tools, 15 resources, and 8 prompts
  • Ultimate Dark Tower agent — VS Code / GitHub Copilot coding agent for building apps with the ultimatedarktower npm library

Supported in VS Code (GitHub Copilot), Claude.ai, ChatGPT, and 20+ tools via the AGENTS.md standard.


📚 Table of Contents <!-- omit in toc -->


⚡ Quick Start

Requires Node.js 18+. Run node --version to check.

🌐 For Web AI Chat Apps (Claude.ai, ChatGPT, etc.)

Step 1 — Open a terminal and start the server:

npx -y mcp-server-return-to-dark-tower --http-only --port 3001

npx fetches the package from npm on first run (cached after that) and starts the server. Keep this terminal open — the server runs as long as the window is open.

Step 2 — Connect your web AI app to the server.

In your AI app's settings, add a new MCP connection pointing at:

http://localhost:3001/mcp

See Web-Based AI Chat Apps for step-by-step instructions for Claude.ai and ChatGPT.

Step 3 — Ask it something like:

"Connect to the tower, calibrate it, then turn on all the north doorway lights."


🖥️ For Desktop AI Tools (Claude Desktop, Cursor, VS Code, etc.)

Step 1 — Add this to your AI tool's config file (find the exact file path for your tool in Setup with Your AI Tool):

{
  "mcpServers": {
    "return-to-dark-tower": {
      "command": "npx",
      "args": ["-y", "mcp-server-return-to-dark-tower", "--stdio-only"]
    }
  }
}

Step 2 — Restart your AI tool.

When it starts, it runs the npx command above — npx fetches the package from npm (first run only, cached after that) and launches the server as a background process. No separate terminal needed.

Step 3 — Ask it something like:

"Connect to the tower, calibrate it, then turn on all the north doorway lights."


What is MCP?

MCP (Model Context Protocol) is an open standard that lets AI assistants use tools and access data from external systems — similar to how a browser loads plugins. Instead of the AI just knowing about your tower, it can control it.

This server implements the MCP standard. Once configured, your AI assistant gains 31 tools it can call by name — things like tower_play_sound, tower_break_seal, or tower_rotate_drum — and it can chain them together to run full dramatic game sequences on command.

Two ways to connect:

Transport Best for How it works
stdio Desktop AI apps (Claude Desktop, Cursor, VS Code, etc.) The AI app launches this server as a background process and communicates over stdin/stdout
HTTP Web-based AI apps (Claude.ai, ChatGPT web) You start the server manually; the AI app connects to it over HTTP

Getting Started

Prerequisites

Before you begin, make sure you have:

  1. Node.js 18 or newer — Download from nodejs.org. To check your version, run node --version in a terminal.
  2. Bluetooth Low Energy (BLE) hardware — Built into most Macs made after 2011 and most modern Windows PCs.
  3. A physical Return to Dark Tower tower, though you could use the resources in the server without a tower.

Platform-specific setup:

Platform What you need to do
macOS Nothing extra. After first use, grant Bluetooth permission: System Settings → Privacy & Security → Bluetooth → allow Terminal (or your AI app).
Linux Install BlueZ first: sudo apt install bluetooth bluez libbluetooth-dev
Windows Windows 10 or newer with Bluetooth is required. No extra setup needed.

Install

The easiest way is to use npx, which runs the package directly from npm without any installation step:

# Test that it works — this starts the server in stdio mode
npx -y mcp-server-return-to-dark-tower --stdio-only

What is npx? It's a tool that comes bundled with Node.js. It downloads and runs a package from the npm registry on demand, so you don't have to install anything globally.

If you'd rather install it globally (for faster startup after the first run):

npm install -g mcp-server-return-to-dark-tower

Pick your AI tool below for the exact config to paste in. You do not need to run the server yourself — your AI tool will start it for you using stdio.

<details> <summary>Prefer to build from source?</summary>

git clone https://github.com/your-org/mcp-server-return-to-dark-tower.git
cd mcp-server-return-to-dark-tower
npm install
npm run build

Then in all config snippets below, replace:

"command": "npx",
"args": ["-y", "mcp-server-return-to-dark-tower", "--stdio-only"]

with:

"command": "node",
"args": ["/absolute/path/to/dist/index.js", "--stdio-only"]

</details>


🖥️ Setup with Your AI Tool

Each section is self-contained — jump straight to the tool you use.

All desktop AI tools use stdio transport. The config tells the AI app how to launch this server; the app handles the rest. You just edit a JSON (or YAML) config file, save it, and restart your AI app.

If the config file doesn't exist yet, create it as a new empty file at the path shown. All configs shown below are complete and valid — you can paste them as-is if you're starting fresh.

If the file already exists, add the "return-to-dark-tower" block inside the existing "mcpServers" (or equivalent) object. Don't replace the whole file.


Claude Desktop

Claude Desktop reads its config file at startup. After saving changes, you must fully quit and reopen the app (⌘Q on Mac, not just closing the window).

Config file location:

OS Path
macOS ~/Library/Application Support/Claude/claude_desktop_config.json
Windows %APPDATA%\Claude\claude_desktop_config.json

Tip (macOS): Open the file quickly in Terminal: open -e ~/Library/Application\ Support/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "return-to-dark-tower": {
      "command": "npx",
      "args": ["-y", "mcp-server-return-to-dark-tower", "--stdio-only"]
    }
  }
}

After restarting Claude, you should see a hammer icon (🔨) in the chat input area indicating MCP tools are available.

Windows note: If npx doesn't work, try replacing "command": "npx" with "command": "node" and adding the full path to node_modules/.bin/mcp-server-dark-tower.js as the first arg, or install globally first.


🎯 Cursor

Cursor can load MCP config from a project-specific file or a global file.

Config file locations:

Scope Path
This project only .cursor/mcp.json (in your project root)
All projects ~/.cursor/mcp.json (in your home directory)
{
  "mcpServers": {
    "return-to-dark-tower": {
      "command": "npx",
      "args": ["-y", "mcp-server-return-to-dark-tower", "--stdio-only"]
    }
  }
}

Cursor picks up changes automatically — no restart required.

Important: MCP tools only appear when you're in Agent mode. In the Cursor chat panel, look for the mode selector and switch from "Normal" to "Agent" before asking the AI to use the tower.


🐙 VS Code (GitHub Copilot)

VS Code supports two config locations. The .vscode/mcp.json file can be committed to your repo so your whole team shares the same MCP setup.

Requires: VS Code 1.99 or newer. Update via Help → Check for Updates.

Option A — Workspace config (recommended, shareable with your team):

Create or edit .vscode/mcp.json in your project root:

{
  "servers": {
    "return-to-dark-tower": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "mcp-server-return-to-dark-tower", "--stdio-only"]
    }
  }
}

Option B — User settings (applies to all your projects):

Open settings.json (Cmd/Ctrl+Shift+P → "Open User Settings JSON") and add:

{
  "mcp": {
    "servers": {
      "return-to-dark-tower": {
        "type": "stdio",
        "command": "npx",
        "args": ["-y", "mcp-server-return-to-dark-tower", "--stdio-only"]
      }
    }
  }
}

Important: Switch the Copilot Chat panel to Agent mode (look for the mode dropdown in the chat panel). MCP tools are not available in Ask or Edit modes.


🌊 Windsurf

Windsurf uses a single global config file for all MCP servers.

Config file location:

OS Path
macOS / Linux ~/.codeium/windsurf/mcp_config.json
Windows %USERPROFILE%\.codeium\windsurf\mcp_config.json

You can also open it from within Windsurf: click the MCP icon in the top-right of the Cascade panel → Configure.

{
  "mcpServers": {
    "return-to-dark-tower": {
      "command": "npx",
      "args": ["-y", "mcp-server-return-to-dark-tower", "--stdio-only"]
    }
  }
}

Restart Windsurf after saving. The tower tools will appear in the Cascade agent panel.


⚡ Zed

Zed's MCP servers are configured in its global settings file.

Config file location:

OS Path
macOS / Linux ~/.config/zed/settings.json
Windows %APPDATA%\Zed\settings.json

Add the context_servers block (alongside any existing settings in the file):

{
  "context_servers": {
    "return-to-dark-tower": {
      "source": "custom",
      "command": "npx",
      "args": ["-y", "mcp-server-return-to-dark-tower", "--stdio-only"],
      "env": {}
    }
  }
}

Restart Zed after saving. Open the Agent Panel and look for a green dot next to the server name — that means it connected successfully.


🔎 Perplexity (macOS App)

Perplexity's native MCP support is available in the Mac App (download from the App Store). The web interface does not support MCP.

Requirements:

  • macOS only
  • Paid Perplexity plan (Pro or higher)
  • The free tier does not include MCP

Setup:

  1. Install the Perplexity Mac App from the App Store if you haven't already
  2. Open the app and go to Account SettingsConnectors
  3. Click "Install Helper" and install the PerplexityXPC helper app when prompted — this is a one-time step required by macOS's App Store sandbox rules
  4. Click "Add Connector"Simple"Add MCP Connector"
  5. Fill in:
    • Server Name: return-to-dark-tower (or anything you like)
    • Command: npx
    • Arguments: -y mcp-server-return-to-dark-tower --stdio-only
  6. Click Save and wait for the status indicator to show Running
  7. In a Perplexity chat, click Sources and enable the return-to-dark-tower connector

There is no config file to edit — everything is done through Perplexity's UI.

Note: Remote MCP support (for the web interface) is on Perplexity's roadmap but not yet available.


🐋 DeepSeek

DeepSeek's web chat (chat.deepseek.com) and API do not currently support MCP — there is no config file or UI to connect an MCP server to DeepSeek directly.

If you're using DeepSeek through an IDE that supports it (Cursor and VS Code both allow you to switch the underlying AI model to DeepSeek while keeping their MCP layer), MCP tools work fine. The IDE handles the MCP connection; it's independent of which AI model is powering the responses. Configure the tower using the Cursor or VS Code section above, then switch your model to DeepSeek in that IDE's settings.

If you use DeepSeek's own web or API interface, MCP is not available at this time. Check DeepSeek's documentation for updates.


Summary

Tool Config file Root key Agent mode required?
Claude Desktop claude_desktop_config.json mcpServers No (always on)
Cursor .cursor/mcp.json mcpServers Yes
VS Code (Copilot) .vscode/mcp.json servers Yes
Windsurf mcp_config.json mcpServers No (Cascade only)
Zed settings.json context_servers No
Perplexity App UI (no file) macOS + paid plan only
DeepSeek Not supported natively

🌐 Web-Based AI Chat Apps

Web-based AI tools can't launch processes on your machine the way desktop apps can. Instead, you start the HTTP server yourself and point the web app at it.

Start the HTTP Server

Open a terminal and run:

npx mcp-server-return-to-dark-tower --http-only --port 3001

Keep this terminal window open while you use your web AI tool. The server exposes:

  • http://localhost:3001/mcp — the main MCP endpoint
  • http://localhost:3001/health — returns {"status":"ok"} if it's running

To verify it's up, open http://localhost:3001/health in your browser. You should see {"status":"ok"}.

What is localhost? It means "this computer". The server is running on your machine and is only accessible from your own browser — it's not exposed to the internet by default.


Claude.ai (Web)

Remote MCP connections are available on Pro, Max, Team, and Enterprise plans (not the free tier).

  1. Go to claude.ai and open SettingsIntegrations
  2. Click Add Integration (or Add MCP Server)
  3. Enter the URL: http://localhost:3001/mcp
  4. Save. The tower tools will appear in your next conversation.

Heads up: Claude.ai connects from your browser to localhost, which works as long as your browser and the server are on the same machine. If you want to use it from another device (like a phone), you'll need to expose the server publicly — see the note below.

<details> <summary>Accessing from another device or sharing with others</summary>

Use a tunneling tool like ngrok to create a public URL for your local server:

# In a second terminal (while the server is running)
ngrok http 3001

ngrok will print a public URL like https://abc123.ngrok.io. Use that URL instead of http://localhost:3001 in your AI app's settings.

⚠️ Anyone with that URL can send commands to your tower. Use ngrok's auth features or keep the session short.

</details>


ChatGPT / OpenAI

ChatGPT added MCP support in late 2025, available through Developer Mode (requires ChatGPT Plus or higher).

  1. In ChatGPT, open SettingsDeveloper Mode (enable it if you haven't)
  2. Go to ConnectorsAdd Connector
  3. Select Streamable HTTP as the transport type
  4. Enter the URL: http://localhost:3001/mcp
  5. Save and start a new conversation. Tower tools will be available.

Note: OpenAI's MCP UI is evolving quickly. If "Connectors" has been renamed to "Apps" or similar, look for the MCP integration option there. Check OpenAI's help docs for the latest steps.


Custom Web Applications

Building your own web app to control the tower? Use the HTTP endpoint directly.

Start the server with both transports running simultaneously:

npx mcp-server-return-to-dark-tower
# stdio on stdin/stdout  +  HTTP on http://localhost:3001/mcp

Send a command with fetch:

// Generate a session ID once per user session
const sessionId = crypto.randomUUID();

const response = await fetch("http://localhost:3001/mcp", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "mcp-session-id": sessionId, // keeps this session's context consistent
  },
  body: JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "tools/call",
    params: {
      name: "tower_play_sound_by_name",
      arguments: { name: "Ashstrider" },
    },
  }),
});

const result = await response.json();
console.log(result);

Subscribe to streaming events (SSE):

const eventSource = new EventSource("http://localhost:3001/mcp");
eventSource.onmessage = (event) => {
  const data = JSON.parse(event.data);
  console.log("Tower event:", data);
};

CORS: If your web app runs on a different port (e.g., localhost:5173), the browser will block requests to localhost:3001 due to CORS. Configure your dev server to proxy /mcp requests, or add a CORS header to the MCP server. See the Architecture section for details on how HTTP and stdio share a single tower connection.


Available Tools

Connection (8 tools)

Tool Description
tower_connect Connect to the tower via BLE
tower_disconnect Disconnect from the tower
tower_calibrate Calibrate drum positions
tower_status Get connection status, calibration state, battery
tower_device_info Get manufacturer, model, firmware info
tower_is_responsive Active connectivity check
tower_cleanup Clean up resources
tower_set_monitoring Configure connection monitoring

Audio (3 tools)

Tool Description
tower_play_sound Play a sound by index (1-113)
tower_play_sound_by_name Play a sound by name (e.g., "Ashstrider")
tower_list_sounds List available sounds, optionally filtered by category

Lights (5 tools)

Tool Description
tower_set_lights Set doorway, ledge, and base lights
tower_set_led Set individual LED by layer and index
tower_light_sequence Run a named light sequence by ID
tower_light_sequence_by_name Run a light sequence by name (e.g., "victory")
tower_lights_off Turn all lights off

Drums (4 tools)

Tool Description
tower_rotate Rotate all drums to specific positions
tower_rotate_drum Rotate a single drum to a position
tower_random_rotate Randomly rotate drums
tower_get_drum_positions Get current drum positions

Seals (5 tools)

Tool Description
tower_break_seal Break a seal at a specific side and level
tower_is_seal_broken Check if a specific seal is broken
tower_get_broken_seals Get all broken seals
tower_reset_seals Reset all seals
tower_random_seal Get a random unbroken seal

State & Glyphs (7 tools)

Tool Description
tower_get_state Get current tower state
tower_send_state Send a tower state update
tower_get_glyphs Get all glyph positions
tower_get_glyph Get a specific glyph's position
tower_glyphs_facing Get glyphs facing a direction
tower_skull_count Get skull drop count
tower_reset_skull_count Reset skull drop count

Available Resources

Resources are read-only data the AI can pull in for context (e.g., checking battery level before a long sequence).

Tower State Resources

Resource URI Description
Tower Connection tower://connection Connection status, calibration, busy state
Device Info tower://device-info Manufacturer, model, firmware revisions
Battery tower://battery Millivolts, percentage, previous values
Drum Positions tower://drums All 3 drum positions
Glyph Positions tower://glyphs All 5 glyph positions and directions
Seal State tower://seals Broken/unbroken seals
Tower State tower://state Full tower state snapshot
Audio Library tower://audio-library All 113 sounds with categories
Light Effects tower://light-effects 6 effects + 19 named sequences

Game Knowledge Resources

Resource URI Description
Rules tower://game/rules Setup, turn phases, win/loss conditions
Adversaries tower://game/adversaries Abilities, spawn mechanics, escalation
Quests tower://game/quests Quest types, conditions, rewards
Items tower://game/items Equipment, potions, relics
Heroes tower://game/heroes Classes, stats, abilities
Buildings tower://game/buildings Citadel, sanctuary, village, bazaar
Lore tower://game/lore World lore, tower history, flavor
Glossary tower://game/glossary Key terms and concepts

Glyph Icon Resources

Resource URI Description
Cleanse tower://glyphs/cleanse Cleanse glyph SVG
Quest tower://glyphs/quest Quest glyph SVG
Battle tower://glyphs/battle Battle glyph SVG
Banner tower://glyphs/banner Banner glyph SVG
Reinforce tower://glyphs/reinforce Reinforce glyph SVG
All Glyphs tower://glyphs/all Combined SVG sheet

Available Prompts

Prompts are pre-built instruction templates you can invoke by name. They chain multiple tools together into a single dramatic sequence.

Prompt Args Description
dramatic_entrance adversary? Connect, calibrate, spawn sound, strobe lights, random drums
victory_sequence soundIndex? Victory sound + victory light sequence
defeat_sequence Defeat sound + defeat lights
monthly_transition month? Month end/start sounds and lights
dungeon_run type? Dungeon sound + idle lights
battle_start Battle sound + flicker lights
game_master_setup Full game session setup guide
sound_browser category? Browse audio library by category

Architecture

┌─────────────────┐     ┌──────────────────┐
│  Claude Desktop │────▶│  stdio transport  │──┐
└─────────────────┘     └──────────────────┘  │    ┌───────────────────┐     ┌─────────┐
                                               ├───▶│ TowerController   │────▶│  Tower  │
┌─────────────────┐     ┌──────────────────┐  │    │ (singleton)       │ BLE │  (HW)   │
│   React App     │────▶│  HTTP transport   │──┘    └───────────────────┘     └─────────┘
└─────────────────┘     └──────────────────┘

The TowerController singleton wraps UltimateDarkTower (v2.0.0) and is shared by both transports. The library's BluetoothAdapterFactory auto-detects the Node.js environment and uses @stoprocent/noble for BLE communication.


CLI Options

Flag Description
--stdio-only Run stdio transport only (for desktop AI tools)
--http-only Run HTTP transport only (for web apps)
--port <n> HTTP port (default: 3001)

Dependencies

Package Purpose
@modelcontextprotocol/sdk MCP server and transport
ultimatedarktower Tower BLE control library
@stoprocent/noble Node.js BLE backend
zod Schema validation
express HTTP transport server

Development

npm run dev      # Watch mode with tsx
npm run build    # Compile TypeScript
npm run lint     # Run ESLint + Prettier check
npm test         # Run tests

License

MIT — see LICENSE.


Acknowledgments

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured