Connect MCP servers
Connect an MCP server to the Bub application with the bub-mcp plugin. This guide registers a time server, checks the connection, and calls one of its tools.
The integration uses the app’s plugin system and lifecycle. For tool definitions shared with direct Agent use, see Tools.
Before you begin
Section titled “Before you begin”You need:
- The Bub application, with
bub --helpworking. uvonPATHsouvx mcp-server-timecan launch the time MCP server on demand.- A working model provider if you want to call the MCP tool from a real turn (see the final section).
1. Install bub-mcp
Section titled “1. Install bub-mcp”bub-mcp lives in bubbuild/bub-contrib. Use bub install to resolve names against bub-contrib with an @<ref> suffix:
bub install bub-mcp@main
bub install uses the active Bub environment. See the CLI reference for plugin source and dependency handling.
Agent Plugins can also load skills and their own MCP servers alongside these servers. That integration uses a separate lifecycle channel and plugin-qualified tool names.
Verify the plugin loaded:
bub hooks
You should see mcp listed alongside builtin:
load_state: builtin, mcp
provide_channels: builtin, mcp
register_cli_commands: builtin, mcp
If mcp is missing, the plugin landed outside the environment used by bub.
2. Register the time server
Section titled “2. Register the time server”bub-mcp reads server definitions from ~/.bub/mcp.json (or $BUB_HOME/mcp.json when BUB_HOME is set). Create the file with one entry that launches mcp-server-time over stdio:
mkdir -p ~/.bub
cat > ~/.bub/mcp.json <<'EOF'
{
"mcpServers": {
"time": {
"command": "uvx",
"args": ["mcp-server-time"]
}
}
}
EOF
For stdio servers, command is required; args and env are optional. The presence of command selects stdio; there is no transport field on stdio entries.
3. Verify the server is connected
Section titled “3. Verify the server is connected”bub mcp list
Expected output:
🔌 MCP Tools
- time
Status: Connected
Tools: mcp.time_get_current_time, mcp.time_convert_time
Status: Connected means bub-mcp started the child process, completed the MCP handshake, and discovered the server’s tools. Each remote tool is exposed to Bub under the prefix mcp.<server>_<tool>.
If you see Status: Disconnected, run the launch command directly to debug it:
uvx mcp-server-time
The process should start without exiting. Press Ctrl-C to stop it, fix the underlying issue, then re-run bub mcp list.
4. Use the MCP tool from a running turn
Section titled “4. Use the MCP tool from a running turn”bub mcp list is enough to confirm the integration. Calling the tool from a real turn requires Bub’s channel runtime:
bub chatstarts thecliinterface and automatically attaches enabledLifecycleruntimes, includingmcp.lifecycle.bub gatewaystarts every channel returned by theprovide_channelshook (subject to--enable-channel/BUB_ENABLED_CHANNELS). Withmcp.lifecycleenabled, the channel boots in the background, registers each remote tool into the global tool registry asmcp.<server>_<tool>, and from then on the model can call them.bub runstill does not start channels, so MCP tools discovered throughmcp.lifecycleare not exposed there.
Run the gateway with both the input channel and the MCP lifecycle channel enabled:
bub gateway --enable-channel cli --enable-channel mcp.lifecycle
Wait a few seconds after channel.manager started listening so the MCP bootstrap can complete, then ask Bub a question that needs the time server (for example, What time is it right now in UTC?). The model should call mcp.time_get_current_time and include the result in its reply.
If the model answers without calling the tool, check that server startup has finished, then ask it explicitly to use the time tool. MCP startup runs in the background, so the first turn can begin before the tools are available.
For long-running deployments, see Deploy; the same gateway invocation is what runs in the container image.
Add other server types
Section titled “Add other server types”Edit ~/.bub/mcp.json to add more entries under mcpServers. Each transport has its own shape.
HTTP: url plus transport: "http", with optional headers:
{
"weather": {
"url": "https://weather.example.com/mcp",
"transport": "http"
}
}
SSE: url plus transport: "sse", with optional headers:
{
"events": {
"url": "https://events.example.com/mcp",
"transport": "sse",
"headers": { "Authorization": "Bearer token" }
}
}
Another stdio server: for example, the Node @modelcontextprotocol/server-filesystem over npx. Add allowed directories as positional args, and pass credentials through env:
{
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
}
}
After saving, run bub mcp list to confirm each new server connects.
CLI alternatives
Section titled “CLI alternatives”If you prefer the CLI over editing JSON, bub mcp add writes the same entries:
# stdio
bub mcp add --transport stdio time -- uvx mcp-server-time
bub mcp add --transport stdio --env API_KEY=secret example -- node ./my-server.js
# http / sse
bub mcp add --transport http weather https://weather.example.com/mcp
bub mcp add --transport sse --header "Authorization: Bearer token" \
events https://events.example.com/mcp
# remove
bub mcp remove time
--env is only allowed with --transport stdio; --header is only allowed with --transport http or --transport sse.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Check |
|---|---|
mcp does not appear in bub hooks |
The plugin was installed outside the environment used by bub. Re-install it with the same bub executable. |
bub mcp list reports Status: Disconnected |
Run the configured command (or open the url) outside Bub and confirm it starts cleanly; the error column shows the underlying cause. |
bub mcp add prints CancelledError after Added MCP server … |
The entry may already be written. Use bub mcp list to verify, or edit mcp.json by hand. |
| Tool never called during a turn | Confirm bub mcp list shows Status: Connected and lists the expected tool, then ask a question that clearly maps to that tool. |
Permission denied on mcp.json |
Verify ~/.bub/ is writable, or set BUB_HOME to a directory you own. |
Next steps
Section titled “Next steps”- Load Agent Plugins: load portable skills and MCP servers alongside
mcp.json. - Configure: Bub’s config layer and environment variables.
- bub-mcp source: the plugin’s full source and advanced options.