Skip to content

Commit f9b1c19

Browse files
authored
Merge pull request #1 from riligar/2025-04-18_mcp
feat: MCP integration
2 parents 731c7df + 62afd69 commit f9b1c19

File tree

18 files changed

+780
-178
lines changed

18 files changed

+780
-178
lines changed

README.md

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,22 @@ The RiLiGar Agents SDK is a robust JavaScript library designed to streamline the
1010
- **Agent Management System**: Sophisticated agent lifecycle and interaction handling
1111
- **Voice Integration**: Native support for voice-based interactions
1212
- **Advanced Tracing**: Comprehensive system for monitoring and debugging agent behaviors
13-
- **MCP Protocol**: Implementation of Message Control Protocol v1.0 featuring:
14-
- Secure handshake mechanism
15-
- Capability exchange
16-
- Synchronous and asynchronous messaging
17-
- Streaming support
18-
- Robust error handling
13+
- **MCP Protocol**: Implementation of Message Control Protocol
1914

2015
## Resources
2116

22-
- [OpenAI](https://platform.openai.com/logs)
23-
- [Anthropic](https://www.anthropic.com/api)
17+
- [OpenAI](https://platform.openai.com)
18+
- [Library](https://github.com/openai/openai-node)
19+
- [Anthropic](https://console.anthropic.com/)
20+
- [SDK](https://github.com/anthropics/anthropic-sdk-typescript)
2421
- [Google](https://ai.google.dev/gemini-api/)
22+
- [SDK](https://www.npmjs.com/package/@google/genai)
2523
- [Meta](https://www.llama.com/)
26-
- [ModelContext](https://modelcontextprotocol.io/introduction)
24+
25+
- [Model Context Protocol](https://modelcontextprotocol.io)
26+
- [Documentation](https://modelcontextprotocol.info/docs/)
27+
- [TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk)
28+
- [Inspector](https://github.com/modelcontextprotocol/inspector)
2729

2830

2931
## Installation
@@ -32,6 +34,14 @@ The RiLiGar Agents SDK is a robust JavaScript library designed to streamline the
3234
npm install @riligar/agents-sdk
3335
```
3436

37+
### MCP Protocol
38+
39+
The RiLiGar Agents SDK implements the Message Control Protocol (MCP) for reliable agent communication and management. MCP is a secure and efficient protocol that ensures secure and reliable communication between agents and their environment.
40+
41+
```bash
42+
npx -y @modelcontextprotocol/inspector npm start
43+
```
44+
3545
## Usage
3646

3747
```js

bun.lock

Lines changed: 122 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/guardrail.js

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
// guardrail-example.js
2-
const { Agent, Runner, functionTool, inputGuardrail, outputGuardrail } = require('../src/index');
3-
4-
// Set your OpenAI API key
5-
const OPENAI_API_KEY = process.env.OPENAI_API_KEY;
2+
const { Agent, Runner, Tool, Guardrail } = require('../src/index');
63

74
// Create an input guardrail that checks if the input contains inappropriate content
8-
const inappropriateContentGuardrail = inputGuardrail({
5+
const inappropriateContentGuardrail = new Guardrail.InputGuardrail({
96
name: "inappropriate_content_filter",
107
check: async (context, agent, input) => {
118
// In a real implementation, you might use a content moderation API
@@ -29,11 +26,11 @@ const inappropriateContentGuardrail = inputGuardrail({
2926
});
3027

3128
// Create an output guardrail that ensures the response isn't too short
32-
const minimumLengthGuardrail = outputGuardrail({
29+
const minimumLengthGuardrail = new Guardrail.OutputGuardrail({
3330
name: "minimum_length_check",
3431
check: async (context, agent, output) => {
3532
const minimumLength = 20; // characters
36-
33+
3734
// Safely handle null/undefined output
3835
if (!output) {
3936
return {
@@ -65,7 +62,7 @@ const minimumLengthGuardrail = outputGuardrail({
6562
});
6663

6764
// Create a tool for our agent
68-
const getWeather = functionTool({
65+
const getWeather = new Tool({
6966
name: "get_weather",
7067
description: "Get the current weather for a city",
7168
parameters: {

examples/handoffs.js

Lines changed: 12 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,39 @@
11
const { Agent, Runner } = require('../src/index');
22

3-
// Set your OpenAI API key
4-
const OPENAI_API_KEY = process.env.OPENAI_API_KEY;
5-
6-
// Provider configuration
7-
const providerConfig = {
8-
apiKey: OPENAI_API_KEY
9-
};
10-
113
async function main() {
124
// Create the Spanish agent with explicit configuration
135
const spanishAgent = new Agent({
146
name: "Spanish_Agent", // Use underscore for consistency
15-
instructions: "You are a helpful assistant that only speaks Spanish. Always respond in Spanish to any questions or requests.",
16-
model: "gpt-4",
17-
provider: "openai",
18-
providerConfig,
19-
modelSettings: {
20-
temperature: 0.7,
21-
max_tokens: 500
22-
}
7+
instructions: "You are a helpful assistant that only speaks Spanish. Always respond in Spanish to any questions or requests."
238
});
249

2510
// Create the English agent with explicit configuration
2611
const englishAgent = new Agent({
2712
name: "English_Agent", // Use underscore for consistency
28-
instructions: "You are a helpful assistant that only speaks English. Always respond in English to any questions or requests.",
29-
model: "gpt-4",
30-
provider: "openai",
31-
providerConfig,
32-
modelSettings: {
33-
temperature: 0.7,
34-
max_tokens: 500
35-
}
13+
instructions: "You are a helpful assistant that only speaks English. Always respond in English to any questions or requests."
3614
});
3715

3816
// Create the triage agent with explicit configuration
3917
const triageAgent = new Agent({
4018
name: "Triage_Agent", // Use underscore for consistency
4119
instructions: `You are a language triage agent. Your task is to analyze messages and route them to the appropriate language agent.
42-
43-
Rules:
44-
1. For Spanish messages -> Use transfer_to_Spanish_Agent
45-
2. For English messages -> Use transfer_to_English_Agent
46-
3. DO NOT respond to the user directly
47-
4. ALWAYS use the appropriate transfer function
48-
5. If you detect Spanish, IMMEDIATELY call transfer_to_Spanish_Agent
49-
6. If you detect English, IMMEDIATELY call transfer_to_English_Agent`,
50-
handoffs: [spanishAgent, englishAgent],
51-
model: "gpt-4",
52-
provider: "openai",
53-
providerConfig,
54-
modelSettings: {
55-
temperature: 0.7,
56-
max_tokens: 500
57-
}
20+
Rules:
21+
1. For Spanish messages -> Use transfer_to_Spanish_Agent
22+
2. For English messages -> Use transfer_to_English_Agent
23+
3. DO NOT respond to the user directly
24+
4. ALWAYS use the appropriate transfer function
25+
5. If you detect Spanish, IMMEDIATELY call transfer_to_Spanish_Agent
26+
6. If you detect English, IMMEDIATELY call transfer_to_English_Agent`,
27+
handoffs: [spanishAgent, englishAgent]
5828
});
5929

6030
try {
6131
console.log('Sending message to triage agent...');
6232
const result = await Runner.run(triageAgent, "Hola, ¿cómo estás?", {
63-
maxTurns: 3, // Allow for triage + response
33+
// maxTurns: 1, // Allow for triage + response
6434
context: { debug: true }
6535
});
66-
36+
6737
console.log('\nFinal response:', result.finalOutput);
6838
console.log('Last agent:', result.lastAgent.name);
6939
console.log('\nMessage history:');

examples/hello.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
const { Agent, Runner } = require('../src/index');
22

3-
// Set your OpenAI API key
4-
const OPENAI_API_KEY = process.env.OPENAI_API_KEY;
5-
63
async function main() {
74
const agent = new Agent({
85
name: "Assistant",

examples/mcp/agent.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Exemplo de agente integrado ao MCP server de weather
2+
const { Agent, Runner } = require('../../src');
3+
4+
(async () => {
5+
// URL do MCP server (ajuste conforme necessário)
6+
const mcpWeatherUrl = 'http://localhost:3001/sse';
7+
8+
// Instancia o agente com integração MCP
9+
const agent = new Agent({
10+
name: 'WeatherAgent',
11+
instructions: 'Consulte informações meteorológicas usando ferramentas remotas.',
12+
mcpServers: [mcpWeatherUrl]
13+
});
14+
15+
// Inicializa o agente e aguarda o carregamento das ferramentas MCP
16+
await agent.init();
17+
18+
// Exibe as ferramentas disponíveis
19+
console.log('Ferramentas disponíveis:', agent.tools.map(t => t.name));
20+
21+
// Input natural do usuário
22+
const input = 'Quais alertas meteorológicos existem para NY?';
23+
24+
// Executa o agente, que decide qual ferramenta usar
25+
const result = await Runner.run(agent, input);
26+
console.log('Saída final do agente:', result.finalOutput);
27+
})();

examples/mcp/client.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// https://github.com/modelcontextprotocol/typescript-sdk?tab=readme-ov-file#backwards-compatibility
2+
// https://github.com/modelcontextprotocol/quickstart-resources/blob/main/mcp-client-typescript/index.ts
3+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
4+
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
5+
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
6+
7+
let client = undefined
8+
const url = "http://localhost:3001/sse";
9+
10+
const baseUrl = new URL(url);
11+
try {
12+
client = new Client({
13+
name: 'streamable-http-client',
14+
version: '1.0.0'
15+
});
16+
const transport = new StreamableHTTPClientTransport(
17+
new URL(baseUrl)
18+
);
19+
await client.connect(transport);
20+
console.log("Connected using Streamable HTTP transport");
21+
} catch (error) {
22+
// If that fails with a 4xx error, try the older SSE transport
23+
console.log("Streamable HTTP connection failed, falling back to SSE transport");
24+
client = new Client({
25+
name: 'sse-client',
26+
version: '1.0.0'
27+
});
28+
const sseTransport = new SSEClientTransport(baseUrl);
29+
await client.connect(sseTransport);
30+
console.log("Connected using SSE transport");
31+
}
32+
33+
34+
const tools = await client.listTools();
35+
// console.log("Tools:", tools)
36+
console.log("Tools:", tools.tools.map(tool => ({
37+
name: tool.name,
38+
description: tool.description,
39+
input_schema: tool.inputSchema
40+
})))
41+
42+
// call echo tool
43+
const result = await client.callTool({
44+
name: 'get-alerts',
45+
arguments: {
46+
state: 'NY'
47+
}
48+
});
49+
console.log("Result:", result.content[0].text.length);
50+
51+
process.exit(0);
52+

examples/mcp/server/echo.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
2+
import express, { Request, Response } from "express";
3+
import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
4+
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
5+
import { z } from "zod";
6+
7+
export const server = new McpServer({
8+
name: "echo",
9+
version: "1.0.0"
10+
});
11+
12+
server.resource(
13+
"echo",
14+
new ResourceTemplate("echo://{message}", { list: undefined }),
15+
async (uri, { message }) => ({
16+
contents: [{
17+
uri: uri.href,
18+
text: `Resource echo: ${message}`
19+
}]
20+
})
21+
);
22+
23+
server.tool(
24+
"echo",
25+
{ message: z.string() },
26+
async ({ message }) => ({
27+
content: [{ type: "text", text: `Tool echo: ${message}` }]
28+
})
29+
);
30+
31+
server.prompt(
32+
"echo",
33+
{ message: z.string() },
34+
({ message }) => ({
35+
messages: [{
36+
role: "user",
37+
content: {
38+
type: "text",
39+
text: `Please process this message: ${message}`
40+
}
41+
}]
42+
})
43+
);
44+
45+
46+
const app = express();
47+
const transports: { [sessionId: string]: SSEServerTransport } = {};
48+
49+
app.get("/sse", async (_: Request, res: Response) => {
50+
const transport = new SSEServerTransport('/messages', res);
51+
transports[transport.sessionId] = transport;
52+
res.on("close", () => {
53+
delete transports[transport.sessionId];
54+
});
55+
await server.connect(transport);
56+
});
57+
58+
app.post("/messages", async (req: Request, res: Response) => {
59+
const sessionId = req.query.sessionId as string;
60+
const transport = transports[sessionId];
61+
if (transport) {
62+
await transport.handlePostMessage(req, res);
63+
} else {
64+
res.status(400).send('No transport found for sessionId');
65+
}
66+
});
67+
68+
app.listen(3000, () => {
69+
console.error("MCP Server running with sse transport");
70+
});
71+

0 commit comments

Comments
 (0)