Week 8: MCP Servers & Plugins¶
Teaching Goal¶
Learners should leave this session able to explain MCP vs plugins, add existing MCP servers safely, and design a tiny custom MCP server with one tool and one resource.
Where We Are¶
So far, learners can customize OpenCode from inside the project:
- Commands
- Skills
- Agents
- Multi-agent workflows
This week connects agents to outside systems.
The New Boundary¶
Agents become more useful when they can access external systems.
Examples:
- GitHub
- Notion
- Browser state
- Databases
- Internal APIs
MCP is one standard way to expose those capabilities.
What Is MCP?¶
MCP means Model Context Protocol.
Simple model:
OpenCode agent -> MCP server -> external system
The MCP server is a bridge. It is not the agent.
MCP Server Examples¶
- GitHub MCP server: read PRs, issues, comments
- Filesystem MCP server: expose a safe directory
- Database MCP server: query development data
- Browser MCP server: inspect UI behavior
- Custom MCP server: expose one internal workflow
The server decides what tools and resources exist.
Tools vs Resources¶
Tool:
Do something.
Resource:
Read something.
Examples:
- Tool:
create_issue_comment - Resource:
pull_request_diff
OpenCode Plugins Are Different¶
MCP extends what the agent can reach.
Plugins extend OpenCode itself.
Plugins can:
- Hook into events
- Modify tool behavior
- Add OpenCode-specific tools
- Integrate telemetry or notifications
MCP vs Plugin¶
| Question | MCP | Plugin |
|---|---|---|
| Main job | Connect external systems | Customize OpenCode |
| Shape | Server process or URL | JS/TS package |
| Scope | Agent capability | OpenCode behavior |
| Portability | MCP-capable clients | OpenCode-specific |
Ask: "external system or OpenCode behavior?"
Config Shape: MCP¶
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"server-name": {
"enabled": true
}
}
}
Each key names one server.
Local Server Example¶
{
"mcp": {
"filesystem": {
"type": "local",
"command": ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/safe/dir"],
"enabled": true
}
}
}
Local server means OpenCode starts a command on your machine.
Remote Server Example¶
{
"mcp": {
"remote-tools": {
"type": "remote",
"url": "https://mcp.example.com/mcp",
"enabled": true
}
}
}
Remote server means OpenCode connects to an HTTP endpoint.
Config Shape: Plugin¶
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-helicone-session", "@my-org/custom-plugin"]
}
Plugins are packages OpenCode loads.
Security Questions¶
Before enabling an MCP server, ask:
- What can it read?
- What can it write?
- Does it touch secrets?
- Can access be scoped?
- Is it maintained?
- What happens if the agent calls the wrong tool?
Begin with read-only access.
Demo Part 1: Wire Existing Server¶
Demo flow:
- Pick a real use case.
- Add the server config.
- Restart OpenCode.
- Ask a bounded prompt.
- Confirm the agent stayed in scope.
Keep the demo small.
Bounded MCP Prompt¶
Use the GitHub MCP server to read PR #42 only.
Do not comment, approve, close, or edit anything.
Return a five-bullet summary of the diff.
The prompt still matters. MCP access does not replace judgment.
Demo Part 2: Tiny Custom Server¶
Design before code:
Server: release-helper
Tool: format_release_note
Resource: release-note-style-guide
Safety: no network, no file writes
One useful tool is enough.
Lab 8.1 Preview¶
Learners wire two existing MCP servers.
Deliverables:
- Use case for each server
- Config snippet
- Safety notes
- Test prompt
- Result summary
Lab 8.2 Preview¶
Learners author a tiny MCP server.
Deliverables:
- One tool
- One resource
- OpenCode config entry
- Test prompt
- Reflection on whether MCP was necessary
Common Confusion¶
"Should this be a skill, command, agent, MCP server, or plugin?"
Decision guide:
- Prompt template -> command
- Reusable knowledge -> skill
- Role and permissions -> agent
- External system -> MCP
- OpenCode behavior -> plugin
Closing Thought¶
MCP makes agents powerful.
Boundaries make that power usable.