Stumbling into AI: Part 1—MCP

Published by in AI, MCP, Raycast at https://rmoff.net/2025/09/04/stumbling-into-ai-part-1mcp/

A short series of notes for myself as I learn more about the AI ecosystem as of September 2025. The driver for all this is understanding more about Apache Flink’s Flink Agents project, and Confluent’s Streaming Agents.

The first thing I want to understand better is MCP.

2025 09 03T10 32 54 772Z

For context, so far I’ve been a keen end-user of LLMs, for generating images, proof-reading my blog posts, and general lazyweb stuff like getting it to spit out the right syntax for a bash one-liner. I use Raycast with its Raycast AI capabilities to interact with different models, and I’ve used Cursor to vibe-code some useful (and less useful, fortunately never deployed) functionality for this blog.

But what I’ve not done so far is dig any further into the ecosystem beyond. Let’s fix that!

MCP 🔗

So, what is MCP?

Model Context Protocol sounds fancy and intimidating, but on first pass after a couple of hours poking around here’s my rough take:

MCP exists as an open standard defining a way for LLMs to interact with APIs.

This makes a ton of sense, because the alternative is something awful like vibe coding some piece of boilerplate code to call the API to feedback to the LLM.

mcp 01.excalidraw

The MCP core concepts are tools (the API calls I’m talking about above), resources, and prompts.

The MCP website has a useful guide to how MCP clients and servers interact.

You’ll find plenty of lists of MCP servers online.

This article is basically a journal of my journey figuring out MCP in my head, taking somewhat rambling twists and turns. However, if you’d like to watch a clearly organised and crystal-clear explanation of MCP from one of the industry’s best, check out this video from Tim Berglund:

Local or Remote 🔗

The APIs that the MCP server interacts with could be local (e.g. your filesystem, a database, etc), or remote (e.g. a SaaS platform like AWS or simply a website like AirBnb or Strava).

MCP servers can be run locally, which you’d do if you’re accessing local resources, or if you are developing the MCP server yourself (or want to run one that someone else has written and isn’t provided as a hosted service). You can also host MCP servers remotely (there are a bunch listed here).

Where you want your MCP server also depends on where your LLM client is running. There’s no point running your MCP locally if your LLM client is in the cloud somewhere.

stdio, sse, wtf? 🔗

If your MCP server is running local to the client, it can communicate using stdio (good ole' Linux pipes).

MCP servers can also use HTTP or HTTP SSE, enabling clients to work with them over a network.

Using MCP 🔗

To use an MCP you’ll usually configure your AI tool with it, as an MCP client. ChatGPT and Claude are the biggies here. I like using Raycast as it gives me access to a bunch of different LLMs, and also supports MCPs.

This is where Flink Agents enter the room, as they use MCPs too

Here’s a Raycast conversation using a Strava MCP running locally:

2025 09 02T15 11 39 940Z

Looking at it, it’s quite clearly just a wrapper around the Strava API (which is totally cool, it’s all it claims to be too). It’s just giving the LLM clear parameters and on how to use the API—as well as, crucially, a description of what the API does. For example, rather than just “get-recent-activities”, it tells the LLM “Fetches the most recent activities for the authenticated athlete.”.

When I ask my question, the LLM draws on the fact that it has Strava MCP available with the explanations of what each "tool" (API call) provides. It uses this to work out what to tell the client (Raycast) to request from the MCP server:

mcp 02.excalidraw

The response—a lump of JSON—is passed back to the LLM, which then does its LLM magic and uses the information to answer my question:

mcp 03.excalidraw

The text in red is the actual "Thinking" that the LLM does; you can usually access this in your client, such as Raycast here: strava mcp local

Poking around 🔗

You can use the Inspector tool to look at MCP servers and understand more about how they interact with clients.

npx @modelcontextprotocol/inspector node

(there’s also a CLI MCP inspector, if you prefer)

You can specify both local or remote MCP servers. Here’s the above local Strava MCP server. It’s a stdio server and so I just specify the command to launch it—node plus the code file of the server:

fa29490d2144779ec1176a9e1c36b136a80808501590524648faec44011cb56a

Once connected, List Tools will show me the available tools (in this case, the API calls that the MCP server is a wrapper for), and you can invoke a tool to see the output:

strava1

The list of tools describes to the LLM what each does, the output it’ll get—and what input it can give to the command.

strava2

For example, I might use natural language to ask for some running recommendations, and the LLM will understand that it can use this particular tool (API call) to look up some routes:

2025 09 03T11 34 53 950Z

By using the MCP Inspector you can look at the actual output from the tool (API call); the above image shows how the LLM then weaves this output into the conversation:

2025 09 03T11 37 04 569Z

The sum is greater than the parts 🔗

In the example above I showed the LLM getting running routes from the Strava MCP. If you look closer though, the LLM is using another MCP server (the "Location" one that Raycast provides) to find out the latitude and longitude of Ilkley. That’s because the LLM itself doesn’t know where Ilkley actually is.

This is a nice example of where the natural language side of LLMs can benefit from all the data enrichment that MCP servers can provide.

strava mcp local1

It’s not all just API calls 🔗

So API calls == MCP Server Tools. There are also Resources, and Prompts.

Here’s an example of a Prompt from an MCP server provided by Cloudflare:

2025 09 03T13 37 18 832Z

Bringing all three together is the GitHub MCP Server. First up are the tools, which are similar to what we saw above - nice wrappers around an existing API:

2025 09 03T14 22 35 415Z

Paired with an LLM they make it easy to "talk" to your repos:

2025 09 03T14 21 38 119Z

Next are the prompts.

2025 09 03T14 29 41 547Z

And then finally resources. These are accessed either directly (if provided by the MCP, which they’re not here) or via resource templates.

2025 09 03T14 31 31 468Z

A resource template explains to the LLM the fields to provide to identify a particular resource. For example, if you wanted your LLM to access a particular file in the repository it would be able to find it. Here’s an example of accessing my blog repository’s README:

2025 09 03T14 35 32 057Z

This means that an LLM can then (with the appropriate permissions) access files in GitHub, which is pretty handy.

TABLE OF CONTENTS