- Adaptive Intelligence Framework integration - 94% TypeScript error reduction (103 → 6 errors) - 47 new runtime modules - 11 high-performance packages - 4,565 new tests added - Production readiness: 78/100 Resolving conflicts by accepting develop changes.
Model Context Protocol (MCP) Integration
PCL now supports the Model Context Protocol (MCP), enabling seamless integration with Claude Code, Cursor, VS Code, and other MCP-compatible AI tools.
What is MCP?
The Model Context Protocol is Anthropic's open standard for connecting AI applications to external data sources and tools. It provides a universal way to:
- Expose capabilities as discoverable tools
- Share data as accessible resources
- Enable integration with any MCP-compatible client
With MCP, your PCL personas become first-class tools that AI assistants can discover and use automatically.
Why Use MCP with PCL?
Before MCP
// Manual persona execution
const compiler = new Compiler();
const ast = compiler.compile(source);
const runtime = new Runtime();
const result = await runtime.execute(ast);
Limitations:
- Manual integration required for each tool
- No standardized discovery mechanism
- Custom protocols for each AI assistant
- Difficult to share personas across tools
After MCP
User: "Claude Code, use the CodeReviewer persona on this file"
Claude Code: *discovers PCL MCP server*
Claude Code: *executes persona/execute tool*
Claude Code: Here's the code review...
Benefits:
- ✅ Automatic discovery: AI tools find your personas instantly
- ✅ Standardized protocol: One implementation works everywhere
- ✅ Zero configuration: No custom integrations needed
- ✅ Universal compatibility: Works with Claude Code, Cursor, VS Code, etc.
Quick Start
1. Install Dependencies
npm install @pcl/sdk @modelcontextprotocol/sdk
2. Create MCP Server
import { PclServer, StdioTransport } from '@pcl/sdk/mcp';
import { Runtime } from '@pcl/sdk/runtime';
const runtime = new Runtime({
personas: [...], // Your personas
teams: [...], // Your teams
});
const server = new PclServer({
name: 'My PCL Server',
version: '1.0.0',
runtime,
});
const transport = new StdioTransport();
await server.start(transport);
3. Configure AI Tool
Claude Code (~/.config/claude/mcp.json):
{
"mcpServers": {
"pcl": {
"command": "node",
"args": ["./dist/mcp-server.js"]
}
}
}
4. Use Your Personas
Ask Claude Code:
"List available PCL personas"
"Execute CodeReviewer on this file"
"Run the ResearchTeam on topic X"
Done! Your personas are now available to any MCP-compatible tool.
Architecture
MCP Components
┌─────────────────────┐
│ AI Assistant │ (Claude Code, Cursor, VS Code)
│ (MCP Client) │
└──────────┬──────────┘
│ JSON-RPC 2.0 over stdio/HTTP
↓
┌─────────────────────┐
│ PCL MCP Server │
│ │
│ ┌───────────────┐ │
│ │ Tool Handlers │ │ persona/execute
│ │ │ │ persona/list
│ │ │ │ team/execute
│ └───────────────┘ │
│ │
│ ┌───────────────┐ │
│ │ Resources │ │ persona://definition/{name}
│ │ │ │ team://definition/{name}
│ └───────────────┘ │
│ │
│ ┌───────────────┐ │
│ │ PCL Runtime │ │ Execute personas & workflows
│ └───────────────┘ │
└─────────────────────┘
Communication Flow
- Discovery: Client sends
initializerequest - Tool Listing: Client calls
tools/listto get available tools - Execution: Client calls
tools/callwith parameters - Result: Server returns tool execution results
- Resources: Client can read
resources/readfor additional data
Core Features
1. Persona Execution
Execute any PCL persona as an MCP tool.
Tool: persona/execute
Parameters:
persona(string): Persona name or IDinput(string): Input message/promptcontext(object, optional): Context variables
Example:
await client.callTool('persona/execute', {
persona: 'CodeReviewer',
input: 'function add(a, b) { return a + b }',
context: { language: 'javascript' },
});
Result:
{
"content": [
{
"type": "text",
"text": "Code Review:\n- Good: Simple, pure function\n- Improvement: Add JSDoc comments\n- Security: No issues"
}
]
}
2. Persona Discovery
List and inspect available personas.
Tool: persona/list
Example:
await client.callTool('persona/list', {});
Result:
{
"content": [
{
"type": "text",
"text": "Available Personas:\n- CodeReviewer: Expert code reviewer\n- DocumentationWriter: Technical writer\n- SecurityAnalyst: Security expert"
}
]
}
Tool: persona/info
Parameters:
persona(string): Persona name or ID
Example:
await client.callTool('persona/info', {
persona: 'CodeReviewer',
});
3. Team Execution
Execute multi-persona teams.
Tool: team/execute
Parameters:
team(string): Team name or IDinput(string): Input for the teamcontext(object, optional): Context variables
Example:
await client.callTool('team/execute', {
team: 'ResearchTeam',
input: 'Analyze AI safety concerns',
context: { depth: 'comprehensive' },
});
4. Workflow Execution
Execute complex PCL workflows.
Tool: workflow/execute
Parameters:
workflow(string): Workflow name or IDinput(object): Input data
Example:
await client.callTool('workflow/execute', {
workflow: 'CodeReviewWorkflow',
input: {
repository: 'github.com/user/repo',
prNumber: 123,
},
});
5. Resource Access
Access persona definitions and outputs as resources.
Resources:
persona://definition/{name}- Persona source codeteam://definition/{name}- Team source codeworkflow://definition/{name}- Workflow source code
Example:
const definition = await client.readResource(
'persona://definition/CodeReviewer'
);
console.log(definition.text);
// persona CodeReviewer {
// role: "Expert code reviewer"
// instructions: "..."
// }
Transport Options
PCL MCP Server supports multiple transports:
1. Stdio Transport (CLI Tools)
Use for: Claude Code, command-line tools
Setup:
import { StdioTransport } from '@pcl/sdk/mcp';
const transport = new StdioTransport({ debug: false });
await server.start(transport);
Communication: JSON-RPC messages via stdin/stdout
2. HTTP + SSE Transport (Web Apps)
Use for: Web applications, remote servers
Setup:
import { HttpSseTransport } from '@pcl/sdk/mcp';
const transport = new HttpSseTransport({
baseUrl: 'https://api.example.com',
headers: { Authorization: 'Bearer token' },
});
await server.start(transport);
Communication:
- HTTP POST for requests
- Server-Sent Events (SSE) for notifications
3. WebSocket Transport (Real-time)
Use for: Real-time applications, collaborative tools
Coming Soon: Full-duplex WebSocket transport
Integration Guides
Claude Code
Quick Start:
// ~/.config/claude/mcp.json
{
"mcpServers": {
"pcl": {
"command": "node",
"args": ["./dist/mcp-server.js"]
}
}
}
VS Code
Extension: Install pcl-vscode extension
Features:
- Syntax highlighting
- IntelliSense
- MCP server management
- One-click persona execution
Cursor
Setup: Same as Claude Code configuration
Features:
- AI-powered code generation with PCL personas
- Context-aware suggestions
- Inline persona execution
Examples
Basic Server
import { PclServer, StdioTransport } from '@pcl/sdk/mcp';
import { Runtime, Compiler } from '@pcl/sdk';
// Compile PCL source
const compiler = new Compiler();
const ast = compiler.compile(`
persona CodeReviewer {
role: "Expert code reviewer"
instructions: "Review code for best practices"
}
`);
// Create runtime
const runtime = new Runtime({
personas: [ast.persona],
});
// Create MCP server
const server = new PclServer({
name: 'PCL Server',
version: '1.0.0',
runtime,
});
// Start with stdio transport
const transport = new StdioTransport();
await server.start(transport);
HTTP Server
import { PclServer } from '@pcl/sdk/mcp';
import { createServer } from 'http';
const server = new PclServer({ name: 'PCL HTTP', version: '1.0.0', runtime });
// Handle HTTP requests
const httpServer = createServer(async (req, res) => {
if (req.method === 'POST' && req.url === '/mcp/request') {
const body = await readBody(req);
const request = JSON.parse(body);
const response = await server.handleRequest(request);
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(response));
}
});
httpServer.listen(3000);
Custom Tools
// Register custom tool
server.registerTool(
{
name: 'custom/analyze',
description: 'Custom analysis tool',
inputSchema: {
type: 'object',
properties: {
data: { type: 'string' },
},
required: ['data'],
},
},
async (params) => {
const result = await customAnalyze(params.arguments.data);
return {
content: [{ type: 'text', text: result }],
};
}
);
Best Practices
1. Error Handling
Always wrap tool handlers in try-catch:
server.registerTool(tool, async (params) => {
try {
const result = await execute(params);
return { content: [{ type: 'text', text: result }] };
} catch (error) {
return {
content: [{ type: 'text', text: error.message }],
isError: true,
};
}
});
2. Input Validation
Validate all inputs:
server.registerTool(tool, async (params) => {
if (!params.arguments.persona) {
return {
content: [{ type: 'text', text: 'Missing persona name' }],
isError: true,
};
}
// Continue with valid input...
});
3. Logging
Use stderr for logging (stdout is for MCP messages):
console.error('[MCP] Server started');
console.error('[MCP] Processing request:', request.method);
4. Graceful Shutdown
Handle shutdown signals:
process.on('SIGINT', async () => {
console.error('[MCP] Shutting down...');
await server.stop();
process.exit(0);
});
5. Security
- Validate all inputs
- Sanitize outputs
- Use environment variables for sensitive data
- Implement authentication if needed
Troubleshooting
Server Not Starting
Check build:
npm run build
ls dist/mcp-server.js
Test directly:
node dist/mcp-server.js
Client Not Connecting
Verify configuration path is absolute:
{
"command": "node",
"args": ["/full/path/to/dist/mcp-server.js"]
}
Check logs:
tail -f ~/.config/claude/logs/mcp.log
Tools Not Working
Enable debug mode:
const transport = new StdioTransport({ debug: true });
Check tool registration:
const tools = await server.handleRequest({
jsonrpc: '2.0',
method: 'tools/list',
id: 1,
});
console.error('Available tools:', tools);
API Reference
PclServer
class PclServer {
constructor(config: PclMcpServerConfig);
registerTool(
tool: McpTool,
handler: (params: McpToolCallParams) => Promise<McpToolCallResult>
): void;
registerResource(
resource: McpResource,
provider: (uri: string) => Promise<McpResourceContent>
): void;
start(transport: McpTransport): Promise<void>;
stop(): Promise<void>;
handleRequest(request: McpRequest): Promise<McpResponse>;
}
Transports
class StdioTransport implements McpTransport {
constructor(config?: StdioTransportConfig);
send(message: McpRequest | McpResponse): Promise<void>;
onMessage(handler: (message: McpResponse) => void): void;
close(): Promise<void>;
isConnected(): boolean;
}
class HttpSseTransport implements McpTransport {
constructor(config: HttpSseTransportConfig);
send(message: McpRequest): Promise<void>;
onMessage(handler: (message: McpResponse) => void): void;
close(): Promise<void>;
isConnected(): boolean;
}
Resources
- MCP Specification: https://modelcontextprotocol.io/
- Claude Code Integration: claude-code-integration.md
- Examples: examples.md
- Troubleshooting: troubleshooting.md
- GitHub: https://github.com/pcl-lang/pcl
Questions or Issues?