If you've been following the MCP Workshop series, you're probably familiar with
the Epic Me Journaling app we've been building. Starting from simple tools that
add numbers together, we've evolved it into a full-featured journaling MCP
server through the MCP Fundamentals workshop.
When you transition to MCP-UI, the next workshop in the series, you might expect
everything to change. After all, we're moving from a standard I/O server to HTTP
streaming with Cloudflare Workers. But here's the surprising truth: most of
the MCP-focused code doesn't change at all.
The key insight is that MCP concepts are separate from the infrastructure that
hosts them. Whether you're running on a standard I/O server, Cloudflare Workers,
Netlify Functions, or Express, the MCP protocol and your server logic remain
fundamentally the same.
This is why there are no exercises to transition between these approaches in the
workshop. The infrastructure changes are handled for you because they're not
central to learning MCP concepts.
The most significant change is moving from a local SQLite database to a separate
application that holds all the data. Instead of having a database file in your
MCP server, you now have:
A separate Epic Me app running on port 7787
HTTP calls to communicate with that app
A database client that abstracts these calls
This mirrors real-world scenarios where you have an existing application and
want to build an MCP server that communicates with it.
// Before: Direct database access
constentries= awaitdb.getEntries()
// After: HTTP client (same interface)
constentries= awaitdb.getEntries()
The interface remains the same, but the implementation now makes HTTP calls to
your separate application.
MCP is platform-agnostic: The protocol works the same regardless of
hosting
Infrastructure changes are minimal: Focus on MCP concepts, not platform
details
Real-world architecture: Separate applications communicating via HTTP
Consistent interfaces: Your MCP code can remain largely unchanged
The transition from MCP Fundamentals to MCP-UI is less about learning new MCP
concepts and more about understanding how MCP fits into real-world application
architectures. The core skills you've developed remain valuable and transferable
across different hosting platforms.
Remember: MCP is about the protocol and the tools you build, not the
infrastructure that hosts them. Focus on the concepts, and the platform details
will fall into place.
Share
Hey, so if you've been going through the MCP Workshop series, then you might have gotten used to the app that we're building through MCP, the Epic Me Journaling app. We started out here in the MCP Fundamentals. We start with some really simple tools with adding numbers together and stuff. And then that gets upgraded to a full journaling MCP server. And we continue with that through MCP Fundamentals, and it just continues to evolve and adding more and more features.
In MCPUI, which is the next workshop in the series. We stick with that as the concept. So we're still doing the Epic Me journaling app, but we kind of changed the way that it's structured. Both of these workshops use a standard I-O server, But when we get over to MCPUI, we're using HTTP streaming. And so the setup is a little bit different, and I wanted to show you what some of those differences are.
The good thing is that most of the MCP-focused stuff doesn't change at all, which is why we don't actually have any exercises to take us from the standard I.O. Over to the streaming. Instead, I just kind of do that for you because it's not actually all that relevant as far as the MCP side of things is concerned. And even the way that we do it with MCPUI with Cloudflare is going to be a little different than if you do it with another hosting provider or with an express server or whatever. And So, because of that, it's a little like it's parallel to MCP.
We're not going to have any exercises about that. But I'll take you through the diff so you get an idea of what this actually looks like. So this is the subscriptions version of the workshop. So it's this right here, the version of the workshop at the solution of the very last exercise, and we're taking that as a diff to the very first exercise, the problem of the first exercise of the MCPUI workshop. So, that's what we're comparing here.
You'll notice we delete a bunch of things, or we move a lot of things. So, before we had, of course, a SQLite database. That is now moved completely, and instead we have, I think it's 7787, or something like that, yeah. We have this new app that's running right alongside the rest of your workshop app experience and so when you start the workshop app this app gets started automatically and it holds all of the data. So we've got these entries, we've got Kelly, and this app is really cool because you can come over here and click Reset Database and KB Store, and now We've got five entries.
And so you can always just come over to this app and get your data exactly where it needs to be. You don't need to worry about seeding the database or anything like that. And all of your exercises, everything is going to be pointing to this app. So this is actually, I think, what most of you are going to experience as you apply MCP in the workplace, is you've got an existing application and you want to build an MCP server that communicates to that application. So that's why I structured it like this.
Here's our existing application, and now we're going to make an MCP server that talks to that application. And so, to that end, we get rid of the SQLite database from our MCP server, because all of that lives in that separate app, in the Epic Me app. We also get rid of this font that was for the FFmpeg videos. We remove that tool entirely. That is, yeah, we no longer use that.
The package.json changes as well because we are now using Wrangler for our server and all of that. Let me bump this up a little bit. And Wrangler is the CLI for Cloudflare for running things locally and even deploying onto Cloudflare. Most things don't really change. It looks like the SDK, I updated that.
So I should go back and update that in the advanced thing. But nothing really changes with the SDK. We add agents as a dependency. This is coming from Cloudflare, and this is how you use the SDK for MCP with Cloudflare's technology. And yeah, for the most part, like, not significant changes there.
We get rid of everything that's in the database and instead all of that has been moved over to the Epic Me app and we're going to be making HTTP calls to make database calls and stuff like that. And let's see, yeah, so The resources actually changes significantly enough that get things we just deleted it, but we actually move it and we change just a little bit. There's not really a lot that's changed as far as the resources are concerned. The reason probably that it thought we changed a lot is because, actually, I'm really not sure why. We don't change a ton.
We do remove the video resource, but we keep the entry resource. We keep the tag resource. We don't really change a lot about resources. We remove subscriptions entirely. We also remove video entirely.
And part of the reason for that is it's just an extra thing that I would have to add to the Epic Me server to support database subscriptions and stuff. So I don't bother doing that. Whatever app you're building, they're going to have data subscriptions or they're not. And that is kind of a parallel topic to MCP, and so we're leaving that out. So I delete that.
Also, the video stuff, we are not going to be doing that. I'd have to do a whole separate thing on Cloudflare to make that work. And it's not relevant to your learning of MCP. So we do get rid of some of the tools associated with that. TS config is going to change that.
I don't think it's relevant to you. We now have a worker DBTS file. This is going to be the database client that communicates to the Epic Me app. And so this server address is going to be running alongside your application as you're running it, and we create a new instance of that DB client. This DB variable is effectively the exact same as what we had in the previous workshops.
And so as you've been doing db.getentries and stuff like that, all of those things will be the same. I did, it turns out, I discovered as I was making this video, that I did change a couple of the things that went from getentries to listentries or vice versa or something like that. But For all intents and purposes, it's basically the same, and it's all fully typed, and it's nice. You can dive in to figure out how I made that work. It is kind of hacky, but it works, and it works great.
And at whatever app that you're building, you probably have some mechanism for communicating with your downstream services, for making API calls. So just do whatever that does. Okay, and then our index changes. So this is how you set up a Cloudflare worker. It's just export default, a fetch function that accepts a request, the environment stuff, and execution context.
This is not relevant to MCP specifically. This is just Cloudflare worker stuff. If you're hosting on Netlify or Vercel or wherever else, It's all going to be those specific platform will have their own way of doing this. The point here is that when we make a request to slash MCP, we're going to be using the Epic Me MCP durable object. If you don't know what a durable object is, that is just fine.
You don't have to understand what a durable object is to be able to learn everything you need to know about MCP. Feel free to dive into that topic a little bit later. But yeah, we're going to just leave that as an exercise for you. And then, yeah, we have our Wrangler config, and here you can dive into that if you're curious about what that's all about. But the most important stuff is all of what's inside of the source directory.
So This was the file that had the most number of changes. So we no longer have the database. We now instead have a DB client. We're using the agent's MCP to create our MCP agent. A big part of why I structured things the way I did in the standard I O exercises is because I really like the structure of the CloudFlare MCP API with the durable objects.
And so we structure it in a similar way so that we can just kind of continue with that. And so you'll notice in here, like, we're still initialize prompts, initialize resource, initialize tools. We get rid of the subscription stuff. It's still a class. It has a database.
But here we're going to say that Our database is the DB client. And then we extend the MCP agent. We create our MCP class here. I changed the title for some reason. I don't know why, but all of this stuff is exactly the same.
We no longer need a constructor. We initialize the database as part of the init. Our database is just the instance of our DB client, and so we just set it here as a convenience thing. So anywhere the agent is, you can say agent.db. We've got all the initialization is the same.
We no longer have a main function. We instead export this class, and then that gets wired up by our worker index right here. So not a ton of changes there. Like fundamentally, it's all very, very similar. And then if we look at something like prompts, instead of assigning the prompt to a value so that we can do the update prompts thing, we did that with the list change.
We got rid of database subscriptions and stuff like that. You can still definitely do that in a Cloudflare worker. And so if you want to, feel free to do that. But I removed that to reduce the amount of extra code that's in here that's not entirely relevant. And also, yeah, for some reason, I changed it from list tags to get tags in here.
Don't remember doing that, but I guess I did. And so, hopefully that doesn't throw anybody for a loop. And then with sampling, same sort of thing. Yeah, just that. I probably, I regret doing that now because it would be like, look, nothing changed.
But now it looks like a lot of things changed, but it really didn't change a whole lot. Again, this is very similar. I'm kind of surprised that Git decided that this was such a significant change that it said we deleted one file and added another rather than moving it. And then yeah, tools had probably the most changes, but like again, it's all just, we're no longer assigning these values to anything. We just register the tool.
We don't disable or enable them. That's what Most of this is. A couple of whitespace changes here as well. This is set up for the first exercise of the MCPUI workshop. Yeah, for the most part, all the same.
We did delete the create wrapped video. And yeah. Oh, also, as of this recording, Cloudflare does not support elicitation. And so we just disable it here. There is an issue that's being tracked on that, because the way that elicitation works in the SDK doesn't work in the Cloudflare environment.
So they're working on that, and that will eventually not be a problem. So that's that. That's pretty much all you need to know about the differences between what you've been working on so far in the workshop series, and what you can expect from MCPUI, as well as the auth workshop. Auth workshop does a very similar thing to this, adds a bunch of authentication stuff. MCPUI actually gets relatively complicated as we get further on.
We'll get to this part, where we add in an entire framework for displaying UI. It's a React router. And I take you on a tour of this later in the exercises, but yeah. So there will be yet another slight change to this, and our worker index will have to change to add the React router support and all of that stuff. So you'll be eased into that when we get to that point.
And then when we go to the auth stuff, we actually remove a bunch of that. We remove all the UI stuff just to focus purely on auth, but it's all still Cloudflare sort of thing. So anyway, I just wanted to make this video really quick for you to get yourself familiar with the way that things are and how things change between MCPUI and the other workshops that you've been doing before this. I hope that is helpful to you and I look forward to working with you