raku-mcp-sdk

logo

Raku MCP SDK: A Raku (Perl 6) implementation of the Model Context Protocol (MCP) SDK.

Build MCP servers and clients in Raku to integrate with LLM applications like Claude Desktop, IDEs, and other AI tools.

CI zef License: MIT

Why Raku?
Raku is a expressive, multi-paradigm language with strong concurrency tools, a flexible type system, and modern Unicode support. It is well suited for building protocol-first infrastructure where clarity, safety, and rapid iteration matter.

Status

Raku MCP SDK provides comprehensive coverage of the MCP specification 2025-11-25.
See Gap Analysis for details.

Implementation progress

Feature Status Notes
JSON-RPC 2.0 ✅ Done Full message handling
Stdio Transport ✅ Done Production ready
Tools ✅ Done List, call, builder API, annotations
Resources ✅ Done List, read, builder API, annotations
Prompts ✅ Done List, get, builder API
Pagination ✅ Done Cursor-based for all list endpoints
Logging ✅ Done Server-side notifications, logging/setLevel, level filtering
Progress ✅ Done _meta.progressToken extraction, server notifications, client Supply
Cancellation ✅ Done Request cancellation with notifications
Resource subscriptions ✅ Done Subscribe, unsubscribe, update notifications
Roots ✅ Done Client roots, server list-roots
Sampling ✅ Done Full support with tools, toolChoice, includeContext, stopReason
HTTP Transport ✅ Done Full client/server with session management, SSE, resumption
Legacy SSE Transport ✅ Done Backwards-compatible HTTP+SSE transport (spec 2024-11-05)
Elicitation ✅ Done Form and URL modes with handler callbacks
Tasks (experimental) ✅ Done Async tool execution, status polling, cancellation
Extensions framework ✅ Done (experimental) Negotiation via experimental capabilities + extension method routing
Completion ✅ Done Prompt and resource autocomplete with handler registration
Tool output schemas ✅ Done outputSchema and structuredContent for structured results
Resource templates ✅ Done URI templates with pattern matching and builder API
Tool metadata ✅ Done Tool name validation (SEP-986), icons and title on Tool/Resource/Prompt/Implementation (SEP-973)
OAuth 2.1 ✅ Done PKCE, token management, server validation, metadata discovery, dynamic client registration, M2M client credentials, enterprise IdP (SEP-990)

Roadmap

The Raku MCP SDK is currently in review by the community.
Planned and currently ongoing efforts:

Table of contents

Introduction

MCP

Model Context Protocol (MCP) is an open standard that standardizes how AI models interact with external data and tools. Consider it a “USB-C port for AI applications”, a universal interface that replaces the need to build custom connectors for every new data source or tool.

What is it for?

It solves the “m-by-n” integration problem. Instead of every AI application (Claude, ChatGPT, IDEs) needing a specific adapter for every data source (Postgres, Google Drive, Slack), they all speak one protocol.

Design principles

Current status

Raku

Raku (formerly Perl 6) is a high-level, multi-paradigm programming language optimized for expressiveness, modularity, and consistency. It is a specification-driven language (with Rakudo being the primary implementation) that encourages “programming as a human language”—allowing code to be written in a way that feels natural and context-aware rather than rigid and machine-like.

Design principles

Raku preserves the spirit of Perl (“There Is More Than One Way To Do It”) but rebuilds the foundation entirely. Its core principles include:

What is outstanding? (Unique features)

Raku offers features that are often libraries or “hacks” in other languages as first-class citizens:

Raku for AI and MCP

Raku is a “sleeper” choice for specific AI domains, particularly those involving language and orchestration.

Suitability for AI:

Interfacing through MCP (Model Context Protocol): Raku is surprisingly well-architected for the Model Context Protocol (MCP), which connects LLMs to external tools and data.

Installation

# From zef
zef install MCP

# From source
git clone https://github.com/wkusnierczyk/raku-mcp-sdk
cd raku-mcp-sdk
zef install .

Quick start

Creating a server

use MCP;
use MCP::Server;
use MCP::Transport::Stdio;
use MCP::Types;

# Create server
my $server = MCP::Server::Server.new(
    info => MCP::Types::Implementation.new(
        name => 'my-server',
        version => '1.0.0'
    ),
    transport => MCP::Transport::Stdio::StdioTransport.new,
);

# Add a tool
$server.add-tool(
    name => 'greet',
    description => 'Greet someone by name',
    schema => {
        type => 'object',
        properties => {
            name => { type => 'string', description => 'Name to greet' }
        },
        required => ['name'],
    },
    handler => -> :%params {
        "Hello, %params<name>!"
    }
);

# Add a resource
$server.add-resource(
    uri => 'info://about',
    name => 'About',
    description => 'About this server',
    mimeType => 'text/plain',
    reader => { 'This is my MCP server!' }
);

# Start serving
await $server.serve;

Using the fluent builder API

use MCP::Server::Tool;

# Build tools with fluent API
my $calculator = tool()
    .name('add')
    .description('Add two numbers')
    .number-param('a', description => 'First number', :required)
    .number-param('b', description => 'Second number', :required)
    .annotations(title => 'Calculator', :readOnly, :idempotent)
    .handler(-> :%params { %params<a> + %params<b> })
    .build;

$server.add-tool($calculator);

Creating a client

use MCP;
use MCP::Transport::StreamableHTTP;

# Connect to a remote MCP server over HTTP
my $client = Client.new(
    info => Implementation.new(
        name => 'my-client',
        version => '1.0.0'
    ),
    transport => StreamableHTTPClientTransport.new(
        endpoint => 'http://localhost:8080/mcp'
    ),
);

await $client.connect;

# List and call tools (with pagination support)
my $tools-result = await $client.list-tools;
for $tools-result<tools> -> $tool {
    say "Tool: $tool.name() - $tool.description()";
}
# Use $tools-result<nextCursor> for pagination if present

my $call-result = await $client.call-tool('greet', arguments => { name => 'World' });
say $call-result.content[0].text;  # "Hello, World!"

# Read resources
my @contents = await $client.read-resource('info://about');
say @contents[0].text;

Examples

The examples/ directory contains runnable, minimal reference implementations that demonstrate common MCP SDK patterns. Use them to quickly validate your environment, see how transports and handlers fit together, and copy a solid starting point for your own servers and clients.

To list available examples:

# execute without naming any example
make run-examples

Available examples:
  • advanced-client      # In-process loopback covering pagination, completions, roots, and elicitation
  • advanced-server      # Pagination, resource subscriptions, and cancellation
  • http-server          # Streamable HTTP server transport
  • oauth-server         # HTTP server with OAuth 2.1 token validation
  • sampling-client      # Client-side sampling handler
  • extensions           # Extension registration, negotiation, and method dispatch
  • simple-server        # Stdio server with tools, resources, and prompts

Run any example with:

# execute naming an example
make run-example EXAMPLE=advanced-server

→ Running example: advanced-server...

== Pagination ==
Page 1 tools: tool-beta, tool-epsilon
Page 1 nextCursor present: yes
Page 2 tools: tool-alpha, tool-delta
Page 2 nextCursor present: yes

== Resource Subscriptions ==
Subscribe result keys: 
Update notifications sent: 1
Last notification method: notifications/resources/updated

== Cancellation ==
Marked cancelled: yes
Responses sent after cancellation: 0

Done.

Features

Tools

Tools are functions that the LLM can call.

$server.add-tool(
    name => 'search',
    description => 'Search for something',
    schema => {
        type => 'object',
        properties => {
            query => { type => 'string' },
            limit => { type => 'integer', default => 10 },
        },
        required => ['query'],
    },
    handler => -> :%params {
        # Return string, Content object, or CallToolResult
        my @results = do-search(%params<query>, %params<limit>);
        @results.join("\n")
    }
);

Resources

Resources provide read-only data.

# Static resource
$server.add-resource(
    uri => 'config://app',
    name => 'App Config',
    mimeType => 'application/json',
    reader => { to-json(%config) }
);

# File-based resource
use MCP::Server::Resource;
$server.add-resource(file-resource('data.txt'.IO));

Prompts

Prompts are templated message workflows.

use MCP::Server::Prompt;

$server.add-prompt(
    name => 'summarize',
    description => 'Summarize content',
    arguments => [
        { name => 'content', required => True },
        { name => 'length', required => False },
    ],
    generator => -> :%params {
        my $length = %params<length> // 'medium';
        user-message("Please provide a $length summary of: %params<content>")
    }
);

Development

The project uses a comprehensive Makefile for development tasks:

make about       # Show project information
make all         # Full build: dependencies → build → test
make test        # Run test suite

Makefile Targets

Target Description Notes
Primary targets
allInstall deps, build, and testRuns dependencies → build → test
buildValidate and precompile modulesRuns validate then build-precompile
build-precompilePrecompile the main moduleUses raku -Ilib -c lib/MCP.rakumod fallback
testBuild and run testsDepends on build
installInstall module globallyUses zef install . --/test
Validation and metadata
validateValidate META6.json and provides entriesRuns validate-meta and validate-provides
validate-metaCheck required META6.json fieldsEnsures name, version, description, provides
validate-providesVerify provides paths existPrints each resolved entry
Dependencies
dependenciesInstall runtime dependencieszef install --deps-only .
dependencies-devInstall dev dependenciesIncludes Prove6, Test::META, Mi6, Racoco
dependencies-updateUpdate dependenciesRuns zef update and reinstalls project deps
Lint and formatting
lintRun syntax + META checksRuns lint-syntax and lint-meta
lint-syntaxCompile-check source filesUses raku -Ilib -c
lint-metaValidate META6.jsonRequires JSON::Fast
formatFormat guidance and whitespace scanNon-destructive
format-fixRemove trailing whitespaceApplies to source + tests
checkRun lint + testsEquivalent to lint test
Testing and coverage
test-verboseRun tests with verbose outputUses prove6 with --verbose
test-fileRun a specific test fileFILE=t/01-types.rakutest
test-quickRun tests without buildSkips build
coverageCheck coverage threshold (CI)Uses Test::Coverage; fails if below threshold
coverage-reportGenerate coverage report (local)Uses RaCoCo; produces HTML, JSON, and Markdown reports
benchmarkRun performance benchmarksParsing, dispatch, concurrency
Documentation
docsGenerate text docs into docs/Uses raku --doc=Text per module
docs-serveServe docs (placeholder)Not implemented
architecture-diagramBuild architecture PNGRenders architecture/architecture.mmd to architecture/architecture.png
Distribution and release
distCreate source tarballWrites to dist/
releaseInteractive release helperPrompts for fez upload
Utilities and examples
aboutShow project infoPrints metadata from Makefile
replStart REPL with project loadedraku -Ilib -MMCP
run-exampleRun example by nameEXAMPLE=simple-server
infoShow toolchain + statsRaku/Zef/Prove versions
list-modulesList module filesFrom lib/
list-testsList test filesFrom t/
Install/uninstall
install-localInstall to homeUses zef install . --to=home
install-forceForce installUses zef install . --force-install
uninstallUninstall modulezef uninstall MCP
CI helpers
ciCI pipelinedependencies → lint → test
ci-fullFull CI pipelinedependencies-dev → lint → test → coverage
Version management
versionShow or update project versionmake TAG=1.2.3 version updates Makefile + META6.json + README (no tag)
bump-patchPatch bumpmake bump-patch bumps to the next patch version (no tag)
bump-minorMinor bumpmake bump-minor bumps to the next minor version (no tag)
bump-majorMajor bumpmake bump-major bumps to the next major version (no tag)
Benchmarks and stress tests
benchmarkRun performance benchmarksWrites timestamped reports to bench/
stressRun stress testsWrites timestamped reports to bench/
Cleaning
cleanRemove build/coverage/distRuns clean-build/clean-coverage/clean-dist
clean-buildRemove precomp/build dirsRemoves .precomp and .build
clean-coverageRemove coverage outputRemoves *.rakucov, coverage-report/, and .racoco/
clean-distRemove tarballs/dist dirRemoves dist/ and *.tar.gz
clean-allDeep cleanAlso removes docs build output

Environment Variables

Variable Description
V=1 Enable verbose output
NO_COLOR=1 Disable colored output
FILE=<path> Specify file for test-file target
EXAMPLE=<name> Specify example for run-example target

Versioning

Use make version to set an explicit version (no tag):

make TAG=0.10.0 version

Or use a positional argument:

make version 0.10.0

For quick bumps, use:

make bump-patch    # x.y.(z+1)
make bump-minor    # x.(y+1).0
make bump-major    # (x+1).0.0

Coverage

The project uses two complementary coverage tools with separate make targets:

Target Tool Purpose Output
make coverage Test::Coverage Threshold check (CI) Pass/fail TAP output
make coverage-report RaCoCo Detailed report (local) HTML, JSON, and Markdown in coverage-report/

Important: The two tools measure coverage differently, so their reported percentages will not match. Test::Coverage instruments at the statement level and is used in CI to enforce a minimum threshold. RaCoCo instruments at the line level and produces detailed per-module reports for local analysis. The CI workflow uses only make coverage; make coverage-report is for local use.

Install both with:

make dependencies-dev

Or individually:

zef install Test::Coverage   # for make coverage
zef install App::RaCoCo      # for make coverage-report

CI pipeline

The project runs automated checks on every push and pull request via GitHub Actions.

CI workflow (ci.yml):

  1. Lint — validates META6.json, checks syntax, and scans formatting.
  2. Test — runs the full test suite across a matrix of 3 OSes (Ubuntu, macOS, Windows) and 2 Raku versions (2024.12, latest). Windows is tested on latest only.
  3. Coverage — runs after tests pass on Ubuntu, checks coverage with Test::Coverage, and fails if coverage drops below the configured threshold (see Coverage).

Release workflow (release.yml), triggered on version tags (v*.*.*):

  1. Validate — checks the tag matches META6.json version.
  2. Test — runs the full matrix (same as CI).
  3. Build — creates a distribution archive.
  4. Release — creates a GitHub release (draft, upload assets, publish).
  5. Publish — uploads to the Zef ecosystem via fez.

Project structure

MCP/
├── MCP.rakumod                     # Main module, re-exports
├── MCP/
│   ├── Types.rakumod               # Protocol types
│   ├── JSONRPC.rakumod             # JSON-RPC 2.0
│   ├── Transport/
│   │   ├── Base.rakumod            # Transport role
│   │   ├── Stdio.rakumod           # Stdio transport
│   │   ├── StreamableHTTP.rakumod  # HTTP transport with SSE
│   │   └── SSE.rakumod             # Legacy SSE transport (2024-11-05)
│   ├── OAuth.rakumod               # OAuth 2.1 types, PKCE, exceptions
│   ├── OAuth/
│   │   ├── Client.rakumod          # Client-side OAuth flow
│   │   └── Server.rakumod          # Server-side token validation
│   ├── Server.rakumod              # Server implementation
│   ├── Server/
│   │   ├── Tool.rakumod            # Tool helpers
│   │   ├── Resource.rakumod        # Resource helpers
│   │   └── Prompt.rakumod          # Prompt helpers
│   └── Client.rakumod              # Client implementation

Contributing

Contributions are welcome. You can:

Note

Quality

Security

A security review was conducted on the codebase. No critical vulnerabilities were found. The following defense-in-depth measures are implemented:

Additional areas reviewed with no issues found:

User responsibility (by design for an SDK):

To report a security issue, please open a confidential issue or email the maintainer directly.

Performance and stress testing

The SDK includes benchmarks and stress tests (make benchmark, make stress) that measure:

Reports are written as timestamped Markdown and JSON files to bench/.

License

MIT License - see the LICENSE file and the MIT License site.

References

Acknowledgments

Building this repository was supported by:

About

$ make about

Raku MCP SDK: Raku Implementation of the Model Context Protocol
├─ version:    0.33.6
├─ developer:  mailto:waclaw.kusnierczyk@gmail.com
├─ source:     https://github.com/wkusnierczyk/raku-mcp-sdk
└─ licence:    MIT https://opensource.org/licenses/MIT