MAIN MENU
Blog di Devolutions

Annunci, aggiornamenti e approfondimenti di Devolutions.

Devolutions PowerShell Universal and GitHub Copilot illustration for the blog.

Esporre PowerShell Universal come server MCP per l'integrazione con GitHub Copilot

Documenti gli endpoint PSU con New-PSUEndpointDocumentation, generi un proxy MCP con openapi-mcp-generator, aggiunga l'URL SSE in VS Code e chieda a Copilot di elencare o avviare processi.

GitHub Copilot è un assistente IA che può essere eseguito in un editor come Visual Studio Code. Offre il completamento del codice e funzioni di chat per analizzare e generare codice. GitHub Copilot supporta anche la modalità Agent, che consente di comunicare con altri strumenti per eseguire azioni per suo conto. In questo articolo vedremo come esporre PowerShell Universal come strumento perché GitHub Copilot possa eseguire azioni.

Model Context Protocol (MCP)

Il Model Context Protocol, o MCP, è uno standard per esporre strumenti ad agenti IA come Copilot. Analogamente a standard come OpenAPI o il Language Server Protocol in Visual Studio Code, questo standard usa oggetti JSON ed endpoint per fornire a un agente IA i dettagli di uno strumento. Fornendo input e output attesi e le descrizioni dello strumento, i modelli IA possono decidere se usare uno strumento e come usarlo.

I server MCP stanno diventando comuni negli stack software per offrire all’IA modi semplici di interagire con essi. PowerShell Universal non supporta ancora MCP in modo diretto, ma possiamo usare l’implementazione OpenAPI esistente e un progetto open source per ospitare un server proxy MCP. Questo server traduce la specifica OpenAPI in specifica MCP e poi inoltra le richieste MCP alle API corrispondenti.

PowerShell Universal e OpenAPI

Per prima cosa dobbiamo definire un’API e una documentazione API che il proxy MCP possa consumare. In PowerShell Universal creeremo un paio di API per restituire e avviare processi. Queste API sono semplici da implementare, ma usano alcune tecniche PSU per fornire informazioni al motore di generazione della documentazione OpenAPI della piattaforma. Indichiamo i tipi di output degli endpoint e una descrizione per ciascuno, che l’LLM potrà analizzare.

New-PSUEndpoint -Url "/process" -Description "Gets a list of processes running on the PowerShell Universal server." -Method @('GET') -Endpoint {
    <#
.OUTPUTS
200:
  Description: An array of process information.
  Content:
      application/json: ProcessInfo[]

400:
  Description: Invalid input
#>
    param()

    Get-Process | Select-Object Name, Id
} -Documentation "Agent Docs"

New-PSUEndpoint -Url "/process/:name" -Description "Starts a process on the PowerShell Universal server." -Endpoint {
    param(
        [Parameter(Mandatory, HelpMessage = "The file name of the process to start.")]
        $Name
    )

    Start-Process $Name -PassThru | Select-Object Name, Id
} -Documentation "Agent Docs"

Dobbiamo anche creare un documento API per questi endpoint che definisca inoltre una classe con la struttura del nostro output.

New-PSUEndpointDocumentation -Name "Agent Docs" -Definition {
    [Documentation()]
    class ProcessInfo {
        [string]$Name
        [string]$Id
    }
} -Url "/agent-docs" -ContactName "Adam Driscoll" -Version "1.0.0" -LicenseName "MIT"

Dopo aver definito gli endpoint e il documento, possiamo visualizzare la documentazione all’indirizzo http://localhost:5000/swagger/index.html?urls.primaryName=Agent%20Docs.

Inoltre viene creata una specifica OpenAPI JSON.

{
  "openapi": "3.0.4",
  "info": {
    "title": "Agent Docs",
    "contact": {
      "name": "Adam Driscoll"
    },
    "license": {
      "name": "MIT"
    },
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "http://localhost:5000"
    }
  ],
  "paths": {
    "/process": {
      "get": {
        "summary": "",
        "description": "Gets a list of processes running on the PowerShell Universal server.",
        "requestBody": {
          "description": "Error processing input types. Cannot perform runtime binding on a null reference",
          "content": { }
        },
        "responses": {
          "200": {
            "description": "An array of process information.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ProcessInfo"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          }
        }
      }
    },
    "/process/{name}": { }
  },
  "components": {
    "schemas": {
      "ProcessInfo": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "nullable": true
          },
          "id": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      }
    },
    "securitySchemes": {
      "Bearer": {
        "type": "http",
        "description": "App Token for accessing the API",
        "scheme": "bearer",
        "bearerFormat": "JWT"
      }
    }
  },
  "security": [
    {
      "Bearer": [ ]
    }
  ],
  "tags": [
    {
      "name": "default"
    }
  ]
}

Gli LLM sono molto bravi ad analizzare schemi come questo, ma possiamo semplificare ulteriormente mettendo un proxy MCP davanti alla documentazione API, così strumenti come GitHub Copilot scoprono facilmente gli strumenti.

Proxy MCP

Useremo il pacchetto npm openapi-mcp-generator per generare un server proxy MCP per la nostra API. Occorre avere Node.js installato. Per installare il pacchetto, usi il comando seguente.

npm install -g openapi-mcp-generator

Poi dobbiamo generare il proxy del server MCP in base alla nostra API. Questo genera file TypeScript che poi possono essere transpilati ed eseguiti in Node.js. Quanto segue legge la documentazione OpenAPI, poi compila e avvia il server MCP.

openapi-mcp-generator --input http://localhost:5000/agent-docs --output .\mcp --base-url http://localhost:5000 --transport web
cd .\mcp
npm i
npm run build
npm run start:web

GitHub Copilot

Ora che le API di PowerShell Universal sono definite e il server proxy MCP è in esecuzione, possiamo configurare GitHub Copilot. Occorre avere l’estensione installata prima di continuare. In VS Code, prema Ctrl+Shift+P e cerchi MCP: Add Server....

Selezioni l’opzione HTTP e inserisca l’URL del server MCP. Occorre il percorso /sse. L’URL completo, per impostazione predefinita, è http://localhost:3000/sse. Assegni al server il nome che preferisce.

Il contenuto risultante di settings.json sarà simile a questo.

"mcp": {
    "servers": {
        "PSU": {
            "url": "http://localhost:3000/sse"
        }
    }
}

Usare lo strumento agente IA di PowerShell Universal

Con tutto configurato, possiamo usare il nostro strumento agente IA. Faccia clic sull’icona Copilot e apra una nuova chat.

Visual Studio Code Copilot chat panel ready for a new conversation.
Chat Copilot in VS Code

Nella finestra di chat può chiedere a Copilot, ad esempio: Can you please list all the processes as an array of strings in a new PowerShell script? Copilot chiamerà il nostro strumento PSU, recupererà l’elenco dei processi e poi genererà uno script PowerShell in VS Code.

GitHub Copilot generating a PowerShell script from PowerShell Universal process data.
Copilot elenca i processi tramite lo strumento PowerShell Universal

Poiché abbiamo anche un endpoint per avviare processi, può chiedere a Copilot di farlo con una frase come: Can you start a new process in PowerShell Universal named calc? Questo farà avviare il processo calc.exe, perché l’endpoint PSU verrà chiamato con quell’argomento.

Conclusione

In questo articolo abbiamo visto come creare un server proxy MCP per PowerShell Universal per richiamarlo da GitHub Copilot. Poiché MCP è un protocollo standard, potrebbe anche integrare il server PSU in altri agenti LLM.

Pronto a iniziare a creare? Scarichi PowerShell Universal.