DU

dust-mcp-server

Create and register new MCP servers in Dust to connect remote platforms, using a structured step-by-step development process.

Install

mkdir -p .claude/skills/dust-mcp-server && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/4233" && unzip -o skill.zip -d .claude/skills/dust-mcp-server && rm skill.zip

Installs to .claude/skills/dust-mcp-server

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Step-by-step guide for creating new internal MCP server integrations in Dust that connect to remote platforms (Jira, HubSpot, Salesforce, etc.). Use when adding a new MCP server, implementing a platform integration, or connecting Dust to a new external service.
261 chars✓ has a “when” triggerlonger than Claude Code's old 250-char listing cap (fine on current versions)
Advanced

Key capabilities

  • Create internal MCP server metadata
  • Implement tool handlers for remote platforms
  • Register servers in the Dust ecosystem
  • Configure OAuth providers for external services

How it works

The process involves creating metadata and handler files within the Dust repository structure, then registering the server in the central constants and index files.

Inputs & outputs

You give it
Platform API documentation and tool definitions
You get back
Registered internal MCP server integration

When to use dust-mcp-server

  • Add new platform integration
  • Register internal MCP server
  • Define tool metadata for external services

About this skill

MCP Server Runbook: Adding Internal MCP Server Integrations for Remote Platforms

This runbook provides step-by-step instructions for creating new internal MCP server integrations in Dust that connect to remote platforms (e.g., Jira, HubSpot, Salesforce, etc.).

MVP Fast Path

For a minimal new server (no OAuth, no external API yet — just the skeleton to register and test):

  1. Create front/lib/api/actions/servers/{provider}/metadata.ts with a literal metadata array
  2. Create front/lib/api/actions/servers/{provider}/tools/index.ts with stub handlers
  3. Create front/lib/api/actions/servers/{provider}/index.ts with createServer
  4. Register in constants.ts and servers/index.ts
  5. Add the server to SERVER_SOURCES in bm25_tool_search_utils.test.ts
  6. Add at least one BM25 query case to bm25_tool_search.test.ts

See the BM25 Tests section below for the test setup. This gives you a runnable skeleton with type-checked tool descriptions before writing any real API calls.

Quick Reference

File Structure

front/lib/api/actions/servers/{provider}/
├── metadata.ts           # Tool metadata array and server info
├── tools/index.ts        # Schema-inferred handlers and built tools
├── index.ts              # Provider-local server creation and registration
├── client.ts             # API client (optional)
└── helpers.ts            # Helper functions (optional)

Registration Files

  1. front/lib/actions/mcp_internal_actions/constants.ts - Add server config with metadata: YOUR_SERVER
  2. front/lib/actions/mcp_internal_actions/servers/index.ts - Import and register in switch statement

OAuth Requirements (if the platform requires OAuth)

  • OAuth provider must already exist in front/lib/api/oauth/providers/{provider}.ts
  • OAuth core implementation must exist in core/src/oauth/providers/{provider}.rs
  • OAuth scopes must be configured for the required API access
  • Server's authorization field must reference the OAuth provider

Common Gotchas

  • Do not forget to add the server to AVAILABLE_INTERNAL_MCP_SERVER_NAMES array
  • Server IDs must be stable and unique; never change them once deployed
  • Tool stakes must be configured appropriately (never_ask, low, medium, high)
  • Every internal tool must define displayLabels, toolCostCategory, and freeUsage
  • Tool descriptions should start with a bare infinitive/base verb like List, Get, Search, Create, or Update
  • Always implement proper error handling with Result types
  • Handle OAuth token refresh automatically through the withAuth pattern

Prerequisites

OAuth Configuration (if required)

If the remote platform requires OAuth authentication:

  1. Check whether an OAuth provider exists in core/src/oauth/providers/ as {provider}.rs
  2. Check whether a front OAuth provider exists in front/lib/api/oauth/providers/{provider}.ts

If the OAuth provider does not exist, implement it first in core and front:

  • create core/src/oauth/providers/{provider}.rs
  • implement the OAuth flow: authorization URL, token exchange, refresh
  • register the provider in core/src/oauth/providers/mod.rs
  • create front/lib/api/oauth/providers/{provider}.ts for the front-end OAuth setup

See existing providers like hubspot.rs or jira.rs for reference implementations.

Research Phase

Before starting implementation, research the platform API:

1. API Documentation

  • find the official API documentation
  • identify REST endpoints vs GraphQL vs SDK usage
  • note rate limits and pagination requirements

2. Authentication Method

  • OAuth 2.0, preferred for user-facing integrations
  • API key / bearer token, simpler but less secure
  • required OAuth scopes

3. Available Operations

Document the operations you want to expose:

  • read operations: list, get, search
  • write operations: create, update, delete
  • special operations: transitions, associations, etc.

Step-by-Step Implementation

1. Create metadata.ts

Create front/lib/api/actions/servers/{provider}/metadata.ts:

import type { ServerMetadata } from "@app/lib/actions/mcp_internal_actions/tool_definition";
import { z } from "zod";

export const YOUR_PROVIDER_SERVER_NAME = "your_provider" as const;

export const YOUR_PROVIDER_TOOLS_METADATA = [
  {
    name: "list_items",
    description: "List all items accessible to the user.",
    schema: {
      pageToken: z.string().optional().describe("Page token for pagination."),
      maxResults: z.number().optional().describe("Maximum results to return."),
    },
    stake: "never_ask",
    toolCostCategory: "advanced",
    freeUsage: false,
    displayLabels: {
      running: "Listing Items",
      done: "List items",
    },
  },
  {
    name: "get_item",
    description: "Get a single item by ID.",
    schema: {
      itemId: z.string().describe("The ID of the item to retrieve."),
    },
    stake: "never_ask",
    toolCostCategory: "advanced",
    freeUsage: false,
    displayLabels: {
      running: "Retrieving item",
      done: "Retrieve item",
    },
  },
  {
    name: "create_item",
    description: "Create a new item.",
    schema: {
      name: z.string().describe("Name of the item."),
      description: z.string().optional().describe("Description of the item."),
    },
    stake: "low",
    toolCostCategory: "advanced",
    freeUsage: false,
    displayLabels: {
      running: "Creating item",
      done: "Create item",
    },
  },
] as const;

export const YOUR_PROVIDER_SERVER = {
  serverInfo: {
    name: YOUR_PROVIDER_SERVER_NAME,
    version: "1.0.0",
    description: "Short description of what this integration does.",
    authorization: {
      provider: "your_provider",
      supported_use_cases: ["personal_actions", "platform_actions"],
    },
    icon: "YourProviderLogo",
    documentationUrl: "https://docs.dust.tt/docs/your-provider",
    instructions: null,
  },
  tools: YOUR_PROVIDER_TOOLS_METADATA,
} as const satisfies ServerMetadata;

Key points:

  • Use snake_case for the tool names
  • Internal tools must include displayLabels; unlike remote MCP tools, these labels are required
  • Set toolCostCategory and freeUsage deliberately, following a comparable existing server
  • tool descriptions start with a bare infinitive/base verb such as List, Get, Search, Create, Update, or Retrieve; avoid noun phrases, articles, gerunds, and third-person verbs because descriptions are part of the BM25 tool-search corpus (see BM25-Friendly Descriptions below)
  • stake values map to review/approval expectations

BM25-Friendly Descriptions (MCP3 rule)

Tool names and descriptions both drive BM25 retrieval. Names are the strongest signal — they must be consistent and follow the verb_noun convention (e.g., list_warehouses, get_workbook). Descriptions are the secondary signal: write each one as if answering "what user intent does this tool serve?"

Rules:

  1. Start with a bare infinitive verb: List, Get, Search, Create, Update, Send, Delete
  2. Include platform-specific nouns that users mention in queries: warehouse, workbook, ticket, channel
  3. Include common synonyms inline when the platform uses an unusual term: worksheets (sheets/tabs)
  4. Include the platform name when it adds specificity (e.g., Databricks workspace, Excel workbook), but don't lead with the full brand name or repeat it redundantly across every tool
  5. For platform-specific servers, avoid adding location qualifiers (e.g., in OneDrive, in SharePoint) to every tool — BM25 treats these as content tokens, so they widen the match surface and cause your tools to surface on location-based queries (e.g., a Drive search) even when the user intended a different tool

Examples:

// BAD — noun phrase, redundant "Microsoft Excel", location noise
description: "Microsoft Excel file listing from OneDrive and SharePoint."

// BAD — gerund
description: "Listing all SQL warehouses in Databricks."

// BAD — third-person verb
description: "Lists all SQL warehouses available in Databricks."

// GOOD — bare infinitive, platform noun, no location noise
description: "List all SQL warehouses available in the Databricks workspace."

// GOOD — synonym in parentheses helps BM25 match "sheets" and "tabs"
description: "Get a list of all worksheets (sheets/tabs) in an Excel workbook."

// GOOD — verb + context + common synonyms
description: "Search Slack channels, messages, and threads by keyword or topic."

Test your descriptions: add a BM25 query case (see next section) before merging. If your expected tool doesn't score > 0 in its own server-scoped index, the description is too generic or missing the key tokens the user will type.

2. Create tools/index.ts

Create front/lib/api/actions/servers/{provider}/tools/index.ts:

import { MCPError } from "@app/lib/actions/mcp_errors";
import type { ToolHandlers } from "@app/lib/actions/mcp_internal_actions/tool_definition";
import { buildTools } from "@app/lib/actions/mcp_internal_actions/tool_definition";
import { YOUR_PROVIDER_TOOLS_METADATA } from "@app/lib/api/actions/servers/your_provider/metadata";
import { Err, Ok } from "@app/types/shared/result";

const handlers: ToolHandlers<typeof YOUR_PROVIDER_TOOLS_METADATA> = {
  list_items: async ({ pageToken, maxResults }, { authInfo }) => {
    const token = authInfo?.token;
    if (!token) {
      return new Err(new MCPError("No access token provided"));
    }

    try {
      const items = [];

      return new Ok([
        { type: "text" as const, text: `Found ${items.length} items` },
        { type: "text" as const, text: JSON.stringify({ items }, null, 2) },
      ]);
    } catch (e) {
      return new Err(new MCPError("Failed to list items"));
    }
  },

  get_item: async ({ itemId }, { authInfo }) => {
    const token = authInfo?.token;
    if (!token) {
      return new Err(new MCPError

---

*Content truncated.*

When not to use it

  • Developing external-facing public MCP servers
  • General platform integration without Dust ecosystem requirements

Prerequisites

OAuth provider implementation in core and frontDust development environment

Limitations

  • Server IDs must be stable and unique once deployed
  • Requires manual registration in multiple configuration files
  • OAuth token refresh must follow the withAuth pattern

How it compares

This workflow enforces a specific file structure and type-checked tool definition pattern compared to generic MCP server development.

Compared to similar skills

dust-mcp-server side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
dust-mcp-server (this skill)125dReviewAdvanced
mcporter72moNo flagsIntermediate
calcom-api23moNo flagsIntermediate
developing-genkit-tooling26moNo flagsIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

You might also like

mcporter

openclaw

Use the mcporter CLI to list, configure, auth, and call MCP servers/tools directly (HTTP or stdio), including ad-hoc servers, config edits, and CLI/type generation.

726

calcom-api

calcom

Interact with the Cal.com API v2 to manage scheduling, bookings, event types, availability, and calendars. Use this skill when building integrations that need to create or manage bookings, check availability, configure event types, or sync calendars with Cal.com's scheduling infrastructure.

216

developing-genkit-tooling

firebase

Best practices for authoring Genkit tooling, including CLI commands and MCP server tools. Covers naming conventions, architectural patterns, and consistency guidelines.

27

juicebox-rate-limits

jeremylongshore

Implement Juicebox rate limiting and backoff. Use when handling API quotas, implementing retry logic, or optimizing request throughput. Trigger with phrases like "juicebox rate limit", "juicebox quota", "juicebox throttling", "juicebox backoff".

23

clay-sdk-patterns

jeremylongshore

Apply production-ready Clay SDK patterns for TypeScript and Python. Use when implementing Clay integrations, refactoring SDK usage, or establishing team coding standards for Clay. Trigger with phrases like "clay SDK patterns", "clay best practices", "clay code patterns", "idiomatic clay".

04

vercel-sdk-patterns

jeremylongshore

Execute apply production-ready Vercel SDK patterns for TypeScript and Python. Use when implementing Vercel integrations, refactoring SDK usage, or establishing team coding standards for Vercel. Trigger with phrases like "vercel SDK patterns", "vercel best practices", "vercel code patterns", "idiomatic vercel".

13

Search skills

Search the agent skills registry