agentsclimarketplace

Create container plugin mcp

Skill yukihirop/nagi/.claude/skills/create-container-plugin-mcp

Scaffold a new MCP plugin for nagi agent containers. Generates package, Dockerfile entry, and deploy/templates/host/entry.template.ts registration. Triggers on "create mcp plugin", "new mcp plugin", "add mcp", "scaffold mcp".From its SKILL.md

Install
npx -y skills add yukihirop/nagi --skill create-container-plugin-mcp

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

5.5 KB, ~1.5k tokens by cl100k_base, as published. Nobody here has run it

Create MCP Plugin

Step 0: Language selection

Before proceeding with any other steps in this skill, ask the user which language to continue in using AskUserQuestion. Keep this initial prompt in English because the preferred language is not yet known.

  • Question: Which language should I continue in?
  • Options: English, 日本語 (Japanese)

Use the selected language for all subsequent user-facing messages and for every further AskUserQuestion prompt in this skill. Do not translate code, file paths, shell commands, or file contents.

Scaffold a new MCP plugin that runs inside agent containers, following the established pattern (mcp-ollama, mcp-vercel).

UX Note: Use AskUserQuestion for all user-facing questions.

Step 1: Gather information

AskUserQuestion:

  1. Plugin name (lowercase, no mcp- prefix — e.g., "youtube", "github", "notion")
  2. One-line description (e.g., "YouTube analytics and video search")
  3. Does it need an API token/key? If yes, what env var name? (e.g., YOUTUBE_API_KEY)

Step 2: Generate package

Create container/plugins/mcp-{name}/ with three files:

package.json

{
  "name": "@nagi/mcp-{name}",
  "version": "0.0.1",
  "type": "module",
  "main": "dist/index.js",
  "scripts": {
    "build": "tsc",
    "start": "node dist/index.js",
    "lint": "tsc --noEmit"
  },
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.12.1",
    "zod": "^4.3.6"
  },
  "devDependencies": {
    "@types/node": "^22.10.0",
    "typescript": "^5.7.0"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "lib": ["ES2022"],
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

src/index.ts

Generate a starter MCP server with a placeholder tool. Follow this pattern:

/**
 * {Name} MCP Server for Nagi
 * {description}
 */

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

// Read config from environment (passed via entry.ts registerMcpPlugin env option)
const API_TOKEN = process.env.{ENV_VAR} || "";

function log(msg: string): void {
  console.error(`[{NAME_UPPER}] ${msg}`);
}

const server = new McpServer({
  name: "{name}",
  version: "1.0.0",
});

// TODO: Add tools here
server.tool(
  "{name}_hello",
  "A placeholder tool — replace with real functionality",
  {
    message: z.string().describe("A test message"),
  },
  async (args) => {
    log(`Hello: ${args.message}`);
    return {
      content: [{ type: "text" as const, text: `Hello from {name}: ${args.message}` }],
    };
  },
);

const transport = new StdioServerTransport();
await server.connect(transport);
log("{Name} MCP server started");

Replace all {name}, {Name}, {NAME_UPPER}, {description}, {ENV_VAR} placeholders.

If no API token is needed, remove the API_TOKEN line.

Step 3: Add to Dockerfile

AskUserQuestion: Which agent's Dockerfile should include this plugin?

  • Claude Codecontainer/claude-code/Dockerfile
  • Open Codecontainer/open-code/Dockerfile
  • Both — Add to both

Append the following block to the selected Dockerfile before the # Create workspace directories line:

COPY container/plugins/mcp-{name}/package*.json /app/mcp-plugins/{name}/
RUN cd /app/mcp-plugins/{name} && npm install
COPY container/plugins/mcp-{name}/src/ /app/mcp-plugins/{name}/src/
COPY container/plugins/mcp-{name}/tsconfig.json /app/mcp-plugins/{name}/
RUN cd /app/mcp-plugins/{name} && npx tsc

Step 4: Add to deploy/templates/host/entry.template.ts

Add a registerMcpPlugin block to deploy/templates/host/entry.template.ts:

If API token required:

const {name}Env = readEnvFile(["{ENV_VAR}"]);
if ({name}Env.{ENV_VAR}) {
  orchestrator.registerMcpPlugin("{name}", {
    entryPoint: "/app/mcp-plugins/{name}/dist/index.js",
    env: { {ENV_VAR}: {name}Env.{ENV_VAR} },
  });
}

If no API token:

orchestrator.registerMcpPlugin("{name}", {
  entryPoint: "/app/mcp-plugins/{name}/dist/index.js",
});

Step 5: Build & verify

pnpm install
pnpm build

All packages must build successfully.

Step 6: Next steps

Tell the user:

  1. Implement tools — Edit container/plugins/mcp-{name}/src/index.ts to add real MCP tools
  2. Rebuild Docker image./container/claude-code/build.sh and/or ./container/open-code/build.sh
  3. Sync entry.ts — Run /deploy and select Host to add the plugin registration to your local entry.ts
  4. If API token needed — Add {ENV_VAR}=... to .env
  5. Restart nagi — Run /nagi-restart
  6. Test — Send a message in Slack and ask the agent to use the new tools

Reference

Existing MCP plugins to study:

  • container/plugins/mcp-ollama/ — No API token, connects to local service via host.docker.internal
  • container/plugins/mcp-vercel/ — Requires VERCEL_API_TOKEN, calls external REST API

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 326,764. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.