Create, test, and publish MCP packages for PPM — tool schemas, Delphi server, pai.package manifests, registry publishing
ppm install mcp-developer
ppm skill install-claude
The second command activates the skill in Claude Code
(copies it into .claude/skills/).
You are an MCP package developer for the PascalAI PPM registry. You know the full pipeline from tool design to publication.
mcp-mypackage/
├── pai.package — PPM manifest (required)
├── main.pai — PAI unit with external declarations
├── SKILL.md — skill documentation (optional)
└── tools/
└── mypackage.tool — JSON tool schema
[package]
name=mcp-mypackage
version=1.0.0
type=mcp
description=Brief description — what tools does this MCP provide?
author=yourname
license=MIT
tags=mcp,category,keyword
[mcp]
transport=stdio
tools=tool_one,tool_two
file=main.pai
unit mcp_mypackage;
// Each MCP tool maps to one PAI function
// String in/out is the standard pattern
function MCP_ToolOne(Input: string): string; external 'mcp-mypackage';
function MCP_ToolTwo(Param1: string; Param2: Int64): string; external 'mcp-mypackage';
{
"tools": [
{
"name": "tool_one",
"description": "What this tool does — specific enough for an LLM to choose it correctly",
"inputSchema": {
"type": "object",
"properties": {
"input": {
"type": "string",
"description": "The text or value to process"
}
},
"required": ["input"]
}
}
]
}
// In MCPService/src/tools/Standalone/MCPTool.MyPackage.pas
unit MCPTool.MyPackage;
type
TMCPMyPackageTool = class(TMCPToolBase)
public
class function Name: string; override;
class function Description: string; override;
class function InputSchema: TJSONObject; override;
function Execute(const Input: TJSONObject): TJSONObject; override;
end;
implementation
class function TMCPMyPackageTool.Name: string;
begin Result := 'tool_one'; end;
function TMCPMyPackageTool.Execute(const Input: TJSONObject): TJSONObject;
var
InputStr, OutputStr: string;
begin
InputStr := Input.GetValue<string>('input');
OutputStr := ProcessSomething(InputStr);
Result := TJSONObject.Create;
Result.AddPair('result', OutputStr);
end;
program use_my_mcp;
uses mcp_mypackage;
begin
LLM_Connect('claude-opus-4-6', GetEnv('ANTHROPIC_API_KEY'));
var Result := MCP_ToolOne('hello world');
WriteLn(Result);
// MCP tools are also available as LLM tools automatically
var Answer := LLM_Complete('Use tool_one to process: hello world');
WriteLn(Answer);
end.
| Package | Tools |
|---|---|
mcp-datetime |
now, format_date, add_days, diff_days |
mcp-hash |
md5, sha256, sha512, blake3, hmac |
mcp-text-transform |
uppercase, lowercase, trim, reverse, word_count |
mcp-shell |
exec, eval |
mcp-fs |
read_file, write_file, list_dir, file_exists |
mcp-sqlite |
query, execute, tables |
mcp-postgres |
query, execute |
mcp-smtp |
send_email |
mcp-telegram |
send_message |
# Pack the folder into .paipkg
ppm pack mcp-mypackage/
# Publish
ppm publish mcp-mypackage.paipkg \
--type=mcp \
--description="My MCP tools" \
--tags="mcp,utility" \
--api-key=YOUR_PPM_KEY
# Verify
ppm search mcp-mypackage --type=mcp
get_current_datetime not date{"error": "message"} not crashtests/examples/NNN_mcp_mypackage.pai and verify PASSpai run demo.pai before publishing