# Directory Structure
```
├── .gitignore
├── .npmignore
├── CHANGELOG.md
├── create-ad.js
├── DEMO-VISTA.md
├── EPIC-UNICODE-ART.md
├── examples
│ ├── all-templates.js
│ ├── basic-usage.js
│ └── mcp-client.js
├── LICENSE
├── mcp.json
├── package-lock.json
├── package.json
├── README.md
├── src
│ ├── integrations
│ │ └── symbl.js
│ ├── server
│ │ └── index.js
│ ├── steganography
│ │ └── manager.js
│ └── templates
│ └── engine.js
├── test-puzzle.js
├── test-simple.js
└── VISUAL-DEMO.md
```
# Files
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
```
node_modules/
*.log
*.tmp
.DS_Store
.env
dist/
build/
coverage/
.vscode/
.idea/
*.swp
*.swo
*~
```
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
```
# Development files
test-puzzle.js
DEMO-VISTA.md
VISUAL-DEMO.md
*.test.js
*.spec.js
# Config files
.eslintrc*
.prettierrc*
jest.config.js
# Dev dependencies
node_modules/
coverage/
.nyc_output/
# Editor files
.vscode/
.idea/
*.swp
*.swo
*~
# OS files
.DS_Store
Thumbs.db
# Git
.git/
.gitignore
# Logs
*.log
npm-debug.log*
# Examples (they're in README)
# Keep examples/ for users to reference!
# CI/CD
.github/
.travis.yml
.circleci/
```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
```markdown
# 🌌 Unicode Puzzles MCP
[](https://www.npmjs.com/package/unicode-puzzles-mcp)
[](https://opensource.org/licenses/MIT)
[](https://modelcontextprotocol.io)
Quantum steganography puzzles powered by MCP. Create and manage encoded messages using zero-width characters and advanced Unicode techniques.
## 🎯 Features
- Advanced Unicode steganography (zero-width characters, combining marks)
- Quantum-themed puzzle templates
- symbl.cc integration for character discovery
- Full MCP memory system integration
- Multiple encoding patterns and difficulty levels
- Real-time puzzle generation and verification
## 🛠️ Installation
```bash
npm install unicode-puzzles-mcp
```
## 💫 Quick Start
```javascript
import { UnicodePuzzlesMCP } from 'unicode-puzzles-mcp';
// Initialize MCP server
const mcp = new UnicodePuzzlesMCP();
// Create a quantum puzzle
const puzzle = await mcp.createPuzzle({
template: 'quantum',
message: 'System integrity compromised',
secret: 'LIBRAXIS://repair-protocol-7A'
});
// Decode an encoded message
const decoded = await mcp.decodePuzzle(encodedText);
```
## 🌟 Puzzle Templates
- **Quantum** - Messages encoded using quantum superposition principles
- **Orbital** - Circular pattern encoding using orbital mechanics
- **Glitch** - Random noise patterns with hidden data
- **Void** - Space-based encoding using astronomical symbols
## 🔮 Examples
### Creating a Quantum Puzzle
```javascript
const quantumPuzzle = await mcp.createPuzzle({
template: 'quantum',
message: 'Reality distortion detected',
secret: 'Coordinates: α-359-ω',
difficulty: 'advanced'
});
// Result: 【𝚀𝚄𝙰𝙽𝚃𝚄𝙼】∎∎∎Reality⠀distortion⠀detected∎∎∎
// (with hidden ZWSP characters encoding the secret)
```
--------------------------------------------------------------------------------
/mcp.json:
--------------------------------------------------------------------------------
```json
{
"name": "unicode-puzzles-mcp",
"version": "0.1.0",
"description": "MCP server for quantum steganography puzzles using Unicode",
"author": "MCP Division",
"license": "MIT",
"main": "src/server/index.js",
"mcp": {
"serverType": "stdio",
"runtime": "node",
"command": "node",
"args": ["src/server/index.js"]
},
"capabilities": {
"tools": [
"create_puzzle",
"decode_puzzle",
"list_templates",
"encode_message",
"decode_message",
"search_characters",
"get_zero_width_chars"
]
}
}
```
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
```markdown
# Changelog
All notable changes to unicode-puzzles-mcp will be documented in this file.
## [0.1.0] - 2025-07-21
### 🎉 Initial Release
#### Features
- 🌟 Four unique puzzle templates: Quantum, Orbital, Glitch, and Void
- 🔐 Binary, trinary, and random encoding methods
- 🎚️ Three difficulty levels (easy, medium, hard)
- 🔍 Integration with symbl.cc for Unicode character discovery
- 🛠️ Full MCP (Model Context Protocol) server implementation
- 📚 Comprehensive examples and documentation
#### Templates
- **Quantum**: Superposition-based encoding with quantum symbols
- **Orbital**: Circular patterns with orbital mechanics
- **Glitch**: Visual noise patterns for obfuscation
- **Void**: Space-themed constellation encoding
#### Zero-Width Characters Support
- ZWSP (U+200B) - Zero Width Space
- ZWNJ (U+200C) - Zero Width Non-Joiner
- ZWJ (U+200D) - Zero Width Joiner
- And 9 more invisible Unicode characters!
---
Made with 🧠 by LibraxisAI MCP Division
```
--------------------------------------------------------------------------------
/test-simple.js:
--------------------------------------------------------------------------------
```javascript
#!/usr/bin/env node
/**
* Simple test to verify the package works
*/
import { StegoPuzzleManager } from './src/steganography/manager.js';
import { TemplateEngine } from './src/templates/engine.js';
import { SymblConnector } from './src/integrations/symbl.js';
console.log('🧪 Running package verification tests...\n');
try {
// Test 1: Can create instances
console.log('✓ StegoPuzzleManager instantiated');
const manager = new StegoPuzzleManager();
console.log('✓ TemplateEngine instantiated');
const templates = new TemplateEngine();
console.log('✓ SymblConnector instantiated');
const symbl = new SymblConnector();
// Test 2: Basic encoding works
const encoded = await manager.encodeSecret('test', 'secret', {
pattern: 'binary',
difficulty: 'easy'
});
console.log('✓ Binary encoding works');
// Test 3: Templates are available
const templateList = templates.listTemplates();
console.log(`✓ Found ${templateList.length} templates`);
// Test 4: Zero-width characters defined
const zwCount = Object.keys(manager.zeroWidthChars).length;
console.log(`✓ ${zwCount} zero-width characters available`);
console.log('\n✅ All tests passed! Package is ready for publishing.');
process.exit(0);
} catch (error) {
console.error('\n❌ Test failed:', error.message);
process.exit(1);
}
```
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
```json
{
"name": "unicode-puzzles-mcp",
"version": "0.1.0",
"description": "MCP server for quantum steganography puzzles using Unicode - hide secrets in plain sight using zero-width characters",
"main": "src/server/index.js",
"type": "module",
"bin": {
"unicode-puzzles-mcp": "./src/server/index.js"
},
"scripts": {
"start": "node src/server/index.js",
"dev": "nodemon src/server/index.js",
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
"test:local": "node test-puzzle.js",
"lint": "eslint src/",
"prepublishOnly": "node test-simple.js"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^0.6.0",
"jsdom": "^23.0.0",
"node-fetch": "^3.3.2"
},
"devDependencies": {
"jest": "^27.0.6",
"nodemon": "^2.0.12",
"eslint": "^7.32.0",
"prettier": "^2.3.2"
},
"keywords": [
"mcp",
"model-context-protocol",
"unicode",
"steganography",
"puzzle",
"quantum",
"zero-width",
"hidden-messages",
"encoding",
"claude-desktop",
"libraxis"
],
"author": "Maciej Gad <[email protected]>",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/maciejgad/unicode-puzzles-mcp.git"
},
"bugs": {
"url": "https://github.com/maciejgad/unicode-puzzles-mcp/issues"
},
"homepage": "https://github.com/maciejgad/unicode-puzzles-mcp#readme",
"engines": {
"node": ">=18.0.0"
},
"files": [
"src/",
"LICENSE",
"README.md",
"mcp.json"
]
}
```
--------------------------------------------------------------------------------
/examples/basic-usage.js:
--------------------------------------------------------------------------------
```javascript
#!/usr/bin/env node
/**
* Basic usage example for unicode-puzzles-mcp
* This example shows how to use the steganography functions directly
*/
import { StegoPuzzleManager } from '../src/steganography/manager.js';
import { TemplateEngine } from '../src/templates/engine.js';
async function main() {
const manager = new StegoPuzzleManager();
const templates = new TemplateEngine();
console.log('🌌 Unicode Puzzles - Basic Usage Example\n');
// Example 1: Simple message encoding
console.log('1. Simple Binary Encoding:');
const encoded = await manager.encodeSecret(
'Hello World',
'secret123',
{ pattern: 'binary', difficulty: 'easy' }
);
console.log('Visible text:', encoded);
console.log('Looks normal but contains hidden data!\n');
// Example 2: Create a Quantum Puzzle
console.log('2. Quantum Puzzle:');
const quantumTemplate = templates.getTemplate('quantum', 'medium');
const puzzle = await manager.createPuzzle({
template: quantumTemplate,
message: 'Meeting at midnight',
secret: 'Location: 40.7128,-74.0060',
difficulty: 'medium'
});
console.log('Puzzle:', puzzle);
// Example 3: Decode the puzzle
console.log('\n3. Decoding the Puzzle:');
const decoded = await manager.decodePuzzle(puzzle);
console.log('Visible message:', decoded.visibleText);
console.log('Hidden secret:', decoded.hiddenMessage);
// Example 4: Show zero-width character usage
console.log('\n4. Zero-Width Character Analysis:');
const zwChars = encoded.match(/[\u200B-\u200F\u2060-\u206F]/g);
console.log('Total zero-width characters:', zwChars ? zwChars.length : 0);
console.log('These are completely invisible to users!');
}
main().catch(console.error);
```
--------------------------------------------------------------------------------
/test-puzzle.js:
--------------------------------------------------------------------------------
```javascript
import { StegoPuzzleManager } from './src/steganography/manager.js';
import { TemplateEngine } from './src/templates/engine.js';
// Test the puzzle creation locally
async function testPuzzle() {
const manager = new StegoPuzzleManager();
const templates = new TemplateEngine();
console.log('🧪 Testing Unicode Puzzles...\n');
// Test 1: Create a quantum puzzle
console.log('1️⃣ Creating Quantum Puzzle...');
const quantumTemplate = templates.getTemplate('quantum', 'medium');
const quantumPuzzle = await manager.createPuzzle({
template: quantumTemplate,
message: 'Reality distortion detected',
secret: 'LIBRAXIS://repair-protocol-7A',
difficulty: 'medium'
});
console.log('Result:', quantumPuzzle);
console.log('');
// Test 2: Decode the puzzle
console.log('2️⃣ Decoding Quantum Puzzle...');
const decoded = await manager.decodePuzzle(quantumPuzzle);
console.log('Decoded:', decoded);
console.log('');
// Test 3: Simple binary encoding
console.log('3️⃣ Testing Binary Encoding...');
const binaryEncoded = await manager.encodeSecret(
'Hello World',
'Secret123',
{ pattern: 'binary', difficulty: 'easy' }
);
console.log('Binary Encoded:', binaryEncoded);
console.log('Length:', binaryEncoded.length);
// Count zero-width characters
const zwChars = binaryEncoded.match(/[\u200B-\u200F\u2060-\u206F]/g);
console.log('Zero-width characters:', zwChars ? zwChars.length : 0);
console.log('');
// Test 4: List all templates
console.log('4️⃣ Available Templates:');
const templateList = templates.listTemplates();
templateList.forEach(t => {
console.log(`- ${t.name}: ${t.description}`);
console.log(` Difficulties: ${t.difficulties.join(', ')}`);
});
}
// Run tests
testPuzzle().catch(console.error);
```
--------------------------------------------------------------------------------
/examples/all-templates.js:
--------------------------------------------------------------------------------
```javascript
#!/usr/bin/env node
/**
* Showcase all available puzzle templates
*/
import { StegoPuzzleManager } from '../src/steganography/manager.js';
import { TemplateEngine } from '../src/templates/engine.js';
async function showcaseTemplates() {
const manager = new StegoPuzzleManager();
const templates = new TemplateEngine();
console.log('🎨 Unicode Puzzles - Template Showcase\n');
console.log('Each template creates unique visual patterns while hiding your secrets!\n');
const secretMessage = 'LIBRAXIS-2025';
const visibleMessage = 'The future is distributed';
// Get all template names
const templateList = templates.listTemplates();
for (const templateInfo of templateList) {
console.log(`\n${'='.repeat(60)}`);
console.log(`📦 Template: ${templateInfo.name.toUpperCase()}`);
console.log(`📝 ${templateInfo.description}`);
console.log(`🎚️ Difficulties: ${templateInfo.difficulties.join(', ')}`);
console.log(`${'='.repeat(60)}\n`);
// Show each difficulty level
for (const difficulty of templateInfo.difficulties) {
const template = templates.getTemplate(templateInfo.name, difficulty);
const puzzle = await manager.createPuzzle({
template,
message: visibleMessage,
secret: secretMessage,
difficulty
});
console.log(`[${difficulty.toUpperCase()}]:`);
console.log(puzzle);
// Analyze the encoding
const hiddenChars = puzzle.match(/[\u200B-\u200F\u2060-\u206F]/g);
console.log(`Hidden characters: ${hiddenChars ? hiddenChars.length : 0}`);
console.log('');
}
}
console.log('\n💡 TIP: Copy any puzzle above and it will maintain the hidden message!');
console.log('The zero-width characters are preserved in clipboard operations.');
}
showcaseTemplates().catch(console.error);
```
--------------------------------------------------------------------------------
/examples/mcp-client.js:
--------------------------------------------------------------------------------
```javascript
#!/usr/bin/env node
/**
* Example of using unicode-puzzles-mcp as an MCP client
* This shows how Claude Desktop or other MCP clients would interact
*/
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
import { spawn } from 'child_process';
async function main() {
console.log('🔌 Connecting to Unicode Puzzles MCP Server...\n');
// Spawn the MCP server
const serverProcess = spawn('node', ['../src/server/index.js'], {
stdio: ['pipe', 'pipe', 'pipe']
});
// Create transport and client
const transport = new StdioClientTransport({
stdin: serverProcess.stdout,
stdout: serverProcess.stdin,
stderr: serverProcess.stderr
});
const client = new Client({
name: 'unicode-puzzles-client',
version: '1.0.0'
}, {
capabilities: {}
});
// Connect to server
await client.connect(transport);
console.log('✅ Connected to MCP server!\n');
// List available tools
console.log('📋 Available Tools:');
const tools = await client.listTools();
tools.tools.forEach(tool => {
console.log(`- ${tool.name}: ${tool.description}`);
});
// Example 1: Create a puzzle
console.log('\n🎯 Creating a Quantum Puzzle...');
const puzzleResult = await client.callTool('create_puzzle', {
template: 'quantum',
message: 'System breach detected',
secret: 'Access code: DELTA-7-ALPHA',
difficulty: 'hard'
});
const puzzleData = JSON.parse(puzzleResult.content[0].text);
console.log('Created:', puzzleData.puzzle);
// Example 2: List templates
console.log('\n📚 Available Templates:');
const templatesResult = await client.callTool('list_templates', {});
const templates = JSON.parse(templatesResult.content[0].text);
console.log(templates);
// Example 3: Search for zero-width characters
console.log('\n🔍 Zero-Width Characters:');
const zwResult = await client.callTool('get_zero_width_chars', {});
const zwChars = JSON.parse(zwResult.content[0].text);
console.log('Found', zwChars.chars.length, 'zero-width characters');
// Cleanup
await client.close();
serverProcess.kill();
console.log('\n👋 Disconnected from server');
}
main().catch(console.error);
```
--------------------------------------------------------------------------------
/src/integrations/symbl.js:
--------------------------------------------------------------------------------
```javascript
import fetch from 'node-fetch';
import jsdom from 'jsdom';
const { JSDOM } = jsdom;
export class SymblConnector {
constructor() {
this.baseUrl = 'https://symbl.cc/en';
this.cache = new Map();
this.rateLimit = {
requests: 0,
lastReset: Date.now(),
limit: 100 // requests per minute
};
// Initialize character categories
this.categories = {
zeroWidth: [
'200B', '200C', '200D', '200E', '200F',
'2060', '206A', '206B', '206C', '206D',
'206E', '206F'
],
quantum: [
'0278', '0299', '1D487', '1D688', '1D689',
'1D68A', '1D68B', '1D68C', '1D68D', '1D68E'
],
special: [
'2022', '2023', '25A0', '25A1', '25CF',
'25CB', '25D0', '25D1', '25D2', '25D3'
]
};
}
async searchCharacters(query, category = null) {
await this.checkRateLimit();
// Check cache first
const cacheKey = `search:${query}:${category}`;
if(this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
try {
// Fetch search results from symbl.cc
const response = await fetch(`${this.baseUrl}/search/?q=${encodeURIComponent(query)}`);
const html = await response.text();
// Parse results using jsdom
const dom = new JSDOM(html);
const document = dom.window.document;
// Extract character data
const results = Array.from(document.querySelectorAll('.char-block')).map(block => {
const char = block.querySelector('.char').textContent;
const code = block.querySelector('.code').textContent;
const name = block.querySelector('.name').textContent;
return {
char,
code: code.replace('U+', ''),
name,
category: this.determineCategory(code)
};
});
// Filter by category if specified
const filtered = category ?
results.filter(r => r.category === category) :
results;
// Cache results
this.cache.set(cacheKey, filtered);
// Update rate limit counter
this.rateLimit.requests++;
return filtered;
} catch (error) {
throw new Error(`Failed to search symbl.cc: ${error.message}`);
}
}
async getZeroWidthCharacters() {
return this.getCharactersByCategory('zeroWidth');
}
async getQuantumCharacters() {
return this.getCharactersByCategory('quantum');
}
async getSpecialCharacters() {
return this.getCharactersByCategory('special');
}
async getCharactersByCategory(category) {
if (!this.categories[category]) {
throw new Error(`Invalid category: ${category}`);
}
const results = [];
for (const code of this.categories[category]) {
const char = await this.getCharacterByCode(code);
if (char) results.push(char);
}
return results;
}
async getCharacterByCode(code) {
await this.checkRateLimit();
// Check cache
const cacheKey = `char:${code}`;
if(this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
try {
const response = await fetch(`${this.baseUrl}/${code}/`);
const html = await response.text();
const dom = new JSDOM(html);
const document = dom.window.document;
const charBlock = document.querySelector('.char-block');
if (!charBlock) return null;
const result = {
char: charBlock.querySelector('.char').textContent,
code,
name: charBlock.querySelector('.name').textContent,
category: this.determineCategory(code)
};
// Cache result
this.cache.set(cacheKey, result);
// Update rate limit
this.rateLimit.requests++;
return result;
} catch (error) {
throw new Error(`Failed to fetch character ${code}: ${error.message}`);
}
}
determineCategory(code) {
code = code.replace('U+', '');
if(this.categories.zeroWidth.includes(code)) return 'zeroWidth';
if(this.categories.quantum.includes(code)) return 'quantum';
if(this.categories.special.includes(code)) return 'special';
return 'other';
}
async checkRateLimit() {
const now = Date.now();
const timeSinceReset = now - this.rateLimit.lastReset;
// Reset counter if a minute has passed
if(timeSinceReset >= 60000) {
this.rateLimit.requests = 0;
this.rateLimit.lastReset = now;
return;
}
// Check if we've hit the limit
if(this.rateLimit.requests >= this.rateLimit.limit) {
const waitTime = 60000 - timeSinceReset;
throw new Error(`Rate limit exceeded. Please wait ${Math.ceil(waitTime/1000)} seconds.`);
}
}
// Memory integration methods
async saveToMemory(mcpMemory) {
const timestamp = new Date().toISOString();
// Store cache statistics
await mcpMemory.create_entities([{
name: `symbl_cache_${timestamp}`,
entityType: 'Cache',
observations: [
`Total Cached Items: ${this.cache.size}`,
`Rate Limit Status: ${this.rateLimit.requests}/${this.rateLimit.limit}`,
`Last Reset: ${new Date(this.rateLimit.lastReset).toISOString()}`
]
}]);
// Store category statistics
for(const [category, codes] of Object.entries(this.categories)) {
await mcpMemory.create_entities([{
name: `symbl_category_${category}_${timestamp}`,
entityType: 'CharacterCategory',
observations: [
`Category: ${category}`,
`Total Characters: ${codes.length}`,
`Codes: ${codes.join(', ')}`
]
}]);
}
}
clearCache() {
this.cache.clear();
this.rateLimit.requests = 0;
this.rateLimit.lastReset = Date.now();
}
}
```
--------------------------------------------------------------------------------
/src/steganography/manager.js:
--------------------------------------------------------------------------------
```javascript
export class StegoPuzzleManager {
constructor() {
this.zeroWidthChars = {
ZWSP: '\u200B', // Zero width space
ZWNJ: '\u200C', // Zero width non-joiner
ZWJ: '\u200D', // Zero width joiner
LRM: '\u200E', // Left-to-right mark
RLM: '\u200F', // Right-to-left mark
WJ: '\u2060', // Word joiner
ISS: '\u206A', // Inhibit symmetric swapping
ASS: '\u206B', // Activate symmetric swapping
IAFS: '\u206C', // Inhibit arabic form shaping
AAFS: '\u206D', // Activate arabic form shaping
NADS: '\u206E', // National digit shapes
NODS: '\u206F' // Nominal digit shapes
};
this.patterns = {
quantum: {
prefix: '【𝚀𝚄𝙰𝙽𝚃𝚄𝙼】',
separator: '∎∎∎',
encoding: 'binary'
},
orbital: {
prefix: '◉',
separator: '◯',
encoding: 'trinary'
},
glitch: {
prefix: '[ERR0R]',
separator: '',
encoding: 'random'
}
};
}
async createPuzzle({ template, message, secret, difficulty = 'medium' }) {
// Get encoding pattern based on template and difficulty
const pattern = this.patterns[template.name];
// Encode secret message
const encodedText = await this.encodeSecret(message, secret, {
pattern: pattern.encoding,
difficulty
});
// Apply template formatting
return this.applyTemplate(encodedText, template);
}
async encodeSecret(message, secret, options) {
const { pattern, difficulty } = options;
// Convert secret to binary
const binarySecret = this.textToBinary(secret);
// Initialize encoded text
let encoded = '';
let charIndex = 0;
// Apply encoding based on pattern
switch(pattern) {
case 'binary':
encoded = this.binaryEncode(message, binarySecret, difficulty);
break;
case 'trinary':
encoded = this.trinaryEncode(message, binarySecret, difficulty);
break;
case 'random':
encoded = this.randomEncode(message, binarySecret, difficulty);
break;
default:
throw new Error('Invalid encoding pattern');
}
return encoded;
}
binaryEncode(message, binarySecret, difficulty) {
let encoded = '';
let secretIndex = 0;
for(let i = 0; i < message.length; i++) {
encoded += message[i];
if(secretIndex < binarySecret.length) {
// Insert zero-width character based on binary value
if(binarySecret[secretIndex] === '1') {
encoded += this.zeroWidthChars.ZWSP;
} else {
encoded += this.zeroWidthChars.ZWNJ;
}
secretIndex++;
}
// Add noise for higher difficulties
if(difficulty === 'hard') {
if(Math.random() > 0.7) {
encoded += this.getRandomZeroWidth();
}
}
}
return encoded;
}
trinaryEncode(message, binarySecret, difficulty) {
let encoded = '';
let secretIndex = 0;
// Convert binary to trinary for more complex encoding
const trinarySecret = this.binaryToTrinary(binarySecret);
for(let i = 0; i < message.length; i++) {
encoded += message[i];
if(secretIndex < trinarySecret.length) {
// Use three zero-width characters for trinary encoding
switch(trinarySecret[secretIndex]) {
case '0':
encoded += this.zeroWidthChars.ZWSP;
break;
case '1':
encoded += this.zeroWidthChars.ZWNJ;
break;
case '2':
encoded += this.zeroWidthChars.ZWJ;
break;
}
secretIndex++;
}
}
return encoded;
}
randomEncode(message, binarySecret, difficulty) {
let encoded = '';
let secretIndex = 0;
const chars = Object.values(this.zeroWidthChars);
for(let i = 0; i < message.length; i++) {
encoded += message[i];
// Random noise insertion
if(Math.random() > 0.5) {
encoded += chars[Math.floor(Math.random() * chars.length)];
}
// Secret encoding
if(secretIndex < binarySecret.length) {
if(binarySecret[secretIndex] === '1') {
encoded += this.zeroWidthChars.WJ;
}
secretIndex++;
}
}
return encoded;
}
textToBinary(text) {
return text.split('').map(char =>
char.charCodeAt(0).toString(2).padStart(8, '0')
).join('');
}
binaryToTrinary(binary) {
// Convert binary to decimal
const decimal = parseInt(binary, 2);
// Convert decimal to trinary
return decimal.toString(3);
}
getRandomZeroWidth() {
const chars = Object.values(this.zeroWidthChars);
return chars[Math.floor(Math.random() * chars.length)];
}
applyTemplate(encodedText, template) {
return `${template.prefix}${template.separator}${encodedText}${template.separator}`;
}
// Decoding methods
async decodePuzzle(encodedText) {
// Detect template
const template = this.detectTemplate(encodedText);
// Remove template formatting
const stripped = this.stripTemplate(encodedText, template);
// Extract and decode hidden message
return this.decodeSecret(stripped, template.encoding);
}
detectTemplate(encodedText) {
for(const [name, pattern] of Object.entries(this.patterns)) {
if(encodedText.startsWith(pattern.prefix)) {
return { name, ...pattern };
}
}
throw new Error('Unknown puzzle template');
}
stripTemplate(encodedText, template) {
return encodedText
.replace(template.prefix, '')
.split(template.separator)[1];
}
decodeSecret(text, encoding) {
let binary = '';
let visibleText = '';
for(let i = 0; i < text.length; i++) {
const char = text[i];
// Check if it's a zero-width character
if(Object.values(this.zeroWidthChars).includes(char)) {
switch(encoding) {
case 'binary':
binary += char === this.zeroWidthChars.ZWSP ? '1' : '0';
break;
case 'trinary':
if(char === this.zeroWidthChars.ZWSP) binary += '0';
else if(char === this.zeroWidthChars.ZWNJ) binary += '1';
else if(char === this.zeroWidthChars.ZWJ) binary += '2';
break;
case 'random':
if(char === this.zeroWidthChars.WJ) binary += '1';
break;
}
} else {
visibleText += char;
}
}
return {
visibleText,
hiddenMessage: this.binaryToText(binary)
};
}
binaryToText(binary) {
// Split binary into 8-bit chunks
const bytes = binary.match(/.{1,8}/g) || [];
// Convert each byte to character
return bytes.map(byte =>
String.fromCharCode(parseInt(byte, 2))
).join('');
}
}
```
--------------------------------------------------------------------------------
/src/templates/engine.js:
--------------------------------------------------------------------------------
```javascript
export class TemplateEngine {
constructor() {
this.templates = {
quantum: {
name: 'quantum',
prefix: '【𝚀𝚄𝙰𝙽𝚃𝚄𝙼】',
patterns: {
easy: {
opening: '∎',
closing: '∎',
separator: '⠀', // Unicode space
noiseChance: 0.1
},
medium: {
opening: '∎∎',
closing: '∎∎',
separator: '⠀',
noiseChance: 0.3
},
hard: {
opening: '∎∎∎',
closing: '∎∎∎',
separator: '⠀',
noiseChance: 0.5
}
},
quantumChars: ['α', 'β', 'γ', 'δ', 'ψ', 'Ψ', 'Φ', 'ℏ', '∞'],
description: 'Quantum superposition encoding with variable noise'
},
orbital: {
name: 'orbital',
prefix: '◉',
patterns: {
easy: {
opening: '◯',
closing: '◯',
separator: '·',
rotationSteps: 4
},
medium: {
opening: '◐',
closing: '◑',
separator: '∘',
rotationSteps: 8
},
hard: {
opening: '◒',
closing: '◓',
separator: '⋅',
rotationSteps: 12
}
},
orbitalChars: ['⌾', '☉', '⊕', '⊗', '⊙', '◎', '⚪', '⚫'],
description: 'Circular pattern encoding with orbital mechanics'
},
glitch: {
name: 'glitch',
prefix: '[ERR0R]',
patterns: {
easy: {
opening: '█',
closing: '█',
separator: ' ',
glitchIntensity: 0.2
},
medium: {
opening: '▓▒',
closing: '▒▓',
separator: '',
glitchIntensity: 0.4
},
hard: {
opening: '▓▒░',
closing: '░▒▓',
separator: '',
glitchIntensity: 0.6
}
},
glitchChars: ['░', '▒', '▓', '█', '☐', '☑', '☒', '✓', '✗'],
description: 'Glitch-based encoding with visual noise'
},
void: {
name: 'void',
prefix: '✧・゚:*',
patterns: {
easy: {
opening: '⋆',
closing: '⋆',
separator: ' ',
constellationSize: 3
},
medium: {
opening: '⋆⋆',
closing: '⋆⋆',
separator: '・',
constellationSize: 5
},
hard: {
opening: '⋆⋆⋆',
closing: '⋆⋆⋆',
separator: '⋆',
constellationSize: 7
}
},
spaceChars: ['✧', '✦', '★', '☆', '✯', '✩', '✫', '✬', '✭'],
description: 'Space-themed encoding with constellation patterns'
}
};
}
getTemplate(name, difficulty = 'medium') {
const template = this.templates[name];
if (!template) {
throw new Error(`Template '${name}' not found`);
}
const pattern = template.patterns[difficulty];
if (!pattern) {
throw new Error(`Difficulty '${difficulty}' not found for template '${name}'`);
}
return {
...template,
pattern,
difficulty
};
}
generatePattern(template, length, options = {}) {
const { name, pattern } = template;
let result = '';
switch (name) {
case 'quantum':
result = this.generateQuantumPattern(pattern, length, options);
break;
case 'orbital':
result = this.generateOrbitalPattern(pattern, length, options);
break;
case 'glitch':
result = this.generateGlitchPattern(pattern, length, options);
break;
case 'void':
result = this.generateVoidPattern(pattern, length, options);
break;
default:
throw new Error(`Unknown template type: ${name}`);
}
return result;
}
generateQuantumPattern(pattern, length, { seed = Math.random() } = {}) {
let result = pattern.opening;
const template = this.templates.quantum;
for (let i = 0; i < length; i++) {
// Add content character
result += pattern.separator;
// Add quantum noise based on difficulty
if (Math.random() < pattern.noiseChance) {
const quantumChar = template.quantumChars[
Math.floor(Math.random() * template.quantumChars.length)
];
result += quantumChar;
}
}
return result + pattern.closing;
}
generateOrbitalPattern(pattern, length, { rotation = 0 } = {}) {
let result = pattern.opening;
const template = this.templates.orbital;
const stepSize = (2 * Math.PI) / pattern.rotationSteps;
for (let i = 0; i < length; i++) {
// Calculate orbital position
const angle = (rotation + i) * stepSize;
const orbitalIndex = Math.floor((angle / (2 * Math.PI)) * template.orbitalChars.length);
const orbitalChar = template.orbitalChars[orbitalIndex % template.orbitalChars.length];
result += pattern.separator + orbitalChar;
}
return result + pattern.closing;
}
generateGlitchPattern(pattern, length, { intensity = 1.0 } = {}) {
let result = pattern.opening;
const template = this.templates.glitch;
const effectiveIntensity = pattern.glitchIntensity * intensity;
for (let i = 0; i < length; i++) {
result += pattern.separator;
// Add glitch artifacts based on intensity
if (Math.random() < effectiveIntensity) {
const glitchLength = Math.floor(Math.random() * 3) + 1;
for (let j = 0; j < glitchLength; j++) {
const glitchChar = template.glitchChars[
Math.floor(Math.random() * template.glitchChars.length)
];
result += glitchChar;
}
}
}
return result + pattern.closing;
}
generateVoidPattern(pattern, length, { constellation = [] } = {}) {
let result = pattern.opening;
const template = this.templates.void;
// Create constellation pattern
const constellationPoints = constellation.length > 0 ?
constellation :
this.generateConstellation(pattern.constellationSize);
for (let i = 0; i < length; i++) {
result += pattern.separator;
// Add space characters at constellation points
if (constellationPoints.includes(i)) {
const spaceChar = template.spaceChars[
Math.floor(Math.random() * template.spaceChars.length)
];
result += spaceChar;
}
}
return result + pattern.closing;
}
generateConstellation(size) {
const points = new Set();
while (points.size < size) {
points.add(Math.floor(Math.random() * size * 2));
}
return Array.from(points).sort((a, b) => a - b);
}
// MCP Memory Integration
async saveToMemory(mcpMemory) {
const timestamp = new Date().toISOString();
// Store template metadata
for (const [name, template] of Object.entries(this.templates)) {
await mcpMemory.create_entities([{
name: `template_${name}_${timestamp}`,
entityType: 'PuzzleTemplate',
observations: [
`Name: ${name}`,
`Description: ${template.description}`,
`Prefix: ${template.prefix}`,
`Available Difficulties: ${Object.keys(template.patterns).join(', ')}`
]
}]);
}
// Log template usage statistics if needed
}
listTemplates() {
return Object.entries(this.templates).map(([name, template]) => ({
name,
description: template.description,
difficulties: Object.keys(template.patterns)
}));
}
}
```
--------------------------------------------------------------------------------
/src/server/index.js:
--------------------------------------------------------------------------------
```javascript
#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
CallToolRequestSchema,
ListResourcesRequestSchema,
ListToolsRequestSchema,
ReadResourceRequestSchema,
ErrorCode,
McpError
} from '@modelcontextprotocol/sdk/types.js';
import { StegoPuzzleManager } from '../steganography/manager.js';
import { SymblConnector } from '../integrations/symbl.js';
import { TemplateEngine } from '../templates/engine.js';
class UnicodePuzzlesMCP {
constructor() {
this.server = new Server(
{
name: 'unicode-puzzles-mcp',
version: '0.1.0'
},
{
capabilities: {
tools: {},
resources: {}
}
}
);
this.puzzleManager = new StegoPuzzleManager();
this.symbl = new SymblConnector();
this.templates = new TemplateEngine();
this.setupTools();
}
async setupTools() {
// Register tools handler
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
switch (request.params.name) {
case 'create_puzzle':
return await this.createPuzzle(request.params.arguments);
case 'decode_puzzle':
return await this.decodePuzzle(request.params.arguments);
case 'list_templates':
return await this.getTemplates();
case 'encode_message':
return await this.encodeMessage(request.params.arguments);
case 'decode_message':
return await this.decodeMessage(request.params.arguments);
case 'search_characters':
return await this.searchCharacters(request.params.arguments);
case 'get_zero_width_chars':
return await this.getZeroWidthChars();
default:
throw new McpError(
ErrorCode.MethodNotFound,
`Unknown tool: ${request.params.name}`
);
}
});
// Register list tools handler
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: 'create_puzzle',
description: 'Create a Unicode steganography puzzle',
inputSchema: {
type: 'object',
properties: {
template: { type: 'string', enum: ['quantum', 'orbital', 'glitch', 'void'] },
message: { type: 'string' },
secret: { type: 'string' },
difficulty: { type: 'string', enum: ['easy', 'medium', 'hard'], default: 'medium' }
},
required: ['template', 'message', 'secret']
}
},
{
name: 'decode_puzzle',
description: 'Decode a Unicode steganography puzzle',
inputSchema: {
type: 'object',
properties: {
encodedText: { type: 'string' }
},
required: ['encodedText']
}
},
{
name: 'list_templates',
description: 'List available puzzle templates'
},
{
name: 'encode_message',
description: 'Encode a message using steganography',
inputSchema: {
type: 'object',
properties: {
message: { type: 'string' },
secret: { type: 'string' },
method: { type: 'string', enum: ['binary', 'trinary', 'random'], default: 'binary' }
},
required: ['message', 'secret']
}
},
{
name: 'decode_message',
description: 'Decode a steganographic message',
inputSchema: {
type: 'object',
properties: {
encodedText: { type: 'string' },
method: { type: 'string', enum: ['binary', 'trinary', 'random'], default: 'binary' }
},
required: ['encodedText']
}
},
{
name: 'search_characters',
description: 'Search for Unicode characters',
inputSchema: {
type: 'object',
properties: {
query: { type: 'string' },
category: { type: 'string', enum: ['zeroWidth', 'quantum', 'special'] }
},
required: ['query']
}
},
{
name: 'get_zero_width_chars',
description: 'Get list of zero-width Unicode characters'
}
]
};
});
}
// Tool implementations
async createPuzzle(args) {
try {
const { template, message, secret, difficulty = 'medium' } = args;
// Get template configuration
const templateConfig = await this.templates.getTemplate(template, difficulty);
// Create puzzle using selected template
const puzzle = await this.puzzleManager.createPuzzle({
template: templateConfig,
message,
secret,
difficulty
});
return {
content: [
{
type: 'text',
text: JSON.stringify({
status: 'success',
puzzle,
metadata: {
template,
difficulty,
encodingType: templateConfig.encoding
}
}, null, 2)
}
]
};
} catch (error) {
throw new McpError(
ErrorCode.InternalError,
`Failed to create puzzle: ${error.message}`
);
}
}
async decodePuzzle(args) {
try {
const { encodedText } = args;
const decoded = await this.puzzleManager.decodePuzzle(encodedText);
return {
content: [
{
type: 'text',
text: JSON.stringify({ decoded }, null, 2)
}
]
};
} catch (error) {
throw new McpError(
ErrorCode.InternalError,
`Failed to decode puzzle: ${error.message}`
);
}
}
async getTemplates() {
try {
const templates = this.templates.listTemplates();
return {
content: [
{
type: 'text',
text: JSON.stringify({ templates }, null, 2)
}
]
};
} catch (error) {
throw new McpError(
ErrorCode.InternalError,
`Failed to list templates: ${error.message}`
);
}
}
async encodeMessage(args) {
try {
const { message, secret, method = 'binary' } = args;
const encoded = await this.puzzleManager.encodeSecret(message, secret, {
pattern: method,
difficulty: 'medium'
});
return {
content: [
{
type: 'text',
text: JSON.stringify({ encoded }, null, 2)
}
]
};
} catch (error) {
throw new McpError(
ErrorCode.InternalError,
`Failed to encode message: ${error.message}`
);
}
}
async decodeMessage(args) {
try {
const { encodedText, method = 'binary' } = args;
const decoded = this.puzzleManager.decodeSecret(encodedText, method);
return {
content: [
{
type: 'text',
text: JSON.stringify({ decoded }, null, 2)
}
]
};
} catch (error) {
throw new McpError(
ErrorCode.InternalError,
`Failed to decode message: ${error.message}`
);
}
}
async searchCharacters(args) {
try {
const { query, category } = args;
const results = await this.symbl.searchCharacters(query, category);
return {
content: [
{
type: 'text',
text: JSON.stringify({ results }, null, 2)
}
]
};
} catch (error) {
throw new McpError(
ErrorCode.InternalError,
`Failed to search characters: ${error.message}`
);
}
}
async getZeroWidthChars() {
try {
const chars = await this.symbl.getZeroWidthCharacters();
return {
content: [
{
type: 'text',
text: JSON.stringify({ chars }, null, 2)
}
]
};
} catch (error) {
throw new McpError(
ErrorCode.InternalError,
`Failed to get zero-width characters: ${error.message}`
);
}
}
async start() {
const transport = new StdioServerTransport();
await this.server.connect(transport);
console.error('Unicode Puzzles MCP server started');
}
}
// Initialize and start server
const server = new UnicodePuzzlesMCP();
server.start().catch(console.error);
```