Aller au contenu

Serveur MCP TypeScript

Générer un serveur Model Context Protocol (MCP) TypeScript pour fournir du contexte aux grands modèles de langage (LLM), et éventuellement le déployer sur Amazon Bedrock AgentCore.

Le Model Context Protocol (MCP) est un standard ouvert qui permet aux assistants IA d’interagir avec des outils et des ressources externes. Il fournit une manière cohérente pour les LLM de :

  • Exécuter des outils (fonctions) qui effectuent des actions ou récupèrent des informations
  • Accéder à des ressources qui fournissent du contexte ou des données

Vous pouvez générer un serveur MCP TypeScript de deux manières :

Exécuter ce générateur@aws/nx-plugin:ts#mcp-server

pnpm nx g @aws/nx-plugin:ts#mcp-server
Composez votre commande6

Requis

infra = agentcore | agentcore-ecr

Options du générateur6 options
projectRequisstring

Le projet auquel ajouter un serveur MCP

authenuminfra = agentcore | agentcore-ecrPar défaut: iam

La méthode utilisée pour s'authentifier auprès de votre serveur MCP. Applicable uniquement lorsque infra est défini (ignoré lorsque infra est none).

iamcognito
iacenumPar défaut: inherit

Le fournisseur IaC préféré. Par défaut, cette valeur est héritée de votre sélection initiale.

inheritcdkterraform
infraenumPar défaut: agentcore

Le type d'infrastructure pour héberger votre serveur MCP. agentcore déploie votre code sous forme de zip vers un runtime géré par AgentCore pour le cycle de build et déploiement le plus rapide. agentcore-ecr construit et héberge une image conteneur à la place, pour un contrôle au niveau de l'OS ou un pipeline de conteneurs établi. Sélectionnez none pour aucun hébergement.

agentcoreagentcore-ecrnone
namestring

Le nom de votre serveur MCP (par défaut : mcp-server)

preferInstallDependenciesbooleanPar défaut: true

Indique s'il faut privilégier l'installation des dépendances après l'exécution du générateur. Définir sur false pour différer l'installation lors de l'exécution de plusieurs générateurs en lot (une installation s'exécute quand même si nécessaire pour que les générateurs suivants puissent calculer le graphe de projet Nx) ; installer une seule fois à la fin.

Le générateur ajoutera les fichiers suivants à votre projet TypeScript existant :

  • Répertoireyour-project/
    • Répertoiresrc/
      • Répertoiremcp-server/ (ou nom personnalisé si spécifié)
        • index.ts Exports your server
        • server.ts Main server definition
        • stdio.ts Entry point for STDIO transport, useful for simple local MCP servers
        • http.ts Entry point for Streamable HTTP transport, useful for hosting your MCP server
        • Répertoiretools/
          • divide.ts Sample tool
        • Répertoireresources/
          • sample-guidance.ts Sample resource
        • Dockerfile Container image definition (only when infra is agentcore-ecr)
    • project.json Updated with MCP server serve target

L’option infra sélectionne la manière dont votre code est empaqueté et hébergé sur Amazon Bedrock AgentCore Runtime :

  • agentcore (par défaut) utilise le déploiement direct de code : votre code compilé est empaqueté sous forme de .zip, téléchargé vers S3, et exécuté sur un runtime de langage géré par AgentCore. Il n’y a pas d’image de conteneur à construire, pas de dépôt ECR à gérer, et pas d’image à pousser, ce qui permet un cycle de construction et de déploiement nettement plus rapide.
  • agentcore-ecr construit une image de conteneur arm64 à partir d’un Dockerfile fourni et l’héberge depuis le registre partagé core/asset-ecr, aux côtés de tous les autres conteneurs de l’espace de travail. Choisissez cette option lorsque vous avez besoin de contrôler l’image du système d’exploitation — par exemple pour installer des bibliothèques système natives — ou lorsque vous disposez d’un pipeline de conteneurs établi. Cette option fournit également une cible d’analyse d’image Trivy (voir Analyse d’image ci-dessous).
  • none ne génère aucune infrastructure, de sorte que le projet ne peut être exécuté que localement.
infra = agentcore | agentcore-ecr

Étant donné que ce générateur fournit de l’infrastructure en tant que code basée sur votre iac choisi, il créera un projet dans packages/common qui inclut les constructs CDK ou modules Terraform pertinents.

Le projet d’infrastructure en tant que code commun est structuré comme suit :

  • Répertoirepackages/common/constructs
    • Répertoiresrc
      • Répertoireapp/ Constructs pour l’infrastructure spécifique à un projet/générateur
      • Répertoirecore/ Constructs génériques qui sont réutilisés par les constructs dans app
      • index.ts Entry point exporting constructs from app
    • project.json Project build targets and configuration

Pour déployer votre serveur MCP, les fichiers suivants sont générés :

  • Répertoirepackages/common/constructs/src
    • Répertoireapp
      • Répertoiremcp-servers
        • Répertoire<mcp-server-name>
          • <mcp-server-name>.ts CDK construct for deploying your MCP Server
infra = none

Si vous avez sélectionné none pour infra, aucune construction CDK ou module Terraform n’est généré — le serveur MCP est configuré uniquement pour une utilisation locale STDIO / HTTP. L’option auth est ignorée dans ce mode car il n’y a pas de point de terminaison hébergé à authentifier.

Lorsqu’il est déployé sur Bedrock AgentCore Runtime, le code de votre serveur est empaqueté sous forme de zip et exécuté dans le runtime géré AgentCore. Les assistants IA invoquent le point de terminaison du plan de données AgentCore Runtime, qui transmet les appels tools/* et resources/* à votre serveur via le transport HTTP diffusable.

Loading the diagram…

Les outils sont des fonctions que l’assistant IA peut appeler pour effectuer des actions. Chaque outil se trouve dans son propre fichier sous tools/ qui exporte une fonction register<Name>Tool, que vous appelez ensuite depuis server.ts. Par exemple, ajoutez tools/my-tool.ts :

tools/my-tool.ts
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';
export const registerMyTool = (server: McpServer) => {
server.registerTool(
'toolName',
{
description: 'tool description',
// Input schema using Zod
inputSchema: { param1: z.string(), param2: z.number() },
},
async ({ param1, param2 }) => {
// Tool implementation
const result = `${param1} ${param2}`;
return {
content: [{ type: 'text' as const, text: result }],
};
},
);
};

Ensuite, enregistrez-le à l’intérieur de createServer dans server.ts :

server.ts
import { registerMyTool } from './tools/my-tool.js';
export const createServer = async () => {
const server = new McpServer({ name: 'my-server', version: '1.0.0' });
registerMyTool(server);
return server;
};

Les ressources fournissent du contexte à l’assistant IA. Comme les outils, chaque ressource se trouve dans son propre fichier sous resources/ qui exporte une fonction register<Name>Resource appelée depuis server.ts. Vous pouvez ajouter des ressources statiques à partir de fichiers ou des ressources dynamiques :

resources/my-resource.ts
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
const fetchSomeData = async (): Promise<string> => 'some dynamic context';
export const registerMyResource = (server: McpServer) => {
const exampleContext = 'some context to return';
server.registerResource(
'resource-name',
'example://resource',
{},
async (uri) => ({
contents: [{ uri: uri.href, text: exampleContext }],
}),
);
// Dynamic resource
server.registerResource(
'dynamic-resource',
'dynamic://resource',
{},
async (uri) => {
const data = await fetchSomeData();
return {
contents: [{ uri: uri.href, text: data }],
};
},
);
};

Enregistrez-le à l’intérieur de createServer dans server.ts de la même manière qu’un outil :

server.ts
import { registerMyResource } from './resources/my-resource.js';
export const createServer = async () => {
const server = new McpServer({ name: 'my-server', version: '1.0.0' });
registerMyResource(server);
return server;
};

La plupart des assistants IA qui prennent en charge MCP utilisent une approche de configuration similaire. Vous devrez créer ou mettre à jour un fichier de configuration avec les détails de votre serveur MCP :

{
"mcpServers": {
"your-mcp-server": {
"command": "npx",
"args": ["tsx", "/path/to/your-mcp-server/stdio.ts"]
}
}
}

Lors du développement de votre serveur MCP, vous pouvez souhaiter configurer le flag --watch afin que l’assistant IA voie toujours les dernières versions des outils/ressources :

{
"mcpServers": {
"your-mcp-server": {
"command": "npx",
"args": ["tsx", "--watch", "/path/to/your-mcp-server/stdio.ts"]
}
}
}

Veuillez vous référer à la documentation suivante pour configurer MCP avec des assistants IA spécifiques :

Pour exécuter votre serveur MCP (et tout ce qui y est connecté, comme une base de données locale) localement, utilisez la cible dev du projet :

Terminal window
pnpm nx dev your-project

Si vous avez ajouté plusieurs composants à votre projet (serveurs MCP, agents, etc.), cela les démarre tous. Pour exécuter uniquement ce serveur MCP, ciblez sa cible <your-server-name>-dev :

Terminal window
pnpm nx your-server-name-dev your-project

Le générateur configure une cible nommée <your-server-name>-inspect, qui démarre votre serveur MCP localement (via la cible <your-server-name>-dev, y compris toutes les dépendances connectées telles qu’une base de données locale) et lance l’inspecteur MCP préconfiguré pour s’y connecter via le transport HTTP Streamable.

Terminal window
pnpm nx your-server-name-inspect your-project

Cela démarrera l’inspecteur à http://localhost:6274. Commencez en cliquant sur le bouton « Connect ».

Le moyen le plus simple de tester et d’utiliser un serveur MCP est d’utiliser l’inspecteur ou de le configurer avec un assistant IA (comme ci-dessus).

Vous pouvez cependant exécuter votre serveur avec le transport STDIO directement en utilisant la cible <your-server-name>-serve-stdio.

Terminal window
pnpm nx your-server-name-serve-stdio your-project

Cette commande utilise tsx --watch pour redémarrer automatiquement le serveur lorsque les fichiers changent.

Si vous souhaitez exécuter votre serveur MCP localement en utilisant le transport HTTP Streamable, vous pouvez utiliser la cible <your-server-name>-serve.

Terminal window
pnpm nx your-server-name-serve your-project

Cette commande utilise tsx --watch pour redémarrer automatiquement le serveur lorsque les fichiers changent.

infra = agentcore | agentcore-ecr

Déployer votre serveur MCP sur Bedrock AgentCore Runtime

Section intitulée « Déployer votre serveur MCP sur Bedrock AgentCore Runtime »

Si vous avez sélectionné agentcore ou agentcore-ecr pour infra, l’infrastructure CDK ou Terraform pertinente est générée et vous pouvez l’utiliser pour déployer votre serveur MCP sur Amazon Bedrock AgentCore Runtime.

Un construct CDK est généré pour votre serveur MCP, nommé en fonction du name que vous avez choisi lors de l’exécution du générateur, ou <ProjectName>McpServer par défaut.

Vous pouvez utiliser ce construct CDK dans une application CDK :

import { MyProjectMcpServer } from '@my-scope/common-constructs';
export class ExampleStack extends Stack {
constructor(scope: Construct, id: string) {
// Add the MCP server to your stack
new MyProjectMcpServer(this, 'MyProjectMcpServer');
}
}

Le générateur fournit une option auth pour configurer l’authentification de votre serveur MCP. Vous pouvez choisir entre l’authentification IAM (par défaut) ou Cognito lors de la génération de votre serveur MCP.

Par défaut, votre serveur MCP sera sécurisé à l’aide de l’authentification IAM, déployez-le simplement sans aucun argument :

import { MyProjectMcpServer } from '@my-scope/common-constructs';
export class ExampleStack extends Stack {
constructor(scope: Construct, id: string) {
new MyProjectMcpServer(this, 'MyProjectMcpServer');
}
}

Vous pouvez accorder l’accès pour invoquer votre serveur MCP sur Bedrock AgentCore Runtime en utilisant la méthode grantInvokeAccess. Par exemple, vous pouvez souhaiter qu’un agent généré avec le générateur py#agent appelle votre serveur MCP :

import { MyProjectAgent, MyProjectMcpServer } from '@my-scope/common-constructs';
export class ExampleStack extends Stack {
constructor(scope: Construct, id: string) {
const agent = new MyProjectAgent(this, 'MyProjectAgent');
const mcpServer = new MyProjectMcpServer(this, 'MyProjectMcpServer');
mcpServer.grantInvokeAccess(agent);
}
}

Lorsque vous sélectionnez l’authentification Cognito, le générateur configure le serveur MCP pour utiliser Cognito pour l’authentification.

Le construct généré accepte une prop identity qui configure l’authentification Cognito :

import { MyProjectMcpServer, UserIdentity } from '@my-scope/common-constructs';
export class ExampleStack extends Stack {
constructor(scope: Construct, id: string) {
const identity = new UserIdentity(this, 'Identity');
new MyProjectMcpServer(this, 'MyProjectMcpServer', {
identity,
});
}
}

Le construct UserIdentity peut être généré en utilisant le générateur ts#website#auth, ou vous pouvez créer vos propres UserPool et UserPoolClient CDK.

Le générateur configure automatiquement une cible bundle qui utilise Rolldown pour créer un package de déploiement :

Terminal window
pnpm nx bundle <project-name>

La configuration de Rolldown se trouve dans rolldown.config.ts, avec une entrée par bundle à générer. Rolldown gère la création de plusieurs bundles en parallèle s’ils sont définis.

La cible de bundle utilise http.ts comme point d’entrée pour le serveur MCP HTTP Streamable à héberger sur Bedrock AgentCore Runtime.

infra = agentcore

Le générateur configure une cible <your-server-name>-package qui assemble le package de code déployable : le index.js regroupé plus une installation vendorisée de AWS Distro for OpenTelemetry, qu’AgentCore exige d’être présent dans le package. L’infrastructure générée télécharge ce répertoire sous forme de .zip — via AgentRuntimeArtifact.fromCodeAsset sous CDK, ou archivé dans le bucket d’actifs partagé sous Terraform.

infra = agentcore-ecr

Le générateur configure une cible <your-server-name>-docker qui copie le Dockerfile depuis le répertoire source de votre serveur MCP dans le répertoire de sortie du bundle. Cela co-localise le Dockerfile avec les artefacts regroupés, permettant à CDK de construire l’image Docker directement en utilisant AgentRuntimeArtifact.fromAsset.

Une cible docker est également générée qui prépare le contexte docker pour tous les serveurs MCP si vous en avez plusieurs définis.

L’image Docker construite pour ce projet peut être analysée pour détecter les vulnérabilités à l’aide de Trivy, exécuté depuis l’image Trivy hébergée sur ECR.

Une cible trivy est ajoutée à votre projet qui analyse l’image construite et se termine avec un code non nul si une vulnérabilité de gravité HIGH ou CRITICAL est trouvée. Le Dockerfile généré utilise une image de base sans vulnérabilité corrigeable connue de ces gravités au moment de la génération, et met à niveau les outils fournis (tels que npm) pour maintenir cet état.

L’analyse utilise le même moteur de conteneur que votre construction d’image (docker ou finch), donc aucun outillage supplémentaire n’est requis. L’analyse n’est pas mise en cache, car l’image qu’elle lit se trouve dans le moteur de conteneur plutôt que sur le disque — elle analyse donc toujours l’image réelle et échoue bruyamment plutôt que de signaler un succès mis en cache pour une image qui n’est plus là. Chaque exécution prend donc des dizaines de secondes par image et actualise la base de données de vulnérabilités de Trivy, elle nécessite donc un accès réseau. Le script racine trivy fourni analyse chaque image dans l’espace de travail :

Terminal window
pnpm trivy

Il peut y avoir des cas où vous souhaitez supprimer une vulnérabilité spécifique, par exemple lorsqu’aucun correctif n’est encore disponible et que vous avez évalué le risque comme acceptable.

Ajoutez l’ID de vulnérabilité (un par ligne) au fichier .trivyignore à la racine de votre projet (c’est-à-dire à côté de votre project.json) :

.trivyignore
# node-tar arbitrary file write - not exploitable in our usage
CVE-2024-XXXXX

Pour plus de détails sur le filtrage des résultats, consultez la documentation de filtrage Trivy.

Votre serveur MCP est automatiquement configuré avec l’observabilité en utilisant AWS Distro for Open Telemetry (ADOT), en configurant l’auto-instrumentation dans votre Dockerfile.

Vous pouvez trouver les traces dans la console AWS CloudWatch, en sélectionnant « GenAI Observability » dans le menu. Notez que pour que les traces soient remplies, vous devrez activer Transaction Search.

Pour plus de détails, consultez la documentation AgentCore sur l’observabilité.

Utilisez le générateur connection pour intégrer ce projet avec d’autres dans votre espace de travail. Les connexions suivantes impliquent ce projet :

Strands AgentsTypeScriptModel Context Protocol
TypeScript Agent to MCPConnect a TypeScript Agent to an MCP server
Strands AgentsPythonModel Context Protocol
Python Agent to MCPConnect a Python Agent to an MCP server
Model Context ProtocolAmazon Aurora
MCP Server to Relational DatabaseConnect a TypeScript MCP Server to an Aurora relational database
Model Context ProtocolAmazon DynamoDB
MCP Server to TypeScript DynamoDBConnect a TypeScript MCP Server to a DynamoDB table
Amazon Bedrock AgentCore GatewayModel Context Protocol
AgentCore Gateway to MCP ServerAggregate an MCP server behind an AgentCore Gateway