mcpbeat

Niche — Editorial Intelligence MCP Server

com.nicheangle/niche
answering

Niche — Editorial Intelligence is answering right now. Last checked 13 min ago. It exposes 25 tools. Last commit 19 Jun 2026.

Find the stories worth writing about: discover emerging stories, rank the angle, draft from sources.

Uptime history 40 hours of history
40 hours agonow
100.0%
Uptime 24h
91 of 91 checks
25
Tools
read from the server
358 ms
Response time
average over 24h
0
Stars
last commit 19 Jun 2026

Connect this server

Endpoint below is the one we actually reach during checks — not the one copied from a README. Last verified 13 min ago.

run in your terminal
claude mcp add niche --transport http https://api.nicheangle.com/mcp
~/Library/Application Support/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "niche": {
      "url": "https://api.nicheangle.com/mcp"
    }
  }
}
~/.codex/config.toml
[mcp_servers.niche]
url = "https://api.nicheangle.com/mcp"
.cursor/mcp.json
{
  "mcpServers": {
    "niche": {
      "url": "https://api.nicheangle.com/mcp"
    }
  }
}
.vscode/mcp.json
{
  "mcpServers": {
    "niche": {
      "url": "https://api.nicheangle.com/mcp"
    }
  }
}

Available tools 25

Read directly from the server with tools/list, grouped by what they act on. If a tool disappears, we record the date.

niche
niche_add_output
Add an output cell to a session that's already reached CP3. Use this when the user picked a small initial cell set, previewed the drafts, and now wants another surface (e.g. the session started with linkedin:text_post and the user wants to add instagram:carousel too). Text-only cells (linkedin:text_post, x:thread, long_form_article, etc.): generates text via the matching generator if it hasn't run yet, then creates the Output row. This call blocks synchronously ~20-30s when it must run a new generator family (no status to poll); it returns fast when that family already generated. Idempotent: if the cell is already on the session, returns the existing Output unchanged. Asset cells (linkedin:image_post, x:reel, instagram:image_post, etc.): creates the text Output row; image-bearing cells auto-attach a free branded card (static_urls populated without an explicit render, swappable anytime), while video/reel assets are never auto-rendered. The response's next_step says exactly what to call for more: niche_render_image_card (cell plus an explicit background: 'photo' or 'brand_color') or niche_render_reel (cell). The response's copy_lineage says whether this cell drafted fresh text or shares its generator family's existing copy. Remove: pass `remove_cell` to delete a produced cell the user no longer wants on this run. Idempotent: a clean message when the cell isn't present. Errors: 400 if session is pre-CP3; 422 if cell is invalid.
niche_angle_propose
Niche content angles: pick a story from the discovery slate and surface the strongest angles worth publishing, the editorial-judgment step that turns a development into a piece. Returns five angles[], each with frame, hook, tension, cta_direction, and cta_variants (a swap palette). niche_session_state then carries an angle_recommendation (recommended_angle_id plus reasoning); when a brand profile is bound it is brand-fit-scored, otherwise recommended_angle_id is null with recommendation_basis='default_ordering' (no invented pick). Returns immediately with status=cp2_generating; poll niche_session_state until angles[] is populated. Custom framing (provenance-preserving): to draft your own angle on this researched story, not one of the proposed five, pass `custom_framing` (after the story is locked and angles are ready). The framing is shaped onto the real story and drafted on this session, so the trust block keeps the story's actual sources. Use this instead of niche_draft_direct when you have a researched story in hand; draft_direct works from your take alone, so it has no researched sources to cite. Regenerate: pass `regenerate=true` (story locked, angles ready) for a fresh set of five angles on the same story; pair with `lens` to steer the rerun. Capped per session and metered like a generation.
niche_attach_image
Upload or attach a user-supplied or externally-designed image (bring-your-own asset) to a post: the creator's own visual (a product shot, their actual work, a card designed elsewhere) instead of an AI-generated image (niche_render_image_card photo, paid) or a flat brand card. Free, with no image-generation spend. For a visual-product maker the real piece is the sale. Input modes, in order of preference: (1) `upload_ref`, the FAST path for an agent that built the asset itself and can run a shell: POST the raw file to `/asset/upload` (multipart/form-data, your bearer token) to get back an `upload_ref`, then pass it here. The bytes travel over HTTP and never round-trip through the model as base64, so it's effectively instant for a real graphic. (2) `image_url`, a fetchable https URL (the server fetches + stores it; for an asset that already lives on the web). (3) `image: {mime_type, data_base64}`, inline base64, fine for small images only. (4) `image_chunk`, the no-shell FALLBACK: upload bounded chunks of base64. It still re-types the bytes through the model (slow), so use it only when the agent has no shell to curl with. Split the file's bytes into ~32-48KB pieces, base64 EACH independently, send in order, each with a `sha256` of that piece's raw bytes so the server catches a mis-transcribed chunk and has you resend just that one (this is what makes the slow path reliable). Omit upload_id on the first chunk; the response returns one to pass on the rest. Set `final:true` on the last chunk (optionally with `total_sha256`); that call assembles, validates, and attaches. The cell's output must already exist (use niche_add_output first if needed). Sets it as the post's image; publishes with the caption. A dimension_note warns if the image's aspect won't fit the cell. Undo-able (the prior image is kept in history).
niche_brand_kit_guided_setup
Return a structured question chain the agent walks the user through to populate the BrandKit, VoiceProfile, and (optionally) BrandProfile. Each entry carries an `intent` describing what the answer is for (so the agent paraphrases in its own voice based on the conversation it's already having) plus a `prompt_hint` fallback for agents that relay tools verbatim. Use this when the agent is helping a new user set up Niche and wants a predictable, brand-aware Q&A sequence instead of improvising. Tiered by impact: - Tier 0 (primary): URL ingest, fills 70-90% in one ask. - Tier 1 (gap_fill): only the fields URL ingest didn't fill. - Tier 2 (discipline): opt-in guardrails (topics off, banned terms, competitor stance). - Tier 3 (no_url): full fallback for users without a site. Per-question `applies_to_field` tells the agent where the answer writes (via niche_brand_kit_update or niche_brand_profile_set). `is_already_set` is computed from the user's current BrandKit and BrandProfile state so the agent skips questions already answered. Returns the full chain in one call; the agent inspects state, decides flow, and asks in any order (or skips entirely if the user volunteered the answer earlier in the conversation).
niche_brand_kit_ingest
Auto-populate the user's BrandKit (palette / fonts / tagline / logo / wordmark / boilerplate / voice notes) from files, a URL, or pasted text. Additive by default: fills empty fields, leaves populated ones alone. Idempotent: re-running the same inputs doesn't double-write. Overwrite rule: if the target brand kit already has an identity (a tagline/boilerplate/voice for a different brand), do not silently overwrite it. First ask the user whether to replace it. If the account supports multiple brand profiles, prefer creating a separate brand instead: pass a new `brand_id` slug plus `brand_name` rather than clobbering the existing one. Only pass `replace=true` once the user has confirmed they want this brand re-learned from the new source. Use when the agent has brand assets in scope (a working directory with logos / press-kit / brand-guide PDFs, the user's portfolio or Substack URL, pasted boilerplate copy) and wants to populate Niche's BrandKit so future signal_scan and content generation inherit the brand context. Agent-side equivalent of the Niche web app brand-kit ingest surface, same backend engine. Async, then poll: a URL or multi-file ingest runs in the background, so this call returns fast with {ingest_id, status:'ingesting'}. Then poll niche_brand_kit_ingest_status(ingest_id) until status is 'done'; that response carries the populated BrandKit, the ingest report (detected[] / skipped[] / errors[]), and a diff[] of changed fields. (Loop: ingest, then poll status until done/failed; same pattern as niche_signal_scan to niche_session_state.) Do not re-call ingest while one is running; a duplicate of the same inputs attaches to the in-flight job. URL ingest also fills voice primitives when the page has post-shaped text (Substack/blog/X). If a URL is slow or thin to scrape, the visual fields may land before the voice pass completes; when the report flags this, paste the page's About/homepage copy via `text=` to complete the brand voice.
niche_brand_kit_ingest_status
Poll the result of an async niche_brand_kit_ingest. Pass the `ingest_id` it returned. status: 'ingesting' (keep polling) | 'done' (response carries the full kit plus detected[]/skipped[]/errors[]/diff[]/left_unchanged_because_populated[]) | 'failed' (error plus failed_step; the kit was not written). The marker expires 30 min after the ingest starts.
niche_brand_kit_update
Set specific BrandKit fields by name. The write path for the structured fields (tagline / boilerplate / voice_notes / forbidden_phrases / signature_phrases / endcard preferences / video voice preference / colors / fonts) without going through the ingest engine. Use after niche_brand_kit_ingest fills the easy stuff, or to commit values the user answered through niche_brand_kit_guided_setup. Only fields you pass are touched; fields you omit stay at their current value. Lists replace the current value (they do not append). Response includes a diff[] of fields that changed and the full updated kit. Archiving: pass archive=true to archive a brand (soft and reversible; it disappears from every list but is not deleted), or archive=false to restore one. The default/active brand can't be archived (promote another to default first). A brand with published history won't archive unless you also pass acknowledge=true. Use archive_scope='test' to archive every scratch brand at once (never the default). There is no hard delete here; archive is the removal verb agents have.
niche_brand_profile_get
Read back the persisted brand profile without modifying it. Use it to confirm a profile landed as expected, to check the active profile a run is bound to, or to inspect the current shape before a partial update. Pass `brand_id` to read one profile; omit it to list all (brand_id, updated_at) summaries. Returns the full profile JSON, schema_version, created/updated timestamps, and a brand_kit_sync_status indicating whether the profile's mirrored fields are in sync with the brand kit.
niche_brand_profile_set
Set or update the persisted brand profile for a brand. The profile is a structured JSON document applied across every pipeline stage: voice rules, banned terms, canonical vocabulary, framing allowlist, channel config, compliance disclosures, and verifier overrides. Use it to persist a profile derived from a repo or docs so future runs inherit the rules, or to update voice rules and banned terms before the next run. Required sections: `identity` and `voice` (a profile with no voice falls back to generic drafts). A re-set that omits voice is accepted with a default voice stub rather than rejected. Validation: tiered lints (error / warn / info). 'error' lints reject the set; 'warn' lints accept with a note. The response includes `lints[]`. `conflicts[]` lists fields locked by the brand kit, which takes precedence; those profile values are not stored. brand_id is unique per user; re-setting the same brand_id replaces the prior profile.
niche_draft_create
Niche draft content: lock the chosen angle and turn it into platform-native social drafts (LinkedIn post, X thread, Instagram, newsletter/long-form), ready to review and publish, the downstream payoff once the story and angle are decided. Returns immediately with status=cp3_generating; poll niche_session_state until outputs[] is populated. Each output carries its trust data nested under `outputs[i].trust`: `source_faithfulness_score`, `source_ungrounded_claims[]`, `source_diversity_passed`, `source_recency_passed`, `overall_severity`, a severity-tagged `flags[]`, and `verifier_blocked_reason`/`verifier_blocked_claim` when a fabrication was refused. (No top-level `verifier_audit` field; read `outputs[i].trust`.) BRAND: voice/offer/CTA come from the run's bound brand. If this account has MULTIPLE brands and the run isn't bound to one, this returns `brand_choice_required` with `brand_options[]` and generates NOTHING. STOP, ask the user which brand, then re-call with `brand_id` (or `brand_id:'none'` to draft deliberately unbranded). A single/default brand binds automatically.
niche_draft_direct
Draft the creator's own take or product straight into posts, with no research scan and no story/angle picks. Use this for product-led or bring-your-own-content work: a specific thing to say ('new walnut dining table, live edge, $2,800') or a page to repurpose. The signal pipeline (niche_signal_scan) is for 'what's worth writing about my niche'; this is for 'write this exact thing.' Provide at least one of: `take` (what to say), `source_url`, or `source_text` (the last two repurpose an existing page). Returns a session_id in under 2s; poll niche_session_state(wait:30, wait_until:'checkpoint') to cp3_awaiting_review/complete, then read outputs[]. Pass `brand_id` to bind the creator's voice, offer, and call to action so the draft sounds like them and includes their offer (set those first via niche_brand_profile_set).
niche_draft_publish
Publish a single output to its platform. Defaults to dry_run=true: returns the would-publish payload plus any verifier blocks without actually filing. Set dry_run=false and provide an idempotency_key to commit. The commit is the only irreversible action in the workflow; the agent should present the dry-run preview to the human and only commit on explicit go-ahead. For any piece with a rendered image, reel, or card, show the human the actual pixels (the preview_url / image_url) first: never let publish be the first time a human sees the final visual. Verifier-blocked outputs refuse to publish even with dry_run=false; clear the block on the row first. When the target social isn't linked, returns status='not_connected' plus a `connect_url` instead of publishing; send the user to connect once, then retry. Scheduling: pass `scheduled_for` (an ISO-8601 datetime in the future) to file the post for later instead of publishing now; it dispatches automatically through the same publish path. Pass `cancel_scheduled=true` to clear a pending schedule for this platform. Prefer an exact cell string (e.g. 'x:thread', 'x:single_tweet') over a bare family name. A bare family that matches more than one draft on the session returns status='ambiguous_platform' with the candidate cells rather than guessing. Every publish and dry-run response echoes `resolved_cell` so you can confirm which artifact shipped.
niche_draft_revise
Applies the values you pass to a specific output. Accepts any subset of the output's fields: caption, hashtags, or partial script updates (hook / body / cta / hook_tweet / body_tweets / title / subtitle / pull_quote / cover_slide / slides / cta_slide / alt_text / card_headline, where card_headline rewords the image card's header). Pass `apply_hook_variant_index` to splice an existing hook_variants[N] into the live hook in one move without rewriting the rest. If you pass no editable field (or values identical to the current draft) it changes nothing and returns `status:'no_change'` naming the params that edit content. Angle and story changes still go back through niche_angle_propose; they invalidate the verifier trust block and need fresh generation. Response includes a `diff[]` array listing every field that changed (`{field, before, after}`) so agents can show users the delta rather than the full new payload.
niche_intelligence_query
Niche (nicheangle.com) research and analysis: answer an analyst-shaped question over fresh-scanned sources and get an intelligence answer as the deliverable, not a single post. Use for: 'the 10 biggest developments in X this week', 'what's emerging before it goes mainstream', 'where is investment activity rising', 'find 3 non-obvious narratives to publish on LinkedIn'. The answer is the ranked slate plus engine-grounded narratives or patterns: every narrative cites real slate stories and is fact-verified by a second pass (no source, no narrative). This uses the same engine as the Niche web app, so both surfaces return the identical grounded answer; do not synthesize your own narratives over the slate, present these. Non-blocking: returns a `session_id` immediately (under 2s). Poll niche_session_state every ~3-5s. At status == cp1_awaiting_story the ranked slate (`stories[]`) is ready; present it right away. Synthesis runs concurrently and usually lands 20-90s after the slate (hard cap ~2 min); if you requested it, call niche_session_state(wait:30, wait_until:'synthesis') and repeat until `synthesis_pending == false` (usually 1-3 calls); don't give up early, you'll always get `synthesis[]` or a `synthesis_shortfall_note`. With synthesis:'none', `synthesis` stays null and `synthesis_pending` is false at cp1, so stop there. To turn a narrative into a post, pick its supporting story id and call niche_angle_propose; no new scan needed. BRAND: omit brand_id and a single/default brand binds automatically; on a MULTI-brand account you'll get `brand_choice_required` with `brand_options[]` (the query still runs). Ask the user which brand before drafting. Pass brand_id to bind one, or 'none' for unbranded.
niche_list_sessions
Enumerate the user's recent sessions. Returns id, niche_input, status, `outcome`, target_platforms, picked story/angle ids, and created/updated_at for each. Use this when the session_id has been lost (across agent invocations, hours of work, etc.) or to find an in-flight session to resume. Returns newest-first. Judge a terminal run by `outcome`, not raw `status`: a `failed` status is usually a walk-away, not an error. outcome ∈ {complete, expired (a slate was produced but nobody picked; re-open and choose), interrupted (a restart ended it, credits refunded; just re-run), cancelled (stopped on purpose), failed (a real error; see error_message), running}. (`status_filter` still matches the raw status value.)
niche_render_image_card
Render a visual onto a post at CP3, or edit an existing image. scope: 'full' (default) renders a new visual and requires `background`. 'recomposite' re-composites new text, color, or size over the retained background at no charge. 'restore' reverts to the prior image from history, at no charge. 'reframe' produces a per-platform aspect variant from the retained background, at no charge. background (required for scope='full'): • 'photo': a generated AI/photographic image with the headline composited over it. ~30 credits, ~30-90s, asynchronous: returns status='rendering_image_card'; poll niche_session_state (image_render.status: rendering, then done with static_urls on the output, or failed with credits refunded). A repeat call while a render is in flight is a no-op. • 'design': the INFOGRAPHIC, a generated editorial graphic that DRAWS the argument (a ranked bar chart, a two-column diagram, a stat, a before/after, a pull-quote), on-brand and legible, with vetted icons. The designer art-directs the treatment from the brand PALETTE (leads light for data, dark for narrative; accent as a spice), and honors a look steer in design_concept ('brighten it up', 'a ranked bar chart', 'navy and gold'). ~30 credits, asynchronous (poll as above). • 'brand_color': a flat brand card with the headline on the brand's solid color with logo and wordmark. No generation, no credits, synchronous. • 'svg': you author the card exactly as SVG markup (pass `svg`); the server rasterizes it to the cell's dimensions. Free, instant, deterministic. The right choice for data, labels, charts, and comparisons (where generated images fail at layout), and the only visual that works from a network-locked sandbox (SVG is text). The SVG owns the whole canvas; use brand colors and fonts from niche_whoami. Static shapes, paths, and text only (no scripts, external references, or foreignObject). `headline` sets the bold header (defaults to the post's card_headline; auto-fits, not truncated). Idempotent: a prior render is replaced. Errors: render_not_ready before CP3; render_not_configured when image generation is unavailable; render_card_unavailable when background='brand_color' but the piece has no card-bearing platform.
niche_render_reel
Render a 9:16 vertical reel for a session at CP3. A per-beat script (typically 4-7 beats) is composited into one video: stills, voiceover, motion, caption overlays, and an endcard (~30-120s). Reels are delivered as a downloadable file for the user to publish. scope: 'full' (default) renders a new reel. 'recomposite' re-renders presentation only (captions on/off, caption_sync_mode, endcard text) from the retained footage at no charge. 'endcard' is the same, limited to the endcard. 'beat:N' re-renders a single beat's still (optional beat_direction), charged for that one image; everything else is reused. Idempotent on the video output: a prior render is replaced. Options: captions_enabled (default true) overlays per-beat captions; music_enabled (default false) mixes background music under the voiceover; tone shapes the script (default | punchy | direct | reflective), with reel_direction for free-form direction beyond those words; length or target_duration_sec set the runtime target; music_direction shapes the music; voice picks the voiceover voice; endcard_mark chooses the endcard brand mark; needs_legible_text forces a text-capable still generator; caption_sync_mode (default 'phrase') reveals captions phrase-by-phrase in sync with the voiceover at no extra cost, and is ignored when captions_enabled is false. Errors: 503 if reel rendering is unavailable; 400 before CP3; 422 if the script is unusable. Cost: ~350 credits.
niche_reuse_asset
Copy an image that already exists on one output onto another cell, instant and free (no regeneration, no credits). Use this when the user wants 'the same image' on a second surface ('use the LinkedIn image on X', 'same picture on the newsletter') instead of niche_render_image_card (which generates a new image and costs credits). Both cells must already exist on the session (add the target via niche_add_output first if needed) and the source must have a rendered image. Copies the source's static_urls onto the target so it publishes with that image. Idempotent: source==target is a no-op.
niche_session_cancel
Cancel a running session. Marks status=failed with an error_message ('cancelled by user' or the caller's reason), and stops the in-flight orchestrator if any. Used when you want to free a slot under the concurrent-session cap without deleting the session (history and audit trail preserved). Use the REST DELETE endpoint if you want a hard archive cleanup that also wipes outputs. Idempotent: cancelling a completed / already-failed session returns its current state unchanged. Credits: the unused hold is released; work already committed (e.g. the discovery for a story you picked) stays charged, so cancelling does not refund committed work. A pre-CP1 cancel (nothing committed yet) is effectively free. A full refund applies only to an actual run failure.
niche_session_export
Export a session as a structured calendar artifact preserving session_id and per-story story_id traceability. Use after a niche_signal_scan when you want a metadata-rich content backlog instead of running individual pieces end-to-end. Outputs a standard editorial-calendar shape suitable for content-backlog and planning workflows. Two formats: • markdown: human-readable and agent-citable. Session metadata at top (session_id, niche, scan timestamp, and brand_profile_active state). Then a card per story with title, headline_candidate, summary, recency_score, publication_breakdown, source_breakdown, and empty slots for the user to fill (Frame, Hook, Article-shape, Ship Order). Followed by a 'recommended ship order' section and cross-cutting notes. • json: structured shape ready to pipe to other tools or load into a notebook. Same data, machine-shaped. Preserves story_id and session_id traceability so you can come back in N weeks and re-run niche_angle_propose / niche_draft_create against the same stories with the same brand profile bound. The artifact is the entry point to a calendar-builder workflow.
niche_session_revert
Revert a session back to an earlier checkpoint. Use when the user (or you) decided the picked story / angle isn't the right one and you want to re-pick without starting a new scan. to='story': cancels current generation, returns to CP1_AWAITING_STORY with the same ranked stories list. Clears selected_story_id and selected_angle_id. to='angle': returns to CP2_AWAITING_ANGLE with the same angles list. Clears selected_angle_id only. Idempotent: reverting a session already at the target checkpoint returns the current state unchanged. Safety: reverting a finished run (cp3/complete) discards its paid-for drafts. The first call returns status='confirm_discard' with the count instead of reverting; pass acknowledge_discard=true to actually proceed. Credits: the discarded drafts are not refunded (the generation already ran), and re-picking re-runs and re-charges content generation. Revert to change direction, not to reclaim spend.
niche_session_state
Universal poll endpoint: read the full current state of a session. Returns status, ranked stories, picked story_id, generated angles, picked angle_id, draft outputs (with trust fields), and an elicitation hint for whatever decision is next. Call this whenever you need to check progress; it's safe and cheap. Each story includes title, summary, headline_candidate (the post-shaped headline distinct from the cluster title), recency_score, relevance_score, freshness_label, and the publication_breakdown of contributing outlets (provenance). Each story also carries a recommended_story_id plus recommendation_reason before a pick. Each draft output's trust data lives under `outputs[i].trust.*` (verifier_blocked_reason, source_faithfulness_score, source_ungrounded_claims, source_diversity_passed, source_recency_passed, source_distinct_count, plus a flags[] array with explicit severity and source_grounding_map). The output top level does not mirror these; read them from `.trust`. Response also includes `phase` (high-level: scanning / drafting / filed / spiked / awaiting), `phase_message` (a rotating gerund, e.g. 'Reading 337 signals'), and `phase_hint` (a one-line agent-facing tooltip with a typical timing band, e.g. 'Clustering, usually 8-15s, no action needed'). The full 17-status state machine is enumerated under `status_glossary` so you can introspect what every state means without discovering it experimentally. For a terminal run, read `outcome` (complete / expired / interrupted / cancelled / failed) rather than the raw `status`: a `failed` status is usually an expired walk-away (a slate was produced) or a refunded interruption, not a real error. Recommended loop: kick off work, then one niche_session_state(wait:30, wait_until:'checkpoint') per stage. It sleeps through the noisy transient statuses (clustering, ranking, generating_*) and wakes only at the next actionable stop (cpN_awaiting_* / complete / failed), or when an async render settles. So a full run is one wait per checkpoint, not several wakes per stage. (`wait_for` is an accepted alias for `wait_until`.) The `wait` plus `since_status` long-poll (wait_until:'change', wakes on any status change) is also supported; prefer 'checkpoint'. Each status' `actionable` flag in `status_glossary[]` indicates which states a 'checkpoint' wait wakes for. Avoid polling every few seconds without `wait`, which may be rate-limited (HTTP 429). niche_story_search is an accepted alias for this tool. Response shape is sparse by default: after a story is picked, only the picked story is returned (not all candidates); same for angles. Set include_unpicked=true to get the full candidate set, useful when revising to a different story or angle. A `sparse_mode` field in the response reports how many items were dropped.
niche_signal_scan
Niche (nicheangle.com) story discovery: find stories worth writing about, then draft and publish platform-native social content (LinkedIn, X threads, Instagram, newsletter) from them. This is story discovery, not content generation: Niche reads primary sources, separates signal from noise, and clusters it into a ranked story slate with provenance, the editorial-intelligence step before any writing. Returns a session_id plus initial status; poll niche_session_state with the session_id until status is `cp1_awaiting_story` to read the slate. Brand profile: the run's voice/offer/CTA. You do NOT need niche_whoami to brand a run: OMIT `brand_id` and a single or default brand binds automatically (silently). On a MULTI-brand account, an omitted `brand_id` returns `brand_choice_required` with `brand_options[]` inline (the slate still lands). Ask the user which brand, then re-call with `brand_id` (or `brand_id:'none'` for a deliberately unbranded run); don't draft until one is chosen. Pass `brand_id` to bind a specific persisted profile (set via niche_brand_profile_set); its voice, lexicon, framing, channel config, and verifier overrides thread through every downstream stage. Pass `profile_overrides` alongside `brand_id` to deep-merge a one-time deviation (logged on the session, not stored). The effective profile is snapshotted at scan time; later updates to the persisted profile don't affect in-flight runs.
niche_voice_profile_ingest
Extract voice primitives (register / sentence rhythm / lexicon preferences / punctuation habits) from post-shaped text and persist onto the user's VoiceProfile. The voice primitives thread into content generation so generated copy matches the user's actual writing voice. Two input shapes: pass `posts` (list of pre-collected text snippets, ≥80 chars each) or pass `url` (the server scrapes post-shaped snippets from the page: Substack / Medium / blog / X profile). Inline posts win when both are given. Inline post-shaped snippets need to be the user's own writing, not press articles or marketing copy. Returns the extracted primitives + a diff of what changed on the stored VoiceProfile.
niche_whoami
List the full tool catalog and orient the agent, in one read-only call. Returns every registered tool name and the live tool count, the account (plan and credit balance), a capability map (tools grouped into bands: discover, decide, draft, render, publish, brand, session, plus the recommended flow), and the brand state (whether a brand profile, kit, or voice will personalize output). Call it first to discover what's available, plan a session, and check credits before spending.

Endpoints

URLTransportStateLatencyChecked
https://api.nicheangle.com/mcp streamable-http answering 328 ms 13 min ago

Niche — Editorial Intelligence — questions

Answers built from our own checks of this server.

What can Niche — Editorial Intelligence do?
It exposes 25 tools, read directly from the server on our last check. Among them: niche_add_output, niche_angle_propose, niche_attach_image, niche_brand_kit_guided_setup, niche_brand_kit_ingest, niche_brand_kit_ingest_status and 19 more. The full list with descriptions is on this page — we take it from the server itself via tools/list, not from a README. How MCP servers expose tools in the first place →
Is Niche — Editorial Intelligence working right now?
We send a real MCP handshake every 15 minutes. Over the last 24 hours 91 of 91 checks got a reply (100.0%), average response time 358 ms. The bar chart above shows every period we have measured.
How do I connect Niche — Editorial Intelligence?
Copy the ready config from this page — we generate it for Claude Code, Claude Desktop, Codex, Cursor and VS Code, each with the file path that client actually reads. It is a remote server, so there is nothing to install — the client connects to the address.
Does Niche — Editorial Intelligence need an API key?
No. Niche — Editorial Intelligence completed a full MCP handshake with us as an anonymous client and listed its tools without asking for anything. All 25 of them are readable on this page. This is what we observed, not what the docs claim.
How fast is Niche — Editorial Intelligence?
It answers our handshake in 358 ms on average, which is faster than 39% of all working MCP servers we measure. The comparison comes from our own checks across the whole registry, every 15 minutes.
Is Niche — Editorial Intelligence open source?
Yes — it is published under the NOASSERTION licence, written in Shell, 0 stars on GitHub and 1 open issue. The source link is on this page, so you can read exactly what it does with your data before you connect it.