Video Chapters
0:00 What we build today
0:38 The two problems
1:22 The checklist, second run
1:44 Let Claude see the folder
2:47 Open one draft
3:14 Save your editing job
3:42 Check what the server offers
4:03 Restart and ask Claude
5:08 Run the proof
5:19 What this lesson cost
5:54 The map now

Let Claude see the whole folder

Lesson 14 of 30, Module 2: Your First Server. Your own server edits real documents in your Drive folder.

Table of Contents
Downloads

Lesson 14 of 30, Module 2: Your First Server. Your own server edits real documents in your Drive folder.

What you can do after this lesson

Give the model two things it cannot get from a tool alone: a way to see what exists (a resource) and a job you have already written down (a prompt). Each is a small function, one decorator line and one sentence, and you can add them without touching what already works.

The problem we inherited

You install the official Google Drive server and Claude reads every document and changes none of them.

The 5 steps this lesson runs

  1. Write the plain Python function
  2. Put the @mcp line above it
  3. Write the one-line docstring
  4. Restart Claude Desktop
  5. Ask Claude to use it

Code in this lesson

Every block the lesson shows on screen, in the order it appears.

1. Write the plain Python function
2. Put the @mcp line above it
3. Write the one-line docstring
4. Restart Claude Desktop
5. Ask Claude to use it
@mcp.resource("drafts://folder")
def folder() -> str:
    """The name of every draft in the Scribe folder."""
    q = (f"'{FOLDER}' in parents and trashed = false"
         " and mimeType contains 'text/'")
    found = drive.files().list(q=q, fields="files(name)",
                               orderBy="name").execute()
    return "\n".join(f["name"] for f in found["files"])
@mcp.resource("drafts://{name}")
def draft(name: str) -> str:
    """One draft from the Scribe folder, by its name."""
    return _text(_find(name))
@mcp.prompt()
def tidy_draft(name: str) -> str:
    """Fix the spelling and tighten the opening of one draft."""
    return (f"Read the draft called {name}. Fix every spelling"
            " mistake. Make the opening line shorter and"
            " stronger. Keep my voice, and change nothing else."
            " Use edit_doc for each change.")
uv run what_can_it_do.py
python3 what_can_it_do.py
TOOLS
  read_doc
    Read one draft from the Scribe folder in Google Drive.
    input: name (string, required)
  edit_doc
    Replace some text inside one draft in the Scribe folder.
    input: name (string, required)
    input: find (string, required)
    input: replace (string, required)

RESOURCES
  drafts://folder
    The name of every draft in the Scribe folder.
  drafts://{name}
    One draft from the Scribe folder, by its name.

PROMPTS
  tidy_draft
    Fix the spelling and tighten the opening of one draft.
    input: name
Which of my drafts is about the launch?
python3 prove_it.py
VERDICT
   PASS  both tools are offered
   PASS  typo was there before
   PASS  typo is gone after
   PASS  the draft changed on Drive
   PASS  missing words change nothing
   PASS  a missing draft is explained
   PASS  the folder lists your draft
   PASS  the resource matches the tool
   PASS  the saved job names your draft

RESULT: your server works.

Downloads

Prefer to read?

The written version of this part of the course is on Substack: https://genaiunplugged.substack.com/p/how-to-build-an-mcp-server-and-connect.

Lesson transcript

What we build today

Today Claude stops asking you for file names, and you stop typing the same instruction every week.

Hello, and welcome to lesson 14 of the MCP Masterclass. Last lesson we proved that Scribe changes the real document. Today we give Claude the whole folder, and we save your editing job. And we start with our map, as always.

9 lit boxes. Today 2 more light up, and both of them sit right beside your server.

So let me show you the finished thing first.

On screen: in Claude Desktop, the folder list from Scribe is attached to the chat. Then the saved job tidy_draft is picked, launch-post.md is named, and Claude tidies the draft.

I hand Claude the list of my drafts. Then I pick a saved job, and I name a draft. Claude tidies that draft, and I typed almost nothing.

Now let us go back and build it.

The two problems

Scribe works, and you proved it. But it has 2 problems, and you have probably felt both.

The first problem. Scribe edits the 1 file you name. Claude cannot see what else is in the folder, so you have to remember every file name yourself.

The second problem. You type the same instruction every single time. Fix the spelling, tighten the opening, keep my voice.

MCP has an answer for each of them, and you met both in lesson 8.

A resource is nothing but something your AI can look at. And a prompt here is nothing but a saved job.

Now, there is one difference that matters, and it is about who is in charge.

A tool is picked by the model. Claude decides when to run it. A resource and a prompt are picked by you. You hand them over when you want them.

The checklist, second run

Okay. Here is our list, and it has not changed by a single word.

1. Write the plain Python function
2. Put the @mcp line above it
3. Write the one-line docstring
4. Restart Claude Desktop
5. Ask Claude to use it

Write the plain Python function. Put the @mcp line above it. Write the one line docstring. Restart Claude Desktop. Ask Claude to use it.

Last time, steps 1 to 3 needed a long and careful walk. This time you already know them, so I am going to show you all 3 at once.

Let Claude see the folder

So let us start with the folder.

Open scribe_server.py, and put this under your 2 tools.

@mcp.resource("drafts://folder")
def folder() -> str:
    """The name of every draft in the Scribe folder."""
    q = (f"'{FOLDER}' in parents and trashed = false"
         " and mimeType contains 'text/'")
    found = drive.files().list(q=q, fields="files(name)",
                               orderBy="name").execute()
    return "\n".join(f["name"] for f in found["files"])

There is the function, there is the @mcp line, and there is the docstring. Same 3 steps.

Now look at the @mcp line, because it has changed a little. Last time it said tool. This time it says resource, and it carries an address.

But what is an address here?

An address is nothing but a name that an app uses to ask for this exact thing. Ours says drafts, and then folder.

And now you know why step 2 says the @mcp line. It never said the tool line, because the same step covers all 3 kinds of thing.

The function itself is a search you already know, which names the folder and skips anything in the bin.

Then it does 1 new thing, which is to keep the text files and leave everything else out.

I added that after looking at my own Drive. One of my folders holds over 100 video files, and Claude does not need to read through those. Scribe edits text, so Scribe lists text.

And it hands back the names, with 1 name on each line.

Open one draft

Next, a single draft.

@mcp.resource("drafts://{name}")
def draft(name: str) -> str:
    """One draft from the Scribe folder, by its name."""
    return _text(_find(name))

Look at the address again. This one has a blank in it, and the curly brackets mark the blank.

The app fills that blank with a file name. Your function receives the name, and it hands back the words.

And the real work is 1 line, because your 2 helpers already exist. You wrote them once, and now a tool and a resource both lean on them.

That was steps 1, 2 and 3, twice over. Did you notice how little I had to explain?

Save your editing job

Now the saved job.

@mcp.prompt()
def tidy_draft(name: str) -> str:
    """Fix the spelling and tighten the opening of one draft."""
    return (f"Read the draft called {name}. Fix every spelling"
            " mistake. Make the opening line shorter and"
            " stronger. Keep my voice, and change nothing else."
            " Use edit_doc for each change.")

Same 3 steps again. The function, the @mcp line, which says prompt this time, and the docstring.

And look at what this function does. It does no work at all, because it only hands back words.

Those words are the instruction you would have typed by hand. You give it a draft name, and it gives you the full instruction with that name inside.

The words on screen are mine. Change them to yours, because this is your editing job and you know how you like it done.

Check what the server offers

So let us ask the server what it offers now.

uv run what_can_it_do.py

Or with pip.

python3 what_can_it_do.py

And here is the new list.

TOOLS
  read_doc
    Read one draft from the Scribe folder in Google Drive.
    input: name (string, required)
  edit_doc
    Replace some text inside one draft in the Scribe folder.
    input: name (string, required)
    input: find (string, required)
    input: replace (string, required)

RESOURCES
  drafts://folder
    The name of every draft in the Scribe folder.
  drafts://{name}
    One draft from the Scribe folder, by its name.

PROMPTS
  tidy_draft
    Fix the spelling and tighten the opening of one draft.
    input: name

2 tools, 2 resources, and 1 prompt. Every one of them describes itself, and you wrote no description twice.

And notice what did not change. We never touched read_doc or edit_doc. We added 3 things beside them, and the old ones carried on working.

Restart and ask Claude

Step 4. Restart Claude Desktop.

Your settings entry stays exactly as it is, because it is the same file in the same place. So quit Claude Desktop properly, and open it again.

Step 5. Ask Claude to use it.

Now remember who is in charge. You pick resources and prompts. So this time you start with a menu.

Open the menu beside the chat box, and look for the name scribe.

On screen: the menu beside the chat box in Claude Desktop, with scribe in it. Under scribe, the folder resource and the tidy_draft saved job.

Every app puts this in a slightly different place. So do not hunt for a button. Look for the name of your server.

Pick the folder first.

On screen: the folder resource attached to the chat. It holds 4 names: draft.md, launch-post.md, weekly-notes.txt and welcome-email.md.

Claude now holds the list of your drafts. Those are the 3 samples you uploaded in lesson 11, and the draft from lesson 4.

And that list is external intelligence. Claude was never trained on your folder, and now it can see what is in it.

So ask it something that needs the list.

Which of my drafts is about the launch?

Claude answers with the file name. You did not have to remember it.

Now pick the saved job, and give it that name.

On screen: Tidy draft picked from the scribe menu. A small window asks for the draft name, and launch-post.md is typed in. The instruction attaches to the chat.

Your instruction is attached to the chat, with the draft name already inside it. Send it.

On screen: Claude reads launch-post.md, then makes 3 edits. It shortens the opening line and fixes 2 spelling mistakes. Then launch-post.md open in Drive, changed.

Claude reads the draft. If it stops and asks you first, say yes. And then it fixes the draft in your Drive.

Run the proof

And one last check, because we never take the server at its word. Run the proof again.

python3 prove_it.py

It now tests the new parts too, and this is how it ends.

VERDICT
   PASS  both tools are offered
   PASS  typo was there before
   PASS  typo is gone after
   PASS  the draft changed on Drive
   PASS  missing words change nothing
   PASS  a missing draft is explained
   PASS  the folder lists your draft
   PASS  the resource matches the tool
   PASS  the saved job names your draft

RESULT: your server works.

9 checks, and 9 passes.

What this lesson cost

Now stop for a moment, because I want you to see what this lesson cost you.

You added 3 new things to your server. Each one was a function, 1 line above it, and 1 sentence inside it.

Steps 1 to 3 were slow in lesson 12, and today they were quick. And steps 4 and 5 were the same as they always are.

That is the second time through the list. Keep an eye on it, because it gets cheaper again in module 3.

And what did you get for it? Claude can see your whole folder, so you stop remembering file names. And your editing job is saved, so you stop typing it.

The map now

So where does our map stand at the end of this lesson?

2 new boxes are lit. One is the folder Claude can browse, and the other is your saved jobs. That makes 11 lit boxes.

Next lesson is a quick recap of everything we built in module 2.

Bye now, and I will see you in the next lesson.

Frequently Asked Questions

The written version of this part of the course is on Substack: https://genaiunplugged.substack.com/p/how-to-build-an-mcp-server-and-connect.

Dheeraj Sharma

Dheeraj Sharma

AI Systems Builder
Creator of the n8n Zero to Hero course (42 lessons, 31+ hours). I help solopreneurs build AI systems that grow revenue without growing workload.

Get the Scribe checkpoints and code

Every module ships a checkpoint zip with the server exactly as the module leaves it, so you can start any lesson from working code.

Open the GitHub repo