# We tried converting Agent Plugins to Microsoft 365 Cowork

> We wanted one portable plugin package to work in Microsoft's background enterprise agent. Microsoft's documented converter broke three ways. The maintained one packaged it. Then it guessed at the part that mattered most.

Published August 13, 2026
Dillon Nys, Member of the Human Staff, Celest

The AI community has collectively decided that MCP servers are the best way for agents to use remote tools. (...right?)

Once every agent client speaks MCP, the next problem is that every client still packages MCP differently. [Agent Plugins](https://agent-plugins.org/) is a new attempt to make that layer portable: one package for Agent Skills and MCP servers, backed by maintainers from Amazon, Cursor, Microsoft, OpenAI, and Vercel.

We wanted to use it with [Microsoft 365 Copilot Cowork](https://learn.microsoft.com/en-us/microsoft-365/copilot/cowork/). Cowork does not consume Agent Plugins, but supports a plugin format which, at least in principle, mirrors an agent plugin. Luckily, Microsoft publishes a PowerShell script that converts Claude Code plugins into Cowork packages, so we thought we'd start there.

But a specification is different than a standard, as we learned.

## A converter should be boring

An Agent Plugin is a small directory:

```text
plugin.json
skills/
mcp.json
```

Cowork asks for the same basic ingredients inside a strict Microsoft 365 app manifest. A converter should preserve the skills and MCP endpoints, write an acceptable zip, and disappear from the story.

And Microsoft had already written 95% of what we needed.

## Microsoft's converter broke three different ways

We downloaded Microsoft's documented [`Convert-ClaudePluginToMOS3.ps1`](https://aka.ms/copilot-cowork-plugin-conversion-script) on August 12, 2026 and gave it one skill, one HTTPS MCP server, and ordinary author metadata.

It failed before producing a zip. Supplying source icons got us a package. Microsoft's validator then failed twice more:

| Attempt | What the official script did | Result |
| --- | --- | --- |
| 1 | Tried to generate a missing `outline.png` with `System.Drawing` | Crashed inside `Windows.Win32.PInvokeGdiPlus` on PowerShell 7/macOS |
| 2 | Wrote `manifest.json` with a UTF-8 byte-order mark | ATK passed the bytes to `JSON.parse`, which rejected its first character |
| 3 | Added `developer.contactInfo` when the plugin author had an email | ATK rejected the object shape during manifest conversion |

It also warned that the generated `packageName` field is deprecated.

Three failures across three different layers: packaging, parsing, schema. We filed [a reproducible issue with the exact script hash and output](https://github.com/OfficeDev/microsoft-365-agents-toolkit/issues/16599).

No worries, we'll whip one up from scratch. Conceptually, all we're doing is copying folders and writing a manifest. And, hey, maybe we can share it with the community if it adds value.

## The plan

Agent Plugins v1.0.0 gave us a cleaner input contract. Most of it mapped without drama:

| Agent Plugin input | Cowork result |
| --- | --- |
| Name, version, description, author | ✅ Microsoft 365 manifest metadata |
| `skills/<name>/SKILL.md` | ✅ Cowork Agent Skills |
| Headerless HTTPS `streamable-http` server | 👌 Remote Cowork MCP connector |
| `stdio` or legacy HTTP+SSE server | 👍 No supported target |
| Literal HTTP headers | 🤨 No faithful Cowork field |

Our rule was simple: translate only what keeps the same meaning. Everything else gets flagged.

Two specs, one hour, we thought.

## The package was portable. Authentication wasn't.

Agent Plugins says literal headers are visible package data and must not contain secrets. It is equally explicit about the larger boundary:

> Agent Plugins 1.0.0 defines no OAuth configuration or portable credential-reference fields. Authorization discovery, user interaction, and credential storage are client-managed.

At this point, I'm starting to wonder which MCP servers will actually fit all these criteria and/or how we suddenly need a lot of user input to faithfully map a single server.

Because on the one hand, leaving auth out of a public plugin spec is justifiable. On the other, it means a converter cannot tell whether a server is public, supports MCP OAuth discovery, needs an API key, or requires a pre-registered OAuth client, and it means there will necessarily be more specs to follow 😅

And Cowork had its own selection of auth choices: `None`, `OAuthPluginVault`, `ApiKeyPluginVault`, or Dynamic Client Registration. The vault modes need something called a `referenceId`, which was an additional layer of abstraction on top of the auth data and used none of the normal suspects like Azure Key Vault.

The PowerShell converter, it turns out, guessed here when converting from Claude plugins. It took any external HTTPS endpoint and turned it into an `OAuthPluginVault`, handing back a plausible-looking `referenceId` whether or not the server could be registered.

It compiled, but didn't work.

So we built the converter, if it still deserves that name: [Agent Plugin CLI](https://github.com/celest-dev/agent-plugin-cli). And since we were more than halfway there already, we turned it into a general-purpose plugin CLI which can convert plugins or create ones from scratch, including generating skills and helping you fill in the blanks for auth.

## Then Microsoft replied

The next morning, an ATK maintainer politely pointed out that the toolkit already had a related command, `atk import openplugin`, and that their team did not maintain the PowerShell script. They also pointed us to [PR #16540](https://github.com/OfficeDev/microsoft-365-agents-toolkit/pull/16540) for the open Agent Plugins v1 work.

Our bad. Microsoft's docs sent us to one converter, and we'd filed its bugs against the team that owned another.

So we gave ATK 1.1.15 the exact same fixture. It generated cross-platform placeholder icons. It wrote BOM-free JSON. It omitted the invalid `contactInfo`. Then `atk package` produced a zip and `atk validate` reported 57 passes and one harmless description warning.

The maintained converter worked for packaging.

Then we opened the connector it generated. Its default `Auto` mode had turned Microsoft's public Learn MCP endpoint into `OAuthPluginVault` and generated `repro-plugin-public-docs-auth` as the `referenceId`. The package was valid. ATK had not created that registration, and the endpoint did not need one.

Passing `--default-auth-type None` fixed this server. It would be the wrong answer for an authenticated one. And a single global default still cannot faithfully describe a plugin containing both.

The open Agent Plugins v1 work in ATK preserves the same heuristic. So we thanked the maintainer, [closed our original issue](https://github.com/OfficeDev/microsoft-365-agents-toolkit/issues/16599#issuecomment-5283529623), and opened [a focused follow-up for unresolved auth](https://github.com/OfficeDev/microsoft-365-agents-toolkit/issues/16606).

The first bug was in a converter owned somewhere else. The deeper problem had reproduced itself in both.

## The missing contract

Agent Plugins does not need to standardize credential storage. It needs a portable way to describe a server's non-secret authentication requirements, or a standard way for clients to negotiate them.

We opened [an Agent Plugins v2 discussion for that missing contract](https://github.com/agentplugins/agent-plugins-spec/issues/55). The answer could be a tiny requirements declaration or capability negotiation. The important part is making the unresolved requirement visible without pretending the credential itself is portable.

The package moved. The authority was guessed.

Oh well. Back to wiring it up by hand until either side can describe the decision without making it for us.

## Sources

- [Agent Plugins](https://agent-plugins.org/) and its [canonical v1.0.0 specification](https://github.com/agentplugins/agent-plugins-spec/blob/main/spec/1.0.0.md).
- [Agent Plugins launch announcement](https://x.com/OpenAIDevs/status/2085398373511918022?s=20).
- [Agent Plugins maintainers](https://github.com/agentplugins/agent-plugins-spec/blob/main/MAINTAINERS.md).
- [Build plugins for Copilot Cowork](https://learn.microsoft.com/en-us/microsoft-365/copilot/cowork/cowork-plugin-development) and Microsoft's [Claude-to-Cowork conversion script](https://aka.ms/copilot-cowork-plugin-conversion-script).
- [ATK Agent Plugins v1 import/export pull request](https://github.com/OfficeDev/microsoft-365-agents-toolkit/pull/16540).
- [Microsoft Teams manifest v1.28 schema](https://developer.microsoft.com/json-schemas/teams/v1.28/MicrosoftTeams.schema.json).
- [MCP authorization specification](https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization).
