Appa Tools documentation for MCP Studio, including setup, guides, concepts, and API-related reference content.

Skip to main content

How to authenticate to access your private MCP Server

A public MCP server answers anyone who knows its endpoint URL. That is the right behaviour for documentation you want people to connect, and the wrong one for a server built on a private GitHub repo. Endpoint URLs are not designed to be secret — they sit in client config files, terminal history and shared screens — so the URL on its own is not access control.

A private MCP server requires a valid access token on every request. This guide covers turning that on and connecting to it afterwards.

AudienceAnyone running an MCP server that should not be world-readable
PrerequisitesA deployed MCP server and access to your MCP client's config file

What "private" changes

When a server is private, every request must present a token — not just tool calls. The initialize handshake and tools/list are refused too. Tool names and server instructions describe what the indexed content is about, which is often as sensitive as the content itself.

An unauthenticated request gets back HTTP 401 and JSON-RPC error -32001.

Servers that become private automatically

Adding a private GitHub repo as a source makes the server private. This is automatic rather than a prompt, and it takes effect before indexing begins, so private content is never indexed into a public server.

While a private source is connected, the server cannot be switched back to public. To reopen it, disconnect the private source first — which also permanently deletes everything indexed from it.

You can also make any server private at any time, whether or not it has a private repo. You do not need a reason.

Turn a server private

  1. Open the server from your dashboard.
  2. In the Access panel, choose Private.
  3. Copy the access token that appears.

The token is shown once. MCP Studio stores only a SHA-256 hash of it, so it cannot be displayed again or recovered by support. If you lose it, revoke it and create a replacement.

warning

Switching to private takes effect immediately. Any client already connected without a token stops working until you add one to its config.

Access tokens

Access tokens look like mcps_live_... and are deliberately not the same thing as an account API key:

Access token (mcps_live_)Account API key (msk_live_)
ScopeOne MCP serverYour whole account
Can doQuery that server's toolsCreate, edit and delete servers; read analytics
Where it goesClient config files on every machine that connectsServer-side automations
If exposedThat one server's search results are readableFull account access

Because an access token gets pasted into mcp.json on every developer laptop and CI runner that connects, it is deliberately the narrowest credential that still does the job. Use one token per team, environment or machine so you can revoke a single one without disrupting everyone else. A server can hold up to 10 active tokens.

An account API key belonging to the server's owner is also accepted, so existing n8n and Langflow connections keep working when you make a server private. Prefer an access token for anything new.

Create another token

In the Access panel, click New token. Copy it immediately.

Revoke a token

Click the bin icon next to it. Revocation is immediate — the next request using that token is refused. Revoking the last token on a private server is allowed and leaves the server reachable by nobody, which is a reasonable thing to want during an incident.

Connect a client

The token goes in an Authorization: Bearer header.

Cursor

Open Settings → MCP Servers and use the headers field:

{
"mcpServers": {
"your-server": {
"url": "https://appatools.com/mcp-studio/api/mcp/your-server",
"headers": {
"Authorization": "Bearer mcps_live_your_token_here"
}
}
}
}

Restart Cursor after saving.

Claude Desktop

Claude Desktop's local config launches commands rather than calling URLs directly, so use the mcp-remote bridge:

{
"mcpServers": {
"your-server": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://appatools.com/mcp-studio/api/mcp/your-server",
"--header",
"Authorization: Bearer mcps_live_your_token_here"
]
}
}
}

Restart Claude Desktop after saving.

Windsurf and VS Code

Both accept the same headers object as Cursor. Add it alongside the server URL in your MCP settings and reload the window.

curl

Useful for confirming a token works before you edit any config:

curl -X POST https://appatools.com/mcp-studio/api/mcp/your-server \
-H "Authorization: Bearer mcps_live_your_token_here" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

A 401 means the token is missing, revoked, or belongs to a different server.

MCP SDKs

Pass the header through the transport's request options:

import { Client } from '@modelcontextprotocol/sdk/client/index.js'
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'

const transport = new StreamableHTTPClientTransport(
new URL('https://appatools.com/mcp-studio/api/mcp/your-server'),
{
requestInit: {
headers: { Authorization: `Bearer ${process.env.MCP_STUDIO_TOKEN}` },
},
},
)

const client = new Client({ name: 'my-app', version: '1.0.0' })
await client.connect(transport)

Read the token from an environment variable rather than committing it.

Clients that cannot send headers

A few clients open the legacy SSE transport with a plain GET that carries no headers. For those only, the token can go in a query parameter:

https://appatools.com/mcp-studio/api/mcp/your-server/sse?token=mcps_live_your_token_here
caution

Query strings end up in proxy logs, browser history and shared URLs in a way headers do not. Use this only when your client genuinely cannot set a header, and revoke that token if the URL is ever shared.

Disconnecting a source deletes its content

Disconnecting any source — private repo or public site — permanently deletes everything derived from it:

  • every indexed chunk and its embedding
  • cached search results for the server
  • the stored excerpts in your request log that came from that source

This is not reversible. Re-adding the source re-indexes it from scratch and does not restore the history. The server's other sources are untouched.

Troubleshooting

Every request returns 401. The client is not sending the header. Confirm with the curl command above; if curl works and your client does not, the header is not reaching us.

It worked yesterday and stopped today. The token was probably revoked, or the server was switched to private. Check the Access panel.

"That access token is not valid for this MCP server." The token is real but belongs to a different server. Tokens are scoped to exactly one server.

I lost the token. It cannot be recovered — only a hash is stored. Revoke it and create a new one.

I cannot switch back to public. A private GitHub source is still connected. Disconnect it first.