coda_duplicate_page
Duplicate a page within a Coda document by specifying the original page and a new name. Solves the need to copy existing content for reuse.
Instructions
Duplicate a page in the current document
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| docId | Yes | The ID of the document that contains the page to duplicate | |
| pageIdOrName | Yes | The ID or name of the page to duplicate | |
| newName | Yes | The name of the new page |
Implementation Reference
- src/server.ts:231-256 (handler)Handler for coda_duplicate_page tool. Fetches page content via getPageContent helper and creates a new page with that content as a canvas markdown page.
server.tool( "coda_duplicate_page", "Duplicate a page in the current document", { docId: z.string().describe("The ID of the document that contains the page to duplicate"), pageIdOrName: z.string().describe("The ID or name of the page to duplicate"), newName: z.string().describe("The name of the new page"), }, async ({ docId, pageIdOrName, newName }): Promise<CallToolResult> => { try { const pageContent = await getPageContent(docId, pageIdOrName); const createResp = await createPage({ path: { docId }, body: { name: newName, pageContent: { type: "canvas", canvasContent: { format: "markdown", content: pageContent } }, }, throwOnError: true, }); return { content: [{ type: "text", text: JSON.stringify(createResp.data) }] }; } catch (error) { return { content: [{ type: "text", text: `Failed to duplicate page: ${error}` }], isError: true }; } }, ); - src/server.ts:231-256 (registration)Registration of the coda_duplicate_page tool using server.tool() from the MCP SDK.
server.tool( "coda_duplicate_page", "Duplicate a page in the current document", { docId: z.string().describe("The ID of the document that contains the page to duplicate"), pageIdOrName: z.string().describe("The ID or name of the page to duplicate"), newName: z.string().describe("The name of the new page"), }, async ({ docId, pageIdOrName, newName }): Promise<CallToolResult> => { try { const pageContent = await getPageContent(docId, pageIdOrName); const createResp = await createPage({ path: { docId }, body: { name: newName, pageContent: { type: "canvas", canvasContent: { format: "markdown", content: pageContent } }, }, throwOnError: true, }); return { content: [{ type: "text", text: JSON.stringify(createResp.data) }] }; } catch (error) { return { content: [{ type: "text", text: `Failed to duplicate page: ${error}` }], isError: true }; } }, ); - src/server.ts:234-238 (schema)Zod schema for tool inputs: docId, pageIdOrName, and newName.
{ docId: z.string().describe("The ID of the document that contains the page to duplicate"), pageIdOrName: z.string().describe("The ID or name of the page to duplicate"), newName: z.string().describe("The name of the new page"), }, - src/helpers.ts:4-76 (helper)Helper function that exports a page to markdown and returns the content, used by the duplicate_page handler.
export async function getPageContent(docId: string, pageIdOrName: string) { let requestId: string | undefined; try { // Begin page export const beginExportResp = await beginPageContentExport({ path: { docId, pageIdOrName, }, body: { outputFormat: "markdown", }, throwOnError: true, }); if (!beginExportResp.data) { throw new Error("Failed to begin page content export"); } requestId = beginExportResp.data.id; } catch (error) { throw new Error(`Failed to get page content: ${error}`, { cause: error }); } // Poll for export status let retries = 0; const maxRetries = 5; let downloadLink: string | undefined; while (retries < maxRetries) { // Wait for 5 seconds await new Promise((resolve) => setTimeout(resolve, 5000)); try { const exportStatusResp = await getPageContentExportStatus({ path: { docId, pageIdOrName, requestId, }, throwOnError: true, }); if (exportStatusResp.data?.status === "complete") { downloadLink = exportStatusResp.data.downloadLink; break; } } catch (error) { throw new Error(`Failed to get page content export status: ${error}`, { cause: error }); } retries++; if (retries >= maxRetries) { throw new Error(`Page content export did not complete after ${maxRetries} retries.`); } } if (!downloadLink) { throw new Error("Failed to get page content export status"); } try { const downloadResponse = await axios.get<string>(downloadLink, { responseType: "text", }); const markdownContent = downloadResponse.data; return markdownContent; } catch { throw new Error(`Failed to download exported page content from ${downloadLink}. `); } }