NicheDB
Sources in, feeds out: an open, ever-growing database of real-time public data, enriched.
我该使用它吗
质量与安全性
发现(3)
- LOW在 recent_items 中
- LOW在 follow_feed 中
- LOW在 get_tld 中
基于对工具定义和协议合规性的自动分析。
上下文开销
这是每次将服务器的工具加载到模型上下文窗口时所消耗的大致 token 数。数值越高,可用于其他任务的注意力就越少。
安装
一键安装
将以下内容添加到你的 `claude_desktop_config.json` 文件中:
{
"mcpServers": {
"nichedb": {
"command": "npx",
"args": [
"@profullstack/nichedb"
]
}
}
}可运行的软件包
0.1.0stdio远程端点
https://nichedb.dev/mcpstreamable-http它能做什么
工具清单
工具(26)
⚪stats
What this deployment holds: collections, sources, items, items added today, feeds.
输入模式
{
"type": "object",
"properties": {}
}🟢list_collections
The collections (niches) with their source, feed and item counts.
输入模式
{
"type": "object",
"properties": {}
}🟡list_adapters
Every adapter this deployment can run, with the config fields each takes. Use before add_source.
输入模式
{
"type": "object",
"properties": {}
}🟢list_enrichers
Every enricher (YouTube videos, Wikipedia, repo stats, downloads, company profiles, TL;DRs) and which collections turn it on by default. Items carry their results under `enrichment`.
输入模式
{
"type": "object",
"properties": {}
}🟢list_sources(collection)
Sources with status, last run and item counts. Optionally one collection.
输入模式
{
"type": "object",
"properties": {
"collection": {
"type": "string",
"description": "Collection slug, e.g. games"
}
}
}🟢list_feeds(collection)
Public feeds, most followed first. Optionally one collection.
输入模式
{
"type": "object",
"properties": {
"collection": {
"type": "string",
"description": "Collection slug"
}
}
}⚪feed_items(lat, long, radius, unit, bbox, ...)
What a feed selects, newest first. Page with before_id.
输入模式
{
"type": "object",
"properties": {
"lat": {
"type": "number",
"minimum": -90,
"maximum": 90,
"description": "Query center latitude; requires long"
},
"long": {
"type": "number",
"minimum": -180,
"maximum": 180,
"description": "Query center longitude; requires lat"
},
"radius": {
"type": "number",
"exclusiveMinimum": 0,
"description": "Default 10; maximum 1000 km"
},
"unit": {
"type": "string",
"enum": [
"km",
"mi"
],
"description": "Default km"
},
"bbox": {
"type": "string",
"description": "west,south,east,north; west > east crosses the antimeridian"
},
"sort": {
"type": "string",
"enum": [
"id",
"published",
"updated",
"distance"
]
},
"feed": {
"type": "string",
"description": "Feed slug"
},
"limit": {
"type": "integer",
"description": "Default 30, max 200"
},
"before_id": {
"type": "integer",
"description": "Keyset cursor; cannot combine with distance sorting"
},
"offset": {
"type": "integer",
"description": "Distance pagination offset"
}
},
"required": [
"feed"
]
}⚪recent_items(lat, long, radius, unit, bbox, ...)
Newest items, optionally narrowed to a collection, source or kind.
输入模式
{
"type": "object",
"properties": {
"lat": {
"type": "number",
"minimum": -90,
"maximum": 90,
"description": "Query center latitude; requires long"
},
"long": {
"type": "number",
"minimum": -180,
"maximum": 180,
"description": "Query center longitude; requires lat"
},
"radius": {
"type": "number",
"exclusiveMinimum": 0,
"description": "Default 10; maximum 1000 km"
},
"unit": {
"type": "string",
"enum": [
"km",
"mi"
],
"description": "Default km"
},
"bbox": {
"type": "string",
"description": "west,south,east,north; west > east crosses the antimeridian"
},
"sort": {
"type": "string",
"enum": [
"id",
"published",
"updated",
"distance"
]
},
"collection": {
"type": "string",
"description": "Collection slug"
},
"source": {
"type": "string",
"description": "Source slug"
},
"kind": {
"type": "string",
"description": "Item kind"
},
"limit": {
"type": "integer",
"description": "Default 30, max 200"
},
"before_id": {
"type": "integer",
"description": "Keyset cursor; cannot combine with distance sorting"
},
"offset": {
"type": "integer",
"description": "Distance pagination offset"
}
}
}⚪upcoming(lat, long, radius, unit, bbox, ...)
Items dated in the future (releases, launches, deadlines), soonest first.
输入模式
{
"type": "object",
"properties": {
"lat": {
"type": "number",
"minimum": -90,
"maximum": 90,
"description": "Query center latitude; requires long"
},
"long": {
"type": "number",
"minimum": -180,
"maximum": 180,
"description": "Query center longitude; requires lat"
},
"radius": {
"type": "number",
"exclusiveMinimum": 0,
"description": "Default 10; maximum 1000 km"
},
"unit": {
"type": "string",
"enum": [
"km",
"mi"
],
"description": "Default km"
},
"bbox": {
"type": "string",
"description": "west,south,east,north; west > east crosses the antimeridian"
},
"sort": {
"type": "string",
"enum": [
"id",
"published",
"updated",
"distance"
]
},
"collection": {
"type": "string",
"description": "Collection slug"
},
"days": {
"type": "integer",
"description": "Horizon, default 30"
},
"limit": {
"type": "integer",
"description": "Default 50"
}
}
}🟢search_items(lat, long, radius, unit, bbox, ...)
Full-text search over titles, summaries and tags. Use this first when you know a name.
输入模式
{
"type": "object",
"properties": {
"lat": {
"type": "number",
"minimum": -90,
"maximum": 90,
"description": "Query center latitude; requires long"
},
"long": {
"type": "number",
"minimum": -180,
"maximum": 180,
"description": "Query center longitude; requires lat"
},
"radius": {
"type": "number",
"exclusiveMinimum": 0,
"description": "Default 10; maximum 1000 km"
},
"unit": {
"type": "string",
"enum": [
"km",
"mi"
],
"description": "Default km"
},
"bbox": {
"type": "string",
"description": "west,south,east,north; west > east crosses the antimeridian"
},
"sort": {
"type": "string",
"enum": [
"id",
"published",
"updated",
"distance"
]
},
"q": {
"type": "string",
"description": "Query"
},
"collection": {
"type": "string",
"description": "Collection slug"
},
"kind": {
"type": "string",
"description": "Item kind"
},
"limit": {
"type": "integer",
"description": "Default 20, max 100"
}
},
"required": [
"q"
]
}⚪match_items(lat, long, radius, unit, bbox, ...)
Which title, channel or fixture is this name? Give a file name, a release name or a playlist entry ("Top.Gun.Maverick.2022.1080p.mkv", "US: ESPN2 HD"); it is cleaned (year, season and episode, quality tags, playlist decorations) and matched by similarity. A matchup ("NFL: Chiefs vs Bills", "Lakers @ Celtics", "Rangers at Celtic 19:45") is answered by the fixture whose two teams those are, kicking off between 36 hours ago and 7 days ahead unless date narrows it. Each result carries a score in 0..1. Use screen for films and TV, channels for television channels, sports for fixtures.
输入模式
{
"type": "object",
"properties": {
"lat": {
"type": "number",
"minimum": -90,
"maximum": 90,
"description": "Query center latitude; requires long"
},
"long": {
"type": "number",
"minimum": -180,
"maximum": 180,
"description": "Query center longitude; requires lat"
},
"radius": {
"type": "number",
"exclusiveMinimum": 0,
"description": "Default 10; maximum 1000 km"
},
"unit": {
"type": "string",
"enum": [
"km",
"mi"
],
"description": "Default km"
},
"bbox": {
"type": "string",
"description": "west,south,east,north; west > east crosses the antimeridian"
},
"sort": {
"type": "string",
"enum": [
"id",
"published",
"updated",
"distance"
]
},
"q": {
"type": "string",
"description": "The name as written"
},
"collection": {
"type": "string",
"description": "Collection slug: screen, channels or sports"
},
"kind": {
"type": "string",
"description": "Item kind: title, channel, fixture"
},
"year": {
"type": "integer",
"description": "A year to prefer, when known"
},
"date": {
"type": "string",
"description": "A day (YYYY-MM-DD) to look for a fixture on, plus a day either side"
},
"limit": {
"type": "integer",
"description": "Default 5, max 50"
}
},
"required": [
"q"
]
}🟢get_item(id)
One item with its full adapter payload.
输入模式
{
"type": "object",
"properties": {
"id": {
"type": "integer",
"description": "Item id"
}
},
"required": [
"id"
]
}⚪population(key, zip, q, level, limit, ...)
Population and demography, drilled down from the world to the ZIP code. Give a `key` (us, us-ca, us-ca-los-angeles, gb, gb-england-london), a US `zip`, or a place name in `q`; no argument is the world. Answers with the area (population, year, measures: age, income, home value, rent, poverty, education, unemployment, race and Hispanic origin for the US; growth, age structure, births, deaths, fertility, life expectancy, migration, GDP per head and Gini for countries), how many areas of each level it contains, and the largest of its children at `level` (country, state, city or zip). Sources: World Bank, US Census ACS 5-year, GeoNames.
输入模式
{
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Area key, e.g. us, us-ca, us-ca-los-angeles, us-90210, de (optional)"
},
"zip": {
"type": "string",
"description": "A US ZIP code (optional)"
},
"q": {
"type": "string",
"description": "A place name to look up, e.g. Springfield (optional)"
},
"level": {
"type": "string",
"description": "Which children to list: country, state, city or zip (optional)"
},
"limit": {
"type": "integer",
"description": "Children to list, default 20, max 500"
},
"offset": {
"type": "integer",
"description": "Skip this many children, for paging"
}
}
}🟡create_feed(lat, long, radius, unit, bbox, ...)
Save a query as a feed (needs a key). Sources, kinds and tags narrow; q is a text match; upcoming keeps only future-dated items.
输入模式
{
"type": "object",
"properties": {
"lat": {
"type": "number",
"minimum": -90,
"maximum": 90,
"description": "Query center latitude; requires long"
},
"long": {
"type": "number",
"minimum": -180,
"maximum": 180,
"description": "Query center longitude; requires lat"
},
"radius": {
"type": "number",
"exclusiveMinimum": 0,
"description": "Default 10; maximum 1000 km"
},
"unit": {
"type": "string",
"enum": [
"km",
"mi"
],
"description": "Default km"
},
"bbox": {
"type": "string",
"description": "west,south,east,north; west > east crosses the antimeridian"
},
"sort": {
"type": "string",
"enum": [
"id",
"published",
"updated",
"distance"
]
},
"collection": {
"type": "string",
"description": "Collection slug"
},
"name": {
"type": "string",
"description": "Feed name"
},
"description": {
"type": "string",
"description": "Optional"
},
"sources": {
"type": "array",
"items": {
"type": "string"
},
"description": "Source slugs"
},
"kinds": {
"type": "array",
"items": {
"type": "string"
},
"description": "Item kinds"
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "Tags, any match"
},
"q": {
"type": "string",
"description": "Text match"
},
"upcoming": {
"type": "boolean"
},
"enrichers": {
"type": "array",
"items": {
"type": "string"
},
"description": "Enrichers to show; omit for the collection defaults"
},
"public": {
"type": "boolean",
"description": "Default true"
}
},
"required": [
"collection",
"name"
]
}⚪follow_feed(feed, channels, webhook_url, webhook_secret)
Follow a feed as the key owner (needs a key). Channels: webpush, email, webhook.
输入模式
{
"type": "object",
"properties": {
"feed": {
"type": "string",
"description": "Feed slug"
},
"channels": {
"type": "array",
"items": {
"type": "string"
},
"description": "Default webpush,email"
},
"webhook_url": {
"type": "string",
"description": "For the webhook channel"
},
"webhook_secret": {
"type": "string",
"description": "Shared secret the receiver verifies with"
}
},
"required": [
"feed"
]
}🟡submit_feed(url, collection, note, email)
Suggest an RSS or Atom feed for the index. No key needed. An admin reviews every suggestion before anything is fetched; approved podcast feeds are handed to rssamplifier, everything else becomes a source here.
输入模式
{
"type": "object",
"properties": {
"url": {
"type": "string",
"description": "The feed URL, starting with https://"
},
"collection": {
"type": "string",
"description": "Collection slug it belongs in (optional; an admin decides otherwise)"
},
"note": {
"type": "string",
"description": "Why it belongs here: who publishes it, what it covers (optional)"
},
"email": {
"type": "string",
"description": "Where to hear back, if you are not sending a key (optional)"
}
},
"required": [
"url"
]
}🟡search_profiles(q, since, limit)
People: one entry per person assembled from every app that serves their OpenProfile.md (podcasters from p0dcasters, public profiles from OutreachGraph). Search by name, headline or anything in the document; newest change first. Each answer carries the page, the openprofile.md URL, accounts, topics, Broadcast shows and the Guest section.
输入模式
{
"type": "object",
"properties": {
"q": {
"type": "string",
"description": "Text to match against the name, headline and document (optional)"
},
"since": {
"type": "string",
"description": "ISO time: only profiles changed after it (optional)"
},
"limit": {
"type": "integer",
"description": "Default 30, max 200"
}
}
}🟢get_profile(ref)
One person by id, `<slug>-<id>` or handle: the parsed view and the OpenProfile.md as served.
输入模式
{
"type": "object",
"properties": {
"ref": {
"type": "string",
"description": "Profile id, slug-id or handle"
}
},
"required": [
"ref"
]
}🟢claim_profile(ref, email)
Claim a profile as the key owner (needs a key). Proven when the key owner’s email is one the profile lists, or when the person’s site or show page links back to the profile’s nichedb page. An admin may claim on behalf of an email.
输入模式
{
"type": "object",
"properties": {
"ref": {
"type": "string",
"description": "Profile id, slug-id or handle"
},
"email": {
"type": "string",
"description": "Admins only: claim it for this email"
}
},
"required": [
"ref"
]
}🟡update_profile(ref, markdown, name, headline, identity, ...)
Edit a profile you own (needs a key). Send `markdown`, a whole OpenProfile.md that replaces what you wrote before, or any of `name`, `headline`, `identity` (key: value, null removes), `sections` (name: body, `none` removes), `handle`, `public`. What you write wins over every source and survives every re-read.
输入模式
{
"type": "object",
"properties": {
"ref": {
"type": "string",
"description": "Profile id, slug-id or handle"
},
"markdown": {
"type": "string",
"description": "A complete OpenProfile.md"
},
"name": {
"type": "string",
"description": "The name"
},
"headline": {
"type": "string",
"description": "One line"
},
"identity": {
"type": "object",
"description": "Identity keys: Kind, Web, Email, Location, ...; null removes"
},
"sections": {
"type": "object",
"description": "Section bodies by name (accounts, topics, broadcast, guest, ...); the word none removes one"
},
"handle": {
"type": "string",
"description": "Your URL: /c/profiles/<handle>"
},
"public": {
"type": "boolean",
"description": "Listed and pulled by other directories"
}
},
"required": [
"ref"
]
}🟡add_source(adapter, collection, name, config, cadence_minutes)
Add a source: an adapter with a config, fetched on a schedule (needs a key; admins and Pro). Call list_adapters first for the fields.
输入模式
{
"type": "object",
"properties": {
"adapter": {
"type": "string",
"description": "Adapter name, e.g. github-releases"
},
"collection": {
"type": "string",
"description": "Collection slug; defaults to the adapter's"
},
"name": {
"type": "string",
"description": "Display name"
},
"config": {
"type": "object",
"description": "Adapter config fields"
},
"cadence_minutes": {
"type": "integer",
"description": "5 to 1440"
}
},
"required": [
"adapter"
]
}🟢run_source(source)
Fetch a source now instead of waiting for its schedule (needs a key; owner or admin).
输入模式
{
"type": "object",
"properties": {
"source": {
"type": "string",
"description": "Source slug"
}
},
"required": [
"source"
]
}🟢search_tlds(q, type, manager, registrar, max_renew, ...)
Top-level domains: every label in IANA's root, with type, registry, RDAP server and each registrar's one-year register/renew/transfer price (Porkbun, Dynadot, Cloudflare, OVHcloud). Sorted by renewal by default, because the first year is a promotion. `best` is the cheapest USD price across registrars; with `registrar` it is that registrar's own price in its currency. Answers carry facet counts. `trap: true` keeps only labels that renew at 2x the first year or more.
输入模式
{
"type": "object",
"properties": {
"q": {
"type": "string",
"description": "Text in the label, its Unicode form or the registry name (optional)"
},
"type": {
"type": "string",
"description": "generic, country-code, sponsored, generic-restricted, infrastructure, test; comma separated (optional)"
},
"manager": {
"type": "string",
"description": "Exact registry name, as IANA writes it (optional)"
},
"registrar": {
"type": "string",
"description": "porkbun, dynadot, cloudflare, ovh (optional): only labels it sells, at its prices"
},
"max_renew": {
"type": "number",
"description": "Highest renewal price (optional)"
},
"max_register": {
"type": "number",
"description": "Highest first-year price (optional)"
},
"trap": {
"type": "boolean",
"description": "Only labels renewing at 2x the first year or more"
},
"idn": {
"type": "boolean",
"description": "true: internationalised labels only; false: ASCII only"
},
"status": {
"type": "string",
"description": "delegated (default), removed, or all"
},
"sort": {
"type": "string",
"description": "renew (default), register, transfer, restore, ratio, tld, registrars, type, manager, first_seen"
},
"order": {
"type": "string",
"description": "asc or desc"
},
"limit": {
"type": "integer",
"description": "Default 50, max 500"
},
"offset": {
"type": "integer",
"description": "Default 0"
}
}
}🟡get_tld(tld)
One top-level domain: type, registry, RDAP server, when it entered or left the root, every registrar price (register, renew, transfer, restore, promotions, privacy, restrictions) and its change history.
输入模式
{
"type": "object",
"properties": {
"tld": {
"type": "string",
"description": "The label, with or without the dot; Unicode or xn-- both work"
}
},
"required": [
"tld"
]
}🟢tld_changes(since, change, limit)
Top-level domains added to or removed from IANA's root, newest first, with the IANA list version each happened in. Nobody else publishes this diff.
输入模式
{
"type": "object",
"properties": {
"since": {
"type": "string",
"description": "ISO time: only changes after it (optional)"
},
"change": {
"type": "string",
"description": "added, removed or returned (optional)"
},
"limit": {
"type": "integer",
"description": "Default 100, max 1000"
}
}
}🟢check_domain(name, tlds)
Is a domain name registered? Asks each registry over RDAP. Give `name` as a full name (foo.watches), or a bare word with `tlds` (foo + com,dev,io), or several names comma separated. Each answer is registered (with registrar and expiry), not_registered, or unknown. not_registered means the registry holds no registration; the name may still be reserved or premium, so it is not a promise that it is for sale. unknown (no RDAP server, a timeout, a 429) is never a yes. Each answer carries the cheapest known USD price for its ending.
输入模式
{
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "foo.watches, or foo, or a.com,b.dev"
},
"tlds": {
"type": "string",
"description": "Endings to try a bare word under, comma separated (optional)"
}
},
"required": [
"name"
]
}社区
证据