Skip to content

Commit b35817b

Browse files
authored
fix: restore lost custom sections and prevent future overwrite regresion (#869)
fix: restore lost custom sections and prevent future overwrite regression Two bugs in the toolkit-docs-generator caused hand-authored custom sections (documentationChunks, customImports, subPages) to be silently wiped on every CI run for affected toolkits: Bug 1 (Critical): buildFallbackToolkit in previous-output.ts hardcoded empty arrays for documentationChunks, customImports, and subPages instead of carrying them forward from the raw record. This was triggered whenever MergedToolkitSchema.safeParse() failed — which happened for any toolkit whose chunks used location/type values missing from the schema enum ("before_available_tools", "after_available_tools", "custom_section", "section"). Once wiped, the preservation logic had nothing to restore, so every subsequent CI run preserved the empty arrays. Bug 2 (High): buildMergeErrorResult in data-merger.ts also hardcoded empty arrays, meaning any exception during mergeToolkitEntry would wipe custom sections from the output file. Root cause: DocumentationChunkLocationSchema and DocumentationChunkTypeSchema in the generator were out of sync with the frontend types, which already supported the broader set of values. MergedToolkitSchema.subPages was also declared as z.array(z.string()) while jira and zoom had rich objects. Fixes: - Sync DocumentationChunkLocationSchema: add before_available_tools, after_available_tools, custom_section - Sync DocumentationChunkTypeSchema: add section - Add header and priority optional fields to DocumentationChunkSchema - Fix MergedToolkitSchema.subPages to accept string | Record union - buildFallbackToolkit now reads documentationChunks/customImports/subPages from raw record instead of hardcoding empty arrays - buildMergeErrorResult now accepts previousToolkit and uses its custom sections instead of hardcoding empty arrays - Restore 17 affected toolkit JSON files from git history (github, brightdata, clickup, googlecalendar, googledocs, googlefinance, googleflights, googlehotels, googlejobs, googlemaps, googlenews, googleslides, intercomapi, jira, linear, zohobooksapi, zoom) - Add 4 tests covering the fallback preservation and error-result preservation paths All 17 toolkits now parse STRICT (no fallback) in the CI round-trip. Made-with: Cursor
1 parent 7f36d92 commit b35817b

23 files changed

Lines changed: 606 additions & 55 deletions

app/_components/toolkit-docs/types/index.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ export type DocumentationChunkType =
1818
| "code"
1919
| "warning"
2020
| "info"
21-
| "tip";
21+
| "tip"
22+
| "section";
2223

2324
/**
2425
* Location where the chunk should be injected
@@ -343,8 +344,12 @@ export type ToolkitData = {
343344
documentationChunks?: DocumentationChunk[];
344345
/** Custom imports for MDX */
345346
customImports: string[];
346-
/** Sub-pages that exist for this toolkit */
347-
subPages: string[];
347+
/**
348+
* Sub-pages that exist for this toolkit.
349+
* Each entry is either a string (legacy slug) or a rich object with
350+
* { type, content, relativePath } for inline MDX sub-page content.
351+
*/
352+
subPages: (string | Record<string, unknown>)[];
348353
/** Optional pip package name override */
349354
pipPackageName?: string;
350355
/** Generation timestamp */

toolkit-docs-generator/data/toolkits/brightdata.json

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -408,9 +408,17 @@
408408
}
409409
}
410410
],
411-
"documentationChunks": [],
411+
"documentationChunks": [
412+
{
413+
"type": "section",
414+
"location": "custom_section",
415+
"position": "after",
416+
"content": "## Secrets\n\nThis tool requires the following secrets:\n\n- `BRIGHTDATA_API_KEY`\n- `BRIGHTDATA_ZONE`\n\n### Auth\n\nThe Arcade Bright Data MCP Server uses [Bright Data](https://brightdata.com/) to access proxy networks and web scraping infrastructure.\n\n**Global Environment Variables:**\n\n- `BRIGHTDATA_API_KEY`: Your Bright Data API key. You can generate this from your [Bright Data dashboard](https://brightdata.com/cp/zones) under Account Settings → API Access.\n\n- `BRIGHTDATA_ZONE`: Your Bright Data zone name (e.g., `residential_proxy1`). This is the zone identifier you created in your Bright Data dashboard under Proxies & Scraping Infrastructure → Zones.\n\n**How to get your credentials:**\n\n1. **API Key**: Navigate to your [Bright Data Control Panel](https://brightdata.com/cp) → Settings → API Access → Generate API Token\n2. **Zone**: Go to Zones section in your dashboard, find your zone name in the format shown in the zone username: `brd-customer-{customer_id}-zone-{zone_name}`\n\nFor more details, see the [Bright Data API Documentation](https://docs.brightdata.com/api-reference).",
417+
"header": "## Secrets"
418+
}
419+
],
412420
"customImports": [],
413421
"subPages": [],
414422
"generatedAt": "2026-03-01T11:12:08.063Z",
415423
"summary": "Bright Data provides a developer toolkit for large-scale web search, crawling, and scraping, enabling reliable extraction of pages and structured data without getting blocked. It supports search queries, content-to-Markdown conversion, and configurable data feeds across many site types.\n\nDesigned for integration into data pipelines and analytics workflows with parameterized feeds and output formats.\n\n**Capabilities**\n- Scale-resistant crawling and scraping with anti-blocking behavior for sustained collection.\n- Flexible search engine queries with advanced parameters across major engines.\n- Transform pages into clean Markdown and emit structured JSON feeds for profiles, products, reviews, listings, and media.\n- Configurable extraction parameters for batching, pagination, and media handling.\n\n**Secrets**\n- API key (BRIGHTDATA_API_KEY) and zone token (BRIGHTDATA_ZONE). Example values: BRIGHTDATA_API_KEY=sk_..., BRIGHTDATA_ZONE=zone123."
416-
}
424+
}

toolkit-docs-generator/data/toolkits/clickup.json

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2688,9 +2688,31 @@
26882688
}
26892689
}
26902690
],
2691-
"documentationChunks": [],
2691+
"documentationChunks": [
2692+
{
2693+
"type": "section",
2694+
"location": "custom_section",
2695+
"position": "after",
2696+
"content": "## TaskPriority\n\n- **URGENT**: `URGENT`\n- **HIGH**: `HIGH`\n- **NORMAL**: `NORMAL`\n- **LOW**: `LOW`",
2697+
"header": "## TaskPriority"
2698+
},
2699+
{
2700+
"type": "section",
2701+
"location": "custom_section",
2702+
"position": "after",
2703+
"content": "## TaskOrderBy\n\n- **CREATED**: `created`\n- **UPDATED**: `updated`\n- **DUE_DATE**: `due_date`",
2704+
"header": "## TaskOrderBy"
2705+
},
2706+
{
2707+
"type": "section",
2708+
"location": "custom_section",
2709+
"position": "after",
2710+
"content": "## CommentResolution\n\n- **SET_AS_RESOLVED**: `resolved`\n- **SET_AS_UNRESOLVED**: `unresolved`",
2711+
"header": "## CommentResolution"
2712+
}
2713+
],
26922714
"customImports": [],
26932715
"subPages": [],
26942716
"generatedAt": "2026-02-26T20:45:10.379Z",
26952717
"summary": "The Arcade.dev Toolkit for ClickUp empowers developers to efficiently manage tasks, comments, and workspace structures within ClickUp through seamless API interactions. \n\n**Capabilities**\n- Create, update, and retrieve tasks and comments, enabling direct engagement with team tasks.\n- Conduct fuzzy searches for lists, folders, and members to enhance navigability.\n- Retrieve insights about workspaces and configure task statuses dynamically.\n- Manage team assignments effectively, facilitating team collaboration.\n- Execute structured queries for tasks based on specified criteria to optimize task management.\n\n**OAuth** \n- Provider: ClickUp \n- Note: Utilizes OAuth2 authentication for secure access.\n\n**Secrets** \n- No secrets required for integration."
2696-
}
2718+
}

toolkit-docs-generator/data/toolkits/github.json

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5727,9 +5727,45 @@
57275727
}
57285728
}
57295729
],
5730-
"documentationChunks": [],
5731-
"customImports": [],
5730+
"documentationChunks": [
5731+
{
5732+
"type": "warning",
5733+
"location": "description",
5734+
"position": "after",
5735+
"content": "<Callout type=\"warning\">\n **Critical**: This MCP Server is built for **GitHub Apps**, not OAuth Apps.\n \n You **must** create a GitHub App (not an OAuth App) to use this server properly. \n \n 👉 [Complete GitHub App Setup Guide](/references/auth-providers/github)\n</Callout>"
5736+
},
5737+
{
5738+
"type": "info",
5739+
"location": "description",
5740+
"position": "after",
5741+
"content": "<Callout type=\"info\">\n **Configuration Required**: All tools require secrets to be configured in Arcade Dashboard. See [Secrets Setup](#secrets-setup) below.\n</Callout>"
5742+
},
5743+
{
5744+
"type": "info",
5745+
"location": "before_available_tools",
5746+
"position": "after",
5747+
"content": "## GitHub Enterprise Support\n\n<Callout type=\"info\">\n This MCP Server fully supports **GitHub Enterprise Server 2.22+**\n</Callout>\n\n**Default Configuration:**\n- If no `GITHUB_SERVER_URL` is configured, the default is `https://api.github.com` (GitHub.com)\n- All tools work with GitHub.com out of the box\n\n**For GitHub Enterprise Server:**\n\n1. Create your GitHub App on your Enterprise instance (not github.com)\n2. Configure the `GITHUB_SERVER_URL` secret in Arcade Dashboard (see [Secrets Setup](#secrets-setup) below)\n3. Use your Enterprise server's API endpoint\n\n**Example Enterprise Server URLs:**\n- `https://github.yourcompany.com/api/v3`\n- `https://enterprise.yourorg.com/api/v3`\n- `https://git.company.internal/api/v3`\n\n<Callout>\n **Note**: GitHub Enterprise Server uses the `/api/v3` path after the hostname. GitHub.com uses `https://api.github.com` (no `/api/v3` suffix).\n</Callout>\n\n---",
5748+
"header": "## GitHub Enterprise Support"
5749+
},
5750+
{
5751+
"type": "section",
5752+
"location": "before_available_tools",
5753+
"position": "after",
5754+
"content": "## GitHub App Permissions Summary\n\nWhen creating your GitHub App, you'll need to grant specific permissions. Here's a quick reference of which tools require which permissions:\n\n### Repository Permissions\n\n| Permission | Level | Required For |\n|------------|-------|--------------|\n| **Contents** | Read | All repository and pull request tools, getting file contents |\n| **Contents** | Write | Creating/updating files, creating branches, merging PRs |\n| **Issues** | Read & Write | Issue management, PR assignments, managing labels (Issues) |\n| **Pull requests** | Read & Write | Pull request management, reviews, managing labels (PRs) |\n| **Metadata** | Read | All tools (automatically granted) |\n| **Statuses** | Read | `CheckPullRequestMergeStatus` |\n\n### Organization Permissions\n\n| Permission | Level | Required For |\n|------------|-------|--------------|\n| **Members** | Read | Projects, collaborators, org repos, user search |\n| **Projects** | Read & Write | All Projects V2 tools |\n\n### User Permissions\n\n| Permission | Level | Required For |\n|------------|-------|--------------|\n| **Read user profile** | Read | User context tools, review workload |\n| **Act on behalf of user** | Enabled | `SetStarred` (starring repositories) |\n\n### Tools by Permission Requirements\n\n<details>\n<summary><b>Basic Repository Access</b> (Contents Read + Metadata)</summary>\n\n- `GetRepository`\n- `CountStargazers`\n- `ListStargazers`\n- `ListRepositoryActivities`\n- `GetFileContents`\n\n</details>\n\n<details>\n<summary><b>Repository Write</b> (Contents Write + Metadata)</summary>\n\n- `CreateBranch`\n- `CreateOrUpdateFile`\n- `UpdateFileLines`\n\n</details>\n\n<details>\n<summary><b>Issue Management</b> (Contents Read + Issues + Metadata)</summary>\n\n- `CreateIssue`\n- `UpdateIssue`\n- `GetIssue`\n- `ListIssues`\n- `CreateIssueComment`\n- `ListRepositoryLabels`\n- `ManageLabels` (for issues)\n\n</details>\n\n<details>\n<summary><b>Pull Request Read</b> (Contents + Pull requests Read + Metadata)</summary>\n\n- `ListPullRequests`\n- `GetPullRequest`\n- `ListPullRequestCommits`\n- `ListReviewCommentsOnPullRequest`\n- `CheckPullRequestMergeStatus` (+ Statuses)\n\n</details>\n\n<details>\n<summary><b>Pull Request Write</b> (Contents Read + Pull requests Write + Metadata)</summary>\n\n- `UpdatePullRequest`\n- `CreatePullRequest`\n- `SubmitPullRequestReview`\n- `ManagePullRequest`\n- `ManagePullRequestReviewers`\n- `CreateReviewComment`\n- `CreateReplyForReviewComment`\n- `ResolveReviewThread`\n- `ManageLabels` (for pull requests)\n- `MergePullRequest` (+ Contents Write)\n\n</details>\n\n<details>\n<summary><b>Organization Tools</b> (Contents + Metadata + Members)</summary>\n\n- `ListOrgRepositories`\n- `SearchMyRepos`\n- `ListRepositoryCollaborators`\n- `AssignPullRequestUser` (+ Issues Write)\n\n</details>\n\n<details>\n<summary><b>Projects V2</b> (Contents + Metadata + Projects + Members)</summary>\n\n- `ListProjects`\n- `ListProjectItems`\n- `SearchProjectItem`\n- `ListProjectFields`\n- `UpdateProjectItem` (Projects Write)\n\n</details>\n\n<details>\n<summary><b>User Context</b> (Contents + Metadata + Read user profile)</summary>\n\n- `WhoAmI` (+ Members)\n- `GetUserRecentActivity`\n- `GetUserOpenItems`\n- `GetReviewWorkload` (+ Pull requests Read)\n\n</details>\n\n<details>\n<summary><b>⚠️ Special: Notifications</b> (Requires Classic PAT)</summary>\n\n- `GetNotificationSummary`\n- `ListNotifications`\n\n**Note**: GitHub Apps cannot access notifications API. Requires classic Personal Access Token with `notifications` scope.\n\n</details>\n\n---",
5755+
"header": "## GitHub App Permissions Summary"
5756+
},
5757+
{
5758+
"type": "warning",
5759+
"location": "custom_section",
5760+
"position": "after",
5761+
"content": "## Configuration & Setup\n\n### Authentication\n\n<Callout type=\"warning\">\n **Critical**: This MCP Server uses **GitHub Apps** authentication, not OAuth Apps.\n \n You **must** create a GitHub App to use this server. OAuth Apps are not supported.\n</Callout>\n\nThe Arcade GitHub MCP Server uses the [GitHub auth provider](/references/auth-providers/github) to connect to users' GitHub accounts.\n\n**For Arcade Cloud:**\n- No configuration needed\n- Your users will see `Arcade` as the requesting application\n- All tools work out of the box\n\n**For Self-Hosted:**\n- You must [create your own GitHub App](/references/auth-providers/github#creating-a-github-app)\n- [Configure the GitHub auth provider](/references/auth-providers/github#configuring-github-auth-in-arcade) with your app credentials\n- Your users will see your application name\n\n<Callout type=\"info\">\n **New to GitHub Apps?** Read [Why Arcade Uses GitHub Apps](/references/auth-providers/github#why-arcade-uses-github-apps-not-oauth-apps) \n to understand the security and compliance benefits.\n</Callout>\n\n### Secrets Setup\n\nAll tools require secrets to be configured in Arcade Dashboard.\n\n**Steps:**\n\n1. Go to [Arcade Dashboard](https://api.arcade.dev/dashboard)\n2. Navigate to **Secrets** in the left sidebar\n3. Click **Add Secret**\n4. Add the following secrets:\n\n| Secret Name | Value | Required For |\n|-------------|-------|--------------|\n| `GITHUB_SERVER_URL` | `https://api.github.com` (default for GitHub.com) | All tools |\n| `GITHUB_CLASSIC_PERSONAL_ACCESS_TOKEN` | Classic PAT with `notifications` scope | Notifications tools only |\n\n<Callout type=\"info\">\n **Default**: If `GITHUB_SERVER_URL` is not configured, it defaults to `https://api.github.com` (GitHub.com)\n \n **GitHub Enterprise Users**: Set `GITHUB_SERVER_URL` to your Enterprise server's API endpoint (e.g., `https://github.yourcompany.com/api/v3`). Note that Enterprise uses `/api/v3` path. See [GitHub Enterprise Support](#github-enterprise-support) for details.\n</Callout>\n\n<Callout type=\"warning\">\n **For Notifications Tools**: Create a classic Personal Access Token at [github.com/settings/tokens](https://github.com/settings/tokens) with only the `notifications` scope checked. GitHub Apps cannot access the notifications API.\n</Callout>\n\n---",
5762+
"header": "## Configuration & Setup"
5763+
}
5764+
],
5765+
"customImports": [
5766+
"import { Callout, Tabs } from \"nextra/components\";"
5767+
],
57325768
"subPages": [],
57335769
"generatedAt": "2026-03-04T11:17:26.984Z",
57345770
"summary": "Arcade.dev's GitHub toolkit exposes programmatic access to repositories, pull requests, issues, reviews, and project data. It enables automated repo/file edits, PR lifecycle handling, issue/project workflows, and user/activity discovery.\n\n**Capabilities**\n- Repository and file management: create branches and files, update file blocks, and read file contents or ranges.\n- Pull request and review workflows: create/update/merge PRs, manage reviewers, post and resolve review comments, and check merge status.\n- Issue, label, and project automation: create/update issues and comments, manage labels, and list/search Project V2 items and fields.\n- Search, auditing, and user context: list collaborators, stargazers, recent activity, and search/repos accessible to the authenticated user.\n\n**OAuth**\nProvider: GitHub\nScopes: None (no predeclared scopes; runtime consent required)\n\n**Secrets**\nGITHUB_SERVER_URL — secret type unknown; typically a GitHub Enterprise base URL (e.g., https://github.example.com). Store endpoints and tokens in a secure secrets manager."
5735-
}
5771+
}

toolkit-docs-generator/data/toolkits/googlecalendar.json

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -892,9 +892,26 @@
892892
}
893893
}
894894
],
895-
"documentationChunks": [],
896-
"customImports": [],
895+
"documentationChunks": [
896+
{
897+
"type": "markdown",
898+
"location": "auth",
899+
"position": "after",
900+
"content": "The Arcade Google Calendar MCP Server uses the [Google auth provider](/references/auth-providers/google) to connect to users' Google accounts.\n---",
901+
"header": "## Auth"
902+
},
903+
{
904+
"type": "section",
905+
"location": "custom_section",
906+
"position": "after",
907+
"content": "## UpdateGoogleMeetOptions\n\n- **`NONE`**: No action is taken.\n- **`ADD`**: Add the Google Meet link to the event.\n- **`REMOVE`**: Remove the Google Meet link from the event.\n\n<ToolFooter pipPackageName=\"arcade_google_calendar\" />",
908+
"header": "## UpdateGoogleMeetOptions"
909+
}
910+
],
911+
"customImports": [
912+
"import ScopePicker from \"@/app/_components/scope-picker\";"
913+
],
897914
"subPages": [],
898915
"generatedAt": "2026-02-26T20:45:10.392Z",
899916
"summary": "Arcade.dev offers a toolkit for Google Calendar that streamlines event management and calendar interaction through powerful APIs. This toolkit enables developers to effectively create, update, and manage calendar events while accessing user calendars.\n\n**Capabilities:**\n- Create and delete events seamlessly.\n- Fetch user calendars and events within specified date ranges.\n- Identify time slots when all participants are available.\n- Retrieve user profile information from Google services.\n\n**OAuth:**\n- Provider: Google\n- Scopes: `https://www.googleapis.com/auth/calendar.events`, `https://www.googleapis.com/auth/calendar.readonly`, `https://www.googleapis.com/auth/userinfo.email`, `https://www.googleapis.com/auth/userinfo.profile`."
900-
}
917+
}

toolkit-docs-generator/data/toolkits/googledocs.json

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,9 +1156,32 @@
11561156
}
11571157
}
11581158
],
1159-
"documentationChunks": [],
1160-
"customImports": [],
1159+
"documentationChunks": [
1160+
{
1161+
"type": "warning",
1162+
"location": "description",
1163+
"position": "after",
1164+
"content": "<Callout type=\"warning\">\n This Toolkit is not available in Arcade Cloud. You can use these tools with a\n [self-hosted](/guides/deployment-hosting/configure-engine) instance of Arcade.\n</Callout>"
1165+
},
1166+
{
1167+
"type": "section",
1168+
"location": "custom_section",
1169+
"position": "after",
1170+
"content": "## Tab Support\n\nGoogle Docs supports hierarchical tabs within documents. The Google Docs tools provide comprehensive support for working with tabs:\n\n- **Tab Metadata**: `GetDocumentMetadata` returns hierarchical tab structures with approximate character and word counts for each tab\n- **Tab Content**: `GetDocumentAsDocMD` and `SearchAndRetrieveDocuments` include all tab content in their output\n- **Tab Filtering**: `GetDocumentAsDocMD` supports filtering to retrieve content from a specific tab using the `tab_id` parameter\n\nTabs are represented with the following structure:\n- Each tab has a unique `tabId`, `title`, `index`, and `nestingLevel`\n- Tabs can be nested up to 3 levels deep (parent → child → grandchild)\n- Tab metadata includes approximate character and word counts for each tab's content\n\n---",
1171+
"header": "## Tab Support"
1172+
},
1173+
{
1174+
"type": "markdown",
1175+
"location": "auth",
1176+
"position": "after",
1177+
"content": "The Arcade Google Docs MCP Server uses the [Google auth provider](/references/auth-providers/google) to connect to users' Google accounts.\n---",
1178+
"header": "## Auth"
1179+
}
1180+
],
1181+
"customImports": [
1182+
"import ScopePicker from \"@/app/_components/scope-picker\";"
1183+
],
11611184
"subPages": [],
11621185
"generatedAt": "2026-02-26T20:45:10.393Z",
11631186
"summary": "Arcade.dev Google Docs toolkit lets LLM-driven apps create, read, edit, comment on, and search Google Docs while accessing document metadata and user profile information.\n\n**Capabilities**\n- Create and populate new documents or append and edit document body content programmatically.\n- Retrieve structured document content (DocMD) and metadata including tab structure and character counts for robust context-aware workflows.\n- Search Drive for documents, list comments, and produce file-picker URLs to recover from permission or missing-file errors.\n- Access authenticated user profile and environment info to tailor behavior and permissions.\n\n**OAuth**\nProvider: google\nScopes: https://www.googleapis.com/auth/drive.file, https://www.googleapis.com/auth/userinfo.email, https://www.googleapis.com/auth/userinfo.profile\n\n**Secrets**\nType: api_key\nExample: OPENAI_API_KEY (used for LLM or external API calls; store in environment variables or a secret manager)."
1164-
}
1187+
}

0 commit comments

Comments
 (0)