The code in this directory provides a working example of using tsidp with an MCP server that requires authentication. To run this example you’ll need to do the following:
If running via docker, it should look like this:
docker run -d \
--name tsidp \
-p 443:443 \
-e TS_AUTHKEY=YOUR_TAILSCALE_AUTHKEY \
-e TSNET_FORCE_LOGIN=1
-e TAILSCALE_USE_WIP_CODE=1 \
-v tsidp-data:/var/lib/tsidp \
tsidp --hostname=idp --dir=/var/lib/tsidpMCP requires the use of resource indicators, so you’ll also need to add an ACL application grant rule to your tailnet that allows a given user and / or device the ability to specify resources in their request. The following rule is extra permissive for this demo, but it allows anyone from any device on the tailnet to exchange tokens to request any resource. If you’d like to make it more specific, you can change “*” in resources to http://localhost:9933.
{
"src": ["*"],
"dst": ["*"],
"app": {
"tailscale.com/cap/tsidp": [
{
"users": ["*"],
"resources": ["*"],
},
],
},
},In a new terminal run the MCP server using the following command. It should start on localhost port 9933.
go run ./mcp-server.go --tsidp idp.YOUR_TAILNET.ts.netTo test the server we’ll use the MCP inspector provided directly by the MCP project. As of 2025/09/13, there appears to be a bug in the latest version of the inspector, so we’ll use an earlier version.
npx @modelcontextprotocol/inspector@0.16.3- Change the transport type to
Streamable HTTP - Update the URL to
http://localhost:9933 - Click on
Open Auth Settings - Click on
Quick OAuth Flowand you should see all green checks.
- Click
Connect - Click
List tools - Call a tool

