The Inspector's looking pretty complete. Tools, resources, prompts — all three tabs have something in them. By every measure we set up back in part two, this is a complete working MCP server.
Now we'll connect it to another MCP server: the Applitools Eyes MCP.
When people hear "multi-server agentic workflow," they picture our server contacting the Eyes server directly. That's not actually how it works, and it's worth getting into, because the wrong mental model here will cost you some serious debugging time later.
MCP servers don't actually talk to each other. There's no server-to-server channel in the protocol at all. Every connection in MCP runs through a client, and every client lives inside of a host. So when our workbook tools server and the Applitools Eyes server both need to participate in one workflow, the thing doing the connecting is the host. It's the AI agent itself running two client connections side by side, one to each server.
Think about what that means for the agent's job. It calls generate_workbook on our server. It gets back a file path. Nothing about that result crosses over to the Eyes server automatically. The agent has to read the file path out of that response and then hand it as plain text into whatever it calls next. The agent is doing the wiring. Our server doesn't know that Eyes exists. Eyes doesn't know that we exist.
And that separation is the whole point. It's what lets you swap either server out without touching the other — which puts a real design requirement onto us. If the agent is going to carry our output into a second tool call on a completely different server, that output had better be something the agent can actually use.
This is the token efficiency conversation from part five, but now it has a second purpose behind it. A file path is portable. A wall of cell contents is not. We already built generate_workbook to return exactly that — the file path, sheet count, row count, et cetera. And it turns out that wasn't just about staying lean inside of one conversation. It was about being a good citizen in somebody else's workflow — one that we hadn't even built yet when we wrote it.
Let's bring in that second server. To do that, we open up mcp.json. Just like we declared this server's block with our first MCP server inside, at the end of that we're going to paste in our second MCP server. This one is the Applitools Eyes MCP.
In addition, we're also going to add a third MCP server: the Playwright MCP server offered by Microsoft. We're going to have the Playwright MCP server create the scaffolding for a test case that will run the test that the Applitools Eyes MCP is going to validate. We're going to have it automate the workbook viewer web app that we created, to validate that we can upload a workbook, view it, and verify that it looks the same between different runs with the same seed.
All of that using our workbook tools, Playwright, and the Applitools Eyes MCP.
To get it working, you're going to have to add your own Applitools API key into this field right here. And if you're curious about using Playwright with MCP for testing, there's more about that in a different Test Automation University course.
Here it is. Here is the full loop that we've been working towards since the very beginning. It's a live demo, so I don't know quite what's going to happen, but I'm going to paste in the prompt and we're going to follow along.
As expected, we want to use the Applitools Eyes MCP, the Playwright MCP, and the workbook generator MCP server to create a test. It needs to:
Afterwards, I want to run that test again with the same spreadsheet seed to verify that the same workbook was made, and have Eyes verify that it displays the same way.
If you haven't already seen it, this is the workbook viewer web app that we talked about in the previous sections. You just click to upload and then it should display the workbook. Pretty straightforward.
So while it's thinking — it's been calling tools like the Applitools Eyes MCP's verify-API-key, basically authenticating, checking to make sure that we can find the API key somewhere. It's calling the Applitools Eyes MCP tool "Eyes setup project," which is explaining how to create the project that it needs.
It's then made a to-do list. This is very critical for these kinds of workflows — it creates a checklist of things to do to accomplish the goal you've given it. In this case, it's trying to scaffold a Playwright project and Eyes. It's going to run everything to verify that Eyes is ready, write that test, run that test, regenerate and run test number two, and then verify to make sure that the Eyes results are the same. This is the essence of what's happening here.
Let's see how it's doing. It already found browsers as it's setting up this Playwright JS project. It's ensuring Chromium's installed, ensuring Applitools Eyes is installed. It's running Eyes setup.
And then it changes its mind — it wanted to use TypeScript. Interesting. So it looks like it checked the configuration information available and realized that Eyes expects it to be in TypeScript, not JavaScript.
There's a lot of advantage here in using MCP servers, because they can provide context to the tool. Playwright might say "do it in JavaScript," but the Eyes MCP says "do this in TypeScript." So the agent can look at those two and say, "Oh, okay, I understand what you want. I can provide that," and then do the handshake.
Setup has succeeded. It's created a config file. It's pasted my API key in plain text — that's wonderful. It's bumped the global timeout as it's going along.
There's a visual test. It's opened up, using the Playwright tool "browser navigate," a new browser. The Playwright "browser snapshot" tool takes a snapshot of the backend of this webpage so it can filter out IDs and other selectors, so that it's able to find elements and generate a test case out of it.
Now that it's figured that out, it calls our workbook tools generate_workbook function to create a workbook. It's going to try to click on "choose a file" like we said in our workflow. And then it says, "Oh nope, that's not right. I need to do something else." It got the error out of it and ran a click.
So now this is where it starts to investigate. It looks like it got a file-access-denied, and then it thought through it and figured it out. You can see it working through and processing all of this.
Part of these kinds of workflows, especially using MCP servers, is that it has to try and fail. But the value of this is that instead of creating a whole test case, setting it up, running it, then waiting for a failure, coming back, making a change, and running it again, it's able to do all of this live using Playwright. So instead of waiting through that whole round-trip process, it can try that function directly, see it failed, try something else, keep doing that to get the correct result, and then save that back and say, "Ah, I know how this works," for the actual test case.
Let's see where it's at now. It looks like it got that test case down. So it removed some functions here, and it ran the test case.
What does that test case look like? It's in tests/manifest-viewer. It goes to the page, validates what the page looks like, uses that file chooser to upload the workbook path we generated, verifies that it uploaded, and then verifies using Eyes to check what it looks like.
Let's see what's happening back over here. Test one passed. It uses generate_workbook, runs test two. Both runs passed. Excellent. And here's our summary.
Run two passed, confirming Eyes compared it against run one and found it visually identical — which is what we expect from a reproducible, seeded workbook.
Here's the summary. It set up the Applitools Eyes and Playwright TypeScript project at this location using our existing API key. It fixed some configuration issue it came across, navigated to the location, did the workflow, generated the Excel worksheet via the tool, passed it along, regenerated it, and ran it again.
And voila. Off on the side, I can pull up the Applitools Eyes dashboard to go in and view what it actually uploaded. Here's test run number one. There's what that looked like. And then on this test here, I can validate, and they all looked the same.
So there you have it. We were able to use the Applitools Eyes and Playwright MCPs with our own custom MCP server to generate a workbook, upload it, view it, and validate it. Again, I didn't have to do anything here. I just sat and talked for a little while. The MCP servers did all of the work and had all of the context to set up and create the project, create the test case, use the Eyes MCP tool, and use our tool to automate this all while I watched. Incredible stuff.
Sometimes as computer scientists we're so preoccupied with whether or not we could, we don't stop to ask whether or not we should. MCP is cool. I genuinely enjoy using it in my personal projects and at work — but it's not always the best solution.
Reach for MCP when:
Skip MCP when a direct function call or a simple API integration already does the job. If your app already has a command line interface, that might be a faster way to integrate AI into your testing workflow. As fun as it is, not everything needs a protocol and a server process sitting behind it. If you're the only consumer, if the data isn't shared, if there's only one process that will ever call this thing, MCP might be overkill.
Bring this back to your team as a genuinely practical checklist:
If not, you're probably better off with something a little bit simpler.
Let's pause for a second and take stock of what we built here, because the whole is greater than the sum of its parts.
We started with two existing Java projects and one problem that neither of them solved on its own: someone still had to tell the generator what to make.
Instead of making a whole new project, we added an MCP server directly into the workbook generator. We gave it three tools so the agent could generate, list, and clear workbooks on request instead of someone running a script by hand. We gave it resources so the model would stop guessing about the shape of a valid request and start reading the actual schema. We gave it a prompt so a user could kick off a whole generation flow with two plain-language arguments instead of hoping the model would pick the right tool on its own. And today we connected a second server we didn't write a single line of, and let an agent orchestrate both of them into one workflow: generate the data, render it, and check that it looks right.
That is the complete shape of an MCP server, start to finish, in Java. Tools, resources, prompts, and the multi-server orchestration that makes all three of those worth building in the first place.
Take a moment to celebrate.
When I first started with MCP, I was struggling to understand how it all worked. I had to watch a ton of tutorials to make any sense of it, and I was intimidated by the complexity of AI and frameworks. Ultimately, it was a lot easier than I expected. The key was just getting started.
You already know more about getting this properly done than most of what's out there. You know the difference between a tool-level error and a protocol-level error. You know a schema resource beats a longer tool description. And you know how to guide a vague user prompt into an effective workflow.
You ready? So get out there. Go build something.