Skip to main content
Glama
utils.ts5.83 kB
import fetch, { Response } from 'node-fetch'; import { USER_AGENT } from '../server.js'; import { wikiService } from './wikiService.js'; import { getMwn } from './mwn.js'; type RequestConfig = { headers: Record<string, string>; body: Record<string, unknown> | undefined; }; async function withAuth( headers: Record<string, string>, body: Record<string, unknown> | undefined, needAuth: boolean ): Promise<RequestConfig> { const { private: privateWiki, token } = wikiService.getCurrent().config; if ( !needAuth && !privateWiki ) { return { headers, body }; } if ( token !== undefined && token !== null ) { // OAuth2 authentication - just add Bearer token return { headers: { ...headers, Authorization: `Bearer ${ token }` }, body }; } // Cookie-based authentication - add cookies and CSRF token const cookies = await getCookiesFromJar(); if ( cookies === undefined ) { return { headers, body }; } return { headers: { ...headers, Cookie: cookies }, body: body ? { ...body, token: await getCsrfToken() } : body }; } async function getCsrfToken(): Promise<string> { const mwn = await getMwn(); return await mwn.getCsrfToken(); } async function getCookiesFromJar(): Promise<string | undefined> { const mwn = await getMwn(); const cookieJar = mwn.cookieJar; if ( !cookieJar ) { return undefined; } const { server, scriptpath } = wikiService.getCurrent().config; // Get cookies for the REST API URL const restApiUrl = `${ server }${ scriptpath }/rest.php`; const cookies = cookieJar.getCookieStringSync( restApiUrl ); if ( cookies ) { return cookies; } // Fallback: try getting cookies for the domain return cookieJar.getCookieStringSync( server ) || undefined; } async function fetchCore( baseUrl: string, options?: { params?: Record<string, string>; headers?: Record<string, string>; body?: Record<string, unknown>; method?: string; } ): Promise<Response> { let url = baseUrl; if ( url.startsWith( '//' ) ) { url = 'https:' + url; } if ( options?.params ) { const queryString = new URLSearchParams( options.params ).toString(); if ( queryString ) { url = `${ url }?${ queryString }`; } } const requestHeaders: Record<string, string> = { 'User-Agent': USER_AGENT }; if ( options?.headers ) { Object.assign( requestHeaders, options.headers ); } const fetchOptions: { headers: Record<string, string>; method?: string; body?: string } = { headers: requestHeaders, method: options?.method || 'GET' }; if ( options?.body ) { fetchOptions.body = JSON.stringify( options.body ); } const response = await fetch( url, fetchOptions ); if ( !response.ok ) { const errorBody = await response.text().catch( () => 'Could not read error response body' ); throw new Error( `HTTP error! status: ${ response.status } for URL: ${ response.url }. Response: ${ errorBody }` ); } return response; } export async function makeApiRequest<T>( url: string, params?: Record<string, string> ): Promise<T> { const response = await fetchCore( url, { params, headers: { Accept: 'application/json' } } ); return ( await response.json() ) as T; } export async function makeRestGetRequest<T>( path: string, params?: Record<string, string>, needAuth: boolean = false ): Promise<T> { const headers: Record<string, string> = { Accept: 'application/json' }; const { headers: authHeaders } = await withAuth( headers, undefined, needAuth ); const { server, scriptpath } = wikiService.getCurrent().config; const response = await fetchCore( `${ server }${ scriptpath }/rest.php${ path }`, { params, headers: authHeaders } ); return ( await response.json() ) as T; } export async function makeRestPutRequest<T>( path: string, body: Record<string, unknown>, needAuth: boolean = false ): Promise<T> { const headers: Record<string, string> = { Accept: 'application/json', 'Content-Type': 'application/json' }; const { headers: authHeaders, body: authBody } = await withAuth( headers, body, needAuth ); const { server, scriptpath } = wikiService.getCurrent().config; const response = await fetchCore( `${ server }${ scriptpath }/rest.php${ path }`, { headers: authHeaders, method: 'PUT', body: authBody } ); return ( await response.json() ) as T; } export async function makeRestPostRequest<T>( path: string, body?: Record<string, unknown>, needAuth: boolean = false ): Promise<T> { const headers: Record<string, string> = { Accept: 'application/json', 'Content-Type': 'application/json' }; const { headers: authHeaders, body: authBody } = await withAuth( headers, body, needAuth ); const { server, scriptpath } = wikiService.getCurrent().config; const response = await fetchCore( `${ server }${ scriptpath }/rest.php${ path }`, { headers: authHeaders, method: 'POST', body: authBody } ); return ( await response.json() ) as T; } export async function fetchPageHtml( url: string ): Promise<string | null> { try { const response = await fetchCore( url ); return await response.text(); } catch { return null; } } export async function fetchImageAsBase64( url: string ): Promise<string | null> { try { const response = await fetchCore( url ); const arrayBuffer = await response.arrayBuffer(); const buffer = Buffer.from( arrayBuffer ); return buffer.toString( 'base64' ); } catch { return null; } } export function getPageUrl( title: string ): string { const { server, articlepath } = wikiService.getCurrent().config; return `${ server }${ articlepath }/${ encodeURIComponent( title ) }`; } export function formatEditComment( tool: string, comment?: string ): string { const suffix = `(via ${ tool } on MediaWiki MCP Server)`; if ( !comment ) { return `Automated edit ${ suffix }`; } return `${ comment } ${ suffix }`; }

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/ProfessionalWiki/MediaWiki-MCP-Server'

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