private.me
White Papers / Quickstarts / MCP + xLink
Get xLink
Quickstart Guide

MCP + xLink in 5 Minutes

Add identity-based authentication to Model Context Protocol servers. Replace localhost trust assumptions with cryptographic identity verification using XLinkTransport.

@private.me/mcp-transport JSON-RPC 2.0 Universal Identity Layer
WHAT YOU'LL BUILD

Secure MCP Server with Identity

By the end of this guide, you'll have an MCP server that verifies caller identity before executing tool calls. Every JSON-RPC request is cryptographically signed and verified — no more implicit localhost trust.

WHY THIS MATTERS

Standard MCP servers assume all connections are trusted. XLinkTransport wraps the MCP protocol with xLink's identity layer, so your server knows who is calling each tool — not just that a request arrived on the correct port.

IMPLEMENTATION

Five Steps to Production

1

Install the Package

Add the MCP transport adapter to your project:

npm install
npm install @private.me/mcp-transport @modelcontextprotocol/sdk
2

Create an MCP Server with Identity

Wrap your MCP server with MCPServerAdapter to enforce identity verification:

server.ts
import { Agent, MemoryTrustRegistry, LoopbackTransport } from '@private.me/xlink';
import { MCPServerAdapter } from '@private.me/mcp-transport';
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';

// Shared infrastructure (use HttpTrustRegistry in production)
const registry = new MemoryTrustRegistry();
const transport = new LoopbackTransport();

// Create server identity
const serverAgent = await Agent.quickstart({
  name: 'mcp-server',
  registry,
  transport,
});

// Create standard MCP server
const mcpServer = new Server(
  { name: 'secure-tools', version: '1.0.0' },
  { capabilities: { tools: {} } }
);

// Register tools
mcpServer.setRequestHandler('tools/list', async () => ({
  tools: [
    {
      name: 'get_user_data',
      description: 'Retrieve sensitive user data',
      inputSchema: {
        type: 'object',
        properties: {
          userId: { type: 'string' },
        },
        required: ['userId'],
      },
    },
  ],
}));

mcpServer.setRequestHandler('tools/call', async (request) => {
  if (request.params.name === 'get_user_data') {
    return {
      content: [
        {
          type: 'text',
          text: `User data for ${request.params.arguments.userId}`,
        },
      ],
    };
  }
  throw new Error(`Unknown tool: ${request.params.name}`);
});

// Wrap with identity verification
const adapter = new MCPServerAdapter({
  server: mcpServer,
  agent: serverAgent,
  policyConstraints: {
    allowedCallers: ['did:key:z6Mk...'], // Only allow specific clients
    requireSignatures: true,
    allowedScopes: ['tools:read', 'tools:execute'],
  },
});

// Start the server
const stdio = new StdioServerTransport();
await mcpServer.connect(stdio);
console.log('Secure MCP server running with identity verification');
3

Create a Client with Identity

Connect to the MCP server with cryptographic identity:

client.ts
import { Agent } from '@private.me/xlink';
import { MCPClientAdapter } from '@private.me/mcp-transport';
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';

// Create client identity (using same registry as server)
const clientAgent = await Agent.quickstart({
  name: 'mcp-client',
  registry, // Same registry as server
  transport,
});

// Create standard MCP client
const mcpClient = new Client(
  { name: 'ai-agent', version: '1.0.0' },
  { capabilities: {} }
);

// Wrap with identity layer
const adapter = new MCPClientAdapter({
  client: mcpClient,
  agent: clientAgent,
  serverDID: 'did:key:z6Mk...', // Server's DID from registry
  scope: 'tools:execute',
});

// Connect to server
const stdio = new StdioClientTransport({
  command: 'node',
  args: ['./server.js'],
});

await mcpClient.connect(stdio);
console.log('Connected to secure MCP server');
4

Call Tools with Automatic Verification

Every tool call is cryptographically signed and verified:

Calling tools
// List available tools
const tools = await mcpClient.request(
  { method: 'tools/list' },
  ListToolsResultSchema
);

console.log('Available tools:', tools.tools);
// Available tools: [ { name: 'get_user_data', description: '...' } ]

// Call a tool (automatically signed with client's identity)
const result = await mcpClient.request(
  {
    method: 'tools/call',
    params: {
      name: 'get_user_data',
      arguments: { userId: 'user_123' },
    },
  },
  CallToolResultSchema
);

console.log('Result:', result);
// Result: { content: [ { type: 'text', text: 'User data for user_123' } ] }
5

Add Audit Logging (Optional)

Track all MCP calls with structured audit logs:

Audit logging
import { AuditLogger } from '@private.me/mcp-transport';

// Create audit logger
const auditLogger = new AuditLogger({
  output: './audit.jsonl', // JSONL append-only log
});

// Add to server adapter
const adapter = new MCPServerAdapter({
  server: mcpServer,
  agent: serverAgent,
  auditLogger, // Logs every call
  policyConstraints: {
    allowedCallers: ['did:key:z6Mk...'],
    requireSignatures: true,
  },
});

// Audit log format:
// {"timestamp":"2024-04-28T10:30:00.000Z","caller":"did:key:z6Mk...","method":"tools/call","params":{"name":"get_user_data"},"direction":"inbound","verified":true}
BENEFITS

What You Get

ARCHITECTURE

How It Works

XLinkTransport wraps the MCP protocol with xLink's identity layer. Every JSON-RPC request is signed, verified, and logged before reaching your tool handlers.

Request Flow

  1. Client signs request: MCPClientAdapter wraps the JSON-RPC request in a signed xLink envelope
  2. Transport delivers: Standard MCP transport (stdio, HTTP, SSE) delivers the envelope
  3. Server verifies signature: MCPServerAdapter extracts the caller's DID and verifies the signature using the trust registry
  4. Policy check: PolicyEnforcer validates the caller against allowedCallers, scopes, and capabilities
  5. Audit log: AuditLogger records the call (timestamp, caller, method, params, verification status)
  6. Tool execution: If all checks pass, the request reaches your MCP server's tool handler
  7. Response signing: Server's response is signed and returned to the client
MCP COMPATIBILITY

XLinkTransport is fully compatible with the official @modelcontextprotocol/sdk. It wraps the standard MCP protocol without breaking compatibility — clients and servers that don't use xLink can still communicate using standard MCP transports.

DEPLOYMENT

Production Checklist

NEXT STEPS

Learn More

Explore the full xLink documentation for advanced patterns: