Skip to main content
Glama
acchuang

Jina AI Remote MCP Server

by acchuang

capture_screenshot_url

Capture web page screenshots in base64 JPEG format for visual inspection, analysis, or display. Specify URL and choose single-screen or full-page capture options.

Instructions

Capture high-quality screenshots of web pages in base64 encoded JPEG format. Use this tool when you need to visually inspect a website, take a snapshot for analysis, or show users what a webpage looks like.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
urlYesThe complete HTTP/HTTPS URL of the webpage to capture (e.g., 'https://example.com')
firstScreenOnlyNoSet to true for a single screen capture (faster), false for full page capture including content below the fold
return_urlNoSet to true to return screenshot URLs instead of downloading images as base64

Implementation Reference

  • The core handler function that implements capture_screenshot_url tool logic: calls r.jina.ai API with URL, handles response to get screenshot URL, downloads the image, encodes as base64 PNG, and returns as MCP image content with error handling.
    async ({ url, firstScreenOnly }: { url: string; firstScreenOnly?: boolean }) => {
    	try {
    		const props = getProps();
    		const headers: Record<string, string> = {
    			'Accept': 'application/json',
    			'Content-Type': 'application/json',
    			'X-Return-Format': firstScreenOnly === true ? 'screenshot' : 'pageshot',
    		};
    
    		// Add Authorization header if bearer token is available
    		if (props.bearerToken) {
    			headers['Authorization'] = `Bearer ${props.bearerToken}`;
    		}
    
    		const response = await fetch('https://r.jina.ai/', {
    			method: 'POST',
    			headers,
    			body: JSON.stringify({ url }),
    		});
    
    		if (!response.ok) {
    			return handleApiError(response, "Screenshot capture");
    		}
    
    		const data = await response.json() as any;
    
    		// Fetch and return the screenshot as base64-encoded image
    		const imageUrl = data.data.screenshotUrl || data.data.pageshotUrl;
    		if (imageUrl) {
    			try {
    				// Download the image from the URL
    				const imageResponse = await fetch(imageUrl);
    				if (!imageResponse.ok) {
    					return {
    						content: [
    							{
    								type: "text" as const,
    								text: `Error: Failed to download screenshot from ${imageUrl}`,
    							},
    						],
    						isError: true,
    					};
    				}
    
    				// Convert to base64
    				const imageBuffer = await imageResponse.arrayBuffer();
    				const base64Image = Buffer.from(imageBuffer).toString('base64');
    
    				return {
    					content: [
    						{
    							type: "image" as const,
    							data: base64Image,
    							mimeType: "image/png",
    						},
    					],
    				};
    			} catch (downloadError) {
    				return {
    					content: [
    						{
    							type: "text" as const,
    							text: `Error downloading screenshot: ${downloadError instanceof Error ? downloadError.message : String(downloadError)}`,
    						},
    					],
    					isError: true,
    				};
    			}
    		} else {
    			return {
    				content: [
    					{
    						type: "text" as const,
    						text: "Error: No screenshot URL received from API",
    					},
    				],
    				isError: true,
    			};
    		}
    	} catch (error) {
    		return {
    			content: [
    				{
    					type: "text" as const,
    					text: `Error: ${error instanceof Error ? error.message : String(error)}`,
    				},
    			],
    			isError: true,
    		};
    	}
    },
  • Zod schema defining input parameters for the tool: required 'url' (string URL) and optional 'firstScreenOnly' (boolean).
    {
    	url: z.string().url().describe("The complete HTTP/HTTPS URL of the webpage to capture (e.g., 'https://example.com')"),
    	firstScreenOnly: z.boolean().optional().describe("Set to true for a single screen capture (faster), false for full page capture including content below the fold (default: false)")
    },
  • Registers the 'capture_screenshot_url' tool on the MCP server using server.tool(), providing name, description, input schema, and handler function.
    server.tool(
    	"capture_screenshot_url",
    	"Capture high-quality screenshots of web pages. Use this tool when you need to visually inspect a website, take a snapshot for analysis, or show users what a webpage looks like. Returns the screenshot as a base64-encoded PNG image that can be displayed directly.",
    	{
    		url: z.string().url().describe("The complete HTTP/HTTPS URL of the webpage to capture (e.g., 'https://example.com')"),
    		firstScreenOnly: z.boolean().optional().describe("Set to true for a single screen capture (faster), false for full page capture including content below the fold (default: false)")
    	},
    	async ({ url, firstScreenOnly }: { url: string; firstScreenOnly?: boolean }) => {
    		try {
    			const props = getProps();
    			const headers: Record<string, string> = {
    				'Accept': 'application/json',
    				'Content-Type': 'application/json',
    				'X-Return-Format': firstScreenOnly === true ? 'screenshot' : 'pageshot',
    			};
    
    			// Add Authorization header if bearer token is available
    			if (props.bearerToken) {
    				headers['Authorization'] = `Bearer ${props.bearerToken}`;
    			}
    
    			const response = await fetch('https://r.jina.ai/', {
    				method: 'POST',
    				headers,
    				body: JSON.stringify({ url }),
    			});
    
    			if (!response.ok) {
    				return handleApiError(response, "Screenshot capture");
    			}
    
    			const data = await response.json() as any;
    
    			// Fetch and return the screenshot as base64-encoded image
    			const imageUrl = data.data.screenshotUrl || data.data.pageshotUrl;
    			if (imageUrl) {
    				try {
    					// Download the image from the URL
    					const imageResponse = await fetch(imageUrl);
    					if (!imageResponse.ok) {
    						return {
    							content: [
    								{
    									type: "text" as const,
    									text: `Error: Failed to download screenshot from ${imageUrl}`,
    								},
    							],
    							isError: true,
    						};
    					}
    
    					// Convert to base64
    					const imageBuffer = await imageResponse.arrayBuffer();
    					const base64Image = Buffer.from(imageBuffer).toString('base64');
    
    					return {
    						content: [
    							{
    								type: "image" as const,
    								data: base64Image,
    								mimeType: "image/png",
    							},
    						],
    					};
    				} catch (downloadError) {
    					return {
    						content: [
    							{
    								type: "text" as const,
    								text: `Error downloading screenshot: ${downloadError instanceof Error ? downloadError.message : String(downloadError)}`,
    							},
    						],
    						isError: true,
    					};
    				}
    			} else {
    				return {
    					content: [
    						{
    							type: "text" as const,
    							text: "Error: No screenshot URL received from API",
    						},
    					],
    					isError: true,
    				};
    			}
    		} catch (error) {
    			return {
    				content: [
    					{
    						type: "text" as const,
    						text: `Error: ${error instanceof Error ? error.message : String(error)}`,
    					},
    				],
    				isError: true,
    			};
    		}
    	},
    );
  • src/index.ts:21-21 (registration)
    Calls registerJinaTools in the MCP agent's init() method, which registers all Jina tools including capture_screenshot_url.
    registerJinaTools(this.server, () => this.props);

Latest Blog Posts

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

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