Intro Link to heading
It seems that everyone is an MCP guru these days.
I am not.
In fact, I know almost nothing about it. I am just aware of the concept.
This post describes the steps I took in order to create an MCP from scratch, resulting in the project created at:
I also recorded my journey starting from scatch with almost zero knowledge on the topic and using the Quarkus Blog as a guide:
Full version Link to heading
This is me having no idea what I am doing and spending 1.5 hours trying to figure it out.
Shorter version Link to heading
A reshoot of the first video, so that I can come up with something shorter.
What is MCP? Link to heading
MCP stands for Model Context Protocol. It’s the protocol that tools like Goose, an interactive AI shell, use to talk to plugins.
The idea is simple:
- The AI shell sends JSON messages over stdin.
- The plugin processes them and sends responses over stdout.
If you’ve ever written a language server or CLI plugin using stdio, this will feel familiar.
In this case, the plugin acts as a bridge between Goose and Backstage, using Quarkus Backstage
The goal Link to heading
I wanted to:
- List available Backstage templates from Goose.
- Instantiate a template using parameters from a YAML file.
And I wanted to do this using:
- Quarkus as the backend,
- Backstage as the API target,
- MCP as the communication protocol,
- Quarkus Backstage and Quarkus MCP Server extensions to simplify things.
Anatomy of the project Link to heading
Dependencies Link to heading
The project uses two main Quarkus extensions:
|
|
The first implements an MCP server using stdin/stdout. The second talks to the Backstage API.
Implementation Link to heading
The actual implementation lives in a single Java class. It defines the logic for handling incoming MCP requests. Right now, it supports:
- Listing templates
- Instantiating a template using values from a YAML file
The actual code:
|
|
That’s it. Minimal and focused.
Backstage setup Link to heading
To allow the MCP plugin to talk to your Backstage instance, make sure app-config.yaml
has a service-to-service token configured like this:
|
|
That token will be used by the plugin to authenticate against the Backstage API.
Goose integration Link to heading
Goose can be configured to use this MCP plugin via config.yaml
:
|
|
Alternatively, you could launch the jar directly using Java or through your favorite launch tool.
Example prompts Link to heading
Once everything is wired up, you can interact with Backstage through Goose:
List available templates Link to heading
|
|
Instantiate a template Link to heading
First, extract the default values:
|
|
Then prompt Goose:
|
|
The plugin takes care of everything: parsing, calling the API, and responding over stdout.
Reflections Link to heading
It was much easier than I inital thought. Today, I managed two record two videos on the subject, create a github project and write a blog about it.
I find the result pretty impressive and I love the fact that I can allow tools like goose instantly gain access to the tools I’ve been building.
Next steps?
I think I want re-visit every single Quarkus extension I’ve created and add an `mcp` command to it. Well, it’s still Saturday evening, so who knows …
Until then, the code is there. And it works.