hono-telescope
Monitors a Hono application's incoming requests, responses, exceptions, logs, and outgoing fetch calls, and exposes that telemetry through a dashboard and MCP tools.
Captures MongoDB database queries with execution time as part of request telemetry.
Captures Prisma database queries with execution time as part of request telemetry.
Captures Sequelize database queries with execution time as part of request telemetry.
Captures Bun SQLite database queries with execution time as part of request telemetry.
hono-telescope
A debugging tool for Hono applications, inspired by Laravel Telescope: a dashboard that shows you every request with the logs, queries, exceptions and outgoing calls that happened inside it.
The same endpoint is also an MCP server. Point Claude Code, Cursor or any MCP client at it and your coding agent reads the running application's telemetry directly β the actual exception, the request that produced it, and the queries that ran β instead of being handed a pasted stack trace. Nothing else in the Hono ecosystem does that.
Zero runtime dependencies. Works on Node.js and Bun.

π Live Demo
A hosted instance of the example app, running 1.0. No installation needed.
π Open the dashboard β API base: https://hono-telescope.ilkerbalcilar.com
Hit a few endpoints and watch the entries appear:
BASE=https://hono-telescope.ilkerbalcilar.com
curl $BASE/api/users # incoming request + Bun SQLite queries
curl -X POST $BASE/api/import-users # outgoing fetch to JSONPlaceholder, plus inserts
curl -X POST $BASE/api/webhook # outgoing POST whose payload is recorded, `token` redacted
curl -X POST $BASE/api/db-error # UNIQUE violation, recorded as a failed query; 409, no exception
curl $BASE/api/mixed-clients-test # the fetch call is captured, the axios call is not
curl $BASE/api/slow # 2s handler, to see the duration column
curl $BASE/api/error # exception recorded as a child of its requestThe demo runs with memoryStorage({ maxEntries: 500 }) and no dashboard auth, so entries are
public, capped at 500 and gone on restart. Don't send anything you wouldn't publish.
Related MCP server: Hono MCP Server
β¨ Features
Currently Available:
π‘ MCP Server - The dashboard endpoint doubles as a Model Context Protocol server, so an AI agent can read live requests, exceptions and queries with five read-only tools
π HTTP Request Monitoring - Track incoming requests with headers, payloads and response bodies, and outgoing
fetchcalls with headers, payloads and responsesπ¨ Exception Tracking - Capture and monitor application errors with stack traces
π Log Monitoring - Monitor console logs with different severity levels
ποΈ Database Query Monitoring - Explicit per-client instrumentation for Prisma, Sequelize, MongoDB, and Bun SQLite with execution time
π Beautiful Dashboard - Modern React-based web interface with real-time updates
π― Zero Configuration - Works out of the box with sensible defaults
π·οΈ Tagging System - Organize entries with custom tags and context
π§ TypeScript Support - Full type definitions and type safety
β‘ High Performance - Minimal overhead with efficient memory management
π Bun & Node.js - Works with both runtimes seamlessly
ποΈ Multiple Database Support - Integrates with popular database libraries
βοΈ Zero Runtime Dependencies - Depends only on Hono (peer dependency)
Planned Features (Roadmap):
πΎ Data Export - Export monitored data in multiple formats (JSON, CSV)
π Alerts & Notifications - Real-time alerts for errors and performance issues
π Analytics & Reporting - Advanced analytics and historical data analysis
π Authentication & Authorization - Dashboard access control beyond basic auth
π Multi-Tenancy Support - Support for multiple isolated projects
π§© Plugin System - Extensible plugin architecture for custom integrations
π Data Persistence - Optional database storage for long-term monitoring
π¦ Installation
# Using npm
npm install hono-telescope
# Using yarn
yarn add hono-telescope
# Using pnpm
pnpm add hono-telescope
# Using bun
bun add hono-telescopeQuick Start
import { Hono } from 'hono';
import { createTelescope, memoryStorage } from 'hono-telescope';
const app = new Hono();
const telescope = createTelescope({ storage: memoryStorage({ maxEntries: 1000 }) });
app.use('*', telescope.middleware());
app.route('/telescope', telescope.dashboard());
export default app;Visit /telescope. Telescope is on by default outside production and off inside it.
π Complete Example: See src/example/index.ts for a full working example with all Telescope features including database query monitoring, external request tracking, and error handling.
MCP Server
Telescope's dashboard doubles as an MCP server, so an AI coding agent can read the running application's telemetry instead of being handed pasted stack traces. There is nothing extra to mount β it is served from the dashboard you already mounted:
app.route('/telescope', telescope.dashboard()); // MCP is at /telescope/mcpclaude mcp add --transport http telescope http://localhost:3000/telescope/mcpTool | What it answers |
| What just failed β each exception with its request and that request's logs and queries |
| Which requests ran; filter by |
| One request in full, untruncated, with every child entry |
| The slowest recent queries and which request each ran in |
| How many entries of each type exist |
All five are read-only; there is no tool that clears or writes telemetry. minStatus: 400 is
the one worth remembering β a handler that returns an error status without throwing records no
exception, so that filter is the only way to find those failures.
The transport is the current Streamable HTTP revision (2026-07-28), with 2025-11-25 still
accepted for older clients. GET and DELETE answer 405: this revision has no SSE stream
and no sessions.
Clients that only speak stdio
Many editors cannot point an MCP client at a URL. The package ships a bridge for them: it reads one JSON-RPC message per line on stdin, forwards it to the endpoint your app already serves, and writes the reply back on stdout.
claude mcp add telescope -- npx -y hono-telescope mcp-stdio \
--url http://localhost:3000/telescope/mcp{
"mcpServers": {
"telescope": {
"command": "npx",
"args": ["-y", "hono-telescope", "mcp-stdio"],
"env": { "TELESCOPE_URL": "http://localhost:3000/telescope/mcp" }
}
}
}--url (or TELESCOPE_URL) is the only required option. For a dashboard behind
dashboard.auth, pass credentials as a header β --header is repeatable, and
TELESCOPE_HEADER takes one for clients that can only set environment variables:
npx -y hono-telescope mcp-stdio --url https://example.com/telescope/mcp \
--header "Authorization: Basic $(printf 'user:pass' | base64)"The bridge forwards; it does not implement the protocol a second time. Your app stays the only place that answers MCP, so the bridge adds no tools, no session state and no new dependency β and it needs the app to already be running.
The MCP endpoint exposes exactly what the dashboard exposes β request and response bodies, headers and SQL β to whatever agent you connect. It is covered by
dashboard.authand by the same production refusal: withenabled: trueunderNODE_ENV=production, mounting without credentials throws.
Configuration
import { createTelescope, memoryStorage, alsContext, consoleCollector } from 'hono-telescope';
const telescope = createTelescope({
enabled: process.env.NODE_ENV !== 'production',
storage: memoryStorage({ maxEntries: 1000 }),
context: alsContext(),
collectors: [consoleCollector()],
dashboardPath: '/telescope',
ignorePaths: ['/health'],
ignoreStaticAssets: true,
capture: {
requestBody: true,
responseBody: true,
maxBodySize: 65536,
},
redact: {
headers: ['authorization', 'cookie', 'set-cookie', 'x-api-key', 'proxy-authorization'],
bodyKeys: ['password', 'token', 'secret', 'apikey', 'authorization'],
},
dashboard: {
auth: { username: 'admin', password: 'telescope' },
},
});All options are optional β createTelescope() works with the defaults.
Key | Type | Default | Notes |
|
|
| Disable in production by default |
|
|
| In-memory storage with 1000 entry limit |
|
|
| AsyncLocalStorage-based request context tracking |
|
|
| Default collectors for console, exceptions, and fetch; pass |
|
|
| Dashboard mount path; must match the path in |
|
|
| Paths to exclude from monitoring |
|
|
| Skip monitoring requests for static files (.js, .css, .svg, etc.) |
|
|
| Capture incoming request bodies |
|
|
| Capture outgoing response bodies |
|
|
| Maximum bytes to capture per body (64 KB) |
|
|
| Header names to redact |
|
|
| Object keys to redact in request/response bodies |
|
|
| Optional basic auth for dashboard; required if |
Mounting at a Custom Path
If you mount the dashboard at a path other than /telescope, you must set dashboardPath to the same value:
const telescope = createTelescope({ dashboardPath: '/admin/debug' });
app.route('/admin/debug', telescope.dashboard());The middleware uses dashboardPath to avoid recording the dashboard's own traffic, and the dashboard uses it to construct its base URL.
Database Queries
Pass your database client to Telescope for query instrumentation. Prisma returns a new clientβuse the returned one:
import { createTelescope } from 'hono-telescope';
import { PrismaClient } from '@prisma/client';
const telescope = createTelescope();
const prisma = telescope.instrumentPrisma(new PrismaClient());
// Use the returned `prisma` client, not the originalSupported databases:
const prisma = telescope.instrumentPrisma(new PrismaClient());
telescope.instrumentSequelize(sequelize);
const mongoClient = new MongoClient(url, { monitorCommands: true });
telescope.instrumentMongo(mongoClient);
telescope.instrumentBunSqlite(db);Note: Automatic database interception was removed in 1.0 because it never worked under Node ESM and captured only raw SQL where it did run. Explicit per-client instrumentation is now required.
A query that fails is recorded too, marked failed with the client's own error message, so a
failed command is distinguishable from a slow one in the dashboard and over MCP. This covers
Prisma, MongoDB and Bun SQLite. Sequelize is the exception: it is instrumented through the
afterQuery hook, which does not appear to run when a query fails, so failed Sequelize queries
are currently not recorded at all. Fixing that needs verification against a real Sequelize.
Call each instrument* method once per client. Unlike the collectors, they are not
idempotent (only instrumentBunSqlite guards against double wrapping), so instrumenting the
same client twice records every query twice.
instrumentBunSqlite wraps the query and prepare statement factories, so statement calls
(all, get, run, values) are recorded. Queries issued directly on the database β
db.exec, db.run, db.all, db.get β are not captured.
Security
The dashboard exposes request and response bodies, headers, and SQL. Telescope is therefore disabled when NODE_ENV === 'production'. If you enable it there anyway, you must supply dashboard.auth; mounting without it throws.
You have two options for production:
Supply credentials to protect the dashboard with basic auth:
createTelescope({
enabled: true,
dashboard: { auth: { username: 'admin', password: 'secret' } },
});Explicitly opt out of auth to acknowledge full exposure (no auth, dashboard fully open):
createTelescope({
enabled: true,
dashboard: { auth: false },
});Sensitive headers (authorization, cookie, set-cookie, x-api-key, proxy-authorization) and body keys (password, token, secret, apikey, authorization) are redacted by default, at any nesting depth. Redaction is recursive through nested objects and arrays, case-insensitive, and replaces values with [REDACTED] rather than deleting them.
Limitations
Outgoing request bodies are captured only when they are already in memory β a string, a
URLSearchParamsor anArrayBuffer. AReadableStream,FormDataorBlobbody, and the body of aRequestobject passed as the first argument tofetch, are skipped and the payload stays empty. Reading those would either consume the body the caller is about to send or force aclone()that can stall on Node.Streamed responses are not captured. Responses produced by Hono's
streamTextandstreamSSEare recorded without a body, so that recording never buffers or delays a stream. Detection relies on theTransfer-Encoding: chunkedheader those helpers set (the barestream()helper sets no content-type, so it is skipped too); a hand-rollednew Response(readableStream, { headers: { 'content-type': 'text/plain' } })sets neither header, so it is read and buffered before being recorded. SetTransfer-Encoding: chunkedor a non-text content type on such a response to opt it out of capture.Request and response bodies larger than
capture.maxBodySizeare recorded as metadata only ({ truncated: true, size }), and a non-JSONtext/*request body is recorded as{ body: text }. A JSON array body is wrapped so that a recorded body is always an object:{ body: [...] }for requests,{ response: [...] }for responses. Redaction still reaches inside the array.
Custom Storage Adapters
Implement StorageAdapter and verify it against the contract suite that ships with the
package:
import { runStorageContract } from 'hono-telescope/testing';
import { myStorage } from './my-storage';
runStorageContract('myStorage', () => myStorage());The suite (a Vitest suite; run it with your own test runner installed) pins the two ordering
guarantees the dashboard relies on: list returns newest first, and findByParent returns
oldest first.
Upgrading from 0.x
The 1.0 release introduces a new API centered on createTelescope():
0.x (Old API)
import { setupTelescope } from 'hono-telescope';
setupTelescope(app, {
enabled: true,
max_entries: 1000,
sanitize_headers: ['authorization'],
});1.0 (New API)
import { createTelescope, memoryStorage } from 'hono-telescope';
const telescope = createTelescope({
storage: memoryStorage({ maxEntries: 1000 }),
redact: { headers: ['authorization'] },
});
app.use('*', telescope.middleware());
app.route('/telescope', telescope.dashboard());Key changes:
setupTelescope(app, config)is replaced bycreateTelescope(config)with explicit middleware and dashboard mountingConfiguration keys are now camelCase (e.g.,
max_entriesβmaxEntries,sanitize_headersβredact.headers)Database interception is now explicit per-client; automatic interception was removed
Axios interception was removed (axios on Node does not use
fetch)A request whose handler throws is recorded with the status your own
onErrorreturned, and the exception is recorded as a child entry of that request
Development
Getting Started
First, install dependencies:
bun installThen build the project for the first time:
bun run buildRunning in Development Mode
Start the TypeScript watcher and example app:
Terminal 1 - TypeScript Compilation (Watch Mode)
bun run devThis watches for TypeScript changes and compiles them to JavaScript.
Terminal 2 - Example Application
bun run dev:exampleThis starts the example Hono application with hot reload at http://localhost:3000
Example API endpoints:
http://localhost:3000/api/...Dashboard:
http://localhost:3000/telescope
Test all endpoints at once with the test script:
bash src/example/test-all-endpoints.shThis will automatically test all endpoints and populate the dashboard with data.
License
Available Tools
5 toolsrecent_exceptionsRecent exceptionsARead-only
The most recent exceptions, each with the request that produced it and that request's logs, queries and outgoing calls. Start here when something failed.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | How many exceptions to return, most recent first. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, and the description adds behavioral detail beyond that: the return items include linked request context, logs, queries, and outgoing calls, and results are ordered most-recent-first. This gives the agent useful expectations without contradicting the annotations.
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, no filler. The first sentence conveys content and scope; the second gives a direct usage directive. Every word earns its place and the key information is front-loaded.
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 simple read-only listing tool with one optional parameter, the description covers what is returned, the ordering, and the triggering use case. No output schema exists, but the description sufficiently describes the response contents for an agent to call 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 100% and the single 'limit' parameter already has a clear description in the schema. The tool description does not add additional parameter semantics, so the baseline of 3 is appropriate.
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?
The description states a specific resource ('the most recent exceptions') and adds substantial scope: each exception includes the request that produced it and that request's logs, queries, and outgoing calls. This clearly distinguishes it from siblings like recent_requests and request_detail.
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?
'Start here when something failed' provides explicit guidance for when to use this tool: failure triage. It does not name alternative tools explicitly, but the instruction strongly implies this is the entry point, making the usage context clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
recent_requestsRecent requestsARead-only
Recent incoming requests with child counts. Filter with minStatus: 400 to find failures that returned an error status without throwing.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | How many requests to return, most recent first. | |
| status | No | Exact response status | |
| minStatus | No | Inclusive lower bound on response status | |
| minDuration | No | Only requests that took at least this many milliseconds. | |
| uriContains | No | Case-sensitive substring the request path must contain. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With readOnlyHint=true, the safety profile is already known; the description adds useful behavioral context about child counts and the distinction between error-status responses and exceptions. It does not contradict the annotations and adds enough context to set agent expectations.
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, with the core definition front-loaded and a practical filter example in the second. Every sentence earns its place and there is no filler.
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?
The definition is complete for a read-only, fully optional-filter list tool: it names the output shape (requests with child counts), provides a filtering use case, and the schema covers all five parameters. No output schema is present, but the description supplies the key return concept.
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 100%, so parameters like minStatus and uriContains are already documented; the description adds meaning by highlighting the minStatus: 400 failure-detection pattern and the child-count output. This goes beyond merely restating schema fields.
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?
The description clearly identifies the resource ('incoming requests') and a defining attribute ('with child counts'), and its example filter signals a retrieval operation. It distinguishes from siblings like recent_exceptions and slow_queries by scope, though it uses a noun phrase rather than an explicit verb.
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?
It gives a concrete, high-value usage example: using minStatus: 400 to find failures that returned an error status without throwing. This implies when to use the tool, but it does not explicitly state when to prefer recent_exceptions, request_detail, or slow_queries instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
request_detailRequest detailARead-only
One request in full β headers, payload, response body β with every log, query, exception and outgoing call recorded inside it. Nothing is truncated. Reach for it once a list tool has narrowed the search to one request.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | An incoming request id: the `id` of a recent_requests result, or the `request.id` attached to a recent_exceptions or slow_queries result. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only behavior; the description adds value by revealing that responses are not truncated and that all nested request artifacts are included. It does not discuss error cases or rate limits, but for a simple read-only detail tool this is acceptable.
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-load the core behavior and add a usage trigger with no filler. 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?
For a one-parameter, read-only detail tool with no output schema, the description is complete: it states what is returned, that nothing is truncated, and when to call it. The schema covers the id source, so nothing an agent needs to invoke it correctly is missing.
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 input schema already documents the id parameter at 100% coverage, including valid sources for the value. The description adds no extra parameter semantics, so the baseline score of 3 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?
The description states exactly what the tool returns ('One request in full') and enumerates the contents (headers, payload, response body, logs, queries, exceptions, outgoing calls), which clearly distinguishes it from the sibling list/aggregation tools. 'Nothing is truncated' further defines the scope.
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?
It gives an explicit trigger condition: use it after a list tool has narrowed the search to a single request. It does not name the alternative list tools or specify when not to use it, so it falls just short of a full 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
slow_queriesSlow queriesARead-only
Recent database queries sorted slowest first, each with the request it ran in. Use request_detail on that request to see everything else it did.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | How many queries to return, slowest first. | |
| minMs | No | Only queries that took at least this many milliseconds. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With readOnlyHint already covering safety, the description adds meaningful behavioral detail: sorting by slowness, recency, and association with the request. The only minor gap is that 'recent' is not precisely defined, but there is no contradiction with the annotations.
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, front-loaded with the core behavior and a useful follow-up instruction. Every word earns its place, with no filler or redundancy.
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 simple read-only listing tool, the schema and annotations carry much of the burden, and the description covers sorting and request linkage. The slight ambiguity around the time window of 'recent' and the absence of an explicit output shape keep it 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?
Schema description coverage is 100%, and both limit and minMs are already well documented in the input schema. The description adds no parameter-specific detail, so the baseline score of 3 is appropriate.
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 exactly what it returns: recent database queries sorted slowest first, with the request that ran them. This clearly distinguishes it from request-centric siblings like recent_requests and recent_exceptions, so an agent can identify the right tool.
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 gives clear context for when to use this tool: to inspect slow database queries and then drill into the associated request via request_detail. It does not explicitly list alternatives or exclusions, but the workflow is evident enough to guide selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
statsTelemetry countsARead-only
How many entries of each type Telescope is holding right now. The counts cover what is still retained: the oldest entries are dropped once storage reaches maxEntries. Read it first to see whether there is anything to look at, then drill in with recent_exceptions or recent_requests.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true. The description adds valuable behavioral context beyond that: counts reflect only retained entries, and oldest entries are dropped once storage reaches maxEntries. This helps the agent interpret results correctly, though it doesn't detail return format or exact counts semantics.
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?
Three sentences with no filler: purpose, retention caveat, and usage guidance. The most important information is front-loaded and every sentence adds value.
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 parameterless, read-only summary tool, the description is complete. It tells the agent what counts are shown, how retention affects the data, and how to proceed using sibling tools. No output schema exists, but the simple nature of the result makes this acceptable.
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 has zero parameters and schema coverage is 100%, so there are no parameter semantics to document. The description effectively communicates that no inputs are needed and that the tool provides a snapshot of current telemetry counts.
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?
The description clearly states the tool counts entries of each type currently retained by Telescope, using a specific verb ('How many entries... holding') and resource. It distinguishes itself from sibling tools by describing its aggregate summary nature rather than individual records.
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 explicitly routes the agent: 'Read it first... then drill in with recent_exceptions or recent_requests.' This gives clear when-to-use guidance and names the relevant alternatives, leaving no ambiguity about the tool's place in the workflow.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
TDQS
Each tool maps to a distinct investigation step: stats for overview, recent_exceptions for thrown failures, recent_requests for status-based failures, slow_queries for DB performance, and request_detail for full inspection. There is no pair an agent would realistically confuse after reading the descriptions.
All names are snake_case noun phrases with a consistent recent_* prefix for list views and a clear singular request_detail for deep dive. The only minor deviation is the abbreviated stats, but the overall pattern is otherwise uniform.
Five tools is well-scoped for a Telescope observability server: an entry point, two list views, one detail drill-down, and one performance view. There are no redundant tools, and the count fits the purpose comfortably.
The tools cover the full inspection workflow: check what is retained, list failures, drill into a single request, and identify slow queries. The workflow has no dead ends because every list tool points toward request_detail for deeper context.
Maintenance
Related MCP Connectors
Analytics and debugging for your MCP server β explore usage and sessions, then root-cause errors.
Hosted MCP server for PostgreSQL diagnostics: slow queries, missing indexes, connection pressure.
MCP observability. Query live traffic, errors, duration, and alerts from your AI agent.
Monitoring for small teams. Logs, traces, metrics, live issue tracking, API/MCP uptime.
Related MCP Servers
- AlicenseNot gradedqualityFmaintenanceA Model Context Protocol server implementation for Axiom that enables AI agents to query your data using Axiom Processing Language (APL).60MIT
- AlicenseNot gradedqualityDmaintenanceExposes Hono API endpoints as Model Context Protocol tools, allowing LLMs to interact with your API routes through a dedicated MCP endpoint. It provides helpers to describe routes and includes a codemode for dynamic API interaction via search and execute tools.7786MIT
- FlicenseNot gradedqualityDmaintenanceA Bun-based MCP server providing a persistent HTTP request toolset for testing and inspecting JSON APIs. It supports session-aware operations, including cookie persistence, automatic bearer token reuse, and configurable base URLs.
- FlicenseNot gradedqualityDmaintenanceA lightweight Hono.js middleware for building Model Context Protocol servers using a simple, fluent API and supporting both SSE and HTTP transports. It enables developers to create type-safe, edge-ready MCP-compatible APIs with built-in session management.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Jubstaaa/hono-telescope'
If you have feedback or need assistance with the MCP directory API, please join our Discord server