
MCP Server : Implémenter un serveur Model Context Protocol en TypeScript
Découvrez comment créer un serveur MCP en TypeScript à l'aide du SDK officiel. Apprenez à fournir un contexte riche aux LLMs.
Progression
pour cette quatrième et dernière partie nous allons voir comment déployer notre application sur Google Cloud PLatform (GCP) avec App Engine.
Pour ce faire nous allons devoir :
stage
de déploiement.La première chose à faire c’est de se connecter ou s'inscrire sur la console de Google Cloud Platform. Si tout va bien vous arriverez sur cette page :
Puis vous cliquez sur créer et vous entrez le nom de votre projet. Vous pouvez aussi customiser l’ID de votre projet :
/!\ Dans mon cas, l’ID du projet est déjà utilisée car je l’avais déjà créée.
Pour le déploiement sur GCP App Engine il faut activer deux APIs :
Pour activer une API il faut, depuis la console GCP, aller dans le menu droite dans API et services
. Ensuite, allez dans la bibliothèque, et avec la barre de recherche trouvez les APIs que vous intéressent. Accédez à la page de l’API et activez-la.
Il nous faudra aussi des identifiants pour nous connecter depuis la CI/CD. Pour ce faire, toujours dans API et services
, allez dans la sous-section identifiant
et cliquez sur créer des identifiants
puis créer une clé de compte de service
.
Vous arrivez sur l'écran ci-dessous. Sélectionnez App Engine default service account
et json
.
Un fichier au format json
est automatiquement téléchargé sur votre ordinateur. Copiez l'intégralité du contenu de ce fichier et allez dans l’interface web de Gitlab dans Settings > CI/CD > Variables
.
Ici, nous créons une nouvelle variable que l’on va nommer GCP_CREDENTIALS
et contenant le contenu du fichier précédemment téléchargé.
Voilà pour le credential.
/!\ N'activez pas la protection, autrement la variable ne pourra pas être utilisée dans les prochaines étapes
Nous allons faire un template pour le fichier app.yaml afin qu’il soit généré selon son environnement grâce l’outil envsubst
du paquet gettext
.
Voici le template du fichier app.yaml :
service: ${CI_ENVIRONMENT_NAME} runtime: python27 api_version: '1' env: standard threadsafe: true instance_class: F1 handlers: - url: / application_readable: false static_files: dist/index.html require_matching_file: false upload: dist/index.html - url: '/(.*)' application_readable: false static_files: "dist/\\1" require_matching_file: false upload: 'dist/.*'
Nous allons nommer ce fichier app.template.yaml
. Dans notre CI/CD nous éxécuterons la commande suivante envsubst < app.template.yaml > app.yaml
, elle nous permettera de modifier les variables d'environnement de notre fichier et de créer le fichier app.yml
.
Nous allons avoir besoin d'une image personnalisée car nous allons avoir besoin de node, de git et du sdk de Google Cloud Plateform.
Dans le cas où vous n'auriez pas besoin de git et de node sachez qu'il existe une image docker avec le sdk de GCP déjà installé. google/cloud-sdk
Pour ce faire, créez un fichier Dockerfile-ci dans un nouveau répertoire nommé docker. Voici le Dockerfile :
FROM node:8-alpine
ARG CLOUD_SDK_VERSION=216.0.0
ENV CLOUD_SDK_VERSION=$CLOUD_SDK_VERSION
ENV PATH /google-cloud-sdk/bin:$PATH
RUN apk --no-cache add \
curl \
python \
py-crcmod \
bash \
libc6-compat \
openssh-client \
git \
gnupg \
gettext \
&& curl -O https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-${CLOUD_SDK_VERSION}-linux-x86_64.tar.gz && \
tar xzf google-cloud-sdk-${CLOUD_SDK_VERSION}-linux-x86_64.tar.gz && \
rm google-cloud-sdk-${CLOUD_SDK_VERSION}-linux-x86_64.tar.gz && \
ln -s /lib /lib64 && \
gcloud config set core/disable_usage_reporting true && \
gcloud config set component_manager/disable_update_check true && \
gcloud config set metrics/environment github_docker_image && \
gcloud --version
RUN apk add --update --no-cache git
RUN rm -rf /var/cache/apk/*
Nous allons mettre notre image sur le registry de notre dépôt. Pour ce faire nous éxécutons les commandes suivantes :
# On se connecte au registry de gitlab.com docker login registry.gitlab.com # Nous construissons notre image docker docker build -t registry.gitlab.com/ngrevin/gitlab-ci-js/deploy-image . # Et nous poussons notre image sur le registry docker push registry.gitlab.com/ngrevin/gitlab-ci-js/deploy-image
Pour créer un token
sur gitlab rendez-vous sur la page Personal Access Token Profile > Personal Access Token
.
Donnez-lui un nom, ici j'ai choisi PERSONAL_ACCESS_TOKEN
, et donnez-lui les droits suiffisants.
En suite, comme pour les credentials de GCP, créez une variable d'environnement dans votre projet avec l'access token précédement créé.
/!\ N'activez pas la protection, autrement la variable ne pourra pas être utilisée dans les prochaines étapes
Maintenant que tout est prêt il nous reste juste à déployer notre application avec Gitlab-ci.
Nous allons donc ajouter deux nouveaux jobs
dans notre dernière stage
.
.deploy_template: &deploy_template # On defini notre template pour le deploiement de notre application stage: deploy # On lie nous prochain job avec le stage 'deploy' image: registry.gitlab.com/ngrevin/gitlab-ci-js/deploy-image # before_script: # Avant le script principale nous faisons : - echo ${GCP_CREDENTIALS} > /tmp/${CI_PIPELINE_ID}.json # Nous récuperons notre variables 'GCP_CREDENTIALS' et on la sauvegarde dans un fichier - gcloud auth activate-service-account --key-file /tmp/$CI_PIPELINE_ID.json # Grâce au fichier précédement créer nous nous connectons à GCP - envsubst < app.template.yaml > app.yaml # Nous créons notre fichier 'app.yml' after_script: # Après le script principale nous faisons : - rm /tmp/$CI_PIPELINE_ID.json # On supprime toute trace de nos credentials GCP cache: # Définition des règles de cache pour récuperer les caches de l'étape de build paths: - ./dist policy: pull deploy:demo: <<: *deploy_template # on appel notre template environment: # On définit notre environnment name: demo url: https://demo-dot-gitlab-ci-js.appspot.com # on indique l'url de notre application de demo script: # Nous déployons notre application avec la commande 'gcloud app deploy ./app.yml --project=gitlab-ci-js' # Comme nous ne voulons pas d'interaction nous ajoutons l'option 'quiet' # Comme nous voulons voir le log lors du déploiement nous ajoutons l'option 'verbosity' avec la valeur à 'error' # Le numéro de version sera l'id de la pipeline # Avec '--promote --stop-previous-version' nous arrêtons la version précédente en promouvant la nouvelle version - gcloud --quiet --verbosity=error app deploy ./app.yaml --project=gitlab-ci-js --version=${CI_PIPELINE_ID} --promote --stop-previous-version only: - demo deploy:production: <<: *deploy_template # on appelle notre template environment: # On définit notre environnment name: production url: https://production-dot-gitlab-ci-js.appspot.com # on indique l'url de notre application de production script: # Idem que pour l'environnment de demo - gcloud --quiet --verbosity=error app deploy ./app.yaml --project=gitlab-ci-js --version=${CI_PIPELINE_ID} --promote --stop-previous-version # Nous configurons git et nous mettons à jour l'origine avec notre token - git config --global user.name "ngrevin" - git config --global user.email "${GITLAB_USER_EMAIL}" - git remote rm origin - git remote add origin https://${GITLAB_USER_LOGIN}:${PERSONAL_ACCESS_TOKEN}@gitlab.com/ngrevin/gitlab-ci-js.git - git fetch --all # Nous passons sur demo et nous copions 'dist/package.json' à la racine de notre projet pour remplacer l'ancien fichier 'package.json' car la version a été mise à jour lors de job build:app - git checkout demo - cp dist/package.json . # On récupère le numéro de version grâce a la commande 'yarn versions' et nous la formattons sans d'autre information que le numéro, et sans couleur - NEW_VERSION=$(yarn versions | grep gitlab-ci-js | sed "s/\('\| \|,\)//g" | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" | cut -d":" -f2) # On ajoute nos modifications, on commit et on pousse les modifications - git add --all - git commit -m "NEW VERSION - v${NEW_VERSION}" - git push https://${GITLAB_USER_LOGIN}:${PERSONAL_ACCESS_TOKEN}@gitlab.com/ngrevin/gitlab-ci-js.git demo # Ici nous allons merge demo dans master en écrasant master par rapport à demo, puis nous poussons les modifications sur master - git merge -s ours origin/master -m "Merge for new version" - git checkout master - git merge --no-ff --commit -m "NEW VERSION - v${NEW_VERSION}" demo - git push https://${GITLAB_USER_LOGIN}:${PERSONAL_ACCESS_TOKEN}@gitlab.com/ngrevin/gitlab-ci-js.git master artifacts: name: "${CI_COMMIT_TAG:1}" untracked: false paths: - . only: - tags
Voici quelques liens pour avoir des explications sur les nouvelle définitions utilisés :
On push nos modifications :
git checkout -b gitlab-ci-js/step3 git add . git commit -m “gitlab-ci-js/step3 - add .gitlab-ci.yml” git origin gitlab-ci-js/step3
Vous créez une PR et vous la mergez dans demo
Et voilà le résultat de notre CI/CD pour le déploiement en démo :
Auteur(s)
Nicolas Grévin
Ingénieur DevOps SRE spécialisé en conteneurisation, Kubernetes, CI/CD, cloud, Infrastructure as Code et outillage. Engagé dans la Green IT et développeur passionné.
Vous souhaitez en savoir plus sur le sujet ?
Organisons un échange !
Notre équipe d'experts répond à toutes vos questions.
Nous contacterDécouvrez nos autres contenus dans le même thème
Découvrez comment créer un serveur MCP en TypeScript à l'aide du SDK officiel. Apprenez à fournir un contexte riche aux LLMs.
Découvrez comment créer un plugin ESLint en TypeScript avec la nouvelle configuration "flat config" et publiez-le sur npm.
Apprenez à concevoir une barre de recherche accessible pour le web, conforme RGAA. Bonnes pratiques, erreurs fréquentes à éviter et exemples concrets en HTML et React/MUI.