exchange_token
Exchange a short-lived access token for a long-lived token to extend its validity.
Instructions
Exchange a short-lived access token for a long-lived token. Requires META_APP_ID and META_APP_SECRET to be configured.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| short_lived_token | Yes | Short-lived access token to exchange |
Implementation Reference
- src/tools/auth.ts:5-21 (registration)Registration of the 'exchange_token' tool on the MCP server via server.tool(), defining name, description, Zod schema, and handler.
export function registerAuthTools(server: McpServer, client: AdsClient): void { // ─── exchange_token ─────────────────────────────────────────── server.tool( "exchange_token", "Exchange a short-lived access token for a long-lived token. Requires META_APP_ID and META_APP_SECRET to be configured.", { short_lived_token: z.string().describe("Short-lived access token to exchange"), }, async ({ short_lived_token }) => { try { const { data } = await client.exchangeToken(short_lived_token); return { content: [{ type: "text" as const, text: JSON.stringify(data, null, 2) }] }; } catch (error) { return { content: [{ type: "text" as const, text: `Failed: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } ); - src/tools/auth.ts:10-12 (schema)Zod input schema for exchange_token: requires a single string parameter 'short_lived_token'.
{ short_lived_token: z.string().describe("Short-lived access token to exchange"), }, - src/tools/auth.ts:13-20 (handler)Handler function that calls client.exchangeToken(short_lived_token) and returns the JSON result.
async ({ short_lived_token }) => { try { const { data } = await client.exchangeToken(short_lived_token); return { content: [{ type: "text" as const, text: JSON.stringify(data, null, 2) }] }; } catch (error) { return { content: [{ type: "text" as const, text: `Failed: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } - src/services/ads-client.ts:246-272 (helper)Core implementation of the token exchange API call: builds URL with fb_exchange_token grant type, calls Facebook's /oauth/access_token endpoint, validates response, and returns data.
/** Exchange short-lived token for long-lived token */ async exchangeToken(shortToken: string): Promise<ClientResponse> { if (!this.config.appId || !this.config.appSecret) { throw new Error( "META_APP_ID and META_APP_SECRET are required for token exchange." ); } const qs = new URLSearchParams({ grant_type: "fb_exchange_token", client_id: this.config.appId, client_secret: this.config.appSecret, fb_exchange_token: shortToken, }); const url = `${this.baseUrl}/oauth/access_token?${qs.toString()}`; const res = await fetch(url, { signal: AbortSignal.timeout(30_000) }); if (!res.ok) { const text = await res.text().catch(() => ""); throw new Error(`Token exchange failed (${res.status}): ${text}`); } const data = await res.json(); if (data.error) { throw new Error(this.formatError(data)); } return { data }; } - src/index.ts:93-94 (registration)Registration call of registerAuthTools(server, client) in the main entry point to wire the tool into the MCP server.
registerAuthTools(server, client);