Corbie

Plugins

mcp

This plugin is a client of an MCP server: it lists the server's tools and calls them.

  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"] }