├── agent ├── README.md ├── app │ ├── __init__.py │ ├── agent │ │ ├── __init__.py │ │ └── graph.py │ ├── utils.py │ └── server.py ├── .env.example ├── .gitignore ├── langgraph.json └── pyproject.toml ├── mcp-servers ├── calendar-mcp │ ├── .python-version │ ├── pyproject.toml │ ├── README.md │ ├── calendar-mcp-server.py │ └── uv.lock └── booking-mcp │ ├── package.json │ ├── src │ ├── stdio-server.ts │ ├── booking-mcp-server.ts │ └── sse-server.ts │ ├── .gitignore │ ├── README.md │ ├── tsconfig.json │ └── bun.lock ├── client ├── .env ├── app │ ├── favicon.ico │ ├── chat │ │ ├── page.tsx │ │ └── [id] │ │ │ ├── agent-types.ts │ │ │ ├── components │ │ │ ├── node-card.tsx │ │ │ ├── weather │ │ │ │ ├── weather-node.tsx │ │ │ │ ├── cloudy.tsx │ │ │ │ ├── sunny.tsx │ │ │ │ ├── rainy.tsx │ │ │ │ └── snowy.tsx │ │ │ ├── reminder.tsx │ │ │ ├── checkpoint-card.tsx │ │ │ └── chatbot-node.tsx │ │ │ └── page.tsx │ ├── layout.tsx │ ├── api │ │ └── agent │ │ │ └── route.ts │ ├── globals.css │ └── page.tsx ├── public │ ├── vercel.svg │ ├── file.svg │ ├── window.svg │ ├── globe.svg │ └── next.svg ├── next.config.ts ├── postcss.config.mjs ├── lib │ └── utils.ts ├── components │ ├── ui │ │ ├── skeleton.tsx │ │ ├── textarea.tsx │ │ ├── input.tsx │ │ ├── separator.tsx │ │ ├── checkbox.tsx │ │ ├── badge.tsx │ │ ├── tooltip.tsx │ │ ├── popover.tsx │ │ ├── button.tsx │ │ ├── card.tsx │ │ ├── sheet.tsx │ │ └── sidebar.tsx │ ├── theme-provider.tsx │ ├── theme-switcher.tsx │ └── app-sidebar.tsx ├── eslint.config.mjs ├── components.json ├── stores │ └── chat-store.tsx ├── hooks │ ├── use-mobile.tsx │ └── useLangGraphAgent │ │ ├── actions.ts │ │ ├── api.ts │ │ ├── ascii-tree.ts │ │ ├── types.ts │ │ └── useLangGraphAgent.tsx ├── .gitignore ├── tsconfig.json ├── package.json ├── README.md └── tailwind.config.ts ├── images ├── header.jpeg └── langgraph-nextjs.jpeg ├── .gitignore ├── LICENSE └── README.md /agent/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /agent/app/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /agent/app/agent/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /agent/.env.example: -------------------------------------------------------------------------------- 1 | OPENAI_API_KEY=your_openai_api_key -------------------------------------------------------------------------------- /mcp-servers/calendar-mcp/.python-version: -------------------------------------------------------------------------------- 1 | 3.13 2 | -------------------------------------------------------------------------------- /client/.env: -------------------------------------------------------------------------------- 1 | NEXT_PUBLIC_AGENT_URL=http://localhost:8000 -------------------------------------------------------------------------------- /agent/.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | *.pyc 3 | 4 | .env 5 | 6 | .DS_Store 7 | **/.DS_Store 8 | -------------------------------------------------------------------------------- /images/header.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akveo/ai-cookbook/HEAD/images/header.jpeg -------------------------------------------------------------------------------- /client/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akveo/ai-cookbook/HEAD/client/app/favicon.ico -------------------------------------------------------------------------------- /images/langgraph-nextjs.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akveo/ai-cookbook/HEAD/images/langgraph-nextjs.jpeg -------------------------------------------------------------------------------- /client/app/chat/page.tsx: -------------------------------------------------------------------------------- 1 | export default function ChatsPage() { 2 | return ( 3 |
4 |
5 | ) 6 | } 7 | 8 | -------------------------------------------------------------------------------- /client/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from "next"; 2 | 3 | const nextConfig: NextConfig = { 4 | /* config options here */ 5 | }; 6 | 7 | export default nextConfig; 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | **/.DS_Store 3 | .DS_Store? 4 | ._* 5 | .Spotlight-V100 6 | .Trashes 7 | ehthumbs.db 8 | Thumbs.db 9 | 10 | .idea/ 11 | .vscode/ 12 | *.swp 13 | *.swo 14 | *~ -------------------------------------------------------------------------------- /client/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /agent/langgraph.json: -------------------------------------------------------------------------------- 1 | { 2 | "graphs": { 3 | "agent": "./app/agent/graph.py:graph" 4 | }, 5 | "env": ".env", 6 | "python_version": "3.12", 7 | "dependencies": [ 8 | "." 9 | ] 10 | } -------------------------------------------------------------------------------- /client/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /mcp-servers/calendar-mcp/pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "mcp-python" 3 | version = "0.1.0" 4 | description = "Add your description here" 5 | readme = "README.md" 6 | requires-python = ">=3.13" 7 | dependencies = [ 8 | "mcp[cli]>=1.6.0", 9 | ] 10 | -------------------------------------------------------------------------------- /client/components/ui/skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "@/lib/utils" 2 | 3 | function Skeleton({ 4 | className, 5 | ...props 6 | }: React.HTMLAttributes) { 7 | return ( 8 |
12 | ) 13 | } 14 | 15 | export { Skeleton } 16 | -------------------------------------------------------------------------------- /client/public/file.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/public/window.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import { dirname } from "path"; 2 | import { fileURLToPath } from "url"; 3 | import { FlatCompat } from "@eslint/eslintrc"; 4 | 5 | const __filename = fileURLToPath(import.meta.url); 6 | const __dirname = dirname(__filename); 7 | 8 | const compat = new FlatCompat({ 9 | baseDirectory: __dirname, 10 | }); 11 | 12 | const eslintConfig = [ 13 | ...compat.extends("next/core-web-vitals", "next/typescript"), 14 | ]; 15 | 16 | export default eslintConfig; 17 | -------------------------------------------------------------------------------- /mcp-servers/booking-mcp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "booking-mcp", 3 | "module": "src/booking-mcp-server.ts", 4 | "type": "module", 5 | "private": true, 6 | "scripts": { 7 | "start": "bun run src/sse-server.ts" 8 | }, 9 | "devDependencies": { 10 | "@types/bun": "latest", 11 | "@types/express": "^5.0.1" 12 | }, 13 | "peerDependencies": { 14 | "typescript": "^5" 15 | }, 16 | "dependencies": { 17 | "@modelcontextprotocol/sdk": "^1.9.0", 18 | "express": "^5.1.0", 19 | "zod": "^3.22.4" 20 | } 21 | } -------------------------------------------------------------------------------- /client/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "app/globals.css", 9 | "baseColor": "zinc", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | }, 20 | "iconLibrary": "lucide" 21 | } -------------------------------------------------------------------------------- /mcp-servers/booking-mcp/src/stdio-server.ts: -------------------------------------------------------------------------------- 1 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; 2 | import { createServer } from "./booking-mcp-server.js"; 3 | 4 | async function main() { 5 | const server = createServer(); 6 | 7 | // Start receiving messages on stdin and sending messages on stdout 8 | const transport = new StdioServerTransport(); 9 | await server.connect(transport); 10 | } 11 | 12 | main().catch(error => { 13 | console.error("Error starting Booking MCP server:", error); 14 | process.exit(1); 15 | }); -------------------------------------------------------------------------------- /mcp-servers/booking-mcp/.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies (bun install) 2 | node_modules 3 | 4 | # output 5 | out 6 | dist 7 | *.tgz 8 | 9 | # code coverage 10 | coverage 11 | *.lcov 12 | 13 | # logs 14 | logs 15 | _.log 16 | report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json 17 | 18 | # dotenv environment variable files 19 | .env 20 | .env.development.local 21 | .env.test.local 22 | .env.production.local 23 | .env.local 24 | 25 | # caches 26 | .eslintcache 27 | .cache 28 | *.tsbuildinfo 29 | 30 | # IntelliJ based IDEs 31 | .idea 32 | 33 | # Finder (MacOS) folder config 34 | .DS_Store 35 | -------------------------------------------------------------------------------- /client/stores/chat-store.tsx: -------------------------------------------------------------------------------- 1 | import { create } from 'zustand' 2 | 3 | export interface ChatItem { 4 | id: string 5 | name: string 6 | } 7 | 8 | interface ChatStore { 9 | chats: ChatItem[] 10 | addChat: () => ChatItem 11 | } 12 | 13 | export const useChatStore = create((set, get) => ({ 14 | chats: [], 15 | addChat: () => { 16 | const newChat: ChatItem = { 17 | id: crypto.randomUUID(), 18 | name: `Chat ${get().chats.length + 1}` 19 | } 20 | set((state) => ({ 21 | chats: [...state.chats, newChat] 22 | })) 23 | return newChat 24 | } 25 | })) -------------------------------------------------------------------------------- /client/components/theme-provider.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import { useEffect, useState } from 'react' 5 | import { ThemeProvider as NextThemesProvider } from "next-themes" 6 | 7 | export const useMounted = () => { 8 | const [mounted, setMounted] = useState(false) 9 | useEffect(() => { setMounted(true) }, []) 10 | return mounted 11 | } 12 | 13 | export function ThemeProvider({ 14 | children, 15 | ...props 16 | }: React.ComponentProps) { 17 | const mounted = useMounted() 18 | return mounted && {children} 19 | } 20 | -------------------------------------------------------------------------------- /mcp-servers/booking-mcp/README.md: -------------------------------------------------------------------------------- 1 | # Booking MCP Server (TypeScript) 2 | 3 | This directory contains a Model Context Protocol (MCP) Booking demo server implementation with two transport protocols: 4 | 5 | 1. **stdio** - For command-line tools and direct integrations 6 | 2. **sse (server-sent events)** - For web-based applications 7 | 8 | ## Prerequisites 9 | 10 | - Project using [Bun](https://bun.sh/) as runtime. 11 | 12 | ## Installation 13 | 14 | ```bash 15 | bun install 16 | ``` 17 | 18 | ## Running with stdio protocol 19 | 20 | Server start is initiated by a MCP client. 21 | 22 | ## Running with sse protocol 23 | 24 | ```bash 25 | bun run start 26 | ``` -------------------------------------------------------------------------------- /client/hooks/use-mobile.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | const MOBILE_BREAKPOINT = 768 4 | 5 | export function useIsMobile() { 6 | const [isMobile, setIsMobile] = React.useState(undefined) 7 | 8 | React.useEffect(() => { 9 | const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) 10 | const onChange = () => { 11 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 12 | } 13 | mql.addEventListener("change", onChange) 14 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 15 | return () => mql.removeEventListener("change", onChange) 16 | }, []) 17 | 18 | return !!isMobile 19 | } 20 | -------------------------------------------------------------------------------- /client/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.* 7 | .yarn/* 8 | !.yarn/patches 9 | !.yarn/plugins 10 | !.yarn/releases 11 | !.yarn/versions 12 | 13 | # testing 14 | /coverage 15 | 16 | # next.js 17 | /.next/ 18 | /out/ 19 | 20 | # production 21 | /build 22 | 23 | # misc 24 | .DS_Store 25 | *.pem 26 | 27 | # debug 28 | npm-debug.log* 29 | yarn-debug.log* 30 | yarn-error.log* 31 | .pnpm-debug.log* 32 | 33 | # env files (can opt-in for committing if needed) 34 | .env.* 35 | 36 | # vercel 37 | .vercel 38 | 39 | # typescript 40 | *.tsbuildinfo 41 | next-env.d.ts 42 | -------------------------------------------------------------------------------- /agent/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "langgraph-agent" 3 | version = "0.1.0" 4 | description = "" 5 | authors = ["elupanov "] 6 | readme = "README.md" 7 | packages = [ 8 | { include = "app" }, 9 | ] 10 | 11 | [tool.poetry.dependencies] 12 | python = "^3.12" 13 | langgraph = "^0.3.22" 14 | langchain = "^0.3.14" 15 | langchain-openai = "^0.3.11" 16 | python-dotenv = "^1.0.1" 17 | fastapi = "^0.115.5" 18 | uvicorn = "^0.34.0" 19 | sse-starlette = ">=2.1.0" 20 | langchain-mcp-adapters = "^0.0.7" 21 | mcp = "^1.6.0" 22 | 23 | [build-system] 24 | requires = ["poetry-core"] 25 | build-backend = "poetry.core.masonry.api" 26 | 27 | [tool.poetry.scripts] 28 | server = "app.server:main" 29 | -------------------------------------------------------------------------------- /client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "module": "esnext", 11 | "moduleResolution": "bundler", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "preserve", 15 | "incremental": true, 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | "paths": { 22 | "@/*": ["./*"] 23 | } 24 | }, 25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 26 | "exclude": ["node_modules"] 27 | } 28 | -------------------------------------------------------------------------------- /mcp-servers/calendar-mcp/README.md: -------------------------------------------------------------------------------- 1 | # Calendar MCP Server (Python) 2 | 3 | This directory contains a Model Context Protocol (MCP) Calendar demo server implementation with two transport protocols: 4 | 5 | 1. **stdio** - For command-line tools and direct integrations 6 | 2. **sse (server-sent events)** - For web-based applications 7 | 8 | ## Prerequisites 9 | 10 | - Python 3.13 or higher 11 | - [uv](https://github.com/astral-sh/uv) for dependency management 12 | 13 | ## Installation 14 | 15 | ```bash 16 | uv sync 17 | ``` 18 | 19 | ## Running with stdio protocol 20 | 21 | Server start is initiated by a MCP client. 22 | 23 | 24 | ## Running with sse protocol 25 | 26 | ```bash 27 | uv run python calendar-mcp-server.py sse 28 | ``` 29 | -------------------------------------------------------------------------------- /client/components/ui/textarea.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | import { cn } from "@/lib/utils" 4 | 5 | const Textarea = React.forwardRef< 6 | HTMLTextAreaElement, 7 | React.ComponentProps<"textarea"> 8 | >(({ className, ...props }, ref) => { 9 | return ( 10 |