DAY 3

Resources & Prompts 📚🔍🤖

Discover how to harness the power of resources and prompts to supercharge your AI agent's abilities. Learn how to effectively utilize these tools to enhance your agent's performance and capabilities.

⏱ 12 mins
⚡ +100 XP

Day 3 — MCP Resources & Prompts

MCP & AI Agents — Agent Bootcamp Part 2 — RohithBuilds

So far your server only has tools — functions the AI actively calls when it decides it needs to. Today you'll meet MCP's other two building blocks: resources (read-only data an AI can look at) and prompts (reusable message templates). By the end of today, your notes won't just be something the AI can fetch on request — they'll be something it can browse, and you'll have ready-made prompts that turn your data into useful AI conversations instantly.

Step 1 — Tools vs Resources vs Prompts

These three MCP building blocks solve different problems:

  • Tools (Day 1–2) — actions. The AI decides "I need to do something" and calls a function, like add_note or exam_countdown.
  • Resources (today) — data. Read-only information an AI client can browse or attach as context, identified by a URI like notes://all. No "calling" or reasoning required — it's just there to be read.
  • Prompts (today) — templates. Pre-written, sometimes parameterized, message templates that turn a request like "summarize my notes" into a fully-formed prompt, every time, the same way.

A simple way to remember it: tools are verbs, resources are nouns, and prompts are sentences your server hands to the AI.

Step 2 — Expose Your Notes as a Resource

Open server.py. Add this above if __name__ == "__main__":, anywhere after your list_notes_logic function:

@mcp.resource("notes://all")
def notes_resource() -> str:
    """All of the student's saved notes, as a readable resource."""
    return list_notes_logic()

The "notes://all" string is a URI — a unique address for this resource, the same idea as a URL. Any MCP client can now "open" notes://all the way a browser opens a web page, without calling it like a function.

Step 3 — Build a Resource Template for a Single Note

Resources can also be templated — part of the URI becomes a parameter. Add this:

def get_note_by_id(note_id: str) -> str:
    try:
        nid = int(note_id)
    except ValueError:
        return f"'{note_id}' is not a valid note ID."

    conn = sqlite3.connect(DB_FILE)
    row = conn.execute(
        "SELECT id, text, created_at FROM notes WHERE id = ?", (nid,)
    ).fetchone()
    conn.close()

    if row is None:
        return f"No note found with ID #{note_id}."
    return f"#{row[0]} [{row[2]}]: {row[1]}"


@mcp.resource("notes://{note_id}")
def note_by_id_resource(note_id: str) -> str:
    """A single note, looked up by its ID."""
    return get_note_by_id(note_id)

Notice the {note_id} in the URI — MCP matches that against the function parameter, the same way Flask matches <filename> in a route. notes://1, notes://2, and so on all become valid resource addresses automatically.

Step 4 — Restart Inspector & Explore Resources

Restart Inspector to pick up the changes:

mcp dev server.py

Open the Inspector link and click the Resources tab. You should see notes://all listed, plus notes://{note_id} shown as a template.

Expected Output

MCP Inspector Resources tab listing notes://all and the notes://{note_id} template

Click notes://all to read it — you should see every note you've saved so far.

Expected Output

MCP Inspector showing the contents of the notes://all resource with all saved notes

Now click on the notes://{note_id} template, enter 1 for note_id, and read it.

Expected Output

MCP Inspector showing a single note returned from the notes://1 resource

Step 5 — Build a Prompt: Summarize My Notes

Prompts work like resources and tools — a plain function plus a thin @mcp.prompt() wrapper. Add this:

def build_summary_prompt() -> str:
    notes = list_notes_logic()
    return (
        f"Here are my notes:\n\n{notes}\n\n"
        "Summarize these into a short to-do list, grouped by topic if possible."
    )


@mcp.prompt()
def summarize_notes() -> str:
    """Ask the AI to summarize all saved notes into a short to-do list."""
    return build_summary_prompt()

This prompt pulls your live notes into the template every time it's used — it's never out of date.

Step 6 — Build a Prompt: Exam Prep Plan

Let's tie today back to Day 1's exam_countdown tool. Add this:

def build_exam_prep_prompt(exam_name: str, exam_date: str) -> str:
    countdown = get_exam_countdown(exam_name, exam_date)
    return (
        f"{countdown}\n\n"
        f"Based on this, create a realistic day-by-day study plan for {exam_name}. "
        "Keep it practical for a student with 2-3 hours of free time per day."
    )


@mcp.prompt()
def exam_prep_plan(exam_name: str, exam_date: str) -> str:
    """Ask the AI to build a day-by-day study plan for an exam."""
    return build_exam_prep_prompt(exam_name, exam_date)

This prompt takes parameters — Inspector will show input fields for exam_name and exam_date, just like it does for tools.

Step 7 — Test Your Prompts in Inspector

Restart Inspector again, then click the Prompts tab. You should see summarize_notes and exam_prep_plan listed.

Expected Output

MCP Inspector Prompts tab listing summarize_notes and exam_prep_plan

Click summarize_notes and run it. You should see the full generated prompt, with your actual notes embedded inside it.

Expected Output

MCP Inspector showing the generated summarize_notes prompt text containing the student's notes

Now click exam_prep_plan, enter exam_name: GATE 2027 and exam_date: 2027-02-08, and run it.

Expected Output

MCP Inspector showing the generated exam_prep_plan prompt combining the countdown and study plan request

This is the output an AI client would actually receive and respond to. Tomorrow, you'll build a client that does exactly that — automatically.

Step 8 — Fallback Test Without Inspector

Create test_local.py (or extend yesterday's):

from server import get_note_by_id, build_summary_prompt, build_exam_prep_prompt

print("=== Note #1 ===")
print(get_note_by_id("1"))

print("\n=== Summarize Notes Prompt ===")
print(build_summary_prompt())

print("\n=== Exam Prep Plan Prompt ===")
print(build_exam_prep_prompt("GATE 2027", "2027-02-08"))

Run it:

python test_local.py

Expected Output

Terminal showing a single note, the summarize notes prompt, and the exam prep prompt printed

✅ Day 3 Complete

Here is what you accomplished today:

Key Takeaways

  • Understood the difference between tools, resources, and prompts ✅
  • Exposed your notes as a readable resource (notes://all) ✅
  • Built a parameterized resource template (notes://{note_id}) ✅
  • Built a prompt that summarizes live notes data ✅
  • Built a parameterized prompt for exam study plans ✅
  • Tested resources and prompts in MCP Inspector ✅

What Is Coming Tomorrow

On Day 4 you will:

  • Build your first MCP client in Python
  • Connect that client to the server you've been building all week
  • List your server's tools programmatically — no Inspector needed
  • Bridge those tools to Groq, so an AI model can choose and call them on its own

This is the day everything clicks together. See you there! 🚀

← Previous Lesson