Docs & FAQ
Everything you need to publish, secure, and connect your MCP or agent.
How the platform works
What is mcpchannel.ai?
A marketplace and proxy gateway for MCP servers and agents. As a provider you publish your MCP listing once. Consumers subscribe and the platform gateway routes all their tool calls to your server — handling auth, metering, and billing.
What is the gateway?
Every consumer tool call goes through the mcpchannel.ai gateway before reaching your server. The gateway authenticates the consumer, injects any OAuth token or provider headers, enforces usage caps, and records metered usage. Your server only has to handle the tool call itself.
What does a request to my MCP server look like?
POST https://your-mcp-server.com/mcp
Authorization: Bearer <consumer-oauth-token> ← injected by gateway (if OAuth enabled)
X-MCP-Market-Verification: mkt_v1_abc9f3... ← platform-generated, always sent
X-Provider-Key: your-static-secret ← from your Provider auth headers (if set)
Content-Type: application/json
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"your_tool","arguments":{}}}Provider auth headers
What are Provider auth headers?
Static key-value headers you configure once on your listing. The gateway sends them on every request to your MCP server — introspection, tool calls, everything. Use them so your server can verify that requests are coming from the gateway.
When should I add Provider auth headers?
Any time your MCP server requires authentication before accepting requests. If your server is open to the internet with no auth, you don't need them — but it's strongly recommended to add at least one so random internet traffic can't call your tools.
What header name should I use?
| Scenario | Header name | Example value |
|---|---|---|
| No OAuth | Authorization | Bearer my-secret-key-123 |
| OAuth enabled | X-Provider-Key | my-secret-key-123 |
| Multiple auth layers | X-Provider-Key + X-Tenant-Id | key + tenant |
| Custom API key | X-Api-Key | sk-abc123 |
If OAuth is enabled, avoid Authorization — the gateway overwrites it with the consumer's live Bearer token. Use X-Provider-Key instead.
How do I verify Provider auth headers on my server?
JavaScript
// Express / Node.js
const key = req.headers["x-provider-key"];
if (key !== process.env.PROVIDER_SECRET) {
return res.status(401).json({ error: "Unauthorized" });
}Python
# Flask / FastAPI
key = request.headers.get("X-Provider-Key")
if key != os.environ.get("PROVIDER_SECRET"):
return jsonify({"error": "Unauthorized"}), 401Go
// net/http
key := r.Header.Get("X-Provider-Key")
if key != os.Getenv("PROVIDER_SECRET") {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}X-MCP-Market-Verification
What is X-MCP-Market-Verification?
A platform-generated secret unique to your listing. The gateway always injects it. Your server can check it to confirm that requests came through the marketplace gateway — not from someone calling your MCP directly.
How is it different from Provider auth headers?
| Provider auth headers | X-MCP-Market-Verification | |
|---|---|---|
| Set by | You | Platform (auto-generated) |
| What it proves | Requests use your secret key | Requests came through the gateway |
| Required | No (recommended) | No (optional check) |
| Changes | Only when you update it | Never (stable per listing) |
How do I check X-MCP-Market-Verification on my server?
JavaScript
const verify = req.headers["x-mcp-market-verification"];
if (verify !== process.env.MCP_MARKET_VERIFICATION_TOKEN) {
return res.status(401).json({ error: "Not from marketplace" });
}Python
import os
verify = request.headers.get("X-MCP-Market-Verification")
if verify != os.environ.get("MCP_MARKET_VERIFICATION_TOKEN"):
return jsonify({"error": "Not from marketplace"}), 401Go
import "os"
verify := r.Header.Get("X-MCP-Market-Verification")
if verify != os.Getenv("MCP_MARKET_VERIFICATION_TOKEN") {
http.Error(w, "Not from marketplace", http.StatusUnauthorized)
return
}Copy the verification secret from the Market verification section on your listing's edit page after saving.
Consumer OAuth
What is Consumer OAuth?
An optional flow where each consumer authenticates with their own identity before calling tools. The gateway fetches a fresh Bearer token per consumer and injects it as Authorization: Bearer <token> on every request to your server. Your server validates the token to know which user is calling.
When should I enable Consumer OAuth?
| Use case | Enable OAuth? |
|---|---|
| MCP with a static API key (same for all users) | No — use Provider auth headers |
| MCP where each user has their own account (GitHub, Google, Slack…) | Yes — authorization_code |
| System-to-system, no per-user data | No |
| Internal tool, consumers have their own OAuth credentials | Yes — client_credentials |
What is the difference between client_credentials and authorization_code?
| Grant type | When to use | Who owns the OAuth app? | User interaction |
|---|---|---|---|
| client_credentials | System-to-system. Consumer has their own OAuth app credentials. | Consumer | None — fully automated |
| authorization_code | Each consumer logs in with their own account (GitHub, Google, Slack…) | You (the provider) | Consumer clicks Authorize once |
How does authorization_code work with GitHub? (provider sets up once)
For GitHub OAuth, you create one OAuth App as the provider. Consumers just click Authorize — they never handle credentials.
- 1
Go to GitHub → Settings → Developer settings → OAuth Apps → New OAuth App - 2
Set Authorization callback URL to: https://mcpchannel.ai/oauth/callback - 3
Copy your Client ID and Client Secret from GitHub - 4
In your listing: Authorize URL = https://github.com/login/oauth/authorize - 5
In your listing: Token URL = https://github.com/login/oauth/access_token - 6
Store your GitHub app Client ID + Secret in the Provider OAuth credentials section (coming soon) - 7
Consumers click 'Connect GitHub' → authorize once → gateway handles their token forever
Provider OAuth credentials storage is coming soon. Currently the platform uses client_credentials flow where each consumer provides their own credentials.
How does client_credentials work? (consumer brings their own credentials)
For system-to-system flows, each consumer has their own client_id and client_secret issued by your OAuth server.
- 1
Enable Consumer OAuth on your listing - 2
Leave Authorize URL empty (no consent screen needed) - 3
Set Token URL to your OAuth server's token endpoint - 4
Consumer enters their client_id and client_secret in Dashboard → Subscriptions - 5
Gateway calls client_credentials grant automatically on each tool call - 6
Your server receives Authorization: Bearer <token> and validates it
What is the platform's OAuth callback URL?
https://mcpchannel.ai/oauth/callback // This is the redirect_uri the platform uses during authorization_code flows. // Register this exact URL in your OAuth provider's app settings // (GitHub, Google, Slack, etc.) as the allowed redirect URI.
How does the gateway inject the OAuth token?
The gateway calls your Token URL server-to-server, gets a fresh access_token, and injects it as Authorization: Bearer <token> on the request to your MCP. Your server then validates the token against your OAuth provider's /userinfo or introspection endpoint to identify the consumer.
Why can't I use Authorization in Provider auth headers when OAuth is on?
The gateway sets Authorization: Bearer <consumer-token> on every request. If you also put Authorization in your Provider auth headers, the gateway overwrites it — your static key is lost. Use X-Provider-Key instead so both values reach your server without conflict.
How do I validate the OAuth token on my server?
JavaScript
// Call your OAuth provider's userinfo endpoint
const res = await fetch("https://api.github.com/user", {
headers: { Authorization: req.headers["authorization"] },
});
if (!res.ok) return reply.status(401).send({ error: "Invalid token" });
const user = await res.json();
// user.login = GitHub username, user.id = GitHub user IDPython
import httpx
token = request.headers.get("Authorization")
r = httpx.get("https://api.github.com/user",
headers={"Authorization": token})
if r.status_code != 200:
return jsonify({"error": "Invalid token"}), 401
user = r.json() # user["login"] = GitHub usernameGo
token := r.Header.Get("Authorization")
req, _ := http.NewRequest("GET", "https://api.github.com/user", nil)
req.Header.Set("Authorization", token)
resp, err := http.DefaultClient.Do(req)
if err != nil || resp.StatusCode != 200 {
http.Error(w, "Invalid token", http.StatusUnauthorized)
return
}Validating your MCP
What does the Validate button do?
It calls your MCP's introspection endpoint (tools/list, prompts/list, resources/list) using the URL and headers you've configured, and reports back how many tools, prompts, and resources were found. This confirms the gateway can reach your server before you publish.
My MCP requires OAuth — how do I validate it?
Expand the Consumer OAuth section, enter your Token URL, Client ID, and Client Secret, then click Fetch token. The token fills in automatically. Then click Validate — the gateway calls your server with that token in the Authorization header.
Validation fails with 'Could not reach Token URL'
The token fetch goes server-to-server (Next.js → your OAuth server), so CORS is not an issue. Check that: (1) your OAuth server is running, (2) the Token URL is correct and publicly reachable, (3) your Client ID and Secret are valid.
Validation fails with 401 Unauthorized
Your MCP server rejected the request. Check that the Provider auth headers match what your server expects, and if OAuth is on, that the fetched token is valid and your server's token validation logic is correct.
Use cases
Static API key only (no OAuth)
Your MCP server has one shared API key. All consumers use the same key — the gateway holds it.
- 1
Leave Consumer OAuth unchecked - 2
Add Provider auth header: Authorization → Bearer your-api-key - 3
Your server checks req.headers["authorization"]
Per-user OAuth with GitHub
Your MCP reads the consumer's GitHub repos. Each consumer authenticates with their own GitHub account.
- 1
Enable Consumer OAuth - 2
Authorize URL: https://github.com/login/oauth/authorize - 3
Token URL: https://github.com/login/oauth/access_token - 4
Add Provider auth header: X-Provider-Key → your-gateway-secret (to verify requests are from the gateway) - 5
Consumer connects once in their dashboard - 6
Gateway injects their GitHub token on every tool call
System-to-system with client_credentials (no user login)
Your MCP server is an internal tool. Consumers provide their own client_id and client_secret — no consent screen.
- 1
Enable Consumer OAuth - 2
Leave Authorize URL empty - 3
Token URL: https://your-auth-server.com/oauth/token - 4
Consumer enters their client_id and client_secret in their dashboard - 5
Gateway calls client_credentials grant automatically
Maximum security — both Provider key and Market verification
Block both unauthorized callers and direct calls that bypass the marketplace.
- 1
Add Provider auth header: X-Provider-Key → your-secret - 2
On your server: check x-provider-key matches your secret - 3
On your server: also check x-mcp-market-verification matches the value from your listing edit page - 4
Any request missing either header is rejected