@ontosdk/mcp 1.1.1 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/server.js +1 -1
- package/dist/server.js.map +1 -1
- package/package.json +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -119,6 +119,6 @@ interface CallOptions {
|
|
|
119
119
|
}
|
|
120
120
|
declare function callOntoApi<T>(endpoint: string, options: CallOptions): Promise<T>;
|
|
121
121
|
|
|
122
|
-
declare const version = "1.1.
|
|
122
|
+
declare const version = "1.1.2";
|
|
123
123
|
|
|
124
124
|
export { OntoApiError, type ReadAndScoreInput, type ReadAndScoreResponse, type ReadResponse, type ReadUrlInput, type Recommendation, type ScoreResponse, type ScoreUrlInput, callOntoApi, readAndScore, readAndScoreInputSchema, readUrl, readUrlInputSchema, scoreUrl, scoreUrlInputSchema, version };
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/tools/read.ts","../src/lib/version.ts","../src/lib/api-client.ts","../src/lib/errors.ts","../src/tools/score.ts","../src/tools/read-and-score.ts"],"sourcesContent":["import { z } from 'zod';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { callOntoApi } from '../lib/api-client.js';\nimport { formatToolError } from '../lib/errors.js';\nimport type { ReadResponse } from '../lib/types.js';\n\nexport const readUrlInputSchema = z.object({\n url: z.string().url(),\n fresh: z.boolean().optional().default(false),\n});\n\nexport type ReadUrlInput = z.infer<typeof readUrlInputSchema>;\n\nexport async function readUrl(input: ReadUrlInput): Promise<CallToolResult> {\n try {\n const result = await callOntoApi<ReadResponse>('/v1/read', {\n body: { url: input.url, fresh: input.fresh },\n });\n\n const metaLines = [\n `- URL: ${result.url}`,\n `- Title: ${result.metadata.title || '(none)'}`,\n `- Original size: ${result.stats.raw_html_size_kb} KB`,\n `- Cleaned size: ${result.stats.markdown_size_kb} KB`,\n `- Reduction: ${result.stats.reduction_percent}%`,\n `- Extraction time: ${result.stats.extraction_time_ms} ms`,\n `- Cache: ${result.cache.hit ? 'HIT' : 'MISS'}`,\n ].join('\\n');\n\n return {\n content: [\n { type: 'text' as const, text: result.markdown },\n {\n type: 'text' as const,\n text: `\\n\\n---\\n\\n**Source metadata (from Onto):**\\n${metaLines}`,\n },\n ],\n };\n } catch (error) {\n return formatToolError(error);\n }\n}\n","export const version = '1.1.1';\n","/* Thin HTTP wrapper around the Onto Read API. Reads ONTO_API_KEY at call time\n * (not module-load) so server.ts can fail with a clean error message first. */\n\nimport { version as PACKAGE_VERSION } from './version.js';\nimport type { ApiErrorBody } from './types.js';\n\nconst DEFAULT_BASE = 'https://api.buildonto.dev';\nconst REQUEST_TIMEOUT_MS = 15_000;\n\nexport class OntoApiError extends Error {\n constructor(\n message: string,\n public readonly status: number,\n public readonly code?: string,\n ) {\n super(message);\n this.name = 'OntoApiError';\n }\n}\n\ninterface CallOptions {\n body: unknown;\n signal?: AbortSignal;\n}\n\nexport async function callOntoApi<T>(endpoint: string, options: CallOptions): Promise<T> {\n const apiKey = process.env.ONTO_API_KEY;\n if (!apiKey) {\n throw new OntoApiError(\n 'ONTO_API_KEY environment variable is not set. Get a key at https://app.buildonto.dev/read/keys',\n 0,\n 'NO_API_KEY',\n );\n }\n\n const base = process.env.ONTO_API_BASE ?? DEFAULT_BASE;\n const url = `${base}${endpoint}`;\n\n const timeout = AbortSignal.timeout(REQUEST_TIMEOUT_MS);\n const signal = options.signal\n ? AbortSignal.any([options.signal, timeout])\n : timeout;\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n 'User-Agent': `@ontosdk/mcp/${PACKAGE_VERSION}`,\n },\n body: JSON.stringify(options.body),\n signal,\n });\n } catch (err) {\n if (err instanceof DOMException && err.name === 'TimeoutError') {\n throw new OntoApiError(\n `Onto API request timed out after ${REQUEST_TIMEOUT_MS / 1000}s. The target site may be slow or unreachable.`,\n 0,\n 'TIMEOUT',\n );\n }\n throw new OntoApiError(\n `Failed to reach Onto API at ${base}: ${(err as Error).message}`,\n 0,\n 'NETWORK_ERROR',\n );\n }\n\n const rawBody = await response.text();\n\n if (!response.ok) {\n let parsed: Partial<ApiErrorBody> = {};\n try {\n parsed = JSON.parse(rawBody) as Partial<ApiErrorBody>;\n } catch {\n // Body wasn't JSON; fall through with status-code-only error\n }\n\n const message = humanizeError(response.status, parsed);\n throw new OntoApiError(message, response.status, parsed.error);\n }\n\n try {\n return JSON.parse(rawBody) as T;\n } catch (err) {\n throw new OntoApiError(\n `Onto API returned invalid JSON: ${(err as Error).message}`,\n response.status,\n 'INVALID_RESPONSE',\n );\n }\n}\n\nfunction humanizeError(status: number, body: Partial<ApiErrorBody>): string {\n if (status === 401) {\n return 'Invalid Onto API key. Verify your key at https://app.buildonto.dev/read/keys';\n }\n if (status === 402) {\n return (\n body.message ??\n 'Monthly plan quota exceeded and credit balance is empty. Top up credits at https://app.buildonto.dev/read/billing'\n );\n }\n if (status === 403) {\n if (body.error === 'ROBOTS_BLOCKED') {\n return body.message ?? 'The target site blocks AI crawlers via robots.txt.';\n }\n return body.message ?? 'Forbidden.';\n }\n if (status === 429) {\n return (\n body.message ??\n 'Onto API rate limit exceeded. Upgrade your tier at https://app.buildonto.dev/read/billing or wait for the monthly reset.'\n );\n }\n if (status >= 500) {\n return body.message ?? `Onto API server error (${status}). Try again in a moment.`;\n }\n return body.message ?? `Onto API returned ${status}.`;\n}\n","/* Format errors as MCP tool responses. We don't throw McpError for\n * tool-call failures — the AI host shows tool errors to the user as\n * unhelpful internal-error messages. Returning isError: true with a\n * text body lets the model see what went wrong and recover. */\n\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { OntoApiError } from './api-client.js';\n\nexport function formatToolError(error: unknown): CallToolResult {\n if (error instanceof OntoApiError) {\n return {\n content: [{ type: 'text', text: error.message }],\n isError: true,\n };\n }\n\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n {\n type: 'text',\n text: `Onto MCP error: ${message}\\n\\nTroubleshooting:\\n- Verify ONTO_API_KEY is set and valid (https://app.buildonto.dev/read/keys)\\n- Check the target URL is publicly accessible\\n- Check your monthly quota at https://app.buildonto.dev/read/usage`,\n },\n ],\n isError: true,\n };\n}\n","import { z } from 'zod';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { callOntoApi } from '../lib/api-client.js';\nimport { formatToolError } from '../lib/errors.js';\nimport type { ScoreResponse, Recommendation } from '../lib/types.js';\n\nexport const scoreUrlInputSchema = z.object({\n url: z.string().url(),\n});\n\nexport type ScoreUrlInput = z.infer<typeof scoreUrlInputSchema>;\n\nexport async function scoreUrl(input: ScoreUrlInput): Promise<CallToolResult> {\n try {\n const result = await callOntoApi<ScoreResponse>('/v1/score', {\n body: { url: input.url },\n });\n\n return {\n content: [{ type: 'text' as const, text: formatScoreSummary(result) }],\n };\n } catch (error) {\n return formatToolError(error);\n }\n}\n\nexport function formatScoreSummary(result: ScoreResponse): string {\n const lines: string[] = [\n `**AIO Score:** ${result.aio_score}/100 (${result.grade})`,\n `**Hallucination risk:** ${result.hallucination_risk}`,\n `**URL:** ${result.url}`,\n '',\n ];\n\n if (result.benefits.length > 0) {\n lines.push('**What works well:**');\n for (const item of result.benefits) lines.push(`- ${item}`);\n lines.push('');\n }\n\n if (result.penalties.length > 0) {\n lines.push('**What hurts AI readability:**');\n for (const item of result.penalties) lines.push(`- ${item}`);\n lines.push('');\n }\n\n const insightEntries = Object.entries(result.insights ?? {});\n if (insightEntries.length > 0) {\n lines.push('**Insights:**');\n for (const [key, value] of insightEntries) {\n lines.push(`- ${key}: ${value ? 'yes' : 'no'}`);\n }\n lines.push('');\n }\n\n if (result.recommendations.length > 0) {\n lines.push('**Recommendations:**');\n for (const rec of result.recommendations) {\n lines.push(describeRecommendation(rec));\n }\n lines.push('');\n }\n\n lines.push('**Stats:**');\n lines.push(`- Raw size: ${result.stats.raw_size}`);\n lines.push(`- Efficiency: ${result.stats.efficiency}`);\n lines.push(`- Extraction time: ${result.stats.extraction_time_ms} ms`);\n\n return lines.join('\\n');\n}\n\nfunction describeRecommendation(rec: Recommendation): string {\n if (typeof rec === 'string') return `- ${rec}`;\n if (rec.title) {\n const head = rec.priority ? `**${rec.title}** _(priority: ${rec.priority})_` : `**${rec.title}**`;\n return rec.description ? `- ${head} — ${rec.description}` : `- ${head}`;\n }\n if (rec.description) return `- ${rec.description}`;\n return `- ${JSON.stringify(rec)}`;\n}\n","import { z } from 'zod';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { callOntoApi } from '../lib/api-client.js';\nimport { formatToolError } from '../lib/errors.js';\nimport type { ReadAndScoreResponse } from '../lib/types.js';\n\nexport const readAndScoreInputSchema = z.object({\n url: z.string().url(),\n fresh: z.boolean().optional().default(false),\n});\n\nexport type ReadAndScoreInput = z.infer<typeof readAndScoreInputSchema>;\n\nexport async function readAndScore(input: ReadAndScoreInput): Promise<CallToolResult> {\n try {\n const result = await callOntoApi<ReadAndScoreResponse>('/v1/read-and-score', {\n body: { url: input.url, fresh: input.fresh },\n });\n\n const trustHint = trustLine(result.aio_score, result.hallucination_risk);\n const summaryLines = [\n `**Source quality assessment (from Onto):**`,\n `- AIO Score: ${result.aio_score}/100 (${result.grade})`,\n `- Hallucination risk: ${result.hallucination_risk}`,\n `- Reduction: ${result.stats.reduction_percent}% (${result.stats.raw_html_size_kb} KB → ${result.stats.markdown_size_kb} KB)`,\n `- Cache: ${result.cache.hit ? 'HIT' : 'MISS'}`,\n '',\n trustHint,\n ];\n\n return {\n content: [\n { type: 'text' as const, text: result.markdown },\n { type: 'text' as const, text: `\\n\\n---\\n\\n${summaryLines.join('\\n')}` },\n ],\n };\n } catch (error) {\n return formatToolError(error);\n }\n}\n\nfunction trustLine(score: number, risk: 'low' | 'medium' | 'high'): string {\n if (risk === 'high' || score < 40) {\n return 'Trust signal: low — this source is poorly structured for AI consumption. Verify any facts before relying on them.';\n }\n if (risk === 'medium' || score < 70) {\n return 'Trust signal: medium — source is partially AI-readable. Cross-check critical claims.';\n }\n return 'Trust signal: high — source is well-structured for AI consumption.';\n}\n"],"mappings":"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","names":["z","z","z","z"]}
|
|
1
|
+
{"version":3,"sources":["../src/tools/read.ts","../src/lib/version.ts","../src/lib/api-client.ts","../src/lib/errors.ts","../src/tools/score.ts","../src/tools/read-and-score.ts"],"sourcesContent":["import { z } from 'zod';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { callOntoApi } from '../lib/api-client.js';\nimport { formatToolError } from '../lib/errors.js';\nimport type { ReadResponse } from '../lib/types.js';\n\nexport const readUrlInputSchema = z.object({\n url: z.string().url(),\n fresh: z.boolean().optional().default(false),\n});\n\nexport type ReadUrlInput = z.infer<typeof readUrlInputSchema>;\n\nexport async function readUrl(input: ReadUrlInput): Promise<CallToolResult> {\n try {\n const result = await callOntoApi<ReadResponse>('/v1/read', {\n body: { url: input.url, fresh: input.fresh },\n });\n\n const metaLines = [\n `- URL: ${result.url}`,\n `- Title: ${result.metadata.title || '(none)'}`,\n `- Original size: ${result.stats.raw_html_size_kb} KB`,\n `- Cleaned size: ${result.stats.markdown_size_kb} KB`,\n `- Reduction: ${result.stats.reduction_percent}%`,\n `- Extraction time: ${result.stats.extraction_time_ms} ms`,\n `- Cache: ${result.cache.hit ? 'HIT' : 'MISS'}`,\n ].join('\\n');\n\n return {\n content: [\n { type: 'text' as const, text: result.markdown },\n {\n type: 'text' as const,\n text: `\\n\\n---\\n\\n**Source metadata (from Onto):**\\n${metaLines}`,\n },\n ],\n };\n } catch (error) {\n return formatToolError(error);\n }\n}\n","export const version = '1.1.2';\n","/* Thin HTTP wrapper around the Onto Read API. Reads ONTO_API_KEY at call time\n * (not module-load) so server.ts can fail with a clean error message first. */\n\nimport { version as PACKAGE_VERSION } from './version.js';\nimport type { ApiErrorBody } from './types.js';\n\nconst DEFAULT_BASE = 'https://api.buildonto.dev';\nconst REQUEST_TIMEOUT_MS = 15_000;\n\nexport class OntoApiError extends Error {\n constructor(\n message: string,\n public readonly status: number,\n public readonly code?: string,\n ) {\n super(message);\n this.name = 'OntoApiError';\n }\n}\n\ninterface CallOptions {\n body: unknown;\n signal?: AbortSignal;\n}\n\nexport async function callOntoApi<T>(endpoint: string, options: CallOptions): Promise<T> {\n const apiKey = process.env.ONTO_API_KEY;\n if (!apiKey) {\n throw new OntoApiError(\n 'ONTO_API_KEY environment variable is not set. Get a key at https://app.buildonto.dev/read/keys',\n 0,\n 'NO_API_KEY',\n );\n }\n\n const base = process.env.ONTO_API_BASE ?? DEFAULT_BASE;\n const url = `${base}${endpoint}`;\n\n const timeout = AbortSignal.timeout(REQUEST_TIMEOUT_MS);\n const signal = options.signal\n ? AbortSignal.any([options.signal, timeout])\n : timeout;\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n 'User-Agent': `@ontosdk/mcp/${PACKAGE_VERSION}`,\n },\n body: JSON.stringify(options.body),\n signal,\n });\n } catch (err) {\n if (err instanceof DOMException && err.name === 'TimeoutError') {\n throw new OntoApiError(\n `Onto API request timed out after ${REQUEST_TIMEOUT_MS / 1000}s. The target site may be slow or unreachable.`,\n 0,\n 'TIMEOUT',\n );\n }\n throw new OntoApiError(\n `Failed to reach Onto API at ${base}: ${(err as Error).message}`,\n 0,\n 'NETWORK_ERROR',\n );\n }\n\n const rawBody = await response.text();\n\n if (!response.ok) {\n let parsed: Partial<ApiErrorBody> = {};\n try {\n parsed = JSON.parse(rawBody) as Partial<ApiErrorBody>;\n } catch {\n // Body wasn't JSON; fall through with status-code-only error\n }\n\n const message = humanizeError(response.status, parsed);\n throw new OntoApiError(message, response.status, parsed.error);\n }\n\n try {\n return JSON.parse(rawBody) as T;\n } catch (err) {\n throw new OntoApiError(\n `Onto API returned invalid JSON: ${(err as Error).message}`,\n response.status,\n 'INVALID_RESPONSE',\n );\n }\n}\n\nfunction humanizeError(status: number, body: Partial<ApiErrorBody>): string {\n if (status === 401) {\n return 'Invalid Onto API key. Verify your key at https://app.buildonto.dev/read/keys';\n }\n if (status === 402) {\n return (\n body.message ??\n 'Monthly plan quota exceeded and credit balance is empty. Top up credits at https://app.buildonto.dev/read/billing'\n );\n }\n if (status === 403) {\n if (body.error === 'ROBOTS_BLOCKED') {\n return body.message ?? 'The target site blocks AI crawlers via robots.txt.';\n }\n return body.message ?? 'Forbidden.';\n }\n if (status === 429) {\n return (\n body.message ??\n 'Onto API rate limit exceeded. Upgrade your tier at https://app.buildonto.dev/read/billing or wait for the monthly reset.'\n );\n }\n if (status >= 500) {\n return body.message ?? `Onto API server error (${status}). Try again in a moment.`;\n }\n return body.message ?? `Onto API returned ${status}.`;\n}\n","/* Format errors as MCP tool responses. We don't throw McpError for\n * tool-call failures — the AI host shows tool errors to the user as\n * unhelpful internal-error messages. Returning isError: true with a\n * text body lets the model see what went wrong and recover. */\n\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { OntoApiError } from './api-client.js';\n\nexport function formatToolError(error: unknown): CallToolResult {\n if (error instanceof OntoApiError) {\n return {\n content: [{ type: 'text', text: error.message }],\n isError: true,\n };\n }\n\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n {\n type: 'text',\n text: `Onto MCP error: ${message}\\n\\nTroubleshooting:\\n- Verify ONTO_API_KEY is set and valid (https://app.buildonto.dev/read/keys)\\n- Check the target URL is publicly accessible\\n- Check your monthly quota at https://app.buildonto.dev/read/usage`,\n },\n ],\n isError: true,\n };\n}\n","import { z } from 'zod';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { callOntoApi } from '../lib/api-client.js';\nimport { formatToolError } from '../lib/errors.js';\nimport type { ScoreResponse, Recommendation } from '../lib/types.js';\n\nexport const scoreUrlInputSchema = z.object({\n url: z.string().url(),\n});\n\nexport type ScoreUrlInput = z.infer<typeof scoreUrlInputSchema>;\n\nexport async function scoreUrl(input: ScoreUrlInput): Promise<CallToolResult> {\n try {\n const result = await callOntoApi<ScoreResponse>('/v1/score', {\n body: { url: input.url },\n });\n\n return {\n content: [{ type: 'text' as const, text: formatScoreSummary(result) }],\n };\n } catch (error) {\n return formatToolError(error);\n }\n}\n\nexport function formatScoreSummary(result: ScoreResponse): string {\n const lines: string[] = [\n `**AIO Score:** ${result.aio_score}/100 (${result.grade})`,\n `**Hallucination risk:** ${result.hallucination_risk}`,\n `**URL:** ${result.url}`,\n '',\n ];\n\n if (result.benefits.length > 0) {\n lines.push('**What works well:**');\n for (const item of result.benefits) lines.push(`- ${item}`);\n lines.push('');\n }\n\n if (result.penalties.length > 0) {\n lines.push('**What hurts AI readability:**');\n for (const item of result.penalties) lines.push(`- ${item}`);\n lines.push('');\n }\n\n const insightEntries = Object.entries(result.insights ?? {});\n if (insightEntries.length > 0) {\n lines.push('**Insights:**');\n for (const [key, value] of insightEntries) {\n lines.push(`- ${key}: ${value ? 'yes' : 'no'}`);\n }\n lines.push('');\n }\n\n if (result.recommendations.length > 0) {\n lines.push('**Recommendations:**');\n for (const rec of result.recommendations) {\n lines.push(describeRecommendation(rec));\n }\n lines.push('');\n }\n\n lines.push('**Stats:**');\n lines.push(`- Raw size: ${result.stats.raw_size}`);\n lines.push(`- Efficiency: ${result.stats.efficiency}`);\n lines.push(`- Extraction time: ${result.stats.extraction_time_ms} ms`);\n\n return lines.join('\\n');\n}\n\nfunction describeRecommendation(rec: Recommendation): string {\n if (typeof rec === 'string') return `- ${rec}`;\n if (rec.title) {\n const head = rec.priority ? `**${rec.title}** _(priority: ${rec.priority})_` : `**${rec.title}**`;\n return rec.description ? `- ${head} — ${rec.description}` : `- ${head}`;\n }\n if (rec.description) return `- ${rec.description}`;\n return `- ${JSON.stringify(rec)}`;\n}\n","import { z } from 'zod';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { callOntoApi } from '../lib/api-client.js';\nimport { formatToolError } from '../lib/errors.js';\nimport type { ReadAndScoreResponse } from '../lib/types.js';\n\nexport const readAndScoreInputSchema = z.object({\n url: z.string().url(),\n fresh: z.boolean().optional().default(false),\n});\n\nexport type ReadAndScoreInput = z.infer<typeof readAndScoreInputSchema>;\n\nexport async function readAndScore(input: ReadAndScoreInput): Promise<CallToolResult> {\n try {\n const result = await callOntoApi<ReadAndScoreResponse>('/v1/read-and-score', {\n body: { url: input.url, fresh: input.fresh },\n });\n\n const trustHint = trustLine(result.aio_score, result.hallucination_risk);\n const summaryLines = [\n `**Source quality assessment (from Onto):**`,\n `- AIO Score: ${result.aio_score}/100 (${result.grade})`,\n `- Hallucination risk: ${result.hallucination_risk}`,\n `- Reduction: ${result.stats.reduction_percent}% (${result.stats.raw_html_size_kb} KB → ${result.stats.markdown_size_kb} KB)`,\n `- Cache: ${result.cache.hit ? 'HIT' : 'MISS'}`,\n '',\n trustHint,\n ];\n\n return {\n content: [\n { type: 'text' as const, text: result.markdown },\n { type: 'text' as const, text: `\\n\\n---\\n\\n${summaryLines.join('\\n')}` },\n ],\n };\n } catch (error) {\n return formatToolError(error);\n }\n}\n\nfunction trustLine(score: number, risk: 'low' | 'medium' | 'high'): string {\n if (risk === 'high' || score < 40) {\n return 'Trust signal: low — this source is poorly structured for AI consumption. Verify any facts before relying on them.';\n }\n if (risk === 'medium' || score < 70) {\n return 'Trust signal: medium — source is partially AI-readable. Cross-check critical claims.';\n }\n return 'Trust signal: high — source is well-structured for AI consumption.';\n}\n"],"mappings":"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","names":["z","z","z","z"]}
|
package/dist/server.js
CHANGED
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts","../src/tools/read.ts","../src/lib/version.ts","../src/lib/api-client.ts","../src/lib/errors.ts","../src/tools/score.ts","../src/tools/read-and-score.ts"],"sourcesContent":["/* Onto MCP Server — exposes the Onto Read API as Model Context Protocol tools.\n *\n * Tools: read_url, score_url, read_and_score.\n * Reads ONTO_API_KEY from env. Defaults base URL to https://api.buildonto.dev.\n *\n * Install in Claude Code:\n * \"mcpServers\": {\n * \"onto\": {\n * \"command\": \"npx\",\n * \"args\": [\"-y\", \"@ontosdk/mcp\"],\n * \"env\": { \"ONTO_API_KEY\": \"onto_sk_live_...\" }\n * }\n * }\n */\n\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n ErrorCode,\n McpError,\n} from '@modelcontextprotocol/sdk/types.js';\n\nimport { readUrl, readUrlInputSchema } from './tools/read.js';\nimport { scoreUrl, scoreUrlInputSchema } from './tools/score.js';\nimport { readAndScore, readAndScoreInputSchema } from './tools/read-and-score.js';\nimport { version } from './lib/version.js';\n\nif (!process.env.ONTO_API_KEY) {\n console.error('[onto-mcp] ONTO_API_KEY environment variable is required.');\n console.error('[onto-mcp] Create a key at https://app.buildonto.dev/read/keys');\n process.exit(1);\n}\n\nconst server = new Server(\n { name: 'onto', version },\n { capabilities: { tools: {} } },\n);\n\nserver.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n {\n name: 'read_url',\n description:\n 'Read any URL and return clean, agent-ready Markdown. Strips HTML noise, preserves semantic content, and returns content optimized for AI consumption. Use this when you need to extract content from a website for an AI agent to process.',\n inputSchema: {\n type: 'object',\n properties: {\n url: {\n type: 'string',\n description: 'The URL to read. Must be a publicly accessible HTTP or HTTPS URL.',\n },\n fresh: {\n type: 'boolean',\n description: 'If true, bypass cache and fetch fresh content. Default false.',\n default: false,\n },\n },\n required: ['url'],\n },\n },\n {\n name: 'score_url',\n description:\n 'Get the AIO (AI-readability) score for any URL. Returns a 0-100 score plus a list of penalties, benefits, and recommendations describing why the source is or is not well-suited for AI consumption. Use this to evaluate source quality before relying on it.',\n inputSchema: {\n type: 'object',\n properties: {\n url: {\n type: 'string',\n description: 'The URL to score.',\n },\n },\n required: ['url'],\n },\n },\n {\n name: 'read_and_score',\n description:\n 'Read any URL and return both clean Markdown AND the AIO accuracy score in one call. The recommended default for most AI workflows — gives both content and quality assessment together, so the AI agent can decide how much to trust the content.',\n inputSchema: {\n type: 'object',\n properties: {\n url: {\n type: 'string',\n description: 'The URL to read and score.',\n },\n fresh: {\n type: 'boolean',\n description: 'If true, bypass cache and fetch fresh content. Default false.',\n default: false,\n },\n },\n required: ['url'],\n },\n },\n ],\n}));\n\nserver.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n\n try {\n switch (name) {\n case 'read_url': {\n const validated = readUrlInputSchema.parse(args ?? {});\n return await readUrl(validated);\n }\n case 'score_url': {\n const validated = scoreUrlInputSchema.parse(args ?? {});\n return await scoreUrl(validated);\n }\n case 'read_and_score': {\n const validated = readAndScoreInputSchema.parse(args ?? {});\n return await readAndScore(validated);\n }\n default:\n throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);\n }\n } catch (error) {\n if (error instanceof McpError) throw error;\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: 'text' as const, text: `Tool '${name}' failed: ${message}` }],\n isError: true,\n };\n }\n});\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n // stderr (not stdout) — stdout is reserved for MCP protocol frames\n console.error(`[onto-mcp] v${version} listening on stdio`);\n}\n\nmain().catch((err) => {\n console.error('[onto-mcp] fatal:', err);\n process.exit(1);\n});\n","import { z } from 'zod';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { callOntoApi } from '../lib/api-client.js';\nimport { formatToolError } from '../lib/errors.js';\nimport type { ReadResponse } from '../lib/types.js';\n\nexport const readUrlInputSchema = z.object({\n url: z.string().url(),\n fresh: z.boolean().optional().default(false),\n});\n\nexport type ReadUrlInput = z.infer<typeof readUrlInputSchema>;\n\nexport async function readUrl(input: ReadUrlInput): Promise<CallToolResult> {\n try {\n const result = await callOntoApi<ReadResponse>('/v1/read', {\n body: { url: input.url, fresh: input.fresh },\n });\n\n const metaLines = [\n `- URL: ${result.url}`,\n `- Title: ${result.metadata.title || '(none)'}`,\n `- Original size: ${result.stats.raw_html_size_kb} KB`,\n `- Cleaned size: ${result.stats.markdown_size_kb} KB`,\n `- Reduction: ${result.stats.reduction_percent}%`,\n `- Extraction time: ${result.stats.extraction_time_ms} ms`,\n `- Cache: ${result.cache.hit ? 'HIT' : 'MISS'}`,\n ].join('\\n');\n\n return {\n content: [\n { type: 'text' as const, text: result.markdown },\n {\n type: 'text' as const,\n text: `\\n\\n---\\n\\n**Source metadata (from Onto):**\\n${metaLines}`,\n },\n ],\n };\n } catch (error) {\n return formatToolError(error);\n }\n}\n","export const version = '1.1.1';\n","/* Thin HTTP wrapper around the Onto Read API. Reads ONTO_API_KEY at call time\n * (not module-load) so server.ts can fail with a clean error message first. */\n\nimport { version as PACKAGE_VERSION } from './version.js';\nimport type { ApiErrorBody } from './types.js';\n\nconst DEFAULT_BASE = 'https://api.buildonto.dev';\nconst REQUEST_TIMEOUT_MS = 15_000;\n\nexport class OntoApiError extends Error {\n constructor(\n message: string,\n public readonly status: number,\n public readonly code?: string,\n ) {\n super(message);\n this.name = 'OntoApiError';\n }\n}\n\ninterface CallOptions {\n body: unknown;\n signal?: AbortSignal;\n}\n\nexport async function callOntoApi<T>(endpoint: string, options: CallOptions): Promise<T> {\n const apiKey = process.env.ONTO_API_KEY;\n if (!apiKey) {\n throw new OntoApiError(\n 'ONTO_API_KEY environment variable is not set. Get a key at https://app.buildonto.dev/read/keys',\n 0,\n 'NO_API_KEY',\n );\n }\n\n const base = process.env.ONTO_API_BASE ?? DEFAULT_BASE;\n const url = `${base}${endpoint}`;\n\n const timeout = AbortSignal.timeout(REQUEST_TIMEOUT_MS);\n const signal = options.signal\n ? AbortSignal.any([options.signal, timeout])\n : timeout;\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n 'User-Agent': `@ontosdk/mcp/${PACKAGE_VERSION}`,\n },\n body: JSON.stringify(options.body),\n signal,\n });\n } catch (err) {\n if (err instanceof DOMException && err.name === 'TimeoutError') {\n throw new OntoApiError(\n `Onto API request timed out after ${REQUEST_TIMEOUT_MS / 1000}s. The target site may be slow or unreachable.`,\n 0,\n 'TIMEOUT',\n );\n }\n throw new OntoApiError(\n `Failed to reach Onto API at ${base}: ${(err as Error).message}`,\n 0,\n 'NETWORK_ERROR',\n );\n }\n\n const rawBody = await response.text();\n\n if (!response.ok) {\n let parsed: Partial<ApiErrorBody> = {};\n try {\n parsed = JSON.parse(rawBody) as Partial<ApiErrorBody>;\n } catch {\n // Body wasn't JSON; fall through with status-code-only error\n }\n\n const message = humanizeError(response.status, parsed);\n throw new OntoApiError(message, response.status, parsed.error);\n }\n\n try {\n return JSON.parse(rawBody) as T;\n } catch (err) {\n throw new OntoApiError(\n `Onto API returned invalid JSON: ${(err as Error).message}`,\n response.status,\n 'INVALID_RESPONSE',\n );\n }\n}\n\nfunction humanizeError(status: number, body: Partial<ApiErrorBody>): string {\n if (status === 401) {\n return 'Invalid Onto API key. Verify your key at https://app.buildonto.dev/read/keys';\n }\n if (status === 402) {\n return (\n body.message ??\n 'Monthly plan quota exceeded and credit balance is empty. Top up credits at https://app.buildonto.dev/read/billing'\n );\n }\n if (status === 403) {\n if (body.error === 'ROBOTS_BLOCKED') {\n return body.message ?? 'The target site blocks AI crawlers via robots.txt.';\n }\n return body.message ?? 'Forbidden.';\n }\n if (status === 429) {\n return (\n body.message ??\n 'Onto API rate limit exceeded. Upgrade your tier at https://app.buildonto.dev/read/billing or wait for the monthly reset.'\n );\n }\n if (status >= 500) {\n return body.message ?? `Onto API server error (${status}). Try again in a moment.`;\n }\n return body.message ?? `Onto API returned ${status}.`;\n}\n","/* Format errors as MCP tool responses. We don't throw McpError for\n * tool-call failures — the AI host shows tool errors to the user as\n * unhelpful internal-error messages. Returning isError: true with a\n * text body lets the model see what went wrong and recover. */\n\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { OntoApiError } from './api-client.js';\n\nexport function formatToolError(error: unknown): CallToolResult {\n if (error instanceof OntoApiError) {\n return {\n content: [{ type: 'text', text: error.message }],\n isError: true,\n };\n }\n\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n {\n type: 'text',\n text: `Onto MCP error: ${message}\\n\\nTroubleshooting:\\n- Verify ONTO_API_KEY is set and valid (https://app.buildonto.dev/read/keys)\\n- Check the target URL is publicly accessible\\n- Check your monthly quota at https://app.buildonto.dev/read/usage`,\n },\n ],\n isError: true,\n };\n}\n","import { z } from 'zod';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { callOntoApi } from '../lib/api-client.js';\nimport { formatToolError } from '../lib/errors.js';\nimport type { ScoreResponse, Recommendation } from '../lib/types.js';\n\nexport const scoreUrlInputSchema = z.object({\n url: z.string().url(),\n});\n\nexport type ScoreUrlInput = z.infer<typeof scoreUrlInputSchema>;\n\nexport async function scoreUrl(input: ScoreUrlInput): Promise<CallToolResult> {\n try {\n const result = await callOntoApi<ScoreResponse>('/v1/score', {\n body: { url: input.url },\n });\n\n return {\n content: [{ type: 'text' as const, text: formatScoreSummary(result) }],\n };\n } catch (error) {\n return formatToolError(error);\n }\n}\n\nexport function formatScoreSummary(result: ScoreResponse): string {\n const lines: string[] = [\n `**AIO Score:** ${result.aio_score}/100 (${result.grade})`,\n `**Hallucination risk:** ${result.hallucination_risk}`,\n `**URL:** ${result.url}`,\n '',\n ];\n\n if (result.benefits.length > 0) {\n lines.push('**What works well:**');\n for (const item of result.benefits) lines.push(`- ${item}`);\n lines.push('');\n }\n\n if (result.penalties.length > 0) {\n lines.push('**What hurts AI readability:**');\n for (const item of result.penalties) lines.push(`- ${item}`);\n lines.push('');\n }\n\n const insightEntries = Object.entries(result.insights ?? {});\n if (insightEntries.length > 0) {\n lines.push('**Insights:**');\n for (const [key, value] of insightEntries) {\n lines.push(`- ${key}: ${value ? 'yes' : 'no'}`);\n }\n lines.push('');\n }\n\n if (result.recommendations.length > 0) {\n lines.push('**Recommendations:**');\n for (const rec of result.recommendations) {\n lines.push(describeRecommendation(rec));\n }\n lines.push('');\n }\n\n lines.push('**Stats:**');\n lines.push(`- Raw size: ${result.stats.raw_size}`);\n lines.push(`- Efficiency: ${result.stats.efficiency}`);\n lines.push(`- Extraction time: ${result.stats.extraction_time_ms} ms`);\n\n return lines.join('\\n');\n}\n\nfunction describeRecommendation(rec: Recommendation): string {\n if (typeof rec === 'string') return `- ${rec}`;\n if (rec.title) {\n const head = rec.priority ? `**${rec.title}** _(priority: ${rec.priority})_` : `**${rec.title}**`;\n return rec.description ? `- ${head} — ${rec.description}` : `- ${head}`;\n }\n if (rec.description) return `- ${rec.description}`;\n return `- ${JSON.stringify(rec)}`;\n}\n","import { z } from 'zod';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { callOntoApi } from '../lib/api-client.js';\nimport { formatToolError } from '../lib/errors.js';\nimport type { ReadAndScoreResponse } from '../lib/types.js';\n\nexport const readAndScoreInputSchema = z.object({\n url: z.string().url(),\n fresh: z.boolean().optional().default(false),\n});\n\nexport type ReadAndScoreInput = z.infer<typeof readAndScoreInputSchema>;\n\nexport async function readAndScore(input: ReadAndScoreInput): Promise<CallToolResult> {\n try {\n const result = await callOntoApi<ReadAndScoreResponse>('/v1/read-and-score', {\n body: { url: input.url, fresh: input.fresh },\n });\n\n const trustHint = trustLine(result.aio_score, result.hallucination_risk);\n const summaryLines = [\n `**Source quality assessment (from Onto):**`,\n `- AIO Score: ${result.aio_score}/100 (${result.grade})`,\n `- Hallucination risk: ${result.hallucination_risk}`,\n `- Reduction: ${result.stats.reduction_percent}% (${result.stats.raw_html_size_kb} KB → ${result.stats.markdown_size_kb} KB)`,\n `- Cache: ${result.cache.hit ? 'HIT' : 'MISS'}`,\n '',\n trustHint,\n ];\n\n return {\n content: [\n { type: 'text' as const, text: result.markdown },\n { type: 'text' as const, text: `\\n\\n---\\n\\n${summaryLines.join('\\n')}` },\n ],\n };\n } catch (error) {\n return formatToolError(error);\n }\n}\n\nfunction trustLine(score: number, risk: 'low' | 'medium' | 'high'): string {\n if (risk === 'high' || score < 40) {\n return 'Trust signal: low — this source is poorly structured for AI consumption. Verify any facts before relying on them.';\n }\n if (risk === 'medium' || score < 70) {\n return 'Trust signal: medium — source is partially AI-readable. Cross-check critical claims.';\n }\n return 'Trust signal: high — source is well-structured for AI consumption.';\n}\n"],"mappings":"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","names":["z","z","z","z"]}
|
|
1
|
+
{"version":3,"sources":["../src/server.ts","../src/tools/read.ts","../src/lib/version.ts","../src/lib/api-client.ts","../src/lib/errors.ts","../src/tools/score.ts","../src/tools/read-and-score.ts"],"sourcesContent":["/* Onto MCP Server — exposes the Onto Read API as Model Context Protocol tools.\n *\n * Tools: read_url, score_url, read_and_score.\n * Reads ONTO_API_KEY from env. Defaults base URL to https://api.buildonto.dev.\n *\n * Install in Claude Code:\n * \"mcpServers\": {\n * \"onto\": {\n * \"command\": \"npx\",\n * \"args\": [\"-y\", \"@ontosdk/mcp\"],\n * \"env\": { \"ONTO_API_KEY\": \"onto_sk_live_...\" }\n * }\n * }\n */\n\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n ErrorCode,\n McpError,\n} from '@modelcontextprotocol/sdk/types.js';\n\nimport { readUrl, readUrlInputSchema } from './tools/read.js';\nimport { scoreUrl, scoreUrlInputSchema } from './tools/score.js';\nimport { readAndScore, readAndScoreInputSchema } from './tools/read-and-score.js';\nimport { version } from './lib/version.js';\n\nif (!process.env.ONTO_API_KEY) {\n console.error('[onto-mcp] ONTO_API_KEY environment variable is required.');\n console.error('[onto-mcp] Create a key at https://app.buildonto.dev/read/keys');\n process.exit(1);\n}\n\nconst server = new Server(\n { name: 'onto', version },\n { capabilities: { tools: {} } },\n);\n\nserver.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n {\n name: 'read_url',\n description:\n 'Read any URL and return clean, agent-ready Markdown. Strips HTML noise, preserves semantic content, and returns content optimized for AI consumption. Use this when you need to extract content from a website for an AI agent to process.',\n inputSchema: {\n type: 'object',\n properties: {\n url: {\n type: 'string',\n description: 'The URL to read. Must be a publicly accessible HTTP or HTTPS URL.',\n },\n fresh: {\n type: 'boolean',\n description: 'If true, bypass cache and fetch fresh content. Default false.',\n default: false,\n },\n },\n required: ['url'],\n },\n },\n {\n name: 'score_url',\n description:\n 'Get the AIO (AI-readability) score for any URL. Returns a 0-100 score plus a list of penalties, benefits, and recommendations describing why the source is or is not well-suited for AI consumption. Use this to evaluate source quality before relying on it.',\n inputSchema: {\n type: 'object',\n properties: {\n url: {\n type: 'string',\n description: 'The URL to score.',\n },\n },\n required: ['url'],\n },\n },\n {\n name: 'read_and_score',\n description:\n 'Read any URL and return both clean Markdown AND the AIO accuracy score in one call. The recommended default for most AI workflows — gives both content and quality assessment together, so the AI agent can decide how much to trust the content.',\n inputSchema: {\n type: 'object',\n properties: {\n url: {\n type: 'string',\n description: 'The URL to read and score.',\n },\n fresh: {\n type: 'boolean',\n description: 'If true, bypass cache and fetch fresh content. Default false.',\n default: false,\n },\n },\n required: ['url'],\n },\n },\n ],\n}));\n\nserver.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n\n try {\n switch (name) {\n case 'read_url': {\n const validated = readUrlInputSchema.parse(args ?? {});\n return await readUrl(validated);\n }\n case 'score_url': {\n const validated = scoreUrlInputSchema.parse(args ?? {});\n return await scoreUrl(validated);\n }\n case 'read_and_score': {\n const validated = readAndScoreInputSchema.parse(args ?? {});\n return await readAndScore(validated);\n }\n default:\n throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);\n }\n } catch (error) {\n if (error instanceof McpError) throw error;\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: 'text' as const, text: `Tool '${name}' failed: ${message}` }],\n isError: true,\n };\n }\n});\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n // stderr (not stdout) — stdout is reserved for MCP protocol frames\n console.error(`[onto-mcp] v${version} listening on stdio`);\n}\n\nmain().catch((err) => {\n console.error('[onto-mcp] fatal:', err);\n process.exit(1);\n});\n","import { z } from 'zod';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { callOntoApi } from '../lib/api-client.js';\nimport { formatToolError } from '../lib/errors.js';\nimport type { ReadResponse } from '../lib/types.js';\n\nexport const readUrlInputSchema = z.object({\n url: z.string().url(),\n fresh: z.boolean().optional().default(false),\n});\n\nexport type ReadUrlInput = z.infer<typeof readUrlInputSchema>;\n\nexport async function readUrl(input: ReadUrlInput): Promise<CallToolResult> {\n try {\n const result = await callOntoApi<ReadResponse>('/v1/read', {\n body: { url: input.url, fresh: input.fresh },\n });\n\n const metaLines = [\n `- URL: ${result.url}`,\n `- Title: ${result.metadata.title || '(none)'}`,\n `- Original size: ${result.stats.raw_html_size_kb} KB`,\n `- Cleaned size: ${result.stats.markdown_size_kb} KB`,\n `- Reduction: ${result.stats.reduction_percent}%`,\n `- Extraction time: ${result.stats.extraction_time_ms} ms`,\n `- Cache: ${result.cache.hit ? 'HIT' : 'MISS'}`,\n ].join('\\n');\n\n return {\n content: [\n { type: 'text' as const, text: result.markdown },\n {\n type: 'text' as const,\n text: `\\n\\n---\\n\\n**Source metadata (from Onto):**\\n${metaLines}`,\n },\n ],\n };\n } catch (error) {\n return formatToolError(error);\n }\n}\n","export const version = '1.1.2';\n","/* Thin HTTP wrapper around the Onto Read API. Reads ONTO_API_KEY at call time\n * (not module-load) so server.ts can fail with a clean error message first. */\n\nimport { version as PACKAGE_VERSION } from './version.js';\nimport type { ApiErrorBody } from './types.js';\n\nconst DEFAULT_BASE = 'https://api.buildonto.dev';\nconst REQUEST_TIMEOUT_MS = 15_000;\n\nexport class OntoApiError extends Error {\n constructor(\n message: string,\n public readonly status: number,\n public readonly code?: string,\n ) {\n super(message);\n this.name = 'OntoApiError';\n }\n}\n\ninterface CallOptions {\n body: unknown;\n signal?: AbortSignal;\n}\n\nexport async function callOntoApi<T>(endpoint: string, options: CallOptions): Promise<T> {\n const apiKey = process.env.ONTO_API_KEY;\n if (!apiKey) {\n throw new OntoApiError(\n 'ONTO_API_KEY environment variable is not set. Get a key at https://app.buildonto.dev/read/keys',\n 0,\n 'NO_API_KEY',\n );\n }\n\n const base = process.env.ONTO_API_BASE ?? DEFAULT_BASE;\n const url = `${base}${endpoint}`;\n\n const timeout = AbortSignal.timeout(REQUEST_TIMEOUT_MS);\n const signal = options.signal\n ? AbortSignal.any([options.signal, timeout])\n : timeout;\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n 'User-Agent': `@ontosdk/mcp/${PACKAGE_VERSION}`,\n },\n body: JSON.stringify(options.body),\n signal,\n });\n } catch (err) {\n if (err instanceof DOMException && err.name === 'TimeoutError') {\n throw new OntoApiError(\n `Onto API request timed out after ${REQUEST_TIMEOUT_MS / 1000}s. The target site may be slow or unreachable.`,\n 0,\n 'TIMEOUT',\n );\n }\n throw new OntoApiError(\n `Failed to reach Onto API at ${base}: ${(err as Error).message}`,\n 0,\n 'NETWORK_ERROR',\n );\n }\n\n const rawBody = await response.text();\n\n if (!response.ok) {\n let parsed: Partial<ApiErrorBody> = {};\n try {\n parsed = JSON.parse(rawBody) as Partial<ApiErrorBody>;\n } catch {\n // Body wasn't JSON; fall through with status-code-only error\n }\n\n const message = humanizeError(response.status, parsed);\n throw new OntoApiError(message, response.status, parsed.error);\n }\n\n try {\n return JSON.parse(rawBody) as T;\n } catch (err) {\n throw new OntoApiError(\n `Onto API returned invalid JSON: ${(err as Error).message}`,\n response.status,\n 'INVALID_RESPONSE',\n );\n }\n}\n\nfunction humanizeError(status: number, body: Partial<ApiErrorBody>): string {\n if (status === 401) {\n return 'Invalid Onto API key. Verify your key at https://app.buildonto.dev/read/keys';\n }\n if (status === 402) {\n return (\n body.message ??\n 'Monthly plan quota exceeded and credit balance is empty. Top up credits at https://app.buildonto.dev/read/billing'\n );\n }\n if (status === 403) {\n if (body.error === 'ROBOTS_BLOCKED') {\n return body.message ?? 'The target site blocks AI crawlers via robots.txt.';\n }\n return body.message ?? 'Forbidden.';\n }\n if (status === 429) {\n return (\n body.message ??\n 'Onto API rate limit exceeded. Upgrade your tier at https://app.buildonto.dev/read/billing or wait for the monthly reset.'\n );\n }\n if (status >= 500) {\n return body.message ?? `Onto API server error (${status}). Try again in a moment.`;\n }\n return body.message ?? `Onto API returned ${status}.`;\n}\n","/* Format errors as MCP tool responses. We don't throw McpError for\n * tool-call failures — the AI host shows tool errors to the user as\n * unhelpful internal-error messages. Returning isError: true with a\n * text body lets the model see what went wrong and recover. */\n\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { OntoApiError } from './api-client.js';\n\nexport function formatToolError(error: unknown): CallToolResult {\n if (error instanceof OntoApiError) {\n return {\n content: [{ type: 'text', text: error.message }],\n isError: true,\n };\n }\n\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n {\n type: 'text',\n text: `Onto MCP error: ${message}\\n\\nTroubleshooting:\\n- Verify ONTO_API_KEY is set and valid (https://app.buildonto.dev/read/keys)\\n- Check the target URL is publicly accessible\\n- Check your monthly quota at https://app.buildonto.dev/read/usage`,\n },\n ],\n isError: true,\n };\n}\n","import { z } from 'zod';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { callOntoApi } from '../lib/api-client.js';\nimport { formatToolError } from '../lib/errors.js';\nimport type { ScoreResponse, Recommendation } from '../lib/types.js';\n\nexport const scoreUrlInputSchema = z.object({\n url: z.string().url(),\n});\n\nexport type ScoreUrlInput = z.infer<typeof scoreUrlInputSchema>;\n\nexport async function scoreUrl(input: ScoreUrlInput): Promise<CallToolResult> {\n try {\n const result = await callOntoApi<ScoreResponse>('/v1/score', {\n body: { url: input.url },\n });\n\n return {\n content: [{ type: 'text' as const, text: formatScoreSummary(result) }],\n };\n } catch (error) {\n return formatToolError(error);\n }\n}\n\nexport function formatScoreSummary(result: ScoreResponse): string {\n const lines: string[] = [\n `**AIO Score:** ${result.aio_score}/100 (${result.grade})`,\n `**Hallucination risk:** ${result.hallucination_risk}`,\n `**URL:** ${result.url}`,\n '',\n ];\n\n if (result.benefits.length > 0) {\n lines.push('**What works well:**');\n for (const item of result.benefits) lines.push(`- ${item}`);\n lines.push('');\n }\n\n if (result.penalties.length > 0) {\n lines.push('**What hurts AI readability:**');\n for (const item of result.penalties) lines.push(`- ${item}`);\n lines.push('');\n }\n\n const insightEntries = Object.entries(result.insights ?? {});\n if (insightEntries.length > 0) {\n lines.push('**Insights:**');\n for (const [key, value] of insightEntries) {\n lines.push(`- ${key}: ${value ? 'yes' : 'no'}`);\n }\n lines.push('');\n }\n\n if (result.recommendations.length > 0) {\n lines.push('**Recommendations:**');\n for (const rec of result.recommendations) {\n lines.push(describeRecommendation(rec));\n }\n lines.push('');\n }\n\n lines.push('**Stats:**');\n lines.push(`- Raw size: ${result.stats.raw_size}`);\n lines.push(`- Efficiency: ${result.stats.efficiency}`);\n lines.push(`- Extraction time: ${result.stats.extraction_time_ms} ms`);\n\n return lines.join('\\n');\n}\n\nfunction describeRecommendation(rec: Recommendation): string {\n if (typeof rec === 'string') return `- ${rec}`;\n if (rec.title) {\n const head = rec.priority ? `**${rec.title}** _(priority: ${rec.priority})_` : `**${rec.title}**`;\n return rec.description ? `- ${head} — ${rec.description}` : `- ${head}`;\n }\n if (rec.description) return `- ${rec.description}`;\n return `- ${JSON.stringify(rec)}`;\n}\n","import { z } from 'zod';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { callOntoApi } from '../lib/api-client.js';\nimport { formatToolError } from '../lib/errors.js';\nimport type { ReadAndScoreResponse } from '../lib/types.js';\n\nexport const readAndScoreInputSchema = z.object({\n url: z.string().url(),\n fresh: z.boolean().optional().default(false),\n});\n\nexport type ReadAndScoreInput = z.infer<typeof readAndScoreInputSchema>;\n\nexport async function readAndScore(input: ReadAndScoreInput): Promise<CallToolResult> {\n try {\n const result = await callOntoApi<ReadAndScoreResponse>('/v1/read-and-score', {\n body: { url: input.url, fresh: input.fresh },\n });\n\n const trustHint = trustLine(result.aio_score, result.hallucination_risk);\n const summaryLines = [\n `**Source quality assessment (from Onto):**`,\n `- AIO Score: ${result.aio_score}/100 (${result.grade})`,\n `- Hallucination risk: ${result.hallucination_risk}`,\n `- Reduction: ${result.stats.reduction_percent}% (${result.stats.raw_html_size_kb} KB → ${result.stats.markdown_size_kb} KB)`,\n `- Cache: ${result.cache.hit ? 'HIT' : 'MISS'}`,\n '',\n trustHint,\n ];\n\n return {\n content: [\n { type: 'text' as const, text: result.markdown },\n { type: 'text' as const, text: `\\n\\n---\\n\\n${summaryLines.join('\\n')}` },\n ],\n };\n } catch (error) {\n return formatToolError(error);\n }\n}\n\nfunction trustLine(score: number, risk: 'low' | 'medium' | 'high'): string {\n if (risk === 'high' || score < 40) {\n return 'Trust signal: low — this source is poorly structured for AI consumption. Verify any facts before relying on them.';\n }\n if (risk === 'medium' || score < 70) {\n return 'Trust signal: medium — source is partially AI-readable. Cross-check critical claims.';\n }\n return 'Trust signal: high — source is well-structured for AI consumption.';\n}\n"],"mappings":"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","names":["z","z","z","z"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ontosdk/mcp",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
|
+
"mcpName": "io.github.ravixalgorithm/onto",
|
|
4
5
|
"description": "Official Onto MCP server — clean Markdown and AIO scoring for any URL, available as MCP tools for Claude Code, Cursor, and any MCP client.",
|
|
5
6
|
"type": "module",
|
|
6
7
|
"main": "./dist/index.js",
|