mcp-puzzlemaster
Stores an audit log of every MCP tool invocation in PostgreSQL, and provides tools for generating usage charts and exporting the audit trail as CSV.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-puzzlemasterSolve today's Spelling Bee with letters T A C R O L Y and center T"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-puzzlemaster
A small MCP server that solves word puzzles — Spelling Bee, crosswords, Wordle — against the full 172,823-word ENABLE1 dictionary, and writes an audit row to Postgres for every call it serves.
It exists to make one argument concrete: once several agents share a single MCP server, you get things you cannot get from tools scattered across three codebases. One dictionary, loaded once, for every caller. One seam that sees every invocation. One table you can graph and export.
Built with FastMCP and deployed to Prefect Horizon (formerly FastMCP Cloud).
Tools
Every tool takes an explicit agent_name. See Agent identity
for why that is honest telemetry and not authentication.
Tool | Arguments | Returns |
|
| every valid word with its score, the total, and any pangrams |
|
| every dictionary word matching the pattern |
|
| the remaining candidate words |
|
| an ASCII bar chart of logged usage |
|
| the audit log as CSV text |
Puzzle rules, as implemented
Spelling Bee. Words are ≥ 4 letters, must contain the center letter, and may use only the 7 allowed letters — but may reuse them freely, so the check is
set(word) <= allowed, not a multiset one. A 4-letter word scores 1 point flat (not 4 — this is the classic trap); 5+ letters score 1 point per letter; a pangram earns +7 on top. Worked example:VALIDTYwith centerVyields 34 words / 171 points, and the pangramVALIDITY. The New York Times' curated answer for the same puzzle was 21 words / 119 points — a public word list over-generates against editorial curation, which is a real and useful lesson about deterministic tools versus curated ground truth.Crossword.
_means unknown. The word length is derived from the pattern, so there is no separate length argument.C_O__W_RD→["CROSSWORD"].Wordle. Feedback is one character per letter:
gright letter and right spot,yright letter wrong spot,babsent. Rather than hand-coding constraint rules — which is exactly where duplicate letters go wrong — a candidate survives only if replaying each guess against it reproduces the feedback that was actually seen.CRANE/gybbbleaves 34 candidates.
export_results returns CSV content, not a file path
The obvious design writes a CSV to disk and returns the path. That is wrong for a server you reach over HTTPS: the file lands on the server's filesystem, which the caller cannot read and which is wiped on the next deploy. So the tool returns the CSV itself — header row plus one row per invocation — which the caller can save, paste into a spreadsheet, or read directly.
Two caps keep that safe:
at most 1000 rows per call (
limit, default 200, most recent first, then returned oldest-first), anda 4 MB response ceiling, below the 6 MB hard cap on hosted MCP responses, after which the CSV ends with a
# truncated at N of M rowscomment line.
Audit cells are capped at 1000 characters
Each of the inputs and outputs columns holds at most 1000 characters of
JSON. Anything larger collapses to a still-valid JSON object recording the
original size and a short preview:
{"truncated_chars": 41297, "preview": "{\"candidates\": [\"CABLE\", ..."}This matters more than it sounds. A single Wordle result serialized whole runs to roughly 9 KB, and a one-letter crossword pattern matches thousands of words — a handful of those rows makes the exported CSV unreadable in any spreadsheet. The cap is a promise about the stored value: the preview is shrunk until the finished JSON object fits in 1000 characters, escaping included.
The audit trail is an audit trail and a ready-made eval dataset: every row is an input/output pair that nobody had to write by hand. That only exists because the calls funnel through one place.
Related MCP server: PostgreSQL MCP Server
Environment variables
Name | Required | Purpose |
| for the audit log | Postgres connection string, e.g. |
There are no other configuration variables, and no secrets are committed to this
repository. If DATABASE_URL is unset or the database is unreachable:
the solvers still work. A logging failure must never break a tool call, so a failed audit write is reported to stderr and swallowed. Repeats are collapsed so a standing misconfiguration cannot flood the logs.
usage_graphandexport_resultsfail with aToolErrornamingDATABASE_URLand what to set it to — they have nothing to report without it.
The schema
Everything lives in — and is qualified to — a schema of its own,
mcp_training. Point DATABASE_URL at an empty database and the server
creates it on startup; point it at a database that already has it and the
startup DDL is a no-op.
CREATE SCHEMA IF NOT EXISTS mcp_training;
CREATE TABLE IF NOT EXISTS mcp_training.invocations (
id BIGSERIAL PRIMARY KEY,
ts TIMESTAMPTZ NOT NULL DEFAULT now(),
agent_name TEXT NOT NULL,
tool TEXT NOT NULL,
inputs JSONB NOT NULL,
outputs JSONB NOT NULL,
duration_ms INTEGER NOT NULL,
ok BOOLEAN NOT NULL
);
CREATE INDEX IF NOT EXISTS invocations_ts_idx ON mcp_training.invocations (ts DESC);
CREATE INDEX IF NOT EXISTS invocations_agent_idx ON mcp_training.invocations (agent_name);Every statement the server issues names mcp_training.invocations in full.
Nothing depends on search_path, and the server never touches an object outside
its own schema — it is expected to share a database instance with unrelated
applications, where a bare table name is a genuine hazard rather than a style
preference.
A connection that fails at startup is retried at most once every 30 seconds rather than being written off for the life of the process, and connections come from a small pool (1–4), not one per call.
Postgres rather than SQLite because the deployment target has an ephemeral filesystem: a local database file disappears on redeploy, and "monitor usage over time" is meaningless if the counter resets.
Run it locally
Python 3.12 (3.11–3.14 all work).
git clone https://github.com/overclock-accelerator/mcp-puzzlemaster
cd mcp-puzzlemaster
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txtVerify it — no database and no API key needed:
python test_server.pyThis drives the server with FastMCP's in-memory Client(mcp), which speaks the
real MCP protocol to the server object in the same process: no subprocess, no
port, no network. Without DATABASE_URL it checks the solvers and asserts that
the reporting tools fail with a clear message; with DATABASE_URL set it also
round-trips the audit log through Postgres — including a check, run with
search_path deliberately set to pg_catalog, that rows really do land in
mcp_training.invocations and not wherever the connection's search path
happened to point.
Run it over stdio (what a local MCP client speaks):
python server.pyInspect what a client will see — this is the same inspection the deployment build runs, so if it fails here it will fail there:
fastmcp inspect server.py:mcpPoint Claude Code at your local copy:
claude mcp add puzzlemaster -- python /absolute/path/to/server.pyDeploying to Prefect Horizon
Horizon builds from a Git repository and redeploys on every push to the default branch.
Push this repository to GitHub and sign in at horizon.prefect.io.
Connect the Horizon GitHub App and grant it access to the repository. For a repository owned by a GitHub organization, the person completing that popup must be an admin of that organization.
Create a server, and set the entrypoint explicitly to:
server.py:mcpThe build system has no default entrypoint — this is the most common reason a first build never goes live.
Add
DATABASE_URLunder Settings → Environment Variables. Environment variables are injected at build time as well as runtime, so changing one requires a new build and deploy; editing the value does not touch the running server.The server goes live at
https://<name>.fastmcp.app/mcpover Streamable HTTP.
What this repository does to satisfy the platform:
.python-versionpins3.12. Horizon supports 3.11–3.14. It does not support 3.10.requirements.txtis discovered automatically and pinsfastmcpexactly.fastmcpmust be a dependency even though the platform runs the server for you — it uses thefastmcpCLI to install, inspect, and launch it.data/enable1.txtis committed (~1.7 MB) and resolved asPath(__file__).parent / "data" / "enable1.txt", never from the working directory. Committed files ship inside the build artifact; the ephemeral- filesystem warning applies to files the server writes at runtime.The word list loads at import time, which is a deliberate trade: it adds to cold start once instead of adding latency to every request.
Nothing is ever printed to stdout. Under stdio transport stdout is the JSON-RPC channel and a single stray
printcorrupts the stream. All diagnostics go to stderr, which the platform surfaces as server logs.if __name__ == "__main__": mcp.run()is kept for local stdio testing. The deployed object is the module-levelmcp; the platform serves it over HTTPS itself.
Connect a client (Horizon authentication is on by default, so callers present a bearer key or sign in interactively):
claude mcp add --transport http puzzlemaster https://<name>.fastmcp.app/mcpAgent identity
agent_name is an ordinary tool parameter, which means the model fills it in.
It is honest attribution for telemetry, not authentication — a model can get it
wrong, and a hostile one can simply lie. It is the right baseline for a server
that also runs over stdio, where there is no header channel at all.
Over HTTP the production answer is different: inject the caller's identity from
the authenticated request with FastMCP's Depends(), which excludes the
parameter from the generated schema entirely so the model can neither see nor
set it. Horizon's gateway also records the acting user or service account for
every request before it reaches this code, independently of what the model
claims.
Layout
mcp-puzzlemaster/
├── server.py # the whole server — entrypoint is server.py:mcp
├── test_server.py # in-memory protocol tests, no key and no DB required
├── requirements.txt # pinned
├── .python-version # 3.12
└── data/enable1.txt # ENABLE1, 172,823 words, public domainThe solver function bodies in server.py are byte-identical to their reference
implementations and are meant to stay that way. The @mcp.tool wrappers around
them are the seam: they add agent identity, hand in the shared word list, and
translate ValueError into ToolError. Add a sixth tool tomorrow and it is
audited for free, because the audit lives in middleware at on_call_tool rather
than inside any solver.
Credits
data/enable1.txt is the ENABLE1 word list, which is in the public domain.
License
MIT — see LICENSE. Copyright (c) 2026 Overclock Accelerator.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceA serverless backend that enables natural language querying of a Postgres database, converting user questions into SQL and returning structured, UI-friendly responses.
- AlicenseNot gradedqualityDmaintenanceEnables natural language interaction with PostgreSQL databases, supporting query execution, schema management, data operations, user management, and database maintenance with secure remote access via HTTP/SSE transport.MIT
- FlicenseNot gradedqualityDmaintenanceEnables querying PostgreSQL and MySQL databases using natural language, with RESTful endpoints for listing tables, describing schemas, and executing read-only queries.1
- AlicenseNot gradedqualityDmaintenanceEnables natural language querying of PostgreSQL databases with intelligent SQL generation using LLMs.1Apache 2.0
Related MCP Connectors
Query PostgreSQL databases in plain English — LLM-generated, safety-validated SQL.
AI-powered biblical research tools — lexicons, morphology, manuscripts, and more.
Resolve, search and verify legal citations against the official sources, with provenance.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Overclock-Accelerator/mcp-puzzlemaster'
If you have feedback or need assistance with the MCP directory API, please join our Discord server