chatgpt-app-builder

Par mcp-use · mcp-use

**OBLIGATOIRE pour TOUT travail sur un serveur MCP** - bonnes pratiques et patterns du framework mcp-use. **LIRE EN PREMIER** avant tout travail sur un serveur MCP, notamment : - Création de nouveaux serveurs MCP - Modification de serveurs MCP existants (ajout/mise à jour de tools, resources, prompts, widgets) - Débogage de problèmes ou d'erreurs sur un serveur MCP - Revue de code de serveur MCP (qualité, sécurité ou performance) - Réponse à des questions sur le développement MCP ou les patterns mcp-use - Toute modification de `server.tool()`, `server.resource()`, `server.prompt()` ou des widgets Ce skill contient des décisions d'architecture critiques, des patterns de sécurité et des pièges courants. Consultez toujours les fichiers de référence pertinents AVANT d'implémenter des fonctionnalités MCP.

npx skills add https://github.com/mcp-use/mcp-use --skill chatgpt-app-builder

IMPORTANT : Comment utiliser cette compétence

Ce fichier fournit un GUIDE DE NAVIGATION UNIQUEMENT. Avant d'implémenter une quelconque fonctionnalité de serveur MCP, tu DOIS :

  1. Lire cet aperçu pour comprendre quels fichiers de référence sont pertinents
  2. TOUJOURS lire le ou les fichiers de référence spécifiques pour les fonctionnalités que tu implémentes
  3. Appliquer les motifs détaillés de ces fichiers à ton implémentation

Ne te fie PAS uniquement aux exemples rapides de ce fichier — ils sont minimalistes. Les fichiers de référence contiennent les meilleures pratiques critiques, les considérations de sécurité et les motifs avancés.


Meilleures pratiques de serveur MCP

Guide complet pour construire des serveurs MCP prêts pour la production avec outils, ressources, prompts et widgets utilisant mcp-use.

⚠️ AVANT TOUT : Nouveau projet ou projet existant ?

Avant de faire quoi que ce soit, détermine si tu es à l'intérieur d'un projet mcp-use existant.

Détection : Vérifie l'espace de travail pour un package.json qui liste "mcp-use" comme dépendance, OU tout fichier .ts qui importe depuis "mcp-use/server".

├─ Projet mcp-use TROUVÉ → Ne fais PAS de scaffolding. Tu es déjà dans un projet.
│  └─ Saute à « Quick Navigation » ci-dessous pour ajouter des fonctionnalités.
│
├─ Pas de projet mcp-use (répertoire vide, projet non lié ou greenfield)
│  └─ Fais d'abord le scaffolding avec npx create-mcp-use-app, puis ajoute les fonctionnalités.
│     Voir « Scaffolding a New Project » ci-dessous.
│
└─ À l'intérieur d'un projet NON LIÉ (p. ex. app Next.js) et l'utilisateur veut un serveur MCP
   └─ Demande à l'utilisateur où le créer, puis fais le scaffolding dans ce répertoire.
      Ne fais PAS le scaffolding à l'intérieur d'une racine de projet non lié existante.

NE crée JAMAIS manuellement le boilerplate MCPServer, package.json ou la structure du projet. La CLI configure TypeScript, les scripts de développement, l'intégration de l'inspecteur, le rechargement à chaud et la compilation des widgets, ce qui est difficile à reproduire manuellement.


Scaffolding d'un nouveau projet

npx create-mcp-use-app my-server
cd my-server
npm run dev

Pour les détails complets du scaffolding et les drapeaux CLI, voir quickstart.md.


Navigation rapide

Choisis ton chemin en fonction de ce que tu construis :

🚀 Fondations

Quand : TOUJOURS lire d'abord quand tu commences un travail MCP dans une nouvelle conversation. Référence ultérieurement pour clarifier l'architecture/les concepts.

  1. concepts.md — Primitives MCP (Tool, Resource, Prompt, Widget) et quand utiliser chacune
  2. architecture.md — Structure du serveur (basée sur Hono), système de middleware, server.use() vs server.app
  3. quickstart.md — Scaffolding, configuration et premier exemple d'outil
  4. deployment.md — Déployer sur Manufact Cloud, auto-hébergement, Docker, gérer les déploiements

Charge-les avant de plonger dans les sections outils/ressources/widgets.


🔐 Ajouter l'authentification ?

Quand : Protéger ton serveur avec OAuth (Auth0, Better Auth, WorkOS, Supabase, Keycloak, ou tout autre fournisseur)

  • overview.md

    • Quand : Première fois ajoutant l'authentification, comprenant ctx.auth, ou choisissant un fournisseur / mode d'intégration
    • Couvre : Authentification distante vs proxy OAuth, config oauth, forme de ctx.auth, comparaison des fournisseurs, erreurs courantes
  • auth0.md

    • Quand : Utilisant Auth0 — DCR (Early Access) ou une Regular Web App standard via oauthProxy
    • Couvre : Configuration pour les deux modes, extraAuthorizeParams.audience, permissions via rfc9068_profile_authz
  • better-auth.md

    • Quand : Utilisant Better Auth avec le plugin @better-auth/oauth-provider (OAuth 2.1 auto-hébergé)
    • Couvre : oauthBetterAuthProvider, routes d'URL auth / métadonnées, flux de connexion et consentement
  • workos.md

    • Quand : Utilisant WorkOS AuthKit (DCR uniquement)
    • Couvre : Configuration, variables env, rôles/permissions, filtrage org multi-tenant, appels API WorkOS
  • supabase.md

    • Quand : Utilisant le serveur OAuth 2.1 de Supabase
    • Couvre : Configuration, clés publiables, ES256 vs HS256, héberger l'interface de consentement, appels SDK RLS-aware
  • keycloak.md

    • Quand : Utilisant Keycloak via DCR natif
    • Couvre : Hôtes de confiance DCR + origines web, application de l'audience, rôles realm vs ressource, userinfo
  • custom.md

    • Quand : Tout autre fournisseur — capable de DCR via oauthCustomProvider, ou pré-enregistré (Google, GitHub, Okta, Azure AD) via oauthProxy
    • Couvre : oauthCustomProvider, oauthProxy + jwksVerifier, exemples de fournisseur, vérification de jeton opaque

🔧 Construire un backend de serveur (pas d'interface utilisateur) ?

Quand : Implémenter des fonctionnalités MCP (actions, données, templates). Lis le fichier spécifique pour la primitive que tu construis.

  • tools.md

    • Quand : Créer des actions backend que l'IA peut appeler (send-email, fetch-data, create-user)
    • Couvre : Définition d'outil, schémas, annotations, contexte, gestion d'erreurs
  • resources.md

    • Quand : Exposer des données en lecture seule que les clients peuvent récupérer (config, profils utilisateur, documentation)
    • Couvre : Ressources statiques, ressources dynamiques, templates de ressources paramétrés, complément URI
  • prompts.md

    • Quand : Créer des templates de messages réutilisables pour les interactions IA (code-review, summarize)
    • Couvre : Définition de prompt, paramétrisation, complément d'arguments, meilleures pratiques de prompt
  • response-helpers.md

    • Quand : Formatter les réponses des outils/ressources (texte, JSON, markdown, images, erreurs)
    • Couvre : text(), object(), markdown(), image(), error(), mix()
  • proxy.md

    • Quand : Composer plusieurs serveurs MCP en un serveur agrégateur unifié
    • Couvre : server.proxy(), API config, sessions explicites, routage d'échantillonnage
  • architecture.md

    • Quand : Ajouter de la logique transversale (logging, vérifications auth, rate limiting, filtrage d'outils) qui s'étend sur plusieurs outils/ressources
    • Couvre : Middleware server.use('mcp:...'), MiddlewareContext (method, params, auth, state), correspondance de motifs, middleware HTTP vs MCP

🎨 Construire des widgets visuels (interface utilisateur interactive) ?

Quand : Créer des interfaces React pour parcourir, comparer ou sélectionner des données

  • basics.md

    • Quand : Créer ton premier widget ou ajouter une interface à un outil existant
    • Couvre : Configuration du widget, hook useWidget(), vérifications isPending, manipulation des props
  • state.md

    • Quand : Gérer l'état de l'interface (sélections, filtres, onglets) dans les widgets
    • Couvre : useState, setState, persistance d'état, quand utiliser l'état d'outil vs widget
  • interactivity.md

    • Quand : Ajouter des boutons, formulaires ou appeler des outils depuis les widgets
    • Couvre : useCallTool(), manipulation de formulaires, boutons d'action, mises à jour optimistes
  • ui-guidelines.md

    • Quand : Styliser les widgets pour supporter les thèmes, dispositions réactives ou accessibilité
    • Couvre : useWidgetTheme(), mode clair/sombre, autoSize, motifs de disposition, meilleures pratiques CSS
  • advanced.md

    • Quand : Construire des widgets complexes avec données async, limites d'erreurs ou optimisations de performance
    • Couvre : États de chargement, gestion d'erreurs, mémoïsation, fractionnement de code
  • model-context.md

    • Quand : Garder le modèle IA conscient de ce que l'utilisateur voit actuellement (onglet actif, élément survolé, produit sélectionné) sans nécessiter d'appels d'outils
    • Couvre : Composant <ModelContext>, API impérative modelContext.set/remove, imbrication, sérialisation d'arbre, règles de cycle de vie
  • files.md

    • Quand : Télécharger ou téléverser des fichiers depuis un widget (SDK ChatGPT Apps uniquement)
    • Couvre : Hook useFiles(), garde isSupported, visibilité du modèle (modelVisible), stockage de fileId, URL de téléchargement temporaires

📚 Besoin d'exemples complets ?

Quand : Tu veux voir des implémentations complètes de cas d'usage courants

  • common-patterns.md
    • Exemples de bout en bout : application météo, liste de tâches, navigateur de recettes
    • Affiche : Code serveur + code widget + meilleures pratiques en contexte

Arbre de décision

De quoi as-tu besoin ?

├─ Nouveau projet à partir de zéro
│  └─> quickstart.md (scaffolding + configuration)
│
├─ OAuth / authentification utilisateur
│  └─> authentication/overview.md → guide spécifique au fournisseur
│
├─ Action backend simple (pas d'interface)
│  └─> Utiliser Tool : server/tools.md
│
├─ Données en lecture seule pour les clients
│  └─> Utiliser Resource : server/resources.md
│
├─ Template de prompt réutilisable
│  └─> Utiliser Prompt : server/prompts.md
│
├─ Logique transversale (logging, vérifications auth, rate limiting, filtrage d'outils)
│  └─> Utiliser Middleware : architecture.md#mcp-middleware
│
├─ Interface utilisateur visuelle/interactive
│  └─> Utiliser Widget : widgets/basics.md
│
├─ Garder le modèle conscient de ce que l'utilisateur voit dans le widget
│  └─> widgets/model-context.md
├─ Télécharger/téléverser des fichiers dans un widget
│  └─> widgets/files.md (SDK ChatGPT Apps uniquement)
│
└─ Déployer en production
   └─> deployment.md (déploiement cloud, auto-hébergement, Docker)

Principes fondamentaux

  1. Outils pour les actions — Opérations backend avec entrée/sortie
  2. Ressources pour les données — Données en lecture seule que les clients peuvent récupérer
  3. Prompts pour les templates — Templates de messages réutilisables
  4. Widgets pour l'interface — Interfaces visuelles quand utile
  5. Données fictives d'abord — Prototype rapidement, connecte les API plus tard

❌ Erreurs courantes

Évite ces anti-motifs trouvés dans les serveurs MCP en production :

Définition d'outil

  • ❌ Retourner des objets bruts au lieu d'utiliser les helpers de réponse
    • ✅ Utilise les helpers text(), object(), widget(), error()
  • ❌ Sauter .describe() du schéma Zod sur chaque champ
    • ✅ Ajoute des descriptions à tous les champs du schéma pour une meilleure compréhension de l'IA
  • ❌ Pas de validation ou sanitisation d'entrée
    • ✅ Valide les entrées avec Zod, sanitise les données fournies par l'utilisateur
  • ❌ Lancer des erreurs au lieu d'utiliser le helper error()
    • ✅ Utilise error("message") pour des réponses d'erreur gracieuses

Développement de widget

  • ❌ Accéder à props sans vérifier isPending
    • ✅ Toujours vérifier if (isPending) return <Loading/>
  • ❌ Le widget gère l'état du serveur (filtres, sélections)
    • ✅ Les widgets gèrent leur propre état d'interface avec useState
  • ❌ Wrapper McpUseProvider manquant ou autoSize
    • ✅ Enveloppe le composant root : <McpUseProvider autoSize>
  • ❌ Styles en ligne sans sensibilité au thème
    • ✅ Utilise useWidgetTheme() pour le support du mode clair/sombre

Sécurité et production

  • ❌ Clés API ou secrets codés en dur dans le code
    • ✅ Utilise process.env.API_KEY, documente dans .env.example
  • ❌ Pas de gestion d'erreurs dans les handlers d'outils
    • ✅ Enveloppe dans try/catch, retourne error() en cas d'échec
  • ❌ Opérations coûteuses sans caching
    • ✅ Cache les appels API, les calculs avec TTL
  • ❌ Configuration CORS manquante
    • ✅ Configure CORS pour les déploiements en production

🔒 Règles d'or

Directives architecturales opinionnées :

1. Un outil = Une capacité

Divise les actions larges en outils ciblés :

  • manage-users (trop vague)
  • create-user, delete-user, list-users

2. Retourner les données complètes d'emblée

Les appels d'outils sont coûteux. Évite le chargement paresseux :

  • list-products + get-product-details (2 appels)
  • list-products retourne les données complètes incluant les détails

3. Les widgets possèdent leur état

L'état de l'interface vit dans le widget, pas dans des outils séparés :

  • ❌ Outil select-item, outil set-filter
  • ✅ Le widget gère avec useState ou setState

4. exposeAsTool par défaut à false

Les widgets sont enregistrés comme ressources uniquement par défaut. Utilise un outil personnalisé (recommandé) ou définis exposeAsTool: true pour exposer un widget au modèle :

// ✅ LES 4 ÉTAPES REQUISES pour l'inférence de type appropriée :

// Étape 1 : Définir le schéma séparément
const propsSchema = z.object({
  title: z.string(),
  items: z.array(z.string())
});

// Étape 2 : Référencer la variable du schéma dans les métadonnées
export const widgetMetadata: WidgetMetadata = {
  description: "...",
  props: propsSchema,  // ← PAS z.object() en ligne
  exposeAsTool: false
};

// Étape 3 : Inférer le type Props à partir de la variable du schéma
type Props = z.infer<typeof propsSchema>;

// Étape 4 : Utiliser les Props typés avec useWidget
export default function MyWidget() {
  const { props, isPending } = useWidget<Props>();  // ← Ajouter <Props>
  // ...
}

⚠️ Erreur courante : Faire seulement les étapes 1-2 mais sauter 3-4 (perd la sécurité de type)

5. Valider aux limites uniquement

  • Fais confiance au code interne et aux garanties du framework
  • Valide l'entrée utilisateur, les réponses API externes
  • N'ajoute pas de gestion d'erreurs pour les scénarios qui ne peuvent pas se produire

6. Préférer les widgets pour parcourir/comparer

En cas de doute, ajoute un widget. L'interface visuelle améliore :

  • Le parcours de plusieurs éléments
  • La comparaison de données côte à côte
  • Les workflows de sélection interactive

Référence rapide

Serveur minimal

import { MCPServer, text } from "mcp-use/server";
import { z } from "zod";

const server = new MCPServer({
  name: "my-server",
  title: "My Server",
  version: "1.0.0"
});

server.tool(
  {
    name: "greet",
    description: "Greet a user",
    schema: z.object({ name: z.string().describe("User's name") })
  },
  async ({ name }) => text("Hello " + name + "!"),
);

server.listen();

Helpers de réponse

Helper Utiliser quand Exemple
text() Réponse simple en string text("Success!")
object() Données structurées object({ status: "ok" })
markdown() Texte formaté markdown("# Title\nContent")
widget() Interface visuelle widget({ props: {...}, output: text(...) })
mix() Contenus multiples mix(text("Hi"), image(url))
error() Réponses d'erreur error("Failed to fetch data")
resource() Intégrer des renvois de ressources resource("docs://guide", "text/markdown")

Méthodes du serveur :

  • server.tool() — Définir un outil exécutable
  • server.resource() — Définir une ressource statique/dynamique
  • server.resourceTemplate() — Définir une ressource paramétrée
  • server.prompt() — Définir un template de prompt
  • server.proxy() — Composer/Proxy plusieurs serveurs MCP
  • server.uiResource() — Définir une ressource widget
  • server.listen() — Démarrer le serveur
  • server.use('mcp:tools/call', fn) — Middleware MCP (outils, ressources, prompts, opérations list)
  • server.use('mcp:*', fn) — Middleware MCP fourre-tout
  • server.use(fn) — Middleware HTTP (Hono)

Skills similaires