bot-tells
Click on "Deploy 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., "@bot-tellscheck this email for bot tells and fix safe issues: I hope this finds you well."
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.
bot-tells

Check a message before you send it for what makes readers think a bot wrote it.
npx @askeleven/bot-tells "I hope this email finds you well. I wanted to reach out..."Or paste one into the web page: askeleven.github.io/bot-tells. It runs in your browser, and nothing you paste leaves the page.
A reader decides in one line whether a person wrote to them. "I hope this email finds you
well" and the message is filed with the other thousand. A [First Name] nobody filled in,
or a "Let me know if you'd like me to adjust the tone" left at the bottom, and it is worse:
the reader now knows nobody read it before it went out. bot-tells finds those things
first. It is a CLI for pipelines, an MCP server so an agent can check its own writing, a
library, and a web page. It returns a verdict, a 0-100 bot score, every finding with where
it is and what to write instead, and the fixes that are safe to make without a rewrite.
Zero dependencies. No signup, no account, no network.
Not an AI detector
bot-tells cannot tell who wrote a message, and does not try. People write every one of these phrases too. It finds what a reader would hold against the message, whoever wrote it. A person who opens every email with "I hope this finds you well" gets the same score as a model that does, and should hear the same advice.
Related MCP server: Natural Voice MCP
What it checks
Leaks are chat output that should never reach a reader. Any leak fails the message, whatever the score.
Leak | Example |
Placeholder left in |
|
The model talking about itself | "As an AI language model", "my training data" |
Chat wrapper at the start | "Sure! Here's a draft of the email:", a |
Chat wrapper at the end | "Let me know if you'd like me to adjust the tone", "Feel free to customize this template" |
Markdown that will not render |
|
Tells are wording readers now associate with bots. They add to the score; none of them decides anything alone.
Tell | Example |
Stock openers | "I hope this email finds you well", "I wanted to reach out", "Great question!" |
Stock closers | "Don't hesitate to reach out", "I hope this helps", "I'd be happy to help" |
Stock phrases | "In today's fast-paced world", "navigate the complexities of", "a testament to", "unlock your full potential" |
Words people now read as AI | delve, tapestry, pivotal, seamless, leverage, utilize, moreover, and about 35 more |
"Not X, but Y" | "It's not just a tool, it's a game-changer" |
Rhetorical reveals | "The result?" "The best part?" |
Customer-service sycophancy | "You're absolutely right", "I apologize for any inconvenience" |
Em dashes | People use them well. Readers now count them anyway. |
Emoji bullets, from two lines up | The house style of generated posts |
Exclamation marks, from three up | Enthusiasm at a steady rate |
Every rule is in src/data/rules.js, with its weight and the reason
for it.
The score
Each finding has a weight from 1 (people say it all the time; it only counts in company) to 6 (almost nobody types this by hand any more). Repeats of the same thing count for less each time, and past a cap for nothing. The points become a score from 0 to 99 on a curve scaled by length, because one stock phrase says more about a three-line email than about a long one: one "I hope this email finds you well" in a 60-word email is 39.
Keep below 25. Review from 25: a reader may notice. Fail from 60, or on any leak. Both thresholds are options.
What it does not do
It does not rewrite. --fix makes only the changes that need no judgement: it cuts a
filler sentence when the sentence is nothing but filler, cuts chat wrappers, swaps a few
words one for one (utilize to use, a myriad of to many), turns a pair of em dashes around
an aside into commas, and unwraps Markdown. "Please don't hesitate to contact me on
305-555-0100" stays, because cutting it would cut the number. The rest is listed for a
person, or a model, to rewrite with the suggestion beside it.
It only reads English.
It does not know your reader. "I hope you're well" to a friend is warm. The score is about strangers.
Example
$ npx @askeleven/bot-tells draft.txt
FAIL Reads like a bot wrote it.
Bot score 83/100 [#################---]
Length 90 words, 11 sentences
Found 8 tells
3 >>I hope you're doing well<<! I wanted to follow up on our conversation last week regarding the website redesign. Our team has >>delved<< into your requirements and put together a >>comprehensive<< proposal that addresses your key goals >>—<< faster load times, a cleaner layout, and better mobile support.
5 >>The result?<< A site that >>not only looks great but also<< converts. We believe this will >>play a pivotal role in<< your growth.
7 >>Please let me know if you have any questions<<. I look forward to hearing from you!
TELLS
Words people now read as AI
Real words, but ones language models use far more than people do, so
readers have learned to spot them. "delved" (line 3): Try "look at",
"dig into". "comprehensive" (line 3): Try "full", "complete".
Rhetorical reveal
"The result?" (line 5). "The result?" "The best part?" A question
asked only to answer it in the next breath. Make it a statement: "It
cut onboarding to two days."
...In a terminal the findings are highlighted rather than marked with >> and <<.
$ npx @askeleven/bot-tells draft.txt --fix > fixed.txt
Fixed 2 of 8. Score 83 -> 77/100 (fail). 6 findings left for a person.Options
--fix Print the message with the safe fixes applied, and a
summary on standard error.
--markdown The destination renders Markdown (Slack, GitHub), so
Markdown is not a leak.
--ignore <list> Codes or rule ids to skip, comma-separated, such as
em_dash,exclamations.
--review-at <n> Review at this score or above. Default 25.
--fail-at <n> Fail at this score or above. Default 60.
--json Machine-readable output.
--no-colour Plain text.The message is the text on the command line, a file, or standard input (-, or piped in
with no text).
Exit code 0 means OK to send, 1 means do not send it as it stands (a leak, or the score
is at --review-at or above), 2 means it could not run. So it gates a pipeline:
npx @askeleven/bot-tells reply.txt && ./send reply.txtFor agents: MCP server
npx @askeleven/bot-tells mcpIt serves two tools over stdio: check_message (the verdict, score and findings) and
fix_message (the text with the safe fixes applied, what was applied, and what is left to
rewrite). The server tells the model never to send a message with a leak, to apply the safe
fixes, to rewrite what is left in plain words rather than swap one stock phrase for
another, and to check again.
Claude Code
claude mcp add bot-tells -- npx -y @askeleven/bot-tells mcpClaude Desktop, Cursor, and other clients that take a JSON config:
{
"mcpServers": {
"bot-tells": {
"command": "npx",
"args": ["-y", "@askeleven/bot-tells", "mcp"]
}
}
}As a library
import { checkMessage, fixMessage } from '@askeleven/bot-tells'
const result = checkMessage(draft)
if (result.verdict !== 'keep') {
const { text, unfixed } = fixMessage(draft)
// unfixed: findings with line, column, text and suggestion, for a rewrite
}checkMessage(text, options) takes reviewAt, failAt, markdown and ignore. It
returns verdict, score, summary, reasons (one per kind, with a stable code to
match on and a detail to show a person) and findings (each with start and end
offsets, line, column, the text as written, and a suggestion).
fixMessage(text, options) returns the fixed text, applied, unfixed, and result,
the fixed text checked again.
The library has no Node-only imports, so it runs in a browser as is: the web page imports
the same src/index.js.
Privacy
Nothing leaves your machine. There is no network code. The web page is static, loads no fonts, scripts or analytics from anywhere else, and the score card it makes is drawn in your browser.
Requirements
Node 20 or newer. No dependencies.
Why we built it
AskEleven runs AI employees that email and text candidates and customers for small businesses. A message from one of them has to read like it came from the business, because to the person receiving it, it did. This is the check for how it reads, run before anything is sent.
Contributing
Issues and pull requests welcome, especially:
False positives. A normal sentence a person would write that bot-tells holds against them. Include the sentence. These matter more than anything else here.
Tells we miss, with two or three real examples. A phrase only gets in if people outside this repo already read it as a sign of a bot.
Weights that look wrong.
Other languages. The rules are English only.
Run the tests with npm test, and build the web page into _site/ with
npm run build:site.
License
MIT. See LICENSE.
This server cannot be deployed
Related MCP Connectors
Scores whether a page reads as AI-generated and names the tells to fix.
Paste a draft and see the habits that make writing read like it came from an AI model.
DraftCheck: flags AI-writing patterns in prose with fix hints. Deterministic linter, not a detector.
Check text before your agent reads it: hidden instructions, invisible text and links that leak data.
Related MCP Servers
- AlicenseNot gradedqualityNot gradedmaintenanceProvides tools and resources to detect AI-generated writing patterns and refine text for more authentic, human-like communication. It enables users to analyze phrasing via a scoring system and apply conversational guides tailored for platforms like Twitter and LinkedIn.1-
- AlicenseNot gradedqualityBmaintenanceProvides writing guidance and mechanical lint checks to help AI clients draft or rewrite content in a specific natural voice.MIT
- FlicenseNot gradedqualityAmaintenanceEnables agents to analyze text or files for formulaic AI writing patterns, returning a 0–100 score, band label, violations with context, and advice. It uses configurable rule-based heuristics without LLM judges or API calls.-
- FlicenseNot gradedqualityAmaintenanceEnables agents to analyze prose for formulaic AI writing patterns and return scores, band labels, violations, and improvement advice. Supports checking inline text or files through MCP tools without external LLM or API calls.-