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 (
    <>
      <DocsTitle kicker="Build">Authoring tools</DocsTitle>
      <DocsLead>
        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.
      </DocsLead>

      <DocsH2 id="anatomy">Anatomy of a tool</DocsH2>
      <DocsP>Each generated tool ends up looking like this:</DocsP>
      <DocsCode
        label="generated TypeScript"
        code={`server.registerTool(
  'search_pages',
  {
    title: 'search_pages',
    description: 'Search Notion pages matching a query.',
    inputSchema: {
      query: z.string().describe('search terms'),
    },
  },
  async (args) => {
    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 };
    }
  },
);`}
      />

      <DocsH2 id="rules">Rules the generator enforces</DocsH2>
      <DocsList>
        <DocsLi>No <Mono>eval</Mono>, no <Mono>new Function</Mono>, no <Mono>child_process</Mono>. The static check rejects the build.</DocsLi>
        <DocsLi>No <Mono>import</Mono> statements in tool bodies — the runtime injects <Mono>fetch</Mono>, <Mono>pg</Mono>, <Mono>z</Mono>.</DocsLi>
        <DocsLi>Secrets live in <Mono>process.env</Mono>. Never embedded literally.</DocsLi>
        <DocsLi>External HTTP calls must use <Mono>AbortSignal.timeout</Mono>. Default 10s.</DocsLi>
        <DocsLi>Database access via <Mono>pg</Mono> with parameterized queries only.</DocsLi>
        <DocsLi>Errors return as MCP error-content, not thrown exceptions.</DocsLi>
      </DocsList>

      <DocsH2 id="patterns">Prompt patterns that work</DocsH2>
      <DocsP>
        <strong>Be explicit about tool names.</strong> "Tool: <Mono>search_pages(query)</Mono>"
        beats "give me a search tool".
      </DocsP>
      <DocsP>
        <strong>Name the credentials.</strong> "Auth: <Mono>NOTION_API_KEY</Mono>" tells the
        generator what to put in <Mono>requiredSecrets</Mono>. Saves an iteration.
      </DocsP>
      <DocsP>
        <strong>Say if a tool is destructive.</strong> "Tool: <Mono>delete_page(page_id)</Mono> —
        destructive, permanently removes the page" surfaces the warning to the AI client.
      </DocsP>
      <DocsP>
        <strong>One server per integration, not per tool.</strong> A Notion server with five
        tools is cleaner than five Notion servers each with one tool.
      </DocsP>

      <DocsH2 id="iteration">Iterate on a live server</DocsH2>
      <DocsP>
        Open the server detail page, click the <Mono>Iterate</Mono> 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.
      </DocsP>
    </>
  );
}
