Se gestisci molti siti WordPress, sei sempre alla ricerca di un modo semplice per limitare la quantità di tempo che passi ad accedere alle dashboard e a cliccare su una serie di pulsanti.

Gli MCP (Model Context Protocols) hanno fatto molto parlare di sé negli ultimi tempi, e abbiamo deciso di esplorare come gli MCP, insieme alliAPI di Kinsta, possano aiutare un’agenzia che gestisce molti siti web.

In questo articolo, vediamo un esempio pratico di costruzione di un server MCP che collega gli assistenti AI come Claude all’API di Kinsta per gestire le operazioni dell’hosting per WordPress che le agenzie svolgono già ogni giorno.

Cosa stiamo costruendo

Stiamo costruendo un server MCP che espone una serie di strumenti, in modo che gli assistenti AI possano eseguire azioni come:

  • Elencare tutti i siti WordPress in un account
  • Mostrare gli ambienti per un sito specifico
  • Svuotare la cache in un determinato ambiente
  • Clonare un sito esistente per crearne uno nuovo
  • Vedere quali plugin e temi sono obsoleti o vulnerabili
  • Avviare gli aggiornamenti dei plugin su ambienti specifici

Una volta configurato il server, questo viene collegato a un host/client MCP (in questo caso, Claude for Desktop):

Claude chiama gli strumenti MCP per recuperare dati esterni durante un prompt.
Claude chiama gli strumenti MCP per recuperare dati esterni durante un prompt.

Chiama vari strumenti e poi restituisce la seguente risposta:

Claude che visualizza una risposta strutturata generata dai dati degli strumenti recuperati.
Claude che mostra una risposta strutturata generata dai dati degli strumenti recuperati.

I server MCP possono connettersi a qualsiasi client. Qui utilizziamo Claude for Desktop per semplicità, ma lo stesso server può essere utilizzato con altri strumenti come Cursor, ChatGPT, o anche un client MCP personalizzato costruito nel proprio flusso di lavoro.[/nota]

Come iniziare

Prima di addentrarci nel codice, è utile comprendere alcune nozioni di base su come un MCP si inserisce in questa configurazione.

Un server MCP si colloca tra un assistente AI e un’API esistente. Non sostituisce l’API né cambia il suo funzionamento. Al contrario, espone una serie di strumenti che l’AI può chiamare quando necessario. Ogni strumento corrisponde a un’azione specifica, come l’elenco dei siti o la cancellazione della cache del sito.

Quando si pone una domanda all’assistente AI, questo decide se uno di questi strumenti è pertinente. Se lo è, l’assistente chiama lo strumento attraverso il server MCP, il server parla con l’API e il risultato viene restituito come semplice risposta. Nulla viene eseguito automaticamente senza la sua approvazione, e sono disponibili solo gli strumenti che scegli di esporre.

In questo esempio, il server MCP comunica con l’API Kinsta ed espone un insieme limitato di azioni di hosting WordPress. Non è necessaria un’interfaccia utente personalizzata, un’automazione in background o un’impostazione speciale dell’intelligenza artificiale.

Prequisiti

Per seguire il tutorial serviranno:

  • Una configurazione stabile di Node.js
  • Familiarità di base con TypeScript
  • Un account Kinsta con accesso API abilitato
  • La tua chiave API Kinsta e il tuo ID azienda

Hai bisogno di una chiave/token API valida per utilizzare gli endpoint API di Kinsta. Puoi creare o gestire le tue chiavi API in MyKinsta.[/nota]

Non è necessaria alcuna esperienza precedente con MCP e non è necessario costruire o addestrare un modello AI. Ci concentreremo solo sul collegamento di strumenti esistenti.

Impostazione del progetto

Iniziamo creando una nuova directory per il progetto e inizializzando un’applicazione Node.js:

mkdir kinsta-mcp
cd kinsta-mcp
npm init -y

Successivamente, installiamo MCP SDK e la piccola serie di dipendenze che utilizzeremo:

npm install @modelcontextprotocol/sdk zod@3
npm install -D typescript @types/node

Creiamo una struttura di progetto di base:

mkdir src
toccare src/index.ts

Quindi aggiorniamo il package.json in modo che Node possa eseguire il server costruito:

{
  "name": "kinsta-mcp-server",
  "version": "1.0.0",
  "description": "MCP server for managing WordPress sites via the Kinsta API",
  "type": "module",
  "scripts": {
    "build": "tsc"
  },
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.0.0",
    "zod": "^3.24.0"
  },
  "devDependencies": {
    "@types/node": "^22.0.0",
    "typescript": "^5.0.0"
  }
}

Infine, aggiungiamo un tsconfig.json alla root del progetto:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "Node16",
    "moduleResolution": "Node16",
    "outDir": "./build",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

Con questo, siamo pronti per iniziare a costruire il server MCP.

Costruzione del server MCP

Ora che il progetto è impostato, è il momento di costruire il server MCP.

Iniziamo importando i pacchetti necessari e creando l’istanza del server. Poi aggiungiamo un piccolo helper per parlare con l’API. Dopodiché, registriamo gli strumenti che corrispondono direttamente alle azioni di hosting di WordPress.

Importazione dei pacchetti e creazione del server

Apri src/index.ts e aggiungi le seguenti importazioni nella parte superiore del file:

import { McpServer } from “@modelcontextprotocol/sdk/server/mcp.js”;
import { StdioServerTransport } da “@modelcontextprotocol/sdk/server/stdio.js”;
importare { z } da “zod”;

Queste fanno tre cose:

  • McpServer è il server principale che registra gli strumenti e gestisce le richieste del client AI
  • StdioServerTransport consente al server di comunicare tramite input/output standard, che è il modo in cui la maggior parte dei client AI desktop si connette
  • zod è utilizzato per definire e convalidare l’input che ogni strumento accetta

Successivamente, definiamo alcune costanti per l’API e le credenziali:

const KINSTA_API_BASE = "https://api.kinsta.com/v2";
const KINSTA_API_KEY = process.env.KINSTA_API_KEY;
const KINSTA_COMPANY_ID = process.env.KINSTA_COMPANY_ID;

Ora creiamo l’istanza del server MCP:

const server = new McpServer({
  name: "kinsta",
  version: "1.0.0",
});

Il nome è il modo in cui il server appare all’interno di un client MCP. La versione è opzionale, ma utile quando si inizia a iterare.

Aggiungere un helper per le richieste API

La maggior parte degli strumenti che costruiamo deve effettuare richieste HTTP all’API. Piuttosto che ripetere questa logica ovunque, creiamo una singola funzione helper. Aggiungiamola sotto la configurazione del server:

async function kinstaRequest(
  endpoint: string,
  options: RequestInit = {}
): Promise {
  const url = `${KINSTA_API_BASE}${endpoint}`;
  const headers = {
    Authorization: `Bearer ${KINSTA_API_KEY}`,
    "Content-Type": "application/json",
    ...options.headers,
  };

  const response = await fetch(url, { ...options, headers });

  if (!response.ok) {
    const errorText = await response.text();
    throw new Error(`Kinsta API error (${response.status}): ${errorText}`);
  }

  return response.json() as Promise;
}

Implementazione dell’esecuzione degli strumenti

Gli strumenti sono la cosa principale che un server MCP espone. Ogni strumento è una funzione che un assistente AI può chiamare, con la tua approvazione, per eseguire un compito specifico.

In questo server, ogni strumento segue la stessa struttura:

  • Un nome di strumento (come list_sites)
  • Una breve descrizione (che aiuta l’assistente a sapere quando utilizzarlo)
  • Uno schema di input (in modo che lo strumento venga eseguito solo con input validi)
  • Una funzione di gestione (in cui chiamiamo l’API e formattiamo l’output)

Formattiamo le risposte come testo semplice di proposito. Gli assistenti AI funzionano meglio quando gli strumenti restituiscono un output chiaro e leggibile, invece di scaricare JSON grezzi.

Strumento 1: elencare i siti

Questo strumento recupera tutti i siti WordPress sotto il tuo account aziendale. Di solito è la prima cosa che si desidera quando si lavora con più siti, dal momento che la maggior parte delle altre azioni inizia con l’ID del sito.

La risposta dell’API include informazioni di base su ogni sito, quindi definiamo una forma semplice con cui lavorare:

interface Site {
  id: string;
  name: string;
  display_name: string;
  status: string;
  site_labels: Array;
}

interface ListSitesResponse {
  company: {
    sites: Site[];
  };
}

Con questo, possiamo registrare lo strumento:

server.registerTool(
  "list_sites",
  {
    description:
      "Get all WordPress sites for your company. Returns site IDs, names, and status.",
    inputSchema: {},
  },
  async () => {
    const data = await kinstaRequest(
      `/sites?company=${KINSTA_COMPANY_ID}`
    );

    const sites = data.company.sites;

    if (!sites || sites.length === 0) {
      return {
        content: [
          { type: "text", text: "No sites found for this company." }
        ],
      };
    }

    const siteList = sites
      .map((site) => {
        const labels =
          site.site_labels?.map((l) => l.name).join(", ") || "none";

        return `• ${site.display_name} (${site.name})
  ID: ${site.id}
  Status: ${site.status}
  Labels: ${labels}`;
      })
      .join("\n\n");

    return {
      content: [
        {
          type: "text",
          text: `Found ${sites.length} site(s):\n\n${siteList}`,
        },
      ],
    };
  }
);

Questo strumento non richiede alcun input, quindi lo schema di input è vuoto. All’interno del gestore, chiamiamo l’API, verifichiamo se il risultato è vuoto e poi formattiamo la risposta come testo leggibile.

Invece di restituire un JSON grezzo, restituiamo un breve riassunto che funziona bene in un’interfaccia di chat. In questo modo è facile per un assistente AI rispondere a domande come “Quali siti ho?” o “Mostrami tutti i miei siti WordPress” senza alcun parsing aggiuntivo.

Strumento 2: ottenere gli ambienti

Una volta ottenuto l’ID di un sito, il passo successivo più comune è la verifica dei tuoi ambienti. Questo strumento restituisce tutti gli ambienti per un determinato sito, compresi gli ambienti live, staging e premium staging.

interface Environment {
  id: string;
  name: string;
  display_name: string;
  is_premium: boolean;
  primaryDomain?: {
    id: string;
    name: string;
  };
  container_info?: {
    php_engine_version: string;
  };
}

interface GetEnvironmentsResponse {
  site: {
    environments: Environment[];
  };
}

Alcuni campi sono opzionali, come il dominio primario o la versione PHP, quindi sono contrassegnati di conseguenza. Lo strumento stesso prende solo l’ID del sito:

server.registerTool(
  "get_environments",
  {
    description:
      "Get environments (live, staging) for a specific site. Requires the site ID.",
    inputSchema: {
      site_id: z.string().describe("The site ID to get environments for"),
    },
  },
  async ({ site_id }) => {
    const data = await kinstaRequest(
      `/sites/${site_id}/environments`
    );

    const envs = data.site.environments;

    if (!envs || envs.length === 0) {
      return {
        content: [
          { type: "text", text: "No environments found for this site." }
        ],
      };
    }

    const envList = envs
      .map((env) => {
        const domain = env.primaryDomain?.name || "No domain";
        const php = env.container_info?.php_engine_version || "Unknown";
        const type = env.is_premium
          ? "Premium Staging"
          : env.name === "live"
            ? "Live"
            : "Staging";

        return `• ${env.display_name} (${type})
  ID: ${env.id}
  Domain: ${domain}
  PHP: ${php}`;
      })
      .join("\n\n");

    return {
      content: [
        {
          type: "text",
          text: `Found ${envs.length} environment(s):\n\n${envList}`,
        },
      ],
    };
  }
);

Questo è solitamente il passo successivo prima di azioni come la cancellazione della cache, la clonazione di un sito o l’aggiornamento dei plugin.

Strumento 3: svuotare la cache del sito

La cancellazione della cache è un’attività di routine, ma è anche un’operazione asincrona. Quando la avviamo, l’API risponde immediatamente con un ID di operazione, mentre la cancellazione della cache continua in background.

Ecco la definizione del tipo e la funzione tool:

interface OperationResponse {
  operation_id: string;
  message: string;
  status: number;
}

server.registerTool(
  "clear_site_cache",
  {
    description:
      "Clear the cache for a site environment. Requires the environment ID.",
    inputSchema: {
      environment_id: z
        .string()
        .describe("The environment ID to clear cache for"),
    },
  },
  async ({ environment_id }) => {
    const data = await kinstaRequest(
      "/sites/tools/clear-cache",
      {
        method: "POST",
        body: JSON.stringify({ environment_id }),
      }
    );

    return {
      content: [
        {
          type: "text",
          text: `Cache clear initiated!

Operation ID: ${data.operation_id}
Message: ${data.message}

Use get_operation_status to check progress.`,
        },
      ],
    };
  }
);

Invece di attendere il termine dell’operazione, lo strumento restituisce immediatamente l’ID dell’operazione. In questo modo l’interazione è veloce e l’assistente AI può seguire l’operazione in un secondo momento, se necessario.

Strumento 4: clonare un sito

La clonazione di un sito è una di quelle azioni che le agenzie utilizzano di continuo, soprattutto quando si lavora da template o si creano nuovi siti per i clienti. Invece di partire da zero, si prende un ambiente esistente e si crea un nuovo sito basato su di esso.

La risposta utilizza la stessa forma di operazione che abbiamo visto in precedenza, quindi non è necessario definirla di nuovo. Lo strumento richiede un nome di visualizzazione per il nuovo sito e l’ID dell’ambiente da cui clonare:

server.registerTool(
  "clone_site",
  {
    description:
      "Clone an existing site environment to create a new site. Great for spinning up new client sites from a template.",
    inputSchema: {
      display_name: z
        .string()
        .describe("Name for the new cloned site"),
      source_env_id: z
        .string()
        .describe("The environment ID to clone from"),
    },
  },
  async ({ display_name, source_env_id }) => {
    const data = await kinstaRequest(
      "/sites/clone",
      {
        method: "POST",
        body: JSON.stringify({
          company: KINSTA_COMPANY_ID,
          display_name,
          source_env_id,
        }),
      }
    );

    return {
      content: [
        {
          type: "text",
          text: `Site clone initiated!

New site: ${display_name}
Operation ID: ${data.operation_id}
Message: ${data.message}

Use get_operation_status to check progress.`,
        },
      ],
    };
  }
);

Questo strumento è particolarmente utile se abbinato ad altri strumenti. Ad esempio, un assistente AI può clonare un sito e poi elencare immediatamente gli ambienti o controllare lo stato dei plugin una volta completata l’operazione.

Strumento 5: ottenere lo stato dell’operazione

Poiché alcune azioni vengono eseguite in modo asincrono, abbiamo bisogno di un modo per verificarne l’avanzamento. Ecco a cosa serve questo strumento.

interface OperationStatusResponse {
  status?: number;
  message?: string;
}

server.registerTool(
  "get_operation_status",
  {
    description:
      "Check the status of an async operation (cache clear, site clone, etc.)",
    inputSchema: {
      operation_id: z
        .string()
        .describe("The operation ID to check"),
    },
  },
  async ({ operation_id }) => {
    const response = await fetch(
      `${KINSTA_API_BASE}/operations/${encodeURIComponent(operation_id)}`,
      {
        headers: {
          Authorization: `Bearer ${KINSTA_API_KEY}`,
        },
      }
    );

    const data: OperationStatusResponse = await response.json();

    if (response.status === 200) {
      return {
        content: [
          {
            type: "text",
            text: `Operation completed successfully!

Message: ${data.message || "Operation finished"}`,
          },
        ],
      };
    }

    if (response.status === 202) {
      return {
        content: [
          {
            type: "text",
            text: `Operation still in progress...

Message: ${data.message || "Processing"}`,
          },
        ],
      };
    }

    return {
      content: [
        {
          type: "text",
          text: `Operation status: ${response.status}

Message: ${data.message || "Unknown status"}`,
        },
      ],
    };
  }
);

Strumento 6: ottenere i plugin in tutti i siti

Quando si gestiscono molti siti WordPress, i plugin sono di solito il motivo per cui le cose iniziano ad andare alla deriva. Questo strumento risolve il problema esaminando i plugin nell’intero account aziendale, non un sito alla volta.

L’API restituisce molte informazioni, tra cui gli ambienti in cui è installato ogni plugin, se sono disponibili aggiornamenti e se una versione è contrassegnata come vulnerabile. Per lavorare con questi dati, definiamo le seguenti forme:

interface PluginEnvironment {
  id: string;
  site_display_name: string;
  display_name: string;
  plugin_status: string;
  plugin_update: string | null;
  plugin_version: string;
  is_plugin_version_vulnerable: boolean;
  plugin_update_version: string | null;
}

interface Plugin {
  name: string;
  title: string;
  latest_version: string | null;
  is_latest_version_vulnerable: boolean;
  environment_count: number;
  update_count: number;
  environments: PluginEnvironment[];
}

interface GetPluginsResponse {
  company: {
    plugins: {
      total: number;
      items: Plugin[];
    };
  };
}

Lo strumento stesso non richiede alcun input:

server.registerTool(
  "get_plugins",
  {
    description:
      "Get all WordPress plugins across all sites. Shows which plugins have updates available or security vulnerabilities.",
    inputSchema: {},
  },
  async () => {
    const data = await kinstaRequest(
      `/company/${KINSTA_COMPANY_ID}/wp-plugins`
    );

    const plugins = data.company.plugins.items;

    if (!plugins || plugins.length === 0) {
      return {
        content: [
          { type: "text", text: "No plugins found." }
        ],
      };
    }

    const sorted = [...plugins].sort(
      (a, b) => b.update_count - a.update_count
    );

    const pluginList = sorted.slice(0, 20).map((plugin) => {
      const status =
        plugin.update_count > 0
          ? `⚠️ ${plugin.update_count} site(s) need update`
          : "✅ Up to date";

      const vulnerable =
        plugin.is_latest_version_vulnerable ? " 🔴 VULNERABLE" : "";

      return `• ${plugin.title} (${plugin.name})${vulnerable}
  Latest: ${plugin.latest_version || "unknown"}
  Installed on: ${plugin.environment_count} environment(s)
  ${status}`;
    }).join("\n\n");

    const outdatedCount = plugins.filter(
      (p) => p.update_count > 0
    ).length;

    return {
      content: [
        {
          type: "text",
          text: `Found ${data.company.plugins.total} plugins (${outdatedCount} have updates available):\n\n${pluginList}`,
        },
      ],
    };
  }
);

Strumento 7: ottenere temi in tutti i siti

I temi hanno problemi simili a quelli dei plugin, ma spesso vengono controllati ancora meno frequentemente. Questo strumento funziona come quello dei plugin, ma si concentra sui temi di WordPress.

La struttura della risposta rispecchia l’endpoint del plugin, ma con campi specifici per il tema:

interface ThemeEnvironment {
  id: string;
  site_display_name: string;
  display_name: string;
  theme_status: string;
  theme_update: string | null;
  theme_version: string;
  is_theme_version_vulnerable: boolean;
  theme_update_version: string | null;
}

interface Theme {
  name: string;
  title: string;
  latest_version: string | null;
  is_latest_version_vulnerable: boolean;
  environment_count: number;
  update_count: number;
  environments: ThemeEnvironment[];
}

interface GetThemesResponse {
  company: {
    themes: {
      total: number;
      items: Theme[];
    };
  };
}

Strumento 8: aggiornamento di un plugin

Elencare i problemi è utile, ma alla fine è necessario risolverli. Questo strumento consente di aggiornare un plugin specifico su un ambiente specifico.

L’endpoint di aggiornamento restituisce la stessa forma di operazione asincrona utilizzata in precedenza, quindi possiamo saltarla. Ecco la definizione dello strumento:

server.registerTool(
  "update_plugin",
  {
    description:
      "Update a specific plugin to a new version on a site environment.",
    inputSchema: {
      environment_id: z
        .string()
        .describe("The environment ID where the plugin is installed"),
      plugin_name: z
        .string()
        .describe("The plugin name/slug (e.g., 'akismet', 'elementor')"),
      update_version: z
        .string()
        .describe("The version to update to (e.g., '5.3')"),
    },
  },
  async ({ environment_id, plugin_name, update_version }) => {
    const data = await kinstaRequest(
      `/sites/environments/${environment_id}/plugins`,
      {
        method: "PUT",
        body: JSON.stringify({
          name: plugin_name,
          update_version,
        }),
      }
    );

    return {
      content: [
        {
          type: "text",
          text: `Plugin update initiated!

Plugin: ${plugin_name}
Target version: ${update_version}
Operation ID: ${data.operation_id}
Message: ${data.message}

Use get_operation_status to check progress.`,
        },
      ],
    };
  }
);

Come la pulizia della cache e la clonazione del sito, gli aggiornamenti vengono eseguiti in modo asincrono. Restituendo l’ID dell’operazione, l’assistente AI può seguire i progressi, invece di supporre che l’aggiornamento sia terminato all’istante.

Avviare il server

Con tutti gli strumenti registrati, l’ultimo passo è avviare il server MCP e renderlo disponibile a un client AI.

In fondo al file, aggiungiamo la funzione principale che collega il server utilizzando STDIO transport:

async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error("Kinsta MCP Server running on stdio");
}

main().catch((error) => {
  console.error("Fatal error:", error);
  process.exit(1);
});

Questo indica al server MCP di ascoltare le richieste tramite input e output standard. Rende il server individuabile dai client desktop compatibili con MCP.

Un dettaglio importante sono i log. Poiché questo server comunica su STDIO, tutti i log devono andare su stderr. La scrittura su stdout può interferire con i messaggi MCP e interrompere la connessione.

Successivamente, eseguiamo la build del progetto:

npm run build

Questo compila i file TypeScript nella directory di compilazione e rende eseguibile il punto di ingresso.

Una volta terminata la compilazione, il server è pronto per essere lanciato da un client MCP. Puoi accedere al codice completo su GitHub.

Testare il server con Claude for Desktop

Claude for Desktop è attualmente disponibile su macOS e Windows. Se utilizzi Linux, dovrai collegare il server ad un altro assistente AI o costruire un client MCP personalizzato.[/nota]

Per utilizzare il tuo server MCP, Claude for Desktop deve sapere come avviarlo. Apri il file di configurazione di Claude Desktop:

~/Library/Application Support/Claude/claude_desktop_config.json

Crea il file se non esiste già. Se utilizzi VS Code, puoi aprirlo direttamente dal terminale:

code ~/Library/Application\ Support/Claude/claude_desktop_config.json

All’interno del file, aggiungi il tuo server MCP sotto la chiave mcpServers. Ad esempio:

{
  "mcpServers": {
    "kinsta": {
      "command": "node",
      "args": ["/ABSOLUTE/PATH/TO/mcp-server-demo-kinsta-api/build/index.js"],
      "env": {
        "KINSTA_API_KEY": "your-api-key-here",
        "KINSTA_COMPANY_ID": "your-company-id-here"
      }
    }
  }
}

Questa configurazione indica a Claude for Desktop che esiste un server MCP chiamato kinsta, che deve essere lanciato utilizzando Node.js e che il punto di ingresso è il file index.js compilato.

Assicurati che il percorso punti al file compilato nella directory di compilazione, non alla sorgente TypeScript. Salva il file e riavvia Claude for Desktop.

Verificare la connessione

Una volta riavviato Claude, apri una nuova chat. Clicca sull’icona + accanto al campo di immissione, quindi passa il mouse su Connectors. Dovresti vedere il tuo server MCP elencato.

Registrazione di un server MCP in Claude per abilitare l'accesso agli strumenti.
Registrazione di un server MCP in Claude.

Una volta collegato il server, puoi iniziare subito ad utilizzarlo. Claude decide quale strumento utilizzare, passa l’input richiesto e restituisce il risultato come testo normale.

Aggiornamento di un plugin WordPress utilizzando un flusso di lavoro alimentato da MCP in Claude.
Aggiornamento di un plugin WordPress utilizzando un flusso di lavoro alimentato da MCP in Claude.

Un modo diverso di lavorare con gli strumenti che già hai

Ciò che sta cambiando in questo momento non sono gli strumenti. Le API sono sempre API. Le piattaforme di hosting funzionano ancora allo stesso modo. Ciò che sta cambiando è il modo in cui interagiamo con essi.

Gli strumenti di intelligenza artificiale stanno iniziando a essere meno simili a caselle di chat e più a interfacce. Questo server MCP è un piccolo esempio di questo cambiamento. Non introduce nuove funzionalità. Espone quelle esistenti e le adatta al modo in cui le persone lavorano.

La direzione da seguire dipende da te. Puoi scegliere di mantenere le cose semplici e di sola lettura. Puoi aggiungere più automazione con approvazioni e guardrail. Oppure collegare lo stesso server ad altri strumenti del tuo flusso di lavoro.

Quando scopri nuovi strumenti e flussi di lavoro come questo, è importante avere una solida base di hosting. L’ultima cosa che vuoi è perdere tempo a gestire downtime o problemi di prestazioni, invece di costruire e migliorare i tuoi siti.

Kinsta offre un hosting gestito per WordPress che consente ai tuoi siti di funzionare in modo affidabile, anche quando sei offline. Puoi dare un’occhiata ai nostri piani di hosting o parlare con il nostro team di vendita per trovare il piano che fa per te.

Joel Olawanle Kinsta

Joel è uno Frontend developer che lavora in Kinsta come redattore tecnico. È un insegnante appassionato che ama l'open source e ha scritto oltre 200 articoli tecnici principalmente su JavaScript e i suoi framework.