Skip to main content
Glama
README.md
<div align="center">

# ๐Ÿพ copilot-studio-claw

### Give a Copilot Studio agent a machine it can actually operate.

[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
[![Node.js](https://img.shields.io/badge/Node.js-20%2B-339933?logo=node.js&logoColor=white)](https://nodejs.org)
[![MCP](https://img.shields.io/badge/Model_Context_Protocol-Streamable_HTTP-6E56CF)](https://modelcontextprotocol.io)
[![Platform: Windows](https://img.shields.io/badge/Platform-Windows-0078D6?logo=windows&logoColor=white)](#)

</div>

---

## In plain English

A Microsoft **Copilot Studio** agent is great at chatting and reasoning, but on its own it can't
*do* much on a computer โ€” it has no keyboard, no files, no way to run programs.

**copilot-studio-claw gives your agent its own dedicated Windows computer** (a throwaway cloud VM)
and a safe doorway to use it. Once connected, you can ask your agent things like *"set up a Node
project, run the tests, and tell me what failed"* โ€” and it will actually open the machine, install
what it needs, run the commands, and report back.

Think of it as handing your AI assistant the keys to a **sandbox laptop in the cloud**: powerful
inside that laptop, and walled off from everything else.

> [!WARNING]
> This is, quite literally, **a remote Administrator command line exposed to the internet**
> (protected by a secret key). Only ever run it on a **disposable machine** in a **throwaway
> account** โ€” never on anything holding real data, passwords, or production access. See
> [Security](#-security) before you deploy.

---

## Table of contents

- [What you get](#-what-you-get)
- [How it works](#-how-it-works)
- [Quick start](#-quick-start)
  - [1. Deploy the machine (Azure)](#1-deploy-the-machine-azure)
  - [2. Set up the machine](#2-set-up-the-machine)
  - [3. Connect Copilot Studio](#3-connect-copilot-studio)
  - [4. Try it](#4-try-it)
- [Security](#-security)
- [Configuration](#-configuration)
- [The toolbox](#-the-toolbox)
- [Architecture & docs](#-architecture--docs)
- [Uninstall / tear down](#-uninstall--tear-down)
- [Contributing](#-contributing)

---

## โœจ What you get

- **A small set of powerful, general-purpose tools** instead of a fiddly connector per task โ€”
  run commands, run PowerShell, read/write files, run long jobs, and inspect the machine.
- **The agent installs its own software.** Need the Azure CLI, Python, or Playwright? Just ask โ€”
  the agent runs `winget` / `npm` / `pip` itself and keeps going. There's no "add a tool" step.
- **One safe front door.** Everything goes through an authenticated HTTPS endpoint with a real
  TLS certificate โ€” the only thing Copilot Studio needs is a URL and a key.
- **Reproducible from scratch.** One infrastructure script, one setup script, no secrets in the
  repo, everything parameterised.

---

## ๐Ÿงญ How it works

```mermaid
flowchart LR
    A["๐Ÿค– Copilot Studio agent<br/>(GitHub Copilot harness)"] -->|"MCP over HTTPS<br/>secret key in a header"| B["๐Ÿ”’ Caddy ยท :443<br/>automatic TLS"]
    subgraph VM["โ˜๏ธ Dedicated, disposable Windows VM"]
        B -->|"localhost:8787"| C["โš™๏ธ claw-server<br/>(runs as a Windows service)"]
        C --> D["PowerShell ยท CLIs ยท files ยท jobs"]
    end
```

Your agent sends tool requests over HTTPS. **Caddy** answers on port 443 with an automatically
issued Let's Encrypt certificate and forwards to **claw-server**, a small Node.js service that only
listens on `localhost`. claw-server runs the request against the machine โ€” a PowerShell script, a
command, a file operation โ€” and streams back the result. Long tasks become **background jobs** the
agent can poll, so nothing hangs waiting.

**The machine is the security boundary.** Inside it, the agent is an Administrator and that's fine โ€”
it's disposable. Outside it, nothing is granted by default.

---

## ๐Ÿš€ Quick start

**You'll need:** an [Azure](https://azure.microsoft.com) subscription (a throwaway one is ideal),
the [Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli) signed in (`az login`),
and a Copilot Studio agent using the **GitHub Copilot harness**.

The whole thing is three short steps: **deploy a machine โ†’ set it up โ†’ connect Copilot Studio.**

### 1. Deploy the machine (Azure)

Clone the repo and run the deployment script. It creates a resource group, a Windows VM with a
public web address, and a firewall that only opens what's needed (443 for HTTPS, 80 for the
certificate check, and RDP locked to *your* IP).

```powershell
git clone https://github.com/ogradyliam5/copilot-studio-claw
cd copilot-studio-claw

./deploy/azure/deploy-azure.ps1 `
  -DnsLabelPrefix "claw-<something-unique>" `
  -Location "eastus" `
  -RestrictRdpToMyIp
```

When it finishes it prints your machine's address, e.g.
`https://claw-something-unique.eastus.cloudapp.azure.com`.

> [!TIP]
> **If you hit `SkuNotAvailable`,** the default VM size isn't available in your region/subscription
> (common on trial or Dev subscriptions). Add `-VmSize Standard_D2as_v7` โ€” or run
> `az vm list-skus -l eastus --size Standard_D2 --query "[].name"` to see what's on offer โ€” and
> re-run. Any 2-vCPU size is plenty.

### 2. Set up the machine

The deploy step builds the *infrastructure*; this step installs the *software*. Connect to the VM
with **Remote Desktop** (address above, username `clawadmin`, and the password you set), open
**PowerShell 7 as Administrator**, and run:

```powershell
git clone https://github.com/ogradyliam5/copilot-studio-claw C:\claw
cd C:\claw
./deploy/azure/cloud-init/bootstrap-vm.ps1 `
  -Domain "claw-<something-unique>.eastus.cloudapp.azure.com" `
  -Profile developer
```

This installs the tools, builds the server, generates your secret **API key**, and starts
`claw-server` + Caddy as auto-starting Windows services. **It prints the API key once โ€” copy it now.**
(Pick a tool profile: `minimal`, `developer`, `power-platform`, or `full`. The agent can always
install more later.)

Check it's live from your own machine:

```powershell
curl https://claw-<something-unique>.eastus.cloudapp.azure.com/health
# โ†’ {"status":"ok","service":"copilot-studio-claw","version":"0.1.0"}
```

<details>
<summary><strong>Prefer to run it somewhere other than Azure?</strong></summary>

copilot-studio-claw runs on any Windows machine with a public DNS name and a valid TLS certificate.
See [`docs/installation.md`](docs/installation.md) for the manual walkthrough.
</details>

### 3. Connect Copilot Studio

In [Copilot Studio](https://copilotstudio.microsoft.com), open (or create) an agent that uses the
**GitHub Copilot harness**, then:

1. Go to the **Build** tab โ†’ **Tools** โ†’ **Add** โ†’ choose **Model Context Protocol (MCP)**.
2. Fill in the form:
   | Field | Value |
   | --- | --- |
   | **Server name** | `Claw VM` |
   | **Description** | *Operate a dedicated Windows VM: run commands, PowerShell, files, jobs.* |
   | **Server URL** | `https://<your-address>/mcp` |
   | **Authentication** | **API key** |
   | **Parameter type** | **Header** |
   | **Header name** | `x-api-key` |
3. Click **Add**. Copilot Studio connects to the server and lists its tools.
4. When prompted, **Create a new connection** and paste your **API key** into the `x-api-key` field.
5. Confirm all **14 tools** appear (if they do, the handshake worked โœ…), then **Save**.

> The first time the agent uses a tool, Copilot Studio shows a one-time **"Allow"** consent card โ€”
> approve it to let the agent call the server.

Full details and troubleshooting: [`docs/copilot-studio.md`](docs/copilot-studio.md).

### 4. Try it

Open the **Preview** panel and ask your agent something real:

> *"Check what version of Windows and Node are on the machine."*
>
> *"Create a folder `C:\demo`, write a file `hello.txt` in it, then read it back to me."*
>
> *"Install the Azure CLI, then tell me its version."*
>
> *"Clone github.com/expressjs/express, run `npm install` as a background job, and show me the output when it finishes."*

Paste the ready-made operating instructions from
[`examples/agent-instructions.md`](examples/agent-instructions.md) into your agent's **Instructions**
so it knows to inspect first, install what it needs, use background jobs for slow work, and never
echo secrets.

---

## ๐Ÿ” Security

copilot-studio-claw is deliberately powerful, so the trust model matters. Read this before you
deploy anything real.

- **The endpoint is an authenticated remote Administrator shell.** Anyone with the API key can run
  anything on the VM. Guard the key like a production password โ€” it's never stored in this repo.
- **Use a disposable machine in a throwaway account.** The VM should have **no** subscription-Owner
  rights, **no** Global Admin, and **no** production credentials or SSH keys sitting on it. Any
  external access it needs, you grant deliberately.
- **The firewall is closed by default.** Only 443 (HTTPS) and 80 (certificate issuance) are open to
  the world; RDP is restricted to your IP and is easy to turn off after setup.
- **Secrets stay out of the repo.** `.env` is git-ignored, logs are redacted, and the API key is
  generated on the machine โ€” never committed.

Full trust-boundary model and the roadmap from API-key auth to Microsoft Entra ID:
[`docs/security.md`](docs/security.md).

---

## โš™๏ธ Configuration

Everything is set through environment variables (see [`.env.example`](.env.example)). Sensible
defaults mean you usually only set `API_KEY`.

| Variable | Default | What it does |
| --- | --- | --- |
| `API_KEY` | *(required)* | The secret Copilot Studio must send. Generate with `npm run new-apikey`. |
| `API_KEY_HEADER` | `x-api-key` | Header the key is read from. |
| `PORT` | `8787` | Local port the server listens on (Caddy proxies to it). |
| `HOST` | `127.0.0.1` | Kept on loopback so it's never exposed directly. |
| `MAX_OUTPUT_BYTES` | `200000` | Caps tool output so responses stay within Copilot Studio's limit. |
| `DEFAULT_TIMEOUT_SECONDS` | `60` | Default timeout for a synchronous command. |
| `MAX_TIMEOUT_SECONDS` | `600` | Upper bound a single call may request. |
| `POWERSHELL_PATH` | `pwsh` | PowerShell 7 executable (falls back to Windows PowerShell if absent). |
| `LOG_LEVEL` | `info` | Log verbosity. |

---

## ๐Ÿงฐ The toolbox

A small, general-purpose set on purpose โ€” Copilot Studio limits how many tools an agent can juggle,
so a few powerful ones beat dozens of narrow ones.

| Tool | What it does |
| --- | --- |
| `exec` | Run a program with arguments; returns output, exit code, and duration. |
| `powershell` | Run a (multi-line) PowerShell 7 script. |
| `fs_read` ยท `fs_write` | Read or write a file (text or binary, with byte-range paging). |
| `fs_list` ยท `fs_search` | List a directory or search files/contents. |
| `fs_op` ยท `fs_stat` | Copy / move / delete / mkdir, and get file metadata. |
| `job_start` ยท `job_status` ยท `job_output` ยท `job_cancel` ยท `job_list` | Run and follow long tasks that outlast a single request. |
| `system_info` | Structured machine inspection (OS, hardware, disks, network, ports, runtimes, processes). |

**There is no "install software" tool** โ€” installing is just `exec`/`powershell` running `winget`,
`npm`, `pip`, `dotnet tool install`, or `Install-Module`, the same way a person would.

---

## ๐Ÿ—๏ธ Architecture & docs

| Doc | For |
| --- | --- |
| [`docs/architecture.md`](docs/architecture.md) | The layering, the stateless request lifecycle, the job subsystem, and the adapter seam that lets it target other machines later. |
| [`docs/installation.md`](docs/installation.md) | Azure and manual (any Windows box) setup in depth. |
| [`docs/copilot-studio.md`](docs/copilot-studio.md) | Step-by-step connection guide + a 12-step end-to-end test. |
| [`docs/security.md`](docs/security.md) | The full security model and auth roadmap. |
| [`docs/troubleshooting.md`](docs/troubleshooting.md) | Fixes for the common snags. |
| [`docs/development.md`](docs/development.md) | Build, test, and how to add a new tool. |

**Built with** Node.js + TypeScript, the [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk)
(Streamable HTTP), [Caddy](https://caddyserver.com) for TLS, [WinSW](https://github.com/winsw/winsw)
for the Windows service, and [Bicep](https://learn.microsoft.com/azure/azure-resource-manager/bicep/)
for Azure.

---

## ๐Ÿงน Uninstall / tear down

Remove the whole Azure environment (VM, IP, network, disks) in one command:

```powershell
az group delete --name "copilot-studio-claw-rg" --yes --no-wait
```

To just stop paying for compute while keeping the machine, deallocate it instead:

```powershell
az vm deallocate --resource-group "copilot-studio-claw-rg" --name "claw-vm"
```

To remove only the Windows services (leaving the VM), run
[`scripts/uninstall-service.ps1`](scripts/uninstall-service.ps1) on the VM.

---

## ๐Ÿค Contributing

Contributions welcome! See [`CONTRIBUTING.md`](CONTRIBUTING.md) for setup, the PR flow, and the
one golden rule for new tools (flat input schemas โ€” the reason is explained there). Found a
security issue? Please follow [`SECURITY.md`](SECURITY.md) rather than opening a public issue.

## License

[MIT](LICENSE) ยฉ 2026 Liam O'Grady