mcp.connect(address, { headers, client, timeout }) returns a server, over the web
mcp.start(program, { args, env, dir, timeout }) returns a server, a program it starts
server.tools() returns [{ name, does, args }]
server.call(name, { args, responses, state }) returns { content, data }, or { requests, state }
server.close() closes the connection, or stops the program
address is a URL that starts https:// or http://. program is as for exec.run (exec).
Options:
headers headers sent with every request, as written; a value may be a handle
client { id, secret } or { id, key }: signs in with these OAuth client
credentials, each a handle; and scope, if the server wants one
args, env, dir as for exec.run
timeout seconds, or text such as "5m", for connecting and for each call;
default 1m
args the tool's arguments, a map
responses the responses to a server's requests for input, by their names
state the state the server gave with its requests for input
- The plugin speaks MCP 2026-07-28, and the earlier version a server has if it does not speak that one.
- tools gives the server's tools in the form an agent's list: job returns (
Agent). args is the tool's input schema as the server wrote it. Over the web, a tool that marks an argument for a header where no header can carry it is left out. - call gives content as a list: text as text, an image, audio or a file as a blob, and a link as { link, name }. data is the tool's structured content, if it gave one.
- A server that needs input to finish a call gives { requests, state }. The same call made with { responses, state }, in this job or a later one, carries on. The plugin tells a server it takes requests made with a form, and the script gives the responses.
- A job whose output is too large to send fails. A script that gives an agent a tool's result puts a large text into a blob, which the model reads with its blob tools:
text.length > 100000 ? blobs.make(text) : text. - With client, the plugin finds the server's sign-in server from the server, gets a token, and sends it to that server and no other.
- A program the plugin started is stopped when the job ends.
- The plugin follows no redirect, and does not speak the HTTP+SSE transport of MCP 2024-11-05.
Errors:
failedthe tool reported an error, and the message is its text; or the server answered with an error
bad_inputthe server refused the request: a tool it does not have, or arguments it does not take
not_foundthe program was not found
refusedthe server turned the connection or the sign-in away
timeoutthe server did not answer within the timeout
Needs net:host for the server, and with client for its sign-in server; or exec:program for a program. A handle needs one of these.
secret:NAME@net:hostin a header, or a client's secret to the sign-in server
secret:NAME@exec:programin a program's args or env
secret:NAME@*a client's key, which the plugin signs with
This script lists the tools of a server on the web and calls one, with a token in a header.
allow: [net:notes.example.com, "secret:NOTES_TOKEN@net:notes.example.com"]
const server = mcp.connect("https://notes.example.com/mcp", {
headers: { Authorization: secrets.text`Bearer ${secrets.get("NOTES_TOKEN")}` },
})
const names = server.tools().map((tool) => tool.name) // ["add_note", "find_notes"]
return server.call("add_note", { args: { text: "buy tea" } }) // gives { content: ["added"] }This script lists the tools of a server it starts, and calls one.
allow: [exec:notes-server, "secret:NOTES_KEY@exec:notes-server"]
const server = mcp.start("notes-server", { env: { NOTES_KEY: secrets.get("NOTES_KEY") } })
const names = server.tools().map((tool) => tool.name) // ["add_note", "find_notes"]
const found = server.call("find_notes", { args: { text: "tea" } })
server.close()
return found // gives { content: ["2 notes: tea at 4, tea at 5"] }