Skip to content

Commit 93ee363

Browse files
committed
update mcp course content formate
1 parent 58c344c commit 93ee363

File tree

17 files changed

+376
-397
lines changed

17 files changed

+376
-397
lines changed

app/course/[slug]/page.tsx

Lines changed: 88 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,114 +1,108 @@
1-
import fs from 'fs'
2-
import path from 'path'
3-
import matter from 'gray-matter'
41
import { notFound } from 'next/navigation'
5-
import Link from 'next/link'
2+
import { CustomMDX } from '@/components/mdx'
3+
import { getCourseModules } from '../utils'
64

7-
interface PageProps {
8-
params: Promise<{
9-
slug: string
10-
}>
11-
}
5+
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:3000'
6+
7+
export async function generateStaticParams() {
8+
const modules = getCourseModules()
129

13-
interface UnitData {
14-
title: string
15-
content: string
16-
frontmatter: Record<string, unknown>
10+
return modules.map((module) => ({
11+
slug: module.slug,
12+
}))
1713
}
1814

19-
async function getUnitBySlug(slug: string): Promise<UnitData | null> {
20-
try {
21-
// Parse the slug to get unit directory and file name
22-
const [unitDir, fileName] = slug.split('/')
23-
24-
if (!unitDir || !fileName) {
25-
return null
26-
}
15+
export function generateMetadata({ params }: { params: { slug: string } }) {
16+
const courseModule = getCourseModules().find((module) => module.slug === params.slug)
17+
if (!courseModule) {
18+
return
19+
}
2720

28-
const filePath = path.join(process.cwd(), 'app/course/units', unitDir, `${fileName}.mdx`)
29-
30-
if (!fs.existsSync(filePath)) {
31-
return null
32-
}
21+
const {
22+
title,
23+
publishedAt: publishedTime,
24+
summary: description,
25+
image,
26+
} = courseModule.metadata
27+
const ogImage = image
28+
? image
29+
: `${baseUrl}/og?title=${encodeURIComponent(title)}`
3330

34-
const source = fs.readFileSync(filePath, 'utf8')
35-
const { data: frontmatter, content } = matter(source)
36-
37-
// Extract title from the first heading or use filename
38-
const titleMatch = content.match(/^#\s+(.+)$/m)
39-
const title = titleMatch ? titleMatch[1] : fileName
40-
41-
return {
31+
return {
32+
title,
33+
description,
34+
openGraph: {
35+
title,
36+
description,
37+
type: 'article',
38+
publishedTime,
39+
url: `${baseUrl}/course/${courseModule.slug}`,
40+
images: [
41+
{
42+
url: ogImage,
43+
},
44+
],
45+
},
46+
twitter: {
47+
card: 'summary_large_image',
4248
title,
43-
content,
44-
frontmatter
45-
}
46-
} catch (error) {
47-
console.error('Error reading unit file:', error)
48-
return null
49+
description,
50+
images: [ogImage],
51+
},
4952
}
5053
}
5154

52-
export default async function UnitPage({ params }: PageProps) {
53-
const { slug } = await params
54-
const unit = await getUnitBySlug(slug)
55-
56-
if (!unit) {
55+
export default async function CourseModule({ params }: { params: { slug: string } }) {
56+
const courseModule = getCourseModules().find((module) => module.slug === params.slug)
57+
58+
if (!courseModule) {
5759
notFound()
5860
}
5961

6062
return (
61-
<div className="min-h-screen bg-gray-50">
62-
<div className="max-w-4xl mx-auto px-4 py-8">
63-
<div className="mb-8">
64-
<nav className="mb-6">
65-
<Link
66-
href="/course/units"
67-
className="text-blue-600 hover:text-blue-800 font-medium"
68-
>
69-
← Back to Course
70-
</Link>
71-
</nav>
72-
73-
<h1 className="text-4xl font-bold text-gray-900 mb-4">
74-
{unit.title}
75-
</h1>
76-
</div>
77-
78-
<article className="bg-white rounded-lg shadow-md overflow-hidden">
79-
<div className="p-8">
80-
<div className="prose prose-lg max-w-none">
81-
<div className="whitespace-pre-wrap text-gray-700 leading-relaxed">
82-
{unit.content}
83-
</div>
84-
</div>
63+
<section className="items-center justify-center">
64+
<script
65+
type="application/ld+json"
66+
suppressHydrationWarning
67+
dangerouslySetInnerHTML={{
68+
__html: JSON.stringify({
69+
'@context': 'https://schema.org',
70+
'@type': 'Course',
71+
headline: courseModule.metadata.title,
72+
datePublished: courseModule.metadata.publishedAt,
73+
dateModified: courseModule.metadata.publishedAt,
74+
description: courseModule.metadata.summary,
75+
image: courseModule.metadata.image
76+
? `${baseUrl}${courseModule.metadata.image}`
77+
: `/og?title=${encodeURIComponent(courseModule.metadata.title)}`,
78+
url: `${baseUrl}/course/${courseModule.slug}`,
79+
author: {
80+
'@type': 'Person',
81+
name: 'CAMEL MCP Course',
82+
},
83+
}),
84+
}}
85+
/>
86+
<div className="max-w-[900px] min-h-screen mx-auto justify-center items-center py-24">
87+
<div className="flex flex-col items-center rounded-xl gap-8 w-full">
88+
<h1 className="title font-semibold text-4xl tracking-tighter leading-tight text-center font-[family-name:var(--font-main)]">
89+
{courseModule.metadata.title || `Module ${courseModule.slug}`}
90+
</h1>
91+
{courseModule.metadata.publishedAt && (
92+
<div className="flex flex-row justify-center gap-8 w-full items-center mt-2 mb-8 text-sm border-b border-neutral-200 pt-2 pb-8 font-[family-name:var(--font-mono)]">
93+
<p className="text-sm text-neutral-600 dark:text-neutral-400">
94+
<span className="font-bold italic mr-2">Written by</span> {courseModule.metadata.author || 'CAMEL-AI'}
95+
</p>
96+
<p className="text-sm text-neutral-600 dark:text-neutral-400">
97+
<span className="font-bold italic mr-2">Reviewed by</span> {courseModule.metadata.reviewer || 'CAMEL-AI'}
98+
</p>
8599
</div>
100+
)}
101+
</div>
102+
<article className="prose prose-lg max-w-none font-[family-name:var(--font-sans)]">
103+
{await CustomMDX({ source: courseModule.content })}
86104
</article>
87105
</div>
88-
</div>
106+
</section>
89107
)
90108
}
91-
92-
// Generate static params for all units
93-
export async function generateStaticParams() {
94-
const unitsDir = path.join(process.cwd(), 'app/course/units')
95-
const unitDirs = fs.readdirSync(unitsDir).filter(dir =>
96-
fs.statSync(path.join(unitsDir, dir)).isDirectory() && dir.startsWith('unit')
97-
)
98-
99-
const params: { slug: string }[] = []
100-
101-
for (const unitDir of unitDirs) {
102-
const unitPath = path.join(unitsDir, unitDir)
103-
const files = fs.readdirSync(unitPath).filter(file => file.endsWith('.mdx'))
104-
105-
for (const file of files) {
106-
const fileName = file.replace('.mdx', '')
107-
params.push({
108-
slug: `${unitDir}/${fileName}`
109-
})
110-
}
111-
}
112-
113-
return params
114-
}

app/course/modules/module0.mdx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
3+
title: "Course Overview - CAMEL-AI with MCP"
4+
publishedAt: "2025-08-07"
5+
summary: "Introduction to the CAMEL AI MCP course"
6+
author: "Parth Sharma"
7+
reviewer: "Xiaotian Jing"
8+
9+
---
10+
11+
# Mastering CAMEL AI with Model Context Protocol (MCP)
12+
13+
## Course Overview
14+
15+
This course takes you on a journey from understanding basic tooling in CAMEL AI to mastering the Model Context Protocol (MCP), a powerful standard for connecting AI agents with external tools. You'll learn how to configure tools in CAMEL AI, explore MCP's role as a universal bridge, build custom MCP servers, and integrate them with CAMEL AI agents. By the end, you'll be able to create versatile, tool-augmented AI agents that work seamlessly across platforms.
16+
17+
## Target Audience
18+
19+
- Developers with basic Python knowledge.
20+
- AI enthusiasts eager to explore advanced tooling and interoperability.
21+
22+
## Prerequisites
23+
24+
- Basic Python skills (functions, imports).
25+
- Optional: Familiarity with AI concepts.

app/course/units/unit1/module1.mdx renamed to app/course/modules/module1.mdx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
1-
# Module 1: Understanding Tooling in CAMEL AI
1+
---
2+
title: "Module 1: Understanding Tooling in CAMEL AI"
3+
publishedAt: "2025-08-07"
4+
summary: "Learn what tools are in CAMEL AI, how to configure and use them, and why traditional tooling has limitations."
5+
author: "Parth Sharma"
6+
reviewer: "Xiaotian Jing"
7+
---
28

3-
**Objective:** Learn what tools are in CAMEL AI, how to configure and use them, and why traditional tooling has limitations.
9+
## Objective:
10+
11+
Learn what tools are in CAMEL AI, how to configure and use them, and why traditional tooling has limitations.
412

513
## 1.1 Introduction to Tools in CAMEL AI
614

@@ -93,6 +101,6 @@ While powerful, traditional tooling in CAMEL AI has drawbacks:
93101

94102
These limitations call for a better solution—MCP.
95103

96-
**Reflection Question:**
104+
## Reflection Question:
97105

98-
What tool would you create for an AI agent, and how would you define it?
106+
#### What tool would you create for an AI agent, and how would you define it?

app/course/units/unit2/module2.mdx renamed to app/course/modules/module2.mdx

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
1-
# Module 2: Introducing the Model Context Protocol (MCP)
1+
---
2+
title: "Module 2: Introducing the Model Context Protocol (MCP)"
3+
publishedAt: "2025-08-07"
4+
summary: "Understand MCP, its principles, and how it solves tooling limitations."
5+
author: "Parth Sharma"
6+
reviewer: "Xiaotian Jing"
7+
---
28

3-
**Objective:** Understand MCP, its principles, and how it solves tooling limitations.
9+
## Objective:
10+
11+
Understand MCP, its principles, and how it solves tooling limitations.
412

513
## 2.1 What is MCP?
614

@@ -42,8 +50,8 @@ graph TD
4250
style E fill:#fff3e0
4351
```
4452

45-
![how-mcp-solves-tooling-issues.png](mcp.camel-ai.org/course/module2/how-mcp-solves-tooling-issues.png)
53+
![how-mcp-solves-tooling-issues.png](/course/module2/how-mcp-solves-tooling-issues.png)
4654

47-
**Reflection Question:**
55+
## Reflection Question
4856

49-
How might MCP's standardization change AI development?
57+
#### How might MCP's standardization change AI development?

app/course/units/unit3/module3.mdx renamed to app/course/modules/module3.mdx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
1-
# Module 3: Understanding MCP’s Architecture
1+
---
2+
title: "Module 3: Understanding MCP’s Architecture"
3+
publishedAt: "2025-08-07"
4+
summary: "Get familiar with how MCP’s client-server design works and follow the steps of its interaction flow."
5+
author: "Parth Sharma"
6+
reviewer: "Xiaotian Jing"
7+
---
28

3-
**Objective:** Get familiar with how MCP’s client-server design works and follow the steps of its interaction flow.
9+
## Objective:
10+
11+
Get familiar with how MCP’s client-server design works and follow the steps of its interaction flow.
412

513
## 3.1 What is MCP’s Client-Server Architecture?
614

@@ -68,6 +76,6 @@ graph LR
6876

6977
A CAMEL agent asks, “What time is it?” It connects to a Time MCP Server, discovers `get_current_time`, invokes it, and gets the time.
7078

71-
**Reflection Question:**
79+
## Reflection Question:
7280

73-
Why is dynamic tool discovery useful?
81+
#### Why is dynamic tool discovery useful?

app/course/units/unit4/module4.mdx renamed to app/course/modules/module4.mdx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
1-
# Module 4: Building Your Own MCP Server
1+
---
2+
title: "Module 4: Building Your Own MCP Server"
3+
publishedAt: "2025-08-07"
4+
summary: "Learn how to create your own MCP server using FastMCP to share tools with AI agents."
5+
author: "Parth Sharma"
6+
reviewer: "Xiaotian Jing"
7+
---
28

3-
**Objective:** Learn how to create your own MCP server using FastMCP to share tools with AI agents.
9+
## Objective:
10+
11+
Learn how to create your own MCP server using FastMCP to share tools with AI agents.
412

513
## 4.1 Introduction to FastMCP
614

@@ -52,6 +60,6 @@ Decorators are like labels that tell FastMCP how to use your functions. Here’s
5260

5361
Unlike traditional toolkits, MCP servers decouple tool logic from the agent, enabling standardized, discoverable access.
5462

55-
**Reflection Question:**
63+
## Reflection Question:
5664

57-
What custom tool would you build with FastMCP?
65+
#### What custom tool would you build with FastMCP?

app/course/units/unit5/module5.mdx renamed to app/course/modules/module5.mdx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
1-
# Module 5: Integrating CAMEL AI with MCP
1+
---
2+
title: "Module 5: Integrating CAMEL AI with MCP"
3+
publishedAt: "2025-08-07"
4+
summary: "Configure CAMEL AI agents as MCP clients to use tools from MCP servers."
5+
author: "Parth Sharma"
6+
reviewer: "Xiaotian Jing"
7+
---
28

3-
**Objective:** Configure CAMEL AI agents as MCP clients to use tools from MCP servers.
9+
## Objective:
10+
11+
Configure CAMEL AI agents as MCP clients to use tools from MCP servers.
412

513
## 5.1 CAMEL AI as an MCP Client
614

@@ -259,6 +267,6 @@ toolkit.mcp.run(args.mode)
259267

260268
The `mcp.run()` method (with an assumed `@MCPServer()` decorator in `ArxivToolkit`) exposes toolkit methods as MCP tools, listed via `tools/list`. Other MCP clients can then tap in.
261269

262-
**Reflection Question:**
270+
## Reflection Question:
263271

264-
Why bother with config files for MCP servers?
272+
#### Why bother with config files for MCP servers?

0 commit comments

Comments
 (0)