Overview
The Agent MCP lets you put an Upsolve agent behind the Model Context Protocol so that your end users, or an agent built into your product, can ask questions in natural language and get trusted, data-scoped answers. Every call is scoped to a single end user via that user’s own project-user token — the same short-lived JWT you already mint in Backend Setup. The MCP server holds no secrets of its own; it forwards the caller’s token to the agent, and row-level security does the rest. One user can never see another user’s data.Not the same as the Claude MCP Server.
That one is for you, the builder, to explore your own data inside Claude (you sign
in with your Upsolve account via OAuth, and it renders interactive charts). This one
is for your end users / your agent, authenticated with a per-user token you mint.
Pick this page if you’re embedding analytics into your product.
How it works
- You register each end user and mint a short-lived project-user token — exactly the Backend Setup flow.
- You run the Agent MCP, configured with the agent id you want to expose.
- Your end user’s agent connects to the MCP and calls one tool,
query_data, passing the user’s token. The MCP forwards it toPOST /v1/api/project-agents/{agentId}/chat, and the agent answers within that user’s data scope.
Prerequisites
An agent to expose
Build and publish an agent in Agent Studio, and copy its agent id. This is the single agent the MCP server will serve.
A way to mint user tokens
Complete Backend Setup: register your organization and users, and be able to fetch a project-user token on demand. That token is what your users present to this MCP.
Configure the server
The Agent MCP is configured entirely through environment variables:| Variable | Required | Description |
|---|---|---|
UPSOLVE_API_URL | Yes | Upsolve API base URL, e.g. https://api.upsolve.ai |
UPSOLVE_AGENT_ID | Yes | The agent id this server exposes |
MCP_TRANSPORT | No | stdio (default, local / per-user) or http (hosted, many users) |
UPSOLVE_PROJECT_USER_JWT | stdio only | The end user’s project-user token (one process serves one user) |
MCP_PORT | http only | Port for the hosted server (default 3002) |
UPSOLVE_TOOL_NAME | No | Rename the tool your agent sees (default query_data) |
UPSOLVE_INCLUDE_TOOL_RESULTS | No | true to append chart/table data as JSON for your agent to render (default false) |
Connect your users
Choose the shape that matches how your users consume it.- Hosted (HTTP)
- Local (stdio)
Best when many end users hit one server (a web product). Run the Agent MCP once with Example MCP client config:
MCP_TRANSPORT=http, then have each user’s agent connect over HTTP and pass that user’s token as the bearer — the server forwards each request’s token, so concurrent users stay isolated.The tool your agent gets
A single tool — the same shape as the Claude MCP Server’s, so it’s familiar:query_data
| Parameter | Type | Required | Description |
|---|---|---|---|
message | string | Yes | The analytical question, in plain English |
thread_id | string | No | Pass back the thread_id from a previous response to continue the conversation |
<thread_id>…</thread_id> marker your agent can echo back on the next call. If UPSOLVE_INCLUDE_TOOL_RESULTS=true, chart/table data is appended as a JSON block for your agent to render (there is no built-in chart UI on this server).
On the first call, omit
thread_id. Read it back from the response and pass it on every
follow-up so the agent keeps conversation context.Token lifecycle
Project-user tokens are short-lived (1 hour by default — see Backend Setup). Mint one per session and refresh it before it expires.- HTTP: when a token expires the tool returns an actionable error; mint a fresh token and send it on the next request.
- stdio: the token lives in the process environment, so restart the process (or relaunch with a new token) when it expires. For long-lived agents, have your backend re-mint and respawn.
- Hands-off tokens (optional, advanced): a trusted hosted deployment can hold your API key and mint per-user tokens itself, so end users never handle tokens. This places your API key on the server — use it only for a server you control. Contact Upsolve if you want this pattern.
Security
- Per-user scoping — every answer is filtered by the token’s
properties(row-level security). Set the correct tenant keys when you register the user; that is your isolation boundary. - Org-bound — a user can only reach agents in their own organization. A wrong or foreign
UPSOLVE_AGENT_IDreturns “not found”, never another tenant’s data. - No server-side secret — in the default flow the MCP forwards the caller’s token and stores nothing; it can’t see anything the token doesn’t already allow.
- Read-only — the agent queries your data; it never writes or modifies it.
Troubleshooting
“No credential” / Unauthorized
“No credential” / Unauthorized
Session expired (401)
Session expired (401)
The project-user token is past its expiry. Mint a fresh one (see Backend Setup) and reconnect.
“Agent not found for your organization”
“Agent not found for your organization”
Check
UPSOLVE_AGENT_ID, and confirm the agent has a published production version in Agent Studio and belongs to the same organization as the user’s token.Empty answer
Empty answer
The question returned no rows under this user’s row-level security. Verify the user’s
properties and your data model’s RLS.Next steps
Backend Setup
Register users and mint the project-user tokens this MCP consumes.
Build Your Agent
Encode KPI definitions, golden assets, and guardrails before you expose the agent.
Claude MCP Server
The builder-facing MCP for exploring your own data inside Claude.
Frontend Setup
Embed the agent as a UI Space instead of (or alongside) MCP.