Calling upstream MCP servers — Reference¶
Complete reference for upstream MCP server configuration flags and the JavaScript mcp API.
CLI flags¶
--mcp-server¶
Type: string (repeatable)
Connect one upstream MCP server. May be repeated. All names must be unique across --mcp-server entries and --mcp-config entries combined.
Stdio transport — spawns the command as a child process via the MCP stdio transport:
--mcp-server name=stdio:command:arg1:arg2:...
Arguments after the command are delimited by :. The subprocess inherits the mcp-v8 process environment; additional environment variables can only be set via --mcp-config.
--mcp-server github=stdio:npx:-y:@modelcontextprotocol/server-github
--mcp-server fs=stdio:mcp-filesystem-server:/tmp
SSE transport — connects to an existing MCP server over Server-Sent Events:
--mcp-server name=sse:URL
--mcp-server analytics=sse:http://analytics-mcp.internal:9000/sse
--mcp-config¶
Type: string (file path)
Default: none
Path to a JSON file containing a JSON array of McpServerConfig objects (see schema below). Combined with any --mcp-server entries; all server names must be unique.
--mcp-stubs¶
Type: bool
Default: true
When true, each upstream tool is surfaced in mcp-v8's own list_tools response as a stub tool. Calling a stub tool directly returns a text response instructing the caller to use run_js with mcp.callTool; it does not execute the upstream tool.
When false, upstream tools are not included in list_tools at all. They remain callable from JavaScript via mcp.callTool.
--mcp-stub-prefix¶
Type: string
Default: runjs__
Prefix prepended to every stub tool name. The full stub name format is:
{prefix}{server}__{tool}
The separator between server name and tool name is always __ (two underscores). Changing this prefix has no effect on the JavaScript mcp API; the API always uses the original server and tool names.
--mcp-config JSON schema¶
The file must contain a JSON array. Each element is one of the following object shapes.
Stdio server object¶
{
"name": "<unique-server-name>",
"transport": "stdio",
"command": "<executable>",
"args": ["<arg1>", "<arg2>"],
"env": {
"<ENV_VAR>": "<value>"
}
}
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
name |
string | yes | — | Unique logical name; used in the JS API and in stub tool names |
transport |
"stdio" |
yes | — | Transport discriminator |
command |
string | yes | — | Executable to spawn |
args |
string[] | no | [] |
Command-line arguments passed to the executable |
env |
object (string → string) | no | {} |
Additional environment variables for the subprocess |
SSE server object¶
{
"name": "<unique-server-name>",
"transport": "sse",
"url": "<SSE endpoint URL>"
}
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | Unique logical name; used in the JS API and in stub tool names |
transport |
"sse" |
yes | Transport discriminator |
url |
string | yes | Full URL of the upstream server's SSE endpoint |
JavaScript mcp global¶
The mcp global is injected into every V8 execution when at least one upstream server is configured. It is not available when no upstream servers are connected.
mcp.servers¶
Type: getter property → string[]
Returns an array of the names of all connected upstream MCP servers.
mcp.servers // e.g. ["github", "analytics"]
mcp.listTools([serverName])¶
Type: synchronous function
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
serverName |
string | no | If provided, return only tools for this server. If omitted, return tools for all servers. |
Returns: ToolInfo[]
interface ToolInfo {
server: string; // name of the connected server
name: string; // upstream tool name
description: string | null;
inputSchema: object; // JSON Schema object for the tool's input
}
Examples:
// All tools across all servers
const all = mcp.listTools();
// Tools on one server only
const githubTools = mcp.listTools("github");
Throws an Error if serverName refers to a server that is not connected.
mcp.callTool(serverName, toolName[, args])¶
Type: async function → Promise<CallToolResult>
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
serverName |
string | yes | Name of the connected server to call |
toolName |
string | yes | Name of the tool to invoke |
args |
object | no | Arguments for the tool; must be JSON-serialisable. Omit or pass undefined for tools that take no arguments. |
Returns:
interface CallToolResult {
content: unknown[]; // array of MCP content items from the upstream server
isError: boolean; // true when the upstream tool reported an error
}
Throws McpToolError when the upstream tool returns a result with isError: true.
Throws a TypeError if serverName or toolName is not a string.
Throws an Error if serverName refers to a server that is not connected, if the tool is not found, or if the policy denies the call.
const result = await mcp.callTool("github", "list_issues", {
owner: "acme",
repo: "api",
});
// result.content[0] is a MCP content item, e.g. { type: "text", text: "..." }
McpToolError¶
Thrown by mcp.callTool when the upstream tool returns isError: true.
| Property | Type | Description |
|---|---|---|
name |
"McpToolError" |
Error class name |
message |
string | "mcp.callTool {server}.{tool} failed: {first content text}" |
serverName |
string | Name of the server that was called |
toolName |
string | Name of the tool that was called |
result |
CallToolResult |
The full result object with isError: true |
try {
await mcp.callTool("github", "create_issue", { owner: "acme", repo: "api", title: "Bug" });
} catch (e) {
if (e instanceof McpToolError) {
console.error(e.serverName, e.toolName, e.result);
}
}
Stub tool naming¶
| Component | Value |
|---|---|
| Default prefix | runjs__ |
| Server–tool separator | __ (two underscores) |
| Full pattern | {prefix}{server}__{tool} |
Example: server github, tool create_issue, default prefix → runjs__github__create_issue.
Stub tools carry the same inputSchema as the upstream tool. Their description is replaced with a notice that the tool is a stub and code showing how to call it via mcp.callTool. Annotations from the upstream tool are not included in the stub.
mcp_tools policy input¶
Rego entrypoint: data.mcp.tools.allow
Evaluated on every mcp.callTool call before the upstream server is contacted.
{
"operation": "mcp_call_tool",
"server": "<server-name>",
"tool": "<tool-name>",
"arguments": { ... }
}
arguments is null when no arguments are passed to mcp.callTool.
If the policy returns false, mcp.callTool throws a JavaScript error; the upstream server is not contacted.