Hovedmenu
Devolutions-blog

Nyheder, opdateringer og indsigter fra Devolutions.

Devolutions PowerShell Universal and GitHub Copilot illustration for the blog.

Eksponering af PowerShell Universal som MCP-server til integration med GitHub Copilot

Dokumentér PSU-endpoints med New-PSUEndpointDocumentation, generér en MCP-proxy med openapi-mcp-generator, tilføj SSE-URL'en i VS Code, og bed så Copilot om at liste eller starte processer.

GitHub Copilot er en AI-hjælper, der kan køre i en editor som Visual Studio Code. Den giver kodefuldførelse og chatfunktioner til at analysere og generere kode. GitHub Copilot understøtter også Agent-tilstand, som gør det muligt at kommunikere med yderligere værktøjer for at udføre handlinger på dine vegne. I dette indlæg ser vi på, hvordan du eksponerer PowerShell Universal som et værktøj, GitHub Copilot kan bruge til at udføre handlinger.

Model Context Protocol (MCP)

Model Context Protocol, eller MCP, er en standard for at eksponere værktøjer over for AI-agenter som Copilot. I lighed med standarder som OpenAPI eller Language Server Protocol i Visual Studio Code bruger standarden JSON-objekter og endepunkter til at give en AI-agent oplysninger om et værktøj. Ved at angive forventede input og output og beskrivelser af værktøjet kan AI-modeller afgøre, om et værktøj skal bruges, og hvordan det skal bruges.

MCP-servere er ved at blive almindelige, så softwarestakke kan give AI enkle måder at interagere med dem på. PowerShell Universal understøtter endnu ikke MCP direkte, men vi kan bruge den eksisterende OpenAPI-implementering og et open source-projekt til at hoste en MCP-proxyserver. Serveren oversætter OpenAPI-specifikationen til MCP-specifikationen og videresender derefter MCP-anmodninger til de tilhørende API’er.

PowerShell Universal og OpenAPI

Først skal vi definere et API og en API-dokumentation, som MCP-proxyen kan forbruge. I PowerShell Universal opretter vi et par API’er, der returnerer og starter processer. API’erne er enkle at implementere, men de bruger et par PSU-teknikker til at give oplysninger til platformens motor til generering af OpenAPI-dokumentation. Vi angiver outputtyperne for endepunkterne og en beskrivelse af hvert endepunkt, som LLM’en kan analysere.

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"

Vi skal også oprette et API-dokument til endepunkterne, som desuden definerer en klasse med strukturen af vores 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"

Når endepunkterne og dokumentet er defineret, kan vi se dokumentationen på http://localhost:5000/swagger/index.html?urls.primaryName=Agent%20Docs.

Derudover oprettes en OpenAPI-specifikation i 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"
    }
  ]
}

LLM’er er meget gode til at analysere skemaer som dette, men vi kan gøre det endnu lettere ved at lægge en MCP-proxy foran API-dokumentationen, så værktøjer som GitHub Copilot nemt kan opdage værktøjer.

MCP-proxy

Vi bruger npm-pakken openapi-mcp-generator til at generere en MCP-proxyserver til vores API. Det kræver, at Node.js er installeret. Installér pakken med følgende kommando.

npm install -g openapi-mcp-generator

Dernæst skal vi generere MCP-serverproxyen ud fra vores API. Det genererer TypeScript-filer, som derefter kan transpileres og køres i Node.js. Følgende læser OpenAPI-dokumentationen og kompilerer og starter derefter MCP-serveren.

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

Nu hvor vi har defineret vores PowerShell Universal-API’er, og MCP-proxyserveren kører, kan vi konfigurere GitHub Copilot. Du skal have udvidelsen installeret, før du fortsætter. I VS Code trykker du på Ctrl+Shift+P og søger efter MCP: Add Server....

Vælg HTTP-muligheden, og angiv URL’en til MCP-serveren. Du skal bruge ruten /sse. Den fulde URL er som standard http://localhost:3000/sse. Navngiv serveren, som du vil.

Det færdige indhold i settings.json kommer til at se nogenlunde sådan ud.

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

Brug af AI-agentværktøjet i PowerShell Universal

Når alt er konfigureret, kan vi bruge vores AI-agentværktøj. Klik på Copilot-ikonet, og åbn en ny chat.

Chatpanelet i Visual Studio Code Copilot, klar til en ny samtale.
Copilot-chat i VS Code

I chatvinduet kan du spørge Copilot, for eksempel: Kan du liste alle processerne som et array af strenge i et nyt PowerShell-script? Copilot kalder vores PSU-værktøj, henter listen over processer og genererer derefter et PowerShell-script i VS Code.

GitHub Copilot genererer et PowerShell-script ud fra procesdata i PowerShell Universal.
Copilot lister processer via værktøjet i PowerShell Universal

Fordi vi også har et endepunkt til at starte processer, kan du også bede Copilot om det med en sætning som: Kan du starte en ny proces i PowerShell Universal med navnet calc? Det får processen calc.exe til at starte, fordi PSU-endepunktet kaldes med det argument.

Konklusion

I dette indlæg så vi på, hvordan du opretter en MCP-proxyserver til PowerShell Universal, så den kan kaldes fra GitHub Copilot. Fordi MCP er en standardprotokol, kan du også integrere PSU-serveren i andre LLM-agenter.

Klar til at bygge? Download PowerShell Universal.