← Blog

The Portable Part

August 9, 2026 AIAgentsAsterEngineering

You find a skill you like. It is a folder with a markdown file in it, telling the agent how to do one job well. You install it for one tool. Then you want it in a second tool, so you install it again, somewhere else, under a different name. Then a third.

Nothing about that folder ever changed. Only the address did.

That is what Agent Plugins fixes. It is an open standard for packaging the things that extend an agent, proposed by Vercel and built with AWS, Cursor, GitHub, Microsoft, and OpenAI. Aster reads it as of today.

What the standard is

A plugin is a directory with a manifest at the top:

text
my-plugin/
├── plugin.json
├── skills/
│   └── summarize/
│       └── SKILL.md
└── mcp.json

Two kinds of things live inside. A skill is a set of instructions the agent loads when the task calls for it and ignores the rest of the time. An MCP server is a separate program that hands the agent real tools: a browser, a database client, a search endpoint.

The locations are fixed. Skills are always under skills/, servers are always in mcp.json, and the manifest cannot point somewhere else. That sounds minor. It means every client finds a plugin’s contents the same way, so an author never writes a per-client install path again.

In Aster it is one command:

bash
aster plugins add owner/repo

Publish the folder once and it loads in ChatGPT, Codex, Cursor, Copilot, Kiro, VS Code, and Aster.

Small on purpose

The standard covers Skills and MCP servers. That is all it covers.

You could read that as unfinished. It is the opposite. Skills and MCP are the two pieces every agent already had in common, and both already had specs of their own. Everything else that extends an agent, commands and hooks and sub-agents, still works differently in every tool. Writing those into a standard now would freeze one tool’s habits into everyone else’s contract.

So the spec waits. The steering committee can add component types later, once the shapes agree. Vercel’s own phrase for it is “small on purpose”, and I think that is right.

For Aster it means a plugin brings skills and servers, and nothing else changes. The 18 built-in skills, sub-agents, project memory, and the sandbox around every command are all still Aster’s own. A standard was never going to carry those.

The rules that look boring

The parts of a spec that read as tedious are usually the parts doing the work. Here it is the failure rules.

Say a plugin ships three skills and one MCP server, and the server is misconfigured. You should still get three skills. The standard is exact about that. One bad skill is skipped. One bad server is skipped. A broken mcp.json turns off that plugin’s servers and leaves its skills alone. Only a broken manifest rejects the whole package.

Most code fails at the outermost level where it notices a problem, which turns one typo into a plugin that does nothing at all. Writing the ladder down means every client fails in the same shape.

There is a containment rule too. Any path inside a plugin has to stay inside that plugin’s folder, checked before the file exists and again after symlinks resolve. A package cannot quietly point a skill at the rest of your disk.

And the manifest is closed. Ten fields are allowed. An unknown field is reported and ignored rather than treated as fatal. Those two rules sound like they argue with each other. Together they are what lets the format grow later without breaking clients that already read it.

Servers you do not run

The other half of this release has nothing to do with plugins.

Until now Aster could only talk to an MCP server it started itself: a child process on your machine, messages passed over its input and output. That covers a lot. It covers nothing that lives on the internet.

Now a server can name a url instead of a command.

yaml
mcp:
  servers:
    deepwiki:
      url: https://mcp.deepwiki.com/mcp

There are two remote shapes. Streamable HTTP is the current one, where each message is a normal POST and the reply comes back either as plain JSON or as a stream. SSE is the older one, deprecated but still deployed, where a single long-lived connection carries every reply and messages go out to an address that connection names.

The useful thing is how little had to change. The conversation is identical in all three cases: same handshake, same tool list, same call. Only the bytes underneath move differently, so that is the only piece I split apart. The session sits on top and does not know which wire it is on.

JSON-RPC sessionhandshake, list, call wire stdioa child process streamable httpa POST per message sseone long connection

You never say which one you mean. A server with a command is local, a server with a url is remote, and nobody’s existing config has to change.

Headers do not travel

One rule is worth pulling out, because it is the kind of thing that goes wrong quietly.

A remote server often needs a header, and that header is often a credential. If the server answers with a redirect and your client follows it anywhere, the credential goes with it, to a host you never named and never approved.

Aster follows a redirect only inside the same origin. Cross that line and the request stops instead. It is a few lines of code and it is the difference between a config file and a leak.

What it does not do

No OAuth. A server that takes a token will take it from your headers. A server that wants you to sign in through a browser reports that it needs auth and stops there. That is a real gap and I would rather name it than let you find it.

The old SSE transport is verified against a test server I wrote, not a public one. I went looking for a live endpoint to point it at and could not find one still standing. DeepWiki answers its SSE address with a 410 and a note telling you to use the other one. That is a deprecated transport doing what deprecated transports do, and it is also why the coverage is what it is.

And Aster claims no corner of the format for itself. The spec lets a client stake out a namespace for its own files inside a plugin. I did not take one, so a plugin never needs an Aster-shaped file to work here.

Install it once

The test that matters is small. Take a plugin someone published for a different agent, install it into Aster, and never once think about the format.

That is the whole feature, and it is the kind you only notice when it is missing.