feat(mintlify): add Mintlify integration (#6457)

* feat(mintlify): add Mintlify integration

Adds all 18 documented Mintlify REST API endpoints across deployment, automation, agent jobs, prose detection, docs search/assistant, and analytics export.

* refactor(mintlify): tighten payload typing and test import
This commit is contained in:
Waleed
2026-08-08 15:46:29 -07:00
committed by GitHub
parent ff1ea218dc
commit 56200177e6
35 changed files with 4593 additions and 3 deletions
+19
View File
@@ -2494,6 +2494,25 @@ export function DocumentIcon(props: SVGProps<SVGSVGElement>) {
)
}
export function MintlifyIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg {...props} xmlns='http://www.w3.org/2000/svg' viewBox='0 0 19 19' fill='none'>
<path
d='M18.367 7.28888V1.59755C18.367 0.986819 17.8715 0.5 17.2699 0.5H11.5812C10.6877 0.5 9.80295 0.677018 8.98017 1.01336C8.15738 1.35856 7.40539 1.85424 6.77724 2.49152L6.733 2.53578C5.90137 3.37664 5.30862 4.42108 5.00781 5.57174C5.54749 5.43012 6.10483 5.35931 6.6622 5.35046C8.14852 5.33276 9.60831 5.81073 10.7938 6.7047C11.8643 7.50131 12.6783 8.59885 13.1206 9.86458C13.5807 11.148 13.6337 12.5465 13.2887 13.8653C14.43 13.5644 15.4828 12.9714 16.3233 12.1393L16.3675 12.0951C16.9957 11.4667 17.4999 10.7143 17.845 9.89114C18.19 9.06797 18.3581 8.18285 18.3581 7.28888H18.367Z'
fill='#18E299'
/>
<path
d='M4.83793 7.193C4.84674 5.44706 5.54303 3.77167 6.76814 2.51953L2.03511 7.25472C2.01749 7.27236 1.99985 7.28117 1.98222 7.29881C0.827615 8.44513 0.131342 9.97945 0.0167623 11.6019C-0.0890033 13.1186 0.307609 14.6176 1.15373 15.8698C1.23444 15.9892 1.45343 16.0285 1.57682 15.9139L4.47656 13.0216C5.38438 12.1134 5.66643 10.7642 5.23455 9.55618C4.96132 8.80666 4.82912 8.00424 4.83793 7.193Z'
fill='#0C8C5E'
/>
<path
d='M16.341 12.0938C15.4332 12.9844 14.2962 13.6016 13.0623 13.875C11.8195 14.1483 10.5327 14.0689 9.33405 13.6457C9.33405 13.6457 9.32522 13.6457 9.31641 13.6457C8.10892 13.2136 6.76042 13.4958 5.8526 14.3952L2.95282 17.2875C2.82943 17.4109 2.84706 17.6137 2.99689 17.7107C4.24845 18.5484 5.74683 18.954 7.26281 18.8482C8.88455 18.7336 10.4093 18.037 11.5639 16.8818L11.608 16.8378L16.341 12.1026V12.0938Z'
fill='#0C8C5E'
/>
</svg>
)
}
export function MistralIcon(props: SVGProps<SVGSVGElement>) {
const id = useId()
const clipId = `mistral_clip_${id}`
+2
View File
@@ -149,6 +149,7 @@ import {
MicrosoftSharepointIcon,
MicrosoftTeamsIcon,
MillionVerifierIcon,
MintlifyIcon,
MistralIcon,
MondayIcon,
MongoDBIcon,
@@ -428,6 +429,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
microsoft_teams: MicrosoftTeamsIcon,
'microsoft-teams': MicrosoftTeamsIcon,
millionverifier: MillionVerifierIcon,
mintlify: MintlifyIcon,
mistral_parse: MistralIcon,
mistral_parse_v2: MistralIcon,
mistral_parse_v3: MistralIcon,
@@ -157,6 +157,7 @@
"microsoft_planner",
"microsoft_teams",
"millionverifier",
"mintlify",
"mistral_parse",
"monday",
"monday-service-account",
@@ -0,0 +1,654 @@
---
title: Mintlify
description: Deploy, edit, search, and measure Mintlify documentation
---
import { BlockInfoCard } from "@/components/ui/block-info-card"
<BlockInfoCard
type="mintlify"
color="#000000"
/>
{/* MANUAL-CONTENT-START:intro */}
[Mintlify](https://mintlify.com/) is a documentation platform for building, deploying, and maintaining developer docs. Docs live as MDX in your Git repository, deploy on every merge, and ship with a built-in AI assistant trained on your content.
With Mintlify, you can:
- **Deploy documentation from Git**: Trigger production updates and per-branch preview deployments, then poll deployment status for logs, commit details, and screenshots
- **Run automations on demand**: Kick off a scheduled automation immediately from CI/CD instead of waiting for its next run
- **Edit docs with an agent**: Launch background agent jobs from a prompt, send follow-up instructions, and get a pull request when the agent changes files
- **Check writing quality**: Analyze a page for AI-sounding prose and get flagged passages with suggested human rewrites
- **Search and retrieve content**: Run semantic and keyword search across your docs, then fetch the full text of any matching page
- **Ask the docs assistant**: Get a grounded answer with its cited source pages, and continue the conversation across turns with a thread ID
- **Export analytics**: Pull user feedback, assistant conversations, caller stats, search queries, page views, and unique visitors
In Sim, the Mintlify integration lets your agents ship docs, drive documentation agent jobs, answer questions from your published content, and measure how that content performs — all from a single block.
**Authentication.** Mintlify issues two key types for these endpoints, and the API Key field takes whichever the selected operation needs:
- **Admin API key** (`mint_` prefix) — Trigger Update, Get Update Status, Trigger Preview Deployment, Trigger Automation, Create/Get Agent Job, Send Agent Message, Detect AI-Sounding Prose, and every analytics export
- **Assistant API key** (`mint_dsc_` prefix) — Search Documentation, Get Page Content, and Ask Assistant
Generate both on the [API keys page](https://app.mintlify.com/settings/organization/api-keys) in your Mintlify dashboard. The **Project ID** used by the admin operations is on the same page; the **Domain** used by the assistant operations is the identifier at the end of your dashboard URL (`app.mintlify.com/organization/domain`). The REST API requires a Mintlify Pro or Enterprise plan.
{/* MANUAL-CONTENT-END */}
## Usage Instructions
Integrate Mintlify into your workflow. Trigger production and preview deployments, run scheduled automations, launch documentation agent jobs, detect AI-sounding prose, search your docs and read page content, ask the docs assistant, and export feedback, conversation, search, view, and visitor analytics.
## Actions
### Mintlify Trigger Update
Queue a deployment update for a Mintlify documentation project from its configured deployment branch. Returns a status ID for tracking progress.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `projectId` | string | Yes | Mintlify project ID, copied from the API keys page in your dashboard |
| `apiKey` | string | Yes | Mintlify admin API key \(starts with mint_\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `statusId` | string | Status ID of the queued update. Poll it with Get Update Status. |
### Mintlify Get Update Status
Get the status of a Mintlify deployment update from its status ID, including logs, commit details, and screenshots.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `statusId` | string | Yes | Status ID returned by Trigger Update or Trigger Preview Deployment |
| `apiKey` | string | Yes | Mintlify admin API key \(starts with mint_\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `id` | string | Status ID of the update |
| `projectId` | string | Documentation project ID |
| `createdAt` | string | ISO 8601 UTC start time |
| `endedAt` | string | ISO 8601 UTC end time |
| `status` | string | Update status: queued, in_progress, success, or failure |
| `summary` | string | Summary of the update status |
| `logs` | array | Deployment log lines |
| `subdomain` | string | Subdomain of the docs being updated |
| `screenshot` | string | Screenshot of the docs |
| `screenshotLight` | string | Light-mode screenshot of the docs |
| `screenshotDark` | string | Dark-mode screenshot of the docs |
| `author` | object | Author of the update |
| ↳ `name` | string | Author name |
| ↳ `avatarUrl` | string | Author avatar image URL |
| ↳ `githubUserId` | number | Author GitHub user ID |
| `commit` | object | Commit that produced the update |
| ↳ `sha` | string | Commit SHA |
| ↳ `ref` | string | Git ref of the commit |
| ↳ `message` | string | Commit message |
| ↳ `filesChanged` | object | Files added, modified, and removed by the commit |
| ↳ `added` | array | New files added |
| ↳ `modified` | array | Existing files that were modified |
| ↳ `removed` | array | Files that were removed |
| `source` | string | Source of the update trigger: internal, github-app-installation, api, github, dashboard, gitlab, or onboarding |
### Mintlify Trigger Preview Deployment
Create or update a Mintlify preview deployment for a Git branch. Redeploys when a preview already exists for the branch.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `projectId` | string | Yes | Mintlify project ID, copied from the API keys page in your dashboard |
| `branch` | string | Yes | Name of the Git branch to create a preview deployment for |
| `apiKey` | string | Yes | Mintlify admin API key \(starts with mint_\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `statusId` | string | Status ID for tracking the preview deployment |
| `previewUrl` | string | URL where the preview deployment is hosted |
### Mintlify Trigger Automation
Run a scheduled Mintlify automation immediately instead of waiting for its next scheduled time. Only automations with a custom schedule can be triggered.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `projectId` | string | Yes | Mintlify project ID, copied from the API keys page in your dashboard |
| `automationId` | string | Yes | Automation ID, copied from the automation's settings panel on the Automations page |
| `apiKey` | string | Yes | Mintlify admin API key \(starts with mint_\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `schemaId` | string | ID of the triggered automation |
| `instanceId` | string | ID of the queued automation run, visible in the run history |
| `jobId` | string | ID of the background job processing the run |
### Mintlify Detect AI-Sounding Prose
Analyze a documentation page for AI-generated prose and return flagged passages with suggested human rewrites. Consumes one AI credit per checked page.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `projectId` | string | Yes | Mintlify project ID, copied from the API keys page in your dashboard |
| `path` | string | Yes | Repo-relative path of the page, used for reporting only |
| `content` | string | Yes | Raw MDX or Markdown content of the page to check \(max 1,000,000 characters\) |
| `apiKey` | string | Yes | Mintlify admin API key \(starts with mint_\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `path` | string | Path from the request |
| `skipped` | string | Reason the page was skipped \("too_short"\), or null when the page was checked |
| `predictionShort` | string | Overall verdict for the page: AI, AI-Assisted, Human, or Mixed. Null when the page was skipped. |
| `fractionAi` | number | Fraction of the page detected as AI-generated \(0-1\). Null when the page was skipped. |
| `fractionAiAssisted` | number | Fraction of the page detected as AI-assisted \(0-1\). Null when the page was skipped. |
| `fractionHuman` | number | Fraction of the page detected as human-written \(0-1\). Null when the page was skipped. |
| `windows` | array | Flagged non-human passages with line ranges and suggested rewrites. Empty when the page was skipped. |
| ↳ `text` | string | The flagged passage text |
| ↳ `label` | string | Detection label, for example AI-Generated |
| ↳ `aiAssistanceScore` | number | AI-assistance score for the passage \(0-1\) |
| ↳ `confidence` | json | Detection confidence, either a label such as High or a numeric score |
| ↳ `startLine` | number | 1-based start line of the passage |
| ↳ `endLine` | number | 1-based end line of the passage |
| ↳ `rewrites` | array | Suggested human rewrites of the passage |
| ↳ `text` | string | The rewritten passage |
| ↳ `rationale` | string | Why the rewrite reads more human |
| `creditsCharged` | number | AI credits charged for this request \(0 when skipped\) |
### Mintlify Create Agent Job
Create a background Mintlify agent job that edits your documentation from a prompt. Opens a pull request when the agent successfully edits files.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `projectId` | string | Yes | Mintlify project ID, copied from the API keys page in your dashboard |
| `prompt` | string | Yes | The instruction for the agent to execute |
| `apiKey` | string | Yes | Mintlify admin API key \(starts with mint_\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `statusId` | string | Status ID of a queued deployment |
| `previewUrl` | string | URL where the preview deployment is hosted |
| `id` | string | Deployment status ID or agent job ID |
| `projectId` | string | Documentation project ID |
| `createdAt` | string | Creation timestamp |
| `endedAt` | string | Deployment end timestamp |
| `archivedAt` | string | Agent job archive timestamp |
| `status` | string | Deployment status or agent job status |
| `summary` | string | Summary of the deployment status |
| `logs` | array | Deployment log lines |
| `subdomain` | string | Subdomain of the docs being updated |
| `screenshot` | string | Screenshot of the docs |
| `screenshotLight` | string | Light-mode screenshot of the docs |
| `screenshotDark` | string | Dark-mode screenshot of the docs |
| `author` | json | Author of the deployment update |
| `commit` | json | Commit that produced the deployment |
| `source` | json | Deployment trigger source \(string\) or agent job source repository details \(object\) |
| `schemaId` | string | ID of the triggered automation |
| `instanceId` | string | ID of the queued automation run |
| `jobId` | string | ID of the background job processing an automation run |
| `model` | string | AI model used for the agent job |
| `prLink` | string | Pull request URL created by the agent |
| `path` | string | Documentation page path |
| `content` | string | Full text content of the page |
| `skipped` | string | Reason a prose check was skipped |
| `predictionShort` | string | Prose verdict: AI, AI-Assisted, Human, Mixed |
| `fractionAi` | number | Fraction of the page detected as AI-generated |
| `fractionAiAssisted` | number | Fraction detected as AI-assisted |
| `fractionHuman` | number | Fraction detected as human-written |
| `windows` | array | Flagged passages with suggested rewrites |
| `creditsCharged` | number | AI credits charged for the prose check |
| `results` | array | Documentation search results |
| `resultCount` | number | Number of search results returned |
| `text` | string | Assembled assistant answer |
| `threadId` | string | Assistant thread ID for follow-up messages |
| `sources` | array | Documentation sources the assistant cited |
| `feedback` | array | Feedback entries or per-page feedback aggregates |
| `conversations` | array | Assistant conversation history |
| `searches` | array | Documentation search terms with hit counts |
| `totalSearches` | number | Total search events in the date range |
| `views` | array | Per-page content view event counts |
| `visitors` | array | Per-page unique visitor counts |
| `totals` | json | Site-wide human, AI, and total traffic counts |
| `web` | number | Assistant queries from the documentation site |
| `api` | number | Assistant queries from API calls |
| `other` | number | Assistant queries from other sources |
| `total` | number | Total assistant queries across all caller types |
| `nextCursor` | string | Cursor for the next page of results |
| `hasMore` | boolean | Whether additional results are available |
### Mintlify Get Agent Job
Retrieve the current status and details of a Mintlify agent job, including the pull request link once the agent opens one.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `projectId` | string | Yes | Mintlify project ID, copied from the API keys page in your dashboard |
| `jobId` | string | Yes | Unique identifier of the agent job |
| `apiKey` | string | Yes | Mintlify admin API key \(starts with mint_\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `statusId` | string | Status ID of a queued deployment |
| `previewUrl` | string | URL where the preview deployment is hosted |
| `id` | string | Deployment status ID or agent job ID |
| `projectId` | string | Documentation project ID |
| `createdAt` | string | Creation timestamp |
| `endedAt` | string | Deployment end timestamp |
| `archivedAt` | string | Agent job archive timestamp |
| `status` | string | Deployment status or agent job status |
| `summary` | string | Summary of the deployment status |
| `logs` | array | Deployment log lines |
| `subdomain` | string | Subdomain of the docs being updated |
| `screenshot` | string | Screenshot of the docs |
| `screenshotLight` | string | Light-mode screenshot of the docs |
| `screenshotDark` | string | Dark-mode screenshot of the docs |
| `author` | json | Author of the deployment update |
| `commit` | json | Commit that produced the deployment |
| `source` | json | Deployment trigger source \(string\) or agent job source repository details \(object\) |
| `schemaId` | string | ID of the triggered automation |
| `instanceId` | string | ID of the queued automation run |
| `jobId` | string | ID of the background job processing an automation run |
| `model` | string | AI model used for the agent job |
| `prLink` | string | Pull request URL created by the agent |
| `path` | string | Documentation page path |
| `content` | string | Full text content of the page |
| `skipped` | string | Reason a prose check was skipped |
| `predictionShort` | string | Prose verdict: AI, AI-Assisted, Human, Mixed |
| `fractionAi` | number | Fraction of the page detected as AI-generated |
| `fractionAiAssisted` | number | Fraction detected as AI-assisted |
| `fractionHuman` | number | Fraction detected as human-written |
| `windows` | array | Flagged passages with suggested rewrites |
| `creditsCharged` | number | AI credits charged for the prose check |
| `results` | array | Documentation search results |
| `resultCount` | number | Number of search results returned |
| `text` | string | Assembled assistant answer |
| `threadId` | string | Assistant thread ID for follow-up messages |
| `sources` | array | Documentation sources the assistant cited |
| `feedback` | array | Feedback entries or per-page feedback aggregates |
| `conversations` | array | Assistant conversation history |
| `searches` | array | Documentation search terms with hit counts |
| `totalSearches` | number | Total search events in the date range |
| `views` | array | Per-page content view event counts |
| `visitors` | array | Per-page unique visitor counts |
| `totals` | json | Site-wide human, AI, and total traffic counts |
| `web` | number | Assistant queries from the documentation site |
| `api` | number | Assistant queries from API calls |
| `other` | number | Assistant queries from other sources |
| `total` | number | Total assistant queries across all caller types |
| `nextCursor` | string | Cursor for the next page of results |
| `hasMore` | boolean | Whether additional results are available |
### Mintlify Send Agent Message
Send a follow-up instruction to an existing Mintlify agent job. The message is processed asynchronously.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `projectId` | string | Yes | Mintlify project ID, copied from the API keys page in your dashboard |
| `jobId` | string | Yes | Unique identifier of the agent job to send a message to |
| `prompt` | string | Yes | The follow-up instruction for the agent |
| `apiKey` | string | Yes | Mintlify admin API key \(starts with mint_\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `statusId` | string | Status ID of a queued deployment |
| `previewUrl` | string | URL where the preview deployment is hosted |
| `id` | string | Deployment status ID or agent job ID |
| `projectId` | string | Documentation project ID |
| `createdAt` | string | Creation timestamp |
| `endedAt` | string | Deployment end timestamp |
| `archivedAt` | string | Agent job archive timestamp |
| `status` | string | Deployment status or agent job status |
| `summary` | string | Summary of the deployment status |
| `logs` | array | Deployment log lines |
| `subdomain` | string | Subdomain of the docs being updated |
| `screenshot` | string | Screenshot of the docs |
| `screenshotLight` | string | Light-mode screenshot of the docs |
| `screenshotDark` | string | Dark-mode screenshot of the docs |
| `author` | json | Author of the deployment update |
| `commit` | json | Commit that produced the deployment |
| `source` | json | Deployment trigger source \(string\) or agent job source repository details \(object\) |
| `schemaId` | string | ID of the triggered automation |
| `instanceId` | string | ID of the queued automation run |
| `jobId` | string | ID of the background job processing an automation run |
| `model` | string | AI model used for the agent job |
| `prLink` | string | Pull request URL created by the agent |
| `path` | string | Documentation page path |
| `content` | string | Full text content of the page |
| `skipped` | string | Reason a prose check was skipped |
| `predictionShort` | string | Prose verdict: AI, AI-Assisted, Human, Mixed |
| `fractionAi` | number | Fraction of the page detected as AI-generated |
| `fractionAiAssisted` | number | Fraction detected as AI-assisted |
| `fractionHuman` | number | Fraction detected as human-written |
| `windows` | array | Flagged passages with suggested rewrites |
| `creditsCharged` | number | AI credits charged for the prose check |
| `results` | array | Documentation search results |
| `resultCount` | number | Number of search results returned |
| `text` | string | Assembled assistant answer |
| `threadId` | string | Assistant thread ID for follow-up messages |
| `sources` | array | Documentation sources the assistant cited |
| `feedback` | array | Feedback entries or per-page feedback aggregates |
| `conversations` | array | Assistant conversation history |
| `searches` | array | Documentation search terms with hit counts |
| `totalSearches` | number | Total search events in the date range |
| `views` | array | Per-page content view event counts |
| `visitors` | array | Per-page unique visitor counts |
| `totals` | json | Site-wide human, AI, and total traffic counts |
| `web` | number | Assistant queries from the documentation site |
| `api` | number | Assistant queries from API calls |
| `other` | number | Assistant queries from other sources |
| `total` | number | Total assistant queries across all caller types |
| `nextCursor` | string | Cursor for the next page of results |
| `hasMore` | boolean | Whether additional results are available |
### Mintlify Search Documentation
Run a semantic and keyword search across a Mintlify documentation site, with optional version, language, tag, and group filters.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `domain` | string | Yes | Domain identifier from your domain.mintlify.site URL, found at the end of your dashboard URL |
| `query` | string | Yes | Search query to execute against your documentation content |
| `pageSize` | number | No | Number of search results to return, between 1 and 50 \(default 10\) |
| `scoreThreshold` | number | No | Minimum relevance score for results, between 0 and 1 |
| `version` | string | No | Filter results by documentation version |
| `language` | string | No | Filter results by content language |
| `tag` | string | No | Filter results by tag |
| `groups` | json | No | Documentation groups the caller is authorized to access, as a JSON array of strings. Only applies to deployments using auth or userAuth. |
| `apiKey` | string | Yes | Mintlify assistant API key \(starts with mint_dsc_\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `results` | array | Matching documentation chunks ordered by relevance |
| ↳ `content` | string | The matching content from your documentation |
| ↳ `path` | string | Path or URL to the source document |
| ↳ `metadata` | json | Additional metadata about the search result |
| `resultCount` | number | Number of results returned |
### Mintlify Get Page Content
Retrieve the full text content of a Mintlify documentation page by its path. Use it after a search to fetch the complete page.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `domain` | string | Yes | Domain identifier from your domain.mintlify.site URL, found at the end of your dashboard URL |
| `path` | string | Yes | Page slug or path to retrieve, matching the path field returned by Search Documentation |
| `groups` | json | No | Documentation groups the caller is authorized to access, as a JSON array of strings. Only applies to deployments using auth or userAuth. |
| `apiKey` | string | Yes | Mintlify assistant API key \(starts with mint_dsc_\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `path` | string | The page path that was requested |
| `content` | string | Full text content of the page |
### Mintlify Create Assistant Message
Ask the Mintlify assistant, trained on your documentation, a question and get the assembled answer with its cited sources. Consumes the deployment's assistant credits.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `domain` | string | Yes | Domain identifier from your domain.mintlify.site URL, found at the end of your dashboard URL |
| `message` | string | No | The question to ask the assistant. Ignored when a full Messages array is supplied. |
| `messages` | json | No | Full AI SDK message array for multi-turn conversations, each entry with id, role, and parts. Overrides Message when provided. |
| `fp` | string | No | Fingerprint identifier for tracking conversation sessions \(default "anonymous"\) |
| `threadId` | string | No | Thread ID from a previous response, to continue the same conversation |
| `retrievalPageSize` | number | No | Number of documentation search results used to generate the response |
| `currentPath` | string | No | Path of the page the user is currently viewing, for more relevant answers \(max 200 characters\) |
| `version` | string | No | Filter retrieval by documentation version |
| `language` | string | No | Filter retrieval by content language |
| `groups` | json | No | Group identifiers to filter retrieval by, as a JSON array of strings |
| `assistantContext` | json | No | Contextual snippets for the assistant, as a JSON array of objects with type \("code" or "textSelection"\), value, and optional path and elementId |
| `apiKey` | string | Yes | Mintlify assistant API key \(starts with mint_dsc_\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `text` | string | Assembled assistant answer |
| `threadId` | string | Thread ID for continuing this conversation in a follow-up call |
| `sources` | array | Documentation sources the assistant cited |
| ↳ `sourceId` | string | Source identifier |
| ↳ `url` | string | URL of the cited page |
| ↳ `title` | string | Title of the cited page |
### Mintlify Get Feedback
Export paginated user feedback from a Mintlify documentation project, with optional date-range, source, and status filters.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `projectId` | string | Yes | Mintlify project ID, copied from the API keys page in your dashboard |
| `dateFrom` | string | No | Inclusive start date in ISO 8601 or YYYY-MM-DD format |
| `dateTo` | string | No | Exclusive end date in ISO 8601 or YYYY-MM-DD format |
| `source` | string | No | Filter by feedback source: code_snippet, contextual, agent, or thumbs_only |
| `status` | string | No | Comma-separated statuses to filter by: pending, in_progress, resolved, dismissed |
| `limit` | number | No | Max results per page, between 1 and 100 \(default 50\) |
| `cursor` | string | No | Pagination cursor returned as nextCursor by a previous call |
| `apiKey` | string | Yes | Mintlify admin API key \(starts with mint_\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `feedback` | array | Feedback entries for the requested window |
| ↳ `id` | string | Unique feedback identifier |
| ↳ `path` | string | Path or URL of the page |
| ↳ `comment` | string | Text of the feedback comment |
| ↳ `createdAt` | string | Submission timestamp |
| ↳ `source` | string | Origin: code_snippet, contextual, agent, or thumbs_only |
| ↳ `status` | string | Review status: pending, in_progress, resolved, or dismissed |
| ↳ `helpful` | boolean | Whether the user found the content helpful \(contextual feedback only\) |
| ↳ `contact` | string | Email the user provided for follow-up \(contextual feedback only\) |
| ↳ `code` | string | Code snippet the feedback relates to \(code_snippet feedback only\) |
| ↳ `filename` | string | Filename of the code snippet \(code_snippet feedback only\) |
| ↳ `lang` | string | Language of the code snippet \(code_snippet feedback only\) |
| `nextCursor` | string | Cursor for the next page, or null when there are no more results |
| `hasMore` | boolean | Whether additional results are available |
### Mintlify Get Feedback By Page
Export Mintlify feedback counts aggregated by documentation page path, broken down into thumbs up, thumbs down, and code snippet feedback.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `projectId` | string | Yes | Mintlify project ID, copied from the API keys page in your dashboard |
| `dateFrom` | string | No | Inclusive start date in ISO 8601 or YYYY-MM-DD format |
| `dateTo` | string | No | Exclusive end date in ISO 8601 or YYYY-MM-DD format |
| `limit` | number | No | Max results per page, between 1 and 100 \(default 10\) |
| `source` | string | No | Filter by feedback source: code_snippet, contextual, agent, or thumbs_only |
| `status` | string | No | Comma-separated statuses to filter by: pending, in_progress, resolved, dismissed |
| `apiKey` | string | Yes | Mintlify admin API key \(starts with mint_\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `feedback` | array | Feedback counts aggregated by documentation page path |
| ↳ `path` | string | The documentation page path |
| ↳ `thumbsUp` | number | Positive contextual feedback entries |
| ↳ `thumbsDown` | number | Negative contextual feedback entries |
| ↳ `code` | number | Code snippet feedback entries |
| ↳ `total` | number | Total feedback entries |
| `hasMore` | boolean | Whether additional results are available |
### Mintlify Get Assistant Conversations
Export paginated Mintlify AI assistant conversation history, including the query, response, cited sources, and whether the question was answered.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `projectId` | string | Yes | Mintlify project ID, copied from the API keys page in your dashboard |
| `dateFrom` | string | No | Inclusive start date in ISO 8601 or YYYY-MM-DD format |
| `dateTo` | string | No | Exclusive end date in ISO 8601 or YYYY-MM-DD format |
| `limit` | number | No | Max results per page, between 1 and 1000 \(default 100\) |
| `cursor` | string | No | ULID pagination cursor returned as nextCursor by a previous call |
| `apiKey` | string | Yes | Mintlify admin API key \(starts with mint_\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `conversations` | array | Assistant conversations for the requested window |
| ↳ `id` | string | Unique conversation identifier |
| ↳ `timestamp` | string | When the conversation occurred |
| ↳ `query` | string | The user's question |
| ↳ `response` | string | The assistant's response |
| ↳ `sources` | array | Documentation pages referenced in the response |
| ↳ `title` | string | Title of the page |
| ↳ `url` | string | URL of the page |
| ↳ `resolutionStatus` | string | Whether the assistant answered the question: answered or unanswered |
| ↳ `queryCategory` | string | Auto-assigned category grouping for the conversation |
| ↳ `pageUrl` | string | Full URL of the page where the conversation started |
| `nextCursor` | string | Cursor for the next page, or null when there are no more results |
| `hasMore` | boolean | Whether additional results are available |
### Mintlify Get Assistant Caller Stats
Get a breakdown of Mintlify assistant query counts by caller type — web, API, and other — for a date range.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `projectId` | string | Yes | Mintlify project ID, copied from the API keys page in your dashboard |
| `dateFrom` | string | No | Inclusive start date in ISO 8601 or YYYY-MM-DD format |
| `dateTo` | string | No | Exclusive end date in ISO 8601 or YYYY-MM-DD format |
| `apiKey` | string | Yes | Mintlify admin API key \(starts with mint_\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `web` | number | Assistant queries originating from the documentation site |
| `api` | number | Assistant queries originating from API calls |
| `other` | number | Assistant queries from other sources such as integrations and SDKs |
| `total` | number | Total assistant queries across all caller types |
### Mintlify Get Search Queries
Export Mintlify documentation search terms for a date range, ordered by hit count, with click-through rate and the most-clicked result path.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `projectId` | string | Yes | Mintlify project ID, copied from the API keys page in your dashboard |
| `dateFrom` | string | No | Inclusive start date in ISO 8601 or YYYY-MM-DD format |
| `dateTo` | string | No | Exclusive end date in ISO 8601 or YYYY-MM-DD format |
| `limit` | number | No | Max search terms per page, between 1 and 100 \(default 50\) |
| `cursor` | string | No | Opaque pagination cursor returned as nextCursor by a previous call |
| `apiKey` | string | Yes | Mintlify admin API key \(starts with mint_\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `searches` | array | Search terms ordered by hit count descending |
| ↳ `searchQuery` | string | The search term entered by users |
| ↳ `hits` | number | Number of times this term was searched |
| ↳ `ctr` | number | Click-through rate for this search term |
| ↳ `topClickedPage` | string | Most-clicked result path for this query |
| ↳ `lastSearchedAt` | string | Timestamp of the last time this term was searched |
| `totalSearches` | number | Total search events in the date range, summing all hits rather than distinct queries |
| `nextCursor` | string | Cursor for the next page, or null when there are no more results |
### Mintlify Get Page Views
Export Mintlify per-path and site-wide content view counts for a date range, split by human and AI bot traffic.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `projectId` | string | Yes | Mintlify project ID, copied from the API keys page in your dashboard |
| `dateFrom` | string | No | Inclusive start date in ISO 8601 or YYYY-MM-DD format |
| `dateTo` | string | No | Exclusive end date in ISO 8601 or YYYY-MM-DD format |
| `limit` | number | No | Max results per page, between 1 and 250 \(default 50\) |
| `offset` | number | No | Number of rows to skip for offset-based pagination \(default 0\) |
| `apiKey` | string | Yes | Mintlify admin API key \(starts with mint_\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `views` | array | Per-page content view event counts |
| ↳ `path` | string | The documentation page path |
| ↳ `human` | number | Content view events from human traffic |
| ↳ `ai` | number | Content view events from AI bot traffic |
| ↳ `total` | number | Total content view events |
| `hasMore` | boolean | Whether additional results are available |
### Mintlify Get Unique Visitors
Export Mintlify per-path and site-wide approximate distinct visitor counts for a date range, split by human and AI bot traffic.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `projectId` | string | Yes | Mintlify project ID, copied from the API keys page in your dashboard |
| `dateFrom` | string | No | Inclusive start date in ISO 8601 or YYYY-MM-DD format |
| `dateTo` | string | No | Exclusive end date in ISO 8601 or YYYY-MM-DD format |
| `limit` | number | No | Max results per page, between 1 and 250 \(default 50\) |
| `offset` | number | No | Number of rows to skip for offset-based pagination \(default 0\) |
| `apiKey` | string | Yes | Mintlify admin API key \(starts with mint_\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `visitors` | array | Per-page unique visitor counts |
| ↳ `path` | string | The documentation page path |
| ↳ `human` | number | Unique human visitors |
| ↳ `ai` | number | Unique AI bot visitors |
| ↳ `total` | number | Approximate distinct visitors, deduplicated across human and AI |
| `hasMore` | boolean | Whether additional results are available |
+141
View File
@@ -0,0 +1,141 @@
/**
* @vitest-environment node
*/
import { describe, expect, it } from 'vitest'
import { MintlifyBlock } from '@/blocks/blocks/mintlify'
/**
* The executor merges `tools.config.params` on top of the raw inputs, so every
* assertion runs against the merged result rather than the transform's return
* value alone.
*/
function resolveParams(inputs: Record<string, unknown>) {
return { ...inputs, ...MintlifyBlock.tools.config.params!(inputs) }
}
describe('MintlifyBlock', () => {
describe('tool selection', () => {
it('maps every operation option to a registered tool ID', () => {
const operationSubBlock = MintlifyBlock.subBlocks.find((block) => block.id === 'operation')
const operations = operationSubBlock?.options as { id: string }[]
expect(operations.length).toBeGreaterThan(0)
for (const { id } of operations) {
const toolId = MintlifyBlock.tools.config!.tool!({ operation: id })
expect(MintlifyBlock.tools.access).toContain(toolId)
}
})
it('exposes one operation option per accessible tool', () => {
const operationSubBlock = MintlifyBlock.subBlocks.find((block) => block.id === 'operation')
const operations = operationSubBlock?.options as { id: string }[]
expect(operations).toHaveLength(MintlifyBlock.tools.access!.length)
})
})
describe('operation scoping', () => {
it('clears advanced values retained from another operation', () => {
const result = resolveParams({
operation: 'get_feedback',
projectId: 'proj_1',
// Retained from a prior Get Page Views selection, whose limit ceiling is 250.
offset: '100',
limit: '200',
})
expect(result.offset).toBeUndefined()
expect(result.limit).toBe(200)
})
it('clears a retained search filter when an analytics operation runs', () => {
const result = resolveParams({
operation: 'get_views',
projectId: 'proj_1',
query: 'stale query',
groups: '["internal"]',
tag: 'api-reference',
})
expect(result.query).toBeUndefined()
expect(result.groups).toBeUndefined()
expect(result.tag).toBeUndefined()
})
it('leaves the model arguments untouched on the agent-tool path', () => {
const agentArgs = { projectId: 'proj_1', limit: 25 }
expect(resolveParams(agentArgs)).toEqual(agentArgs)
})
})
describe('param aliasing', () => {
it('forwards the prose-check path under the tool param name', () => {
const result = resolveParams({
operation: 'detect_ai_prose',
projectId: 'proj_1',
deslopPath: 'guides/quickstart.mdx',
content: '# Quickstart',
})
expect(result.path).toBe('guides/quickstart.mdx')
})
it('forwards the page-content path under the tool param name', () => {
const result = resolveParams({
operation: 'get_page_content',
domain: 'acme',
pagePath: 'guides/quickstart',
})
expect(result.path).toBe('guides/quickstart')
})
it('forwards the feedback filters under their tool param names', () => {
const result = resolveParams({
operation: 'get_feedback',
projectId: 'proj_1',
feedbackSource: 'contextual',
feedbackStatus: 'pending,resolved',
})
expect(result.source).toBe('contextual')
expect(result.status).toBe('pending,resolved')
})
})
describe('numeric coercion', () => {
it('coerces numeric inputs delivered as strings', () => {
const result = resolveParams({
operation: 'search',
domain: 'acme',
query: 'custom domains',
pageSize: '25',
scoreThreshold: '0.4',
})
expect(result.pageSize).toBe(25)
expect(result.scoreThreshold).toBe(0.4)
})
it('drops a numeric input that cannot be parsed', () => {
const result = resolveParams({
operation: 'get_views',
projectId: 'proj_1',
limit: 'not-a-number',
})
expect(result.limit).toBeUndefined()
})
it('drops empty optional values', () => {
const result = resolveParams({
operation: 'get_searches',
projectId: 'proj_1',
dateFrom: '',
cursor: '',
})
expect(result.dateFrom).toBeUndefined()
expect(result.cursor).toBeUndefined()
})
})
})
+773
View File
@@ -0,0 +1,773 @@
import { MintlifyIcon } from '@/components/icons'
import type { BlockConfig, BlockMeta } from '@/blocks/types'
import { AuthMode, IntegrationType } from '@/blocks/types'
/**
* SubBlock IDs each operation may forward to its tool. Anything outside the
* selected operation's list is explicitly cleared, because the executor merges
* `tools.config.params` on top of the raw inputs and a retained advanced-mode
* value would otherwise leak across operations.
*/
const OPERATION_PARAMS: Record<string, readonly string[]> = {
trigger_update: ['projectId'],
get_update_status: ['statusId'],
trigger_preview: ['projectId', 'branch'],
trigger_automation: ['projectId', 'automationId'],
detect_ai_prose: ['projectId', 'deslopPath', 'content'],
create_agent_job: ['projectId', 'prompt'],
get_agent_job: ['projectId', 'jobId'],
send_agent_message: ['projectId', 'jobId', 'prompt'],
search: ['domain', 'query', 'pageSize', 'scoreThreshold', 'version', 'language', 'tag', 'groups'],
get_page_content: ['domain', 'pagePath', 'groups'],
create_assistant_message: [
'domain',
'message',
'messages',
'fp',
'threadId',
'retrievalPageSize',
'currentPath',
'version',
'language',
'groups',
'assistantContext',
],
get_feedback: [
'projectId',
'dateFrom',
'dateTo',
'feedbackSource',
'feedbackStatus',
'limit',
'cursor',
],
get_feedback_by_page: [
'projectId',
'dateFrom',
'dateTo',
'limit',
'feedbackSource',
'feedbackStatus',
],
get_assistant_conversations: ['projectId', 'dateFrom', 'dateTo', 'limit', 'cursor'],
get_assistant_caller_stats: ['projectId', 'dateFrom', 'dateTo'],
get_searches: ['projectId', 'dateFrom', 'dateTo', 'limit', 'cursor'],
get_views: ['projectId', 'dateFrom', 'dateTo', 'limit', 'offset'],
get_visitors: ['projectId', 'dateFrom', 'dateTo', 'limit', 'offset'],
}
/** SubBlock IDs whose value reaches the tool under a different param name. */
const PARAM_ALIASES: Record<string, string> = {
deslopPath: 'path',
pagePath: 'path',
feedbackSource: 'source',
feedbackStatus: 'status',
}
const NUMERIC_PARAMS = new Set([
'pageSize',
'scoreThreshold',
'retrievalPageSize',
'limit',
'offset',
])
const PROJECT_OPERATIONS = [
'trigger_update',
'trigger_preview',
'trigger_automation',
'detect_ai_prose',
'create_agent_job',
'get_agent_job',
'send_agent_message',
'get_feedback',
'get_feedback_by_page',
'get_assistant_conversations',
'get_assistant_caller_stats',
'get_searches',
'get_views',
'get_visitors',
]
const ANALYTICS_OPERATIONS = [
'get_feedback',
'get_feedback_by_page',
'get_assistant_conversations',
'get_assistant_caller_stats',
'get_searches',
'get_views',
'get_visitors',
]
const LIMIT_OPERATIONS = [
'get_feedback',
'get_feedback_by_page',
'get_assistant_conversations',
'get_searches',
'get_views',
'get_visitors',
]
const CURSOR_OPERATIONS = ['get_feedback', 'get_assistant_conversations', 'get_searches']
const FEEDBACK_OPERATIONS = ['get_feedback', 'get_feedback_by_page']
const DOMAIN_OPERATIONS = ['search', 'get_page_content', 'create_assistant_message']
const RETRIEVAL_FILTER_OPERATIONS = ['search', 'create_assistant_message']
export const MintlifyBlock: BlockConfig = {
type: 'mintlify',
name: 'Mintlify',
description: 'Deploy, edit, search, and measure Mintlify documentation',
longDescription:
'Integrate Mintlify into your workflow. Trigger production and preview deployments, run scheduled automations, launch documentation agent jobs, detect AI-sounding prose, search your docs and read page content, ask the docs assistant, and export feedback, conversation, search, view, and visitor analytics.',
docsLink: 'https://docs.sim.ai/integrations/mintlify',
category: 'tools',
integrationType: IntegrationType.Documents,
bgColor: '#000000',
icon: MintlifyIcon,
authMode: AuthMode.ApiKey,
subBlocks: [
{
id: 'operation',
title: 'Operation',
type: 'dropdown',
options: [
{ label: 'Trigger Update', id: 'trigger_update' },
{ label: 'Get Update Status', id: 'get_update_status' },
{ label: 'Trigger Preview Deployment', id: 'trigger_preview' },
{ label: 'Trigger Automation', id: 'trigger_automation' },
{ label: 'Create Agent Job', id: 'create_agent_job' },
{ label: 'Get Agent Job', id: 'get_agent_job' },
{ label: 'Send Agent Message', id: 'send_agent_message' },
{ label: 'Detect AI-Sounding Prose', id: 'detect_ai_prose' },
{ label: 'Search Documentation', id: 'search' },
{ label: 'Get Page Content', id: 'get_page_content' },
{ label: 'Ask Assistant', id: 'create_assistant_message' },
{ label: 'Get Feedback', id: 'get_feedback' },
{ label: 'Get Feedback By Page', id: 'get_feedback_by_page' },
{ label: 'Get Assistant Conversations', id: 'get_assistant_conversations' },
{ label: 'Get Assistant Caller Stats', id: 'get_assistant_caller_stats' },
{ label: 'Get Search Queries', id: 'get_searches' },
{ label: 'Get Page Views', id: 'get_views' },
{ label: 'Get Unique Visitors', id: 'get_visitors' },
],
value: () => 'trigger_update',
},
{
id: 'projectId',
title: 'Project ID',
type: 'short-input',
placeholder: 'Copy from the API keys page in your dashboard',
condition: { field: 'operation', value: PROJECT_OPERATIONS },
required: { field: 'operation', value: PROJECT_OPERATIONS },
},
{
id: 'domain',
title: 'Domain',
type: 'short-input',
placeholder: 'Identifier from your domain.mintlify.site URL',
condition: { field: 'operation', value: DOMAIN_OPERATIONS },
required: { field: 'operation', value: DOMAIN_OPERATIONS },
},
{
id: 'statusId',
title: 'Status ID',
type: 'short-input',
placeholder: 'Status ID returned by a deployment trigger',
condition: { field: 'operation', value: 'get_update_status' },
required: { field: 'operation', value: 'get_update_status' },
},
{
id: 'branch',
title: 'Branch',
type: 'short-input',
placeholder: 'feature/new-guides',
condition: { field: 'operation', value: 'trigger_preview' },
required: { field: 'operation', value: 'trigger_preview' },
},
{
id: 'automationId',
title: 'Automation ID',
type: 'short-input',
placeholder: "Copy from the automation's settings panel",
condition: { field: 'operation', value: 'trigger_automation' },
required: { field: 'operation', value: 'trigger_automation' },
},
{
id: 'jobId',
title: 'Job ID',
type: 'short-input',
placeholder: 'Agent job ID',
condition: { field: 'operation', value: ['get_agent_job', 'send_agent_message'] },
required: { field: 'operation', value: ['get_agent_job', 'send_agent_message'] },
},
{
id: 'prompt',
title: 'Prompt',
type: 'long-input',
placeholder: 'Add a quickstart guide for the Python SDK',
condition: { field: 'operation', value: ['create_agent_job', 'send_agent_message'] },
required: { field: 'operation', value: ['create_agent_job', 'send_agent_message'] },
},
{
id: 'deslopPath',
title: 'Page Path',
type: 'short-input',
placeholder: 'guides/quickstart.mdx',
condition: { field: 'operation', value: 'detect_ai_prose' },
required: { field: 'operation', value: 'detect_ai_prose' },
},
{
id: 'content',
title: 'Page Content',
type: 'long-input',
placeholder: 'Raw MDX or Markdown content of the page',
condition: { field: 'operation', value: 'detect_ai_prose' },
required: { field: 'operation', value: 'detect_ai_prose' },
},
{
id: 'query',
title: 'Search Query',
type: 'short-input',
placeholder: 'How do I configure custom domains?',
condition: { field: 'operation', value: 'search' },
required: { field: 'operation', value: 'search' },
},
{
id: 'pagePath',
title: 'Page Path',
type: 'short-input',
placeholder: 'Path returned by Search Documentation',
condition: { field: 'operation', value: 'get_page_content' },
required: { field: 'operation', value: 'get_page_content' },
},
{
id: 'message',
title: 'Question',
type: 'long-input',
placeholder: 'How do I get started?',
condition: { field: 'operation', value: 'create_assistant_message' },
},
{
id: 'pageSize',
title: 'Page Size',
type: 'short-input',
placeholder: '10',
condition: { field: 'operation', value: 'search' },
mode: 'advanced',
},
{
id: 'scoreThreshold',
title: 'Score Threshold',
type: 'short-input',
placeholder: '0.5',
condition: { field: 'operation', value: 'search' },
mode: 'advanced',
},
{
id: 'tag',
title: 'Tag Filter',
type: 'short-input',
placeholder: 'api-reference',
condition: { field: 'operation', value: 'search' },
mode: 'advanced',
},
{
id: 'version',
title: 'Version Filter',
type: 'short-input',
placeholder: 'v2',
condition: { field: 'operation', value: RETRIEVAL_FILTER_OPERATIONS },
mode: 'advanced',
},
{
id: 'language',
title: 'Language Filter',
type: 'short-input',
placeholder: 'en',
condition: { field: 'operation', value: RETRIEVAL_FILTER_OPERATIONS },
mode: 'advanced',
},
{
id: 'groups',
title: 'Authorized Groups',
type: 'long-input',
placeholder: '["customers", "internal"]',
condition: { field: 'operation', value: DOMAIN_OPERATIONS },
mode: 'advanced',
wandConfig: {
enabled: true,
prompt: `Generate a JSON array of Mintlify documentation group identifiers the caller is authorized to access.
### CONTEXT
{context}
### GUIDELINES
- Return ONLY a valid JSON array of strings, starting with [ and ending with ]
- Each entry is a group identifier configured on the deployment's auth or userAuth setup
### EXAMPLE
User: "customers and internal staff"
Output:
["customers", "internal"]
Return ONLY the JSON array.`,
placeholder: 'Describe the authorized groups...',
generationType: 'json-object',
},
},
{
id: 'messages',
title: 'Messages',
type: 'long-input',
placeholder: '[{"id": "1", "role": "user", "parts": [{"type": "text", "text": "Hello"}]}]',
condition: { field: 'operation', value: 'create_assistant_message' },
mode: 'advanced',
wandConfig: {
enabled: true,
prompt: `Generate a JSON array of AI SDK messages for the Mintlify assistant.
### CONTEXT
{context}
### GUIDELINES
- Return ONLY a valid JSON array starting with [ and ending with ]
- Each message has "id" (unique string), "role" ("user", "assistant", or "system"), and "parts"
- Each part is an object with "type": "text" and a "text" string
### EXAMPLE
User: "A user asking about pricing, then a follow-up about enterprise plans"
Output:
[{"id": "1", "role": "user", "parts": [{"type": "text", "text": "What does it cost?"}]}, {"id": "2", "role": "user", "parts": [{"type": "text", "text": "What about enterprise plans?"}]}]
Return ONLY the JSON array.`,
placeholder: 'Describe the conversation...',
generationType: 'json-object',
},
},
{
id: 'threadId',
title: 'Thread ID',
type: 'short-input',
placeholder: 'Thread ID from a previous assistant response',
condition: { field: 'operation', value: 'create_assistant_message' },
mode: 'advanced',
},
{
id: 'fp',
title: 'Fingerprint',
type: 'short-input',
placeholder: 'anonymous',
condition: { field: 'operation', value: 'create_assistant_message' },
mode: 'advanced',
},
{
id: 'retrievalPageSize',
title: 'Retrieval Page Size',
type: 'short-input',
placeholder: '5',
condition: { field: 'operation', value: 'create_assistant_message' },
mode: 'advanced',
},
{
id: 'currentPath',
title: 'Current Path',
type: 'short-input',
placeholder: 'guides/quickstart',
condition: { field: 'operation', value: 'create_assistant_message' },
mode: 'advanced',
},
{
id: 'assistantContext',
title: 'Context',
type: 'long-input',
placeholder: '[{"type": "code", "value": "const x = 1", "elementId": "code-block-1"}]',
condition: { field: 'operation', value: 'create_assistant_message' },
mode: 'advanced',
wandConfig: {
enabled: true,
prompt: `Generate a JSON array of Mintlify assistant context objects.
### CONTEXT
{context}
### GUIDELINES
- Return ONLY a valid JSON array starting with [ and ending with ]
- Each object requires "type" ("code" or "textSelection") and "value" (the snippet or selected text)
- Optionally include "path" (source file or page) and "elementId" (UI element identifier)
### EXAMPLE
User: "A code snippet from the quickstart page"
Output:
[{"type": "code", "value": "npm install mintlify", "path": "guides/quickstart", "elementId": "code-block-1"}]
Return ONLY the JSON array.`,
placeholder: 'Describe the context to provide...',
generationType: 'json-object',
},
},
{
id: 'dateFrom',
title: 'Date From',
type: 'short-input',
placeholder: '2026-01-01',
condition: { field: 'operation', value: ANALYTICS_OPERATIONS },
mode: 'advanced',
wandConfig: {
enabled: true,
prompt:
'Generate an inclusive start date in YYYY-MM-DD format for a Mintlify analytics export. Return ONLY the date string.',
generationType: 'timestamp',
},
},
{
id: 'dateTo',
title: 'Date To',
type: 'short-input',
placeholder: '2026-02-01',
condition: { field: 'operation', value: ANALYTICS_OPERATIONS },
mode: 'advanced',
wandConfig: {
enabled: true,
prompt:
'Generate an exclusive end date in YYYY-MM-DD format for a Mintlify analytics export. Results include dates before, but not on, this date. Return ONLY the date string.',
generationType: 'timestamp',
},
},
{
id: 'feedbackSource',
title: 'Feedback Source',
type: 'dropdown',
options: [
{ label: 'All Sources', id: '' },
{ label: 'Contextual', id: 'contextual' },
{ label: 'Code Snippet', id: 'code_snippet' },
{ label: 'Agent', id: 'agent' },
{ label: 'Thumbs Only', id: 'thumbs_only' },
],
value: () => '',
condition: { field: 'operation', value: FEEDBACK_OPERATIONS },
mode: 'advanced',
},
{
id: 'feedbackStatus',
title: 'Feedback Status',
type: 'short-input',
placeholder: 'pending,in_progress',
condition: { field: 'operation', value: FEEDBACK_OPERATIONS },
mode: 'advanced',
},
{
id: 'limit',
title: 'Limit',
type: 'short-input',
placeholder: '50',
condition: { field: 'operation', value: LIMIT_OPERATIONS },
mode: 'advanced',
},
{
id: 'cursor',
title: 'Cursor',
type: 'short-input',
placeholder: 'Cursor from a previous response',
condition: { field: 'operation', value: CURSOR_OPERATIONS },
mode: 'advanced',
},
{
id: 'offset',
title: 'Offset',
type: 'short-input',
placeholder: '0',
condition: { field: 'operation', value: ['get_views', 'get_visitors'] },
mode: 'advanced',
},
{
id: 'apiKey',
title: 'API Key',
type: 'short-input',
placeholder: 'Admin key (mint_) — assistant key (mint_dsc_) for docs search and assistant',
password: true,
required: true,
},
],
tools: {
access: [
'mintlify_trigger_update',
'mintlify_get_update_status',
'mintlify_trigger_preview',
'mintlify_trigger_automation',
'mintlify_detect_ai_prose',
'mintlify_create_agent_job',
'mintlify_get_agent_job',
'mintlify_send_agent_message',
'mintlify_search',
'mintlify_get_page_content',
'mintlify_create_assistant_message',
'mintlify_get_feedback',
'mintlify_get_feedback_by_page',
'mintlify_get_assistant_conversations',
'mintlify_get_assistant_caller_stats',
'mintlify_get_searches',
'mintlify_get_views',
'mintlify_get_visitors',
],
config: {
tool: (params: Record<string, unknown>) => `mintlify_${params.operation}`,
params: (params: Record<string, unknown>) => {
const { operation } = params
// On the agent-tool path `operation` is a sibling of the tool call rather
// than a member of params, so clearing anything here would erase the
// model's own arguments.
if (typeof operation !== 'string') return {}
const allowed = OPERATION_PARAMS[operation]
if (!allowed) return {}
const result: Record<string, unknown> = {}
for (const key of Object.keys(params)) {
if (key === 'operation' || key === 'apiKey') continue
result[key] = undefined
}
for (const key of allowed) {
const value = params[key]
if (value === undefined || value === null || value === '') continue
if (NUMERIC_PARAMS.has(key)) {
const numeric = Number(value)
if (!Number.isFinite(numeric)) continue
result[key] = numeric
continue
}
result[PARAM_ALIASES[key] ?? key] = value
}
return result
},
},
},
inputs: {
operation: { type: 'string', description: 'Operation to perform' },
projectId: { type: 'string', description: 'Mintlify project ID' },
domain: { type: 'string', description: 'Deployment domain identifier' },
statusId: { type: 'string', description: 'Deployment status ID' },
branch: { type: 'string', description: 'Git branch to preview' },
automationId: { type: 'string', description: 'Scheduled automation ID' },
jobId: { type: 'string', description: 'Agent job ID' },
prompt: { type: 'string', description: 'Instruction for the documentation agent' },
deslopPath: { type: 'string', description: 'Repo-relative path of the page to analyze' },
content: { type: 'string', description: 'Raw MDX or Markdown content of the page' },
query: { type: 'string', description: 'Documentation search query' },
pagePath: { type: 'string', description: 'Page slug or path to retrieve' },
message: { type: 'string', description: 'Question to ask the docs assistant' },
messages: { type: 'json', description: 'Full AI SDK message array for multi-turn chats' },
threadId: { type: 'string', description: 'Assistant thread ID to continue' },
fp: { type: 'string', description: 'Fingerprint identifier for the assistant session' },
retrievalPageSize: {
type: 'string',
description: 'Number of search results used to generate the assistant response',
},
currentPath: { type: 'string', description: 'Path of the page the user is viewing' },
assistantContext: { type: 'json', description: 'Contextual snippets for the assistant' },
pageSize: { type: 'string', description: 'Number of search results to return' },
scoreThreshold: { type: 'string', description: 'Minimum relevance score for search results' },
version: { type: 'string', description: 'Documentation version filter' },
language: { type: 'string', description: 'Content language filter' },
tag: { type: 'string', description: 'Tag filter for search results' },
groups: { type: 'json', description: 'Authorized documentation groups' },
dateFrom: { type: 'string', description: 'Inclusive analytics start date' },
dateTo: { type: 'string', description: 'Exclusive analytics end date' },
feedbackSource: { type: 'string', description: 'Feedback source filter' },
feedbackStatus: { type: 'string', description: 'Comma-separated feedback status filter' },
limit: { type: 'string', description: 'Max results per page' },
cursor: { type: 'string', description: 'Pagination cursor' },
offset: { type: 'string', description: 'Number of rows to skip' },
apiKey: { type: 'string', description: 'Mintlify API key' },
},
outputs: {
statusId: { type: 'string', description: 'Status ID of a queued deployment' },
previewUrl: { type: 'string', description: 'URL where the preview deployment is hosted' },
id: { type: 'string', description: 'Deployment status ID or agent job ID' },
projectId: { type: 'string', description: 'Documentation project ID' },
createdAt: { type: 'string', description: 'Creation timestamp' },
endedAt: { type: 'string', description: 'Deployment end timestamp' },
archivedAt: { type: 'string', description: 'Agent job archive timestamp' },
status: { type: 'string', description: 'Deployment status or agent job status' },
summary: { type: 'string', description: 'Summary of the deployment status' },
logs: { type: 'array', description: 'Deployment log lines' },
subdomain: { type: 'string', description: 'Subdomain of the docs being updated' },
screenshot: { type: 'string', description: 'Screenshot of the docs' },
screenshotLight: { type: 'string', description: 'Light-mode screenshot of the docs' },
screenshotDark: { type: 'string', description: 'Dark-mode screenshot of the docs' },
author: { type: 'json', description: 'Author of the deployment update' },
commit: { type: 'json', description: 'Commit that produced the deployment' },
source: {
type: 'json',
description:
'Deployment trigger source (string) or agent job source repository details (object)',
},
schemaId: { type: 'string', description: 'ID of the triggered automation' },
instanceId: { type: 'string', description: 'ID of the queued automation run' },
jobId: { type: 'string', description: 'ID of the background job processing an automation run' },
model: { type: 'string', description: 'AI model used for the agent job' },
prLink: { type: 'string', description: 'Pull request URL created by the agent' },
path: { type: 'string', description: 'Documentation page path' },
content: { type: 'string', description: 'Full text content of the page' },
skipped: { type: 'string', description: 'Reason a prose check was skipped' },
predictionShort: {
type: 'string',
description: 'Prose verdict: AI, AI-Assisted, Human, Mixed',
},
fractionAi: { type: 'number', description: 'Fraction of the page detected as AI-generated' },
fractionAiAssisted: { type: 'number', description: 'Fraction detected as AI-assisted' },
fractionHuman: { type: 'number', description: 'Fraction detected as human-written' },
windows: { type: 'array', description: 'Flagged passages with suggested rewrites' },
creditsCharged: { type: 'number', description: 'AI credits charged for the prose check' },
results: { type: 'array', description: 'Documentation search results' },
resultCount: { type: 'number', description: 'Number of search results returned' },
text: { type: 'string', description: 'Assembled assistant answer' },
threadId: { type: 'string', description: 'Assistant thread ID for follow-up messages' },
sources: { type: 'array', description: 'Documentation sources the assistant cited' },
feedback: { type: 'array', description: 'Feedback entries or per-page feedback aggregates' },
conversations: { type: 'array', description: 'Assistant conversation history' },
searches: { type: 'array', description: 'Documentation search terms with hit counts' },
totalSearches: { type: 'number', description: 'Total search events in the date range' },
views: { type: 'array', description: 'Per-page content view event counts' },
visitors: { type: 'array', description: 'Per-page unique visitor counts' },
totals: { type: 'json', description: 'Site-wide human, AI, and total traffic counts' },
web: { type: 'number', description: 'Assistant queries from the documentation site' },
api: { type: 'number', description: 'Assistant queries from API calls' },
other: { type: 'number', description: 'Assistant queries from other sources' },
total: { type: 'number', description: 'Total assistant queries across all caller types' },
nextCursor: { type: 'string', description: 'Cursor for the next page of results' },
hasMore: { type: 'boolean', description: 'Whether additional results are available' },
},
}
export const MintlifyBlockMeta = {
tags: ['content-management', 'knowledge-base', 'automation'],
url: 'https://mintlify.com',
templates: [
{
icon: MintlifyIcon,
title: 'Mintlify release-notes publisher',
prompt:
'Build a workflow that reads merged pull requests from GitHub, has an agent draft release notes, creates a Mintlify agent job to add them to the changelog, and triggers a docs deployment once the pull request merges.',
modules: ['agent', 'workflows'],
category: 'engineering',
tags: ['engineering', 'automation'],
alsoIntegrations: ['github'],
},
{
icon: MintlifyIcon,
title: 'Mintlify docs-gap reporter',
prompt:
'Create a scheduled workflow that exports Mintlify assistant conversations weekly, filters the ones marked unanswered, groups them into themes, and posts the top documentation gaps to Slack.',
modules: ['scheduled', 'agent', 'workflows'],
category: 'operations',
tags: ['analysis', 'reporting'],
alsoIntegrations: ['slack'],
},
{
icon: MintlifyIcon,
title: 'Mintlify support answer bot',
prompt:
'Build a workflow that takes an inbound support question, asks the Mintlify docs assistant for an answer, and replies in Slack with the answer and its cited documentation links.',
modules: ['agent', 'workflows'],
category: 'support',
tags: ['customer-support', 'automation'],
alsoIntegrations: ['slack'],
},
{
icon: MintlifyIcon,
title: 'Mintlify preview deployment on PR',
prompt:
'Create a workflow that triggers a Mintlify preview deployment for a Git branch, polls the deployment status until it succeeds or fails, and comments the preview URL on the GitHub pull request.',
modules: ['agent', 'workflows'],
category: 'engineering',
tags: ['ci-cd', 'devops'],
alsoIntegrations: ['github'],
},
{
icon: MintlifyIcon,
title: 'Mintlify prose-quality sweeper',
prompt:
'Build a scheduled workflow that reads documentation pages from a table, runs the Mintlify AI-prose detector on each one, and writes flagged passages and suggested rewrites back to the table for review.',
modules: ['scheduled', 'tables', 'agent', 'workflows'],
category: 'marketing',
tags: ['content', 'analysis'],
},
{
icon: MintlifyIcon,
title: 'Mintlify feedback triage',
prompt:
'Create a scheduled workflow that exports Mintlify user feedback daily, has an agent classify each comment by severity and theme, and opens Linear issues for the ones that need a documentation fix.',
modules: ['scheduled', 'agent', 'workflows'],
category: 'operations',
tags: ['triage', 'automation'],
alsoIntegrations: ['linear'],
},
{
icon: MintlifyIcon,
title: 'Mintlify traffic digest',
prompt:
'Build a scheduled workflow that exports Mintlify page views, unique visitors, and top search queries each week, writes them to a table, and emails a digest highlighting pages with rising AI traffic.',
modules: ['scheduled', 'tables', 'agent', 'workflows'],
category: 'marketing',
tags: ['analytics', 'reporting'],
alsoIntegrations: ['gmail'],
},
{
icon: MintlifyIcon,
title: 'Mintlify knowledge base mirror',
prompt:
'Create a workflow that searches a Mintlify documentation site, fetches the full content of each matching page, and loads it into a Sim knowledge base so agents can retrieve it offline.',
modules: ['knowledge-base', 'agent', 'workflows'],
category: 'engineering',
tags: ['sync', 'knowledge-base'],
},
],
skills: [
{
name: 'ship-docs-update',
description:
'Trigger a Mintlify documentation deployment and poll until it succeeds or fails.',
content:
'# Ship Docs Update\n\nDeploy the latest documentation and confirm it landed.\n\n## Steps\n1. Trigger an update for the Mintlify project and capture the returned status ID.\n2. Poll the update status with that ID until the status is `success` or `failure`.\n3. On failure, read the summary and logs and report what broke.\n4. On success, report the subdomain and the commit that shipped.\n\n## Output\nThe final status, the commit SHA and message, and the deployment logs when the update failed.',
},
{
name: 'answer-from-docs',
description: 'Answer a question using a Mintlify documentation site and cite the pages used.',
content:
'# Answer From Docs\n\nGround an answer in a published Mintlify documentation site.\n\n## Steps\n1. Search the documentation for the question.\n2. Fetch the full content of the most relevant matching pages.\n3. Synthesize an answer using only what those pages say.\n4. If the docs do not cover the question, say so instead of guessing.\n\n## Output\nA concise answer plus the paths of the pages it came from.',
},
{
name: 'find-docs-gaps',
description:
'Export Mintlify assistant conversations and surface the questions the docs could not answer.',
content:
'# Find Docs Gaps\n\nUse assistant history to find what the documentation is missing.\n\n## Steps\n1. Export assistant conversations for the requested date range.\n2. Keep the ones whose resolution status is `unanswered`.\n3. Group the remaining questions into themes and count how often each appears.\n4. For each theme, name the page that should cover it — existing or new.\n\n## Output\nA ranked list of documentation gaps with example questions and a suggested page for each.',
},
{
name: 'run-docs-agent-job',
description:
'Launch a Mintlify agent job to edit documentation and follow it through to a pull request.',
content:
'# Run Docs Agent Job\n\nHand a documentation edit to the Mintlify agent.\n\n## Steps\n1. Create an agent job with a specific, scoped instruction.\n2. Poll the job until its status is `completed`, `archived`, or `failed`.\n3. If the result needs adjusting, send a follow-up message to the same job and poll again.\n4. Report the pull request link once one is created.\n\n## Output\nThe final job status and the pull request URL, or an explanation of why no changes were made.',
},
{
name: 'report-docs-traffic',
description:
'Export Mintlify views, visitors, and search analytics into a single traffic summary.',
content:
'# Report Docs Traffic\n\nSummarize how a documentation site is being read.\n\n## Steps\n1. Export page views and unique visitors for the date range, paginating while `hasMore` is true.\n2. Export the top search queries for the same range.\n3. Compare human and AI traffic per page and flag pages where AI traffic dominates.\n4. Flag search queries with a low click-through rate — they point at missing or poorly titled pages.\n\n## Output\nSite-wide totals, the top pages by traffic, and the search terms that are not finding a good result.',
},
],
} as const satisfies BlockMeta
+3
View File
@@ -205,6 +205,7 @@ import {
import { MicrosoftPlannerBlock, MicrosoftPlannerBlockMeta } from '@/blocks/blocks/microsoft_planner'
import { MicrosoftTeamsBlock, MicrosoftTeamsBlockMeta } from '@/blocks/blocks/microsoft_teams'
import { MillionVerifierBlock, MillionVerifierBlockMeta } from '@/blocks/blocks/millionverifier'
import { MintlifyBlock, MintlifyBlockMeta } from '@/blocks/blocks/mintlify'
import {
MistralParseBlock,
MistralParseBlockMeta,
@@ -531,6 +532,7 @@ export const BLOCK_REGISTRY: Record<string, BlockConfig> = {
microsoft_excel_v2: MicrosoftExcelV2Block,
microsoft_planner: MicrosoftPlannerBlock,
microsoft_teams: MicrosoftTeamsBlock,
mintlify: MintlifyBlock,
mistral_parse: MistralParseBlock,
mistral_parse_v2: MistralParseV2Block,
mistral_parse_v3: MistralParseV3Block,
@@ -833,6 +835,7 @@ export const BLOCK_META_REGISTRY: Record<string, BlockMeta> = {
microsoft_planner: MicrosoftPlannerBlockMeta,
microsoft_teams: MicrosoftTeamsBlockMeta,
millionverifier: MillionVerifierBlockMeta,
mintlify: MintlifyBlockMeta,
mistral_parse: MistralParseBlockMeta,
monday: MondayBlockMeta,
mongodb: MongoDBBlockMeta,
+19
View File
@@ -2494,6 +2494,25 @@ export function DocumentIcon(props: SVGProps<SVGSVGElement>) {
)
}
export function MintlifyIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg {...props} xmlns='http://www.w3.org/2000/svg' viewBox='0 0 19 19' fill='none'>
<path
d='M18.367 7.28888V1.59755C18.367 0.986819 17.8715 0.5 17.2699 0.5H11.5812C10.6877 0.5 9.80295 0.677018 8.98017 1.01336C8.15738 1.35856 7.40539 1.85424 6.77724 2.49152L6.733 2.53578C5.90137 3.37664 5.30862 4.42108 5.00781 5.57174C5.54749 5.43012 6.10483 5.35931 6.6622 5.35046C8.14852 5.33276 9.60831 5.81073 10.7938 6.7047C11.8643 7.50131 12.6783 8.59885 13.1206 9.86458C13.5807 11.148 13.6337 12.5465 13.2887 13.8653C14.43 13.5644 15.4828 12.9714 16.3233 12.1393L16.3675 12.0951C16.9957 11.4667 17.4999 10.7143 17.845 9.89114C18.19 9.06797 18.3581 8.18285 18.3581 7.28888H18.367Z'
fill='#18E299'
/>
<path
d='M4.83793 7.193C4.84674 5.44706 5.54303 3.77167 6.76814 2.51953L2.03511 7.25472C2.01749 7.27236 1.99985 7.28117 1.98222 7.29881C0.827615 8.44513 0.131342 9.97945 0.0167623 11.6019C-0.0890033 13.1186 0.307609 14.6176 1.15373 15.8698C1.23444 15.9892 1.45343 16.0285 1.57682 15.9139L4.47656 13.0216C5.38438 12.1134 5.66643 10.7642 5.23455 9.55618C4.96132 8.80666 4.82912 8.00424 4.83793 7.193Z'
fill='#0C8C5E'
/>
<path
d='M16.341 12.0938C15.4332 12.9844 14.2962 13.6016 13.0623 13.875C11.8195 14.1483 10.5327 14.0689 9.33405 13.6457C9.33405 13.6457 9.32522 13.6457 9.31641 13.6457C8.10892 13.2136 6.76042 13.4958 5.8526 14.3952L2.95282 17.2875C2.82943 17.4109 2.84706 17.6137 2.99689 17.7107C4.24845 18.5484 5.74683 18.954 7.26281 18.8482C8.88455 18.7336 10.4093 18.037 11.5639 16.8818L11.608 16.8378L16.341 12.1026V12.0938Z'
fill='#0C8C5E'
/>
</svg>
)
}
export function MistralIcon(props: SVGProps<SVGSVGElement>) {
const id = useId()
const clipId = `mistral_clip_${id}`
@@ -148,6 +148,7 @@ import {
MicrosoftSharepointIcon,
MicrosoftTeamsIcon,
MillionVerifierIcon,
MintlifyIcon,
MistralIcon,
MondayIcon,
MongoDBIcon,
@@ -414,6 +415,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
microsoft_teams: MicrosoftTeamsIcon,
'microsoft-teams': MicrosoftTeamsIcon,
millionverifier: MillionVerifierIcon,
mintlify: MintlifyIcon,
mistral_parse_v3: MistralIcon,
monday: MondayIcon,
mongodb: MongoDBIcon,
@@ -12831,6 +12831,97 @@
"integrationType": "sales",
"tags": ["enrichment", "sales-engagement"]
},
{
"type": "mintlify",
"slug": "mintlify",
"name": "Mintlify",
"description": "Deploy, edit, search, and measure Mintlify documentation",
"longDescription": "Integrate Mintlify into your workflow. Trigger production and preview deployments, run scheduled automations, launch documentation agent jobs, detect AI-sounding prose, search your docs and read page content, ask the docs assistant, and export feedback, conversation, search, view, and visitor analytics.",
"bgColor": "#000000",
"iconName": "MintlifyIcon",
"docsUrl": "https://docs.sim.ai/integrations/mintlify",
"operations": [
{
"name": "Trigger Update",
"description": "Queue a deployment update for a Mintlify documentation project from its configured deployment branch. Returns a status ID for tracking progress."
},
{
"name": "Get Update Status",
"description": "Get the status of a Mintlify deployment update from its status ID, including logs, commit details, and screenshots."
},
{
"name": "Trigger Preview Deployment",
"description": "Create or update a Mintlify preview deployment for a Git branch. Redeploys when a preview already exists for the branch."
},
{
"name": "Trigger Automation",
"description": "Run a scheduled Mintlify automation immediately instead of waiting for its next scheduled time. Only automations with a custom schedule can be triggered."
},
{
"name": "Create Agent Job",
"description": "Create a background Mintlify agent job that edits your documentation from a prompt. Opens a pull request when the agent successfully edits files."
},
{
"name": "Get Agent Job",
"description": "Retrieve the current status and details of a Mintlify agent job, including the pull request link once the agent opens one."
},
{
"name": "Send Agent Message",
"description": "Send a follow-up instruction to an existing Mintlify agent job. The message is processed asynchronously."
},
{
"name": "Detect AI-Sounding Prose",
"description": "Analyze a documentation page for AI-generated prose and return flagged passages with suggested human rewrites. Consumes one AI credit per checked page."
},
{
"name": "Search Documentation",
"description": "Run a semantic and keyword search across a Mintlify documentation site, with optional version, language, tag, and group filters."
},
{
"name": "Get Page Content",
"description": "Retrieve the full text content of a Mintlify documentation page by its path. Use it after a search to fetch the complete page."
},
{
"name": "Ask Assistant",
"description": "Ask the Mintlify assistant, trained on your documentation, a question and get the assembled answer with its cited sources. Consumes the deployment's assistant credits."
},
{
"name": "Get Feedback",
"description": "Export paginated user feedback from a Mintlify documentation project, with optional date-range, source, and status filters."
},
{
"name": "Get Feedback By Page",
"description": "Export Mintlify feedback counts aggregated by documentation page path, broken down into thumbs up, thumbs down, and code snippet feedback."
},
{
"name": "Get Assistant Conversations",
"description": "Export paginated Mintlify AI assistant conversation history, including the query, response, cited sources, and whether the question was answered."
},
{
"name": "Get Assistant Caller Stats",
"description": "Get a breakdown of Mintlify assistant query counts by caller type — web, API, and other — for a date range."
},
{
"name": "Get Search Queries",
"description": "Export Mintlify documentation search terms for a date range, ordered by hit count, with click-through rate and the most-clicked result path."
},
{
"name": "Get Page Views",
"description": "Export Mintlify per-path and site-wide content view counts for a date range, split by human and AI bot traffic."
},
{
"name": "Get Unique Visitors",
"description": "Export Mintlify per-path and site-wide approximate distinct visitor counts for a date range, split by human and AI bot traffic."
}
],
"operationCount": 18,
"triggers": [],
"triggerCount": 0,
"authType": "api-key",
"category": "tools",
"integrationType": "documents",
"tags": ["content-management", "knowledge-base", "automation"]
},
{
"type": "mistral_parse_v3",
"slug": "mistral-parser",
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,60 @@
import type { MintlifyAgentJobResponse, MintlifyCreateAgentJobParams } from '@/tools/mintlify/types'
import {
AGENT_JOB_OUTPUTS,
MINTLIFY_API_BASE,
mintlifyHeaders,
pathSegment,
readMintlifyJson,
toAgentJobOutput,
} from '@/tools/mintlify/utils'
import type { ToolConfig } from '@/tools/types'
export const mintlifyCreateAgentJobTool: ToolConfig<
MintlifyCreateAgentJobParams,
MintlifyAgentJobResponse
> = {
id: 'mintlify_create_agent_job',
name: 'Mintlify Create Agent Job',
description:
'Create a background Mintlify agent job that edits your documentation from a prompt. Opens a pull request when the agent successfully edits files.',
version: '1.0.0',
params: {
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Mintlify project ID, copied from the API keys page in your dashboard',
},
prompt: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The instruction for the agent to execute',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Mintlify admin API key (starts with mint_)',
},
},
request: {
url: (params) => `${MINTLIFY_API_BASE}/v2/agent/${pathSegment(params.projectId)}/job`,
method: 'POST',
headers: (params) => mintlifyHeaders(params.apiKey),
body: (params) => ({ prompt: params.prompt }),
},
transformResponse: async (response: Response) => {
const data = await readMintlifyJson(response, 'Failed to create Mintlify agent job')
return {
success: true,
output: toAgentJobOutput(data),
}
},
outputs: AGENT_JOB_OUTPUTS,
}
@@ -0,0 +1,255 @@
import { generateId } from '@sim/utils/id'
import type {
MintlifyAssistantSource,
MintlifyCreateAssistantMessageParams,
MintlifyCreateAssistantMessageResponse,
} from '@/tools/mintlify/types'
import {
MINTLIFY_API_BASE,
mintlifyHeaders,
pathSegment,
toNullableString,
toObjectArray,
toStringArray,
} from '@/tools/mintlify/utils'
import type { ToolConfig } from '@/tools/types'
interface AssistantStreamResult {
text: string
threadId: string | null
sources: MintlifyAssistantSource[]
errorText: string | null
}
/**
* Collapses the AI SDK v5 UI message stream the assistant endpoint returns into
* the assembled answer text, its cited sources, and the thread ID emitted on
* the terminal `finish` event.
*/
function parseAssistantStream(body: string): AssistantStreamResult {
const result: AssistantStreamResult = { text: '', threadId: null, sources: [], errorText: null }
for (const rawLine of body.split('\n')) {
const line = rawLine.trim()
if (!line.startsWith('data:')) continue
const payload = line.slice('data:'.length).trim()
if (!payload || payload === '[DONE]') continue
let event: Record<string, unknown>
try {
event = JSON.parse(payload)
} catch {
continue
}
switch (event.type) {
case 'text-delta':
if (typeof event.delta === 'string') result.text += event.delta
break
case 'source-url':
result.sources.push({
sourceId: toNullableString(event.sourceId),
url: toNullableString(event.url),
title: toNullableString(event.title),
})
break
case 'error':
result.errorText = toNullableString(event.errorText)
break
case 'finish':
result.threadId = toNullableString(event.threadId)
break
default:
break
}
}
return result
}
export const mintlifyCreateAssistantMessageTool: ToolConfig<
MintlifyCreateAssistantMessageParams,
MintlifyCreateAssistantMessageResponse
> = {
id: 'mintlify_create_assistant_message',
name: 'Mintlify Create Assistant Message',
description:
"Ask the Mintlify assistant, trained on your documentation, a question and get the assembled answer with its cited sources. Consumes the deployment's assistant credits.",
version: '1.0.0',
params: {
domain: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description:
'Domain identifier from your domain.mintlify.site URL, found at the end of your dashboard URL',
},
message: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'The question to ask the assistant. Ignored when a full Messages array is supplied.',
},
messages: {
type: 'json',
required: false,
visibility: 'user-or-llm',
description:
'Full AI SDK message array for multi-turn conversations, each entry with id, role, and parts. Overrides Message when provided.',
},
fp: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'Fingerprint identifier for tracking conversation sessions (default "anonymous")',
},
threadId: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Thread ID from a previous response, to continue the same conversation',
},
retrievalPageSize: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Number of documentation search results used to generate the response',
},
currentPath: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'Path of the page the user is currently viewing, for more relevant answers (max 200 characters)',
},
version: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter retrieval by documentation version',
},
language: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter retrieval by content language',
},
groups: {
type: 'json',
required: false,
visibility: 'user-or-llm',
description: 'Group identifiers to filter retrieval by, as a JSON array of strings',
},
assistantContext: {
type: 'json',
required: false,
visibility: 'user-or-llm',
description:
'Contextual snippets for the assistant, as a JSON array of objects with type ("code" or "textSelection"), value, and optional path and elementId',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Mintlify assistant API key (starts with mint_dsc_)',
},
},
request: {
url: (params) =>
`${MINTLIFY_API_BASE}/discovery/v2/assistant/${pathSegment(params.domain)}/message`,
method: 'POST',
headers: (params) => mintlifyHeaders(params.apiKey),
body: (params) => {
const messages = toObjectArray(params.messages)
if (!messages && !params.message) {
throw new Error('Either Message or Messages is required')
}
const body: Record<string, unknown> = {
fp: params.fp || 'anonymous',
messages: messages ?? [
{
id: generateId(),
role: 'user',
parts: [{ type: 'text', text: params.message }],
},
],
}
if (params.threadId) body.threadId = params.threadId
if (params.retrievalPageSize !== undefined) {
body.retrievalPageSize = params.retrievalPageSize
}
if (params.currentPath) body.currentPath = params.currentPath
const groups = toStringArray(params.groups)
const filter: Record<string, unknown> = {}
if (params.version) filter.version = params.version
if (params.language) filter.language = params.language
if (groups) filter.groups = groups
if (Object.keys(filter).length > 0) body.filter = filter
const context = toObjectArray(params.assistantContext)
if (context) body.context = context
return body
},
},
transformResponse: async (response: Response) => {
const body = await response.text()
if (!response.ok) {
let message = body.trim()
try {
const parsed = JSON.parse(body)
message = parsed?.error || parsed?.message || message
} catch {
// Non-JSON error bodies are surfaced verbatim.
}
throw new Error(
message || `Failed to create Mintlify assistant message (HTTP ${response.status})`
)
}
const stream = parseAssistantStream(body)
if (stream.errorText) {
throw new Error(stream.errorText)
}
return {
success: true,
output: {
text: stream.text,
threadId: stream.threadId,
sources: stream.sources,
},
}
},
outputs: {
text: { type: 'string', description: 'Assembled assistant answer' },
threadId: {
type: 'string',
description: 'Thread ID for continuing this conversation in a follow-up call',
nullable: true,
},
sources: {
type: 'array',
description: 'Documentation sources the assistant cited',
items: {
type: 'object',
properties: {
sourceId: { type: 'string', description: 'Source identifier', nullable: true },
url: { type: 'string', description: 'URL of the cited page', nullable: true },
title: { type: 'string', description: 'Title of the cited page', nullable: true },
},
},
},
},
}
+192
View File
@@ -0,0 +1,192 @@
import type {
MintlifyDeslopRewrite,
MintlifyDeslopWindow,
MintlifyDetectAiProseParams,
MintlifyDetectAiProseResponse,
} from '@/tools/mintlify/types'
import {
MINTLIFY_API_BASE,
mintlifyHeaders,
pathSegment,
readMintlifyJson,
toNullableNumber,
toNullableString,
} from '@/tools/mintlify/utils'
import type { ToolConfig } from '@/tools/types'
function toRewrites(value: unknown): MintlifyDeslopRewrite[] {
if (!Array.isArray(value)) return []
return value.map((entry) => {
const rewrite = (entry ?? {}) as Record<string, unknown>
return {
text: toNullableString(rewrite.text) ?? '',
rationale: toNullableString(rewrite.rationale) ?? '',
}
})
}
function toWindows(value: unknown): MintlifyDeslopWindow[] {
if (!Array.isArray(value)) return []
return value.map((entry) => {
const window = (entry ?? {}) as Record<string, unknown>
const confidence = window.confidence
return {
text: toNullableString(window.text) ?? '',
label: toNullableString(window.label) ?? '',
aiAssistanceScore: toNullableNumber(window.aiAssistanceScore),
confidence:
typeof confidence === 'string' || typeof confidence === 'number' ? confidence : null,
startLine: toNullableNumber(window.startLine),
endLine: toNullableNumber(window.endLine),
rewrites: toRewrites(window.rewrites),
}
})
}
export const mintlifyDetectAiProseTool: ToolConfig<
MintlifyDetectAiProseParams,
MintlifyDetectAiProseResponse
> = {
id: 'mintlify_detect_ai_prose',
name: 'Mintlify Detect AI-Sounding Prose',
description:
'Analyze a documentation page for AI-generated prose and return flagged passages with suggested human rewrites. Consumes one AI credit per checked page.',
version: '1.0.0',
params: {
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Mintlify project ID, copied from the API keys page in your dashboard',
},
path: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Repo-relative path of the page, used for reporting only',
},
content: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Raw MDX or Markdown content of the page to check (max 1,000,000 characters)',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Mintlify admin API key (starts with mint_)',
},
},
request: {
url: (params) => `${MINTLIFY_API_BASE}/v1/deslop/${pathSegment(params.projectId)}`,
method: 'POST',
headers: (params) => mintlifyHeaders(params.apiKey),
body: (params) => ({ path: params.path, content: params.content }),
},
transformResponse: async (response: Response) => {
const data = await readMintlifyJson(response, 'Failed to analyze page for AI-sounding prose')
return {
success: true,
output: {
path: toNullableString(data.path),
skipped: toNullableString(data.skipped),
predictionShort: toNullableString(data.predictionShort),
fractionAi: toNullableNumber(data.fractionAi),
fractionAiAssisted: toNullableNumber(data.fractionAiAssisted),
fractionHuman: toNullableNumber(data.fractionHuman),
windows: toWindows(data.windows),
creditsCharged: toNullableNumber(data.creditsCharged),
},
}
},
outputs: {
path: { type: 'string', description: 'Path from the request', nullable: true },
skipped: {
type: 'string',
description: 'Reason the page was skipped ("too_short"), or null when the page was checked',
nullable: true,
},
predictionShort: {
type: 'string',
description:
'Overall verdict for the page: AI, AI-Assisted, Human, or Mixed. Null when the page was skipped.',
nullable: true,
optional: true,
},
fractionAi: {
type: 'number',
description:
'Fraction of the page detected as AI-generated (0-1). Null when the page was skipped.',
nullable: true,
optional: true,
},
fractionAiAssisted: {
type: 'number',
description:
'Fraction of the page detected as AI-assisted (0-1). Null when the page was skipped.',
nullable: true,
optional: true,
},
fractionHuman: {
type: 'number',
description:
'Fraction of the page detected as human-written (0-1). Null when the page was skipped.',
nullable: true,
optional: true,
},
windows: {
type: 'array',
description:
'Flagged non-human passages with line ranges and suggested rewrites. Empty when the page was skipped.',
items: {
type: 'object',
properties: {
text: { type: 'string', description: 'The flagged passage text' },
label: { type: 'string', description: 'Detection label, for example AI-Generated' },
aiAssistanceScore: {
type: 'number',
description: 'AI-assistance score for the passage (0-1)',
nullable: true,
},
confidence: {
type: 'json',
description: 'Detection confidence, either a label such as High or a numeric score',
nullable: true,
},
startLine: {
type: 'number',
description: '1-based start line of the passage',
nullable: true,
},
endLine: {
type: 'number',
description: '1-based end line of the passage',
nullable: true,
},
rewrites: {
type: 'array',
description: 'Suggested human rewrites of the passage',
items: {
type: 'object',
properties: {
text: { type: 'string', description: 'The rewritten passage' },
rationale: { type: 'string', description: 'Why the rewrite reads more human' },
},
},
},
},
},
},
creditsCharged: {
type: 'number',
description: 'AI credits charged for this request (0 when skipped)',
nullable: true,
},
},
}
+60
View File
@@ -0,0 +1,60 @@
import type { MintlifyAgentJobResponse, MintlifyGetAgentJobParams } from '@/tools/mintlify/types'
import {
AGENT_JOB_OUTPUTS,
MINTLIFY_API_BASE,
mintlifyHeaders,
pathSegment,
readMintlifyJson,
toAgentJobOutput,
} from '@/tools/mintlify/utils'
import type { ToolConfig } from '@/tools/types'
export const mintlifyGetAgentJobTool: ToolConfig<
MintlifyGetAgentJobParams,
MintlifyAgentJobResponse
> = {
id: 'mintlify_get_agent_job',
name: 'Mintlify Get Agent Job',
description:
'Retrieve the current status and details of a Mintlify agent job, including the pull request link once the agent opens one.',
version: '1.0.0',
params: {
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Mintlify project ID, copied from the API keys page in your dashboard',
},
jobId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Unique identifier of the agent job',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Mintlify admin API key (starts with mint_)',
},
},
request: {
url: (params) =>
`${MINTLIFY_API_BASE}/v2/agent/${pathSegment(params.projectId)}/job/${pathSegment(params.jobId)}`,
method: 'GET',
headers: (params) => mintlifyHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await readMintlifyJson(response, 'Failed to get Mintlify agent job')
return {
success: true,
output: toAgentJobOutput(data),
}
},
outputs: AGENT_JOB_OUTPUTS,
}
@@ -0,0 +1,101 @@
import type {
MintlifyGetAssistantCallerStatsParams,
MintlifyGetAssistantCallerStatsResponse,
} from '@/tools/mintlify/types'
import {
appendParam,
MINTLIFY_API_BASE,
mintlifyHeaders,
pathSegment,
readMintlifyJson,
toNullableNumber,
} from '@/tools/mintlify/utils'
import type { ToolConfig } from '@/tools/types'
export const mintlifyGetAssistantCallerStatsTool: ToolConfig<
MintlifyGetAssistantCallerStatsParams,
MintlifyGetAssistantCallerStatsResponse
> = {
id: 'mintlify_get_assistant_caller_stats',
name: 'Mintlify Get Assistant Caller Stats',
description:
'Get a breakdown of Mintlify assistant query counts by caller type — web, API, and other — for a date range.',
version: '1.0.0',
params: {
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Mintlify project ID, copied from the API keys page in your dashboard',
},
dateFrom: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Inclusive start date in ISO 8601 or YYYY-MM-DD format',
},
dateTo: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Exclusive end date in ISO 8601 or YYYY-MM-DD format',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Mintlify admin API key (starts with mint_)',
},
},
request: {
url: (params) => {
const url = new URL(
`${MINTLIFY_API_BASE}/v1/analytics/${pathSegment(params.projectId)}/assistant/caller-stats`
)
appendParam(url, 'dateFrom', params.dateFrom)
appendParam(url, 'dateTo', params.dateTo)
return url.toString()
},
method: 'GET',
headers: (params) => mintlifyHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await readMintlifyJson(response, 'Failed to get Mintlify assistant caller stats')
return {
success: true,
output: {
web: toNullableNumber(data.web),
api: toNullableNumber(data.api),
other: toNullableNumber(data.other),
total: toNullableNumber(data.total),
},
}
},
outputs: {
web: {
type: 'number',
description: 'Assistant queries originating from the documentation site',
nullable: true,
},
api: {
type: 'number',
description: 'Assistant queries originating from API calls',
nullable: true,
},
other: {
type: 'number',
description: 'Assistant queries from other sources such as integrations and SDKs',
nullable: true,
},
total: {
type: 'number',
description: 'Total assistant queries across all caller types',
nullable: true,
},
},
}
@@ -0,0 +1,169 @@
import type {
MintlifyConversation,
MintlifyGetAssistantConversationsParams,
MintlifyGetAssistantConversationsResponse,
} from '@/tools/mintlify/types'
import {
appendParam,
MINTLIFY_API_BASE,
mintlifyHeaders,
pathSegment,
readMintlifyJson,
toNullableString,
} from '@/tools/mintlify/utils'
import type { ToolConfig } from '@/tools/types'
function toConversations(value: unknown): MintlifyConversation[] {
if (!Array.isArray(value)) return []
return value.map((item) => {
const conversation = (item ?? {}) as Record<string, unknown>
const sources = Array.isArray(conversation.sources) ? conversation.sources : []
return {
id: toNullableString(conversation.id),
timestamp: toNullableString(conversation.timestamp),
query: toNullableString(conversation.query),
response: toNullableString(conversation.response),
sources: sources.map((entry) => {
const source = (entry ?? {}) as Record<string, unknown>
return {
title: toNullableString(source.title),
url: toNullableString(source.url),
}
}),
resolutionStatus: toNullableString(conversation.resolutionStatus),
queryCategory: toNullableString(conversation.queryCategory),
pageUrl: toNullableString(conversation.pageUrl),
}
})
}
export const mintlifyGetAssistantConversationsTool: ToolConfig<
MintlifyGetAssistantConversationsParams,
MintlifyGetAssistantConversationsResponse
> = {
id: 'mintlify_get_assistant_conversations',
name: 'Mintlify Get Assistant Conversations',
description:
'Export paginated Mintlify AI assistant conversation history, including the query, response, cited sources, and whether the question was answered.',
version: '1.0.0',
params: {
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Mintlify project ID, copied from the API keys page in your dashboard',
},
dateFrom: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Inclusive start date in ISO 8601 or YYYY-MM-DD format',
},
dateTo: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Exclusive end date in ISO 8601 or YYYY-MM-DD format',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Max results per page, between 1 and 1000 (default 100)',
},
cursor: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'ULID pagination cursor returned as nextCursor by a previous call',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Mintlify admin API key (starts with mint_)',
},
},
request: {
url: (params) => {
const url = new URL(
`${MINTLIFY_API_BASE}/v1/analytics/${pathSegment(params.projectId)}/assistant`
)
appendParam(url, 'dateFrom', params.dateFrom)
appendParam(url, 'dateTo', params.dateTo)
appendParam(url, 'limit', params.limit)
appendParam(url, 'cursor', params.cursor)
return url.toString()
},
method: 'GET',
headers: (params) => mintlifyHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await readMintlifyJson(response, 'Failed to get Mintlify assistant conversations')
return {
success: true,
output: {
conversations: toConversations(data.conversations),
nextCursor: toNullableString(data.nextCursor),
hasMore: data.hasMore === true,
},
}
},
outputs: {
conversations: {
type: 'array',
description: 'Assistant conversations for the requested window',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Unique conversation identifier', nullable: true },
timestamp: {
type: 'string',
description: 'When the conversation occurred',
nullable: true,
},
query: { type: 'string', description: "The user's question", nullable: true },
response: { type: 'string', description: "The assistant's response", nullable: true },
sources: {
type: 'array',
description: 'Documentation pages referenced in the response',
items: {
type: 'object',
properties: {
title: { type: 'string', description: 'Title of the page', nullable: true },
url: { type: 'string', description: 'URL of the page', nullable: true },
},
},
},
resolutionStatus: {
type: 'string',
description: 'Whether the assistant answered the question: answered or unanswered',
nullable: true,
},
queryCategory: {
type: 'string',
description: 'Auto-assigned category grouping for the conversation',
nullable: true,
},
pageUrl: {
type: 'string',
description: 'Full URL of the page where the conversation started',
nullable: true,
},
},
},
},
nextCursor: {
type: 'string',
description: 'Cursor for the next page, or null when there are no more results',
nullable: true,
},
hasMore: { type: 'boolean', description: 'Whether additional results are available' },
},
}
+184
View File
@@ -0,0 +1,184 @@
import type {
MintlifyFeedbackEntry,
MintlifyGetFeedbackParams,
MintlifyGetFeedbackResponse,
} from '@/tools/mintlify/types'
import {
appendParam,
MINTLIFY_API_BASE,
mintlifyHeaders,
pathSegment,
readMintlifyJson,
toNullableString,
} from '@/tools/mintlify/utils'
import type { ToolConfig } from '@/tools/types'
function toFeedbackEntries(value: unknown): MintlifyFeedbackEntry[] {
if (!Array.isArray(value)) return []
return value.map((item) => {
const entry = (item ?? {}) as Record<string, unknown>
return {
id: toNullableString(entry.id),
path: toNullableString(entry.path),
comment: toNullableString(entry.comment),
createdAt: toNullableString(entry.createdAt),
source: toNullableString(entry.source),
status: toNullableString(entry.status),
helpful: typeof entry.helpful === 'boolean' ? entry.helpful : null,
contact: toNullableString(entry.contact),
code: toNullableString(entry.code),
filename: toNullableString(entry.filename),
lang: toNullableString(entry.lang),
}
})
}
export const mintlifyGetFeedbackTool: ToolConfig<
MintlifyGetFeedbackParams,
MintlifyGetFeedbackResponse
> = {
id: 'mintlify_get_feedback',
name: 'Mintlify Get Feedback',
description:
'Export paginated user feedback from a Mintlify documentation project, with optional date-range, source, and status filters.',
version: '1.0.0',
params: {
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Mintlify project ID, copied from the API keys page in your dashboard',
},
dateFrom: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Inclusive start date in ISO 8601 or YYYY-MM-DD format',
},
dateTo: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Exclusive end date in ISO 8601 or YYYY-MM-DD format',
},
source: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter by feedback source: code_snippet, contextual, agent, or thumbs_only',
},
status: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'Comma-separated statuses to filter by: pending, in_progress, resolved, dismissed',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Max results per page, between 1 and 100 (default 50)',
},
cursor: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Pagination cursor returned as nextCursor by a previous call',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Mintlify admin API key (starts with mint_)',
},
},
request: {
url: (params) => {
const url = new URL(
`${MINTLIFY_API_BASE}/v1/analytics/${pathSegment(params.projectId)}/feedback`
)
appendParam(url, 'dateFrom', params.dateFrom)
appendParam(url, 'dateTo', params.dateTo)
appendParam(url, 'source', params.source)
appendParam(url, 'status', params.status)
appendParam(url, 'limit', params.limit)
appendParam(url, 'cursor', params.cursor)
return url.toString()
},
method: 'GET',
headers: (params) => mintlifyHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await readMintlifyJson(response, 'Failed to get Mintlify feedback')
return {
success: true,
output: {
feedback: toFeedbackEntries(data.feedback),
nextCursor: toNullableString(data.nextCursor),
hasMore: data.hasMore === true,
},
}
},
outputs: {
feedback: {
type: 'array',
description: 'Feedback entries for the requested window',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Unique feedback identifier', nullable: true },
path: { type: 'string', description: 'Path or URL of the page', nullable: true },
comment: { type: 'string', description: 'Text of the feedback comment', nullable: true },
createdAt: { type: 'string', description: 'Submission timestamp', nullable: true },
source: {
type: 'string',
description: 'Origin: code_snippet, contextual, agent, or thumbs_only',
nullable: true,
},
status: {
type: 'string',
description: 'Review status: pending, in_progress, resolved, or dismissed',
nullable: true,
},
helpful: {
type: 'boolean',
description: 'Whether the user found the content helpful (contextual feedback only)',
nullable: true,
},
contact: {
type: 'string',
description: 'Email the user provided for follow-up (contextual feedback only)',
nullable: true,
},
code: {
type: 'string',
description: 'Code snippet the feedback relates to (code_snippet feedback only)',
nullable: true,
},
filename: {
type: 'string',
description: 'Filename of the code snippet (code_snippet feedback only)',
nullable: true,
},
lang: {
type: 'string',
description: 'Language of the code snippet (code_snippet feedback only)',
nullable: true,
},
},
},
},
nextCursor: {
type: 'string',
description: 'Cursor for the next page, or null when there are no more results',
nullable: true,
},
hasMore: { type: 'boolean', description: 'Whether additional results are available' },
},
}
@@ -0,0 +1,140 @@
import type {
MintlifyFeedbackPageEntry,
MintlifyGetFeedbackByPageParams,
MintlifyGetFeedbackByPageResponse,
} from '@/tools/mintlify/types'
import {
appendParam,
MINTLIFY_API_BASE,
mintlifyHeaders,
pathSegment,
readMintlifyJson,
toNullableNumber,
toNullableString,
} from '@/tools/mintlify/utils'
import type { ToolConfig } from '@/tools/types'
function toPageEntries(value: unknown): MintlifyFeedbackPageEntry[] {
if (!Array.isArray(value)) return []
return value.map((item) => {
const entry = (item ?? {}) as Record<string, unknown>
return {
path: toNullableString(entry.path),
thumbsUp: toNullableNumber(entry.thumbsUp),
thumbsDown: toNullableNumber(entry.thumbsDown),
code: toNullableNumber(entry.code),
total: toNullableNumber(entry.total),
}
})
}
export const mintlifyGetFeedbackByPageTool: ToolConfig<
MintlifyGetFeedbackByPageParams,
MintlifyGetFeedbackByPageResponse
> = {
id: 'mintlify_get_feedback_by_page',
name: 'Mintlify Get Feedback By Page',
description:
'Export Mintlify feedback counts aggregated by documentation page path, broken down into thumbs up, thumbs down, and code snippet feedback.',
version: '1.0.0',
params: {
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Mintlify project ID, copied from the API keys page in your dashboard',
},
dateFrom: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Inclusive start date in ISO 8601 or YYYY-MM-DD format',
},
dateTo: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Exclusive end date in ISO 8601 or YYYY-MM-DD format',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Max results per page, between 1 and 100 (default 10)',
},
source: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter by feedback source: code_snippet, contextual, agent, or thumbs_only',
},
status: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'Comma-separated statuses to filter by: pending, in_progress, resolved, dismissed',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Mintlify admin API key (starts with mint_)',
},
},
request: {
url: (params) => {
const url = new URL(
`${MINTLIFY_API_BASE}/v1/analytics/${pathSegment(params.projectId)}/feedback/by-page`
)
appendParam(url, 'dateFrom', params.dateFrom)
appendParam(url, 'dateTo', params.dateTo)
appendParam(url, 'limit', params.limit)
appendParam(url, 'source', params.source)
appendParam(url, 'status', params.status)
return url.toString()
},
method: 'GET',
headers: (params) => mintlifyHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await readMintlifyJson(response, 'Failed to get Mintlify feedback by page')
return {
success: true,
output: {
feedback: toPageEntries(data.feedback),
hasMore: data.hasMore === true,
},
}
},
outputs: {
feedback: {
type: 'array',
description: 'Feedback counts aggregated by documentation page path',
items: {
type: 'object',
properties: {
path: { type: 'string', description: 'The documentation page path', nullable: true },
thumbsUp: {
type: 'number',
description: 'Positive contextual feedback entries',
nullable: true,
},
thumbsDown: {
type: 'number',
description: 'Negative contextual feedback entries',
nullable: true,
},
code: { type: 'number', description: 'Code snippet feedback entries', nullable: true },
total: { type: 'number', description: 'Total feedback entries', nullable: true },
},
},
},
hasMore: { type: 'boolean', description: 'Whether additional results are available' },
},
}
@@ -0,0 +1,83 @@
import type {
MintlifyGetPageContentParams,
MintlifyGetPageContentResponse,
} from '@/tools/mintlify/types'
import {
MINTLIFY_API_BASE,
mintlifyHeaders,
pathSegment,
readMintlifyJson,
toNullableString,
toStringArray,
} from '@/tools/mintlify/utils'
import type { ToolConfig } from '@/tools/types'
export const mintlifyGetPageContentTool: ToolConfig<
MintlifyGetPageContentParams,
MintlifyGetPageContentResponse
> = {
id: 'mintlify_get_page_content',
name: 'Mintlify Get Page Content',
description:
'Retrieve the full text content of a Mintlify documentation page by its path. Use it after a search to fetch the complete page.',
version: '1.0.0',
params: {
domain: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description:
'Domain identifier from your domain.mintlify.site URL, found at the end of your dashboard URL',
},
path: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description:
'Page slug or path to retrieve, matching the path field returned by Search Documentation',
},
groups: {
type: 'json',
required: false,
visibility: 'user-or-llm',
description:
'Documentation groups the caller is authorized to access, as a JSON array of strings. Only applies to deployments using auth or userAuth.',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Mintlify assistant API key (starts with mint_dsc_)',
},
},
request: {
url: (params) => `${MINTLIFY_API_BASE}/discovery/v1/page/${pathSegment(params.domain)}`,
method: 'POST',
headers: (params) => mintlifyHeaders(params.apiKey),
body: (params) => {
const body: Record<string, unknown> = { path: params.path }
const groups = toStringArray(params.groups)
if (groups) body.groups = groups
return body
},
},
transformResponse: async (response: Response) => {
const data = await readMintlifyJson(response, 'Failed to get Mintlify page content')
return {
success: true,
output: {
path: toNullableString(data.path),
content: toNullableString(data.content),
},
}
},
outputs: {
path: { type: 'string', description: 'The page path that was requested', nullable: true },
content: { type: 'string', description: 'Full text content of the page', nullable: true },
},
}
+155
View File
@@ -0,0 +1,155 @@
import type {
MintlifyGetSearchesParams,
MintlifyGetSearchesResponse,
MintlifySearchQueryRow,
} from '@/tools/mintlify/types'
import {
appendParam,
MINTLIFY_API_BASE,
mintlifyHeaders,
pathSegment,
readMintlifyJson,
toNullableNumber,
toNullableString,
} from '@/tools/mintlify/utils'
import type { ToolConfig } from '@/tools/types'
function toSearchRows(value: unknown): MintlifySearchQueryRow[] {
if (!Array.isArray(value)) return []
return value.map((item) => {
const row = (item ?? {}) as Record<string, unknown>
return {
searchQuery: toNullableString(row.searchQuery),
hits: toNullableNumber(row.hits),
ctr: toNullableNumber(row.ctr),
topClickedPage: toNullableString(row.topClickedPage),
lastSearchedAt: toNullableString(row.lastSearchedAt),
}
})
}
export const mintlifyGetSearchesTool: ToolConfig<
MintlifyGetSearchesParams,
MintlifyGetSearchesResponse
> = {
id: 'mintlify_get_searches',
name: 'Mintlify Get Search Queries',
description:
'Export Mintlify documentation search terms for a date range, ordered by hit count, with click-through rate and the most-clicked result path.',
version: '1.0.0',
params: {
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Mintlify project ID, copied from the API keys page in your dashboard',
},
dateFrom: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Inclusive start date in ISO 8601 or YYYY-MM-DD format',
},
dateTo: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Exclusive end date in ISO 8601 or YYYY-MM-DD format',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Max search terms per page, between 1 and 100 (default 50)',
},
cursor: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Opaque pagination cursor returned as nextCursor by a previous call',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Mintlify admin API key (starts with mint_)',
},
},
request: {
url: (params) => {
const url = new URL(
`${MINTLIFY_API_BASE}/v1/analytics/${pathSegment(params.projectId)}/searches`
)
appendParam(url, 'dateFrom', params.dateFrom)
appendParam(url, 'dateTo', params.dateTo)
appendParam(url, 'limit', params.limit)
appendParam(url, 'cursor', params.cursor)
return url.toString()
},
method: 'GET',
headers: (params) => mintlifyHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await readMintlifyJson(response, 'Failed to get Mintlify search queries')
return {
success: true,
output: {
searches: toSearchRows(data.searches),
totalSearches: toNullableNumber(data.totalSearches),
nextCursor: toNullableString(data.nextCursor),
},
}
},
outputs: {
searches: {
type: 'array',
description: 'Search terms ordered by hit count descending',
items: {
type: 'object',
properties: {
searchQuery: {
type: 'string',
description: 'The search term entered by users',
nullable: true,
},
hits: {
type: 'number',
description: 'Number of times this term was searched',
nullable: true,
},
ctr: {
type: 'number',
description: 'Click-through rate for this search term',
nullable: true,
},
topClickedPage: {
type: 'string',
description: 'Most-clicked result path for this query',
nullable: true,
},
lastSearchedAt: {
type: 'string',
description: 'Timestamp of the last time this term was searched',
nullable: true,
},
},
},
},
totalSearches: {
type: 'number',
description:
'Total search events in the date range, summing all hits rather than distinct queries',
nullable: true,
},
nextCursor: {
type: 'string',
description: 'Cursor for the next page, or null when there are no more results',
nullable: true,
},
},
}
@@ -0,0 +1,173 @@
import type {
MintlifyGetUpdateStatusParams,
MintlifyGetUpdateStatusResponse,
MintlifyUpdateAuthor,
MintlifyUpdateCommit,
} from '@/tools/mintlify/types'
import {
MINTLIFY_API_BASE,
mintlifyHeaders,
pathSegment,
readMintlifyJson,
toNullableNumber,
toNullableString,
} from '@/tools/mintlify/utils'
import type { ToolConfig } from '@/tools/types'
function toStringList(value: unknown): string[] {
return Array.isArray(value)
? value.filter((item): item is string => typeof item === 'string')
: []
}
function toAuthor(value: unknown): MintlifyUpdateAuthor | null {
if (!value || typeof value !== 'object') return null
const author = value as Record<string, unknown>
return {
name: toNullableString(author.name),
avatarUrl: toNullableString(author.avatarUrl),
githubUserId: toNullableNumber(author.githubUserId),
}
}
function toCommit(value: unknown): MintlifyUpdateCommit | null {
if (!value || typeof value !== 'object') return null
const commit = value as Record<string, unknown>
const filesChanged = commit.filesChanged as Record<string, unknown> | undefined
return {
sha: toNullableString(commit.sha),
ref: toNullableString(commit.ref),
message: toNullableString(commit.message),
filesChanged: filesChanged
? {
added: toStringList(filesChanged.added),
modified: toStringList(filesChanged.modified),
removed: toStringList(filesChanged.removed),
}
: null,
}
}
export const mintlifyGetUpdateStatusTool: ToolConfig<
MintlifyGetUpdateStatusParams,
MintlifyGetUpdateStatusResponse
> = {
id: 'mintlify_get_update_status',
name: 'Mintlify Get Update Status',
description:
'Get the status of a Mintlify deployment update from its status ID, including logs, commit details, and screenshots.',
version: '1.0.0',
params: {
statusId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Status ID returned by Trigger Update or Trigger Preview Deployment',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Mintlify admin API key (starts with mint_)',
},
},
request: {
url: (params) =>
`${MINTLIFY_API_BASE}/v1/project/update-status/${pathSegment(params.statusId)}`,
method: 'GET',
headers: (params) => mintlifyHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await readMintlifyJson(response, 'Failed to get Mintlify update status')
return {
success: true,
output: {
id: toNullableString(data._id),
projectId: toNullableString(data.projectId),
createdAt: toNullableString(data.createdAt),
endedAt: toNullableString(data.endedAt),
status: toNullableString(data.status),
summary: toNullableString(data.summary),
logs: toStringList(data.logs),
subdomain: toNullableString(data.subdomain),
screenshot: toNullableString(data.screenshot),
screenshotLight: toNullableString(data.screenshotLight),
screenshotDark: toNullableString(data.screenshotDark),
author: toAuthor(data.author),
commit: toCommit(data.commit),
source: toNullableString(data.source),
},
}
},
outputs: {
id: { type: 'string', description: 'Status ID of the update', nullable: true },
projectId: { type: 'string', description: 'Documentation project ID', nullable: true },
createdAt: { type: 'string', description: 'ISO 8601 UTC start time', nullable: true },
endedAt: { type: 'string', description: 'ISO 8601 UTC end time', nullable: true },
status: {
type: 'string',
description: 'Update status: queued, in_progress, success, or failure',
nullable: true,
},
summary: { type: 'string', description: 'Summary of the update status', nullable: true },
logs: { type: 'array', description: 'Deployment log lines' },
subdomain: {
type: 'string',
description: 'Subdomain of the docs being updated',
nullable: true,
},
screenshot: { type: 'string', description: 'Screenshot of the docs', nullable: true },
screenshotLight: {
type: 'string',
description: 'Light-mode screenshot of the docs',
nullable: true,
},
screenshotDark: {
type: 'string',
description: 'Dark-mode screenshot of the docs',
nullable: true,
},
author: {
type: 'object',
description: 'Author of the update',
nullable: true,
properties: {
name: { type: 'string', description: 'Author name', nullable: true },
avatarUrl: { type: 'string', description: 'Author avatar image URL', nullable: true },
githubUserId: { type: 'number', description: 'Author GitHub user ID', nullable: true },
},
},
commit: {
type: 'object',
description: 'Commit that produced the update',
nullable: true,
properties: {
sha: { type: 'string', description: 'Commit SHA', nullable: true },
ref: { type: 'string', description: 'Git ref of the commit', nullable: true },
message: { type: 'string', description: 'Commit message', nullable: true },
filesChanged: {
type: 'object',
description: 'Files added, modified, and removed by the commit',
nullable: true,
properties: {
added: { type: 'array', description: 'New files added' },
modified: { type: 'array', description: 'Existing files that were modified' },
removed: { type: 'array', description: 'Files that were removed' },
},
},
},
},
source: {
type: 'string',
description:
'Source of the update trigger: internal, github-app-installation, api, github, dashboard, gitlab, or onboarding',
nullable: true,
},
},
}
+116
View File
@@ -0,0 +1,116 @@
import type { MintlifyGetViewsParams, MintlifyGetViewsResponse } from '@/tools/mintlify/types'
import {
appendParam,
MINTLIFY_API_BASE,
mintlifyHeaders,
pathSegment,
readMintlifyJson,
TRAFFIC_TOTALS_OUTPUT,
toTrafficRows,
toTrafficTotals,
} from '@/tools/mintlify/utils'
import type { ToolConfig } from '@/tools/types'
export const mintlifyGetViewsTool: ToolConfig<MintlifyGetViewsParams, MintlifyGetViewsResponse> = {
id: 'mintlify_get_views',
name: 'Mintlify Get Page Views',
description:
'Export Mintlify per-path and site-wide content view counts for a date range, split by human and AI bot traffic.',
version: '1.0.0',
params: {
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Mintlify project ID, copied from the API keys page in your dashboard',
},
dateFrom: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Inclusive start date in ISO 8601 or YYYY-MM-DD format',
},
dateTo: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Exclusive end date in ISO 8601 or YYYY-MM-DD format',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Max results per page, between 1 and 250 (default 50)',
},
offset: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Number of rows to skip for offset-based pagination (default 0)',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Mintlify admin API key (starts with mint_)',
},
},
request: {
url: (params) => {
const url = new URL(
`${MINTLIFY_API_BASE}/v1/analytics/${pathSegment(params.projectId)}/views`
)
appendParam(url, 'dateFrom', params.dateFrom)
appendParam(url, 'dateTo', params.dateTo)
appendParam(url, 'limit', params.limit)
appendParam(url, 'offset', params.offset)
return url.toString()
},
method: 'GET',
headers: (params) => mintlifyHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await readMintlifyJson(response, 'Failed to get Mintlify page views')
return {
success: true,
output: {
totals: toTrafficTotals(data.totals),
views: toTrafficRows(data.views),
hasMore: data.hasMore === true,
},
}
},
outputs: {
totals: {
...TRAFFIC_TOTALS_OUTPUT,
description: 'Site-wide content view event counts for the date range',
},
views: {
type: 'array',
description: 'Per-page content view event counts',
items: {
type: 'object',
properties: {
path: { type: 'string', description: 'The documentation page path', nullable: true },
human: {
type: 'number',
description: 'Content view events from human traffic',
nullable: true,
},
ai: {
type: 'number',
description: 'Content view events from AI bot traffic',
nullable: true,
},
total: { type: 'number', description: 'Total content view events', nullable: true },
},
},
},
hasMore: { type: 'boolean', description: 'Whether additional results are available' },
},
}
+116
View File
@@ -0,0 +1,116 @@
import type { MintlifyGetVisitorsParams, MintlifyGetVisitorsResponse } from '@/tools/mintlify/types'
import {
appendParam,
MINTLIFY_API_BASE,
mintlifyHeaders,
pathSegment,
readMintlifyJson,
TRAFFIC_TOTALS_OUTPUT,
toTrafficRows,
toTrafficTotals,
} from '@/tools/mintlify/utils'
import type { ToolConfig } from '@/tools/types'
export const mintlifyGetVisitorsTool: ToolConfig<
MintlifyGetVisitorsParams,
MintlifyGetVisitorsResponse
> = {
id: 'mintlify_get_visitors',
name: 'Mintlify Get Unique Visitors',
description:
'Export Mintlify per-path and site-wide approximate distinct visitor counts for a date range, split by human and AI bot traffic.',
version: '1.0.0',
params: {
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Mintlify project ID, copied from the API keys page in your dashboard',
},
dateFrom: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Inclusive start date in ISO 8601 or YYYY-MM-DD format',
},
dateTo: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Exclusive end date in ISO 8601 or YYYY-MM-DD format',
},
limit: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Max results per page, between 1 and 250 (default 50)',
},
offset: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Number of rows to skip for offset-based pagination (default 0)',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Mintlify admin API key (starts with mint_)',
},
},
request: {
url: (params) => {
const url = new URL(
`${MINTLIFY_API_BASE}/v1/analytics/${pathSegment(params.projectId)}/visitors`
)
appendParam(url, 'dateFrom', params.dateFrom)
appendParam(url, 'dateTo', params.dateTo)
appendParam(url, 'limit', params.limit)
appendParam(url, 'offset', params.offset)
return url.toString()
},
method: 'GET',
headers: (params) => mintlifyHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await readMintlifyJson(response, 'Failed to get Mintlify unique visitors')
return {
success: true,
output: {
totals: toTrafficTotals(data.totals),
visitors: toTrafficRows(data.visitors),
hasMore: data.hasMore === true,
},
}
},
outputs: {
totals: {
...TRAFFIC_TOTALS_OUTPUT,
description:
'Site-wide unique visitor totals for the date range, deduplicated across human and AI',
},
visitors: {
type: 'array',
description: 'Per-page unique visitor counts',
items: {
type: 'object',
properties: {
path: { type: 'string', description: 'The documentation page path', nullable: true },
human: { type: 'number', description: 'Unique human visitors', nullable: true },
ai: { type: 'number', description: 'Unique AI bot visitors', nullable: true },
total: {
type: 'number',
description: 'Approximate distinct visitors, deduplicated across human and AI',
nullable: true,
},
},
},
},
hasMore: { type: 'boolean', description: 'Whether additional results are available' },
},
}
+18
View File
@@ -0,0 +1,18 @@
export { mintlifyCreateAgentJobTool } from '@/tools/mintlify/create_agent_job'
export { mintlifyCreateAssistantMessageTool } from '@/tools/mintlify/create_assistant_message'
export { mintlifyDetectAiProseTool } from '@/tools/mintlify/detect_ai_prose'
export { mintlifyGetAgentJobTool } from '@/tools/mintlify/get_agent_job'
export { mintlifyGetAssistantCallerStatsTool } from '@/tools/mintlify/get_assistant_caller_stats'
export { mintlifyGetAssistantConversationsTool } from '@/tools/mintlify/get_assistant_conversations'
export { mintlifyGetFeedbackTool } from '@/tools/mintlify/get_feedback'
export { mintlifyGetFeedbackByPageTool } from '@/tools/mintlify/get_feedback_by_page'
export { mintlifyGetPageContentTool } from '@/tools/mintlify/get_page_content'
export { mintlifyGetSearchesTool } from '@/tools/mintlify/get_searches'
export { mintlifyGetUpdateStatusTool } from '@/tools/mintlify/get_update_status'
export { mintlifyGetViewsTool } from '@/tools/mintlify/get_views'
export { mintlifyGetVisitorsTool } from '@/tools/mintlify/get_visitors'
export { mintlifySearchTool } from '@/tools/mintlify/search'
export { mintlifySendAgentMessageTool } from '@/tools/mintlify/send_agent_message'
export { mintlifyTriggerAutomationTool } from '@/tools/mintlify/trigger_automation'
export { mintlifyTriggerPreviewTool } from '@/tools/mintlify/trigger_preview'
export { mintlifyTriggerUpdateTool } from '@/tools/mintlify/trigger_update'
+156
View File
@@ -0,0 +1,156 @@
import type {
MintlifySearchParams,
MintlifySearchResponse,
MintlifySearchResult,
} from '@/tools/mintlify/types'
import {
MINTLIFY_API_BASE,
mintlifyHeaders,
pathSegment,
readMintlifyJson,
toNullableString,
toStringArray,
} from '@/tools/mintlify/utils'
import type { ToolConfig } from '@/tools/types'
export const mintlifySearchTool: ToolConfig<MintlifySearchParams, MintlifySearchResponse> = {
id: 'mintlify_search',
name: 'Mintlify Search Documentation',
description:
'Run a semantic and keyword search across a Mintlify documentation site, with optional version, language, tag, and group filters.',
version: '1.0.0',
params: {
domain: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description:
'Domain identifier from your domain.mintlify.site URL, found at the end of your dashboard URL',
},
query: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Search query to execute against your documentation content',
},
pageSize: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Number of search results to return, between 1 and 50 (default 10)',
},
scoreThreshold: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Minimum relevance score for results, between 0 and 1',
},
version: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter results by documentation version',
},
language: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter results by content language',
},
tag: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter results by tag',
},
groups: {
type: 'json',
required: false,
visibility: 'user-or-llm',
description:
'Documentation groups the caller is authorized to access, as a JSON array of strings. Only applies to deployments using auth or userAuth.',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Mintlify assistant API key (starts with mint_dsc_)',
},
},
request: {
url: (params) => `${MINTLIFY_API_BASE}/discovery/v1/search/${pathSegment(params.domain)}`,
method: 'POST',
headers: (params) => mintlifyHeaders(params.apiKey),
body: (params) => {
const body: Record<string, unknown> = { query: params.query }
if (params.pageSize !== undefined) body.pageSize = params.pageSize
if (params.scoreThreshold !== undefined) body.scoreThreshold = params.scoreThreshold
const groups = toStringArray(params.groups)
const filter: Record<string, unknown> = {}
if (params.version) filter.version = params.version
if (params.language) filter.language = params.language
if (params.tag) filter.tag = params.tag
if (groups) filter.groups = groups
if (Object.keys(filter).length > 0) body.filter = filter
return body
},
},
transformResponse: async (response: Response) => {
const data = await readMintlifyJson(response, 'Failed to search Mintlify documentation')
const rows = Array.isArray(data) ? data : []
const results: MintlifySearchResult[] = rows.map((entry) => {
const row = (entry ?? {}) as Record<string, unknown>
return {
content: toNullableString(row.content),
path: toNullableString(row.path),
metadata:
row.metadata && typeof row.metadata === 'object'
? (row.metadata as Record<string, unknown>)
: null,
}
})
return {
success: true,
output: {
results,
resultCount: results.length,
},
}
},
outputs: {
results: {
type: 'array',
description: 'Matching documentation chunks ordered by relevance',
items: {
type: 'object',
properties: {
content: {
type: 'string',
description: 'The matching content from your documentation',
nullable: true,
},
path: {
type: 'string',
description: 'Path or URL to the source document',
nullable: true,
},
metadata: {
type: 'json',
description: 'Additional metadata about the search result',
nullable: true,
},
},
},
},
resultCount: { type: 'number', description: 'Number of results returned' },
},
}
@@ -0,0 +1,70 @@
import type {
MintlifyAgentJobResponse,
MintlifySendAgentMessageParams,
} from '@/tools/mintlify/types'
import {
AGENT_JOB_OUTPUTS,
MINTLIFY_API_BASE,
mintlifyHeaders,
pathSegment,
readMintlifyJson,
toAgentJobOutput,
} from '@/tools/mintlify/utils'
import type { ToolConfig } from '@/tools/types'
export const mintlifySendAgentMessageTool: ToolConfig<
MintlifySendAgentMessageParams,
MintlifyAgentJobResponse
> = {
id: 'mintlify_send_agent_message',
name: 'Mintlify Send Agent Message',
description:
'Send a follow-up instruction to an existing Mintlify agent job. The message is processed asynchronously.',
version: '1.0.0',
params: {
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Mintlify project ID, copied from the API keys page in your dashboard',
},
jobId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Unique identifier of the agent job to send a message to',
},
prompt: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The follow-up instruction for the agent',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Mintlify admin API key (starts with mint_)',
},
},
request: {
url: (params) =>
`${MINTLIFY_API_BASE}/v2/agent/${pathSegment(params.projectId)}/job/${pathSegment(params.jobId)}/message`,
method: 'POST',
headers: (params) => mintlifyHeaders(params.apiKey),
body: (params) => ({ prompt: params.prompt }),
},
transformResponse: async (response: Response) => {
const data = await readMintlifyJson(response, 'Failed to send Mintlify agent message')
return {
success: true,
output: toAgentJobOutput(data),
}
},
outputs: AGENT_JOB_OUTPUTS,
}
@@ -0,0 +1,79 @@
import type {
MintlifyTriggerAutomationParams,
MintlifyTriggerAutomationResponse,
} from '@/tools/mintlify/types'
import {
MINTLIFY_API_BASE,
mintlifyHeaders,
pathSegment,
readMintlifyJson,
toNullableString,
} from '@/tools/mintlify/utils'
import type { ToolConfig } from '@/tools/types'
export const mintlifyTriggerAutomationTool: ToolConfig<
MintlifyTriggerAutomationParams,
MintlifyTriggerAutomationResponse
> = {
id: 'mintlify_trigger_automation',
name: 'Mintlify Trigger Automation',
description:
'Run a scheduled Mintlify automation immediately instead of waiting for its next scheduled time. Only automations with a custom schedule can be triggered.',
version: '1.0.0',
params: {
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Mintlify project ID, copied from the API keys page in your dashboard',
},
automationId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description:
"Automation ID, copied from the automation's settings panel on the Automations page",
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Mintlify admin API key (starts with mint_)',
},
},
request: {
url: (params) =>
`${MINTLIFY_API_BASE}/v1/workflow/${pathSegment(params.projectId)}/${pathSegment(params.automationId)}/trigger`,
method: 'POST',
headers: (params) => mintlifyHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await readMintlifyJson(response, 'Failed to trigger Mintlify automation')
return {
success: true,
output: {
schemaId: toNullableString(data.schemaId),
instanceId: toNullableString(data.instanceId),
jobId: toNullableString(data.jobId),
},
}
},
outputs: {
schemaId: { type: 'string', description: 'ID of the triggered automation', nullable: true },
instanceId: {
type: 'string',
description: 'ID of the queued automation run, visible in the run history',
nullable: true,
},
jobId: {
type: 'string',
description: 'ID of the background job processing the run',
nullable: true,
},
},
}
@@ -0,0 +1,76 @@
import type {
MintlifyTriggerPreviewParams,
MintlifyTriggerPreviewResponse,
} from '@/tools/mintlify/types'
import {
MINTLIFY_API_BASE,
mintlifyHeaders,
pathSegment,
readMintlifyJson,
toNullableString,
} from '@/tools/mintlify/utils'
import type { ToolConfig } from '@/tools/types'
export const mintlifyTriggerPreviewTool: ToolConfig<
MintlifyTriggerPreviewParams,
MintlifyTriggerPreviewResponse
> = {
id: 'mintlify_trigger_preview',
name: 'Mintlify Trigger Preview Deployment',
description:
'Create or update a Mintlify preview deployment for a Git branch. Redeploys when a preview already exists for the branch.',
version: '1.0.0',
params: {
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Mintlify project ID, copied from the API keys page in your dashboard',
},
branch: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Name of the Git branch to create a preview deployment for',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Mintlify admin API key (starts with mint_)',
},
},
request: {
url: (params) => `${MINTLIFY_API_BASE}/v1/project/preview/${pathSegment(params.projectId)}`,
method: 'POST',
headers: (params) => mintlifyHeaders(params.apiKey),
body: (params) => ({ branch: params.branch }),
},
transformResponse: async (response: Response) => {
const data = await readMintlifyJson(response, 'Failed to trigger Mintlify preview deployment')
return {
success: true,
output: {
statusId: toNullableString(data.statusId),
previewUrl: toNullableString(data.previewUrl),
},
}
},
outputs: {
statusId: {
type: 'string',
description: 'Status ID for tracking the preview deployment',
nullable: true,
},
previewUrl: {
type: 'string',
description: 'URL where the preview deployment is hosted',
nullable: true,
},
},
}
+63
View File
@@ -0,0 +1,63 @@
import type {
MintlifyTriggerUpdateParams,
MintlifyTriggerUpdateResponse,
} from '@/tools/mintlify/types'
import {
MINTLIFY_API_BASE,
mintlifyHeaders,
pathSegment,
readMintlifyJson,
toNullableString,
} from '@/tools/mintlify/utils'
import type { ToolConfig } from '@/tools/types'
export const mintlifyTriggerUpdateTool: ToolConfig<
MintlifyTriggerUpdateParams,
MintlifyTriggerUpdateResponse
> = {
id: 'mintlify_trigger_update',
name: 'Mintlify Trigger Update',
description:
'Queue a deployment update for a Mintlify documentation project from its configured deployment branch. Returns a status ID for tracking progress.',
version: '1.0.0',
params: {
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Mintlify project ID, copied from the API keys page in your dashboard',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Mintlify admin API key (starts with mint_)',
},
},
request: {
url: (params) => `${MINTLIFY_API_BASE}/v1/project/update/${pathSegment(params.projectId)}`,
method: 'POST',
headers: (params) => mintlifyHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await readMintlifyJson(response, 'Failed to trigger Mintlify update')
return {
success: true,
output: {
statusId: toNullableString(data.statusId),
},
}
},
outputs: {
statusId: {
type: 'string',
description: 'Status ID of the queued update. Poll it with Get Update Status.',
nullable: true,
},
},
}
+374
View File
@@ -0,0 +1,374 @@
import type { ToolResponse } from '@/tools/types'
/** Every Mintlify endpoint authenticates with a bearer API key. */
interface MintlifyBaseParams {
apiKey: string
}
/** Admin-key endpoints are scoped to a documentation project. */
interface MintlifyProjectParams extends MintlifyBaseParams {
projectId: string
}
/** Assistant-key endpoints are scoped to a deployment domain identifier. */
interface MintlifyDomainParams extends MintlifyBaseParams {
domain: string
}
/** Shared date-range and pagination filters used by the analytics export endpoints. */
interface MintlifyAnalyticsParams extends MintlifyProjectParams {
dateFrom?: string
dateTo?: string
}
export interface MintlifyTriggerUpdateParams extends MintlifyProjectParams {}
export interface MintlifyTriggerUpdateResponse extends ToolResponse {
output: {
statusId: string | null
}
}
export interface MintlifyGetUpdateStatusParams extends MintlifyBaseParams {
statusId: string
}
export interface MintlifyUpdateAuthor {
name: string | null
avatarUrl: string | null
githubUserId: number | null
}
export interface MintlifyUpdateCommit {
sha: string | null
ref: string | null
message: string | null
filesChanged: {
added: string[]
modified: string[]
removed: string[]
} | null
}
export interface MintlifyGetUpdateStatusResponse extends ToolResponse {
output: {
id: string | null
projectId: string | null
createdAt: string | null
endedAt: string | null
status: string | null
summary: string | null
logs: string[]
subdomain: string | null
screenshot: string | null
screenshotLight: string | null
screenshotDark: string | null
author: MintlifyUpdateAuthor | null
commit: MintlifyUpdateCommit | null
source: string | null
}
}
export interface MintlifyTriggerPreviewParams extends MintlifyProjectParams {
branch: string
}
export interface MintlifyTriggerPreviewResponse extends ToolResponse {
output: {
statusId: string | null
previewUrl: string | null
}
}
export interface MintlifyTriggerAutomationParams extends MintlifyProjectParams {
automationId: string
}
export interface MintlifyTriggerAutomationResponse extends ToolResponse {
output: {
schemaId: string | null
instanceId: string | null
jobId: string | null
}
}
export interface MintlifyDetectAiProseParams extends MintlifyProjectParams {
path: string
content: string
}
export interface MintlifyDeslopRewrite {
text: string
rationale: string
}
export interface MintlifyDeslopWindow {
text: string
label: string
aiAssistanceScore: number | null
confidence: string | number | null
startLine: number | null
endLine: number | null
rewrites: MintlifyDeslopRewrite[]
}
export interface MintlifyDetectAiProseResponse extends ToolResponse {
output: {
path: string | null
skipped: string | null
predictionShort: string | null
fractionAi: number | null
fractionAiAssisted: number | null
fractionHuman: number | null
windows: MintlifyDeslopWindow[]
creditsCharged: number | null
}
}
/** Shape returned by all three agent-job endpoints. */
export interface MintlifyAgentJobOutput {
id: string | null
status: string | null
source: {
repository: string | null
ref: string | null
} | null
model: string | null
prLink: string | null
createdAt: string | null
archivedAt: string | null
}
export interface MintlifyAgentJobResponse extends ToolResponse {
output: MintlifyAgentJobOutput
}
export interface MintlifyCreateAgentJobParams extends MintlifyProjectParams {
prompt: string
}
export interface MintlifyGetAgentJobParams extends MintlifyProjectParams {
jobId: string
}
export interface MintlifySendAgentMessageParams extends MintlifyProjectParams {
jobId: string
prompt: string
}
export interface MintlifySearchParams extends MintlifyDomainParams {
query: string
pageSize?: number
scoreThreshold?: number
version?: string
language?: string
tag?: string
groups?: string[] | string
}
export interface MintlifySearchResult {
content: string | null
path: string | null
metadata: Record<string, unknown> | null
}
export interface MintlifySearchResponse extends ToolResponse {
output: {
results: MintlifySearchResult[]
resultCount: number
}
}
export interface MintlifyGetPageContentParams extends MintlifyDomainParams {
path: string
groups?: string[] | string
}
export interface MintlifyGetPageContentResponse extends ToolResponse {
output: {
path: string | null
content: string | null
}
}
export interface MintlifyAssistantContextItem {
type: string
value: string
path?: string
elementId?: string
}
export interface MintlifyCreateAssistantMessageParams extends MintlifyDomainParams {
message?: string
messages?: unknown[] | string
fp?: string
threadId?: string
retrievalPageSize?: number
currentPath?: string
version?: string
language?: string
groups?: string[] | string
assistantContext?: MintlifyAssistantContextItem[] | string
}
export interface MintlifyAssistantSource {
sourceId: string | null
url: string | null
title: string | null
}
export interface MintlifyCreateAssistantMessageResponse extends ToolResponse {
output: {
text: string
threadId: string | null
sources: MintlifyAssistantSource[]
}
}
export interface MintlifyGetFeedbackParams extends MintlifyAnalyticsParams {
source?: string
status?: string
limit?: number
cursor?: string
}
export interface MintlifyFeedbackEntry {
id: string | null
path: string | null
comment: string | null
createdAt: string | null
source: string | null
status: string | null
helpful: boolean | null
contact: string | null
code: string | null
filename: string | null
lang: string | null
}
export interface MintlifyGetFeedbackResponse extends ToolResponse {
output: {
feedback: MintlifyFeedbackEntry[]
nextCursor: string | null
hasMore: boolean
}
}
export interface MintlifyGetFeedbackByPageParams extends MintlifyAnalyticsParams {
limit?: number
source?: string
status?: string
}
export interface MintlifyFeedbackPageEntry {
path: string | null
thumbsUp: number | null
thumbsDown: number | null
code: number | null
total: number | null
}
export interface MintlifyGetFeedbackByPageResponse extends ToolResponse {
output: {
feedback: MintlifyFeedbackPageEntry[]
hasMore: boolean
}
}
export interface MintlifyGetAssistantConversationsParams extends MintlifyAnalyticsParams {
limit?: number
cursor?: string
}
export interface MintlifyConversationSource {
title: string | null
url: string | null
}
export interface MintlifyConversation {
id: string | null
timestamp: string | null
query: string | null
response: string | null
sources: MintlifyConversationSource[]
resolutionStatus: string | null
queryCategory: string | null
pageUrl: string | null
}
export interface MintlifyGetAssistantConversationsResponse extends ToolResponse {
output: {
conversations: MintlifyConversation[]
nextCursor: string | null
hasMore: boolean
}
}
export interface MintlifyGetAssistantCallerStatsParams extends MintlifyAnalyticsParams {}
export interface MintlifyGetAssistantCallerStatsResponse extends ToolResponse {
output: {
web: number | null
api: number | null
other: number | null
total: number | null
}
}
export interface MintlifyGetSearchesParams extends MintlifyAnalyticsParams {
limit?: number
cursor?: string
}
export interface MintlifySearchQueryRow {
searchQuery: string | null
hits: number | null
ctr: number | null
topClickedPage: string | null
lastSearchedAt: string | null
}
export interface MintlifyGetSearchesResponse extends ToolResponse {
output: {
searches: MintlifySearchQueryRow[]
totalSearches: number | null
nextCursor: string | null
}
}
/** Human / AI / total split shared by the views and visitors endpoints. */
export interface MintlifyTrafficTotals {
human: number | null
ai: number | null
total: number | null
}
export interface MintlifyTrafficRow extends MintlifyTrafficTotals {
path: string | null
}
export interface MintlifyGetViewsParams extends MintlifyAnalyticsParams {
limit?: number
offset?: number
}
export interface MintlifyGetViewsResponse extends ToolResponse {
output: {
totals: MintlifyTrafficTotals | null
views: MintlifyTrafficRow[]
hasMore: boolean
}
}
export interface MintlifyGetVisitorsParams extends MintlifyAnalyticsParams {
limit?: number
offset?: number
}
export interface MintlifyGetVisitorsResponse extends ToolResponse {
output: {
totals: MintlifyTrafficTotals | null
visitors: MintlifyTrafficRow[]
hasMore: boolean
}
}
+207
View File
@@ -0,0 +1,207 @@
import type {
MintlifyAgentJobOutput,
MintlifyTrafficRow,
MintlifyTrafficTotals,
} from '@/tools/mintlify/types'
import type { ToolOutputProperty } from '@/tools/types'
/** Single origin for the platform REST, admin, analytics, and discovery APIs. */
export const MINTLIFY_API_BASE = 'https://api.mintlify.com'
/**
* Encodes an identifier for use in a URL path, trimming the whitespace a
* copy-pasted project ID, domain, or job ID commonly carries.
*/
export function pathSegment(value: string): string {
return encodeURIComponent(value.trim())
}
/**
* Builds the bearer auth headers every Mintlify endpoint expects. Admin
* (`mint_`) and assistant (`mint_dsc_`) keys use the same header shape.
*/
export function mintlifyHeaders(apiKey: string): Record<string, string> {
return {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${apiKey}`,
}
}
/**
* Reads a Mintlify JSON body, throwing a descriptive error for non-2xx
* responses. Tolerates an empty body (204) and the `text/plain` body the
* rate-limit responses return.
*/
export async function readMintlifyJson(
response: Response,
fallbackMessage: string
): Promise<Record<string, unknown>> {
const text = await response.text()
if (!response.ok) {
let message = text.trim()
try {
const parsed = JSON.parse(text)
message = parsed?.error || parsed?.message || message
} catch {
// Non-JSON error bodies (for example the plain-text 429) are used verbatim.
}
throw new Error(message || `${fallbackMessage} (HTTP ${response.status})`)
}
if (!text.trim()) return {}
return JSON.parse(text)
}
/**
* Normalizes a `json`-typed tool param that may arrive as a parsed array (from
* a block-to-block reference) or as a JSON string (from a long-input field or
* an LLM tool call). Also accepts a comma-separated list of plain strings.
*/
export function toStringArray(value: unknown): string[] | undefined {
if (value === undefined || value === null || value === '') return undefined
if (Array.isArray(value)) {
const items = value.map((item) => String(item)).filter((item) => item.length > 0)
return items.length > 0 ? items : undefined
}
if (typeof value !== 'string') return undefined
const trimmed = value.trim()
if (!trimmed) return undefined
if (trimmed.startsWith('[')) {
const parsed = JSON.parse(trimmed)
if (!Array.isArray(parsed)) {
throw new Error('Expected a JSON array of strings')
}
return toStringArray(parsed)
}
const items = trimmed
.split(',')
.map((item) => item.trim())
.filter((item) => item.length > 0)
return items.length > 0 ? items : undefined
}
/**
* Normalizes a `json`-typed tool param holding an array of objects, parsing it
* first when the executor delivered it as a JSON string.
*/
export function toObjectArray(value: unknown): Record<string, unknown>[] | undefined {
if (value === undefined || value === null || value === '') return undefined
const parsed = typeof value === 'string' ? JSON.parse(value) : value
if (!Array.isArray(parsed)) {
throw new Error('Expected a JSON array')
}
return parsed.length > 0 ? (parsed as Record<string, unknown>[]) : undefined
}
/** Appends a query parameter only when the value is present and non-empty. */
export function appendParam(url: URL, key: string, value: string | number | undefined): void {
if (value === undefined || value === null || value === '') return
url.searchParams.set(key, String(value))
}
/** Normalizes a nullable number field from a Mintlify response. */
export function toNullableNumber(value: unknown): number | null {
return typeof value === 'number' && Number.isFinite(value) ? value : null
}
/** Normalizes a nullable string field from a Mintlify response. */
export function toNullableString(value: unknown): string | null {
return typeof value === 'string' ? value : null
}
/**
* Maps the `AgentJob` payload returned identically by create-job, get-job, and
* send-message.
*/
export function toAgentJobOutput(data: Record<string, unknown>): MintlifyAgentJobOutput {
const source = data.source as Record<string, unknown> | undefined
return {
id: toNullableString(data.id),
status: toNullableString(data.status),
source: source
? {
repository: toNullableString(source.repository),
ref: toNullableString(source.ref),
}
: null,
model: toNullableString(data.model),
prLink: toNullableString(data.prLink),
createdAt: toNullableString(data.createdAt),
archivedAt: toNullableString(data.archivedAt),
}
}
/** Maps the site-wide human/AI totals shared by the views and visitors endpoints. */
export function toTrafficTotals(value: unknown): MintlifyTrafficTotals | null {
if (!value || typeof value !== 'object') return null
const totals = value as Record<string, unknown>
return {
human: toNullableNumber(totals.human),
ai: toNullableNumber(totals.ai),
total: toNullableNumber(totals.total),
}
}
/** Maps the per-path human/AI rows shared by the views and visitors endpoints. */
export function toTrafficRows(value: unknown): MintlifyTrafficRow[] {
if (!Array.isArray(value)) return []
return value.map((item) => {
const row = (item ?? {}) as Record<string, unknown>
return {
path: toNullableString(row.path),
human: toNullableNumber(row.human),
ai: toNullableNumber(row.ai),
total: toNullableNumber(row.total),
}
})
}
/** Output schema for the site-wide totals object. */
export const TRAFFIC_TOTALS_OUTPUT: ToolOutputProperty = {
type: 'object',
description: 'Site-wide totals for the date range',
nullable: true,
properties: {
human: { type: 'number', description: 'Site-wide human traffic', nullable: true },
ai: { type: 'number', description: 'Site-wide AI bot traffic', nullable: true },
total: { type: 'number', description: 'Site-wide total', nullable: true },
},
}
/** Output schema shared by the three agent-job tools. */
export const AGENT_JOB_OUTPUTS: Record<string, ToolOutputProperty> = {
id: { type: 'string', description: 'Unique identifier for the agent job', nullable: true },
status: {
type: 'string',
description: 'Current job status: active, completed, archived, or failed',
nullable: true,
},
source: {
type: 'object',
description: 'Source repository information',
nullable: true,
properties: {
repository: { type: 'string', description: 'Full GitHub repository URL', nullable: true },
ref: { type: 'string', description: 'Git branch the agent is working on', nullable: true },
},
},
model: { type: 'string', description: 'AI model used for this job', nullable: true },
prLink: {
type: 'string',
description:
'GitHub pull request URL created by the agent. Null while the job is active or if no files changed.',
nullable: true,
},
createdAt: { type: 'string', description: 'Timestamp when the job was created', nullable: true },
archivedAt: {
type: 'string',
description: 'Timestamp when the job was archived',
nullable: true,
},
}
+38
View File
@@ -2639,6 +2639,26 @@ import {
millionverifierGetCreditsTool,
millionverifierVerifyEmailTool,
} from '@/tools/millionverifier'
import {
mintlifyCreateAgentJobTool,
mintlifyCreateAssistantMessageTool,
mintlifyDetectAiProseTool,
mintlifyGetAgentJobTool,
mintlifyGetAssistantCallerStatsTool,
mintlifyGetAssistantConversationsTool,
mintlifyGetFeedbackByPageTool,
mintlifyGetFeedbackTool,
mintlifyGetPageContentTool,
mintlifyGetSearchesTool,
mintlifyGetUpdateStatusTool,
mintlifyGetViewsTool,
mintlifyGetVisitorsTool,
mintlifySearchTool,
mintlifySendAgentMessageTool,
mintlifyTriggerAutomationTool,
mintlifyTriggerPreviewTool,
mintlifyTriggerUpdateTool,
} from '@/tools/mintlify'
import { mistralParserTool, mistralParserV2Tool, mistralParserV3Tool } from '@/tools/mistral'
import {
mondayArchiveItemTool,
@@ -9374,4 +9394,22 @@ export const tools: Record<string, ToolConfig> = {
uptimerobot_update_psp: uptimeRobotUpdatePspTool,
uptimerobot_delete_psp: uptimeRobotDeletePspTool,
uptimerobot_get_account: uptimeRobotGetAccountTool,
mintlify_trigger_update: mintlifyTriggerUpdateTool,
mintlify_get_update_status: mintlifyGetUpdateStatusTool,
mintlify_trigger_preview: mintlifyTriggerPreviewTool,
mintlify_trigger_automation: mintlifyTriggerAutomationTool,
mintlify_detect_ai_prose: mintlifyDetectAiProseTool,
mintlify_create_agent_job: mintlifyCreateAgentJobTool,
mintlify_get_agent_job: mintlifyGetAgentJobTool,
mintlify_send_agent_message: mintlifySendAgentMessageTool,
mintlify_search: mintlifySearchTool,
mintlify_get_page_content: mintlifyGetPageContentTool,
mintlify_create_assistant_message: mintlifyCreateAssistantMessageTool,
mintlify_get_feedback: mintlifyGetFeedbackTool,
mintlify_get_feedback_by_page: mintlifyGetFeedbackByPageTool,
mintlify_get_assistant_conversations: mintlifyGetAssistantConversationsTool,
mintlify_get_assistant_caller_stats: mintlifyGetAssistantCallerStatsTool,
mintlify_get_searches: mintlifyGetSearchesTool,
mintlify_get_views: mintlifyGetViewsTool,
mintlify_get_visitors: mintlifyGetVisitorsTool,
}