LangChain Quickstart (TypeScript)¶
This quickstart shows you how to create AI agent identities in WSO2 Identity Platform, authenticate agents using their credentials, and securely connect them to MCP servers with LangChain.
[//] STEPS_START
Register an AI agent¶
To give your AI agent an identity, first register it in WSO2 Identity Platform.
- Sign in to the WSO2 Identity Platform console and go to Agents, and then click + New Agent.
- Enter the following details:
- Name: A descriptive name for your AI agent (e.g., Math Assistant).
- Click Create to complete the registration.
After registering the agent, you'll receive an Agent ID and an Agent Secret. The Agent Secret is shown only once, so make sure to store it securely. You'll need these credentials later in this guide.
Configure and run the sample MCP Server¶
To let your agent (or a user acting through the agent) authenticate and connect to a secure MCP server, first create an MCP Client in WSO2 Identity Platform.
- In WSO2 Identity Platform console, navigate to Applications > New Application.
- Select MCP Client Application and complete the wizard pop-up by providing the following details.
- Name: A descriptive name for your MCP client application (e.g., MCP Client).
- Authorized redirect URL: The authorized redirect URL (e.g.,http://localhost:6274/oauth/callback).
Info
The authorized redirect URL defines the location WSO2 Identity Platform sends users to after a successful login, typically the address of the client application that connects to the MCP server.
In this guide, the AI agent behaves as the client, which consists of a lightweight OAuth 2.1 callback server running at http://localhost:3001/callback to capture the authorization code. So, we will use this URL as the authorized redirect for this guide.
While we're using the MCP Client Application template here for optimized MCP settings, you can also use other application types (Single Page App, Traditional Web App, Mobile App, or M2M App) to access MCP servers, except Digital Wallet applications.
Make a note of the Client ID from the Protocol tab of the registered application. You will need it during the Build an AI Agent section of this guide.
Your AI agent will call an MCP tool hosted on a secure MCP server. You can:
- Follow the MCP Auth Server Quickstart to set one up quickly (Recommended), or
- Use your own MCP server secured with WSO2 Identity Platform
Build an AI Agent¶
Create a directory called agent-auth-quickstart by running the following commands.
Then initialize a Node.js project using the following command.
Now open the package.json file and replace the existing content with the following given content.
{
"name": "agent-auth-quickstart",
"version": "1.0.0",
"type": "module",
"main": "agent.ts",
"scripts": {
"start": "npx tsx agent.ts"
}
}
Install the following dependencies.
npm install @asgardeo/javascript @langchain/google-genai @langchain/langgraph @langchain/mcp-adapters base64url fast-sha256 jose secure-random-bytes tsx typescript
npm install --save-dev @types/node
Create agent.ts that implements an AI agent which first obtains a valid access token from WSO2 Identity Platform by authenticating itself. The agent then includes that token in the Authorization header (for example Authorization: Bearer <token>) when calling the MCP tool.
import { stdin as input, stdout as output } from "node:process";
import * as readline from "node:readline/promises";
import { ChatGoogleGenerativeAI } from "@langchain/google-genai";
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { MultiServerMCPClient } from "@langchain/mcp-adapters";
import { AsgardeoJavaScriptClient } from "@asgardeo/javascript";
import dotenv from "dotenv";
// Load environment variables from .env file
dotenv.config();
const asgardeoConfig = {
afterSignInUrl: process.env.REDIRECT_URI || "",
clientId: process.env.CLIENT_ID || "",
baseUrl: process.env.ASGARDEO_BASE_URL || "",
};
const agentConfig = {
agentID: process.env.AGENT_ID || "",
agentSecret: process.env.AGENT_SECRET || "",
};
const model = new ChatGoogleGenerativeAI({
apiKey: process.env.GOOGLE_API_KEY || "",
model: process.env.MODEL_NAME || "gemini-2.5-flash",
});
async function runAgent() {
const asgardeoJavaScriptClient = new AsgardeoJavaScriptClient(asgardeoConfig);
const agentToken = await asgardeoJavaScriptClient.getAgentToken(agentConfig);
const client = new MultiServerMCPClient({
math: {
transport: "http",
url: process.env.MCP_SERVER_URL || "http://localhost:8000/mcp",
headers: {
Authorization: "Bearer " + agentToken.accessToken,
},
},
});
const tools = await client.getTools();
const agent = createReactAgent({
llm: model,
tools: tools,
});
const rl = readline.createInterface({ input, output });
while (true) {
try {
const userInput = await rl.question("\nEnter your question (e.g., 'Add 45 and 99') or type 'exit' to quit: ");
if (userInput.toLowerCase() === "exit") {
console.log("Goodbye!");
break;
}
const result = await agent.invoke({
messages: [{ role: "user", content: userInput }],
});
const finalResponse = result.messages[result.messages.length - 1];
console.log("Agent: " + finalResponse.content);
} catch (error) {
console.error("Error running agent:", error);
break;
}
}
await client.close();
rl.close();
}
runAgent().catch(console.error);
Add environment configuration by creating a .env file at the project root to hold the WSO2 Identity Platform configuration:
# WSO2 Identity Platform OAuth2 Configuration
ASGARDEO_BASE_URL=https://api.asgardeo.io/t/<organization-name>
CLIENT_ID=<your-client-id>
REDIRECT_URI=http://localhost:3001/callback
# WSO2 Identity Platform Agent Credentials
AGENT_ID=<agent_id>
AGENT_SECRET=<agent_secret>
# Google Gemini API Key
GOOGLE_API_KEY=<google_api_key>
# MCP Server URL
MCP_SERVER_URL=<mcp_server_url>
# LLM model used by the agent (any supported model can be used).
MODEL_NAME="gemini-2.5-flash"
Important
-
Replace
<organization-name>and<client-id>with the values obtained from the WSO2 Identity Platform console. The organization name is visible in the console URL path (e.g.,https://console.asgardeo.io/t/<organization-name>), and theclient IDcan be found in the application's Protocol tab. -
Add the
<agent-id>and<agent-secret>from the Agent Registration step. -
You’ll need a Google API key to use Gemini as your model. You can generate one from Google AI Studio
-
Replace
<mcp_server_url>with your MCP server’s URL. If you followed the MCP Auth Server quickstart, you can use:http://127.0.0.1:8000/mcp
Your project folder should now look like this:
.
├── .env # Environment file containing all the configuration variables
├── agent.ts # Your AI Agent
├── node_modules
│ └── ...
├── package-lock.json
├── package.json
└── tsconfig.json
Test the Agent Login Flow¶
Start your AI Agent by running the following command.
If authentication succeeds, your agent will prompt you for a question and securely invoke the MCP tool.
--- AI Agent Started (Type 'exit' to quit) ---
Enter your question (e.g., 'Add 45 and 99') or type 'exit' to quit: add 3455 and 235
Agent : The sum of 3455 and 235 is 3690.
Test the On-Behalf-Of Flow¶
In the previous step, the AI agent authenticated itself using its own credentials. Now, let’s look at the scenario where the agent authenticates on behalf of a user.
This flow uses:
- Authorization code issued after the user logs in
- PKCE (Proof Key for Code Exchange) to ensure only your agent can securely exchange the authorization code for the OBO token
- A final token exchange that produces an OBO token, representing the user
Your AI agent will then call the MCP server as the authenticated user.
During the OBO flow, WSO2 Identity Platform redirects back to your client application with an authorization code after the user logs in. Our agent will then catch the authorization code from WSO2 Identity Platform and exchange it for an OBO token.
To handle this, we need to set up a simple express server within agent.ts. This lightweight HTTP server listens for the redirect and captures authorization_code and state.
To get started, first install the following dependencies,
Then, update the agent.ts to perform the OBO Flow. This will:
- Authenticate the agent
- Generate an authorization URL for the user
- Capture the authorization code
- Exchange the code + agent token for an OBO token
- Call the MCP server using the OBO token
Here is the updated implementation:
import { stdin as input, stdout as output } from "node:process";
import * as readline from "node:readline/promises";
import { Server } from "http";
import express from "express";
import { ChatGoogleGenerativeAI } from "@langchain/google-genai";
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { MultiServerMCPClient } from "@langchain/mcp-adapters";
import { AsgardeoJavaScriptClient, AuthCodeResponse } from "@asgardeo/javascript";
import dotenv from "dotenv";
import open from "open";
const port = '3001';
// Load environment variables from .env file
dotenv.config();
const asgardeoConfig = {
afterSignInUrl: process.env.REDIRECT_URI || "",
clientId: process.env.CLIENT_ID || "",
baseUrl: process.env.ASGARDEO_BASE_URL || "",
};
const agentConfig = {
agentID: process.env.AGENT_ID || "",
agentSecret: process.env.AGENT_SECRET || "",
};
const model = new ChatGoogleGenerativeAI({
apiKey: process.env.GOOGLE_API_KEY || "",
model: process.env.MODEL_NAME || "gemini-2.5-flash",
});
async function runAgent() {
const asgardeoJavaScriptClient = new AsgardeoJavaScriptClient(asgardeoConfig);
const authURL = await asgardeoJavaScriptClient.getOBOSignInURL(agentConfig);
console.log("Opening authentication URL in your browser...");
await open(authURL);
const app = express();
let server: Server;
let authCodeResponse: AuthCodeResponse | undefined;
const authCodePromise = new Promise<AuthCodeResponse>((resolve) => {
app.get("/callback", async (req, res) => {
try {
const code = req.query.code as string;
const session_state = req.query.session_state as string;
const state = req.query.state as string;
if (!code) {
res.status(400).send("No authorization code found.");
return;
}
authCodeResponse = {
code: code,
state: state,
session_state: session_state,
};
resolve(authCodeResponse);
res.send("<h1>Login Successful!</h1><p>You can close this window.</p>");
} catch (err) {
res.status(500).send("Internal Server Error");
} finally {
if (server) {
server.close();
}
}
});
});
server = app
.listen(port, () => {
})
.on("error", (error) => {
console.error("Server error:", error);
process.exit(1);
});
authCodeResponse = await authCodePromise;
const oboToken = await asgardeoJavaScriptClient.getOBOToken(agentConfig, authCodeResponse);
const client = new MultiServerMCPClient({
math: {
transport: "http",
url: process.env.MCP_SERVER_URL || "http://localhost:8000/mcp",
headers: {
Authorization: "Bearer " + oboToken.accessToken,
},
},
});
const tools = await client.getTools();
const agent = createReactAgent({
llm: model,
tools: tools,
});
const rl = readline.createInterface({ input, output });
try {
while (true) {
try {
const userInput = await rl.question("\nEnter your question (e.g., 'Add 45 and 99') or type 'exit' to quit: ");
if (userInput.toLowerCase() === "exit") {
console.log("Goodbye!");
break;
}
const result = await agent.invoke({
messages: [{ role: "user", content: userInput }],
});
const finalResponse = result.messages[result.messages.length - 1];
console.log("Agent: " + finalResponse.content);
} catch (error) {
console.error("Error running agent:", error);
break;
}
}
} finally {
await client.close();
rl.close();
process.exit(0);
}
}
runAgent().catch(console.error);
Add environment configuration by creating a .env file at the project root to hold the WSO2 Identity Platform configuration:
# WSO2 Identity Platform OAuth2 Configuration
ASGARDEO_BASE_URL=https://api.asgardeo.io/t/<your-tenant>
CLIENT_ID=<your-client-id>
REDIRECT_URI=http://localhost:3001/callback
# WSO2 Identity Platform Agent Credentials
AGENT_ID=<agent_id>
AGENT_SECRET=<agent_secret>
# Google Gemini API Key
GOOGLE_API_KEY=<google_api_key>
# MCP Server URL
MCP_SERVER_URL=<mcp_server_url>
Start your agent:
You will see an output similar to this and your default browser will open, prompting you to log in:
Info
You need to create a test user in WSO2 Identity Platform by following the instructions in the Onboard a User guide to try out the login feature.
After successful login, return to the terminal. Your agent will automatically resume once it receives the authorization code and call the MCP tool on behalf of the authenticated user.
Your AI agent has now successfully performed an authenticated, user-authorized, On-Behalf-Of request to your MCP server.
[//] STEPS_END