Skip to content

docs: lesson 7 - mcp #108

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions app/public/characters.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,23 @@
"image": "ada.jpeg",
"avatar": "ada-avatar.jpeg",
"voice": 2
},
{
"title": "Scipio Africanus",
"name": "scipio",
"description": "You are Scipio Africanus, a Roman general known for defeating Hannibal in the Second Punic War. Limit your responses to only the time you live in, you don't know anything else. You only want to talk about military strategy and possibly new ideas you have.",
"page": "scipio.html",
"image": "scipio.png",
"avatar": "scipio-avatar.jpeg",
"voice": 1
},
{
"title": "Hedy Lamarr",
"name": "hedy",
"description": "You are Hedy Lamarr, a famous actress and inventor. Limit your responses to only the time you live in, you don't know anything else. You only want to talk about your inventions and possibly new ideas you have.",
"page": "hedy.html",
"image": "hedy.jpeg",
"avatar": "hedy-avatar.jpeg",
"voice": 2
}
]
Binary file added app/public/images/hedy-avatar.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/public/images/hedy.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/public/images/scipio-avatar.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/public/images/scipio.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
482 changes: 482 additions & 0 deletions lessons/07-mcp/README.md

Large diffs are not rendered by default.

Binary file added lessons/07-mcp/assets/scipio.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
82 changes: 82 additions & 0 deletions lessons/07-mcp/code/build/client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { CallToolResultSchema } from "@modelcontextprotocol/sdk/types.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
import { OpenAI } from 'openai';
const transport = new StdioClientTransport({
command: "node",
args: ["build/index.js"]
});
const client = new Client({
name: "example-client",
version: "1.0.0"
});
await client.connect(transport);
function toToolSchema(method, schema) {
return {
name: method,
description: `This is a tool that does ${method}`,
parameters: schema,
};
}
// list tools
const { tools } = await client.listTools();
tools.forEach((tool) => {
console.log(`Tool: ${tool.name}`);
console.log(`Description: ${tool.description}`);
console.log(`Input schema: ${JSON.stringify(tool.inputSchema)}`);
});
const toolsForLLM = tools.map((tool) => {
return toToolSchema(tool.name, tool.inputSchema);
});
console.log("Schema for tool", JSON.stringify(toolsForLLM, null, 2));
// TODO feed this to an llm as functions
const openai = new OpenAI({
baseURL: "https://models.inference.ai.azure.com", // might need to change to this url in the future: https://models.github.ai/inference
apiKey: process.env.GITHUB_TOKEN,
});
const messages = [
{
role: "system",
content: `You are a helpful assistant. You can call functions to perform tasks. Make sure to parse the function call and arguments correctly.`
}, {
role: "user",
content: "Add 5 and 10",
name: "example-user" // Adding the required 'name' property for user role
}
];
openai.chat.completions.create({
model: 'gpt-4o',
messages: messages,
functions: toolsForLLM
}).then((result) => {
console.log("Result", result.choices[0].message);
}).catch((error) => {
console.error("Error:", error);
});
const result = await openai.chat.completions.create({
model: 'gpt-4o',
messages: messages,
functions: toolsForLLM
});
for (const choice of result.choices) {
// console.log("Result", choice.message);
let functionCall = choice.message?.function_call;
let functionName = functionCall?.name;
console.log("Function call: ", functionName);
let args = functionCall?.arguments;
await client.callTool({
name: functionName ?? "",
arguments: typeof args === "string" ? JSON.parse(args) : args ?? {}
}, CallToolResultSchema).then((result) => {
console.log("Result from tool: ", result);
});
}
// call tool
// const result = await client.callTool({
// name: "add",
// arguments: {
// a: 5,
// b: 10
// }
// });
// console.log(`Result: ${JSON.stringify(result)}`);
1 change: 1 addition & 0 deletions lessons/07-mcp/code/build/index-with-llm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {};
38 changes: 38 additions & 0 deletions lessons/07-mcp/code/build/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// simple mc server
import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
// Create an MCP server
const server = new McpServer({
name: "Demo",
version: "1.0.0"
});
// Add an addition tool
// @ts-ignore
server.tool("add", {
input: z.object({
a: z.number(),
b: z.number()
}),
output: z.object({
content: z.array(z.object({ type: z.string(), text: z.string() }))
})
}, async ({ input }) => ({
content: [{ type: "text", text: String(input.a + input.b) }]
}));
// Add a dynamic greeting resource
server.resource("greeting", new ResourceTemplate("greeting://{name}", { list: undefined }), async (uri, { name }) => ({
contents: [{
uri: uri.href,
text: `Hello, ${name}!`
}]
}));
// Start receiving messages on stdin and sending messages on stdout
const transport = new StdioServerTransport();
async function runServer() {
await server.connect(transport);
}
runServer().catch((err) => {
console.error("Error in server:", err);
process.exit(1);
});
Loading