Video Chapters
0:00 Stop taking its word for it
0:26 Six tests, one fails
0:46 Test 1: look in Drive
1:12 Test 2: a proof you can rerun
1:54 Tests 3 and 4: bad inputs
2:35 Why the error went quiet
3:06 The two small changes
4:02 Test 5: Scribe cannot make a file
4:34 Test 6: a second app
5:14 What we proved

Prove it changed the real document

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

Table of Contents
Downloads

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

What you can do after this lesson

A tool that says done has only told you what it meant to do. Check the real thing from outside, vary the input on purpose, and write every error message as a message to the AI that will read it.

The problem we inherited

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

Code in this lesson

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

uv run prove_it.py
python3 prove_it.py
1. READ draft.md FROM DRIVE
   | # My first draft
   |
   | This is a test. Ths line has a typo in it.

2. FIX THE TYPO
   server said:
   | Changed 1 spot(s) in draft.md.

3. READ IT BACK FROM DRIVE
   | # My first draft
   |
   | This is a test. This line has a typo in it.
4. ASK FOR WORDS THAT ARE NOT IN THE DRAFT
   server said:
   | That text is not in draft.md. Nothing changed.
5. ASK FOR A DRAFT THAT IS NOT THERE
   server said:
   | Error executing tool read_doc
   (the server's own log is in server.log)
from mcp.server.mcpserver.exceptions import ToolError
    if not found["files"]:
        raise ToolError(
            f"There is no draft called {name} in your folder.")
5. ASK FOR A DRAFT THAT IS NOT THERE
   server said:
   | Error executing tool read_doc: There is no draft called
   | not-here.md in your folder.
   (the server's own log is in server.log)
python3 verify_drive_access.py key.json YOUR_FOLDER_ID
3. CAN I CREATE A NEW FILE?
   NO. HTTP 403, storageQuotaExceeded
   Google says: Service Accounts do not have storage quota.
claude mcp add scribe \
  -e SCRIBE_FOLDER_ID="paste your folder id here" \
  -e SCRIBE_KEY="/Users/you/scribe/key.json" \
  -- /Users/you/scribe/.venv/bin/python \
  /Users/you/scribe/scribe_server.py

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

Stop taking its word for it

Your server says it changed the document. Today we stop taking its word for it.

Hello, and welcome to lesson 13 of the MCP Masterclass. Last lesson you built Scribe, with a tool that reads and a tool that edits. Today we prove that it works, and then we try to break it. And we start with our map, as always.

9 lit boxes, and no hole. Nothing new lights up today, because today we test what is already there.

Six tests, one fails

Well, last lesson ended with Claude telling you the typo was fixed. And I believe Claude.

But a program that says done has only told you what it meant to do. I want to see what it actually did.

So we run 6 tests today. And I will tell you now that 1 of them fails. That failure is the one I most want you to see.

Test 1: look in Drive

So let us start with test number 1, which needs no code at all. Go and look.

Open Google Drive in your browser, and open your draft.

On screen: draft.md open in Google Drive, with the typo gone. Then the file details panel, showing the service account as the last one to change the file.

The typo is gone, and that is the real file in your real Drive.

Now open the details of that file. Drive records who made the last change. And the name on it is your robot user from lesson 4.

So you did not change that file, and Claude did not change it either. Scribe changed it, with the key you gave it.

Test 2: a proof you can rerun

Test number 2. The same proof, but one you can run as often as you like.

Your module 2 checkpoint has a script called prove_it.py. Run it from your scribe folder.

uv run prove_it.py

Or with pip.

python3 prove_it.py

And here is the first part of what it prints.

1. READ draft.md FROM DRIVE
   | # My first draft
   |
   | This is a test. Ths line has a typo in it.

2. FIX THE TYPO
   server said:
   | Changed 1 spot(s) in draft.md.

3. READ IT BACK FROM DRIVE
   | # My first draft
   |
   | This is a test. This line has a typo in it.

Let us read that together.

First it reads your draft from Drive, and the typo is there. Then it asks your edit tool to fix it. Then it reads the draft from Drive a second time.

That second read is the whole point. The script does not trust what the tool said, so it goes back to Drive and looks.

And you may have noticed something odd. We fixed that typo last lesson, so why is it back?

Because the script puts it back before it starts. I built it that way on purpose. You can run this proof 100 times, and it always has something to fix.

Tests 3 and 4: bad inputs

Now we start changing the inputs. And I change them on purpose, because a tool that only works on a good day is not finished.

Test number 3. We ask for words that are not in the draft.

4. ASK FOR WORDS THAT ARE NOT IN THE DRAFT
   server said:
   | That text is not in draft.md. Nothing changed.

The tool says the text is not there, and it says nothing was changed. Then the script reads the draft again, and the draft is the same.

That is an honest tool. It did nothing, and it told us it did nothing.

Test number 4. We ask for a draft that does not exist.

5. ASK FOR A DRAFT THAT IS NOT THERE
   server said:
   | Error executing tool read_doc
   (the server's own log is in server.log)

And this is the one that fails.

Look at what came back. It names the tool, and it tells us nothing else.

Now think back to last lesson. We wrote a plain sentence for exactly this case. There is no draft called that in your folder.

So where did our sentence go?

Why the error went quiet

This one is easy to miss, so let me save you the time. The MCP package hid it, and it hid it on purpose.

When your code crashes, the crash message can carry things you never meant to share. It can hold a path on your disk. It can even hold a piece of a key.

So the package plays it safe. It treats every surprise as a crash. It shows Claude the tool name only, and it keeps the rest in its own log.

That is a good rule. But our missing draft was no surprise, because we saw it coming, and we only have to say so.

The two small changes

It takes 2 small changes. First, one more import at the top of your file.

from mcp.server.mcpserver.exceptions import ToolError

Then go to the first helper, and change 1 word.

    if not found["files"]:
        raise ToolError(
            f"There is no draft called {name} in your folder.")

A ToolError is nothing but a failure you saw coming. The package passes its words on to Claude, exactly as you wrote them.

Save the file, and run the proof again.

5. ASK FOR A DRAFT THAT IS NOT THERE
   server said:
   | Error executing tool read_doc: There is no draft called
   | not-here.md in your folder.
   (the server's own log is in server.log)

And there is our sentence.

Now, why does this matter so much?

Because Claude reads that message. With the first one, Claude can only tell you that something went wrong. With the second one, Claude can ask you for the correct name.

So an error message is a message to your AI. Write it the way you wrote your docstring, in plain words, for a colleague.

And notice that I left that failure in the lesson. I could have handed you the finished code last time, and you would never have seen it. But then you would not know what to do when your own tool goes quiet.

One more thing. You changed your server file, so Claude Desktop is still running the old one. Quit it properly, and open it again.

Test 5: Scribe cannot make a file

Test number 5. We test the thing Scribe must never do, which is to make a new file.

Run the setup check from your module 1 checkpoint again.

python3 verify_drive_access.py key.json YOUR_FOLDER_ID

Look at part 3 of what it prints.

3. CAN I CREATE A NEW FILE?
   NO. HTTP 403, storageQuotaExceeded
   Google says: Service Accounts do not have storage quota.

I told you about this limit in lesson 4. Now you have watched Google say it.

Your robot user owns no storage space, so Google refuses. And Scribe offers no tool that makes a file, so Claude has nothing to reach for.

I want you to remember that refusal, because in module 3 we build a guard. Part of its job is turning an error like this one into a plain sentence.

Test 6: a second app

And test number 6, which is my favourite. We open a second app.

Add Scribe to the second app you picked in lesson 6. In Claude Code it is one command.

claude mcp add scribe \
  -e SCRIBE_FOLDER_ID="paste your folder id here" \
  -e SCRIBE_KEY="/Users/you/scribe/key.json" \
  -- /Users/you/scribe/.venv/bin/python \
  /Users/you/scribe/scribe_server.py

Every other app takes the same few lines of settings that Claude Desktop took.

Now ask that second app to fix a typo in your draft.

On screen: a second app, Claude Code, calls edit_doc on the same Scribe server and fixes the typo in draft.md.

It uses the same tool, and the same document changes.

And if you have only Claude Desktop, watch mine and count with me. The arithmetic still lands.

So what did the second app cost you? You wrote 1 server, and 2 apps are using it. You wrote no glue for the second app, and you will write none for the third.

That is M+N from lesson 6. But this time the server in the middle is yours.

What we proved

So let us count what we proved today.

The real document changes, and Drive itself names Scribe as the one who changed it. The proof runs as often as you like. Missing words change nothing. A missing draft now gets a plain sentence. Scribe cannot make a file. And a second app uses your server with no new code.

That is 6 tests. One of them failed, and that one taught us the most.

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

Still 9 lit boxes. Nothing new lit up today, but every box you lit last lesson is now proven.

Next lesson we will let Claude see the whole folder, and we will save your editing job.

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