How to Create Custom OpenAI Codex Plugins with @plugin-creator
Problem
My team has a custom deployment pipeline that no generic plugin covers. We deploy to a proprietary internal platform with specific validation steps, rollback procedures, and approval workflows. When I asked Codex to help with deployments, it would suggest generic solutions that didn’t fit our process.
I tried documenting our workflow in comments and README files, but that documentation became stale. Team members would forget steps or use outdated commands. We needed a way to capture this knowledge in a reusable, executable format.
What is @plugin-creator?
@plugin-creator is a tool that helps me prototype Codex plugins locally. It guides through defining skills, configuring MCP integrations, and packaging everything into an installable plugin.
The tool solves this problem: Teams have unique workflows that generic plugins don’t cover. Custom deployment pipelines, proprietary integrations, company-specific coding standards—these require custom solutions.
With @plugin-creator, I can:
- Define skills my plugin provides
- Configure MCP connections to external tools
- Add app integrations for IDE support
- Test locally before sharing
- Package and distribute to team or community
Environment
- Node.js 18+ or Python 3.10+
- Codex CLI installed
- Basic understanding of MCP (Model Context Protocol)
- A workflow you want to automate
Getting Started
First, I installed @plugin-creator:
npm install -g @openai/plugin-creator
# Verify installationplugin-creator --versionI got this output:
@openai/plugin-creator v2.1.0Then I initialized a new plugin project:
plugin-creator init my-deploy-plugin
cd my-deploy-pluginThe tool created this structure:
my-deploy-plugin/├── plugin.json├── skills/│ └── deploy.yaml├── mcp/│ └── servers.json├── integrations/│ └── vscode.json└── README.mdDefining Skills
Skills are the core of a Codex plugin. Each skill defines a capability the plugin provides.
I opened skills/deploy.yaml and defined my deployment skill:
name: deploydescription: Deploy application to internal platform with validation and rollbacktrigger: phrases: - "deploy to staging" - "deploy to production" - "run deployment" patterns: - "deploy.*to.*(staging|production)"steps: - name: validate action: run_command command: npm run validate fail_message: "Validation failed. Check the errors above."
- name: build action: run_command command: npm run build fail_message: "Build failed. Fix the errors before deploying."
- name: notify action: run_command command: ./scripts/notify-team.sh args: environment: "${target_env}"
- name: deploy action: run_command command: ./scripts/deploy.sh args: environment: "${target_env}" version: "${version}"
- name: verify action: run_command command: ./scripts/verify-deployment.sh timeout: 300 fail_message: "Deployment verification failed. Check logs."The skill definition uses trigger phrases and patterns. When I say “deploy to staging,” Codex recognizes this and runs through the steps.
I also added a rollback skill for emergencies:
name: rollbackdescription: Rollback to previous deployment versiontrigger: phrases: - "rollback deployment" - "undo last deploy"steps: - name: confirm action: ask_user message: "Rollback to which version? (last, or specify version tag)"
- name: rollback action: run_command command: ./scripts/rollback.sh args: version: "${user_response}"Configuring MCP Connections
MCP (Model Context Protocol) lets my plugin connect to external tools. I configured connections to our internal systems.
I edited mcp/servers.json:
{ "servers": { "internal-api": { "command": "node", "args": ["./mcp-servers/internal-api/index.js"], "env": { "API_URL": "${INTERNAL_API_URL}", "API_KEY": "${INTERNAL_API_KEY}" } }, "deployment-tracker": { "command": "python", "args": ["./mcp-servers/deployment-tracker/main.py"], "env": { "TRACKER_URL": "${DEPLOYMENT_TRACKER_URL}" } } }}Then I created the MCP server for our internal API:
import { Server } from '@modelcontextprotocol/sdk/server/index.js'import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'import { CallToolRequestSchema, ListToolsRequestSchema,} from '@modelcontextprotocol/sdk/types.js'
const server = new Server( { name: 'internal-api', version: '1.0.0' }, { capabilities: { tools: {} } })
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ { name: 'check_service_status', description: 'Check status of internal services', inputSchema: { type: 'object', properties: { service: { type: 'string', description: 'Service name (api, worker, cache)' } }, required: ['service'] } }, { name: 'get_deployment_history', description: 'Get recent deployment history for a service', inputSchema: { type: 'object', properties: { service: { type: 'string' }, limit: { type: 'number', default: 10 } }, required: ['service'] } } ]}))
server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params
if (name === 'check_service_status') { const status = await fetchServiceStatus(args?.service) return { content: [{ type: 'text', text: JSON.stringify(status, null, 2) }] } }
if (name === 'get_deployment_history') { const history = await fetchDeploymentHistory(args?.service, args?.limit) return { content: [{ type: 'text', text: JSON.stringify(history, null, 2) }] } }
throw new Error(`Unknown tool: ${name}`)})
async function main() { const transport = new StdioServerTransport() await server.connect(transport)}
main().catch(console.error)Adding App Integrations
App integrations let my plugin work with IDEs and other tools. I added VS Code support.
I edited integrations/vscode.json:
{ "commands": [ { "command": "myDeployPlugin.deploy", "title": "Deploy Current Project", "category": "Deploy" }, { "command": "myDeployPlugin.rollback", "title": "Rollback Deployment", "category": "Deploy" } ], "menus": { "commandPalette": [ { "command": "myDeployPlugin.deploy", "when": "workspaceFolderCount > 0" } ] }, "keybindings": [ { "command": "myDeployPlugin.deploy", "key": "ctrl+shift+d", "mac": "cmd+shift+d" } ]}Testing Locally
Before packaging, I tested the plugin locally:
# Install dependenciesnpm install
# Run local testplugin-creator test
# Test specific skillplugin-creator test --skill deployThe test output showed:
Testing plugin: my-deploy-plugin
Skill: deployTrigger: "deploy to staging"
Step 1/5: validate Command: npm run validate Status: PASS
Step 2/5: build Command: npm run build Status: PASS
Step 3/5: notify Command: ./scripts/notify-team.sh Status: PASS
Step 4/5: deploy Command: ./scripts/deploy.sh --env staging Status: PASS
Step 5/5: verify Command: ./scripts/verify-deployment.sh Status: PASS
All tests passed.I also tested the MCP server:
npx mcp-inspector node ./mcp-servers/internal-api/index.tsThe inspector showed:
MCP Inspector running at http://localhost:5173Server connected: internal-api v1.0.0Available tools: - check_service_status - get_deployment_historyPackaging and Distribution
Once tests passed, I packaged the plugin:
plugin-creator package
# Output# Created: my-deploy-plugin-1.0.0.tgzI shared it with my team by publishing to our internal registry:
plugin-creator publish --registry https://plugins.internal.company.comTeam members installed it with:
codex plugin install @company/my-deploy-pluginFor public distribution, I published to the community registry:
plugin-creator publish --publicBest Practices
DO
Start with a clear problem
Define what workflow you’re automating before creating the plugin. My deployment plugin solved a specific problem: our internal deployment process wasn’t captured anywhere.
Test each skill independently
plugin-creator test --skill deployplugin-creator test --skill rollbackUse environment variables for secrets
{ "env": { "API_KEY": "${INTERNAL_API_KEY}" }}Document trigger phrases
Tell your team how to invoke each skill. I added a quick reference to our README:
## Usage
- "deploy to staging" - Deploy to staging environment- "deploy to production" - Deploy to production (requires approval)- "rollback deployment" - Rollback to previous versionDON’T
Don’t hardcode secrets
// WRONGconst apiKey = 'sk-internal-xxxxx'
// CORRECTconst apiKey = process.env.INTERNAL_API_KEYDon’t skip validation steps
Each deployment skill should validate before acting. This prevents bad deployments:
steps: - name: validate action: run_command command: npm run validate fail_message: "Validation failed"Don’t forget error handling
MCP tools should handle errors gracefully:
try { const result = await fetchServiceStatus(service) return { content: [{ type: 'text', text: JSON.stringify(result) }] }} catch (error) { return { content: [{ type: 'text', text: `Error: ${error.message}` }], isError: true }}Don’t make triggers too broad
# WRONG - too broadtrigger: patterns: - "deploy.*"
# CORRECT - specifictrigger: phrases: - "deploy to staging" - "deploy to production"Common Issues
Issue 1: MCP Server Not Connecting
When I ran the test, I got:
Error: MCP server "internal-api" failed to connectThe issue was missing environment variables. I added them to .env:
INTERNAL_API_URL=https://api.internal.company.comINTERNAL_API_KEY=sk-internal-xxxxxThen I loaded them in the test:
plugin-creator test --env-file .envIssue 2: Skills Not Triggering
My skill wasn’t being recognized. I checked the trigger patterns:
# WRONG - pattern didn't match natural languagetrigger: patterns: - "^deploy$"
# CORRECT - includes common phrasestrigger: phrases: - "deploy to staging" - "deploy to production" patterns: - "deploy.*to.*(staging|production)"Issue 3: Package Too Large
When packaging, I got:
Warning: Package exceeds 50MB limitI added files to .pluginignore:
node_modules/*.log.envtests/fixtures/Summary
In this post, I showed how to create custom Codex plugins using @plugin-creator. The key points are:
- Custom plugins capture team-specific workflows in reusable format
- Skills define what the plugin does and when it triggers
- MCP connections let plugins interact with external systems
- Test locally before packaging and distribution
- Use environment variables for secrets, never hardcode them
My deployment plugin transformed our team’s tacit knowledge into an executable workflow. Now when someone says “deploy to staging,” Codex runs through our validation, build, notification, and deployment steps automatically. No more missed steps or outdated documentation.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
- 👨💻 Codex Plugins Documentation
- 👨💻 Model Context Protocol Specification
- 👨💻 Claude Skills GitHub Repository
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments