edubase_delete_exam_branding
Remove branding from exams to present a clean, professional appearance. Specify the exam by its ID to strip all associated branding elements.
Instructions
Remove branding from an exam.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| exam | Yes | exam identification string |
Implementation Reference
- src/tools/exams.ts:116-124 (schema)Schema definition for edubase_delete_exam_branding - defines input schema (requires 'exam' string) and output schema (empty object). The tool removes branding from an exam via DELETE /exam:branding.
// DELETE /exam:branding - Remove branding from an exam { name: 'edubase_delete_exam_branding', description: "Remove branding from an exam.", inputSchema: z.object({ exam: z.string().describe('exam identification string'), }), outputSchema: z.object({}).optional(), }, - src/tools.ts:95-108 (registration)The tool is exported as part of EDUBASE_API_TOOLS_EXAMS which is spread into the consolidated EDUBASE_API_TOOLS array, then passed through withToolAnnotations to add metadata (destructiveHint=true for DELETE methods).
export const EDUBASE_API_TOOLS = [ ...EDUBASE_API_TOOLS_COMMON, ...EDUBASE_API_TOOLS_QUESTIONS, ...EDUBASE_API_TOOLS_EXAMS, ...EDUBASE_API_TOOLS_PLAYS, ...EDUBASE_API_TOOLS_QUIZES, ...EDUBASE_API_TOOLS_USERS, ...EDUBASE_API_TOOLS_CLASSES, ...EDUBASE_API_TOOLS_ORGANIZATIONS, ...EDUBASE_API_TOOLS_INTEGRATIONS, ...EDUBASE_API_TOOLS_TAGS, ...EDUBASE_API_TOOLS_PERMISSIONS, ...EDUBASE_API_TOOLS_METRICS ] as EduBaseApiTool[]; - src/index.ts:203-264 (registration)Generic handler registration: The tool is registered via server.registerTool() using a generic handler that parses the tool name to extract HTTP method (DELETE) and endpoint (exam:branding), then calls sendEduBaseApiRequest to make the actual API call.
Object.values(EDUBASE_API_TOOLS_ANNOTATED).forEach((tool) => { /* Register tools */ server.registerTool(tool.name, { description: tool.description, inputSchema: tool.inputSchema as any, outputSchema: tool.outputSchema as any, annotations: tool.annotations, }, async (args: any, ctx: any): Promise<CallToolResult> => { try { const name = tool.name; /* Decompose request and check arguments */ if (!name.match(/^edubase_(get|post|delete)/)) { throw new Error('Invalid tool configuration'); } if (!args) { throw new Error('No arguments provided'); } /* Prepare and send API request */ const [ , method, ...endpoint ] = name.split('_'); const response = await sendEduBaseApiRequest(method, (apiUrl || EDUBASE_API_URL) + '/' + endpoint.join(':'), args, authentication); /* Return response */ if (z.object({}).strict().safeParse(tool.outputSchema).success) { /* Endpoint with empty output schema */ return { content: [{ type: 'text', text: '{}' }], structuredContent: {}, isError: false, }; } else if (response.length == 0) { /* Endpoint without response */ return { content: [{ type: 'text', text: 'Success.' }], isError: false, }; } else if (typeof response != 'object') { /* Response should be an object (hash or list) at this point */ throw new Error('Invalid response'); } else { /* Return response (schema will be validated automatically) */ return { content: [{ type: 'text', text: JSON.stringify(response) }], structuredContent: response, isError: false, }; } } catch (error) { /* Request failed */ return { content: [{ type: 'text', text: `${error instanceof Error ? error.message : String(error)}`, }], isError: true, }; } }); }); - src/index.ts:311-363 (handler)The sendEduBaseApiRequest function is the actual HTTP handler: it converts the method to uppercase (DELETE), sends the request to the EduBase API endpoint (exam:branding), and returns the response.
async function sendEduBaseApiRequest(method: string, endpoint: string, data: object, authentication: EduBaseAuthentication | null) { /* Check method and endpoint */ method = method.toUpperCase() if (!['GET', 'POST', 'DELETE'].includes(method)) { throw new Error('Invalid method: "' + method + '"'); } if (endpoint.length == 0) { throw new Error('Invalid endpoint'); } /* Check rate limit */ checkRateLimit(); /* Prepare authentication (prefer EDUBASE_API_APP and EDUBASE_API_KEY environment variables) */ if (!authentication) { authentication = { app: EDUBASE_API_APP, secret: EDUBASE_API_KEY }; } else { if (!authentication.hasOwnProperty('app') || authentication.app.length == 0 || EDUBASE_API_APP.length > 0) { authentication.app = EDUBASE_API_APP; } if (!authentication.hasOwnProperty('secret') || authentication.secret.length == 0 || EDUBASE_API_KEY.length > 0) { authentication.secret = EDUBASE_API_KEY; } } /* Send request with input data */ let headers = { 'Content-Type': 'application/json', 'Accept-Encoding': 'gzip', 'EduBase-API-Client': 'MCP', 'EduBase-API-Transport': (STREAMABLE_HTTP) ? 'Streamable HTTP' : ((SSE) ? 'SSE' : 'Stdio'), 'EduBase-API-App': authentication.app, 'EduBase-API-Secret': authentication.secret }; const response = await fetch(endpoint + (method == 'GET' ? '?' + queryString.stringify(data) : ''), { method: method, body: (method != 'GET' ? JSON.stringify(data) : undefined), headers: headers }); if (!response.ok) { throw new Error(`EduBase API error: ${response.status} ${response.statusText}` + (response.headers.has('EduBase-API-Error') ? ` (${response.headers.get('EduBase-API-Error')})` : '')); } /* Parse response and return as object */ let clonedResponse = response.clone(); try { /* First try to decode as JSON */ return await response.json(); } catch (error) { /* Response might be empty string with a 200 status code */ return await clonedResponse.text(); } } - src/tools.ts:70-83 (helper)The inferToolAnnotations helper function marks DELETE tools as destructiveHint: true and idempotentHint: true, which applies to edubase_delete_exam_branding.
function inferToolAnnotations(tool: EduBaseApiTool): EduBaseToolAnnotations { const method = getToolMethod(tool.name); const readOnly = method === 'get'; const destructive = method === 'delete'; const idempotent = method === 'get' || method === 'delete'; return { title: getToolTitle(tool), readOnlyHint: readOnly, destructiveHint: readOnly ? false : destructive, idempotentHint: idempotent, openWorldHint: false, }; }