word-search

MCP serverSearch

Lets your agent create word-search puzzles in six languages with proper accented letters.

Then ask your AI: use word-search to generate word search

Details

Available today. Use it as a step in a pipeline you build, or from your connected AI.

Add it as a step in a pipeline you build on Ahel, or connect Ahel to Claude, ChatGPT, Cursor, Claude Code or Codex and ask your AI to use it.

About this server

Create word-search puzzles in 6 languages (es, en, pt, fr, de, it) with native accented letters.

Install word-search

The server’s own address, for the clients that take one directly. Or connect Ahel once and every client you use reads it from one address, with the account kept on Ahel rather than in each client’s config.

  • Claude Code

    claude mcp add --transport http --scope user word-search 'https://mcp.lettras.org/mcp'

    Run it once in your project, then open /mcp to approve any sign-in the server asks for.

  • Claude Desktop

    https://mcp.lettras.org/mcp

    Add a custom connector in Settings, paste this address, and approve the sign-in.

  • Cursor

    cursor://anysphere.cursor-deeplink/mcp/install?name=word-search&config=eyJ1cmwiOiJodHRwczovL21jcC5sZXR0cmFzLm9yZy9tY3AifQ==

    Open the link and Cursor adds the server at that address.

  • ChatGPT

    https://mcp.lettras.org/mcp

    In Settings, enable Developer mode, create an MCP app, and paste this address. Your plan and workspace must allow custom apps.

  • Codex

    codex mcp add word-search --url 'https://mcp.lettras.org/mcp'

    Run it once, then sign in with codex mcp login word-search if the server asks for an account.

From the project's README

As published by artificialss/lettras-sdk in README.md.

Lettras SDK

Word searches, crosswords, sudoku and Unicode text styles in six languages, with every accent intact.

Developer tools for Lettras, the free word-puzzle platform. Generate word searches from any word list in Spanish, English, Portuguese, French, German and Italian, with native letters (Ñ, Ç, Ã, Ä, ẞ, È…) kept as one cell each, from your own code, a terminal, or an AI assistant. Besides word searches there are crosswords (crucigramas), sudoku and Unicode text styles.

ToolWhat it isInstall / connectSource
lettras on npmJavaScript/TypeScript library and CLI. Runs locally, no network or API keynpm install lettras (npm)npm/
lettras for KotlinKotlin library for the JVM and Android. Same engine, runs locallyorg.lettras.artificialss:lettras (Maven Central)kotlin/
lettras for JavaThe Kotlin library works from plain Java (JVM 17+)org.lettras.artificialss:lettraskotlin/
lettras for GoGo module, pure Go (no cgo), every OS and architecturego get github.com/Artificialss/lettras-sdk/gogo/
lettras for SwiftSwift package for Apple platforms and Linuxhttps://github.com/Artificialss/lettras-sdk (SwiftPM)swift/
Lettras for .NETC# library for .NET 8+ on Windows, macOS and Linuxdotnet add package Lettrasdotnet/
lettras for RustRust crate, engine embedded and run in-processcargo add lettrasrust/
lettras for Dart and FlutterDart package, engine embedded and run in-processdart pub add lettras (pub.dev)dart/
Lettras for VS CodeExtension: write text in 22 Unicode styles, insert word searches and sudokusVS Code Marketplace, artificialss.lettrasvscode/
Lettras for JetBrainsPlugin for IntelliJ IDEA, PyCharm, WebStorm, Android Studio and moreJetBrains Marketplace, "Lettras" (id ai.artificialss.lettras)jetbrains/, upload guide
lettras for HomebrewThe command-line tool as a formula, no Node setupbrew install artificialss/lettras/lettrashomebrew/
Lettras MCP serverLets Claude and other MCP clients create puzzles. Written in Rust, runs on Vercelhttps://mcp.lettras.org/mcp (MCP Registry)mcp/

Published. Live today: the npm package, the Kotlin library on Maven Central (which also serves Java), and the hosted MCP server (also listed in the official MCP Registry). The Rust, Go, Swift, .NET and Dart libraries, the VS Code extension, the JetBrains plugin and the Homebrew formula are built and tested here and are being published to their own stores (crates.io, pkg.go.dev, Swift Package Index, NuGet, pub.dev, the VS Code and JetBrains marketplaces, a Homebrew tap). A documentation site is planned.

Every library on one page: docs/LIBRARIES.md.

Table of contents

  • npm package
  • Kotlin library
  • MCP server
  • Text styles
  • Crossword (crucigrama)
  • Blocked words
  • Sudoku
  • How puzzles are built
  • Architecture and licensing
  • Repository layout
  • Development
  • License
  • About

npm package

npm install lettras
import { generate, render } from 'lettras';

const puzzle = generate({
  words: ['gato', 'perro', 'piña', 'mono', 'cebra'],
  rows: 9,
  cols: 12,
  position: 'mixed', // horizontal | vertical | mixed (all 8 directions)
  seed: 8,           // same input and seed, same grid
});

console.log(render(puzzle));
9×12  seed 8  engine 0.5.0

- - - - - - - - - - - -
- - - - - - - - - - - -
- - - - C - - - - - - -
- - - - - E - O N O M -
- - A - - - B - R - - -
O - - Ñ - - - R - - - -
T - - - I - E - A - - -
A - - - - P - - - - - -
G - - - - - - - - - - -

Words: gato, perro, piña, mono, cebra

piña takes four cells (the Ñ is one), mono is written right to left, and perro and cebra run on diagonals. The grid is plain data: puzzle.grid is an array of rows, each an array of one-letter strings.

CLI

npx lettras --words gato,perro,piña --rows 9 --cols 12 --position mixed --seed 8
npx lettras --words sol,luna,mar --rows 8 --json          # raw JSON
npx lettras --words sol,luna,mar --rows 8 --solution      # only the hidden words

Options

OptionValues
wordsWords to hide, in normal spelling. Accents are kept.
rows, colsGrid size. They can differ for a rectangular grid.
positionhorizontal (left→right), vertical (top→bottom), mixed (all 8 directions, diagonals included).
difficulty1–4. Sets the directions when position is not given.
clustering0 words apart · 1 words crossing · default 0.5.
seedRepeatable puzzles.
langes (default) en pt fr de it.
classicModeStrip accents in the grid (ñ becomes N).
fillCharacter for empty cells. Default -.

Fill the empty cells with random letters. generate leaves empty cells as -. Pass the result to fill, with the language and accents on or off:

import { generate, fill } from 'lettras';

const puzzle = generate({ words: ['gato', 'perro', 'piña'], rows: 9, cols: 12, position: 'mixed', seed: 8 });
const done = fill(puzzle, { lang: 'es', accents: true });   // or: fill(puzzle.grid, { lang: 'es', accents: false })
done.grid;   // the same matrix, every "-" replaced by a random letter
fill optionMeaning
langes (default) en pt fr de it. Letters follow how common they are in that language.
accentstrue (default): include the language's accented/native letters (Ñ, Ç, Ã, Ä, ẞ…). false: plain A-Z only.
seedRepeatable filler. Without one, every call gives different letters.
wordsThe hidden words. Added automatically when you pass the puzzle; the filler never creates an extra copy of one.

On the CLI: lettras --words gato,piña --rows 9 --random --accents off.

Example. The same puzzle before and after fill (Spanish, seed 5):

const puzzle = generate({ words: ['gato', 'perro', 'piña', 'mono', 'cebra'], rows: 8, cols: 10, position: 'mixed', seed: 8 });
const done = fill(puzzle, { lang: 'es', accents: true, seed: 5 });

puzzle.grid has - in every empty cell; done.grid replaces them (58 cells here):

C E B R A - O - - -
- - - - - - - T O -
- - - - M - - R A -
- - - O - - R - - G
- - N - - E - - - -
- O - - P - - - - -
- - - - - - - - - -
- - - - - - A Ñ I P
C E B R A R O G G J
D R A E E R C T O D
B Ó E E M Í M R A Ñ
T S C O N R R A E G
T R N E A E R O E M
I O O E P S N P A O
O C O O A P P A U A
I R E A A S A Ñ I P

With accents: false the filler uses plain A-Z only (the one Ñ left is the hidden word piña, which keeps its spelling):

C E B R A R O G G I
D Q A E E P C T O D
B Y E E M X M R A N
S R C O N R R A E G
S R N E A E R O E M
I O O E P S N O A O
O B O O A P O A T A
H R E A A S A Ñ I P

Same grid, language, accents and seed always give the same filler on every platform. Without a seed the wrappers pick a random one, so every call gives different letters.

Result: grid, placements (word, start r/c, step dr/dc, length), words (placed), unplaced (words that did not fit, never dropped silently), rejected (with reasons), seed, engineVersion. TypeScript types are included. Full notes: npm/README.md.

Kotlin library

For JVM and Android apps (and the mobile game). Same engine, same results, no network.

val lettras = Lettras()   // create once, reuse
val puzzle = lettras.generate(
    PuzzleRequest(words = listOf("gato", "perro", "piña"), rows = 9, cols = 12, position = Position.MIXED, seed = 8),
)
puzzle.grid        // List<List<String>>, one letter per cell
puzzle.placements  // where each word is hidden
puzzle.render()    // text view

val done = lettras.fill(puzzle, lang = Language.ES, accents = true)   // empty cells become random letters
done.grid

The engine is the same WebAssembly binary the MCP server uses, run by Chicory (pure Java, no native libraries to build per CPU). On the JVM it is compiled to bytecode; on Android it uses the interpreter. The tests check it returns exactly the grids the npm package returns. Install notes, API, performance and Android details: kotlin/README.md.

MCP server

An MCP server that lets an AI assistant create puzzles for you. Ask for "a 12×12 sopa de letras about animals, mixed directions, with random letters" and it calls generate_word_search, then fill_word_search. It can also write text in Unicode styles with stylize_text.

  • Transport: streamable HTTP, POST /mcp (JSON-RPC). Protocol versions 2025-06-18, 2025-03-26, 2024-11-05.
  • Runs the engine locally: the compiled engine is embedded in the server and executed in-process. It makes no outside calls and needs no credentials to start.
  • Written in Rust on Vercel's Rust runtime (axum).

Connect a client (hosted endpoint: https://mcp.lettras.org/mcp):

# Claude Code
claude mcp add --transport http lettras https://mcp.lettras.org/mcp
// Claude Desktop, Cursor and other clients that take a remote server URL
{ "mcpServers": { "lettras": { "url": "https://mcp.lettras.org/mcp" } } }

Tools

ToolPurpose
generate_word_searchCreate a puzzle. Arguments match the options above (words, rows, cols, position, difficulty, clustering, seed, lang, classicMode). Returns a readable grid and the full structured result.
fill_word_searchComplete a puzzle: takes the grid from generate_word_search (empty cells -) and fills them with random letters in the chosen lang, with accents on or off. Pass the puzzle's words so the filler never creates an extra copy. Does not use up the puzzle limit; it has its own, larger one.
stylize_textText in Unicode styles (bold, italic, script, fraktur, circled, strikethrough... 22 in all) that keep accents. style is one id, several, or omitted for all; classic strips accents first. Reports in notNative and parts[].missing what a style cannot draw (ß, Æ, Œ, Ø, non-Latin scripts, accents that only exist as combining marks), so you can warn the user. No usage limit.
list_stylesThe style ids stylize_text accepts, with an English name and a category. No usage limit.
crosswordA crossword (crucigrama) from entries ({ word, clue }) inside rows x cols: returns a puzzle matrix (- blank, word numbers, 0, and a/d such as 3/4 where an across and a down word start in the same cell), a solution matrix and placements with the clues. No usage limit. See docs/CROSSWORD.md.
sudokuA sudoku with exactly one solution: size 4, 6, 9, 12 or 16, difficulty 1 to 4, seed. No usage limit.
solve_sudokuSolves a grid (0 = empty) and says whether the solution is unique. No usage limit. See docs/SUDOKU.md.
list_languagesThe supported languages and the native letters each adds to its grid.

Invalid arguments come back as a tool error written for the model to act on (for example rows: an integer from 6 to 30 is required).

Free tiers

WhatFree use
generate_word_search, small: up to 10×10 with at most 10 wordsUnlimited. Never counted.
generate_word_search, larger: a bigger grid (up to 30×30) or more than 10 words5 puzzles per client, in total, forever (there is no daily reset).
fill_word_search100 calls per client, separate from the puzzles.
stylize_text, list_styles, crossword, sudoku, solve_sudoku, list_languagesNo limit.

After a limit the tool answers with "Free limit reached… Visit https://lettras.org". Invalid requests never count.

Limits and privacy. A client is identified by a SHA-256 hash of its IP address, with the whole IPv6 /64 treated as one client so that rotating addresses does not dodge the limit. Because the limit never resets, the server keeps one row per client indefinitely: the hash, a count and a timestamp (no addresses, no words, no puzzles). The request log carries the same hash prefix, never the address. A hash of an IP address can still count as personal data in some jurisdictions, so mention it in your own privacy notice if you operate your own copy. If the database is unreachable the request is allowed (and a usage_store_error line is logged), so a storage outage never takes the service down. The hosted endpoint is public and unauthenticated; small puzzles, styles and languages are free to use, while bigger puzzles are a free trial of five, not a bulk service. To run your own copy with a daily limit instead, set LETTRAS_LIMIT_WINDOW_SECS=86400.

Deploy on Vercel

  1. Create a Vercel project from this repository and set Root Directory to mcp.
  2. Optional but recommended: a Postgres database so the 5-puzzle counter is shared across instances (without it the counter lives in each instance's memory and is not reliable). Create a Neon project, copy its pooled connection string into the project's environment variables as DATABASE_URL (mark it sensitive). The server creates its own mcp_usage table on first use; it stores a hash, a count and a timestamp per client.
  3. Optional settings, all in .env.example: LETTRAS_FREE_LIMIT, LETTRAS_FILL_LIMIT, LETTRAS_LIMIT_WINDOW_SECS (0 = lifetime total, the default), LETTRAS_UPGRADE_URL.
  4. Optional: add your own domain under the project's Settings → Domains (a CNAME pointing to cname.vercel-dns.com; do not change the domain's nameservers).
  5. Deploy. Every puzzle request writes one JSON line to the function logs (hashed client, count, allowed or blocked, grid size, language), which you can read in Vercel Logs or forward with a log drain.

The server is described for MCP registries in server.json.

No secret is stored in this repository. Real values belong in Vercel's project settings.

Text styles

Besides puzzles, the same engine writes text in Unicode styles that keep accents (22 styles). It is what powers Social Media Styles at lettras.org.

import { stylize, unstyle, listStyles } from 'lettras';

const out = stylize('Lettras ejemplo: piña, corazón', { style: ['bold', 'script'] });
out.results[0].text;      // 𝐋𝐞𝐭𝐭𝐫𝐚𝐬 𝐞𝐣𝐞𝐦𝐩𝐥𝐨: 𝐩𝐢𝐧̃𝐚, 𝐜𝐨𝐫𝐚𝐳𝐨́𝐧   (ñ = styled n + combining tilde)
out.results[0].notNative; // ['ñ', 'ó']: accents that exist in no style as one character
unstyle(out.results[0].text); // 'Lettras ejemplo: piña, corazón'
listStyles();             // [{ id: 'bold', label: 'Bold', category: 'bold-italic' }, ...]

style is one id, an array of ids, or omitted for all 22. classic: true strips accents first. parts cuts the output into pieces, and missing: true marks what a style cannot draw (ß, Æ, Œ, Ø, non-Latin scripts), so a UI can show an empty box like a phone without that glyph. Text is limited to 10,000 characters. The same functions exist in Kotlin (stylize, unstyle, listStyles) and as the MCP tools stylize_text and list_styles.

The name in every style

stylize('Lettras') (real output). The list is in display order, which is also the order of listStyles().

Style idNameLettras
boldBold𝐋𝐞𝐭𝐭𝐫𝐚𝐬
italicItalic𝐿𝑒𝑡𝑡𝑟𝑎𝑠
bold-italicBold italic𝑳𝒆𝒕𝒕𝒓𝒂𝒔
sansSans-serif𝖫𝖾𝗍𝗍𝗋𝖺𝗌
sans-boldSans-serif bold𝗟𝗲𝘁𝘁𝗿𝗮𝘀
sans-italicSans-serif italic𝘓𝘦𝘵𝘵𝘳𝘢𝘴
sans-bold-italicSans-serif bold italic𝙇𝙚𝙩𝙩𝙧𝙖𝙨
scriptScriptℒℯ𝓉𝓉𝓇𝒶𝓈
bold-scriptBold script𝓛𝓮𝓽𝓽𝓻𝓪𝓼
frakturFraktur𝔏𝔢𝔱𝔱𝔯𝔞𝔰
bold-frakturBold fraktur𝕷𝖊𝖙𝖙𝖗𝖆𝖘
double-struckDouble-struck𝕃𝕖𝕥𝕥𝕣𝕒𝕤
monospaceMonospace𝙻𝚎𝚝𝚝𝚛𝚊𝚜
small-capsSmall capsʟᴇᴛᴛʀᴀꜱ
fullwidthFullwidthLettras
circledCircledⓁⓔⓣⓣⓡⓐⓢ
negative-circledNegative circled🅛🅔🅣🅣🅡🅐🅢
squaredSquared🄻🄴🅃🅃🅁🄰🅂
negative-squaredNegative squared🅻🅴🆃🆃🆁🅰🆂
parenthesizedParenthesized🄛⒠⒯⒯⒭⒜⒮
strikethroughStrikethroughL̶e̶t̶t̶r̶a̶s̶
underlineUnderlineL̲e̲t̲t̲r̲a̲s̲

Examples

Every style applied to Lettras ejemplo: piña (real output of stylize). The accent in piña is the styled n plus a combining tilde, so how it looks depends on the font; the decoration styles (strikethrough, underline) mark every character, accents included.

Style idResult
bold𝐋𝐞𝐭𝐭𝐫𝐚𝐬 𝐞𝐣𝐞𝐦𝐩𝐥𝐨: 𝐩𝐢𝐧̃𝐚
italic𝐿𝑒𝑡𝑡𝑟𝑎𝑠 𝑒𝑗𝑒𝑚𝑝𝑙𝑜: 𝑝𝑖𝑛̃𝑎
bold-italic𝑳𝒆𝒕𝒕𝒓𝒂𝒔 𝒆𝒋𝒆𝒎𝒑𝒍𝒐: 𝒑𝒊𝒏̃𝒂
sans𝖫𝖾𝗍𝗍𝗋𝖺𝗌 𝖾𝗃𝖾𝗆𝗉𝗅𝗈: 𝗉𝗂𝗇̃𝖺
sans-bold𝗟𝗲𝘁𝘁𝗿𝗮𝘀 𝗲𝗷𝗲𝗺𝗽𝗹𝗼: 𝗽𝗶𝗻̃𝗮
sans-italic𝘓𝘦𝘵𝘵𝘳𝘢𝘴 𝘦𝘫𝘦𝘮𝘱𝘭𝘰: 𝘱𝘪𝘯̃𝘢
sans-bold-italic𝙇𝙚𝙩𝙩𝙧𝙖𝙨 𝙚𝙟𝙚𝙢𝙥𝙡𝙤: 𝙥𝙞𝙣̃𝙖
scriptℒℯ𝓉𝓉𝓇𝒶𝓈 ℯ𝒿ℯ𝓂𝓅𝓁ℴ: 𝓅𝒾𝓃̃𝒶
bold-script𝓛𝓮𝓽𝓽𝓻𝓪𝓼 𝓮𝓳𝓮𝓶𝓹𝓵𝓸: 𝓹𝓲𝓷̃𝓪
fraktur𝔏𝔢𝔱𝔱𝔯𝔞𝔰 𝔢𝔧𝔢𝔪𝔭𝔩𝔬: 𝔭𝔦𝔫̃𝔞
bold-fraktur𝕷𝖊𝖙𝖙𝖗𝖆𝖘 𝖊𝖏𝖊𝖒𝖕𝖑𝖔: 𝖕𝖎𝖓̃𝖆
double-struck𝕃𝕖𝕥𝕥𝕣𝕒𝕤 𝕖𝕛𝕖𝕞𝕡𝕝𝕠: 𝕡𝕚𝕟̃𝕒
monospace𝙻𝚎𝚝𝚝𝚛𝚊𝚜 𝚎𝚓𝚎𝚖𝚙𝚕𝚘: 𝚙𝚒𝚗̃𝚊
small-capsʟᴇᴛᴛʀᴀꜱ ᴇᴊᴇᴍᴘʟᴏ: ᴘɪɴ̃ᴀ
fullwidthLettras ejemplo: piña
circledⓁⓔⓣⓣⓡⓐⓢ ⓔⓙⓔⓜⓟⓛⓞ: ⓟⓘⓝ̃ⓐ
negative-circled🅛🅔🅣🅣🅡🅐🅢 🅔🅙🅔🅜🅟🅛🅞: 🅟🅘🅝̃🅐
squared🄻🄴🅃🅃🅁🄰🅂 🄴🄹🄴🄼🄿🄻🄾: 🄿🄸🄽̃🄰
negative-squared🅻🅴🆃🆃🆁🅰🆂 🅴🅹🅴🅼🅿🅻🅾: 🅿🅸🅽̃🅰
parenthesized🄛⒠⒯⒯⒭⒜⒮ ⒠⒥⒠⒨⒫⒧⒪: ⒫⒤⒩̃⒜
strikethroughL̶e̶t̶t̶r̶a̶s̶ e̶j̶e̶m̶p̶l̶o̶:̶ p̶i̶ñ̶a̶
underlineL̲e̲t̲t̲r̲a̲s̲ e̲j̲e̲m̲p̲l̲o̲:̲ p̲i̲ñ̲a̲

What a style cannot draw. ñ, ó, ü... are flagged in notNative for every letter style, because the accent is a combining mark. ß, Æ, Œ, Ø and non-Latin scripts have no styled version and stay plain:

stylize('Straße', { style: 'script' }).results[0].parts;
// [ { text: '𝒮𝓉𝓇𝒶', missing: false }, { text: 'ß', missing: true }, { text: 'ℯ', missing: false } ]
// show the missing piece as an empty box, or warn the user

Classic mode strips accents first, so nothing is flagged:

stylize('piña', { style: 'bold', classic: true }).results[0];
// { id: 'bold', text: '𝐩𝐢𝐧𝐚', notNative: [], ... }

One style, several styles, or all (results is always an array):

stylize('Hola', { style: 'bold' }).results.length;              // 1
stylize('Hola', { style: ['bold', 'script'] }).results.length;  // 2
stylize('Hola').results.length;                                 // 22

Reference: docs/TEXT_STYLES.md.

Kotlin and MCP. lettras.stylize("piña", style = "bold") returns the same results; in an MCP client, ask for "write 'Lettras ejemplo' in bold and script" and the assistant calls stylize_text with { "text": "Lettras ejemplo", "style": ["bold", "script"] }.

Crossword (crucigrama)

Words with clues in, a crossword out: a puzzle matrix to play and a solution matrix to check. Every language works and accents are kept.

Use it

import { crossword } from 'lettras';

const out = crossword({
  entries: [
    { word: 'gato',  clue: 'Maúlla y caza ratones' },
    { word: 'perro', clue: 'El mejor amigo del hombre' },
    { word: 'mono',  clue: 'Trepa por los árboles' },
    { word: 'cebra', clue: 'Rayas blancas y negras' },
    { word: 'oso',   clue: 'Duerme en invierno' },
    { word: 'rata',  clue: 'Roedor pequeño' },
    { word: 'toro',  clue: 'Embiste al capote' },
    { word: 'piña',  clue: 'Fruta tropical con corona' },
    { word: 'ñu',    clue: 'Antílope africano' },
  ],
  rows: 12, cols: 12,   // the largest it may take; the result is cropped
  seed: 4,              // optional: same input and seed, same crossword
});

Kotlin

val c = Lettras().crossword(listOf("gato" to "Maúlla y caza ratones", "perro" to "El mejor amigo del hombre"), rows = 12, seed = 4)
c.puzzle; c.solution; c.placements; c.clues()

MCP (tool crossword, free, no usage limit): ask "make a Spanish animals crossword with these words and clues", or call it with

{ "name": "crossword", "arguments": { "entries": [ { "word": "gato", "clue": "Maúlla y caza ratones" }, { "word": "perro", "clue": "El mejor amigo del hombre" } ], "rows": 12, "seed": 4 } }

Example output

out.puzzle (7 rows x 11 columns here, what the player sees):

-   -   -   -   -   1   -   2   -   -   -
-   -   -   -   -   0   -   0   -   -   3
-   -   -   -   -   0   -   4   0   0   0
-   -   -   5/6 0   0   0   0   -   -   0
-   -   -   0   -   0   -   -   7   0   0
-   -   -   8   0   -   -   -   -   -   -
9   0   0   0   -   -   -   -   -   -   -

out.solution (the answers):

- - - - - C - G - - -
- - - - - E - A - - M
- - - - - B - T O R O
- - - P E R R O - - N
- - - I - A - - O S O
- - - Ñ U - - - - - -
R A T A - - - - - - -

out.placements lists every word with its number, clue, direction and first cell (r row, c column, both from 0):

{ "number": 1, "word": "cebra", "clue": "Rayas blancas y negras",      "direction": "down",   "r": 0, "c": 5, "length": 5 }
{ "number": 5, "word": "perro", "clue": "El mejor amigo del hombre",   "direction": "across", "r": 3, "c": 3, "length": 5 }
{ "number": 6, "word": "piña",  "clue": "Fruta tropical con corona",   "direction": "down",   "r": 3, "c": 3, "length": 4 }

The clue lists for the player come straight from placements:

Shortened here. Read the whole README on GitHub.

Tools it offers (3)

What this server listed when Ahel dialed its public endpoint in Oct 2026, with no key and no account of yours. The names are the server’s own.

  • generate_word_search
  • fill_word_search
  • list_languages

Signals

Last commit
Oct 2026
Advanced
Delivery
word-search MCP server → your Ahel connector (mcp.ahel.ai) → your AI.
Item type
mcp-server
Key
org-lettras-word-search
Source
github.com/artificialss/lettras-sdk
Hosted endpoint
https://mcp.lettras.org/mcp