← All posts

The Tower of Babylon: One Plugin for Four Coding Agents

AI agentsClaude CodeMCPPlugins

Claude Code, Codex, Kiro, Antigravity: a tale with blueprints for one team plugin marketplace

The Tower of Babylon with four tribes of builders and their familiars

As a technical lead, one of my duties is to provide standards. And now, when we live in the AI era, each company and each team has to deal with the same questions:

  • what coding agent we will use
  • what MCP servers, and with what configuration
  • what skills
  • how to improve team knowledge for local coding agents (this is a topic for the next article)

I could write a boring guide about it. But I am a storyteller, so here is a tale. With blueprints at the end, I promise.

🏗 It all started with a tower

Builders with their familiars on the scaffolding of an unfinished tower

Once upon a time a team of builders decided to build a tower. Not a small one. A tower up to the sky, where every deploy is checked, every dashboard is read and every runbook writes itself.

The builders were not ordinary. Each of them had a familiar, a talking spirit that did the heavy lifting. During the PoC phase everyone picked the familiar they liked, and we forgot to decide on one for all.

So there were four tribes on the scaffolding:

  • the tribe of Claude Code
  • the tribe of Codex
  • the tribe of Kiro
  • the tribe of Antigravity

And somewhere in the shadows, BYOA (bring your own agent). Nobody has seen their familiar. Nobody asks.

For a while everything went fine. The tower grew.

🌩 The morning of confusion

A new builder gets four different answers from four tribes

Then one morning a new builder arrived (or an old one finally decided to configure some MCP and skills) and asked a simple question: “How do I connect my familiar to the cluster?”

He got four answers. One per tribe he asked.

One builder sent a JSON snippet from a chat thread. Another said “copy my config, just change the token”. The third had a skill in his home directory that no one else had ever seen. The fourth spoke a different dialect altogether, so none of the above applied.

You know the old story. Everyone woke up speaking a different language and the construction stopped. In the old story it was the wrath of the gods. In ours, I suspect, somebody just hit the limit of tokens LMAO.

The bricks were fine. Every familiar wanted the same things:

  • 🔌 MCP servers for the systems we run: GitOps, Kubernetes, observability, cloud accounts
  • 📜 Skills: markdown procedures for “how we do X here”
  • 🪝 Hooks: behaviour that must always run
  • 🔑 Settings: URLs, profiles, tokens (only ask during config, never store)

But each one wanted them in its own dialect. Different file names, different config locations, different ways to ask the builder for a token.

🧙 The false prophets

Three prophets offer a wiki page, a dotfiles repo and a shrug

Of course, prophets came. They always come.

The first prophet brought a wiki page with snippets to copy. It was true on the day it was written. Then a server version changed, somebody fixed it locally, and the sacred page quietly became fiction.

The second brought his dotfiles repo. Better, at least it is in git. But it is one man’s layout for one familiar, and tokens sneak into it like mice into a granary.

The third said: “Let everyone figure it out. Temporarily.” We listened to this one the longest. (You know what “temporarily” means in infrastructure.)

📖 The idea (genius one)

One book on a lectern, scribes ready to translate it

One evening, looking at the unfinished tower, I thought: the builders do not need one language. Nobody will give up their familiar, and tomorrow a fifth tribe will come anyway.

They need one book. And scribes who translate it.

  • 📖 The Book: one git repository. A plugin in it is a folder with MCP servers + skills + hooks + the settings to ask the builder for
  • ✍️ The Scribes: an export step that copies each page into the dialect of every tribe. Nobody edits a translation by hand
  • 🚪 The Gatekeeper: CI. It compares each translation with the original and does not let a wrong one through
  • 🧳 The Messenger: a small installer for the tribes whose familiars cannot ask for settings themselves
  • 🔑 The Keys: tokens. Asked for on the builder’s machine, kept there, never written in the Book

And from here, no more magic.

I’m not going to show real code, but I have something better: blueprints to follow.

🛠 Blueprints: acme-platform

All names below are made up, the shape is the real one.

A runnable sample of all this (the plugin, the scribes, the messenger and the gatekeeper) lives here: https://github.com/devops01ua/agent-plugins-sample

# repo layout
agent-plugins/
├── .claude-plugin/
│   └── marketplace.json        # the catalog, written by hand
├── plugins/
│   └── devops/
│       └── acme-platform/
│           ├── .claude-plugin/
│           │   └── plugin.json  # metadata + userConfig
│           ├── .mcp.json        # MCP servers
│           ├── skills/
│           │   └── rollout-check/
│           │       └── SKILL.md
│           ├── hooks/
│           │   ├── hooks.json
│           │   └── remind_notes.py
│           └── README.md
└── scripts/
    └── check.sh                 # the gatekeeper

1) The manifest and the settings

// plugins/devops/acme-platform/.claude-plugin/plugin.json
{
  "name": "acme-platform",
  "version": "0.1.0",
  "description": "Read-only GitOps status MCP for prod and test, a rollout checklist skill, and an end-of-session reminder hook.",
  "author": { "name": "platform-team" },
  "userConfig": {
    "prod_url": {
      "type": "string",
      "title": "GitOps API, prod",
      "description": "Base URL of the prod GitOps API",
      "default": "https://gitops.example.com",
      "required": true
    },
    "prod_token": {
      "type": "string",
      "title": "GitOps API token, prod",
      "description": "Read-only API token",
      "sensitive": true,
      "required": true
    }
  }
}

default holds the team’s real endpoint, so the builder types only the token.

sensitive: true masks the input and keeps the value out of the plain settings file, so the token never gets into the repository.

2) The MCP servers

// plugins/devops/acme-platform/.mcp.json
{
  "mcpServers": {
    "gitops-prod": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "acme-gitops-mcp@1.4.2", "stdio"],
      "env": {
        "GITOPS_BASE_URL": "${user_config.prod_url}",
        "GITOPS_API_TOKEN": "${user_config.prod_token}",
        "MCP_READ_ONLY": "true"
      }
    }
  }
}

The server version is pinned. With @latest every laptop runs something slightly different.

Read-only is the default. Letting a familiar change production is a separate decision with a separate review.

One server per environment (gitops-prod, gitops-test), so both the familiar and the human see which one is being asked.

3) The skill

<!-- plugins/devops/acme-platform/skills/rollout-check/SKILL.md -->
---
name: rollout-check
description: Check a rollout before and after it ships. Use when the user asks
  whether a rollout is safe, why a rollout is stuck, or to verify a release in
  prod or test. Reads sync state and recent events through the GitOps status MCP.
---
# Rollout check
1. Ask which environment. Never assume prod.
2. Read the application state with the `gitops-<env>` server.
3. Compare the desired and the live revision, list what differs.
4. Report: state, differences, last five events. Do not change anything.

The description is the trigger. The familiar reads only this line at startup and decides by it whether to load the rest. With a vague description the skill will never be called.

4) The hook

// plugins/devops/acme-platform/hooks/hooks.json
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          { "type": "command", "command": "python3 \"${CLAUDE_PLUGIN_ROOT}/hooks/remind_notes.py\"" }
        ]
      }
    ]
  }
}

Guidance goes in a skill, behaviour that must always happen goes in a hook. “Please write down what you learned at the end” in a prompt depends on the model remembering it. A hook is run by the harness.

5) The catalog entry

// .claude-plugin/marketplace.json
{
  "name": "acme",
  "owner": { "name": "platform-team" },
  "plugins": [
    {
      "name": "acme-platform",
      "source": "./plugins/devops/acme-platform",
      "description": "Read-only GitOps status MCP, rollout checklist skill, reminder hook.",
      "category": "devops"
    }
  ]
}

One entry per plugin. Keep the entry name and the manifest name the same, otherwise the install command will not find the plugin.

✍️ How the scribes work

Scribes copy the book into four dialects while a gatekeeper checks their work

The files above are what a human writes. Then the scribes produce the rest:

acme-platform/
├── .claude-plugin/plugin.json   # written by hand
├── .mcp.json                    # written by hand
├── plugin.json                  # generated: portable manifest
├── mcp.json                     # generated: servers with ${ACME_...} variables
├── .codex-plugin/plugin.json    # generated
└── codex.mcp.json               # generated

What changes between the dialects is mostly how a setting reaches the server:

// written by hand
"GITOPS_API_TOKEN": "${user_config.prod_token}"
// generated
"GITOPS_API_TOKEN": "${ACME_ACME_PLATFORM_PROD_TOKEN}"

The first form is filled from the agent’s own settings dialog. The second is an environment variable with a predictable name: prefix, plugin, key.

Every generated file carries a marker ("x-generated-by": "..."), and the gatekeeper runs the export in --check mode. If a translation drifts from the original, the pipeline is red.

And the messenger, for the tribes without a settings dialog:

acme-mcp sync                                    # clone or update the checkout
acme-mcp list                                    # plugins and their settings
acme-mcp install --tool codex acme-platform      # prompts, merges, links skills

It merges the servers into the tool’s own config file, replaces servers with the same name and leaves the rest alone. A new plugin needs no change in the messenger, it reads the same two hand-written files.

📦 How each tribe gets the Book

Each tribe receives its own copy of the book

Claude Code

claude plugin marketplace add https://git.example.com/platform/agent-plugins.git
claude plugin install acme-platform@acme

Then, inside a session, /plugin configure acme-platform to enter the settings.

Codex

codex plugin marketplace add https://git.example.com/platform/agent-plugins.git

Then /plugins inside a session.

Kiro

Clone the repo, then: Powers panel, Add Custom Power, Import power from a folder, pick the plugin directory.

Antigravity CLI

agy plugin install ~/agent-plugins/plugins/devops/acme-platform

⚠️ The curses of the tower

Small curses swirl around the scaffolding

No tower is built without curses. Ours were small, and each one cost an evening.

The first curse was four characters long. Without .git at the end of the URL the marketplace was read as a link to a single file, and the answer was Invalid marketplace schema. With .git it is a repository again.

The second: the settings dialog that never came. Installing from the shell does not open it, the plugin panel inside a session does. So the servers start without their values. Install, then configure.

The third came from one of the tribes: their familiar ignores skills that are symlinks. No error, the skill is just absent. The messenger now copies the skills for that tribe and links them for the others.

Some more, shorter:

  • If a familiar can read the Book natively and you also send the messenger, you get every server twice. Pick one path per tribe
  • Hooks travel worse than skills. Ours ship for one tribe so far, the others run the same step as a skill by hand
  • The keys land in different places: the OS credential store with a native install, the tool’s own config file (mode 600) with the messenger

And the last one is about the gatekeeper. It checks layout, frontmatter, catalog parity, versions, translations and secrets. Review still found the same mistakes more than once. Each of them became a new check.

⚡ Epilog

The builders back at work on the tower

The tower is still not up to the sky. But the builders build again.

There are 19 plugins in the Book and four tribes read it. A new builder gets one answer now: the address of the Book. A fix to a server version or a skill is a merge request with a reviewer.

The sre marketplace in Claude Code: 19 available, 19 installed

Installed plugins from the sre marketplace: ArgoCD, Atlassian, AWS, Grafana, Kubernetes MCP and more

And BYOA? Still in the shadows. Nobody has seen their familiar. But I have a feeling the gatekeeper will meet them soon.

In the next tale: how the familiars learned to remember what the builders already knew.

Claude Code

Codex

Kiro

Antigravity

Sample repo

Standards