fetch_url
Fetch data from web URLs using HTTP methods like GET, POST, PUT, DELETE, or PATCH with configurable headers, body content, and timeout settings.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | ||
| method | No | GET | |
| headers | No | ||
| body | No | ||
| timeout | No | ||
| followRedirects | No |
Implementation Reference
- src/tools/web-tools.ts:30-56 (handler)Core execution logic for the fetch_url tool: fetches the URL with given options, reads response text, extracts headers, and returns structured content and metadata.async ({ url, method, headers, body, timeout, followRedirects }) => { return wrapToolExecution(async () => { const response = await fetchWithTimeout(url, { method, headers, body, timeout, followRedirects }); const responseText = await response.text(); const responseHeaders = extractHeaders(response); return { content: [{ type: "text" as const, text: responseText }], metadata: { status: response.status, statusText: response.statusText, headers: responseHeaders, url: response.url } }; }, { errorCode: ERROR_CODES.HTTP_REQUEST, context: "Failed to fetch URL" }); }
- src/tools/web-tools.ts:23-28 (schema)Zod input schema defining parameters for the fetch_url tool: url (required URL), method, headers, body, timeout, followRedirects.url: z.string().url("Valid URL is required"), method: z.enum(["GET", "POST", "PUT", "DELETE", "PATCH"]).optional().default(DEFAULTS.HTTP_METHOD), headers: z.record(z.string()).optional().default({}), body: z.string().optional(), timeout: z.number().optional().default(DEFAULT_TIMEOUTS.HTTP_REQUEST), followRedirects: z.boolean().optional().default(DEFAULTS.HTTP_FOLLOW_REDIRECTS)
- src/tools/web-tools.ts:20-58 (registration)registerFetchUrl function that registers the fetch_url tool on the MCP server using server.tool, providing name, input schema, and handler.function registerFetchUrl(server: McpServer): void { server.tool("fetch_url", { url: z.string().url("Valid URL is required"), method: z.enum(["GET", "POST", "PUT", "DELETE", "PATCH"]).optional().default(DEFAULTS.HTTP_METHOD), headers: z.record(z.string()).optional().default({}), body: z.string().optional(), timeout: z.number().optional().default(DEFAULT_TIMEOUTS.HTTP_REQUEST), followRedirects: z.boolean().optional().default(DEFAULTS.HTTP_FOLLOW_REDIRECTS) }, async ({ url, method, headers, body, timeout, followRedirects }) => { return wrapToolExecution(async () => { const response = await fetchWithTimeout(url, { method, headers, body, timeout, followRedirects }); const responseText = await response.text(); const responseHeaders = extractHeaders(response); return { content: [{ type: "text" as const, text: responseText }], metadata: { status: response.status, statusText: response.statusText, headers: responseHeaders, url: response.url } }; }, { errorCode: ERROR_CODES.HTTP_REQUEST, context: "Failed to fetch URL" }); } ); }
- src/tools/web-tools.ts:63-99 (helper)Supporting helper that performs the actual HTTP fetch with timeout using AbortController, handles redirects, and proper error/timeout management.async function fetchWithTimeout( url: string, options: { method: HttpMethod; headers?: Record<string, string>; body?: string; timeout: number; followRedirects: boolean; } ): Promise<Response> { const { method, headers, body, timeout, followRedirects } = options; const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), timeout); const requestInit: RequestInit = { method, headers, signal: controller.signal, redirect: followRedirects ? "follow" : "manual" }; if (body && ["POST", "PUT", "PATCH"].includes(method)) { requestInit.body = body; } try { const response = await fetch(url, requestInit); return response; } catch (error) { if (error instanceof Error && error.name === 'AbortError') { throw new Error(`Request timeout after ${timeout}ms`); } throw error; } finally { clearTimeout(timeoutId); } }
- src/tools/web-tools.ts:104-110 (helper)Utility helper to extract and convert Response headers into a plain Record<string, string> object.function extractHeaders(response: Response): Record<string, string> { const headers: Record<string, string> = {}; response.headers.forEach((value, key) => { headers[key] = value; }); return headers; }