Use Quarkus MCP client to access secure MCP HTTP server from command line
Introduction
In the Use Quarkus MCP client to access secure MCP HTTP servers blog post, we explained how a user can login to Quarkus LangChain4j AI server application with GitHub OAuth2 and have Google AI Gemini use Quarkus MCP Client to access a secure Quarkus MCP Server user name provider tool with a GitHub access token.
However, not every AI service application is going to be designed to require a user login: for example, it may run as a command line application or cron scheduler. But also, not every AI service application that requires a user login will be able to use a user login token to access a secure MCP server because such a server may only support tokens of different type.
In this blog post, we will explain how Quarkus MCP Client that runs in a command line Quarkus LangChain4j AI application can itself acquire an access token using an OAuth2 client_credentials
grant and use it to access a secure Quarkus MCP Server service account name provider tool.
We will work with Keycloak and rely on it to demonstrate how to approach securing complex, distributed AI applications that may span multiple security boundaries, by requiring that access tokens are restricted to specific audiences, and exchanging them to acquire new, correct audiences.
Demo architecture

As you can see in the diagram above, a command line agent uses a Poem Service
AI service to create a poem. The Poem Service
uses AI Gemini
and requests MCP Client
to complete a tool call to help AI Gemini
to find out the service account name.
The MCP client must use an access token. It uses an OAuth2 client_credential
grant to acquire a service account token and propagate it to the secure MCP server. This service account token’s audience restricts it to accessing the MCP server only.
The MCP server tool implementation must access a REST server to complete the tool action. However, it can not use the current access token that is restricted to accessing this MCP server because the REST server accepts tokens that are meant to access this REST server only.
Therefore, the MCP server exchanges the current token to set the REST server audience before propagating it, with the REST server successfully completing the secure tool call, with the response returned to the MCP Client.
We are now ready to start working on the demo.
You can find the complete project source in the Quarkus LangChain4j Command Line Secure MCP Client Server sample.
Step 1 - Create and start MCP server
First, let’s create a secure Quarkus MCP SSE server that can enforce an authenticated access to its tool, verify that the access token has a correct audience, and complete a tool action by exchanging the current access token for a new access token with the REST server audience and propagating this token to the REST server to get the required service account name.
MCP server maven dependencies
Add the following dependencies:
<dependency>
<groupId>io.quarkiverse.mcp</groupId>
<artifactId>quarkus-mcp-server-sse</artifactId> (1)
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-oidc</artifactId> (2)
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest</artifactId> (3)
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-client-oidc-token-propagation</artifactId> (4)
</dependency>
1 | quarkus-mcp-server-sse is required to support MCP Streamable HTTP and SSE transports. |
2 | quarkus-oidc is required to secure access to MCP SSE endpoints. Its version is defined in the Quarkus BOM. |
3 | quarkus-rest is required to support REST server that the MCP tool has to call. Its version is defined in the Quarkus BOM. |
4 | quarkus-rest-client-oidc-token-propagation also brings quarkus-rest-client and is required to support a REST client call to REST server with the token exchange and propagation. Its version is defined in the Quarkus BOM. |
MCP Service Account Name Tool
Let’s create a tool that can return a name of the current service account.
package io.quarkiverse.langchain4j.sample;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import io.quarkiverse.mcp.server.TextContent;
import io.quarkiverse.mcp.server.Tool;
import jakarta.inject.Inject;
public class ServiceAccountNameProvider { (1)
@RestClient
@Inject
ServiceAccountNameRestClient serviceAccountNameRestClient; (2)
@Tool(name = "sevice-account-name-provider", description = "Provides a name of the current service account") (1)
TextContent provideServiceAccountName() {
return new TextContent(serviceAccountNameRestClient.getServiceAccountName()); (2)
}
}
1 | Provide a tool that can return a name of the current service account. |
2 | Use an injected ServiceAccountNameRestClient to access the REST server to complete the service account name request. See the Service Account Name REST client section below for more details. |
The MCP server tool can be invoked only if the current MCP request is authenticated. In this blog post we do not enforce the secure tool access with annotations such as @PermissionAllowed or @Authenticated but only use the HTTP security policy configuration instead. See how both main MCP SSE and tool endpoints are secured in the MCP Server Configuration section below. |
Service Account Name REST client
The MCP Service Account Name Tool uses the Service Account Name REST client to call the REST server to complete a service account name request.
This REST client looks like this:
package io.quarkiverse.langchain4j.sample;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import io.quarkus.oidc.token.propagation.common.AccessToken;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Produces;
@RegisterRestClient
@AccessToken (2)
public interface ServiceAccountNameRestClient {
@GET
@Produces("text/plain")
String getServiceAccountName(); (1)
}
1 | Get a service account name from the REST server. See the Service Account Name REST server section below for more details. |
2 | Use @AccessToken annotation to require the access token exchange and propagation. This single @AccessToken annotation, supported by an additional configuration in the MCP Server Configuration section below, is all that is required to support this complex access token flow. |
Service Account Name REST server
The MCP Service Account Name Tool uses the Service Account Name REST client to get a service account name from the Service Account Name REST server.
This REST server looks like this:
package io.quarkiverse.langchain4j.sample;
import io.quarkus.security.Authenticated;
import io.quarkus.security.identity.SecurityIdentity;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
@Path("/service-account-name")
public class ServiceAccountNameRestServer {
@Inject
SecurityIdentity securityIdentity;
@GET
@Produces("text/plain")
@Authenticated (1)
public String getServiceAccountName() {
return securityIdentity.getPrincipal().getName(); (2)
}
}
1 | Provide a secure REST resource method that can return a service account name |
2 | Use an injected SecurityIdentity to complete the method’s task, in this case - return a service account identity name. |
In this demo, the REST server is collocated with the MCP server to simplify the demo. Of course, in production, such REST servers will most likely be remote.
Next, let’s have a look, in the MCP Server Configuration section, how access to both the MCP Service Account Name Tool and this server is restricted to tokens with specific audiences only.
MCP Server Configuration
Let’s configure our secure MCP server:
# MCP server
quarkus.mcp.server.server-info.name=Service Account Name Provider (1)
quarkus.mcp.server.traffic-logging.enabled=true
quarkus.mcp.server.traffic-logging.text-limit=1000
# Require an authenticated access to MCP server
quarkus.http.auth.permission.authenticated.paths=/mcp/* (2)
quarkus.http.auth.permission.authenticated.policy=authenticated
# Default Quarkus OIDC tenant that verifies access tokens which reach the MCP server.
quarkus.oidc.client-id=quarkus-mcp-server (3)
quarkus.oidc.token.audience=quarkus-mcp-server (4)
# Request a token exchange before the token propagation
quarkus.rest-client-oidc-token-propagation.exchange-token=true (4)
# OIDC client that performs the current token exchange
quarkus.oidc-client.auth-server-url=${quarkus.oidc.auth-server-url} (5)
quarkus.oidc-client.client-id=${quarkus.oidc.client-id}
quarkus.oidc-client.credentials.secret=${quarkus.oidc.credentials.secret}
quarkus.oidc-client.scopes=quarkus-mcp-service-scope
quarkus.oidc-client.grant.type=exchange
quarkus.oidc-client.grant-options.exchange.subject_token_type=urn:ietf:params:oauth:token-type:access_token (6)
# REST client which accesses a protected REST server, by propagating the exchanged token
io.quarkiverse.langchain4j.sample.ServiceAccountNameRestClient/mp-rest/url=http://localhost:8080/service-account-name (7)
# OIDC `service-account-name-rest-server` tenant that secures a protected REST server.
quarkus.oidc.service-account-name-rest-server.auth-server-url=${quarkus.oidc.auth-server-url} (8)
quarkus.oidc.service-account-name-rest-server.token.audience=quarkus-mcp-service (9)
quarkus.oidc.service-account-name-rest-server.tenant-paths=/service-account-name
# Keycloak devservice that enables a default OIDC tenant that secures MCP server.
quarkus.keycloak.devservices.image-name=quay.io/keycloak/keycloak:26.3.1 (10)
quarkus.keycloak.devservices.port=8081
# Keycloak may require more memory on some systems
quarkus.keycloak.devservices.container-memory-limit=1250M
1 | Declare MCP server and enable traffic logging. |
2 | Enforce an authenticated access to the main MCP SSE and tool endpoints. The configured pattern covers both the initial '/mcp/sse' handshake and '/mcp/messages/' requests. |
3 | Default OIDC tenant that secures the MCP SSE endpoint and tool. It is supported by Keycloak Dev Service in dev mode. In simple cases you do not even have to configure the default OIDC tenant. But in this demo, the default OIDC tenant is required to enforce that the tokens which reach the MCP server contain a quarkus-mcp-server audience. |
4 | Request an access token exchange before the Service Account Name REST client propagates it. |
5 | Configure OIDC client to perform the token exchange |
6 | Set the type of a new token that the current token will be exchanged for to access_token . Starting from Quarkus 3.25, an expected new token type will be set to access_token by default, and users will not have to configure this property when the access token type is required when exchanging tokens. |
7 | Configure the Service Account Name REST client with the REST server address. The REST server is collocated with the MCP server only to simplify the demo. |
8 | The OIDC tenant that protects the REST server only. |
9 | The OIDC tenant that protects the REST server requires that the tokens that are used to access it contain a REST server quarkus-mcp-service audience. |
10 | Configure Keycloak dev service to use one of the latest released Keycloak images, and make it run on a fixed 8081 port to simplify the Poem Service Configuration where an access to Keycloak is also required. |
Start the MCP server in dev mode
Now let’s start the MCP server in dev mode:
mvn quarkus:dev
and go to the Step 2 - Keycloak setup in the next section to complete the Keycloak configuration that is required to support the secure MCP server token audience and exchange requirements.
Step 2 - Keycloak setup
When we started the MCP server in dev mode, Keycloak Dev Service launched a Keycloak container, made it available on port 8081
, created a quarkus
realm with the quarkus-mcp-server
client - this client name was configured with the quarkus.oidc.client-id=quarkus-mcp-server
property in the MCP Server Configuration section.
The quarkus-mcp-server
client represents a confidential OIDC client that protects the MCP server.
But MCP server and REST server have additional token audience and exchange requirements and we must complete the Keycloak setup to support those requirements. Let’s do it.
Go to http://localhost:8081
and login as a Keycloak admin, with the admin
name and admin
password credentials.
Select the quarkus
realm:

First, create a quarkus-mcp-client
OIDC client that the Quarkus MCP client will use to acquire OAuth2 client_credentials
tokens for accessing the MCP server.
Start with the General Settings
:

and enable Client authentication
and Service accounts roles
capabilities:

Save the quarkus-mcp-client
OIDC client. Click on its Credentials
tab and copy the generated secret to export it later as the OIDC client secret in order to run the command line AI Poem Service
application.
For the Quarkus MCP client to be able to access MCP server with access tokens that the quarkus-mcp-client
OIDC client will acquire, these tokens must contain an audience (aud
) claim with a quarkus-mcp-server
audience. The MCP server is configured in the MCP Server Configuration section to require this audience.
Keycloak supports several options for adding an audience (aud
) claim to issued tokens. We will use an option that involves creating a custom Client scope
with an Audience
mapping.
Go to the Client scopes
and create an Optional
quarkus-mcp-server-scope
:

Once the quarkus-mcp-server-scope
scope is created, go to its Mappings
tab, and choose Configure a new mapper
option and select Audience
:

Name this mapper as quarkus-mcp-server-as-audience
and choose quarkus-mcp-server
as an Included Client Audience
:

Once the quarkus-mcp-server-scope
is created, add it as an Optional
scope to the quarkus-mcp-client
:

Now, when Quarkus MCP client will use the quarkus-mcp-client
OIDC client to acquire tokens, it will request a quarkus-mcp-server-scope
token scope, resulting in Keycloak issuing tokens with an audience that contains the quarkus-mcp-server
- exactly what the Quarkus MCP server requires.
Next, we need to support Quarkus MCP server exchanging the incoming access token with the quarkus-mcp-server
audience for a new token that will contain a REST server audience instead.
Create a quarkus-mcp-service
OIDC client that represents the REST server, similarly to how you created the quarkus-mcp-client
OIDC client. Next, create a quarkus-mcp-service-scope
client scope, similarly to how you created the quarkus-mcp-server-scope
client scope, choosing the quarkus-mcp-service
as an Included Client Audience
when creating an audience mapping for this scope.
Once the quarkus-mcp-service-scope
is created, add it as an Optional
client scope to the quarkus-mcp-server
MCP Server OIDC client, similarly to how you added the quarkus-mcp-server-scope
to the quarkus-mcp-client
above.
Finally, update the quarkus-mcp-server
capability to support a Standard Token Exchange
, see the How to enable token exchange example in the Keycloak documentation.
Now, the quarkus-mcp-server
OIDC client that secures the MCP server can also exchange the incoming token and request a new quarkus-mcp-service
audience by adding the quarkus-mcp-service-scope
scope to the token exchange grant request, exactly what the REST server requires.
If you actively work with another OAuth2 provider that can produce tokens with required audiences and exchange them using a standard token exchange grant, then you can also try to adapt this demo to work with that provider instead. |
Step 3 - Create and run Poem Service from command line
The MCP server is now running and ready to accept tool calls. Let’s create a command line AI Poem Service
that will work with AI Gemini and use Quarkus MCP client to complete tool calls.
Poem Service Maven dependencies
Add the following dependencies:
<dependency>
<groupId>io.quarkiverse.langchain4j</groupId>
<artifactId>quarkus-langchain4j-ai-gemini</artifactId> (1)
</dependency>
<dependency>
<groupId>io.quarkiverse.langchain4j</groupId>
<artifactId>quarkus-langchain4j-mcp</artifactId> (2)
</dependency>
<dependency>
<groupId>io.quarkiverse.langchain4j</groupId>
<artifactId>quarkus-langchain4j-oidc-client-mcp-auth-provider</artifactId> (3)
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-picocli</artifactId> (4)
</dependency>
1 | quarkus-langchain4j-ai-gemini brings support for AI Gemini. |
2 | quarkus-langchain4j-mcp provides core MCP Client support. |
3 | quarkus-langchain4j-oidc-cient-mcp-auth-provider provides an implementation of McpClientAuthProvider that can supply access tokens that it itself acquires with an OAuth2 client_credentials grant (or any other supported grant that does not require a user input). Note, this dependency is different from the quarkus-langchain4j-oidc-mcp-auth-provider one that supplies tokens already available after an authorization code flow completes, it was demoed in the Use Quarkus MCP client to access secure MCP HTTP servers blog post to propagate GitHub login access tokens. |
4 | quarkus-picocli supports building command-line Quarkus applications. Its version is defined in the Quarkus BOM. |
AI Gemini API key
Poem Service
relies on AI Gemini to create a poem.
Get AI Gemini API key and export it as an AI_GEMINI_API_KEY
environment property.
OIDC client secret
Quarkus MCP client will use an implementation of McpClientAuthProvider provided by the quarkus-langchain4j-oidc-cient-mcp-auth-provider
dependency.
This McpClientAuthProvider
uses the configured OIDC client to acquire access tokens using an OAuth2 client_credentials
grant, where an OIDC client secret must be provided.
Export the OIDC quarkus-mcp-client
client secret that you copied when working through the Step 2 - Keycloak setup section as an OIDC_CLIENT_SECRET
environment property.
Poem Service
Poem Service
is a simple Quarkus LangChain4j AI service:
package io.quarkiverse.langchain4j.sample;
import dev.langchain4j.service.UserMessage;
import io.quarkiverse.langchain4j.RegisterAiService;
import io.quarkiverse.langchain4j.mcp.runtime.McpToolBox;
@RegisterAiService
public interface PoemService {
@UserMessage("""
Write a short 1 paragraph poem in {language} about a Java programming language.
Provide a translation to English if the original poem language is not English.
Dedicate the poem to the service account, refer to this account by its name.""") (1)
@McpToolBox("service-account-name") (2)
String writePoem(String language); (1)
}
1 | Request to write a poem about Java. |
2 | Use Quarkus MCP service-account-name client configured in the Poem Service Configuration section to call a tool that can provide a service account name. |
This service is called from the PoemCommand
:
package io.quarkiverse.langchain4j.sample;
import java.util.concurrent.Callable;
import jakarta.enterprise.context.control.ActivateRequestContext;
import jakarta.inject.Inject;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
@Command(name = "poem", mixinStandardHelpOptions = true, description = "Create a poem", version = "v1.0")
@ActivateRequestContext
public class PoemCommand implements Callable<Integer> {
@Option(names = { "-l", "--language" }, description = "Poem language", defaultValue = "English")
String poemLanguage;
@Inject
PoemService poemService;
@Override
public Integer call() {
System.out.println(poemService.writePoem(poemLanguage)); (1)
return 0;
}
}
1 | Call PoemService . |
Poem Service Configuration
Let’s see how the command line Poem Service
configuration looks like:
quarkus.langchain4j.mcp.service-account-name.transport-type=http (1)
quarkus.langchain4j.mcp.service-account-name.url=http://localhost:8081/mcp/sse/ (2)
quarkus.oidc-client.auth-server-url=http://localhost:8081/realms/quarkus (3)
quarkus.oidc-client.client-id=quarkus-mcp-client (4)
quarkus.oidc-client.credentials.secret=${oidc_client_secret} (5)
quarkus.oidc-client.scopes=quarkus-mcp-server-scope (6)
quarkus.langchain4j.ai.gemini.api-key=${ai_gemini_api_key} (7)
quarkus.langchain4j.ai.gemini.log-requests=true (8)
quarkus.langchain4j.ai.gemini.log-responses=true
1 | Enable MCP client HTTP transport. In this demo we use SSE, but Streamable HTTP is also supported. |
2 | Point to the Quarkus MCP server endpoint that you started in the Start the MCP server in dev mode step. |
3 | Configure OIDC client to acquire access tokens using OAuth2 client_credentials grant, a default grant type supported by the OIDC client. OIDC client points to a Keycloak quarkus realm, note the fixed 8081 port that you requested Keycloak Dev Service to use for Keycloak in the Step 2 - Keycloak setup section. |
4 | OIDC client id, you created the OIDC quarkus-mcp-client client in the Step 2 - Keycloak setup section. |
5 | OIDC quarkus-mcp-client client secret that you exported during the OIDC client secret step. |
6 | Request that the tokens issued to quarkus-mcp-client must contain a quarkus-mcp-server MCP server audience. You created a client quarkus-mcp-server-scope scope with a quarkus-mcp-server client audience mapping in the Step 2 - Keycloak setup section. |
7 | AI Gemini key that you acquired and exported during the AI Gemini API key step. |
8 | Enable AI Gemini request and response logging |
Please pay attention to the fact that the MCP client configuration has a |
Run Poem Service
Run the command line Poem Service
that you packaged in the Package Poem Service section:
java -jar target/quarkus-app/quarkus-run.jar
You should get a response such as:
For service-account-quarkus-mcp-client, this Java ode I write,
A language strong, with classes bright, and objects shining light.
From simple apps to systems grand, its power knows no end,
With threads and streams, a helping hand, a journey without bend.
Its virtual machine, a sturdy friend, on which great feats depend.
How about trying another language ?
java -jar target/quarkus-app/quarkus-run.jar --language Greek
You should get a response such as:
Here's a short poem in Greek about Java, dedicated to the service account "service-account-quarkus-mcp-client":
**Greek:**
Ω, Java, γλώσσα ισχυρή και γρήγορη,
για προγραμματισμό, εργαλείο ακριβές.
Στον service-account-quarkus-mcp-client αφιερωμένη,
η δύναμή σου, πάντα αξιοθαύμαστη.
**English Translation:**
O Java, language strong and fast,
For programming, a precise tool.
Dedicated to service-account-quarkus-mcp-client,
Your power, always admirable.
Have token audiences made any difference ?
For the command line Poem Service
to run successfully, Quarkus MCP client had to acquire a token with a quarkus-mcp-server
audience to access the MCP server.
Here is how a token that Keycloak issues to the MCP client looks like:

The token aud
claim contains two audience values, one of them is a required quarkus-mcp-server
audience.
For the MCP quarkus-mcp-server
server to complete the Quarkus MCP client request, it had to verify that the token had a correct quarkus-mcp-server
audience, and exchange it for a new token with a quarkus-mcp-service
audience to access the REST server.
Here is how an exchanged token that a Keycloak issues to the MCP server looks like:

The token aud
claim contains a required quarkus-mcp-service
audience.
Note this token still retains a record of the original quarkus-mcp-client
client that acquired the previous token, but also lists quarkus-mcp-server
as the authorizing party (azp
).
Let’s try to access both MCP server and REST server without an audience claim.
Ensure the MCP server is running and Keycloak is configured.
In the demo, the OIDC quarkus-mcp-client
client acquires tokens that are used to access the MCP server.
Use the following curl command to acquire a client_credentials
token for the quarkus-mcp-client
client, omitting a quarkus-mcp-server-scope
grant property:
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=client_credentials&client_id=quarkus-mcp-client&client_secret=keycloak_quarkus_mcp_client_secret" http://localhost:8081/realms/quarkus/protocol/openid-connect/token
and confirm at jwt.io that the returned JWT token has no audience claim.
Try to access the MCP server with this token:
curl -H "Authorization: Bearer <token>" http://localhost:8080/mcp/sse
and you will get HTTP 401.
What about the REST server ? In the demo, the OIDC quarkus-mcp-server
client acquires tokens that are used to access the REST server.
Use the following curl command to acquire a client_credentials
token for the quarkus-mcp-server
client, omitting a quarkus-mcp-service-scope
grant property:
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=client_credentials&client_id=quarkus-mcp-server&client_secret=secret" http://localhost:8081/realms/quarkus/protocol/openid-connect/token
and confirm at jwt.io that the returned JWT token has no audience claim.
Try to access the REST server with this token:
curl -H "Authorization: Bearer <token>" http://localhost:8080/service-account-name
and you will get HTTP 401.
You can also enforce a stricter verification by requiring that tokens received by both MCP and REST servers were issued to the quarkus-mcp-client
and quarkus-mcp-server
respectively by adding the following configuration fragment to the MCP Server Configuration:
# Tokens that are accepted by MCP server must have been requested by `quarkus-mcp-client`
quarkus.oidc.token.required-claims.azp=quarkus-mcp-client
# Tokens that are accepted by REST server must have been requested by `quarkus-mcp-server`
quarkus.oidc.service-account-name-rest-server.token.required-claims.azp=quarkus-mcp-server
Note about Resource Indicators
The latest 2025-06-18 MCP authorization specification requires the use of OAuth2 Resource Indicators.
OAuth2 Resource Indicator allows for a fine grained token audience restriction, in the presence of multiple, diverse resource servers that must be accessed with tokens.
For a simple demo that we created in this blog post, having a token to contain an audience only is sufficient.
If your provider already supports OAuth2 Resource Indicators and you need to have a token to also include a resource indicator, configure OIDC client to request it.
For example, you can add quarkus.oidc-client.grant.client.extra-params.resource=http://localhost:8080/mcp
to the Poem Service Configuration.
In this case, to have the MCP server verify that an access token contains a correct resource indicator, add quarkus.oidc.token.required-claims.resource=http://localhost:8080/mcp
to the MCP Server Configuration.
Security Considerations
Ensuring that each participant in your distributed AI system is properly secured and accepts tokens thar are meant to access this participant only is crucial.
Token audience restriction is one of the key OAuth2 mechanisms that supports this goal, with resource indicators allowing to achieve a finer-grained audience restriction.
Token exchange can help to correctly switch the OAuth2 security context when the tokens are flowing in a multi-hop distributed AI application.
Read more about the Access Token Privilege Restriction in the latest 2025-06-18 MCP authorization specification.
Conclusion
In this blog post, we demonstrated how Quarkus MCP Client can access secure MCP servers by acquiring access tokens using an OAuth2 client_credentials
grant and propagating them to the secure Quarkus MCP server.
We also looked into restricting tokens to specific audiences and started learning about an important OAuth2 token exchange grant.
We have more content dedicated to AI and MCP security lined up for you, stay tuned !