# Directory Structure ``` ├── .gitignore ├── package.json ├── pnpm-lock.yaml ├── README.md ├── src │ └── server.ts └── tsconfig.json ``` # Files -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- ``` 1 | node_modules/ 2 | build/ 3 | *.log 4 | .env* ``` -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- ```markdown 1 | # Jina Reader MCP Server 2 | 3 | Fetch the content of a remote URL as Markdown with Jina Reader 4 | ``` -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "compilerOptions": { 3 | "target": "ES2022", 4 | "module": "Node16", 5 | "moduleResolution": "Node16", 6 | "outDir": "./build", 7 | "rootDir": "./src", 8 | "strict": true, 9 | "esModuleInterop": true, 10 | "skipLibCheck": true, 11 | "forceConsistentCasingInFileNames": true 12 | }, 13 | "include": ["src/**/*"], 14 | "exclude": ["node_modules"] 15 | } 16 | ``` -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "name": "mcp-jina-reader", 3 | "version": "0.1.0", 4 | "description": "Fetch the content of a remote URL as Markdown with Jina Reader", 5 | "private": true, 6 | "type": "module", 7 | "files": [], 8 | "scripts": {}, 9 | "dependencies": { 10 | "litemcp": "^0.7.0", 11 | "zod": "^3.23.8" 12 | }, 13 | "devDependencies": { 14 | "@types/node": "^20.11.24", 15 | "prettier": "^3.4.1", 16 | "typescript": "^5.3.3" 17 | }, 18 | "packageManager": "[email protected]+sha512.c8180b3fbe4e4bca02c94234717896b5529740a6cbadf19fa78254270403ea2f27d4e1d46a08a0f56c89b63dc8ebfd3ee53326da720273794e6200fcf0d184ab" 19 | } 20 | ``` -------------------------------------------------------------------------------- /src/server.ts: -------------------------------------------------------------------------------- ```typescript 1 | import { LiteMCP } from "litemcp"; 2 | import { z } from "zod"; 3 | 4 | async function fetchWithJinaReader(url: string): Promise<string> { 5 | const apiKey = process.env.JINA_API_KEY; 6 | console.error(`Fetching ${url}`, apiKey ? "with API key" : "without API key"); 7 | const response = await fetch(`https://r.jina.ai/${url}`, { 8 | headers: apiKey ? { Authorization: `Bearer ${apiKey}` } : undefined, 9 | }); 10 | if (!response.ok) { 11 | throw new Error(`Failed to fetch ${url}: ${response.statusText}`); 12 | } 13 | return response.text(); 14 | } 15 | 16 | const server = new LiteMCP("mcp-jina-reader", "0.1.0"); 17 | 18 | server.addTool({ 19 | name: "fetch_url_content", 20 | description: "Fetch the content of a URL as Markdown.", 21 | parameters: z.object({ 22 | url: z.string().url(), 23 | }), 24 | execute(args) { 25 | return fetchWithJinaReader(args.url); 26 | }, 27 | }); 28 | 29 | server.addPrompt({ 30 | name: "fetch_url_content", 31 | description: "Fetch the content of a URL as Markdown.", 32 | arguments: [ 33 | { 34 | name: "url", 35 | description: "The URL to fetch the content of.", 36 | required: true, 37 | }, 38 | ], 39 | async load(args) { 40 | const content = await fetchWithJinaReader(args.url); 41 | return `Content of ${args.url}:\n${content}`; 42 | }, 43 | }); 44 | 45 | server.start(); 46 | ```