github_user_lookup
github_user_lookupRetrieve public GitHub user profile data by providing a username. Returns profile information for the specified user.
Instructions
Verified API tool recipes for AI agents.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| username | Yes | path |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| status | Yes | ||
| ok | Yes | ||
| body_preview | Yes |
Implementation Reference
- src/server.ts:14-34 (schema)The RECIPE object that defines the tool's configuration: name 'github_user_lookup', HTTP method GET, URL template to GitHub Users API, headers, auth type 'none', and body kind 'none'. This serves as the schema/metadata for the tool.
const RECIPE = { "name": "github_user_lookup", "description": "Verified API tool recipes for AI agents.", "method": "GET", "url_template": "https://api.github.com/users/${username}", "auth_type": "none", "bearer_token_env": null, "basic_username_env": null, "basic_password_env": null, "header_api_key_header": null, "header_api_key_env": null, "query_api_key_param": null, "query_api_key_env": null, "headers": { "Accept": "application/vnd.github+json", "User-Agent": "firstcall-demo-mcp-server" }, "query": {}, "body_kind": "none", "body_template": {} }; - src/server.ts:49-57 (schema)Input and output Zod schemas for the tool. Input accepts a 'username' (string, path param). Output returns status (number), ok (boolean), and body_preview (string).
const inputShape = { "username": z.string().describe("path") }; const inputSchema = z.object(inputShape); const outputSchema = z.object({ status: z.number(), ok: z.boolean(), body_preview: z.string(), }); - src/server.ts:59-113 (registration)Registration of the tool via server.registerTool() with the name 'github_user_lookup', its input/output schemas, annotations, and the async handler callback that executes the HTTP request.
server.registerTool(TOOL_NAME, { title: TOOL_NAME, description: TOOL_DESCRIPTION, inputSchema, outputSchema, annotations: TOOL_ANNOTATIONS, }, async (args) => { const toolArgs = args as ToolArgs; const url = new URL(fillTemplate(RECIPE.url_template, toolArgs)); for (const [key, value] of Object.entries(RECIPE.query)) { url.searchParams.append(key, fillTemplate(String(value), toolArgs)); } const headers: Record<string, string> = {}; for (const [key, value] of Object.entries(RECIPE.headers)) { headers[key] = fillTemplate(String(value), toolArgs); } applyAuth(headers, url); const init: RequestInit = { method: RECIPE.method, headers, }; if (RECIPE.body_kind !== "none") { const renderedBody = renderTemplateValue(RECIPE.body_template, toolArgs); if (RECIPE.body_kind === "text") { init.body = String(renderedBody); } else if (RECIPE.body_kind === "form") { init.body = new URLSearchParams(stringRecord(renderedBody)).toString(); setDefaultHeader(headers, "Content-Type", "application/x-www-form-urlencoded"); } else { init.body = JSON.stringify(renderedBody); setDefaultHeader(headers, "Content-Type", "application/json"); } } const response = await fetch(url, init); const bodyText = await response.text(); const redactedBodyPreview = redactResponsePreview(bodyText); const structuredContent: ToolOutput = { status: response.status, ok: response.ok, body_preview: redactedBodyPreview, }; return { content: [ { type: "text", text: JSON.stringify(structuredContent), }, ], structuredContent, }; }); - src/server.ts:65-113 (handler)The async handler function that executes the GitHub user lookup logic: fills the URL template with args, applies query params, sets headers, applies auth, makes the HTTP GET fetch request, reads the response body, redacts sensitive fields, and returns structured content with status/ok/body_preview.
}, async (args) => { const toolArgs = args as ToolArgs; const url = new URL(fillTemplate(RECIPE.url_template, toolArgs)); for (const [key, value] of Object.entries(RECIPE.query)) { url.searchParams.append(key, fillTemplate(String(value), toolArgs)); } const headers: Record<string, string> = {}; for (const [key, value] of Object.entries(RECIPE.headers)) { headers[key] = fillTemplate(String(value), toolArgs); } applyAuth(headers, url); const init: RequestInit = { method: RECIPE.method, headers, }; if (RECIPE.body_kind !== "none") { const renderedBody = renderTemplateValue(RECIPE.body_template, toolArgs); if (RECIPE.body_kind === "text") { init.body = String(renderedBody); } else if (RECIPE.body_kind === "form") { init.body = new URLSearchParams(stringRecord(renderedBody)).toString(); setDefaultHeader(headers, "Content-Type", "application/x-www-form-urlencoded"); } else { init.body = JSON.stringify(renderedBody); setDefaultHeader(headers, "Content-Type", "application/json"); } } const response = await fetch(url, init); const bodyText = await response.text(); const redactedBodyPreview = redactResponsePreview(bodyText); const structuredContent: ToolOutput = { status: response.status, ok: response.ok, body_preview: redactedBodyPreview, }; return { content: [ { type: "text", text: JSON.stringify(structuredContent), }, ], structuredContent, }; });