From c0e39f81fe31074b92e655544ff7f9348c8180c8 Mon Sep 17 00:00:00 2001 From: Patrick Kang <1489148+patrickkang@users.noreply.github.com> Date: Mon, 17 Nov 2025 15:45:43 -0500 Subject: [PATCH 01/10] add python counterparts for mcp quickstarts --- .../call-your-apis-on-users-behalf.mdx | 223 +++++++----------- .../call-your-apis/create-env-file.mdx | 31 +++ .../custom-token-exchange-action.mdx | 22 ++ .../exchange-access-token-js.mdx | 52 ++++ .../exchange-access-token-python.mdx | 63 +++++ .../call-your-apis/run-mcp-server-js.mdx | 11 + .../call-your-apis/run-mcp-server-python.mdx | 11 + .../mcp/get-started/server-authorization.mdx | 146 ++++++++---- 8 files changed, 379 insertions(+), 180 deletions(-) create mode 100644 auth4genai/snippets/mcp/get-started/call-your-apis/create-env-file.mdx create mode 100644 auth4genai/snippets/mcp/get-started/call-your-apis/custom-token-exchange-action.mdx create mode 100644 auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-js.mdx create mode 100644 auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-python.mdx create mode 100644 auth4genai/snippets/mcp/get-started/call-your-apis/run-mcp-server-js.mdx create mode 100644 auth4genai/snippets/mcp/get-started/call-your-apis/run-mcp-server-python.mdx diff --git a/auth4genai/mcp/get-started/call-your-apis-on-users-behalf.mdx b/auth4genai/mcp/get-started/call-your-apis-on-users-behalf.mdx index 7e86d5fd1..5abcdb036 100644 --- a/auth4genai/mcp/get-started/call-your-apis-on-users-behalf.mdx +++ b/auth4genai/mcp/get-started/call-your-apis-on-users-behalf.mdx @@ -10,6 +10,12 @@ import CreateProfile from "/snippets/mcp/get-started/create-custom-token-exchang import CreateMCPAPI from "/snippets/mcp/get-started/create-mcp-api.mdx"; import { DownloadQuickstartButton } from "/snippets/download-quickstart/DownloadQuickstartButton.jsx"; import MCPGetStartedTestingInstructions from "/snippets/mcp/get-started/testing-instructions.mdx"; +import CreateEnvFile from "/snippets/mcp/get-started/call-your-apis/create-env-file.mdx"; +import CustomTokenExchangeAction from "/snippets/mcp/get-started/call-your-apis/custom-token-exchange-action.mdx"; +import RunMcpServerJs from "/snippets/mcp/get-started/call-your-apis/run-mcp-server-js.mdx"; +import RunMcpServerPython from "/snippets/mcp/get-started/call-your-apis/run-mcp-server-python.mdx"; +import ExchangeAccessTokenJs from "/snippets/mcp/get-started/call-your-apis/exchange-access-token-js.mdx"; +import ExchangeAccessTokenPython from "/snippets/mcp/get-started/call-your-apis/exchange-access-token-python.mdx"; To call your APIs on behalf of your users, the MCP server needs to exchange the Auth0 access token it received from the MCP client (with the audience set to the MCP server itself) for a new Auth0 access token with the audience set to your API. @@ -18,7 +24,7 @@ In Auth0, this is called Custom Token Exchange and uses [RFC 8693](https://www.r By the end of this quickstart, you should have an MCP server that can: * Exchange an Auth0 access token for another Auth0 access token with a different audience using Custom Token Exchange -* Verify the access token using the `@auth0/auth0-api-js` library (which uses `jose` under the hood) against your tenant JWKS, enforcing issuer, audience, and RS256 +* Verify the access token using the `@auth0/auth0-api-js` library (which uses `jose` under the hood) or the `auth0-api-python` library for Python against your tenant JWKS, enforcing issuer, audience, and RS256 @@ -86,173 +92,112 @@ auth0 api post resource-servers --data '{ Save the `Audience` from the command output, you'll need it on a later step. - +## Sample app - - Start by downloading the sample app for this quickstart. The sample includes a FastMCP MCP server with an Auth0 integration and a protected API built with - [Fastify](https://fastify.dev/). - - - - Once downloaded, extract the files and open the project in your preferred IDE. - - - Clone the repository and navigate to the sample app folder which includes a FastMCP MCP server with an Auth0 integration and a protected API built with - [Fastify](https://fastify.dev/). - - ```shell wrap lines - git clone https://github.com/auth0-samples/auth0-ai-samples.git - cd auth0-ai-samples/auth-for-mcp/fastmcp-mcp-customtokenexchange-js - ``` - - Once cloned, open the project in your preferred IDE. - - - -The sample app demonstrates custom token exchange with a `greet` tool that calls your protected API on behalf of the authenticated user. - -## Install packages - -Ensure you have npm installed or follow the instructions to [install npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) in its documentation. In the `fastmcp-mcp-customtokenexchange-js` directory, install the required packages: - -```shell -npm install -``` - -## Create your environment file - -In the `fastmcp-mcp-customtokenexchange-js` directory, run the following commnd to create a new `.env` file populated with all the required environment variables: - -```shell wrap lines expandable -CLIENT_ID=$(jq -r '.client_id' auth0-app-details.json) \ -&& CLIENT_SECRET=$(jq -r '.client_secret' auth0-app-details.json) \ -&& DOMAIN=$(auth0 tenants list --json | jq -r '.[] | select(.active == true) | .name') \ -&& touch .env \ -&& echo "AUTH0_DOMAIN=${DOMAIN}" > .env \ -&& echo "AUTH0_AUDIENCE=http://localhost:3001/" >> .env \ -&& echo "PORT=3001" >> .env \ -&& echo "MCP_SERVER_URL=http://localhost:3001/" >> .env \ -&& echo "MCP_AUTH0_CLIENT_ID=${CLIENT_ID}" >> .env \ -&& echo "MCP_AUTH0_CLIENT_SECRET=${CLIENT_SECRET}" >> .env \ -&& echo "MCP_AUTH0_SUBJECT_TOKEN_TYPE=urn:fastmcp:mcp" >> .env \ -&& echo "MCP_AUTH0_EXCHANGE_SCOPE=read:tasks" >> .env \ -&& echo "API_AUTH0_AUDIENCE=http://localhost:8787/" >> .env \ -&& echo "API_BASE_URL=http://localhost:8787/" >> .env \ -&& rm auth0-app-details.json \ -&& echo ".env file created with your Auth0 details:" \ -&& cat .env -``` + + + + Start by downloading the sample app for this quickstart. The sample includes a FastMCP MCP server with an Auth0 integration and a protected API built with + [Fastify](https://fastify.dev/). -To get your Auth0 application’s `AUTH0_DOMAIN`, run the following command: + -```shell -auth0 tenants list -``` - -Copy the domain under `TENANT` from the output and update the corresponding variable on the `.env`. - -For `MCP_AUTH0_CLIENT_ID` and `MCP_AUTH0_CLIENT_SECRET` you will use the values obtained on the [Create an Application for your MCP server](./call-your-apis-on-users-behalf#create-an-application-for-your-mcp-server) step. + Once downloaded, extract the files and open the project in your preferred IDE. + + + Clone the repository and navigate to the sample app folder which includes a FastMCP MCP server with an Auth0 integration and a protected API built with + [Fastify](https://fastify.dev/). -## Use Custom Token Exchange Action + ```shell wrap lines + git clone https://github.com/auth0-samples/auth0-ai-samples.git + cd auth0-ai-samples/auth-for-mcp/fastmcp-mcp-customtokenexchange-js + ``` -This Action is the server-side logic Auth0 executes to perform the token exchange. It is necessary because the MCP server receives an access token from the client (with the MCP server as its audience) and must exchange it for a new token (with the upstream API as the audience). This Action validates the original token and mints the new one. + Once cloned, open the project in your preferred IDE. + + -The Custom Token Exchange Action, available as a part of Custom Token Exchange Early Access. Navigate to [the On-behalf-of token exchange for first-party apps template available here](https://manage.auth0.com/#/actions/library/templates/templates/daeda4e8-8da2-4abb-afb5-ac09df0ebb2a) and click on **Use This Template**. + The sample app demonstrates custom token exchange with a `greet` tool that calls your protected API on behalf of the authenticated user. - - Action On-behalf-of token exchange for first-party apps template page - + ## Install packages -This will open a modal for you to name the action: + Ensure you have npm installed or follow the instructions to [install npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) in its documentation. From the root of your sample app directory, install the required packages: - - Action creation modal - + ```shell + npm install + ``` -Once the action is created you can **Deploy** it. When you deploy the Action, Auth0 assigns it an Action ID. You still need to add your custom logic to the Action, but first, get the Action ID to create the Custom Token Exchange Profile. + ## Create your environment file + -## Setup the token exchange profile + ## Use Custom Token Exchange Action + - + ## Setup the token exchange profile -## Run the MCP server and the API + -Run this command to start your server: + ## Run the MCP server and the API + -```shell -npm run start -``` + ## Exchange your access token + + -And in a separate window run this command to start the API: + + + + Start by downloading the sample app for this quickstart. The sample includes a FastMCP MCP server with an Auth0 integration and a protected API built with + [Fastify](https://fastify.dev/). -```shell -npm run start:api -``` + -## Exchange your access token + Once downloaded, extract the files and open the project in your preferred IDE. + + + Clone the repository and navigate to the sample app folder which includes a FastMCP MCP server with an Auth0 integration and a protected Starlette-based API. -To call your APIs on behalf of your users, the MCP server needs to exchange the Auth0 access token it received from the MCP client (with the audience set to the MCP server itself) for a new Auth0 access token with the audience set to your API. In Auth0, this is called Custom Token Exchange and uses [RFC 8693](https://www.rfc-editor.org/rfc/rfc8693.html). + ```shell wrap lines + git clone https://github.com/auth0-samples/auth0-ai-samples.git + cd auth0-ai-samples/auth-for-mcp/fastmcp-mcp-customtokenexchange-python + ``` -### The Orchestrator: `bearerForUpstream` + Once cloned, open the project in your preferred IDE. + + + The sample app demonstrates custom token exchange with a `greet` tool that calls your protected API on behalf of the authenticated user. -The process begins with the `bearerForUpstream` function. Its main job is to take the initial token (the `subjectToken`), manage the exchange process, and handle any potential errors gracefully. + ## Install packages -This function serves as a safe wrapper around our exchange logic. + Ensure you have poetry installed or follow the instructions to [install poetry](https://python-poetry.org/docs/) in its documentation. From the root of your sample app directory, install the required packages: -```shell wrap lines highlight={5} -async function bearerForUpstream(subjectToken: string) { - if (!subjectToken) return { token: null, scopes: null }; + ```shell + poetry install + ``` - try { - const result = await exchangeCustomToken(subjectToken); - return { - token: result.accessToken, - scopes: result.scope, - } - } catch (err) { - console.error('Error during token exchange:', err); - throw err; - } -} -``` + ## Create your environment file + -As you can see, it calls `exchangeCustomToken` and, on a successful exchange, returns the new `accessToken` and its associated scope. If the exchange fails, it logs the error and re-throws it to be handled upstream. + ## Use Custom Token Exchange Action + -### The core logic: `exchangeCustomToken` + ## Setup the token exchange profile -This function, located in `src/auth0.ts`, contains the actual token exchange logic. It uses the `ApiClient` from the `auth0-api-js` SDK to simplify the interaction with Auth0's `/oauth/token` endpoint. + -First, we initialize the `ApiClient` with the credentials of the application performing the exchange: + ## Run the MCP server and the API + -```javascript wrap lines - const exchangeClient = new ApiClient({ - domain: AUTH0_DOMAIN, - audience: API_AUTH0_AUDIENCE, - clientId: MCP_AUTH0_CLIENT_ID, - clientSecret: MCP_AUTH0_CLIENT_SECRET, -}); -``` -With the client configured, the `exchangeCustomToken` function calls the `getTokenByExchangeProfile` method. This method implements the [Custom Token Exchange](https://auth0.com/docs/authenticate/custom-token-exchange) flow. - -```javascript wrap lines -export async function exchangeCustomToken(subjectToken: string) { - return await exchangeClient.getTokenByExchangeProfile(subjectToken, { - subjectTokenType: MCP_AUTH0_SUBJECT_TOKEN_TYPE, - audience: API_AUTH0_AUDIENCE, - ...(MCP_AUTH0_EXCHANGE_SCOPE && { scope: MCP_AUTH0_EXCHANGE_SCOPE }), - }); -} -``` + ## Exchange your access token + + + diff --git a/auth4genai/snippets/mcp/get-started/call-your-apis/create-env-file.mdx b/auth4genai/snippets/mcp/get-started/call-your-apis/create-env-file.mdx new file mode 100644 index 000000000..2f704fb17 --- /dev/null +++ b/auth4genai/snippets/mcp/get-started/call-your-apis/create-env-file.mdx @@ -0,0 +1,31 @@ +From the root of your sample app directory, run the following commnd to create a new `.env` file populated with all the required environment variables: + +```shell wrap lines expandable +CLIENT_ID=$(jq -r '.client_id' auth0-app-details.json) \ +&& CLIENT_SECRET=$(jq -r '.client_secret' auth0-app-details.json) \ +&& DOMAIN=$(auth0 tenants list --json | jq -r '.[] | select(.active == true) | .name') \ +&& touch .env \ +&& echo "AUTH0_DOMAIN=${DOMAIN}" > .env \ +&& echo "AUTH0_AUDIENCE=http://localhost:3001/" >> .env \ +&& echo "PORT=3001" >> .env \ +&& echo "MCP_SERVER_URL=http://localhost:3001/" >> .env \ +&& echo "MCP_AUTH0_CLIENT_ID=${CLIENT_ID}" >> .env \ +&& echo "MCP_AUTH0_CLIENT_SECRET=${CLIENT_SECRET}" >> .env \ +&& echo "MCP_AUTH0_SUBJECT_TOKEN_TYPE=urn:fastmcp:mcp" >> .env \ +&& echo "MCP_AUTH0_EXCHANGE_SCOPE=read:tasks" >> .env \ +&& echo "API_AUTH0_AUDIENCE=http://localhost:8787/" >> .env \ +&& echo "API_BASE_URL=http://localhost:8787/" >> .env \ +&& rm auth0-app-details.json \ +&& echo ".env file created with your Auth0 details:" \ +&& cat .env +``` + +To get your Auth0 application’s `AUTH0_DOMAIN`, run the following command: + +```shell +auth0 tenants list +``` + +Copy the domain under `TENANT` from the output and update the corresponding variable on the `.env`. + +For `MCP_AUTH0_CLIENT_ID` and `MCP_AUTH0_CLIENT_SECRET` you will use the values obtained on the [Create an Application for your MCP server](./call-your-apis-on-users-behalf#create-an-application-for-your-mcp-server) step. diff --git a/auth4genai/snippets/mcp/get-started/call-your-apis/custom-token-exchange-action.mdx b/auth4genai/snippets/mcp/get-started/call-your-apis/custom-token-exchange-action.mdx new file mode 100644 index 000000000..9e56534bf --- /dev/null +++ b/auth4genai/snippets/mcp/get-started/call-your-apis/custom-token-exchange-action.mdx @@ -0,0 +1,22 @@ +This Action is the server-side logic Auth0 executes to perform the token exchange. It is necessary because the MCP server receives an access token from the client (with the MCP server as its audience) and must exchange it for a new token (with the upstream API as the audience). This Action validates the original token and mints the new one. + +The Custom Token Exchange Action, available as a part of Custom Token Exchange Early Access. Navigate to [the On-behalf-of token exchange for first-party apps template available here](https://manage.auth0.com/#/actions/library/templates/templates/daeda4e8-8da2-4abb-afb5-ac09df0ebb2a) and click on **Use This Template**. + + + Action On-behalf-of token exchange for first-party apps template page + + +This will open a modal for you to name the action: + + + Action creation modal + + +Once the action is created you can **Deploy** it. When you deploy the Action, Auth0 assigns it an Action ID. You still need to add your custom logic to the Action, but first, get the Action ID to create the Custom Token Exchange Profile. diff --git a/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-js.mdx b/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-js.mdx new file mode 100644 index 000000000..a76b11dd5 --- /dev/null +++ b/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-js.mdx @@ -0,0 +1,52 @@ +To call your APIs on behalf of your users, the MCP server needs to exchange the Auth0 access token it received from the MCP client (with the audience set to the MCP server itself) for a new Auth0 access token with the audience set to your API. In Auth0, this is called Custom Token Exchange and uses [RFC 8693](https://www.rfc-editor.org/rfc/rfc8693.html). + +### The Orchestrator: `bearerForUpstream` + +The process begins with the `bearerForUpstream` function. Its main job is to take the initial token (the `subjectToken`), manage the exchange process, and handle any potential errors gracefully. + +This function serves as a safe wrapper around our exchange logic. + +```shell wrap lines highlight={5} +async function bearerForUpstream(subjectToken: string) { + if (!subjectToken) return { token: null, scopes: null }; + + try { + const result = await exchangeCustomToken(subjectToken); + return { + token: result.accessToken, + scopes: result.scope, + } + } catch (err) { + console.error('Error during token exchange:', err); + throw err; + } +} +``` + +As you can see, it calls `exchangeCustomToken` and, on a successful exchange, returns the new `accessToken` and its associated scope. If the exchange fails, it logs the error and re-throws it to be handled upstream. + +### The core logic: `exchangeCustomToken` + +This function, located in `src/auth0.ts`, contains the actual token exchange logic. It uses the `ApiClient` from the `auth0-api-js` SDK to simplify the interaction with Auth0's `/oauth/token` endpoint. + +First, we initialize the `ApiClient` with the credentials of the application performing the exchange: + +```javascript wrap lines + const exchangeClient = new ApiClient({ + domain: AUTH0_DOMAIN, + audience: API_AUTH0_AUDIENCE, + clientId: MCP_AUTH0_CLIENT_ID, + clientSecret: MCP_AUTH0_CLIENT_SECRET, +}); +``` +With the client configured, the `exchangeCustomToken` function calls the `getTokenByExchangeProfile` method. This method implements the [Custom Token Exchange](https://auth0.com/docs/authenticate/custom-token-exchange) flow. + +```javascript wrap lines +export async function exchangeCustomToken(subjectToken: string) { + return await exchangeClient.getTokenByExchangeProfile(subjectToken, { + subjectTokenType: MCP_AUTH0_SUBJECT_TOKEN_TYPE, + audience: API_AUTH0_AUDIENCE, + ...(MCP_AUTH0_EXCHANGE_SCOPE && { scope: MCP_AUTH0_EXCHANGE_SCOPE }), + }); +} +``` diff --git a/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-python.mdx b/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-python.mdx new file mode 100644 index 000000000..0e33ccc79 --- /dev/null +++ b/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-python.mdx @@ -0,0 +1,63 @@ +To call your APIs on behalf of your users, the MCP server needs to exchange the Auth0 access token it received from the MCP client (with the audience set to the MCP server itself) for a new Auth0 access token with the audience set to your API. In Auth0, this is called Custom Token Exchange and uses [RFC 8693](https://www.rfc-editor.org/rfc/rfc8693.html). + +### The core logic: `exchange_custom_token` + +The Python implementation uses the `exchange_custom_token` function that handles the token exchange process. + +```python wrap lines highlight={3,4,5,6,7,8} +async def exchange_custom_token(api_client, subject_token: str) -> dict: + """Exchange subject token for access token via Custom Token Exchange.""" + result = await api_client.get_token_by_exchange_profile( + subject_token=subject_token, + subject_token_type=config.mcp_auth0_subject_token_type, + audience=config.api_auth0_audience, + scope=config.mcp_auth0_exchange_scope or None + ) + return {"token": result["access_token"], "scopes": result.get("scope", "")} +``` + +This function uses the `get_token_by_exchange_profile` method of `ApiClient` from the `auth0-api-python` SDK and, on a successful exchange, returns the new `accessToken` and its associated scopes. This method implements the [Custom Token Exchange](https://auth0.com/docs/authenticate/custom-token-exchange) flow. + +### Client Configuration + +The `ApiClient` is initialized in the `Auth0Middleware` (located in `src/auth0/middleware.py`) with the credentials of the application performing the exchange: + +```python wrap lines +self.client = ApiClient(ApiClientOptions( + domain=domain, # AUTH0_DOMAIN + audience=audience, # API_AUTH0_AUDIENCE + client_id=client_id, # MCP_AUTH0_CLIENT_ID + client_secret=client_secret # MCP_AUTH0_CLIENT_SECRET +)) +``` + +The client then gets attached to the request context, making it available to all tools. + +### Using Token Exchange in MCP tools +Here's how it's implemented in the `greet` tool: + +```python wrap lines highlight={10,11,12,13,14} +@mcp.tool(name="greet") +@require_scopes(["tool:greet"]) +async def greet(name: str, ctx: Context) -> str: + user_name = name.strip() if name else "there" + auth_info = ctx.request_context.request.state.auth + user_id = auth_info.get("extra", {}).get("sub") + + logger.info(f"Greet tool invoked for user: {user_id}") + + # Exchange token and call upstream API + exchange_result = await exchange_custom_token( + ctx.request_context.request.state.api_client, + auth_info["token"] + ) + + async with httpx.AsyncClient() as client: + response = await client.get( + f"{config.api_base_url}/api/private-scope", + headers={"authorization": f"Bearer {exchange_result['token']}"} + ) + upstream_result = response.json() + + return f"Hello, {user_name} ({user_id})!\nUpstream API Response: {json.dumps(upstream_result, indent=2)}" +``` diff --git a/auth4genai/snippets/mcp/get-started/call-your-apis/run-mcp-server-js.mdx b/auth4genai/snippets/mcp/get-started/call-your-apis/run-mcp-server-js.mdx new file mode 100644 index 000000000..b0ce4d022 --- /dev/null +++ b/auth4genai/snippets/mcp/get-started/call-your-apis/run-mcp-server-js.mdx @@ -0,0 +1,11 @@ +Run this command to start your server: + +```shell +npm run start +``` + +And in a separate window run this command to start the API: + +```shell +npm run start:api +``` diff --git a/auth4genai/snippets/mcp/get-started/call-your-apis/run-mcp-server-python.mdx b/auth4genai/snippets/mcp/get-started/call-your-apis/run-mcp-server-python.mdx new file mode 100644 index 000000000..c026364b4 --- /dev/null +++ b/auth4genai/snippets/mcp/get-started/call-your-apis/run-mcp-server-python.mdx @@ -0,0 +1,11 @@ +Run this command to start your server: + +```shell +poetry run python -m src.server +``` + +And in a separate window run this command to start the API: + +```shell +poetry run python -m src.api.server +``` diff --git a/auth4genai/snippets/mcp/get-started/server-authorization.mdx b/auth4genai/snippets/mcp/get-started/server-authorization.mdx index 21132f661..e2c5a7809 100644 --- a/auth4genai/snippets/mcp/get-started/server-authorization.mdx +++ b/auth4genai/snippets/mcp/get-started/server-authorization.mdx @@ -20,60 +20,124 @@ By the end of this quickstart, you will have an MCP server that: +## Sample app - - Start by downloading the sample app for this quickstart. The sample includes a FastMCP MCP server with an Auth0 integration in JavaScript. - - - - Once downloaded, extract the files and open the project in your preferred IDE. - - - Clone the repository and navigate to the sample app folder which includes a FastMCP MCP server with an Auth0 integration in JavaScript. - - ```shell wrap lines - git clone https://github.com/auth0-samples/auth0-ai-samples.git - cd auth0-ai-samples/auth-for-mcp/fastmcp-mcp-js + + + + Start by downloading the sample app for this quickstart. The sample includes a FastMCP MCP server with an Auth0 integration in JavaScript. + + + + Once downloaded, extract the files and open the project in your preferred IDE. + + + Clone the repository and navigate to the sample app folder which includes a FastMCP MCP server with an Auth0 integration in JavaScript. + + ```shell wrap lines + git clone https://github.com/auth0-samples/auth0-ai-samples.git + cd auth0-ai-samples/auth-for-mcp/fastmcp-mcp-js + ``` + + Once cloned, open the project in your preferred IDE. + + + ## Install packages + + Ensure you have npm installed or follow the instructions to [install npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) in its documentation. In the `fastmcp-mcp-js` directory, install the required packages: + + ```shell + npm install ``` - Once cloned, open the project in your preferred IDE. + ## Create your environment file + + In the `fastmcp-mcp-js` directory, create a new `.env` file and add the following content: + + ```shell + AUTH0_DOMAIN= + AUTH0_AUDIENCE=http://localhost:3001 + PORT=3001 + MCP_SERVER_URL=http://localhost:3001 + ``` + + To get your Auth0 application’s `AUTH0_DOMAIN`, run the following command: + + ```shell + auth0 tenants list + ``` + + Copy the domain under `TENANT` from the output and update the corresponding variable on the `.env`. + + ## Run your MCP server + + Run this command to start your server: + + ```shell + npm run start + ``` - -## Install packages + + + + Start by downloading the sample app for this quickstart. The sample includes a FastMCP MCP server with an Auth0 integration in Python. -Ensure you have npm installed or follow the instructions to [install npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) in its documentation. In the `fastmcp-mcp-js` directory, install the required packages: + -```shell -npm install -``` + Once downloaded, extract the files and open the project in your preferred IDE. + + + Clone the repository and navigate to the sample app folder which includes a FastMCP MCP server with an Auth0 integration in Python. -## Create your environment file + ```shell wrap lines + git clone https://github.com/auth0-samples/auth0-ai-samples.git + cd auth0-ai-samples/auth-for-mcp/fastmcp-mcp-python + ``` -In the `fastmcp-mcp-js` directory, create a new `.env` file and add the following content: + Once cloned, open the project in your preferred IDE. + + + ## Install packages -```shell -AUTH0_DOMAIN= -AUTH0_AUDIENCE=http://localhost:3001 -PORT=3001 -MCP_SERVER_URL=http://localhost:3001 -``` + Ensure you have poetry installed or follow the instructions to [install poetry](https://python-poetry.org/docs/) in its documentation. In the `fastmcp-mcp-python` directory, install the required packages: -To get your Auth0 application’s `AUTH0_DOMAIN`, run the following command: + ```shell + poetry install + ``` + + ## Create your environment file + + In the `fastmcp-mcp-python` directory, create a new `.env` file and add the following content: -```shell -auth0 tenants list -``` + ```shell + AUTH0_DOMAIN= + AUTH0_AUDIENCE=http://localhost:3001 + PORT=3001 + MCP_SERVER_URL=http://localhost:3001 + ``` + + To get your Auth0 application’s `AUTH0_DOMAIN`, run the following command: -Copy the domain under `TENANT` from the output and update the corresponding variable on the `.env`. + ```shell + auth0 tenants list + ``` -## Run your MCP server + Copy the domain under `TENANT` from the output and update the corresponding variable on the `.env`. -Run this command to start your server: + ## Run your MCP server + + Run this command to start your server: + + ```shell + poetry run python -m src.server + ``` + + -```shell -npm run start -``` From ccd1408e9fc234a663955c4db3a7b687f5f8737b Mon Sep 17 00:00:00 2001 From: Patrick Kang <1489148+patrickkang@users.noreply.github.com> Date: Tue, 18 Nov 2025 09:17:50 -0500 Subject: [PATCH 02/10] update --- auth4genai/mcp/get-started/call-your-apis-on-users-behalf.mdx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/auth4genai/mcp/get-started/call-your-apis-on-users-behalf.mdx b/auth4genai/mcp/get-started/call-your-apis-on-users-behalf.mdx index 03f0bf57a..e9873adce 100644 --- a/auth4genai/mcp/get-started/call-your-apis-on-users-behalf.mdx +++ b/auth4genai/mcp/get-started/call-your-apis-on-users-behalf.mdx @@ -149,8 +149,7 @@ Save the `Audience` from the command output; you'll need it in a later step. - Start by downloading the sample app for this quickstart. The sample includes a FastMCP MCP server with an Auth0 integration and a protected API built with - [Fastify](https://fastify.dev/). + Start by downloading the sample app for this quickstart. The sample includes a FastMCP MCP server with an Auth0 integration and a protected Starlette-based API. Date: Wed, 19 Nov 2025 15:02:50 -0500 Subject: [PATCH 03/10] fix code block language in exchange-access-token-js.mdx --- .../mcp/get-started/call-your-apis/exchange-access-token-js.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-js.mdx b/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-js.mdx index a76b11dd5..e041d34e8 100644 --- a/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-js.mdx +++ b/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-js.mdx @@ -6,7 +6,7 @@ The process begins with the `bearerForUpstream` function. Its main job is to tak This function serves as a safe wrapper around our exchange logic. -```shell wrap lines highlight={5} +```javascript wrap lines highlight={5} async function bearerForUpstream(subjectToken: string) { if (!subjectToken) return { token: null, scopes: null }; From b7481327e6b1b3351b176b42c1e4c2dece407a64 Mon Sep 17 00:00:00 2001 From: Patrick Kang <1489148+patrickkang@users.noreply.github.com> Date: Wed, 19 Nov 2025 15:33:34 -0500 Subject: [PATCH 04/10] fix broken link --- .../snippets/mcp/get-started/call-your-apis/create-env-file.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auth4genai/snippets/mcp/get-started/call-your-apis/create-env-file.mdx b/auth4genai/snippets/mcp/get-started/call-your-apis/create-env-file.mdx index a38a02b7d..9868c474b 100644 --- a/auth4genai/snippets/mcp/get-started/call-your-apis/create-env-file.mdx +++ b/auth4genai/snippets/mcp/get-started/call-your-apis/create-env-file.mdx @@ -28,4 +28,4 @@ auth0 tenants list Copy the domain under `TENANT` from the output and update the corresponding variable in the `.env` file. -For `MCP_AUTH0_CLIENT_ID` and `MCP_AUTH0_CLIENT_SECRET` you will use the values obtained from the [Create an Application for your MCP server](./call-your-apis-on-users-behalf#create-an-application-for-your-mcp-server) step. +For `MCP_AUTH0_CLIENT_ID` and `MCP_AUTH0_CLIENT_SECRET` you will use the values obtained from the [Create an Application for your MCP server](/mcp/get-started/call-your-apis-on-users-behalf#create-an-application-for-your-mcp-server) step. From 988a061202aca38d480318847c4378b085cd4f78 Mon Sep 17 00:00:00 2001 From: Patrick Kang <1489148+patrickkang@users.noreply.github.com> Date: Wed, 19 Nov 2025 16:12:28 -0500 Subject: [PATCH 05/10] adds code snippet --- .../call-your-apis/exchange-access-token-python.mdx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-python.mdx b/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-python.mdx index 0e33ccc79..a7f5bfdef 100644 --- a/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-python.mdx +++ b/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-python.mdx @@ -22,7 +22,7 @@ This function uses the `get_token_by_exchange_profile` method of `ApiClient` fro The `ApiClient` is initialized in the `Auth0Middleware` (located in `src/auth0/middleware.py`) with the credentials of the application performing the exchange: -```python wrap lines +```python src/auth0/middleware.py wrap lines self.client = ApiClient(ApiClientOptions( domain=domain, # AUTH0_DOMAIN audience=audience, # API_AUTH0_AUDIENCE @@ -31,7 +31,12 @@ self.client = ApiClient(ApiClientOptions( )) ``` -The client then gets attached to the request context, making it available to all tools. +The client then gets attached to the request context, making it available to all tools: + +```python src/auth0/middleware.py wrap lines +# In the Auth0Middleware dispatch method +request.state.api_client = self.client +``` ### Using Token Exchange in MCP tools Here's how it's implemented in the `greet` tool: From a7806c6406ea3b3a7d33cb4669defd972a5e350f Mon Sep 17 00:00:00 2001 From: Patrick Kang <1489148+patrickkang@users.noreply.github.com> Date: Wed, 19 Nov 2025 16:29:46 -0500 Subject: [PATCH 06/10] addressing feedback --- .../mcp/get-started/call-your-apis-on-users-behalf.mdx | 3 ++- .../call-your-apis/exchange-access-token-js.mdx | 2 +- .../call-your-apis/exchange-access-token-python.mdx | 8 ++++---- .../snippets/mcp/get-started/server-authorization.mdx | 4 ++-- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/auth4genai/mcp/get-started/call-your-apis-on-users-behalf.mdx b/auth4genai/mcp/get-started/call-your-apis-on-users-behalf.mdx index e9873adce..c78bcd3d8 100644 --- a/auth4genai/mcp/get-started/call-your-apis-on-users-behalf.mdx +++ b/auth4genai/mcp/get-started/call-your-apis-on-users-behalf.mdx @@ -169,7 +169,8 @@ Save the `Audience` from the command output; you'll need it in a later step. Once cloned, open the project in your preferred IDE. - The sample app demonstrates custom token exchange with a `greet` tool that calls your protected API on behalf of the authenticated user. + + The sample app demonstrates custom token exchange with a `greet` tool that calls your protected API on behalf of the authenticated user. ## Install packages diff --git a/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-js.mdx b/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-js.mdx index e041d34e8..901ea5167 100644 --- a/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-js.mdx +++ b/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-js.mdx @@ -39,7 +39,7 @@ First, we initialize the `ApiClient` with the credentials of the application per clientSecret: MCP_AUTH0_CLIENT_SECRET, }); ``` -With the client configured, the `exchangeCustomToken` function calls the `getTokenByExchangeProfile` method. This method implements the [Custom Token Exchange](https://auth0.com/docs/authenticate/custom-token-exchange) flow. +With the client configured, the `exchangeCustomToken` function uses the client's `getTokenByExchangeProfile` method to perform the token exchange. This method implements the [Custom Token Exchange](https://auth0.com/docs/authenticate/custom-token-exchange) flow. ```javascript wrap lines export async function exchangeCustomToken(subjectToken: string) { diff --git a/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-python.mdx b/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-python.mdx index a7f5bfdef..a9964ba23 100644 --- a/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-python.mdx +++ b/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-python.mdx @@ -24,10 +24,10 @@ The `ApiClient` is initialized in the `Auth0Middleware` (located in `src/auth0/m ```python src/auth0/middleware.py wrap lines self.client = ApiClient(ApiClientOptions( - domain=domain, # AUTH0_DOMAIN - audience=audience, # API_AUTH0_AUDIENCE - client_id=client_id, # MCP_AUTH0_CLIENT_ID - client_secret=client_secret # MCP_AUTH0_CLIENT_SECRET + domain=domain, # AUTH0_DOMAIN env var + audience=audience, # API_AUTH0_AUDIENCE env var + client_id=client_id, # MCP_AUTH0_CLIENT_ID env var + client_secret=client_secret # MCP_AUTH0_CLIENT_SECRET env var )) ``` diff --git a/auth4genai/snippets/mcp/get-started/server-authorization.mdx b/auth4genai/snippets/mcp/get-started/server-authorization.mdx index c59c091e1..04f5a59a1 100644 --- a/auth4genai/snippets/mcp/get-started/server-authorization.mdx +++ b/auth4genai/snippets/mcp/get-started/server-authorization.mdx @@ -58,7 +58,7 @@ By the end of this quickstart, you will have an MCP server that: In the `fastmcp-mcp-js` directory, create a new `.env` file and add the following content: ```shell - AUTH0_DOMAIN= + AUTH0_DOMAIN=YOUR_AUTH0_DOMAIN AUTH0_AUDIENCE=http://localhost:3001 PORT=3001 MCP_SERVER_URL=http://localhost:3001 @@ -117,7 +117,7 @@ By the end of this quickstart, you will have an MCP server that: In the `fastmcp-mcp-python` directory, create a new `.env` file and add the following content: ```shell - AUTH0_DOMAIN= + AUTH0_DOMAIN=YOUR_AUTH0_DOMAIN AUTH0_AUDIENCE=http://localhost:3001 PORT=3001 MCP_SERVER_URL=http://localhost:3001 From f1612d0a39005cfa0915d4fe111ec982e6cd6bc7 Mon Sep 17 00:00:00 2001 From: Patrick Kang <1489148+patrickkang@users.noreply.github.com> Date: Wed, 19 Nov 2025 17:21:18 -0500 Subject: [PATCH 07/10] addressing feedback --- auth4genai/mcp/get-started/call-your-apis-on-users-behalf.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auth4genai/mcp/get-started/call-your-apis-on-users-behalf.mdx b/auth4genai/mcp/get-started/call-your-apis-on-users-behalf.mdx index c78bcd3d8..44e64e8b9 100644 --- a/auth4genai/mcp/get-started/call-your-apis-on-users-behalf.mdx +++ b/auth4genai/mcp/get-started/call-your-apis-on-users-behalf.mdx @@ -124,7 +124,7 @@ Save the `Audience` from the command output; you'll need it in a later step. ## Install packages - Ensure you have npm installed or follow the instructions to [install npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) in its documentation. From the root of your sample app directory, install the required packages: + Ensure you have npm installed or follow the instructions to [install npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) in its documentation. In the `fastmcp-mcp-customtokenexchange-js` directory, install the required packages: ```shell npm install @@ -174,7 +174,7 @@ Save the `Audience` from the command output; you'll need it in a later step. ## Install packages - Ensure you have poetry installed or follow the instructions to [install poetry](https://python-poetry.org/docs/) in its documentation. From the root of your sample app directory, install the required packages: + Ensure you have poetry installed or follow the instructions to [install poetry](https://python-poetry.org/docs/) in its documentation. In the `fastmcp-mcp-customtokenexchange-python` directory, install the required packages: ```shell poetry install From 10717ff09e26e486d7d1218e8850ea6239515daa Mon Sep 17 00:00:00 2001 From: Patrick Kang <1489148+patrickkang@users.noreply.github.com> Date: Wed, 19 Nov 2025 17:28:27 -0500 Subject: [PATCH 08/10] addressing feedback --- .../exchange-access-token-python.mdx | 59 ++++++++++--------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-python.mdx b/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-python.mdx index a9964ba23..e98ade477 100644 --- a/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-python.mdx +++ b/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-python.mdx @@ -1,5 +1,34 @@ To call your APIs on behalf of your users, the MCP server needs to exchange the Auth0 access token it received from the MCP client (with the audience set to the MCP server itself) for a new Auth0 access token with the audience set to your API. In Auth0, this is called Custom Token Exchange and uses [RFC 8693](https://www.rfc-editor.org/rfc/rfc8693.html). +### How tools use token exchange +Here's how the `greet` tool performs token exchange and calls the upstream API: + +```python wrap lines highlight={10,11,12,13,14} +@mcp.tool(name="greet") +@require_scopes(["tool:greet"]) +async def greet(name: str, ctx: Context) -> str: + user_name = name.strip() if name else "there" + auth_info = ctx.request_context.request.state.auth + user_id = auth_info.get("extra", {}).get("sub") + + logger.info(f"Greet tool invoked for user: {user_id}") + + # Exchange token and call upstream API + exchange_result = await exchange_custom_token( + ctx.request_context.request.state.api_client, + auth_info["token"] + ) + + async with httpx.AsyncClient() as client: + response = await client.get( + f"{config.api_base_url}/api/private-scope", + headers={"authorization": f"Bearer {exchange_result['token']}"} + ) + upstream_result = response.json() + + return f"Hello, {user_name} ({user_id})!\nUpstream API Response: {json.dumps(upstream_result, indent=2)}" +``` + ### The core logic: `exchange_custom_token` The Python implementation uses the `exchange_custom_token` function that handles the token exchange process. @@ -31,38 +60,10 @@ self.client = ApiClient(ApiClientOptions( )) ``` -The client then gets attached to the request context, making it available to all tools: +The configured client is then attached to the request context during middleware processing, making it available to all tools: ```python src/auth0/middleware.py wrap lines # In the Auth0Middleware dispatch method request.state.api_client = self.client ``` -### Using Token Exchange in MCP tools -Here's how it's implemented in the `greet` tool: - -```python wrap lines highlight={10,11,12,13,14} -@mcp.tool(name="greet") -@require_scopes(["tool:greet"]) -async def greet(name: str, ctx: Context) -> str: - user_name = name.strip() if name else "there" - auth_info = ctx.request_context.request.state.auth - user_id = auth_info.get("extra", {}).get("sub") - - logger.info(f"Greet tool invoked for user: {user_id}") - - # Exchange token and call upstream API - exchange_result = await exchange_custom_token( - ctx.request_context.request.state.api_client, - auth_info["token"] - ) - - async with httpx.AsyncClient() as client: - response = await client.get( - f"{config.api_base_url}/api/private-scope", - headers={"authorization": f"Bearer {exchange_result['token']}"} - ) - upstream_result = response.json() - - return f"Hello, {user_name} ({user_id})!\nUpstream API Response: {json.dumps(upstream_result, indent=2)}" -``` From 7e165aa504df36cb498518ef7dd5dd2a2a9d0a37 Mon Sep 17 00:00:00 2001 From: Patrick Kang <1489148+patrickkang@users.noreply.github.com> Date: Wed, 26 Nov 2025 17:41:26 -0500 Subject: [PATCH 09/10] address feedback --- .../get-started/call-your-apis/create-env-file.mdx | 12 +----------- .../call-your-apis/exchange-access-token-python.mdx | 4 ++-- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/auth4genai/snippets/mcp/get-started/call-your-apis/create-env-file.mdx b/auth4genai/snippets/mcp/get-started/call-your-apis/create-env-file.mdx index 9868c474b..890c04dd7 100644 --- a/auth4genai/snippets/mcp/get-started/call-your-apis/create-env-file.mdx +++ b/auth4genai/snippets/mcp/get-started/call-your-apis/create-env-file.mdx @@ -12,20 +12,10 @@ CLIENT_ID=$(jq -r '.client_id' auth0-app-details.json) \ && echo "MCP_AUTH0_CLIENT_ID=${CLIENT_ID}" >> .env \ && echo "MCP_AUTH0_CLIENT_SECRET=${CLIENT_SECRET}" >> .env \ && echo "MCP_AUTH0_SUBJECT_TOKEN_TYPE=urn:fastmcp:mcp" >> .env \ -&& echo "MCP_AUTH0_EXCHANGE_SCOPE=read:tasks" >> .env \ +&& echo "MCP_AUTH0_EXCHANGE_SCOPE=openid offline_access read:private" >> .env \ && echo "API_AUTH0_AUDIENCE=http://localhost:8787/" >> .env \ && echo "API_BASE_URL=http://localhost:8787/" >> .env \ && rm auth0-app-details.json \ && echo ".env file created with your Auth0 details:" \ && cat .env ``` - -To get your Auth0 application’s `AUTH0_DOMAIN`, run the following command: - -```shell -auth0 tenants list -``` - -Copy the domain under `TENANT` from the output and update the corresponding variable in the `.env` file. - -For `MCP_AUTH0_CLIENT_ID` and `MCP_AUTH0_CLIENT_SECRET` you will use the values obtained from the [Create an Application for your MCP server](/mcp/get-started/call-your-apis-on-users-behalf#create-an-application-for-your-mcp-server) step. diff --git a/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-python.mdx b/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-python.mdx index e98ade477..3a8b14b05 100644 --- a/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-python.mdx +++ b/auth4genai/snippets/mcp/get-started/call-your-apis/exchange-access-token-python.mdx @@ -3,7 +3,7 @@ To call your APIs on behalf of your users, the MCP server needs to exchange the ### How tools use token exchange Here's how the `greet` tool performs token exchange and calls the upstream API: -```python wrap lines highlight={10,11,12,13,14} +```python wrap lines highlight={10,11,12,13,14,19} @mcp.tool(name="greet") @require_scopes(["tool:greet"]) async def greet(name: str, ctx: Context) -> str: @@ -45,7 +45,7 @@ async def exchange_custom_token(api_client, subject_token: str) -> dict: return {"token": result["access_token"], "scopes": result.get("scope", "")} ``` -This function uses the `get_token_by_exchange_profile` method of `ApiClient` from the `auth0-api-python` SDK and, on a successful exchange, returns the new `accessToken` and its associated scopes. This method implements the [Custom Token Exchange](https://auth0.com/docs/authenticate/custom-token-exchange) flow. +This function uses the `get_token_by_exchange_profile` method of `ApiClient` from the `auth0-api-python` SDK and, on a successful exchange, returns the new access token and its associated scopes. This method implements the [Custom Token Exchange](https://auth0.com/docs/authenticate/custom-token-exchange) flow. ### Client Configuration From d34d28e0c3349db7d4b1c31633cc62ed010605be Mon Sep 17 00:00:00 2001 From: Patrick Kang <1489148+patrickkang@users.noreply.github.com> Date: Thu, 27 Nov 2025 13:57:11 -0500 Subject: [PATCH 10/10] simplify env file creation --- .../mcp/get-started/create-mcp-api.mdx | 2 +- .../mcp/get-started/server-authorization.mdx | 52 ++++++++----------- 2 files changed, 23 insertions(+), 31 deletions(-) diff --git a/auth4genai/snippets/mcp/get-started/create-mcp-api.mdx b/auth4genai/snippets/mcp/get-started/create-mcp-api.mdx index b720f4849..833dedf12 100644 --- a/auth4genai/snippets/mcp/get-started/create-mcp-api.mdx +++ b/auth4genai/snippets/mcp/get-started/create-mcp-api.mdx @@ -18,4 +18,4 @@ auth0 api post resource-servers --data '{ Note that `rfc9068_profile_authz` is used as the [token dialect](https://auth0.com/docs/get-started/apis/enable-role-based-access-control-for-apis#token-dialect-options) to include the `permissions` claim in the access token, which can be useful for the API to check user permissions without making additional calls. -For more details on protecting APIs with Auth0, check our [quickstarts](https://auth0.com/docs/quickstarts#backend%2Fapi). \ No newline at end of file +For more details on protecting APIs with Auth0, check our [quickstarts](https://auth0.com/docs/quickstarts#backend%2Fapi). diff --git a/auth4genai/snippets/mcp/get-started/server-authorization.mdx b/auth4genai/snippets/mcp/get-started/server-authorization.mdx index 53a59b355..3bf0cc9ce 100644 --- a/auth4genai/snippets/mcp/get-started/server-authorization.mdx +++ b/auth4genai/snippets/mcp/get-started/server-authorization.mdx @@ -58,23 +58,19 @@ By the end of this quickstart, you will have an MCP server that: ## Create your environment file - In the `fastmcp-mcp-js` directory, create a new `.env` file and add the following content: - - ```shell - AUTH0_DOMAIN=YOUR_AUTH0_DOMAIN - AUTH0_AUDIENCE=http://localhost:3001 - PORT=3001 - MCP_SERVER_URL=http://localhost:3001 + In the `fastmcp-mcp-js` directory, run the following command to create a new `.env` file populated with all the required environment variables: + + ```shell wrap lines + DOMAIN=$(auth0 tenants list --json | jq -r '.[] | select(.active == true) | .name') \ + && touch .env \ + && echo "AUTH0_DOMAIN=${DOMAIN}" > .env \ + && echo "AUTH0_AUDIENCE=http://localhost:3001/" >> .env \ + && echo "PORT=3001" >> .env \ + && echo "MCP_SERVER_URL=http://localhost:3001/" >> .env \ + && echo ".env file created with your Auth0 details:" \ + && cat .env ``` - To get your Auth0 application’s `AUTH0_DOMAIN`, run the following command: - - ```shell - auth0 tenants list - ``` - - Copy the domain under `TENANT` from the output and update the corresponding variable in the `.env` file. - ## Run your MCP server Run this command to start your server: @@ -117,23 +113,19 @@ By the end of this quickstart, you will have an MCP server that: ## Create your environment file - In the `fastmcp-mcp-python` directory, create a new `.env` file and add the following content: - - ```shell - AUTH0_DOMAIN=YOUR_AUTH0_DOMAIN - AUTH0_AUDIENCE=http://localhost:3001 - PORT=3001 - MCP_SERVER_URL=http://localhost:3001 + In the `fastmcp-mcp-python` directory, run the following command to create a new `.env` file populated with all the required environment variables: + + ```shell wrap lines + DOMAIN=$(auth0 tenants list --json | jq -r '.[] | select(.active == true) | .name') \ + && touch .env \ + && echo "AUTH0_DOMAIN=${DOMAIN}" > .env \ + && echo "AUTH0_AUDIENCE=http://localhost:3001/" >> .env \ + && echo "PORT=3001" >> .env \ + && echo "MCP_SERVER_URL=http://localhost:3001/" >> .env \ + && echo ".env file created with your Auth0 details:" \ + && cat .env ``` - To get your Auth0 application’s `AUTH0_DOMAIN`, run the following command: - - ```shell - auth0 tenants list - ``` - - Copy the domain under `TENANT` from the output and update the corresponding variable in the `.env` file. - ## Run your MCP server Run this command to start your server: