Week 8: MCP Servers & Plugins¶
Overview¶
By now, you can shape how OpenCode behaves inside a project. You can write commands, skills, agents, and multi-agent workflows. This week adds a new boundary: tools outside OpenCode.
Modern agents are useful because they can act. They can read files, run commands, call APIs, inspect browser state, query databases, and pull information from external systems. OpenCode supports this kind of extension in two important ways:
- MCP servers expose external tools and resources to the agent.
- OpenCode plugins extend OpenCode itself.
Those sound similar, but they solve different problems. This week is about learning the difference, wiring existing MCP servers safely, and authoring a tiny MCP server of your own.
Concept 1: What Is MCP?¶
MCP stands for Model Context Protocol.
Think of MCP as a standard plug shape for agent tools. Instead of every AI app inventing a custom way to talk to GitHub, Notion, Postgres, a browser, or your internal system, an MCP server exposes tools and resources through a shared protocol.
In plain language:
OpenCode agent -> MCP server -> external system
Examples:
- A GitHub MCP server lets an agent read issues, inspect pull requests, or create comments.
- A filesystem MCP server lets an agent safely access a specific directory.
- A database MCP server lets an agent query a database through controlled tools.
- A custom MCP server can expose one internal company action, such as "look up customer plan by account ID."
The MCP server is not the agent. It is the bridge between the agent and some capability outside the default OpenCode toolset.
Concept 2: Tools And Resources¶
Most MCP servers expose two kinds of things.
Tools¶
A tool is something the agent can call.
Examples:
get_pull_requestcreate_issue_commentquery_databaselookup_customer_plan
Tools usually take arguments and return a result.
Resources¶
A resource is information the agent can read.
Examples:
- A document
- A schema
- A project index
- A status page
- A list of available records
Resources are useful when the agent needs context but should not perform an action.
Simple Rule¶
Use a resource when the agent needs to read.
Use a tool when the agent needs to do.
Concept 3: MCP Servers vs OpenCode Plugins¶
This distinction matters.
MCP Server¶
An MCP server gives the agent access to external tools or resources.
Use MCP when you want OpenCode to reach out to something like:
- GitHub
- Notion
- Postgres
- A browser automation service
- A local script exposed as a tool
- An internal API
MCP is about agent capabilities.
OpenCode Plugin¶
An OpenCode plugin extends or customizes OpenCode itself.
Use a plugin when you want to:
- Hook into OpenCode events
- Modify tool execution behavior
- Add custom tools directly through OpenCode's plugin system
- Integrate session tracking, telemetry, notifications, or workflow behavior
- Package OpenCode-specific behavior for reuse
Plugins are configured in OpenCode's config with a plugin list, for example:
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-helicone-session", "@my-org/custom-plugin"]
}
Plugins are about changing or extending OpenCode.
Comparison¶
| Question | MCP server | OpenCode plugin |
|---|---|---|
| What does it extend? | Agent access to external systems | OpenCode behavior |
| Typical shape | Separate server process or remote endpoint | JavaScript/TypeScript package |
| Good for | GitHub, databases, browser, internal APIs | Hooks, custom behavior, OpenCode-specific tools |
| Who can use it? | Often any MCP-capable client | OpenCode |
| Main risk | Giving the agent too much external access | Changing tool behavior in surprising ways |
If you are unsure which one you need, ask: "Am I connecting to an outside system, or changing OpenCode itself?"
Concept 4: How OpenCode Configures MCP Servers¶
OpenCode config can include an mcp object. Each key is a server name.
The simplest shape looks like this:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"name-of-server": {
"enabled": true
}
}
}
Most real servers need either a local command or a remote URL.
Local MCP Server¶
A local MCP server runs as a command on your machine.
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"filesystem": {
"type": "local",
"command": ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed-dir"],
"enabled": true,
"timeout": 30000
}
}
}
The command starts the server. OpenCode talks to it through standard input/output.
Remote MCP Server (SSE)¶
A remote MCP server runs somewhere else and exposes an HTTP endpoint using Server-Sent Events (SSE). SSE is a standard protocol for streaming data from server to client over HTTP.
{
"$schema": "https://opencode.ai/config.json",
"mcpServers": {
"api-gateway": {
"type": "sse",
"url": "https://mcp.example.com/mcp",
"enabled": true,
"timeout": 30000
}
}
}
SSE servers can also require authentication headers:
{
"mcpServers": {
"team-tools": {
"type": "sse",
"url": "https://mcp.internal.company.com/events",
"headers": {
"Authorization": "Bearer <token>",
"X-Tenant-ID": "engineering"
},
"enabled": true
}
}
}
Do not paste secrets directly into course notes or shared config. Use environment variables or your team's approved secret manager.
When to Use Local vs. SSE¶
| Local (stdio) | Remote (SSE) | |
|---|---|---|
| Where it runs | On your machine, as a child process | On a server, container, or cloud |
| Setup | Install + run a binary | Point to a URL |
| Latency | Low (local process) | Network-dependent |
| Shared access | Per-user | Team-wide |
| Auth | None (local) | Headers or tokens |
| Best for | Personal tools, dev databases | Shared APIs, team infrastructure |
Most beginners start with local MCP servers. SSE becomes useful when you deploy agent tools as a shared team service.
Concept 5: Choosing Existing MCP Servers¶
Start with existing servers before writing your own.
Good candidates for beginners:
- Filesystem server scoped to a safe directory
- GitHub server for issues and pull requests
- Fetch/web server for retrieving public pages
- Browser server for inspecting UI behavior
- Database server against a local development database
Choose servers based on a real workflow, not novelty.
Bad reason:
This server looks powerful.
Good reason:
I open GitHub issues every day while coding. Giving my agent read-only issue access would save context switching.
Concept 6: Security And Boundaries¶
MCP can make agents much more useful. It can also make mistakes more expensive.
Before enabling a server, ask:
- What can this server read?
- What can this server write or mutate?
- Does it have access to secrets?
- Is it local or remote?
- Who maintains it?
- Can I scope it to one repo, one directory, one database, or read-only access?
- What would happen if the agent called the wrong tool?
For this course, prefer read-only or local development access first.
Avoid connecting a beginner workflow directly to production systems.
Concept 7: Authoring A Tiny MCP Server¶
After you wire existing servers, you will write a tiny one.
The smallest useful custom MCP server should expose:
- One tool that performs a simple domain-specific action
- One resource that provides context about that action
Example domain: release notes.
Tool:
summarize_change(type, description) -> formatted release note bullet
Resource:
release-note-style-guide -> rules for tone and format
This is intentionally small. The goal is to learn the shape, not build a production integration.
Walkthrough: Wiring An Existing MCP Server¶
The exact server you choose may differ, but the workflow is consistent.
Step 1: Pick A Use Case¶
Write one sentence:
I want my agent to access <system> so it can <task>.
Example:
I want my agent to access GitHub so it can read PR details during review.
Step 2: Check The Server's Permissions¶
Before adding config, inspect what the server can do.
Prefer:
- Read-only tokens
- Local-only development data
- Narrow directory scopes
- Test repositories
Step 3: Add The Server To OpenCode Config¶
Add an mcp entry to your OpenCode config.
Example local filesystem server:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"course-files": {
"type": "local",
"command": ["npx", "-y", "@modelcontextprotocol/server-filesystem", "./"],
"enabled": true,
"timeout": 30000
}
}
}
Use a safer directory than ./ if your project contains secrets or unrelated files.
Step 4: Restart OpenCode¶
Config changes usually need a restart so OpenCode can load the server.
Step 5: Ask The Agent To Use The Capability¶
Use a prompt that names the capability and the safety boundary.
Use the course-files MCP server to inspect the README only. Do not edit files. Summarize the setup steps in five bullets.
Step 6: Verify The Result¶
Check:
- Did the agent use the intended server?
- Did it stay in scope?
- Did it avoid secrets?
- Did it return useful output?
Walkthrough: Tiny Custom MCP Server Design¶
Before writing code, design the interface.
Use this worksheet:
Server name:
Domain:
Tool name:
Tool input:
Tool output:
Resource name:
Resource content:
Safety boundary:
Example:
Server name: release-helper
Domain: release notes
Tool name: format_release_note
Tool input: change_type, summary
Tool output: one Markdown bullet
Resource name: release-note-style-guide
Resource content: rules for tense, length, and categories
Safety boundary: no network, no file writes
That design is enough for a first server.
When To Use MCP, Plugin, Skill, Command, Or Agent¶
You now know several extension points. Here is the practical decision guide.
| Need | Use |
|---|---|
| Repeat a prompt you invoke manually | Command |
| Give the agent reusable knowledge | Skill |
| Create a role with permissions and behavior | Agent |
| Let the agent call an external system | MCP server |
| Change OpenCode behavior or hook events | Plugin |
Examples:
- "Write release notes from commits" -> command or skill
- "Always review code with a security lens" -> agent
- "Read PR #42 from GitHub" -> MCP server
- "Log every OpenCode session to a dashboard" -> plugin
Summary¶
- MCP is a protocol for giving agents external tools and resources.
- OpenCode plugins customize OpenCode itself.
- Existing MCP servers are the best place to start.
- Local servers run as commands; remote servers run behind URLs.
- Boundaries matter: scope access, prefer read-only, and avoid production systems while learning.
- A tiny custom MCP server should expose one useful tool and one helpful resource.
In the labs, you will wire two existing MCP servers and then author a small custom server that exposes one domain-specific function.