Intro0:00
I know it's one minute ahead, but these 20-minute sessions are really short, so I'm going to get started. So, title of my talk: "You all have seen"—because you're all here—which is, why the heck aren't any agents supporting MCP Tasks?
If you don't know what tasks are, don't worry, you will know in just a moment. But the first answer to that question is, well, because they're smart. The people who are building those clients are smart. What I mean by that is that the MCP Tasks specification that came out in November was marked as experimental.
And so, well, you might shrug and say, well, gosh, those clients and servers, they're all supporting a whole bunch of experimental things. Why not MCP Tasks? Well, again, you'll see the answer to that as we move forward. The next answer to that question is, well, they're pretty involved.
There's a lot of complexity in here, and that's what I want to do over the next 20 minutes: teach you some of that complexity. Quick intro: my name is Cornelia Davis. I'm a technologist at Temporal. We're distributed systems stuff.
I have a long history in distributed systems, did a whole bunch of stuff in the microservices era, including Cloud Foundry, Kubernetes, GitOps, Weaveworks, all of that stuff, and I even wrote a book about that. That's who I am.
Today's agenda in the next 19 minutes is that, rather than just talking about things in the abstract, I'm going to ground us in a very concrete example. So I'm going to give you the lay of the land of that concrete example.
Use Case1:33
Then I'm going to give you an overview of MCP Tasks. Quick question: who here wants to do things with tasks? Async MCP tools. Okay. So I'm going to give you a little bit of an overview. Then we're going to talk about MCP Tasks V1.
That's the spec that came out in November. And spoiler alert, there's a new one coming out in July. So that comment that I made about them being smart about not implementing it yet, well, there's some pretty radical changes.
So I'm going to show you what's happening with V2, and I actually have some live demos to show all this working. And then we'll have some takeaways at the end. So the use case that we're going to talk about here is a simple purchase order use case.
So the use case is you're going to get in a purchase order, and then it's going to go through a number of steps. It's going to record the fact that the goods were received, and then it's going to do, in parallel, it's going to do some back office stuff: updating inventory, sending out notifications, and then in parallel to that, it's going to pay some invoices.
Now, the invoicing is going to happen via an MCP tool. Now, that MCP tool has itself a number of steps. So it's going to validate against an ERP, then it's going to have a little human in the loop to request approval, maybe.
Then it's going to reconcile against the ERP again, do a little bit more human in the loop, and so on. So you can see that on theright-hand side, that MCP server, that's going to be—it's a tool that's going to be doing the invoice processing for us.
It is long-running. It's not going to work in a request-response style. And that's what MCP Tasks are all about. And what we're going to do—and today's talk is not about Temporal—but really what I did here was just showed you a couple of snippets of the code.
And yes, I will be sharing all the code for what I'm showing today. A couple of snippets here. And the real point that I want you to look at is that reject or approve. That is showing you that there is a mechanism for signaling into a long-running process.
And that's really the point. And that's what we need, is that this is all about asynchronous. So you understand what MCP Tasks are now? MCP Tasks are allowing you to have an MCP tool that you can invoke, and then it is long-running in the background, and then eventually you can get back some response.
So let's talk about that MCP Tasks overview. This is a very simple sequence diagram. It's exactly what you all would expect when I tell you that MCP Tasks are long-running tasks. You're going to invoke a tool, and instead of getting back a response, you're going to get a handle.
And you can interact with that handle. Right? Obvious. Right? This isn't rocket science. Looks easy enough,right? Well, it turns out that if you actually want this to work over long horizons, it gets a little bit more complicated than that.
Failure Modes4:37
So what are some of those complications? Well, you can have all sorts of the longer something runs, the more likely there's going to be some kind of infrastructure blip that's going to cause a problem in that long-running task.
So you could have network blips. You could have network challenges. You could have humans that you're waiting for, they're in a loop part, and they go away on vacation, like I'm about to, yay, day after tomorrow. Or processes can crash.
So your agent can go down. The agent that's processing the purchase order can go down. Or your MCP server can go down as well. So all of those problems you need to deal with. And those are the things that make it a little bit more difficult.
Now, in addition to what I've told you about MCP Tasks so far, that you're going to get back a handle that you can interact with, by the specification, those MCP Tasks can't disappear. This is verbiage from the spec itself that says, once you've launched a task, it has to be durable.
What that means is, all of these things that I just showed you on the previous screen, humans going away on vacation, servers going down, clients going down, connections disconnecting. The task needs to survive that, and you need to be able to interact with that task when the infrastructure comes back.
And I'm going to show you how all of that is done. Now, there's elements, there's server-side elements that talk about how you make the server-side durable. And I did a talk at the MCP Dev Summit in March, and this is the QR code that will take you to that YouTube video.
And that's where I go into a lot of detail about the server-side and what you need to do with the server-side. Today, as you saw, is an extension of that work where I'm talking about the client side. So without further ado, let me go into a demo.
For those of you who know me, I'm always doing demos. So what we have here is we have a dashboard. I am not doing this through a chat interface because, frankly, it's more efficient for me to click a couple of buttons here to show you this rather than trying to type things in.
Dashboard Demo7:01
So I have a user interface here that's showing you the number of purchase orders that have been submitted. I'm going to submit a simple purchase order, so that's just a button that is kicking things off. And in a moment, if the demo gods are with me, it says submitted.
We should see the purchase order pop up here, and it should show some ah, here's why it's not working. Because I haven't started my servers. So remember I said it has to work even when the servers aren't running?
I forgot to show you here that what I'm doing in these two windows is in the upper window, I'm starting the backend. This is the MCP server. And in the lower window, I am starting the MCP client. And you'll see what that client is in a moment.
You can see in the splash screen there that I am using Fast MCP on the client side. So let's go back here and notice that even though I submitted that, even though my servers weren't running, that submission did go through.
So it's captured that. So what you can see here, and you didn't see it cycle through, but on the farright-hand side, the invoice task initially showed you that it was submitted, then it showed you that it was working, and now it's asking for input required.
I can come over here. Let me show you what's going on at the backend and at the frontend. What I have here are some dashboards that are showing those running processes. On theright-hand side, you have the backend. That's where the invoice processing is, and you can see the name here.
Let me increase the font size there a little bit. So you can see that this is running the invoice, and on the left-hand side, you can see that it's running the PO. I'll explain that task tracker thing in just a moment.
So if we go into the invoice, we can see that it has the process that we talked about earlier. It validated against the ERP, and now it's waiting for human input. It's waiting for that approval. Over on the PO side, we can also see the process that I showed you earlier, which is to say, let's go back here.
It is. So, ah, yes. So it did that record, it recorded that the goods were received. Then in parallel, it's invoking the invoice processor, MCP Task. And notice that there's this line item here that says task tracker workflow.
Yes, indeed. That is my MCP client implementation. Remember I said nobody's implemented this on the client side? Well, I created my own implementation here. But in parallel with doing the invoice processing, we also had this back office stuff that was happening.
So if I come back over here and I click on input required, I can approve this. And I'll hit submit. And we come over here, and you'll see in just a moment that the signal is going to come into the backend.
I need to refresh. Oh, there it goes. So the approval came into the backend, and now the backend is going ahead with its additional process, paying the invoice. And you'll see a number of line items there. There's some
retries that have been programmed in here, but you can see here that it took a few tries before the ERP went through. We paid the line item, and now you can see that the task completed. So everything's completed.
If I go back to the dashboard that you saw at the top, you can see that all of those processes completed. Okay? So that's the basic stuff. And I can run that again, but I already gave you, inadvertently gave you the example of the infrastructure was down.
I could have killed that server halfway through, and it would have continued exactly as you saw here. Okay? So you saw it at the very beginning. Allright. Let's go back to slides. So that's the first demo. So let's talk about
Tasks Version 1. So in Tasks Version 1, there were a number of tool semantics. And again, I go over these tool semantics in a lot more detail in that MCP Dev Summit talk. But there's one really interesting thing that I want to draw your attention to, which is that tasks come with one of the things that the specification defines is a life cycle for tasks.
V1 Tasks11:17
And that's what you see here on the screen. It has working. It can go into an input required. From input required, it can go back to working, and then eventually it'll complete or be canceled or fail. So that's one of the things that's super interesting about the task specification, is that it's about the life cycle of the task.
There's a whole bunch of other semantics there as well around obtaining inputs and delivering results. And I'm going to go through this fairly quickly because, I already mentioned, some of this is going away. So this is what the tool semantics were before the task semantics.
Notice that tools/call is exactly the same. There's some metadata that you pass in when you want it to be async. And then there's task_get, cancel_list, as well as task_result. And so the top four are request response in style.
The bottom one keeps a connection open. It keeps a connection alive. And the sequence diagram that you can see here is kind of the basic stuff. Now, there's two hiccups with this, two major challenges with this particular version of the protocol.
The first one isright here, task_list. This is a stateful protocol. So what that means is that the, remember I said that the server was responsible for durability? Well, this particular endpoint allows me to go to the server and say, "Hey, what tasks do you have?"
So if I have had, if the client has gone away, if the user took too long to respond, if my network dropped out and I had to reconnect, I can use this task_list to go back to the server and say, "What have you got?"
And then you can continue on with that. That works fine if you have one task or two tasks, or maybe it even works if you have 10 tasks. But what happens if you've got a whole slew of agents out there and you've got a million tasks at the backend?
Spoiler alert, there is no filter on that endpoint. So you would have to go through a million tasks to find the one that you're looking for that you want to interact with. This is going away. You'll see in just a moment.
But that's one of the challenges. Just because you can doesn't mean you should. The other one is the task_result, because that is where we were tunneling the input required. So in the case of task_result, this sequence diagram is really simple.
It doesn't have the interactivity. What we have, as soon as you do task, as soon as you have input required, is the top and bottom are just fine, but this middle section has this weird protocol where you open a long-running connection, and then the server elicits a response from the client.
That gets super tricky. And I'm running short on time, so I'm not actually going to show you this demo. Happy to show it to you. I'll be around all day tomorrow too, so I can happy to show it to you.
But I want to show you instead, here's basically the architecture of what you need to build on the server side. This is, notice that this is using Fast MCP. So Fast MCP already has support for server-side and some client-side stuff as well.
But the interesting thing is, notice that little box on the left-hand side, on the lower part where it says MCP Client Protocol Handler. That protocol handler, with the ugliness that I just showed you around results, actually looks like this.
And I can show this to you running, and it has all sorts of complexity in it. I got to have the long-running connection. Well, what happens if my connection dies in the middle of that? How do I pick up where I left off when I come back?
You'll see that a big part of what the task specification does is it talks about durability. So back to the question of why the heck aren't there any clients that are supporting this protocol? Yeah. That's why. Super involved.
It's still involved with V2, but it gets better. So let me tell you about that. So in May, Angie Jones, who's responsible for developer experience at the Agentic AI Foundation, which is where MCP now lives, posted this blog.
V2 Overhaul16:01
And one of the things that made me jump up and celebrate a little bit is that the protocol is going stateless. So as somebody who's been working in the microservices world for a long time, stateful protocols are the absolute worst thing in large-scale distributed systems.
So the protocol is going stateless. It's also doing a number of other things. So the first bullet is a stateless core. The second bullet is interesting because they also have structured MCP so that there's a core and there's extensions.
If some of you were in the room for the previous two talks, they talked about MCP UI. Two talks ago, they mentioned extension. Well, that's what's happening here in the V2 MCP protocol, is that they have extensions. And tasks have become an extension.
So let me tell you a little bit about how tasks changed from V1 to V2, and I do want to give you one more demo. So on the left-hand side, you can see what the protocol was before. These are the RPC requests that you were doing over the wire.
On theright-hand side, you can see a couple of things. Task_list has gone away. Good. Wasn't particularly useful anyway, especially at large scale. And instead of having this input required going over a long-running session, you now have an endpoint that allows you from the client side to say, "Here's an update."
So if you remember a while ago, I showed you that screenshot that said Temporal has this notion of a signal. That's effectively what this is. It's a way of signaling into this long-running task. The task_result stays, but it changes because it no longer has this long session-based protocol.
But I put the picture on theright-hand side here to emphasize the fact that the life cycle management of these tasks is unchanged. That's actually sound. Now, I go into this a lot into more detail in the talk that I keep referring to.
On the server side, in invoice processing, I have my own state machine that the invoice is going through. And so part of what you're doing when you implement these server-side tasks is you're mapping from the life cycle states of the task over to the domain state machine that's running the application, the MCP server in the backend or the tool.
So list, again, goes away. Now, remember I said that the MCP Tasks specification has durability all over it? With this change, given that lists are gone, you now are required on the client side. Well, kind of required. There's a little parenthetical remark here.
The specright now says that clients should persist task IDs. But it also points out that if you don't persist task IDs, there is no way to get it back. So I'm not quite sure why this doesn't have an all-caps MUST.
The other thing that I want to point out is, and I already mentioned it, is that you're going to have potentially a lot of agents that are processing POs or a lot of agents that are doing a lot of things.
And so having multiple things running, I think, is really crucial as well. So with that, I'm going to go to the second demo, and I'm going to go back to my purchase order here. So what I'm going to do now is I'm going to submit a number of things.
V1 Protocol Demo19:41
And I'm actually still demoing here because I have 13 seconds left. I'm not going to switch over to my V2. You'll see that from the high level, it actually looks exactly the same. I am going to show you what the client server protocol looks like in the V1 case.
It's really quite ugly. But you'll notice here that we have, I've submitted a bunch of different ones. I can tell you with the V1 protocol, the reference implementation, if you had input required on multiple, even though you can see that there's many of them in flight, on the client side, there were FIFO.
So you could only respond to the first one, and part of the protocol that I implemented was to get around that gap. So let's come over here. We can refresh both of these, and you can see that there's going to be a bunch of POs in flight.
And now I want to show you the task tracker. So if we go into the task tracker, that's the MCP client. And now let me just expand this so we can see it in a little bit more detail.
What you can see here is that remember that that protocol, I showed you that big long sequence diagram. There's a lot of steps involved in that. And what I've done here is I've implemented it as a workflow. And you can see here that there's some elicitation handling that's going from the server side back to the client.
Scaling & Future21:27
So I won't go into any more details because I'm literally out of time now, but I want to share two more things. And that is, so going from V1, remember this ugly picture, to V2 in the client server protocol, much, much cleaner, much easier to implement.
So speaking of implementing, here's a summary of all the things that you need to do if you want to implement tasks. Still relatively involved. Here's a picture. I'm going to make these slides available in the Git repo that I'm about to show you.
And here's the Git repo that I'm about to show you. And while you're getting that screenshot, I'm going to tell you about two pieces of work that I'm continuing with. Number one, even though this is better, it still doesn't scale to the millions.
Why? Because if I've got a million tasks running, I've got a million clients that are doing gets against each and every one of those tasks. That does not scale. There is a part of the MCP Task Specification that is a notifications protocol, which I haven't gotten far enough yet, but it's showing promise, which is going to allow you to, instead of having a million clients
pulling their tasks, it's going to have a single endpoint where they can say, "Has something changed?" And if it has, tell me which one, and now I'll go pull that task. So it's definitely from a scale perspective. The other thing that we're doing is, in the very near future, in the next month or two, we're going to have an implementation of all of this where it's going to be much simpler for you.
My goal is to actually implement it in Fast MCP so that you can use the same framework that you're using probably for your MCP servers today. So without further ado, that is it. Thank you to the next speaker for letting me go a few minutes long, and I'll be around.
I'll step out. If you have any questions, find me in the hallway.





