Skip to main content

Model Context Protocol (MCP) Integration Guide

Overview​

The Model Context Protocol (MCP) is an open standard that enables secure, two-way connections between data sources and AI-powered tools. Developed by Anthropic, MCP provides a universal protocol to replace fragmented data integrations and enhance AI system capabilities.

MCP Architecture​

Core Components​

MCP Server​

  • Data Exposure: Exposes data sources through standardized interfaces
  • Security: Implements secure authentication and authorization
  • Transport: Supports stdio, HTTP, and WebSocket transports
  • Tools: Provides callable functions for AI interactions

MCP Client​

  • AI Applications: Connects AI systems to MCP servers
  • Context Management: Maintains conversation context across tools
  • Request Routing: Routes requests to appropriate servers
  • Response Handling: Processes and formats server responses

Protocol Specification​

// MCP message structure
interface MCPMessage {
jsonrpc: "2.0";
id?: string | number;
method?: string;
params?: any;
result?: any;
error?: {
code: number;
message: string;
data?: any;
};
}

// Tool definition
interface Tool {
name: string;
description: string;
inputSchema: {
type: "object";
properties: Record<string, any>;
required?: string[];
};
}

Enterprise MCP Server Implementation​

Government Document Server​

// MCP server for government document access
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';

class GovernmentDocumentServer {
private server: Server;
private documentService: DocumentService;

constructor(documentService: DocumentService) {
this.documentService = documentService;
this.server = new Server({
name: 'government-documents',
version: '1.0.0'
}, {
capabilities: {
tools: {},
resources: {}
}
});

this.setupHandlers();
}

private setupHandlers() {
// List available tools
this.server.setRequestHandler('tools/list', async () => ({
tools: [
{
name: 'search_documents',
description: 'Search government documents by classification and content',
inputSchema: {
type: 'object',
properties: {
query: { type: 'string', description: 'Search query' },
classification: {
type: 'string',
enum: ['public', 'official', 'secret'],
description: 'Document classification level'
},
department: { type: 'string', description: 'Government department' }
},
required: ['query']
}
},
{
name: 'get_document',
description: 'Retrieve specific document by ID',
inputSchema: {
type: 'object',
properties: {
document_id: { type: 'string', description: 'Document identifier' },
access_level: { type: 'string', description: 'Required access level' }
},
required: ['document_id']
}
},
{
name: 'analyze_compliance',
description: 'Analyze document for regulatory compliance',
inputSchema: {
type: 'object',
properties: {
document_id: { type: 'string' },
regulation: {
type: 'string',
enum: ['FISMA', 'GDPR', 'HIPAA', 'SOX'],
description: 'Regulatory framework'
}
},
required: ['document_id', 'regulation']
}
}
]
}));

// Handle tool calls
this.server.setRequestHandler('tools/call', async (request) => {
const { name, arguments: args } = CallToolRequestSchema.parse(request).params;

switch (name) {
case 'search_documents':
return await this.searchDocuments(args);
case 'get_document':
return await this.getDocument(args);
case 'analyze_compliance':
return await this.analyzeCompliance(args);
default:
throw new Error(`Unknown tool: ${name}`);
}
});
}

private async searchDocuments(args: any) {
// Validate user permissions
await this.validateAccess(args.classification);

const results = await this.documentService.search({
query: args.query,
classification: args.classification,
department: args.department
});

return {
content: [{
type: 'text',
text: JSON.stringify(results, null, 2)
}]
};
}

private async getDocument(args: any) {
// Validate access permissions
await this.validateDocumentAccess(args.document_id, args.access_level);

const document = await this.documentService.getById(args.document_id);

if (!document) {
throw new Error(`Document not found: ${args.document_id}`);
}

return {
content: [{
type: 'text',
text: document.content
}]
};
}

private async analyzeCompliance(args: any) {
const document = await this.documentService.getById(args.document_id);
const analysis = await this.documentService.analyzeCompliance(
document,
args.regulation
);

return {
content: [{
type: 'text',
text: JSON.stringify(analysis, null, 2)
}]
};
}

private async validateAccess(classification: string) {
// Implement security validation based on user clearance
const userClearance = await this.getUserClearance();

if (!this.hasRequiredClearance(userClearance, classification)) {
throw new Error('Insufficient clearance for requested classification');
}
}
}

Vector Database MCP Server​

// MCP server for vector database operations
class VectorDatabaseServer {
private server: Server;
private vectorDb: VectorDatabase;

constructor(vectorDb: VectorDatabase) {
this.vectorDb = vectorDb;
this.server = new Server({
name: 'vector-database',
version: '1.0.0'
}, {
capabilities: {
tools: {},
resources: {}
}
});

this.setupHandlers();
}

private setupHandlers() {
this.server.setRequestHandler('tools/list', async () => ({
tools: [
{
name: 'semantic_search',
description: 'Perform semantic search across document embeddings',
inputSchema: {
type: 'object',
properties: {
query: { type: 'string', description: 'Search query' },
collection: { type: 'string', description: 'Vector collection name' },
limit: { type: 'number', description: 'Maximum results', default: 10 },
similarity_threshold: {
type: 'number',
description: 'Minimum similarity score',
minimum: 0,
maximum: 1,
default: 0.7
}
},
required: ['query', 'collection']
}
},
{
name: 'store_embedding',
description: 'Store document embedding in vector database',
inputSchema: {
type: 'object',
properties: {
document_id: { type: 'string' },
embedding: {
type: 'array',
items: { type: 'number' },
description: 'Document embedding vector'
},
metadata: {
type: 'object',
description: 'Document metadata'
},
collection: { type: 'string' }
},
required: ['document_id', 'embedding', 'collection']
}
}
]
}));

this.server.setRequestHandler('tools/call', async (request) => {
const { name, arguments: args } = CallToolRequestSchema.parse(request).params;

switch (name) {
case 'semantic_search':
return await this.performSemanticSearch(args);
case 'store_embedding':
return await this.storeEmbedding(args);
default:
throw new Error(`Unknown tool: ${name}`);
}
});
}

private async performSemanticSearch(args: any) {
const results = await this.vectorDb.search({
query: args.query,
collection: args.collection,
limit: args.limit,
similarityThreshold: args.similarity_threshold
});

return {
content: [{
type: 'text',
text: `Found ${results.length} relevant documents:\n\n` +
results.map((r, i) =>
`${i+1}. [Score: ${r.score.toFixed(3)}] ${r.metadata.title || r.id}\n ${r.metadata.summary || 'No summary available'}`
).join('\n\n')
}]
};
}
}

Drupal MCP Integration​

MCP Registry Module Integration​

<?php
// Drupal service for MCP server management
class MCPServerManager implements MCPServerManagerInterface {

protected $httpClient;
protected $configFactory;
protected $logger;

public function __construct(
ClientInterface $http_client,
ConfigFactoryInterface $config_factory,
LoggerInterface $logger
) {
$this->httpClient = $http_client;
$this->configFactory = $config_factory;
$this->logger = $logger;
}

public function callMCPTool(string $server_id, string $tool_name, array $arguments): array {
$server_config = $this->getServerConfig($server_id);

if (!$server_config) {
throw new \InvalidArgumentException("MCP server not found: {$server_id}");
}

// Prepare MCP request
$request = [
'jsonrpc' => '2.0',
'id' => uniqid(),
'method' => 'tools/call',
'params' => [
'name' => $tool_name,
'arguments' => $arguments
]
];

try {
$response = $this->sendMCPRequest($server_config, $request);

// Log successful call
$this->logger->info('MCP tool call successful', [
'server_id' => $server_id,
'tool_name' => $tool_name,
'arguments' => $arguments
]);

return $response;

} catch (\Exception $e) {
$this->logger->error('MCP tool call failed', [
'server_id' => $server_id,
'tool_name' => $tool_name,
'error' => $e->getMessage()
]);

throw $e;
}
}

private function sendMCPRequest(array $server_config, array $request): array {
switch ($server_config['transport']) {
case 'http':
return $this->sendHttpRequest($server_config, $request);
case 'stdio':
return $this->sendStdioRequest($server_config, $request);
default:
throw new \InvalidArgumentException("Unsupported transport: {$server_config['transport']}");
}
}

private function sendHttpRequest(array $server_config, array $request): array {
$response = $this->httpClient->request('POST', $server_config['url'], [
'json' => $request,
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer ' . $server_config['auth_token'] ?? ''
],
'timeout' => 30
]);

$data = json_decode($response->getBody(), true);

if (isset($data['error'])) {
throw new MCPException($data['error']['message'], $data['error']['code']);
}

return $data['result'] ?? [];
}
}

AI Module MCP Provider​

<?php
// MCP provider for Drupal AI module
class MCPProvider extends ProviderPluginBase {

protected $mcpServerManager;

public function __construct(
array $configuration,
$plugin_id,
$plugin_definition,
MCPServerManagerInterface $mcp_server_manager
) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->mcpServerManager = $mcp_server_manager;
}

public function chat(array $messages, string $model_id): ChatResponseInterface {
// Convert messages to MCP format
$context = $this->prepareChatContext($messages);

// Call MCP server for AI response
$response = $this->mcpServerManager->callMCPTool(
$this->configuration['server_id'],
'generate_response',
[
'messages' => $messages,
'model' => $model_id,
'context' => $context
]
);

return $this->createChatResponse($response);
}

public function generateEmbeddings(array $texts): EmbeddingResponseInterface {
$response = $this->mcpServerManager->callMCPTool(
$this->configuration['server_id'],
'generate_embeddings',
[
'texts' => $texts,
'model' => $this->configuration['embedding_model']
]
);

return $this->createEmbeddingResponse($response);
}
}

Security & Compliance Considerations​

Authentication & Authorization​

// Secure MCP server with JWT authentication
class SecureMCPServer {
private server: Server;
private jwtVerifier: JWTVerifier;

constructor(jwtSecret: string) {
this.jwtVerifier = new JWTVerifier(jwtSecret);
this.server = new Server({
name: 'secure-government-server',
version: '1.0.0'
});

this.setupSecurityMiddleware();
}

private setupSecurityMiddleware() {
// Add authentication middleware
this.server.setRequestHandler('*', async (request, next) => {
const authHeader = request.headers?.authorization;

if (!authHeader?.startsWith('Bearer ')) {
throw new Error('Missing or invalid authorization header');
}

const token = authHeader.substring(7);
const payload = await this.jwtVerifier.verify(token);

// Add user context to request
request.user = {
id: payload.sub,
clearance: payload.clearance,
department: payload.department,
roles: payload.roles
};

return next(request);
});

// Add audit logging
this.server.setRequestHandler('*', async (request, next) => {
const startTime = Date.now();

try {
const result = await next(request);

this.auditLogger.log({
timestamp: new Date().toISOString(),
user_id: request.user?.id,
method: request.method,
success: true,
duration: Date.now() - startTime
});

return result;
} catch (error) {
this.auditLogger.log({
timestamp: new Date().toISOString(),
user_id: request.user?.id,
method: request.method,
success: false,
error: error.message,
duration: Date.now() - startTime
});

throw error;
}
});
}
}

Data Classification & Access Control​

// Data classification middleware
class DataClassificationMiddleware {
private classificationRules: Map<string, ClassificationRule>;

constructor(rules: ClassificationRule[]) {
this.classificationRules = new Map(
rules.map(rule => [rule.pattern, rule])
);
}

async classifyAndAuthorize(request: any, data: any): Promise<boolean> {
// Classify data based on content
const classification = this.classifyData(data);

// Check user authorization
const userClearance = request.user.clearance;

return this.hasAccess(userClearance, classification);
}

private classifyData(data: any): string {
const content = JSON.stringify(data).toLowerCase();

// Check for classified patterns
if (this.containsClassifiedPatterns(content)) {
return 'SECRET';
}

if (this.containsOfficialPatterns(content)) {
return 'OFFICIAL';
}

return 'PUBLIC';
}

private hasAccess(userClearance: string, dataClassification: string): boolean {
const clearanceLevels = ['PUBLIC', 'OFFICIAL', 'SECRET', 'TOP_SECRET'];

const userLevel = clearanceLevels.indexOf(userClearance);
const dataLevel = clearanceLevels.indexOf(dataClassification);

return userLevel >= dataLevel;
}
}

Best Practices​

Server Development​

  1. Security First: Implement authentication and authorization from the start
  2. Error Handling: Comprehensive error handling with appropriate logging
  3. Input Validation: Validate all inputs against schema definitions
  4. Rate Limiting: Implement rate limiting to prevent abuse
  5. Monitoring: Comprehensive monitoring and alerting

Client Integration​

  1. Connection Management: Implement proper connection pooling and retry logic
  2. Context Management: Maintain conversation context efficiently
  3. Error Recovery: Graceful handling of server failures
  4. Caching: Cache responses where appropriate to improve performance

Enterprise Deployment​

  1. Transport Security: Use HTTPS/WSS for all communications
  2. Network Isolation: Deploy servers in secure network segments
  3. Audit Logging: Comprehensive audit trails for compliance
  4. Backup & Recovery: Regular backups of server configurations and data
  5. Monitoring: Real-time monitoring of server health and performance

The Model Context Protocol provides a powerful foundation for integrating AI systems with diverse data sources while maintaining security and compliance requirements essential for government and enterprise deployments.