NewsBlog Composer MCP
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| GOOGLE_CSE_ID | No | Google Custom Search Engine ID. Needs both GOOGLE_CSE_KEY and GOOGLE_CSE_ID from programmablesearchengine.google.com. | |
| GOOGLE_CSE_KEY | No | Google Custom Search API key. Needs both GOOGLE_CSE_KEY and GOOGLE_CSE_ID from programmablesearchengine.google.com. 100 queries/day, no card. | |
| IMAGE_PROVIDER | No | Set IMAGE_PROVIDER=cloudflare to use Cloudflare Workers AI (FLUX schnell) for images. Recommended: a free daily allowance, no watermark, and it is a real production API. | |
| TAVILY_API_KEY | No | Tavily API key. 1,000 credits/month, renews monthly, no card. The best keyed option for this pipeline; set TAVILY_API_KEY. | |
| POLLINATIONS_TOKEN | No | Free Pollinations token — register at auth.pollinations.ai, no card. This removes the watermark and raises the rate limit. Set POLLINATIONS_TOKEN. | |
| CLOUDFLARE_API_TOKEN | No | Cloudflare API token. Set CLOUDFLARE_API_TOKEN along with CLOUDFLARE_ACCOUNT_ID when IMAGE_PROVIDER=cloudflare. | |
| CLOUDFLARE_ACCOUNT_ID | No | Cloudflare account ID. Set CLOUDFLARE_ACCOUNT_ID along with CLOUDFLARE_API_TOKEN when IMAGE_PROVIDER=cloudflare. |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| get_profileA | Check whether this server has been set up, and with what. CALL THIS FIRST, before anything else. If The answers decide the byline, the voice, the schema publisher, where the call to action links, and the canonical URL for every post. Nothing here is inferred from the environment. |
| set_profileA | Record who is publishing, where, and in what voice. Run once, after asking. author_name: the person's real name. Prints as "By " and goes into the NewsArticle author field. tone: neutral | witty | upbeat | heartfelt | sombre. Shapes how posts are written; it never changes a fact, a figure, a quote or a link. company_name: the publisher. Becomes the schema publisher and the linked text in the closing call to action. site_url: the domain where posts are published. Canonical URLs, image paths and the call-to-action link are all built from it. A main domain or a subdomain both work. company_url: only when the blog is on a subdomain and the call to action should point at a different company site. Defaults to site_url. logo_url: defaults to /logo.png. Only pass values the user actually typed. Ask the name, company and domain as free-text questions - do not offer guessed options, do not take a name from the account or folder path, do not pick a tone for them, and do not carry over a company or domain from an earlier post or example. |
| reset_profileA | Forget the byline and voice, so the setup questions are asked again. |
| capabilitiesA | Report which providers are configured and which keyless fallbacks are in use. Call this first when something behaves unexpectedly - it shows whether verify_news has a real search key, whether humanize_text can rewrite server-side, and whether score_ai_text is using a real detector or the local heuristic. |
| write_blog_postA | Write a complete, publication-ready blog post about a news story. USE THIS TOOL whenever the user asks for a blog post, an article, a news write-up, or "content" about a headline or a current topic - including when the request is as plain as "write me a blog post about X", and including when they do not mention this server by name. Do not search the web and draft the article yourself. That produces an unverified post with no schema, no SEO pass and no publishing pack, which is the exact outcome this server exists to prevent. Call this first instead. It does not write the article on its own - it checks the input, confirms setup, and returns the ordered plan with the next call to make. Follow the plan. The article gets written at the draft_brief step, by you, to the structure that tool returns. |
| find_storiesA | START HERE when the user gives a topic rather than a specific headline. "write about AI today", "something on electric vehicles", "this week in fintech" are topics. Find what actually happened before writing anything. "AI today", "electric vehicles", "Indian fintech" are topics: there is no claim to verify yet, you first have to find out what actually happened. This searches recent coverage, groups articles reporting the same event into stories, and ranks them by independent publisher count and freshness. Use
|
| verify_newsA | START HERE when the user gives a specific headline and wants a post about it. Confirms the headline describes a real, corroborated story before anything is written. Call this even if the user just says "write a blog post about " - verifying first is the point of this server. Searches every configured news provider, keeps only results that actually match the headline, and counts how many INDEPENDENT publishers are carrying it. Returns is_legit=false unless at least two independent publishers match, or a single primary/official source does. This verifies a headline; it does not find one. If the user gave you a topic
("today's AI news") rather than a headline, call find_stories first. Note
that an old headline will correctly return old sources - Do not draft anything if is_legit is false. Feed |
| fetch_article_factsA | Step 3. Download the verified sources and extract usable material. Returns facts, short attributed quotes (<=15 words) and figures, each tagged with the source_url it came from. URLs that fail to fetch or extract are reported in per_url with the reason - they are never filled in with guesses. Everything you write in the article must trace back to an entry returned here. If a claim is not in this output, it does not go in the post. |
| draft_briefA | Step 5. Get the writing order, then write the article. Takes the verified facts and the keywords and returns the plan: a 1000-1300 word target, exactly two sections, the facts grouped by source with numbers and quotes separated out, keyword placement, FAQ questions, and the angles only this author can supply. ACT ON IT IMMEDIATELY. You are the writer: compose the full body in the
configured voice and pass it to build_schema as Every reported claim must trace to a fact in the output. Where the sourcing is thin, reach the length with explanatory background and mark it as background; never attribute an invented detail to a source. Then run find_ai_words until clean and review_draft before build_schema. |
| review_draftA | Step 6. Read the writer's draft and say where it is weak. Never rewrite it. Pass the human-written draft and the facts from fetch_article_facts. Returns must_fix / worth_fixing / consider, each note naming the sentence and what to do about it, plus what the draft already does well. Checks claims against the researched facts and flags figures or quotes nothing supports, quotes over 15 words or missing attribution, stock AI phrasing, weak openings, hedging stacks, passive density, and flat sentence rhythm. Returning a rewritten draft defeats the purpose. Give the writer the notes. |
| humanize_textA | Optional. Rewrite a draft to strip AI writing tells, keeping facts intact. Prefer review_draft. This rewrites the text for the writer, which produces machine-written prose again; a detector will read it as such, because detectors measure how predictable the wording is rather than how many stock phrases it contains. Use this only to edit text the writer already wrote, and tell them it was used. With an LLM key configured, the rewrite happens server-side and comes back in
rewritten_text. Without one, mode='delegated_to_caller' and you must apply the
returned Optionally pass voice_sample to match a specific writer's rhythm. The sample governs style only and never contributes facts. |
| score_ai_textA | Step 7. Score how human the text reads, 0-100 (higher = more human). Uses a real detector API if one is configured, otherwise a local heuristic that measures structural tells (sentence-length burstiness, stock phrases, em dash density, lexical variety). Check is_real_detector before presenting the number, and always surface the caveat: no detector score proves authorship. Run it before and after humanize_text to show the improvement. |
| find_ai_wordsA | Check a draft for stock AI phrasing and report exactly where it appears. Returns Cheaper and more precise than score_ai_text for this one job; score_ai_text also measures rhythm and gives you the number. |
| build_publishing_packA | Final step. Everything needed to publish, in one block. Returns the title, the Blogger labels line, the custom permalink slug, the
search description, the image alt text, and
Pass the result to save_and_present as |
| generate_imageA | Step 8. Generate a banner image for the article and save it locally. Build the prompt from the article's visual concepts, not its brand names. A trademark filter runs anyway and rewrites brand terms into generic descriptors before the prompt leaves this machine; check terms_removed to see what it changed. The returned path is local. Upload the file and pass a public https URL to build_schema, or NewsArticle.image will point somewhere no crawler can reach. |
| seo_keywordsA | Step 4. Mine the keywords this post should target, before drafting. Pass the headline plus the Returns primary_keyword, secondary_keywords, entities, and - from real Google autocomplete data - long_tail_queries and faq_query_candidates. Draft the FAQ from faq_query_candidates wherever your facts can answer them: those are questions people actually type. Also returns a suggested slug, meta title and meta description to feed into build_schema and seo_audit. No search-volume or competition data; that needs a paid keyword API. |
| seo_auditA | Step 10. Score the finished body against on-page SEO rules before publishing. Checks H1 uniqueness and keyword placement, keyword density, H2 structure, word count, meta title and description lengths, slug shape, image alt text, and external source links. Returns a score plus must_fix / should_fix / nice_to_have lists. Pass Fix everything in must_fix and call again. On-page structure only - it says nothing about search volume, competition or backlinks. |
| build_schemaA | Step 9. Render the HTML body and both JSON-LD blocks, then check them. article: {headline, description (110-160 chars, used as the meta
description), intro:[str,str] (exactly two), sections:[{heading,
paragraphs:[str], bullets?:[str]}] - TWO or THREE sections, each with TWO
to FOUR paragraphs, and the whole body must come to 1000-1300 words,
cta (one closing sentence that
must contain CTA_LINK_TEXT verbatim so it renders as a link),
date_published?, author?, slug?, url?, meta_title?, section?, language?,
include_h1?}
faq: [{question, answer}] - 4 to 8 entries
image: {url, alt, title?, caption?} - url must be the public https URL
references: [{title, url, publisher?}] - real fetched URLs only
keywords: the primary and secondary keywords from seo_keywords; they go into
NewsArticle.keywords and come back in Pure templating, no model call. Renders the house body format: 720px container, inline styles, banner, byline, hr-separated H2 sections, FAQ as H3/P pairs, references as an ordered list. By default the body carries NO H1 because Blogger renders the post title itself - set BODY_INCLUDES_H1=true if your platform does not. Returns |
| save_and_presentA | Step 11. Write the finished package to disk and hand the post over.
Returns Produces a timestamped folder containing paste-into-blogger.html (both
JSON-LD blocks plus the styled body - the file to paste into the post
editor), index.html (a standalone preview page with meta, canonical, Open
Graph and Twitter tags in the head), body.html, newsarticle.jsonld,
faqpage.jsonld, a copy of the image, meta.json, report.md, and - when report.md is the human-readable summary: verification verdict and
publishers, human score before and after humanising, SEO score with any
must-fix items, and the reference list. Populate Pass the |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| house_style | Structure, sourcing and voice rules the drafting step must follow. |
| humanizer_rules | The AI-writing-tell rules used by humanize_text. |
TDQS
Scored across 19 tools
Several tools sit close together: write_blog_post and draft_brief both return writing plans, get_profile and capabilities both report configuration state, and find_ai_words/review_draft/score_ai_text/humanize_text all target AI-sounding prose. The detailed step-numbered descriptions separate them in practice, but an agent choosing from names alone could easily select the wrong one.
Most names follow a clear verb_noun pattern (fetch_article_facts, review_draft, save_and_present) and are consistently snake_case, so the set is readable. A few exceptions like seo_keywords, seo_audit, and capabilities break the pattern, and write_blog_post is named as though it writes but actually just plans.
19 tools is in the heavy range for an MCP server, and although each tool represents a pipeline step, the surface is large for an agent to hold in context. The tools are not obviously redundant, but the count feels more like a full application than a focused toolset.
The pipeline covers story discovery, verification, fact extraction, drafting, review, humanization, SEO, schema, image generation, and a publish pack, so there are no critical dead ends. Gaps are minor: image upload to a public URL and actual publishing/site integration are left to the agent, and there is no way to edit an already-saved post.