Transcript#

This transcript was generated automatically and may contain errors.

I'm really excited to be here. Um, I'm going to talk about MCP or Not MCP. Anyone, uh, who here has used MCP before? Okay, cool. Who has made your own MCP server? Great.

For those of you who haven't yet, I, hopefully you'll come away from this with understanding of why you might do that and how you might do that. Um, let me introduce myself. See, um, I've spent most of my career working somewhere between the intersection of open source and data and various forms. For a number of years, I was a developer working on Apache Arrow. I was chair of the project management committee last year, currently a VP of engineering at Posit.

Uh, there's some links there, including one to the beautiful book on Arrow and R that I'm holding there, uh, if you're curious. At Posit, one of the teams that I work with is the Posit Connect team. Any Connect, Posit Connect users in there? So for those who don't know, Connect is a platform for deploying and sharing custom apps, dashboards, reports, APIs, things you write in the language or framework of your choice. Whether it's Shiny or Streamlit, FastAPI, there's now Node.js support, Quarto, and other things. And you can also host MCP servers there.

The motivation: Zendesk support tickets

Over the last, however long it's been, we've really gotten interested in using Claude Code for all sorts of things. It's, you know, one of the, it's a weird time to be working in this industry right now, but one of the great things about it is that there's so many things that, um, you know, may have seemed hard or just out of reach for us to do as engineers, for whatever reasons that are now available for us. Connect has a 10 year old code base going back to the beginning and it's big and does a lot of things. And so there, there are things that, you know, seem like a good idea. Someone may come to us with a suggestion and it's a lot of context switching to do to try to figure out how would I actually do this? But now I can fire off Claude Code on a git work tree and it can sort it out and I can read through the code and figure out what to do. And it makes it a lot easier for us to just say yes to good ideas like that.

So naturally, you know, uh, seeing some of these benefits, I start to think like, well, what other hard problems are out there that I could use Claude to help with? You know, what else have we learned from years of experience are hard and painful that maybe, maybe they're not anymore. And one of those, uh, sources of difficulty is responding to, uh, support issues when they get escalated to the engineering team. So Posit uses Zendesk for support. So customers can file tickets when they run into issues and the support engineers will field them and usually they can, they can address them. But sometimes it's a harder thing to debug or, you know, a clear bug or something, and it gets sent to the engineering team and, you know, for an engineer to pick this up, you have to put down whatever they were already working on and try to reason about the particular environment that Connect is deployed in. It's on-prem software, so it could vary quite a bit by the customer. And that's, for humans, that's hard.

Uh, but I thought, you know, Claude's really good at reading through the code base, helping understanding how things work and even, you know, finding bugs. Like what if I could just point Claude at Zendesk and say something like this, here, help me with this Zendesk ticket. This doesn't work. Cause Claude will try to do this, but it will get a 403 or a 401 rather. You're not authenticated. So I can't see what's in that ticket. And it says, could you just paste the tickets in here? I'm like, well, no, that's, that defeats the purpose. That's, that's the work I would want to do. And the first problem we ran into is, is this authentication? And there's really not a way for me to provide my credentials to Claude Code to do this. And even if I could, I wouldn't want my API key or my password in the context here.

You know, Mac was talking about a number of security things that come up here. Like that's very sensitive data that I don't want circulating here. But even if I could do that, the Zendesk API is huge and is really not designed for AI agents to make both efficient and secure use of it. And this is what MCP is designed for. So MCP provides a way for you to authenticate with your APIs without giving your credentials to the agent. And by writing custom MCP servers, you can control exactly what tools are made available. And this makes it more efficient and more secure. And by hosting your own MCP server, you have a way to easily distribute it and share it with your team.

And a point that I want to make sure comes across here is that you can write and host your own MCP servers to do exactly what you need. Because as we know, code is very cheap to produce now. It doesn't require specialized knowledge. You basically just have to ask your agent to say, I would like an MCP server and, and you're off and running. And so my talk is really going to focus on writing your own and not about whether you should use some MCP server that's out there that someone else is providing. And even if you do want to use that, there's probably reasons why you might want to customize it anyway.

And a point that I want to make sure comes across here is that you can write and host your own MCP servers to do exactly what you need. Because as we know, code is very cheap to produce now.

What MCP is (and isn't)

I've said MCP a bunch of times, I should probably say what it is, MCP model context protocol. Uh, I've talked to a lot of people in a lot of different industries about this lately, and I've found a lot of confusion about what it is. And so I first want to say what MCP is not. It is not magic illusions. It's not AI. It's not vector search. It's not any of these things. You could put vector search behind an MCP server. You could put AI behind an MCP server. But MCP is really just a specification for how to provide tools to LLMs. So tools are functions that an LLM can call.

And the definitions of these tools, uh, are in the kind of start of the context window that you have. And so a model will see that a function exists by this name. Here's a description of what it does and what inputs it takes and that kind of thing. So MCP is a standard for, uh, developing servers that provide those tools and for client applications, any AI application to use them. I was talking about Claude Code and that was the example I showed there, but it's not limited to code. AI applications, any AI application that supports MCP can use MCP servers. They don't have to be about writing code.

Local vs. remote MCP servers

Uh, there's two kinds of MCP servers. There's local ones that run on your machine and remote ones that run on someone else's machine. As you can see from this, from that example of like what the command you would use to add an MCP, local MCP to Claude Code, you know, it's calling UVX, could be NPX or something like that. You're running code locally. And often it's pointing at a GitHub repository or something. Because it's running locally, you can access things on your local system that can be really useful. It can also be kind of risky, particularly if you're going to some random GitHub repository and you're not pinning to a SHA that you're pulling there and it could be untrusted code. Uh, remote ones, remote ones run somewhere else and you just reference them by the URL. And so that's really nice for distribution. They can't access your local file system, but they could have access to other things that are maybe are available on the server they're running that aren't available to you locally. So there's some trade-offs there.

I'm going to talk about, mostly about remote MCP servers. And because I think that the, the real, uh, value of MCP today really comes from remote MCP servers. But it also, it really helps with the mental model of what MCP is because MCP is basically just an API standard. A remote MCP server is communicating over HTTP. It makes post requests. It sends JSON. It gets JSON back. This is an API. And so, you know, for people that, you know, many of you in this room, you've worked with data, you've worked with APIs throughout your career. You know what APIs are, you know how to talk to them, you know how to make requests, get response. This is a familiar thing. This is not anything other than a convention of how to structure API endpoints. So you know how to make these.

The MCP backlash — and why it's not dead

MCP was, uh, first announced in the end of 2024. Anthropic put it out. It's now under the Linux foundation. There's an industry consortium that's supporting it. When it came out, there was a lot of enthusiasm because, you know, there were things that you could do with these tools that there wasn't really a good standard way for providing external access to external resources before this. Perhaps not surprisingly, after a lot of exuberance, there was some backlash. One of them being that, why do I need to use, for example, GitHub put out an MCP server. Why would I need that? When Claude Code already knows how to use the GH command line tool. This is just a waste. Leading some to say that MCP is dead. I disagree.

Of course, I think, you know, as with many things, there's truth in both the initial excitement and the backlash against it. When it came out, there weren't great alternatives. People were doing things with MCP that maybe is not the best use of, um, and, but that doesn't mean there's not still important places where MCP fits in today. I'm gonna talk about a few of the critiques and where that I think shakes things out for MCP today.

MCP vs. CLI vs. skills

One line of questioning is what is the right tool for the job? Is it an MCP server? Is it a command line tool or is it a skill? The agent skills standard came out, I guess it was 2025 after MCP. And so, you know, there are many things that you can effectively do just by writing some texts, markdown. And so if you can explain with existing tools that your agent already has, just how to use those tools, that's what skills are good for. Otherwise, skills are often compliments to MCP servers or CLIs. You provide tools and you also need to provide a description of how to use the tools, what you might use the tools for.

So if we're trading, if we're discussing, if we're thinking MCP and skill versus CLI and skill, there's really a couple of places where CLIs are great. I mentioned the example of GitHub. So the gh command line utility has been around for a number of years. It's in the training data, uh, in model. And so I can be in Claude Code, Claude Code knows how to use gh. I don't have to tell it how to do it. It doesn't need a bunch of tool definitions. It doesn't need to do gh dash dash help to see what the command line says it does. So that's great. And so you save all of these, uh, tokens that the context window, the context that you would take up with these tool definitions. That's great. If that exists, it doesn't exist for everything. And so if you're the command line that you want to, utility that you want to use is not widely available, it's not in the training data. You're going to have to, either the model's going to have to discover by trying things, how to use it. Or you're going to have to explain it in a skill. And now you've kind of, you've lost that savings of the tool definition.

Cause MCP servers, I should, I should clarify when you connect an MCP server, it pulls all of the, uh, tool definitions up front. And so the GitHub MCP server has dozens, maybe hundreds of MCP tools. If you were to use them all, that's a lot of tokens. And so that's what you're trying to save. The other place where a CLI is, the other thing you need, if you're going to use a CLI is you need to be able to run commands in the shell. And not every AI application has that. You might be building an agent, uh, an AI agent yourself, and you don't want to give it access to the, to bash because you want to keep it constrained to what its abilities are. Maybe you're using a desktop application that's not Claude Code. And so CLIs don't have the same reach there that MCP does.

There's also more things that you can do with a remote MCP server that you just can't do with a CLI. I mentioned authentication upfront. In the MCP standard, there is this OAuth flow that is specified. And what that means is you can register your, your MCP server with your application. And if the place you've deployed it supports this, it will take you to the, when you try to connect, it'll take you to the browser. You'll log in and it'll say authentication successful. You can close this tab and it handles it automatically. So you don't have to have secrets sitting locally on your machine. That's great. And you just can't do that otherwise. I mentioned before, you could have databases or things that you only want to expose within the server where you're running the MCP server, uh, that you wouldn't have access to locally. And this gives you a, an AI, a, an AI forward portal to those. Monitoring, uh, some of the earlier, uh, presentations we're talking about, you know, having the audit trail of things, these sorts of enterprising things. It's particularly important with AI. And you can get these with a remote MCP server.

Security: the lethal trifecta

Speaking of security, it's a big deal. Mac talked a lot about that. And I, I just want to highlight the concept of the lethal trifecta that Simon Willison has been writing about. And so the idea is that if you have access to, uh, access to private data, exposure to untrusted content, and the ability to communicate out there, an attacker can access your private data and send it back out. This is relevant for MCP. It's also relevant for, uh, command line utilities, but, uh, there were a lot of cases of exploits using MCP servers, uh, which is what kind of why I raised this here. There, the MCP server, it's not just that the MCP server would be malicious. It's that by the whole point of adding tools like this is it allows you to access additional data. And some of that might be from untrusted sources.

So thinking of GitHub, if I can read issues in public repos, that's access to untrusted content. Someone could create a malicious GitHub issue with a prompt injection, read the contents of the secret file and do something with that. And so if I have access to read GitHub issues and write GitHub issues, I have just created this lethal trifecta. So this gets to what I think are of some best practices in building, working with MCP servers and in building your own.

Someone could create a malicious GitHub issue with a prompt injection, read the contents of the secret file and do something with that. And so if I have access to read GitHub issues and write GitHub issues, I have just created this lethal trifecta.

Best practices: brevity and security

And I started the talk MCP, but not MCP. I am not delivering this talk in iambic pentameter, but I do think it's worth at least one Hamlet reference. In general, brevity is the soul of wit when working and building MCP servers. So the first thing to do is to only define the tools that you need. If just with the GitHub example, I said, if we're talking about having access to read issues and write issues being basically enough to get you to the lethal trifecta. If I don't have, if I don't have the ability to write, but I don't have the ability to create issues to communicate out only read, well, I've cut off one of those pieces of the trifecta. So the security reason is one thing to be, one reason to be thrifty with the tools you define. But the other is efficiency, because if all of the tools that I define are taking up context, I don't want to consume extra context. I don't want to waste tokens. I don't want to distract from the intent of what I'm trying to do. So just choosing only the tools that you need and putting them in your MCP server can make it a lot more efficient and more secure.

Likewise, keeping your responses concise. A typical REST API for a product, and certainly that is true with Zendesk, it's going to include a lot of details in, you know, a record that you pull from. It might be enough, might be everything that you need to render the webpage view of this, but it's not what the model needs. It's not what I need to answer my question of what did the customer say was going wrong? I don't need to know, as is the case in the Zendesk API, what the user agent string was of the person when they went to the Zendesk portal and typed in the thing. I just need the content of the text. And so stripping these out saves you tokens and makes your, your inference more efficient. And likewise, you know, be mindful about your personal data. That's my email right there, but I didn't, I have not exposed my, my email there. I've communicated that somebody from Posit made this message and, you know, sometimes you need to give access to personal data for whatever application you're doing, but oftentimes you don't. And by writing a custom MCP server, you own the code that does this so you can tailor it to whatever you need.

So MCP or not MCP, that is a question. So MCP is, like I said, just an API standard. If you write your own and deploy it, you can really unlock a lot of capabilities for your agentic workflows. Posit Connect, I should just say as a side, it's a great place to deploy MCP servers. In designing them, you want to be thoughtful about both what makes it efficient for the model to do the inference, but also the security implications. I can't underscore that enough, but by making your own, you have a lot of ability to shape that and your AI agents are really good at writing them and shaping them. The code here in that repo, I won't claim to have written it myself. There was a lot of Claude involved there. So apologies for places that it's not as pristine and Pythonic as you might want, but it gets the job done and it, and it keeps the data that I don't want in my context out there and lets me unlock the power that I want to get.

Thanks a lot.