Ryvos supports two MCP transport protocols: Stdio for local subprocess servers and SSE (Server-Sent Events) for remote HTTP servers. Both use JSON-RPC 2.0 for communication.
Stdio Transport
Stdio is the most common transport. Ryvos spawns the MCP server as a child process and communicates via stdin/stdout using JSON-RPC.
Configuration
[mcp.servers.my-server]
command = "npx" # The command to run
args = ["-y", "@modelcontextprotocol/server-filesystem", "/home/user"]
env = { CUSTOM_VAR = "value" } # Optional environment variablesHow It Works
Ryvos MCP Server (subprocess)
│ │
│──── spawn process ─────────────────>│
│ │
│──── initialize (JSON-RPC) ────────>│
│<─── capabilities ──────────────────│
│ │
│──── tools/list ───────────────────>│
│<─── [tool1, tool2, ...] ──────────│
│ │
│──── tools/call {tool1, input} ────>│
│<─── {result} ─────────────────────│
│ │
Examples
Filesystem
[mcp.servers.filesystem]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/projects"]Provides: read_file, write_file, list_directory, search_files, move_file, create_directory
GitHub
[mcp.servers.github]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-github"]
env = { GITHUB_TOKEN = "${GITHUB_TOKEN}" }Provides: create_issue, list_issues, create_pull_request, search_code, get_file_contents, list_repos
PostgreSQL
[mcp.servers.postgres]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-postgres", "postgresql://user:pass@localhost/mydb"]Provides: query, list_tables, describe_table
Brave Search
[mcp.servers.brave]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-brave-search"]
env = { BRAVE_API_KEY = "${BRAVE_API_KEY}" }Provides: brave_web_search, brave_local_search
Python Server
[mcp.servers.custom]
command = "python"
args = ["-m", "my_mcp_server"]
env = { API_KEY = "${MY_API_KEY}" }Works with any MCP server implemented in Python using the mcp package.
Process Lifecycle
- The subprocess is spawned when Ryvos starts (daemon mode) or on first tool call
- If the process crashes, Ryvos attempts automatic reconnection
- When Ryvos shuts down, the subprocess is terminated gracefully
- Environment variables from the
envmap are merged with the current environment
SSE Transport
SSE (Server-Sent Events) transport connects to remote MCP servers over HTTP. Use this for servers running on other machines or as standalone services.
Configuration
[mcp.servers.remote-tools]
url = "http://localhost:3001/sse"For authenticated servers:
[mcp.servers.remote-tools]
url = "https://mcp.example.com/sse"
headers = { "Authorization" = "Bearer ${MCP_API_KEY}" }How It Works
Ryvos Remote MCP Server
│ │
│──── GET /sse ──────────────────────>│
│<─── SSE event stream ─────────────│
│ │
│──── POST /message (initialize) ───>│
│<─── SSE: capabilities ────────────│
│ │
│──── POST /message (tools/list) ───>│
│<─── SSE: [tool1, tool2, ...] ─────│
│ │
│──── POST /message (tools/call) ───>│
│<─── SSE: {result} ────────────────│
Running a Remote MCP Server
Example using the MCP TypeScript SDK:
const app = express();
const server = new Server({ name: "my-server", version: "1.0.0" }, {
capabilities: { tools: {} }
});
// Register your tools
server.setRequestHandler("tools/list", async () => ({
tools: [{
name: "my_tool",
description: "Does something useful",
inputSchema: { type: "object", properties: { input: { type: "string" } } }
}]
}));
server.setRequestHandler("tools/call", async (request) => {
// Handle tool calls
return { content: [{ type: "text", text: "Result" }] };
});
// Start SSE transport
const transport = new SSEServerTransport("/message", response);
app.get("/sse", (req, res) => transport.handleSSE(req, res));
app.post("/message", (req, res) => transport.handlePostMessage(req, res));
app.listen(3001);Streamable HTTP Transport
Ryvos also supports the newer Streamable HTTP transport (via rmcp 0.16), which combines the simplicity of HTTP with streaming capabilities:
[mcp.servers.streamable]
url = "http://localhost:3001/mcp"
transport = "streamable-http"This transport uses a single HTTP endpoint with streaming responses, simplifying server implementation.
Verifying Connections
After configuring MCP servers, verify they are working:
ryvos mcp listExpected output:
Server: filesystem (stdio) ✓ connected
Tools (6):
mcp__filesystem__read_file
mcp__filesystem__write_file
mcp__filesystem__list_directory
mcp__filesystem__search_files
mcp__filesystem__move_file
mcp__filesystem__create_directory
Server: github (stdio) ✓ connected
Tools (8):
mcp__github__create_issue
mcp__github__list_issues
mcp__github__create_pull_request
...
The ryvos doctor command also checks MCP server connectivity.
Troubleshooting
| Issue | Solution |
|---|---|
| "Failed to spawn MCP server" | Check that the command exists. For npx, ensure Node.js is installed. |
| "Connection refused" (SSE) | Verify the URL and that the remote server is running. |
| "No tools discovered" | The server may not implement tools/list. Check server logs. |
| Tools appear but calls fail | Check the server's error output. For stdio, stderr is captured in Ryvos logs. |
| "timeout" on tool calls | MCP tools have a default 60-second timeout. Check if the server operation is slow. |
| Environment variables not set | Verify the env map in config. Variables use ${VAR} expansion. |
Multiple Servers
You can run multiple MCP servers simultaneously. Each server's tools are namespaced to avoid conflicts:
[mcp.servers.filesystem]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/home/user"]
[mcp.servers.github]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-github"]
env = { GITHUB_TOKEN = "${GITHUB_TOKEN}" }
[mcp.servers.postgres]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-postgres", "postgresql://localhost/mydb"]
[mcp.servers.custom-api]
url = "http://internal-server:3001/sse"All tools from all servers are available to the agent simultaneously.
Next Steps
- MCP Overview — What MCP is and how Ryvos integrates
- Custom Tools — Other ways to extend Ryvos (Skills, Rust Trait)
- Configuration — Full MCP config reference