🤖 What is MCP?

MCP (Model Context Protocol) is an open and evolving protocol (see modelcontextprotocol.io) that defines how large language models (LLMs) can understand and interact with structured external capabilities.

Instead of relying solely on natural language parsing and undocumented APIs, MCP enables LLMs to introspect and call tools, retrieve and reason with resources, and invoke reusable prompts. This introduces clarity, reusability, and extensibility into AI assistant systems.

MCP defines three types of components:

  • 🛠️ Tools – callable actions or APIs, defined with input/output schemas
  • 📦 Resources – contextual data or runtime configuration for the assistant
  • ✉️ Prompts – snippets of guiding instructions, either static or code-generated

These are described using JSON-compatible schemas and loaded at runtime by a supporting server. The protocol encourages modular design and agent composability.

⚠️ Note: This post presents an experimental implementation of an MCP-compatible framework for the Raku programming language. It is a work in progress, and community input is welcome.


💡 Why Raku?

Raku is well-suited to building MCP tooling due to its:

  • 🧠 Expressive multi-paradigm syntax
  • 🧰 Built-in meta-object protocol (MOP)
  • 🔍 Introspection and trait support
  • 🛡️ Strong type system with gradual typing
  • 📁 Support for resource embedding via %?RESOURCES

These features allow developers to:

  • 🧾 Derive schemas from code automatically
  • ✔️ Perform advanced validation using traits
  • 📝 Annotate and document APIs inline
  • 📚 Embed metadata and logic in clean, declarative structures

🧱 Overview of the Raku Framework

The goal is to provide an ergonomic, modular Raku framework to define and serve MCP-compatible components. The core elements are:

  • 🔧 Tools can be simple exported subs or classes that does MCP::Tool
  • 📦 Resources can be classes, files (via %?RESOURCES), or environment variables
  • ✨ Prompts can be strings or code-defined classes
  • 📄 A mcp.json file describes each group’s capabilities
  • 🌐 A CLI manages scaffolding, execution, and bundling

Execution is powered by servers (e.g. STDIO or HTTP), and applications can load multiple groups at once.


🔨 Defining Tools

As Functions

#| Adds two integers and returns the result
sub add(
    Int $a, #= The first integer
    Int $b  #= The second integer
    --> Int
) is export {
    $a + $b
}

This produces an MCP schema and validates input before execution. Traits like is different(0) can further restrict behavior.

As Classes

unit class WeatherLookup::Tool::Forecast does MCP::Tool;

has Str $.location;

#| Returns a simple forecast string
method call(--> Str) {
    "The weather in $!location will be sunny."
}

MCP::Tool provides a Callable interface and derives the schema from class attributes and the return type of call().

Via Module + Exported Function

To support legacy or utility modules:

{
  "type": "function",
  "module": "Math::Utils",
  "function": "add"
}

📚 Resources

Resources provide configuration, secrets, or contextual data to the assistant. You can define them as:

Embedded Class

"resources": [ "My::Class::Name" ]

File (referenced from %?RESOURCES)

{
  "name": "city-list",
  "type": "resource",
  "value": "data/cities.json"
}

Environment Variable

{
  "name": "api-key",
  "type": "env",
  "value": "API_KEY"
}

🧠 Prompts

Prompts can be:

A Code Class

class GreetingPrompt {
  method run() {
    "Hello! How can I assist you today?"
  }
}

A Static String

{
  "type": "string",
  "name": "greeting",
  "value": "Hello! How can I assist you today?"
}

Use:

mcp create prompt greeting --string "Hello! How can I assist you today?"

🧩 Group Structure and mcp.json

Each MCP group is a Raku module with a resources/mcp.json file listed in META6.json. This file declares the group's:

  • 🛠️ Tools
  • 📦 Resources
  • ✉️ Prompts

Example:

{
  "tools": [
    "WeatherLookup::Tool::Forecast",
    {
      "type": "function",
      "module": "Math::Utils",
      "function": "add"
    }
  ],
  "resources": [ ... ],
  "prompts": [ ... ]
}

The module should implement MCP::Group and define:

unit class WeatherLookup does MCP::Group;
method group-data { %?RESOURCES }

This exposes the tools, resources, and prompts using helper methods.


🛠️ CLI and Example Workflow

The mcp create commands not only generate boilerplate code but also update the group's resources/mcp.json file automatically. This file is the core of group definition and gets listed in META6.json so the framework knows how to load tools, prompts, and resources at runtime.

For example:

mcp new WeatherLookup
cd WeatherLookup
mcp create tool forecast
mcp create resource cities --file cities.json
mcp create resource api-key --env API_KEY
mcp create prompt greeting --string "Hello!"

Then run:

mcp run WeatherLookup ExtraUtils --server=stdio

🤝 Want to Help?

This idea is still experimental. We're exploring how to best represent and serve LLM functionality in Raku using the MCP protocol.

📣 Join us in the #raku channel on Libera.Chat IRC or drop your thoughts on GitHub.

Whether you want to test ideas, write components, improve the CLI, or critique design—your help is welcome!

💡 Let’s build something great together!