How Virtual MCP servers work
A Virtual MCP server exposes the tools you choose, for one user at a time, to any MCP client. How servers, session tokens and tool calls fit together.
A Virtual MCP server is a URL that exposes tools you choose, from one or more connections, to any MCP client. You create one server per agent role, such as a support assistant, and all your users share it. Before each run, you mint a session token for one user. The agent connects to the server URL with that token and can call only the tools you chose, as that user.
Use a Virtual MCP server when your agent already speaks MCP. If you build the agent loop yourself, you can call tools from your code instead: see Use built-in tools.
Why use one
Section titled “Why use one”- The agent sees only the tools it needs. A Gmail connection has dozens of tools. A summarizer needs one. The server exposes only the tools you list, so the agent can’t call the rest.
- Smaller prompts. Every tool on an MCP server goes into the model’s context. Fewer tools means fewer tokens on every call.
- One definition, isolated users. All users share the server’s URL. Each run’s session token is bound to one user and that user’s connected accounts, so one user’s run can’t act with another user’s credentials.
How it works
Section titled “How it works”| When | You | What you get |
|---|---|---|
| Once per agent role | Create a Virtual MCP server with the connections and tools the agent needs | A server ID and a fixed mcp_server_url |
| Before each run | Check the user’s connected accounts are ACTIVE, then mint a session token | A bearer token for one user and one server |
| During the run | Connect any MCP client to the URL with Authorization: Bearer <session token> | The server’s tools, called as that user |
In the API and SDKs, a Virtual MCP server is called an MCP configuration, for example create_config in Python and createConfig in Node.js. The Virtual MCP servers API reference lists every operation.
Session tokens
Section titled “Session tokens”A session token authorizes one user on one server:
- It lasts one hour unless you set
expiry, which must be between 60 seconds and 24 hours. - It can’t be refreshed or extended. Mint a new one instead. Minting a new token doesn’t revoke earlier ones.
- It only works on the server it was minted for. Any other server URL returns
401. - Minting succeeds even if the user hasn’t connected their accounts yet, so check the accounts first.
Mint session tokens covers when to mint for one-off, scheduled, concurrent and long-running agents.
What the agent sees
Section titled “What the agent sees”tools/list returns the tools you chose for the server. Tools from a connection the user hasn’t authorized don’t work until they do. By default, tools/list also includes a connect_account tool. When the user still needs to connect an app, the agent calls it to get an authorization link, and shows the link to the user.
A tool call returns the same output as execute_tool: the app’s response under data. If the app reports an error in a successful (2xx) response, that error is in data. If the app answers with an error status, the tool call returns an error result (isError: true) whose message starts with tool execution failed.
Data flow
Section titled “Data flow”- The MCP client sends a request to the server URL with the session token.
- Scalekit checks the token against the server and the user, and finds the user’s connected account for the tool’s connection.
- Scalekit calls the app’s API with that account’s credentials and returns the result to the client.
Your agent never receives the user’s OAuth token or API key. Responses pass through to the MCP client and aren’t stored. See what Scalekit stores.