Skip to content

Skills vs Apps vs MCP Servers in Codex Plugins: What's the Difference?

When I first started building AI workflows with Codex, I kept confusing three things: Skills, Apps, and MCP Servers. I’d put workflow logic in MCP configurations, or try to use Apps when I really needed an MCP Server. My plugins were messy and hard to maintain.

After some trial and error, I finally understood: each component has a clear, distinct responsibility. Let me share what I learned.

The Core Problem

Building AI workflows requires answering three questions:

  1. What should the AI do? (Workflow logic)
  2. Where does it connect? (External services)
  3. How does it extend? (Additional capabilities)

I was trying to answer all three with one component. That doesn’t work.

The Three Components

Here’s the mental model that finally clicked for me:

Component Responsibilities
┌─────────────────────────────────────────────────────────────┐
│ Codex Plugin Package │
├─────────────────┬─────────────────┬───────────────────────┤
│ Skills │ Apps │ MCP Servers │
├─────────────────┼─────────────────┼───────────────────────┤
│ Define WHAT │ Connect WHERE │ Extend HOW │
│ │ │ │
│ Workflow logic │ Service APIs │ Remote tools │
│ Prompts │ Databases │ Shared context │
│ Behavior │ Auth handling │ Cross-session data │
├─────────────────┼─────────────────┼───────────────────────┤
│ SKILL.md │ .app.json │ .mcp.json │
└─────────────────┴─────────────────┴───────────────────────┘

Skills: Define Behavior

Skills describe what the AI agent should do. They’re workflow descriptions stored in a specific structure.

I initially thought Skills were just prompts. But they’re more than that - they support progressive discovery. Agents learn about skills incrementally as they work through a task.

Let me show you a simple example:

skills/code-review/SKILL.md
---
name: code-review
description: Automated code review workflow for pull requests
---
## Workflow
1. Read the changed files from the PR
2. Analyze code quality using linting rules
3. Check for security vulnerabilities
4. Generate review comments with suggestions
## Behavior
- Be constructive, not critical
- Focus on security and performance
- Provide actionable suggestions

The key insight: Skills are discovered by agents, not hard-coded. This makes them flexible and reusable.

Apps: Connect Services

Apps handle external connections. When I need to talk to GitHub, Jira, or a database, I use an App configuration.

Here’s where I went wrong initially: I tried to put API logic inside my Skills. That’s not the right place. Apps are specifically for integration:

.app.json
{
"github": {
"connector": "github-api",
"auth": "oauth",
"capabilities": ["read-repos", "create-prs", "write-issues"]
},
"jira": {
"connector": "jira-cloud",
"auth": "api-key",
"capabilities": ["read-issues", "create-issues"]
}
}

The App handles:

  • Authentication (OAuth, API keys)
  • Connection management
  • Capability scoping

I don’t have to worry about tokens expiring or rate limits in my workflow logic. The App abstraction handles that.

MCP Servers: Extend Capabilities

MCP Servers are the most powerful component. They provide remote tool access and shared context.

This is where I got confused most often. I’d try to use Apps when I really needed MCP Servers. The distinction:

  • Apps: Connect to existing services with known APIs
  • MCP Servers: Provide custom tools and shared state
.mcp.json
{
"mcpServers": {
"database": {
"command": "postgres-mcp-server",
"args": ["--connection-string", "${DB_URL}"],
"env": {
"MAX_CONNECTIONS": "10"
}
},
"shared-context": {
"command": "context-server",
"args": ["--storage-path", "/data/context"]
}
}
}

MCP Servers shine when you need:

  • Custom tools that don’t exist as services
  • Shared context across multiple workflow sessions
  • Stateful operations that persist between runs

A Real Example: Putting It Together

Let me show you how these work together in a real plugin I built.

Scenario: I wanted to create a plugin that reviews pull requests and posts comments.

Step 1 - Define the Skill (what)

skills/pr-review/SKILL.md
---
name: pr-review
description: Review pull requests and post feedback
---
## Workflow
1. Fetch PR changes
2. Analyze code quality
3. Check for security issues
4. Post review comments

Step 2 - Configure the App (where)

.app.json
{
"github": {
"connector": "github-api",
"auth": "oauth",
"capabilities": ["read-prs", "write-reviews"]
}
}

Step 3 - Add MCP Server (how)

.mcp.json
{
"mcpServers": {
"security-scanner": {
"command": "security-mcp-server",
"args": ["--rules", "owasp-top-10"]
}
}
}

Now my Skill can:

  1. Use the GitHub App to fetch PRs and post comments
  2. Use the security-scanner MCP Server for vulnerability detection
  3. Define the workflow logic in the SKILL.md

Each component stays focused. Each can evolve independently.

Common Mistakes I Made

Mistake 1: Putting Workflow Logic in MCP Config

WRONG - Don't do this
{
"mcpServers": {
"review-workflow": {
"steps": ["fetch", "analyze", "post"],
"prompt": "Review this code..."
}
}
}

This belongs in a Skill, not an MCP Server. MCP Servers are for tools, not workflows.

Mistake 2: Using Apps for Custom Tools

I tried to configure a custom code analyzer as an App. But Apps are for existing services with defined APIs. Custom tools should be MCP Servers.

Mistake 3: Overcomplicating Skills

I once wrote a 500-line Skill that handled everything. Bad idea. Skills should describe workflows, not implement them. Keep Skills focused and readable.

When to Use Each Component

Decision Guide
Need to define a workflow? → Skill (SKILL.md)
Need to connect to GitHub/API? → App (.app.json)
Need custom tools or shared state? → MCP Server (.mcp.json)

All three components are optional in a plugin. You can have:

  • A plugin with only Skills (pure workflow descriptions)
  • A plugin with only Apps (just connectors)
  • A plugin with only MCP Servers (just tools)
  • Any combination

This flexibility is powerful. I’ve built plugins ranging from single-file Skills to full packages with all three components.

Why This Separation Matters

Understanding these distinctions helped me:

  1. Organize code better: Each file has a clear purpose
  2. Debug faster: I know where to look for problems
  3. Reuse components: My GitHub App works across multiple Skills
  4. Scale workflows: Adding new capabilities doesn’t require touching existing logic

The architecture cleanly separates concerns. That’s the point.

Key Takeaways

  • Skills = Workflow descriptions (SKILL.md)
  • Apps = Service connectors (.app.json)
  • MCP Servers = Tool providers (.mcp.json)

Choose based on what you’re solving:

  • Defining behavior → Skill
  • Connecting services → App
  • Extending capabilities → MCP Server

Don’t mix responsibilities. Each component has a job. Let it do that job well.

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:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments