The MCP endpoint
One endpoint gives an agent every app you have configured, without putting a credential in the agent. Codemode, sign-in and elicitation modes explained.
Executor serves one MCP endpoint at /mcp. Every app you have configured is
reachable through it. You do not add one MCP server per service, and you do not
paste a credential into the agent.
- Hosted:
https://v2.executor.sh/mcp - Self-host:
<your origin>/mcp - Local:
http://127.0.0.1:4312/mcp
The transport is streamable HTTP. See Add an MCP client for the exact setup commands.
The tools
The endpoint does not expose one MCP tool per app tool. However many apps you
add, the tool list stays the same size. When a client connects, the server’s
MCP instructions introduce Executor to the agent. They are the Executor app’s
executor skill, which points to its code-mode and app-authoring skills.
skillsreads the instructions an app ships. Callskills({})for a list of what is visible,skills({ app: "support-inbox" })for one app’s skills, andskills({ app: "support-inbox", name: "triage" })to read one. It connects no account and runs no code.executeruns a JavaScript program over your apps.resumecontinues a program that paused for an approval or for input. It is not present in native mode, where the client answers in place.
Codemode
execute is the way an agent uses your apps. The agent writes a short
JavaScript program; Executor runs it in a sandboxed interpreter and returns what
the program returns.
Inside the program, app tools are ordinary async functions:
return await tools.search({ query: "vercel projects" });
Search returns a page of tools: each one’s exact callable path, the first line
of its description and its input type. Each app and profile is listed once.
next continues to the following page, and
tools.search.describe({ paths }) returns a tool’s whole signature, including
its output type. An app without accounts is called by its slug,
tools.<app>.<tool>. An app with accounts is called through one of your
profiles, which chooses the accounts its tools use:
const projects = await tools.vercel.profiles["<profile-id>"].listProjects({});
return projects.projects.map((project) => project.name);
The agent can call several tools, join the results and return only the part it needs. That is the point: the whole result set never has to pass through the model’s context.
The interpreter has no fetch, no process, no filesystem and no imports. Its
only way out is a tool call, which enters the trusted runtime where your
credentials live. Limits are cooperative, not process isolation. Discovery is
not cached across changes, so run tools.search again in a new execute after
you add or reconfigure an app.
Some limits are fixed by the server and a client cannot raise them: 65,536 characters of program source, 100 tool calls, 5 minutes, and 65,536 bytes of output.
Signing in from the browser
Hosted and self-host use OAuth. Your client registers itself, opens your browser
at /mcp/authorize, and you sign in there. You then choose an organization and
approve the connection. The client receives a token; it never receives your
password or your accounts.
The grant that comes back is bound to one organization. Switching organization in the dashboard later does not retarget an existing connection, including after the token refreshes. To use a second organization, connect again and approve it separately.
Every request revalidates the token, the approval and your current membership. A revoked grant returns 401. Losing membership returns 403.
The consent screen approves every app available to you. To give an agent less, connect it through a scoped connection instead.
Scoped connections
A scoped connection is a named MCP URL that reaches only what you turned on. Create one under Scoped connections on the dashboard’s Connect page. For each app, choose which of your profiles it runs as, or none for an app without accounts, and which tools it exposes: all tools, read-only tools, or the tools you pick. All and read-only include tools the app adds later. Approval rules still come from each app’s code.
Each connection has its own URL, /mcp?connection=<id>. Add
&elicitation_mode=browser or native to it for another
mode. The client signs in at that URL as above, and its
grant follows the connection: edits apply to connected agents at once, and
revoking the connection revokes every grant issued through it. Personal access
tokens and the local server key are not limited by a connection; they keep full
access at the plain URL.
On hosted and self-host, Connected agents on the same page lists each client you approved, with the apps it can reach, and revokes its grant.
Elicitation modes
When a tool needs an approval, or needs input, Executor has to ask you. Where that question appears depends on the mode, which you pick in the endpoint URL and which is then fixed in the grant.
| Mode | URL | Where you answer |
|---|---|---|
model |
/mcp |
The agent shows you the request and calls resume with your answer. This is the default. |
native |
/mcp?elicitation_mode=native |
Your MCP client’s own prompt. The execute call stays open and continues. There is no resume. |
browser |
/mcp?elicitation_mode=browser |
A signed-in page in your browser. The result carries an approvalUrl; the agent calls resume({ requestId }) to collect your answer. |
Native mode needs a client that implements form elicitation. Browser mode is the one to use when you do not want the agent to be the one holding the question.
The mode is part of the grant, not just the URL. Changing the query string on an issued connection does not change the mode.
What is coming later
- Remembering an approval, so the same action is not asked again.
- Resuming a program after the server restarts. A lost session cannot be continued, and the program must not be run again automatically, because earlier tool calls may already have taken effect.