dark-mcp
Integrates with Telegram's client API via Telethon to discover channels, read allowed broadcast channels, search messages within permitted channels, and search public posts using free quota. Supports pagination and date filters for monitoring company exposure signals with source links and timestamps.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@dark-mcpcheck if acme.example appears in onion pages or Telegram threat channels"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
dark-mcp
Standalone MCP server for proactive company exposure research on onion pages and Telegram channels.
Search existing indexes for company names, domains, and aliases; inspect matching onion pages through Tor; retrieve relevant Telegram posts with source links and timestamps. Investigate early warning signals such as company targeting, exposed information, alleged data sales, and threat activity before an incident is known. The same tools can be called repeatedly by a monitoring agent or scheduled workflow.
Probing here means investigating sources and exposure signals. Findings should retain their evidence and uncertainty: a source's claim does not establish that an intrusion occurred.
Data sources
Source | Access | Required setup |
Onion discovery | Onion Search Engine API, over HTTPS | Provider API key |
Onion page content | Direct HTTP(S) through your Tor SOCKS proxy | Running Tor client |
Telegram channel posts | Telegram client API via Telethon | Your application credentials, local account login, permitted channels |
Local onion search | SQLite FTS index populated by fetches and bounded crawls | No external search key |
Discovery uses an existing search engine. You do not need to build your own onion index. The local index is optional and only covers pages this installation has collected. Search provider coverage and freshness are not independently verified.
Related MCP server: StealthMole MCP Server
Quick start
Requires Python 3.12+, uv, and Tor or Docker.
git clone https://github.com/superagent-ai/dark-mcp.git
cd dark-mcp
uv sync --locked
cp .env.example .envSet DARK_MCP_ONION_SEARCH_API_KEY in .env to enable discovery. Get your own key through the provider's account flow. This project does not create accounts or subscribe to paid plans for you.
Start Tor for direct page retrieval:
docker compose up -d --build tor
docker compose logs -f torWait for Bootstrapped 100%. The container health check only checks the SOCKS listener; it does not establish bootstrap completion. An existing local Tor process on port 9050 also works. If that port is in use, use your existing Tor process or change the Compose host port and DARK_MCP_TOR_PROXY together.
uv run dark-mcp serveThe default transport is stdio. Do not type into this process: connect an MCP client as shown below.
Connect an MCP client
Use the absolute path to your checkout; the working directory is where .env is read.
{
"mcpServers": {
"dark-mcp": {
"command": "uv",
"args": ["--directory", "/absolute/path/dark-mcp", "run", "dark-mcp", "serve"]
}
}
}For a client supporting local Streamable HTTP:
uv run dark-mcp serve --transport streamable-http --port 8000Connect to http://127.0.0.1:8000/mcp. HTTP binds to loopback only and has no application authentication. Keep it local; remote, multi-user deployment requires an authenticated gateway and isolated credentials/data per tenant.
Tools
Tool | Purpose |
| Configuration and local index count; does not test connectivity |
| Discover onion mentions using the search provider; returns |
| Fetch a v3 onion page over Tor, extract text/links, update local index |
| Collect at most 10 pages from seed onions and same-host links |
| Full text search of collected pages; |
| Discover channels; requires global search to be enabled |
| Read an allowed broadcast channel |
| Search an allowed channel; |
| Public post search using free quota only; requires global search to be enabled |
Dates must include a timezone, for example 2026-10-18T00:00:00Z. Telegram message limits are 1–100; channel discovery is 1–50. Use the returned next_before_id, next_cursor, or next_page for pagination. Search API page size is provider controlled.
Tools return structured ok, results/page, coverage information, and errors with stable codes. Rate limit errors include a retry delay when Telegram provides one. Missing configuration and source failures are explicit errors, never empty results disguised as successful searches.
Example proactive company investigation
For a fictional company called Acme with domain acme.example:
Call
search_onionseparately for"Acme",acme.example, and relevant brand aliases. These are search strings; matching behavior is controlled by the provider.Inspect relevant results with
fetch_onion. Record the exact excerpt, URL, and collection time. The search API does not guarantee publication dates; an old indexed page is not necessarily a new disclosure.Search selected Telegram channels for the same identifiers using
search_telegram_messages, with the start of the research window insince. Where separately permitted, use public post search to discover additional sources.Assess whether the text actually refers to the company. A mention or an alleged leak is not a confirmed compromise. Cite the evidence and retain uncertainty.
For repeated monitoring, the calling workflow should persist seen source URLs, Telegram channel/message IDs, and content hashes; compare each run and notify on new or changed evidence. The server supplies data access, not a built-in scheduler or alert delivery service.
The first version searches text only. It does not OCR images, download attachments, bypass authentication/CAPTCHAs, join channels, post messages, or verify the authenticity of leaked data.
Telegram setup
Telegram's API terms and content licensing terms restrict using platform data for AI, including deployment. Public accessibility and an authenticated session do not grant those rights. Enable this connector only where an applicable permission arrangement or consent exception covers your intended use. The configuration switches are operational controls, not a grant of permission.
Register your own Telegram application at my.telegram.org.
Set
DARK_MCP_TELEGRAM_API_IDandDARK_MCP_TELEGRAM_API_HASHlocally in.env.Run the login command yourself in a terminal:
uv run dark-mcp telegram-loginSet the permitted channels and enable the connector:
DARK_MCP_TELEGRAM_ENABLED=true
DARK_MCP_TELEGRAM_CHANNELS=["permitted_channel","-1001234567890"]Global channel discovery and public post search are disabled separately. Where your permission arrangement covers these searches, set DARK_MCP_TELEGRAM_GLOBAL_SEARCH=true. Public post search may require Premium and available free quota. The server never authorizes spending Telegram Stars.
Private channels require the account to already have access. Read/search tools accept broadcast channels only. Credentials and the account session stay server-side; login is never exposed as an MCP tool. Treat the session file as an account credential. Revoke a session through Telegram's Devices settings if compromised.
Docker-only usage
docker compose build
docker compose up -d tor
# Interactive account login, if using Telegram:
docker compose run --rm mcp telegram-login
# MCP stdio, suitable for an MCP client's command/args:
docker compose run --rm --no-deps -T mcp serveThe MCP client must run that command in this checkout. Persistent container data and sessions live in the mcp-data volume; local uv runs use DARK_MCP_DATA_DIR instead. Do not run multiple processes against the same Telegram session. Tor's SOCKS port is published only to the host loopback address.
Local onion corpus
For sources you already know, populate the optional local corpus without a discovery key:
uv run dark-mcp crawl 'http://YOUR_VALID_V3_ADDRESS.onion/' --max-pages 5
uv run dark-mcp search 'company name'Pages are fetched through Tor, with v3 address checksums checked, redirects validated, robots.txt respected, per-host pacing, request deadlines, and response limits. Crawling follows same-host links; cross-host redirects are still restricted to valid onion destinations and checked against the destination's robots.txt.
Configuration and data
All settings use the DARK_MCP_ prefix; see .env.example. Environment variables override .env. The default data directory is ~/.local/share/dark-mcp; the example uses ./data.
The local SQLite database stores extracted onion content unencrypted on disk. Telegram posts are returned on demand and are not saved by the server. Clients may retain tool responses. Clear the local corpus by stopping the server and removing onions.sqlite3 and its WAL files from your configured data directory. Back up or remove Telegram session files separately.
Search queries sent to the discovery API go to that provider over ordinary HTTPS. Direct onion fetching goes through the configured Tor proxy; it does not fall back to direct internet access. Telegram uses its normal client connection, not Tor.
All retrieved text is untrusted data. HTML scripts are stripped, but this does not eliminate prompt injection. The calling agent must treat source text as evidence, never instructions.
Development
uv sync --locked
uv run ruff check .
uv run ruff format --check .
uv run pytest -q
uv buildTests cover MCP initialization and stdio, provider response contracts and errors, onion URL/redirect/response boundaries, indexing, and Telegram access controls/pagination/rate limits. Default tests make no live network calls. Authenticated provider search and Telegram access require operator credentials and separate live verification.
Available Tools
9 toolscrawl_onionB
Index up to 10 pages from seed onions and same-host links, respecting robots.txt.
| Name | Required | Description | Default |
|---|---|---|---|
| seeds | Yes | ||
| max_pages | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the write profile (readOnlyHint=false, destructiveHint=false) and open-world scope, so the bar is lower. The description nonetheless adds real behavioral context beyond them: link-following is restricted to same-host links and robots.txt is honored, which tells the agent this is a bounded, polite crawl rather than an unbounded spider.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, zero filler, with the scope and the robots.txt constraint front-loaded. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need no explanation, and the description covers scope, page cap, and robots compliance. It is silent on indexing semantics (does it overwrite or append to an existing index?), rate limits, and error behavior when a seed is unreachable — gaps that matter for an open-world crawler.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description carries the full burden for the two parameters. It loosely maps 'seed onions' to seeds and 'up to 10 pages' to max_pages, but never states that seeds is an array of .onion addresses, and the stated 10-page cap conflicts with a max_pages default of 5, leaving the agent unsure which bound actually applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Index/crawl), the resource (onion pages), and the scope (seed onions plus same-host links, capped at 10 pages). It is clearly distinguishable from fetch_onion and search_onion in spirit, though it never names a sibling explicitly, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the tool builds/updates an index rather than retrieving a page, but gives no explicit when-to-use guidance or contrast with fetch_onion (single page) or search_onion (query the index). An agent must infer the routing decision from the verb alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fetch_onionA
Read a v3 onion page through Tor and update the local search index. Returns untrusted text.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false, openWorldHint=true, destructiveHint=false, and the description explains why it isn't read-only ('update the local search index') while adding two things the annotations cannot convey: the Tor transport and the fact that the returned content is untrusted text (a prompt-injection hazard). It stops short of covering failure modes, latency/timeouts, or rate limits for an open-world fetch.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero filler, with the primary action front-loaded and the side effect and the security caveat following in priority order.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return shape need not be explained, and the description still flags the one thing an agent must know about the output ('untrusted text'). For a mutating, open-world fetch it omits operational realities such as expected latency, timeouts, or whether the index update is transactional, keeping it just short of full coverage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% and the single 'url' parameter carries no description, so the description must compensate. 'v3 onion page' does implicitly constrain the input to a v3 .onion address rather than arbitrary or clearnet URLs, but no format example or validation rule is given.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Read a v3 onion page through Tor') and adds a consequential detail: it also 'update[s] the local search index'. This distinguishes it in spirit from crawl_onion (bulk, presumably) and search_onion (query, no fetch), but it never names those siblings, so the differentiation is left to inference.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The single-page framing ('a v3 onion page') implies this is the one-off fetch rather than the crawler, which is useful implicit routing. There is no explicit when-to-use/when-not and no named alternative among crawl_onion, search_onion, or search_onion_cache, so the agent must guess at the boundary.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_statusARead-only
Report configuration and indexed corpus size. Does not probe network connectivity.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so safety is covered. The description adds a genuinely useful behavioral fact beyond the annotations: it performs no network I/O, so an agent knows this is a fast, local, dependency-free call. It stops short of stating cost, caching, or failure modes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, zero filler, with the positive statement of purpose front-loaded and the scoping caveat immediately after. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need no explanation, and zero parameters mean no argument guidance is required. What remains is adequately covered; only the vagueness of 'configuration' keeps this from being fully complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate. Baseline 4 applies; the schema fully covers the (empty) argument object.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a concrete verb and resource: 'Report configuration and indexed corpus size.' It also carves itself out from the network-facing siblings (fetch/crawl/search_onion) with 'Does not probe network connectivity.' The word 'configuration' is slightly generic, but the resource is identifiable and differentiated from siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: the negative clause hints this is the lightweight local alternative to the network-probing tools, but no explicit when-to-use, prerequisites, or named alternative is given. An agent can infer intent but isn't routed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_telegram_channelBRead-only
Read posts from an allowed broadcast channel. Paginate using next_before_id.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| channel | Yes | ||
| before_id | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, openWorldHint=true, and destructiveHint=false, so safety is covered. The description adds two useful facts beyond them: reads are limited to an *allowed* channel (an access constraint) and pagination flows through next_before_id. It does not describe rate limits, error behavior, or result ordering.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, scoping first and pagination second, with no filler. Slightly penalized because the pagination hint uses a parameter name (next_before_id) that does not exist in the schema, which costs the reader a moment of reconciliation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained. But with 0% schema coverage the description should at least characterize limit and the accepted channel format, and it does not; the agent can call it, but not confidently well.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so all three parameters rely on the description. It clarifies that channel must be an allowed broadcast channel and that before_id drives pagination (though it calls it next_before_id, a name mismatch), but says nothing about limit. Partial compensation for a fully undocumented schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Read) and resource (posts from a broadcast channel), which is clear and actionable. It does not, however, explicitly distinguish itself from sibling search_telegram_posts or search_telegram_messages, leaving the read-vs-search split to inference.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
"Paginate using next_before_id" is the only procedural hint and no when-to-use or when-not-to-use guidance is given. The presence of search_telegram_posts, search_telegram_messages, and search_telegram_channels as siblings makes the absence of routing guidance a real gap.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_onionBRead-only
Discover mentions and onion URLs through Onion Search Engine. Requires a provider key.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | ||
| query | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false and openWorldHint=true, so the safety profile is covered structurally. The description adds one useful behavioral fact not in annotations — the provider-key requirement. It says nothing about rate limits, result caps or pagination behavior, so it adds modest value beyond the structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the purpose and then the prerequisite. No waste, though the terseness comes at the cost of useful detail rather than being a virtue of tight editing.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be described. But for a paginated external search with 0% parameter documentation, the description omits pagination semantics, result scope, and any routing to the cache sibling; it is minimally viable rather than complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% for both parameters, so the description must carry the burden and it does not: neither 'query' nor 'page' is explained, and the paging/default behavior of page is left entirely undocumented. It adds no meaning beyond the bare schema property names.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb-plus-resource: 'Discover mentions and onion URLs through Onion Search Engine.' An agent can grasp what it returns. However it does not distinguish itself from siblings such as search_onion_cache or fetch_onion/crawl_onion, so the differentiation is left to inference.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The only guidance is the prerequisite 'Requires a provider key.' There is no statement of when to use this search versus search_onion_cache, crawl_onion or fetch_onion, and no indication of what happens without a key.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_onion_cacheBRead-only
Search locally indexed onion pages. since filters collection time, not publication time.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes | ||
| since | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, destructiveHint=false and openWorldHint, so safety is covered. The description adds a genuinely useful behavioral caveat that annotations cannot express — that `since` filters collection time rather than publication time, which changes how an agent interprets results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the action and followed by the one subtle constraint. Nothing is wasted, though the extreme brevity leaves gaps that more structure could have addressed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be described, and the `since` clarification is valuable. Still missing: the expected format of `since`, the meaning of `limit`, and any query syntax expectations for a search tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry the semantics. It explains only `since` (collection time vs publication time) and says nothing about query matching behavior or what `limit` controls, leaving two of three parameters undocumented in both places.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Search locally indexed onion pages"), and the phrase "locally indexed" implicitly separates it from the live-looking sibling search_onion. It stops short of explicitly naming the alternative or clarifying whether this searches a distinct corpus, so it lands at clear-but-undifferentiated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The word "locally indexed" hints that this is the cache-backed path, but there is no explicit when-to-use-vs-search_onion guidance and no stated prerequisites (index freshness, crawl state). Usage is implied rather than directed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_telegram_channelsCRead-only
Discover channels. Requires Telegram global search to be enabled by the operator.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish this is a safe, read-only, open-world operation. The description adds one genuinely useful behavioral fact not in the annotations: the operator must have enabled Telegram global search. It says nothing about result limits, ranking, or failure behavior when global search is disabled.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the purpose and then the prerequisite. No filler, though the brevity comes at the cost of the missing guidance rather than being efficient density.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the operator prerequisite is covered. However, with 0% schema description coverage and four closely related Telegram siblings, the definition leaves both parameter meaning and tool selection underspecified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% for two parameters (required query, optional limit with default 10), so the schema does not compensate. The description supplies no meaning at all for either parameter, leaving the agent to infer query syntax and limit semantics from the names alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
"Discover channels" conveys a search-like verb and a resource, and the tool name clarifies it is Telegram channels. But the phrasing is close to a restatement of the name and never says it returns channels matching a query, nor does it distinguish itself from the four sibling Telegram tools (search_telegram_messages, search_telegram_posts, read_telegram_channel).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The only guidance is an environmental prerequisite (global search enabled by the operator). There is no statement of when to pick this over search_telegram_messages, search_telegram_posts, or read_telegram_channel, and no exclusions or fallback behavior.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_telegram_messagesCRead-only
Search an allowed channel's text posts. since is a timezone-aware publication date.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes | ||
| since | No | ||
| channel | Yes | ||
| before_id | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, and non-destructive, so the safety profile is covered. The description adds one useful bit of context ('allowed channel' scope) but says nothing about result ordering, pagination behavior, or rate/access limits implied by limit/before_id.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the core action and no wasted words. It is efficient, though the extreme brevity is part of the reason other dimensions are thin.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 5-parameter, 0%-coverage search tool with a sibling that overlaps its purpose, this is inadequate. An output schema exists so return values needn't be explained, but the channel identifier format, query semantics, and pagination via before_id/limit are left entirely to inference.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% across 5 parameters. The description only clarifies one parameter ('since is a timezone-aware publication date'), leaving query, channel, limit, and before_id completely undocumented in either the schema or the description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Search an allowed channel's text posts.' This is a concrete retrievable action. However, it does not distinguish itself from the sibling search_telegram_posts, which appears to cover nearly the same ground, leaving the agent to guess which to call.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The only guidance is the precondition 'an allowed channel,' which hints at an access constraint. There is no statement of when to use this over search_telegram_posts, read_telegram_channel, or search_telegram_channels, and no exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_telegram_postsBRead-only
Search public channel posts with free quota only. Requires global search to be enabled.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes | ||
| cursor | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, openWorldHint=true, destructiveHint=false, so the safety profile is covered. The description adds a real behavioral constraint (free quota only) and a prerequisite (global search enabled), but says nothing about rate limits, pagination, or what the quota restriction means in practice.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with no filler, and the key scoping constraint is front-loaded. It is tight, though the brevity comes at the cost of detail handled in other dimensions.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need no explanation, and the enabled-global-search prerequisite is stated. However, the posts-versus-messages sibling ambiguity and the fully undocumented parameters leave gaps for an agent trying to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% across three parameters, so the description must carry the burden and does not: query, limit, and cursor are entirely unexplained. Nothing indicates default page size, cursor pagination behavior, or query syntax.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clear verb 'Search' plus resource 'public channel posts', with a scoping constraint ('free quota only'). It does not differentiate itself from the close sibling search_telegram_messages, leaving the posts-vs-messages distinction to inference.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Adds a precondition ('Requires global search to be enabled') that shapes when the call can succeed, but gives no guidance on choosing this over search_telegram_messages or search_telegram_channels. Usage context is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
9 tool updates
v0.1.0- First observed
crawl_onion - First observed
fetch_onion - First observed
get_status - First observed
read_telegram_channel - First observed
search_onion - First observed
search_onion_cache - First observed
search_telegram_channels - First observed
search_telegram_messages - First observed
search_telegram_posts
TDQS
Scored across 9 tools
The onion tools are well-differentiated: search_onion hits an external provider, search_onion_cache queries the local index, and fetch_onion/crawl_onion are read vs. index operations. The Telegram search trio (search_telegram_messages vs search_telegram_posts) is the weakest boundary, relying on the 'allowed channel' vs 'public/free quota' distinction, but descriptions do clarify it.
All tools follow a consistent snake_case verb_noun pattern (get_status, fetch_onion, crawl_onion, search_onion, read_telegram_channel, etc.). The search_onion_cache suffix is the only minor deviation but still fits the convention cleanly.
Nine tools is well-scoped for the domain, split sensibly between a Tor/onion surface (5) and a Telegram surface (4). No redundant or filler tools; each earns its place.
The set covers discovery, reading, crawling/indexing, and both local and external search across two sources, which is solid lifecycle coverage. Minor gaps remain: no index management (purge/delete) or explicit corpus listing beyond get_status's size report, but core workflows are covered.
Maintenance
Related MCP Connectors
Search AI infrastructure, inspect facility evidence and explore sourced company relationships.
Search and monitor source-backed AI agent ecosystem signals, briefings, deltas, and source health.
AI-powered threat intelligence, smart contract auditing, and cybersecurity OSINT.
SEC red-flag alerts & company dossiers, token risk, wallet checks, x402 preflight, scraping, OFAC.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables detection and analysis of pre-public product launches through web search, content extraction, AI-powered scoring, and automated alerting. Provides comprehensive tools for surfacing stealth startup signals before they trend publicly.MIT
- FlicenseNot gradedqualityNot gradedmaintenanceEnables access to StealthMole's threat intelligence API for searching and monitoring threats across Deep & Dark Web, Telegram channels, leaked credentials, and ransomware incidents. Provides comprehensive cybersecurity intelligence through natural language queries.-
- AlicenseAqualityDmaintenanceDark web & threat intelligence for AI agents. HIBP, ThreatFox, ransomware tracking, Tor .onion access, blockchain intel, exploit search, stealer logs, malware analysis — unified into a single MCP server.66240 npm477MIT
- AlicenseBqualityDmaintenanceUnified dark web and threat intelligence MCP server providing 66 tools across 16 data sources, including breach databases, ransomware tracking, Tor .onion access, blockchain intel, and malware analysis for AI agents.66240 npm3MIT