Skip to main content
Glama

Jina Free MCP

by ubuygold
index.ts3.03 kB
#!/usr/bin/env bun import { z } from "zod"; import pkg from "./package.json"; import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; // Define the schema for the component's input using Zod. const InputSchema = z.object({ url: z.string().url({ message: "A valid URL is required." }), }); // Define the schema for the component's successful output. const OutputSchema = z.object({ content: z.array( z.object({ type: z.literal("text"), text: z.string(), }), ), }); /** * The core logic for reading webpage content. * This function is now cleaner, without direct console logging. * It focuses on doing one thing: fetching the content or throwing an error. * @param url The URL of the webpage to read. * @returns A promise that resolves to the plain text content of the page. */ export async function readWebpageContent(url: string): Promise<string> { const jinaUrl = `https://r.jina.ai/${url}`; const response = await fetch(jinaUrl, { headers: { Accept: "text/plain", }, }); if (!response.ok) { throw new Error( `Jina Reader API request failed with status ${response.status}: ${response.statusText}`, ); } const content = await response.text(); // Case 1: Structured JSON error from Jina. try { const jsonData = JSON.parse(content); if (jsonData && jsonData.name && jsonData.code && jsonData.message) { throw new Error( `Jina API Error: ${jsonData.readableMessage || jsonData.message}`, ); } } catch (e) { if (!(e instanceof SyntaxError)) { throw e; } } // Case 2: Empty or minimal HTML content. const textOnly = content.replace(/<[^>]*>/g, "").trim(); if (!textOnly) { throw new Error( "Jina Reader returned empty or minimal content, likely due to an upstream error (e.g., 404 Not Found).", ); } return content; } // Create a server instance with basic metadata. const server = new McpServer({ name: "jina-free-mcp", version: pkg.version, }); // Define the tool for reading a webpage. server.tool( "read-webpage", "Reads the content of a given URL using the Jina Reader API.", { input: InputSchema, output: OutputSchema, }, async (args: { input: z.infer<typeof InputSchema> }) => { // Execute the core logic with the validated input. const { input } = args; const content = await readWebpageContent(input.url); // Return the result in the standard MCP content format. return { content: [ { type: "text", text: content, }, ], }; }, ); // Main execution block to connect the server to a transport. async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error("MCP Server 'jina-free-mcp' is running on stdio."); } main().catch((error) => { console.error("Fatal error in main():", error); process.exit(1); });

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/ubuygold/jina-free-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server