import { DocsTitle, DocsLead, DocsH2, DocsP, DocsList, DocsLi, DocsCode, Mono, } from '@/components/docs-page'; export const metadata = { title: 'Authoring tools — BuildMyMCPServer docs' }; export default function Authoring() { return ( <> Authoring tools What you write in the prompt is what Claude turns into TypeScript. Better prompts mean better tools. These patterns cover 80% of the common asks. Anatomy of a tool Each generated tool ends up looking like this: { try { const res = await fetch('https://api.notion.com/v1/search', { method: 'POST', signal: AbortSignal.timeout(10000), headers: { 'Authorization': \`Bearer \${process.env.NOTION_API_KEY}\`, 'Notion-Version': '2022-06-28', 'Content-Type': 'application/json', }, body: JSON.stringify({ query: args.query }), }); const data = await res.json(); return { content: [{ type: 'text', text: JSON.stringify(data.results) }] }; } catch (err) { const msg = err instanceof Error ? err.message : String(err); return { content: [{ type: 'text', text: 'Error: ' + msg }], isError: true }; } }, );`} /> Rules the generator enforces No eval, no new Function, no child_process. The static check rejects the build. No import statements in tool bodies — the runtime injects fetch, pg, z. Secrets live in process.env. Never embedded literally. External HTTP calls must use AbortSignal.timeout. Default 10s. Database access via pg with parameterized queries only. Errors return as MCP error-content, not thrown exceptions. Prompt patterns that work Be explicit about tool names. "Tool: search_pages(query)" beats "give me a search tool". Name the credentials. "Auth: NOTION_API_KEY" tells the generator what to put in requiredSecrets. Saves an iteration. Say if a tool is destructive. "Tool: delete_page(page_id) — destructive, permanently removes the page" surfaces the warning to the AI client. One server per integration, not per tool. A Notion server with five tools is cleaner than five Notion servers each with one tool. Iterate on a live server Open the server detail page, click the Iterate tab, describe what you want to add. A new build version is queued, rolling-deployed, the old version stays live until the new one is healthy. ); }