Etincel
About
Find the AI tells in your prose. Deterministic, local, runs in CI. MCP server + CLI + Action.
Details
- Author
- AIStoryHub
- GitHub stars
- 6
- Downloads
- 843
- Categories
- Productivity, AI, Marketing
Jump to
- leverage
- streamline
- comprehensive
- uses: AIStoryHub/etincel@main
- An MCP server (src/server.ts) exposing twenty tools
Setting up with Highlight
This MCP is not yet compatible with Highlight’s one-click setup. However, you can still use it with Highlight by following these steps:
- Download and install Highlight from highlightai.com/download
- Navigate to the plugins tab and select "Add Custom Plugin"
-
Configure the plugin with the settings below
Plugin Name
EtincelCommand (node, npx, python, etc.)Please refer to the README for specific instructions on how to obtain API keys or other required environment variables.
- Enable "Start Automatically" if you want the plugin to start when Highlight launches
From the repository
The README includes setup instructions such as npx etincel lint README.md.
list_styles
List every available style: premade emotional-tone presets, any voices the user has trained from their own samples, and (if a .etincelrc in the current repo defines one) the shared team style, id 'team'. Call this before drafting or revising non-fiction prose if the caller hasn't been told which style to use, or if the user asks what styles exist.
get_style_guide
Fetch the full drafting guide for one style (a preset id like 'direct-warm', the id of a trained voice, or 'team' for the shared style a .etincelrc in the current repo defines, if any). Returns prose instructions to follow while drafting or revising: sentence rhythm, tone dials, and (for trained voices) the writer's own measured habits. If a .etincelrc in the current repo sets team-wide instructions, those are folded into every style's instructions, not just 'team''s. Read this before drafting; it is context for you, the drafting model, not a tool that writes prose itself.
train_style
Analyze one or more of the user's own writing samples (emails, posts, essays, memos: real finished text they wrote or approved) and persist a trained voice profile under that name. Measures sentence length and variance, paragraph rhythm, contraction rate, em-dash and semicolon habits, fragment use, structural entropy (sentence-opener variety and punctuation-mark variety), and recurring phrasing. Call again with the same name and new samples to add more training data to that voice; the new samples blend into its existing measurements rather than replacing them. If the voice may have been renamed since it was created, pass its id (from list_styles) instead so the right voice is targeted regardless of its current name. This never fabricates a voice from a description; it only learns from real text the user supplies.
create_style_from_dials
Build a style profile from explicit dial values instead of writing samples: for when the user wants to hand-tune a voice (or doesn't have samples handy). 3 persona dials (formality, warmth, directness, 0-10) plus 8 mechanical dials (0-100, including entropy: how much AI-typical structural regularity to break) that map onto the same measurements train_style extracts from real text, so a dial-built style and a trained voice are the same shape. Call again with the same name to overwrite.
update_style
Rename a trained voice or adjust its dials in place, keeping its id (and default-style pointer) stable. Persona dials (formality, warmth, directness) always apply; the mechanical dials only take effect if the voice has no writing samples (was built from dials, not trained). A sample-trained voice keeps its measured mechanical stats regardless of what's passed here.
fork_style
Copy a style into a new trained voice under the given name, seeded with its persona dials and drafting guide. Two kinds of source: a premade preset (e.g. 'pr-review', 'linkedin-post'), or another installer's style published publicly on the hosted gallery, addressed as "handle/slug" (e.g. "jpleblanc/blunt-memo", the same address shown on its public page at etincel.ai/v/handle/slug). A public-style fork also carries over its 8 mechanical dials (rhythm, sentence length, em-dash use, etc.) and any banned words, custom words, or drafting instructions the source installer set specifically for that style, never their private account-wide dictionary or instructions; a preset fork only ever has persona dials and entropy to carry, since a preset has no measured mechanics. A public-style fork makes one network call to etincel.ai to fetch it; a preset fork never leaves this install. The fork is then a normal trained voice: retrain it with train_style from real samples, or hand-tune it with update_style, without touching the original.
delete_style
Permanently delete a trained voice profile by id. Does not affect premade presets.
set_default_style
Set which style (preset or trained voice) should be used by default for this user going forward, so it doesn't need to be re-specified every time.
check_voice_match
Compare a piece of drafted text's measured sentence/paragraph rhythm and mechanics against a trained or custom voice's baseline (sentence length, rhythm variance, paragraph variance, contraction rate, em-dash use, fragment use, question use, structural entropy). Use this after drafting in a voice to check whether the draft's rhythm actually landed close to it, instead of just eyeballing it. Returns a verdict ('on rhythm' / 'some drift' / 'off rhythm'), a match score, specific dials that drifted with a plain-language note for each, and a caveat you should relay alongside the verdict: this is a rhythm/mechanics measurement, not an authorship or AI-detection check, so text merely shaped like the voice (by anyone, or any tool) can come back 'on rhythm', and a genuine off-voice draft by the target writer can still come back drifted. Confidence comes back "low" on short input, since a handful of sentences isn't enough to read rhythm reliably; treat a low-confidence verdict as provisional. Only works against trained or custom voices (from train_style, create_style_from_dials, or fork_style), not bare presets, which have no measured baseline; fork_style a preset first if you want to check a draft against one.
check_self_repetition
Compare a piece of drafted text against a trained voice's own recent training samples for two kinds of self-repetition: opening the same way ("you've opened this way in 4 of your last 6 pieces"), and reusing a characteristic phrase across several of them. This is about the writer's own recurring habits, not AI-writing tells; use audit_text for those. Only meaningful for a voice trained from real samples (train_style) with at least 3 recorded samples; dial-tuned or preset-forked voices, or ones with too little history yet, come back with an empty findings list rather than an error. Only the local install tracks sample history today, so a hosted/remote connection may always report zero history. A signal to weigh, same trust-mode spirit as audit_text: never rewrite the draft on the strength of this alone.
audit_text
Deterministically scan a piece of non-fiction text for common AI-writing tells: banned hype vocabulary, chatbot fingerprints, and structural patterns (uniform paragraph length, stacked transitions, em-dash overuse, rule-of-three compulsion, and more), plus this installer's own banned/custom word lists from add_banned_word/add_custom_word (the 'global' list, merged with a style's own list if styleId is given), plus a repo-local .etincelrc/.etincelrc.json/etincel.config.json if one exists at or above the current directory (dictionary as code, reviewable and versioned). Returns a tier (green/yellow/orange/red), a numeric score, specific findings with severity and location, and a strengths signal (specificity density, concrete-vs-abstract ratio, sentence-rhythm variation). Read strengths too, not just findings: it's the counter-signal against fixing every flagged word into flat, sterile prose. Never a silent rewrite. Use this to show the user what's flagged and why, so they stay in control of any change; only rewrite what they ask you to rewrite.
second_read
A single model call that reads a draft and reports what a careful human editor would notice: unscored, untiered, and never a rewrite. Distinct from audit_text, which is deterministic and reproducible; this is neither, so weigh it as one more opinion, not a verdict, and never gate a decision on it alone. Requires the hosted server (https://etincel.ai/api/mcp): the local (stdio) install has no account to bill a model call against, so this always fails there with a clear explanation. audit_text remains fully available locally, no account needed.
add_banned_word
Add a term to this installer's own banned-words list, checked by audit_text alongside the built-in AI-tell corpus. Without styleId, this adds to the global list, which applies to every style. With styleId, it only applies when auditing against that specific style, merged on top of the global list. Use this when the user says something like 'add [word] to my banned words list' or 'never let me use [word] again'.
remove_banned_word
Remove a term from this installer's banned-words list (global, or a specific style's list).
add_custom_word
Add a term to this installer's own allowed-words list, so audit_text never flags it even if it matches the built-in corpus or a banned word: the 'corporate dictionary' case, e.g. an org's own acronyms or house terms. Without styleId, this adds to the global list. With styleId, it only applies to that specific style, merged on top of the global list. Use this when the user says something like 'add [word] to my custom words list' or 'stop flagging [word], it's one of ours'.
remove_custom_word
Remove a term from this installer's allowed-words list (global, or a specific style's list).
list_dictionary
Show the banned-words and custom (allowed) words lists for a scope: the global list (default), or a specific style's list. For a style, also returns the effective merged list (that style's words plus the global ones): what audit_text actually applies when that style is selected.
set_style_instructions
Save free-text drafting rules layered on top of a style's voice: required elements ('always include a CTA'), audience notes, forbidden topics, format constraints, anything that isn't about sentence rhythm or tone. Overwrites whatever was saved for this scope. Without styleId, this sets the global instructions, which apply to every style. With styleId, it only applies to that specific style, merged after the global instructions (get_style_guide returns the merged result automatically). Use this when the user says something like 'for this style, always end with a CTA' or 'remember: never mention pricing in emails'.
clear_style_instructions
Remove the saved instructions for a scope (global, or a specific style), leaving it empty.
get_style_instructions
Show the saved instructions for a scope: the global instructions (default), or a specific style's own. For a style, also returns the effective merged text (global plus that style's own) that get_style_guide already folds in automatically.
Claude Desktop / Cursor
Paste into your MCP client config file to install this server.
{
"mcpServers": {
"etincel": {
"etincel-nonfiction": {
"command": "npx",
"args": [
"etincel",
"serve"
]
}
}
}
}
McpServers
{
"etincel-nonfiction": {
"command": "npx",
"args": [
"etincel",
"serve"
]
}
}
Sign in to leave a review
Use Google, GitHub, or an email account so ratings stay tied to real people.
No reviews posted yet.


