_ registry / mcp streamable-http · checked 3h ago

niche-mcp

https://api.nicheangle.com

Registry code: d8aa217aa467b1db

api record

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

from a public catalogue that lists it, not from the operator

endpoint
https://api.nicheangle.com/mcp
protocol
streamable-http ·2025-03-26
authentication
none observed
public key
none — nobody has proven they own this listing · is it yours? claim it
karma
0 · newcomer
_ is it live, free and safe measured by this hub
Is niche-mcp live?
Yes — it answered the hub's last check (checked 3h ago). It answered 100% of checks over the last 30 days.
Is niche-mcp free to use?
Not anonymously — it asks for a key or a login before it will serve. Whether that key costs anything is the operator's plan to say: the hub measured the door, not the pricing.
What tools does niche-mcp have?
8 tools: niche_signal_scan, niche_intelligence_query, niche_angle_propose, niche_session_cancel, niche_list_sessions, niche_whoami, niche_feed_read, niche_session_state.
Is niche-mcp safe to connect?
The hub found no text in its card or tool descriptions aimed at the agent reading them. It measures what the server answers, not its code — grant it only the access its tools need.
reachable
live
uptime, 30 days
99.6%

90 days 99.5%· all time 99.5%

latency
383ms

last good check

priced tools
0

of 8 tools

_ answered our checks, 90 days 404 checks · signed record
  • degraded → live
  • live → degraded· timeout after 20000ms
  • degraded → live
  • live → degraded· timeout after 20000ms
  • unknown → live
_ what it is for
used for
  • discover emerging stories in a niche
  • propose content angles
  • draft social media posts
  • render an image card or reel
  • publish a post to a platform
takes → gives
text, images → text, images, video
tools
4 reads3 changes data
_ usage and payments 30 days

Calls placed through this hub's router, from its own receipts. Every caller and every payer counts the same; the chain total is counted from three payers.

accounts
0

through this hub

calls served
0

successful

paid through this hub
0 USDC

what callers paid

_ what it can do 8 tools
8 auth-required 8 of 8 classified

Price is per tool, not per server. An agent whose handshake is open can hold tools that demand a key or a payment, and one figure for the whole agent sends callers into a wall.

  • niche_signal_scan changes data auth-required never probed

    Scan a niche you describe, right now (Pro). Returns a ranked, sourced slate of the stories people in that field are talking about, each with its independent-source count after syndicated copies are merged, the outlets, and why it matters. For a ready-made briefing use niche_feed_read instead; it is free and instant. Poll niche_session_state with the returned session_id until status is cp1_awaiting_story; the slate is in `stories`.

    mcp-tool

    {
      "type": "object",
      "required": [
        "niche"
      ],
      "properties": {
        "niche": {
          "type": "string",
          "maxLength": 200,
          "minLength": 2,
          "description": "Niche / beat description (2-200 chars). Specific is better."
        },
        "density": {
          "enum": [
            "minimal",
            "balanced",
            "essay"
          ],
          "type": "string",
          "default": "balanced",
          "description": "How tightly to pack visual formats (carousels especially).\n  • minimal: split a dense argument across more, shorter slides; favors skimmability.\n  • balanced (default): the standard per-slide caps.\n  • essay: permissive; allows longer slides/sections.\nOver-cap slides auto-split on sentence boundaries (never mid-sentence); over-280 tweets split into a chain regardless."
        },
        "recency": {
          "type": "string",
          "description": "Optional recency window that constrains discovery to fresh sources. One of '24h' | 'week' | 'month' | 'quarter' | 'year' (aliases: 'today'/'day'→24h, 'this week'→week, etc.). Use '24h' for 'today only / breaking'. Putting the demand in the niche string does not constrain recency; use this param. Omit to use the niche's default window."
        },
        "brand_id": {
          "type": "string",
          "description": "Binds this brand's voice, colors, offer, and CTA to the piece. Omit to use your default brand; on a multi-brand account pass the slug explicitly so a post about one product is not bound to another brand's identity. niche_whoami lists your brands."
        },
        "estimate_only": {
          "type": "boolean",
          "default": false,
          "description": "When true, return the discovery credit cost without starting a run or holding a reservation. Use it to quote a price before committing."
        },
        "recency_strict": {
          "type": "boolean",
          "description": "When true, `recency` is a hard cutoff: sources outside the window are dropped before clustering, so 'nothing older than yesterday' is honored exactly. Default false: the window is a strong bias but older corroborating sources can still attach to a fresh cluster. Set true when exactness matters more than slate depth (strict can thin the slate)."
        },
        "source_quality": {
          "enum": [
            "strict",
            "balanced",
            "broad"
          ],
          "type": "string",
          "default": "balanced",
          "description": "How aggressively to filter the slate on source quality (niche-relative; never penalizes a small publication that is the authority for the niche).\n  • strict: drop uncorroborated single-source silos that aren't a primary/official or a niche authority; surfaces only well-sourced stories. Can thin the slate.\n  • balanced (default): down-weight weak sources, don't drop.\n  • broad: surface everything, including low-coverage emerging clusters, with authority as a tiebreaker only.\nUse strict for a high-trust brief, broad to scout early signal."
        },
        "target_outputs": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Output cells to generate (platform×content_type matrix). Each cell is a 'platform:content_type' string or a cross-platform content type. Valid cells:\n  • linkedin:text_post: short LinkedIn post (text only)\n  • linkedin:image_post: LinkedIn post plus 1.91:1 image card\n  • linkedin:carousel: multi-slide carousel\n  • linkedin:reel: LinkedIn-native vertical video\n  • x:single_tweet: standalone tweet\n  • x:thread: multi-tweet thread\n  • x:image_post: tweet plus 16:9 image card\n  • x:reel: tweet plus 9:16 video\n  • instagram:image_post: caption plus 4:5 image card\n  • instagram:carousel: multi-image swipe\n  • instagram:reel: caption plus 9:16 reel\n  • long_form_article: universal essay (Substack/blog)\n\nA bare platform name also works and maps to that platform's default cell: 'x'/'twitter'→x:single_tweet (pass 'x:thread' for a thread), 'linkedin'/'li'→linkedin:text_post, 'instagram'/'ig'→instagram:image_post, 'longform'→long_form_article. The resolved cells are echoed back as target_outputs.\nDefaults to ['linkedin:text_post']; request only the cells you need (each additional cell adds generation cost)."
        },
        "idempotency_key": {
          "type": "string",
          "description": "Optional. A stable key for this logical scan: a retry with the same key reuses the original run instead of starting (and billing) a second. Even without it, an identical scan fired while one is still running is auto-deduped."
        },
        "thinking_budget": {
          "enum": [
            "fast",
            "balanced"
          ],
          "type": "string",
          "default": "balanced",
          "description": "Agent-side polling control. A full editorial workflow is structurally 15-20 tool calls (scan, poll, poll, poll, pick, poll, pick, poll, read). Use this to tune how many of those calls collapse into single waits.\n  • fast: scan blocks briefly (up to ~45s, under the tool-call timeout) for CP1 and returns the stories inline when they land in time. One call instead of many polls. Cheaper agent tokens, smaller cognitive surface. If CP1 isn't ready by the cap it still returns the session_id (status=discovering); poll niche_session_state from there, the run is never lost. Pick when you just want stories and the user is waiting.\n  • balanced (default): scan returns immediately with session_id; the agent polls niche_session_state (with wait plus since_status long-poll)."
        },
        "target_platforms": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Optional. A flat platform list (linkedin, linkedin_carousel, twitter, longform, instagram), coerced into target_outputs cells. Prefer target_outputs."
        },
        "profile_overrides": {
          "type": "object",
          "description": "Optional. Deep-merge these overrides onto the persisted profile for this run only. Use case: same brand, different register for a specific piece (e.g. a product-launch voice over an editorial one). Requires brand_id."
        }
      }
    }
    arguments 82 lines
  • niche_intelligence_query reads auth-required never probed

    Ask an analyst-shaped question over a fresh scan of a niche (Pro): 'the biggest developments this week', 'what is emerging', 'where money is moving'. Returns the sourced slate plus a short grounded synthesis as one answer. Every claim carries its sources.

    mcp-tool

    {
      "type": "object",
      "required": [
        "subject"
      ],
      "properties": {
        "lens": {
          "enum": [
            "mainstream",
            "emerging",
            "investment"
          ],
          "type": "string",
          "description": "Ranking posture. 'mainstream' (default) = authority-weighted. 'emerging' = inverts saturation to surface low-coverage, pre-mainstream signal. 'investment' = lifts stories carrying funding/raise/round/term-sheet markers."
        },
        "count": {
          "type": "integer",
          "maximum": 15,
          "minimum": 3,
          "description": "How many developments / narratives to return (3-15). Default ~5-10."
        },
        "window": {
          "type": "string",
          "description": "Recency window: '24h' | 'week' | 'month' | 'quarter' | 'year'. 'this week' maps to 'week'. Overrides the niche's default recency. A strong bias by default; pair with recency_strict for a hard cutoff."
        },
        "subject": {
          "type": "string",
          "maxLength": 200,
          "minLength": 2,
          "description": "The subject/space to investigate (2-200 chars). Specific is better."
        },
        "brand_id": {
          "type": "string",
          "description": "Binds this brand's voice, colors, offer, and CTA to the piece. Omit to use your default brand; on a multi-brand account pass the slug explicitly so a post about one product is not bound to another brand's identity. niche_whoami lists your brands."
        },
        "platform": {
          "type": "string",
          "description": "Optional publish target (linkedin / x / instagram) that shapes each narrative's publish_hook."
        },
        "synthesis": {
          "enum": [
            "none",
            "narratives",
            "patterns"
          ],
          "type": "string",
          "description": "'narratives' = N non-obvious publishable threads across the slate. 'patterns' = the named movement (pairs with lens:'investment'). 'none' (default) = ranked slate only, no synthesis."
        },
        "recency_strict": {
          "type": "boolean",
          "description": "When true, `window` is a hard cutoff (out-of-window sources dropped before clustering) so 'nothing older than yesterday' is exact. Default false (bias only). Strict returns fewer, higher-confidence stories; use when precision matters more than breadth."
        },
        "source_quality": {
          "enum": [
            "strict",
            "balanced",
            "broad"
          ],
          "type": "string",
          "default": "balanced",
          "description": "Source-quality filter (niche-relative). 'strict' drops uncorroborated single-source silos that aren't primary/official or a niche authority, for high-trust answers only. 'balanced' (default) down-weights weak sources without dropping. 'broad' surfaces everything (incl. low-coverage emerging clusters), authority as a tiebreaker only."
        },
        "target_outputs": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Optional. The draft cells produced if you later draft a narrative into content (same cell list as niche_signal_scan, e.g. ['linkedin:image_post', 'x:thread']). Without this, a draft defaults to a single 'long_form_article'. Set it when you know the surfaces you want, so niche_draft_create yields them directly instead of needing niche_add_output after."
        },
        "idempotency_key": {
          "type": "string",
          "description": "Optional. Stable key so a retry reuses the original run instead of billing a second; an identical query fired while one is still running is auto-deduped regardless."
        }
      }
    }
    arguments 75 lines
  • niche_angle_propose changes data auth-required never probed

    Angles on one story (Pro): up to a few distinct stances a reader could take, each with a hook, the take, and the sources that support it. Pass the session_id from a scan and a story_id from its slate. Nothing is written for you; the angles are starting points.

    mcp-tool

    {
      "type": "object",
      "required": [
        "session_id",
        "story_id"
      ],
      "properties": {
        "lens": {
          "type": "string",
          "description": "Optional steer (e.g. 'more contrarian', 'lead with the data'). Read on a regenerate run, and as a fallback steer for a custom_framing draft when custom_framing is set without its own wording."
        },
        "story_id": {
          "type": "string",
          "description": "id from niche_session_state.stories[].id"
        },
        "regenerate": {
          "type": "boolean",
          "description": "Generate a fresh set of angles on the locked story instead of returning the existing set. Requires the story locked and angles ready. Capped per session; metered like a generation."
        },
        "session_id": {
          "type": "string"
        },
        "custom_framing": {
          "type": "string",
          "description": "Optional. Your own angle in a sentence ('the contrarian take: X is overhyped because Y'). When set, drafts that angle on the real story (provenance preserved) instead of returning the proposed five. Requires the story locked and angles ready (cp2_awaiting_angle)."
        }
      }
    }
    arguments 28 lines
  • niche_session_cancel changes data auth-required never probed

    Cancel a scan that is still running.

    mcp-tool

    {
      "type": "object",
      "required": [
        "session_id"
      ],
      "properties": {
        "reason": {
          "type": "string",
          "description": "Optional. Surfaced as session.error_message."
        },
        "session_id": {
          "type": "string"
        }
      }
    }
    arguments 15 lines
  • niche_list_sessions reads auth-required 3h ago

    List your recent scans: id, the niche you described, status and timestamps. Use it to find a session_id you no longer have.

    mcp-tool

    {
      "type": "object",
      "properties": {
        "limit": {
          "type": "integer",
          "default": 25,
          "maximum": 100,
          "minimum": 1,
          "description": "Max sessions to return (default 25, max 100)."
        },
        "offset": {
          "type": "integer",
          "default": 0,
          "minimum": 0,
          "description": "Skip this many sessions before returning, for paging through history. Default 0."
        },
        "brand_id": {
          "type": "string",
          "description": "Optional filter to sessions tied to one brand profile slot."
        },
        "status_filter": {
          "type": "string",
          "description": "Optional status filter, e.g. 'cp1_awaiting_story', 'cp3_awaiting_review', 'complete', 'failed'. Omit for all."
        },
        "niche_contains": {
          "type": "string",
          "description": "Optional case-insensitive substring filter on the niche input, to find sessions on a topic (e.g. 'walnut')."
        },
        "include_outputs": {
          "type": "boolean",
          "default": false,
          "description": "When true, also returns `recent_outputs`: the account's produced posts/images/reels across all sessions, newest first, each with its session_id, cell, a reachable asset_url, and publish state. Use it to locate a past asset (e.g. an image made on a prior run). Default false."
        }
      }
    }
    arguments 35 lines
  • niche_whoami reads auth-required 3h ago

    Orient in one read-only call: your plan (Free or Pro), the tools this server serves, and the endpoint. Call it first if you are unsure what is available.

    mcp-tool

    {
      "type": "object",
      "properties": {
        "include_test": {
          "type": "boolean",
          "default": false,
          "description": "Include scratch and experimental brand slots in available_brands. Default false so only real brands are listed and an agent does not bind a throwaway by accident."
        },
        "include_all_brands": {
          "type": "boolean",
          "default": false,
          "description": "List every brand on the account in available_brands. Default false: only the active brand is returned (with other_brand_count) so a single orienting call does not enumerate the whole roster. Set true when you genuinely need to pick among multiple brands."
        },
        "include_brand_assets": {
          "type": "boolean",
          "default": false,
          "description": "Include usable brand asset URLs (logo, wordmark) in brand_palette. Default false: the palette returns colours and fonts plus logo_available / wordmark_available booleans, and the renderer fetches the actual asset when a render needs it. Set true only if you need the asset URL directly."
        }
      },
      "additionalProperties": false
    }
    arguments 21 lines
  • niche_feed_read auth-required 3h ago

    Read a niche's daily edition: the stories independent sources back up, each with its independent-source count (after syndicated copies are merged), the outlets and URLs, a one-line why-it-matters, new-vs-continuing status, plus what moved, where the sources disagree and what to watch. Editions are built once a day per niche and shared, so this read is instant and free. Pass a niche slug from the public directory (for example financial-advisors, defense-tech) and optionally a date (YYYY-MM-DD) for a past edition. A quiet day returns status=quiet with no stories. Returns 'no_edition' when the niche exists but hasn't been built yet, and 'unknown_niche' otherwise.

    mcp-tool

    {
      "type": "object",
      "required": [
        "niche"
      ],
      "properties": {
        "date": {
          "type": "string",
          "description": "Optional edition date, YYYY-MM-DD. Default: the latest edition."
        },
        "niche": {
          "type": "string",
          "description": "Niche slug, e.g. financial-advisors."
        }
      }
    }
    arguments 16 lines
  • niche_session_state reads auth-required 22h ago

    Read the current state of a scan: status, the ranked stories with their sources and independent-source counts, and any angles already proposed. Poll this after niche_signal_scan or niche_intelligence_query until the slate is ready.

    mcp-tool

    {
      "type": "object",
      "required": [
        "session_id"
      ],
      "properties": {
        "view": {
          "enum": [
            "status",
            "full"
          ],
          "type": "string",
          "default": "full",
          "description": "`status` (lean): a few-hundred-byte control envelope of status, phase, picked ids, `content_versions` (per-section change counters), `counts`, `output_ids`, cost, and next_step. Use this for the poll loop. `full` (default): the complete state with stories/angles/outputs. Fetch `full` once when a content_version moves, rather than re-shipping the full state every poll. Pairs with wait plus since_status."
        },
        "wait": {
          "type": "integer",
          "default": 0,
          "maximum": 30,
          "minimum": 0,
          "description": "Long-poll for up to N seconds (0-30) waiting for the session state to change. Returns immediately if the state already differs from `since_status` (or if the session is awaiting a checkpoint / complete / failed). Drops agent token burn from N polls to 1 wait. Default 0 (no wait, behave as before)."
        },
        "wait_for": {
          "enum": [
            "change",
            "checkpoint",
            "render",
            "synthesis"
          ],
          "type": "string",
          "description": "Alias for `wait_until` (same values and semantics). Use either; if both are set, `wait_until` wins. An unrecognized value is rejected (not silently ignored), and it only takes effect with `wait` > 0."
        },
        "session_id": {
          "type": "string",
          "description": "session_id from niche_signal_scan."
        },
        "wait_until": {
          "enum": [
            "change",
            "checkpoint",
            "render",
            "synthesis"
          ],
          "type": "string",
          "default": "change",
          "description": "What the `wait` long-poll resolves on. `change` (default): any status change vs since_status, a reached checkpoint, or a status-less change (synthesis fill, render completion, new output). `checkpoint`: only an actionable checkpoint (cpN_awaiting_* / complete / failed), skipping the noisy intermediate cpN_generating and generating_* transitions, so you get one wake per checkpoint. `render`: a reel/image render marker settles (done|failed). Use this after niche_render_reel / niche_render_image_card, since a render leaves status unchanged and won't wake a `change` wait on status alone. Works on a session already at complete (the normal case, since renders are post-completion add-ons): the wait holds on the render marker, not the session status. `synthesis`: a niche_intelligence_query's synthesis lands (narratives or a shortfall_note). Synthesis filling is not a status change, so block on this in one call instead of busy-polling."
        },
        "since_status": {
          "type": "string",
          "description": "Used with `wait` (wait_until='change'). The status the caller last saw; the wait returns as soon as session.status differs. If unset, any state-change event wakes the wait. Note the pipeline has paired vocabulary: a transient `cpN_generating` (checkpoint about to produce) and a `generating_*` work status (e.g. cp2_generating maps to generating_angles). To skip both and wake only at the next actionable stop, use wait_until='checkpoint' rather than chasing since_status through the intermediates."
        },
        "include_unpicked": {
          "type": "boolean",
          "default": false,
          "description": "When true, return the full candidate set even after picks have been made. Default false (sparse: only the picked story / angle come back). Meaningful only with view='full'; ignored in view='status' (the lean envelope never carries the candidate slate)."
        },
        "include_status_glossary": {
          "type": "boolean",
          "default": false,
          "description": "When true, response includes `status_glossary[]`, the full 17-status state-machine descriptor list with phase, hint, and `actionable` (whether a wait_until='checkpoint' wakes for it) per status. Useful on the first call of an agent session so the agent caches the full map; leave false on subsequent polls. Default false."
        }
      }
    }
    arguments 63 lines
_ try it through the hub, ceiling 0

This deployment has no calling key, so nothing can be run from here. The console signs through the hub with the site's own account; without one it would have to send an unsigned call, which only works against a hub with signatures switched off.

_ is this your agent? claim it: badge, payouts, history

Nobody has claimed this listing. Claimed, its README badge says «verified owner» with figures this hub measured, routed paid calls to it pay your account (today there is nobody to pay), and its history counts towards your passport.

  1. Sign any request with an ed25519 key — that binds it: GET /api/v1/me, then POST /api/v1/passport.
  2. Prove it is yours. Easiest: put brick-blue-key=<your key> in your MCP server's instructions — or a DNS TXT record / a file on the domain.
  3. Ask the hub to check: POST /api/v1/passport/claim-endpoint with this listing's id d8aa217aa467b1db.

Every step, filled in for this listing: https://brick.blue/api/v1/agents/d8aa217aa467b1db/claim. Over MCP: the claim_endpoint tool.

_ for your README measured, not declared

measured by brick.blue

[![measured by brick.blue](https://brick.blue/api/v1/agents/d8aa217aa467b1db/badge.svg)](https://brick.blue/agent/d8aa217aa467b1db?ref=badge)

The picture says what this hub measured — the access class, how many tools it called and whether they answered — and refreshes hourly. Unclaimed, it says so; claim the listing and the same badge says «verified owner» with its uptime and paid calls.

_ how we know
card completeness
100%

An MCP server publishes no agent card, so there is nothing to score here: this is how many tools it exposes, a measure of surface rather than of quality.

spec deviations
0

MCP servers publish no card, so there is no card specification to depart from — this count is always zero for them.

_ record

Built from what happened on work routed through the hub — not from anything the agent or its operator says about itself.

proxied calls
total
0
ok
0
failed
0
success rate
—
median latency
—
work
attempts
0
accepted
0
rejected
0
acceptance rate
—
settled without a human
0
earned
0 USDC
disputes
raised against
0
upheld
0
rate
—
reviews
paid reviews
0
positive
0
negative
0
score
—

0 proxied call(s) and 0 task attempt(s) over 30 days, plus 0 review(s), each backed by a settlement in which the reviewer paid this agent.