MCP Tools Reference
Overview
PML (Procedural Memory Layer) exposes its features via the MCP (Model Context Protocol). This reference documents all available tools.
Version: 1.0.0
Available transports:
| Transport | Command | Features |
|---|---|---|
| stdio | pml serve --config ... |
MCP protocol, console logs |
| Streamable HTTP | pml serve --config ... --port 3001 |
MCP on /mcp + Dashboard + Events SSE |
Note: stdio mode is recommended for Claude Code. Streamable HTTP mode (MCP spec 2025-03-26) enables the Fresh dashboard and real-time events.
Tool Architecture
PML exposes two types of tools:
| Type | Pattern | Description |
|---|---|---|
| Meta-tools | pml:* |
PML intelligent tools (search, capabilities, DAG, sandbox) |
| Proxied tools | serverId:toolName |
Tools from underlying MCP servers (filesystem, github...) |
Note: By default, only meta-tools are listed to minimize context usage (ADR-013). Underlying tools are discovered via
search_toolsor used directly if their name is known.
PML Meta-Tools
pml:search_tools
Semantic search and recommendations based on the usage graph.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
query |
string | Yes | Natural language description of what you want to do |
limit |
number | No | Max number of tools to return (default: 5) |
include_related |
boolean | No | Include related tools from graph (default: false) |
context_tools |
string[] | No | Already used tools - boosts related tools |
Request example:
await callTool("pml:search_tools", {
query: "read and parse JSON files",
limit: 5,
include_related: true,
});Response example:
{
"content": [{
"type": "text",
"text": "{\"tools\":[{\"name\":\"filesystem:read_file\",\"score\":0.92,\"description\":\"Read file contents\"},{\"name\":\"filesystem:read_directory\",\"score\":0.85,\"related\":false},{\"name\":\"memory:search_nodes\",\"score\":0.72,\"related\":true}]}"
}]
}pml:search_capabilities
Search for proven code patterns learned from successful executions.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
intent |
string | Yes | What you want to accomplish - finds similar past successes |
include_suggestions |
boolean | No | Also show related capabilities (default: false) |
Request example:
await callTool("pml:search_capabilities", {
intent: "parse JSON from API and store in database",
include_suggestions: true,
});Response example:
{
"content": [{
"type": "text",
"text": "{\"capabilities\":[{\"id\":\"cap_abc123\",\"intent\":\"fetch API data and insert to DB\",\"match_score\":0.94,\"success_rate\":0.95,\"reuse_count\":12,\"tools_used\":[\"fetch:get\",\"json:parse\",\"db:insert\"],\"code\":\"const data = await fetch...\"}]}"
}]
}When to use:
| Tool | Purpose |
|---|---|
search_tools |
Find MCP tools by capability description |
search_capabilities |
Find proven code patterns that worked before |
Tip: Use
search_capabilitieswhen you want to reuse existing patterns instead of building from scratch. The returned code can be executed directly viaexecute_code.
pml:execute_dag
Execute a multi-tool DAG (Directed Acyclic Graph) workflow.
Usage modes:
- Intent: Provide
intent→ PML suggests and executes the optimal DAG - Explicit: Provide
workflow→ Executes the explicitly defined DAG
Provide either
intentorworkflow, not both.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
intent |
string | No* | Natural description of the goal (suggestion mode) |
workflow |
object | No* | Explicit DAG structure (explicit mode) |
per_layer_validation |
boolean | No | Pause between each layer for validation (default: false) |
*At least one of the two is required.
Workflow structure (explicit mode):
{
workflow: {
tasks: [
{
id: string, // Unique task identifier
tool: string, // Tool name (serverId:toolName)
arguments: object, // Tool arguments
dependsOn?: string[] // IDs of dependent tasks
}
]
}
}Example - Intent Mode:
await callTool("pml:execute_dag", {
intent: "Read config.json and create a memory entity with its content",
});Example - Explicit Mode with parallelization:
await callTool("pml:execute_dag", {
workflow: {
tasks: [
{ id: "t1", tool: "filesystem:read_file", arguments: { path: "config.json" } },
{ id: "t2", tool: "filesystem:read_file", arguments: { path: "package.json" } },
{
id: "t3",
tool: "memory:create_entities",
arguments: { entities: [{ name: "config", content: "$t1.result" }] },
dependsOn: ["t1"],
},
],
},
});
// t1 and t2 execute in parallel, t3 waits for t1Response example (success):
{
"content": [{
"type": "text",
"text": "{\"status\":\"complete\",\"results\":{\"t1\":{\"content\":\"...\"},\"t2\":{\"content\":\"...\"},\"t3\":{\"success\":true}},\"metrics\":{\"total_time_ms\":1823,\"parallel_branches\":2}}"
}]
}Response example (per-layer validation):
{
"content": [{
"type": "text",
"text": "{\"status\":\"layer_complete\",\"workflow_id\":\"wf_abc123\",\"current_layer\":1,\"total_layers\":3,\"layer_results\":[...],\"next_action\":\"Use pml:continue to proceed\"}"
}]
}pml:execute_code
Execute TypeScript/JavaScript code in an isolated Deno sandbox.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
code |
string | Yes | TypeScript code to execute |
intent |
string | No | Description for automatic tool discovery |
context |
object | No | Data/context to inject into the sandbox |
sandbox_config |
object | No | Sandbox configuration |
sandbox_config options:
| Option | Type | Default | Description |
|---|---|---|---|
timeout |
number | 30000 | Timeout in milliseconds |
memoryLimit |
number | 512 | Heap memory limit in MB |
allowedReadPaths |
string[] | [] | Additional allowed read paths |
REPL behavior:
- Simple expressions → auto-return (
2 + 2returns4) - Multi-statements → explicit
returnrequired
Example - Data processing:
await callTool("pml:execute_code", {
code: `
const items = context.data;
const filtered = items.filter(x => x.active);
return {
total: filtered.length,
summary: filtered.slice(0, 5)
};
`,
context: { data: largeDataset },
});Example - With tool discovery:
await callTool("pml:execute_code", {
intent: "Analyze GitHub commits",
code: `
// 'github' injected automatically thanks to intent
const commits = await github.listCommits({ limit: 100 });
return commits.filter(c => c.author === "alice").length;
`,
});Response example:
{
"content": [{
"type": "text",
"text": "{\"result\":42,\"logs\":[],\"metrics\":{\"execution_time_ms\":127,\"memory_used_mb\":45}}"
}]
}pml:continue
Continue execution of a paused workflow (after per-layer validation).
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
workflow_id |
string | Yes | Workflow ID (returned by execute_dag) |
reason |
string | No | Reason for continuation |
Example:
await callTool("pml:continue", {
workflow_id: "wf_abc123",
reason: "Layer 1 validated, continue",
});pml:abort
Stop a running workflow.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
workflow_id |
string | Yes | Workflow ID to stop |
reason |
string | Yes | Reason for stopping |
Example:
await callTool("pml:abort", {
workflow_id: "wf_abc123",
reason: "Error detected in layer 1 results",
});pml:replan
Re-plan a DAG with new requirements (discovered during execution).
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
workflow_id |
string | Yes | Workflow ID to replan |
new_requirement |
string | Yes | Description of what needs to be added |
available_context |
object | No | Context for replanning |
Example:
// After discovering unexpected XML files
await callTool("pml:replan", {
workflow_id: "wf_abc123",
new_requirement: "Parse discovered XML files",
available_context: {
discovered_files: ["config.xml", "data.xml"],
},
});pml:approval_response
Respond to a Human-in-the-Loop (HIL) approval checkpoint.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
workflow_id |
string | Yes | Workflow ID |
checkpoint_id |
string | Yes | Checkpoint ID (returned by workflow) |
approved |
boolean | Yes | true to approve, false to reject |
feedback |
string | No | Comment or reason for the decision |
Example:
await callTool("pml:approval_response", {
workflow_id: "wf_abc123",
checkpoint_id: "cp_xyz789",
approved: true,
feedback: "Operation validated, proceed with deployment",
});Proxied Tools
Tools from underlying MCP servers are accessible via the serverId:toolName pattern.
Examples:
// File reading via filesystem server
await callTool("filesystem:read_file", { path: "/path/to/file.txt" });
// GitHub issue creation
await callTool("github:create_issue", {
repo: "owner/repo",
title: "Bug report",
body: "Description...",
});
// Memory search
await callTool("memory:search_nodes", { query: "configuration" });Discovery: Use
pml:search_toolsto find available tools by intent.
Data Types
DAGStructure
Structure of a DAG workflow.
interface DAGStructure {
tasks: DAGTask[];
}
interface DAGTask {
id: string; // Unique identifier
tool: string; // "serverId:toolName"
type?: "mcp_tool" | "code_execution";
arguments: Record<string, unknown>;
dependsOn?: string[]; // Dependency IDs (camelCase, not snake_case)
code?: string; // For type: "code_execution"
}TaskResult
Task execution result.
interface TaskResult {
taskId: string;
status: "success" | "error" | "skipped";
result?: unknown;
error?: string;
duration_ms: number;
}WorkflowStatus
Workflow status.
type WorkflowStatus =
| "running" // Currently executing
| "paused" // Waiting for validation/approval
| "complete" // Completed successfully
| "aborted" // Stopped by user
| "error"; // FailedError Codes
| Code | Name | Description | Resolution |
|---|---|---|---|
| -32700 | PARSE_ERROR | Invalid JSON | Check request format |
| -32600 | INVALID_REQUEST | Malformed request | Check MCP structure |
| -32601 | METHOD_NOT_FOUND | Unknown method | Use tools/list, tools/call, or prompts/get |
| -32602 | INVALID_PARAMS | Invalid parameters | Check required parameters |
| -32603 | INTERNAL_ERROR | Internal error | Check logs, retry |
PML specific errors:
| Error | Description | Resolution |
|---|---|---|
WORKFLOW_NOT_FOUND |
Non-existent workflow ID | Check ID, workflow may have expired |
TOOL_NOT_FOUND |
Unknown tool | Use search_tools to discover tools |
SANDBOX_TIMEOUT |
Code execution timeout | Reduce complexity or increase timeout |
SANDBOX_MEMORY |
Sandbox memory exceeded | Reduce data or increase memoryLimit |
MCP_SERVER_ERROR |
Underlying MCP server error | Check MCP server connection |
Limits
| Resource | Limit | Configurable |
|---|---|---|
| Per-tool timeout | 30s | Yes (sandbox_config.timeout) |
| Sandbox memory | 512MB | Yes (sandbox_config.memoryLimit) |
| Code size | 100KB | No |
| Active workflows | 100 | No |
| Paused workflow TTL | 1 hour | No |
| Cache entries | 100 | Yes (--no-cache to disable) |
Complete Examples
Project Analysis Workflow
// 1. Discover relevant tools
const tools = await callTool("pml:search_tools", {
query: "read files and analyze project structure",
include_related: true,
});
// 2. Execute a DAG workflow
const result = await callTool("pml:execute_dag", {
intent: "Read all TypeScript files in src/ and count lines",
});
// 3. Post-process with sandbox
const analysis = await callTool("pml:execute_code", {
code: `
const files = context.files;
return {
totalFiles: files.length,
totalLines: files.reduce((sum, f) => sum + f.lines, 0),
avgLinesPerFile: Math.round(files.reduce((sum, f) => sum + f.lines, 0) / files.length)
};
`,
context: { files: result.results },
});Workflow with Human Validation
// 1. Start with per-layer validation
const workflow = await callTool("pml:execute_dag", {
intent: "Deploy new version to production",
per_layer_validation: true,
});
// 2. Examine layer results
console.log(workflow.layer_results);
// 3. Approve and continue
await callTool("pml:continue", {
workflow_id: workflow.workflow_id,
reason: "Tests passed, approved for deployment",
});See Also
- Installation - Installation and setup
- User Guide - Detailed usage
- Concepts - How PML works
- Configuration - Configuration files
- CLI Reference - Command-line interface