MCP Proxy API
Your gateway handles sign-in. Miso handles MCP.
Pick the setup by who handles sign-in and who handles MCP:
| Setup | What you build | Who connects | Sign-in handled by | MCP protocol handled by | Usage reports |
|---|---|---|---|---|---|
| Internal Use | Nothing. Paste one URL | Your team, or one app | No one. The URL carries the key and token | Miso | Per app |
| For your Subscribers | A sign-in hand-off on your login page | Each subscriber | Your existing login. Miso runs OAuth | Miso, on your domain | Per subscriber and tier |
| MCP Proxy API (this page) | A gateway that signs users in and forwards calls | Your users | Your gateway | Miso | Per user your gateway names |
| Tools API | An MCP server that calls Miso's tools | Your users | Your MCP server | Your MCP server | Per app or per user |
Your users connect their assistant to an address you run. Your gateway signs them in, then passes each MCP call to Miso with your Secret API Key. Miso speaks the MCP protocol: it reads the call, runs the search, and answers in MCP. Your gateway hands that answer straight back. Below we build the gateway.
The split is what sets this setup apart from the Tools API. There, your own MCP server speaks the protocol and calls Miso for search. Here, your gateway decides who gets in, and Miso does everything after that.
Your Secret API Key stays on your server. This page is for a gateway you run. Never put the secret key into an agent, an MCP URL, or a browser. To give people a URL they can paste into an assistant, use MCP — Internal Use or MCP — for your Subscribers instead.
How a call travels
The proxy suits a pass-through. Every MCP call is one JSON-RPC POST that answers with JSON. There is no session to carry and nothing streams on the POST, so your gateway forwards the body as it is and adds three things.
What your gateway adds
| What | Where | Notes |
|---|---|---|
| Your Secret API Key | Authorization: Bearer <SECRET_API_KEY>, or the X-API-Key header |
No MCP token. The secret key opens the proxy alone. |
| The user | X-MCP-User-Id header, or ?user_id= |
Optional. Accepted only with the secret key. The header wins when both are sent. |
| A filter | ?fq= on the URL |
Optional. Narrows what this call can search. |
The proxy's address is the same endpoint every MCP client uses:
POST https://api.askmiso.com/v1/ask/mcp
All three ride outside the JSON-RPC body. The body belongs to the protocol, and
the tool arguments inside it belong to the assistant, which fills them in. A
user_id or fq at the top level of the body is refused with a message naming
where it goes.
Tell Miso who the user is
Send your own id for the user on every call:
X-MCP-User-Id: user-123
Miso records it beside every search and every full-text read, so your usage report splits by user. Use an opaque id rather than an email address. It can be up to 256 characters, with no control characters.
The user id is your assertion. Miso trusts it because it arrives with your
secret key, which only your server holds. With a publishable key the call is
refused with 401.
Narrow what a call can search
Add a filter in Lucene syntax as ?fq=:
POST https://api.askmiso.com/v1/ask/mcp?fq=tags:public
The filter can only narrow. Miso adds it as one clause and keeps its own filter for your app on top, so a call never reaches content your app's setup excludes. Your gateway chooses the filter per call, so it can give each user the slice their plan allows.
Brackets must open and close within the filter, and phrases and regular
expressions must close. A filter that breaks either rule, ends with a
backslash, or runs past 2,000 characters is refused with 400 before any
search runs. ?type= still works beside it, and the two combine.
Full text follows the same rules
The detail tool only returns a passage that a search surfaced in the last hour.
Behind the proxy, that rule also checks the filter, the ?type= and the user.
A passage that one user's search returned is not readable under another user,
or under a different filter. So the filter you set on search holds for full
text too.
Keep the same fq, type and user id on the search and on the detail call that
follows it. Your gateway does this naturally when it sets them per user.
The gateway
In the following gateway, we sign the user in, pick their filter, and forward the call:
import os
import httpx
from fastapi import FastAPI, HTTPException, Request
from fastapi.responses import JSONResponse
MISO_MCP = "https://api.askmiso.com/v1/ask/mcp"
MISO_SECRET_API_KEY = os.environ["MISO_SECRET_API_KEY"]
app = FastAPI()
client = httpx.AsyncClient(timeout=60)
def sign_in(request: Request) -> dict:
"""Your own check. Return the user, or raise."""
user = your_auth.user_from(request) # whatever your site already uses
if not user:
raise HTTPException(401, "Sign in first")
return user
@app.post("/mcp")
async def mcp(request: Request) -> JSONResponse:
user = sign_in(request)
reply = await client.post(
MISO_MCP,
params={"fq": "tags:public"} if user["plan"] == "free" else {},
headers={
"Authorization": f"Bearer {MISO_SECRET_API_KEY}",
"X-MCP-User-Id": user["id"],
},
json=await request.json(),
)
return JSONResponse(reply.json(), status_code=reply.status_code)
your_auth.user_from stands for whatever your site already does to recognise a
signed-in user: a session cookie, a token, or your auth library.
When something is refused
| Status | Message | Cause |
|---|---|---|
401 |
MCP token required |
A publishable key with no MCP token. Use the secret key. |
401 |
Invalid MCP token |
A token was sent and it is not this app's. With the secret key, send no token. |
401 |
MCP is not enabled for this app |
MCP is not set up for this app. Contact Miso. |
401 |
A user id is only accepted with the secret API key |
A user id arrived with a publishable key. |
400 |
Names the problem with the filter | A bracket, phrase or regular expression does not close. Or the filter ends with a backslash, or is too long. |
200, JSON-RPC error |
Names the header or parameter | user_id or fq was sent in the body. |
Next
- Tools API — when your own MCP server speaks the protocol and calls Miso for search.
- MCP — Internal Use — the search and detail tools in full.
