MCP — for your Subscribers
Let your subscribers connect their own AI agent, on your login.
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 (this page) | 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 | 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 |
Let each of your subscribers connect their own AI agent to your content, tied to their existing login and their plan. Usage comes back to you per subscriber and per tier. Below we show the address your subscribers connect to and what it gives them, then run the sign-in once, from the agent to your site and back.
Miso runs the OAuth exchange with the AI agent. Your site provides the login and, on the way back, a signed token that proves who the subscriber is.
Try one
Miso runs a public host you can connect to right now. It carries the Wikinews archive, and it is built the same way as yours:
https://wikinews.mcp.miso.ai
Open it in a browser to see the install page. In Claude Code, two commands give you the connection and the skill:
/plugin marketplace add https://wikinews.mcp.miso.ai/marketplace.json
/plugin install wikinews-mcp-plugin@wikinews
Sign in with an email address on first use. Access lasts 30 days. Then ask your assistant something the archive covers, such as what happened at the 2012 Olympics opening ceremony, and watch it search, read the full article, and cite it.
Every path in What a Miso MCP server host serves
answers on that host, so you can also open /llms.txt or /marketplace.json
and read what a client reads.
A Miso product demo, with content from Wikinews under CC BY 2.5. It is not affiliated with Wikinews or the Wikimedia Foundation. The archive runs through 2013.
Your MCP address
Your subscribers do not paste a Miso URL or hold a key. They connect to a host that carries your name, and sign in there.
The host can be a Miso subdomain, or a name on your own domain.
| Shape | Example | What you do |
|---|---|---|
| Miso subdomain | your-site.mcp.miso.ai |
Nothing. Miso runs the DNS. |
| Your own domain | mcp.your-site.com |
Point a CNAME at Miso. |
Your own domain is the one to pick when subscribers will see the address. It keeps your brand on the connection, in the assistant's settings screen, and in the sign-in prompt. Any shape of name works: a subdomain, a deep subdomain, or your apex domain.
Miso maps the host to your content when the host is set up. A name that was
never declared returns 404, so no other address can serve your content.
The endpoint your subscribers connect to is /mcp on that host:
https://mcp.your-site.com/mcp
What a Miso MCP server host serves
Miso runs the host. These answer on it from the day it is set up.
Each path below links to the live demo host, so you can open it and read what a client reads.
| Path | What it is |
|---|---|
/ |
The install page. A reader picks their assistant and copies one command. |
/mcp |
The MCP endpoint. Your subscribers sign in here. |
/marketplace.json |
The plugin catalog, for a one-command install in Claude Code. |
/plugin.zip |
The plugin itself: the connection and the skill together. |
/skills.zip |
The skill on its own, for every other assistant. |
/llms.txt |
A plain-text index of all of the above, for an agent that lands on the host. |
/.well-known/… |
The sign-in metadata a client reads before it connects. |
Two of those links download a file, and /mcp answers 405 in a browser. The
endpoint speaks JSON-RPC over POST, and answering a browser GET that way is
what the transport specification asks for.
You build none of these. The content carries your brand name and your tool names.
What your subscribers install
The install page
https://mcp.your-site.com/ is a page you can send to a subscriber, or link
from your account settings. It shows your name, what the connection gives
them, and a tab for each assistant: Claude Code, Cursor, Codex, Gemini CLI,
Claude Desktop and ChatGPT. Each tab holds the exact command for that client.
The page has two halves. The first installs the plugin, which is the connection and the skill in one step. The second connects the endpoint on its own, for a reader who wants the tools and no more.
The plugin, and what is in it
In Claude Code, two commands install everything:
/plugin marketplace add https://mcp.your-site.com/marketplace.json
/plugin install your-site-mcp-plugin@your-site
That install carries two pieces:
The connection. The MCP endpoint, already pointed at your host, so the reader types no URL and pastes no key. They sign in on first use.
A skill. A short set of instructions that loads into the assistant alongside your tools. It teaches the assistant how to get good answers from your archive: search before answering, rephrase and try again when the first search misses, open the full article when detail matters, and cite the title and URL of everything it used. It also states what your archive does not cover, so the assistant says so rather than inventing an answer.
The skill is the part that changes answer quality. A connection alone gives an assistant your tools. The skill tells it how you want them used.
Every other assistant
The one-command install is specific to Claude Code. Every other assistant loads the same skill from a folder, so the host serves it as a plain archive:
curl -sL https://mcp.your-site.com/skills.zip -o /tmp/skill.zip
unzip -o /tmp/skill.zip -d ~/.cursor/skills/
The archive holds the skill folders at its top level, so it unzips straight
into the assistant's skills directory. Change the last path for the client in
front of you: ~/.cursor/skills/ for Cursor, ~/.agents/skills/ for Codex,
~/.gemini/skills/ for Gemini CLI. In ChatGPT, download the file and upload
it under Plugins.
The endpoint is added separately in those clients, with one command:
codex mcp add your-site --url https://mcp.your-site.com/mcp
The install page carries the version of this for each client, so a subscriber copies rather than adapts.
The index for agents
https://mcp.your-site.com/llms.txt describes the host in plain text: what
the archive covers, where the install page is, the endpoint URL, the plugin
commands, and the name and purpose of each tool. An agent that is handed your
host and no instructions reads this file and knows what to do with it.
The round-trip
What your site needs
You do not need to build an identity provider. If you have a login and can sign a token, you have the pieces. Three things:
1. A sign-in page Miso can redirect to. Miso sends the subscriber to your
login with two query parameters — a state and the callback URL to return
to. The subscriber signs in with their existing account. You confirm that their
plan includes MCP.
2. A redirect back with a signed assertion. Send the subscriber to the
callback carrying a short-lived JWT. Sign it with your Miso secret key
(HS256). That shared secret is how Miso knows the assertion came from you.
3. The right claims in that assertion.
| Claim | What it is |
|---|---|
sub |
A stable subscriber id. Who the access is for. |
access_exp |
How long MCP access stays valid. |
state |
Echo the state Miso sent you. This blocks CSRF. |
aud |
The audience: https://api.askmiso.com. |
exp |
The lifetime of this assertion. Keep it under 5 minutes. |
tier |
Optional. The plan tier, to segment your usage reports. |
What your sign-in page receives
GET https://your-site.com/login
?state=Yk3f...opaque
&callback=https://api.askmiso.com/v1/ask/oauth/callback
Signing the assertion
After the subscriber signs in, and after you confirm their entitlement, sign a short-lived assertion and redirect them back.
import time, jwt # pip install pyjwt
from urllib.parse import urlencode
def redirect_back(state, callback, subscriber_id, tier):
now = int(time.time())
assertion = jwt.encode(
{
"sub": subscriber_id, # stable subscriber id
"aud": "https://api.askmiso.com",
"state": state, # echo Miso's state
"exp": now + 120, # keep this short
"access_exp": now + 30 * 24 * 3600,
"tier": tier, # optional, for reports
},
MISO_SECRET_API_KEY, # your Miso secret key
algorithm="HS256",
)
params = {"state": state, "assertion": assertion}
return redirect(f"{callback}?{urlencode(params)}")
import jwt from "jsonwebtoken"; // npm i jsonwebtoken
function redirectBack(res, state, callback, subscriberId, tier) {
const now = Math.floor(Date.now() / 1000);
const assertion = jwt.sign(
{
sub: subscriberId, // stable subscriber id
aud: "https://api.askmiso.com",
state, // echo Miso's state
exp: now + 120, // keep this short
access_exp: now + 30 * 24 * 3600,
tier, // optional, for reports
},
MISO_SECRET_API_KEY, // your Miso secret key
{ algorithm: "HS256" }
);
const params = new URLSearchParams({ state, assertion });
return res.redirect(`${callback}?${params}`);
}
<?php
use Firebase\JWT\JWT; // composer require firebase/php-jwt
function redirect_back($state, $callback, $subscriber_id, $tier) {
$now = time();
$assertion = JWT::encode(
[
'sub' => $subscriber_id, // stable subscriber id
'aud' => 'https://api.askmiso.com',
'state' => $state, // echo Miso's state
'exp' => $now + 120, // keep this short
'access_exp' => $now + 30 * 24 * 3600,
'tier' => $tier, // optional, for reports
],
MISO_SECRET_API_KEY, // your Miso secret key
'HS256'
);
$q = http_build_query([
'state' => $state,
'assertion' => $assertion,
]);
header("Location: {$callback}?{$q}");
exit;
}
require "jwt" # gem install jwt
def redirect_back(state, callback, subscriber_id, tier)
now = Time.now.to_i
assertion = JWT.encode(
{
sub: subscriber_id, # stable subscriber id
aud: "https://api.askmiso.com",
state: state, # echo Miso's state
exp: now + 120, # keep this short
access_exp: now + 30 * 24 * 3600,
tier: tier # optional, for reports
},
MISO_SECRET_API_KEY, # your Miso secret key
"HS256"
)
query = URI.encode_www_form(state: state, assertion: assertion)
redirect_to "#{callback}?#{query}"
end
That is the whole integration on your side. Miso handles discovery, PKCE, and the token exchange with the agent.
Who does what
| Step | Your site | Miso |
|---|---|---|
| Start | — | Receives the agent and begins OAuth. |
| Sign-in | Login, and enable MCP for the plan. | Redirects the subscriber to you. |
| Hand-back | Redirect back with a signed JWT. | Verifies the JWT. |
| Token | — | Issues the access token to the agent. |
| Reporting | Receives usage reports. | Attributes usage from your claims. |
The tools your subscribers get
Once connected, a subscriber's agent sees two tools. They are the same two the internal setup gets, and they work the same way here.
The search tool
Named for your brand, for example ask_yourbrand.
| Parameter | Type | Required | Notes |
|---|---|---|---|
question |
string | yes | The question to search for. |
context |
string | no | What the subscriber is working on. Miso adds it to the question. |
skill_used |
string | no | The skill or template that made the call. Analytics only. |
author |
string | no | Restrict results to one author. Available when Miso enables it for your app. |
The agent sends a question in the subscriber's own words. Back come ranked passages from your archive:
{
"query": "interest rate cuts",
"results": [
{
"product_id": "art-20260612-rates",
"product_title": "Central bank signals 2026 cuts",
"authors": "A. Reporter",
"offset": 1,
"snippet_preview": "The central bank said it expects two cuts...",
"published_date": "2026-06-12",
"url": "https://example.com/markets/rates",
"relevance_score": 0.87
}
],
"citation_format": "Use markdown links: [product_title](url) by authors"
}
Each result carries what an answer needs to cite you: the headline, the date, and the URL that sends the reader back to your page. There is no parameter for result count, paging or filtering. Miso scopes every search to your catalog on the server side.
The detail tool: get_snippet_detail
This is the default name. Miso renames it for your brand on request.
| Parameter | Type | Required | Notes |
|---|---|---|---|
product_id |
string | yes | From a search result. |
offset |
integer | yes | From the same search result. |
skill_used |
string | no | Analytics only. |
It returns the full text of one passage, plus a ready-made markdown link in
citation_format that the agent is told to cite with.
The two tools are a pair, and the order is enforced. get_snippet_detail accepts
only a product_id and offset that a search returned, and a result stays
readable for one hour after the search that found it. An agent therefore
reads your archive one passage at a time, in response to a real question.
See MCP — Internal Use for the full field list and the content protections that apply to both tools.
Getting set up
Miso sets up the host and the sign-in with you, in one short working session with your engineers. Together you agree:
- The name. A Miso subdomain needs nothing from you. Your own domain needs a CNAME record, which Miso gives you.
- The wording. Your brand name, what the archive covers, the tool names, and anything you want the assistant told about your content.
- The sign-in. Your login URL, the signing key, and how you map a signed-in user to a subscriber id and tier.
Most publishers pilot it on a single tier first. Contact your Miso representative.
Next
- MCP — Internal Use — one credential for your own team.
- Tools API — run the same tools inside a server you own.
