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β
- Security First: Implement authentication and authorization from the start
- Error Handling: Comprehensive error handling with appropriate logging
- Input Validation: Validate all inputs against schema definitions
- Rate Limiting: Implement rate limiting to prevent abuse
- Monitoring: Comprehensive monitoring and alerting
Client Integrationβ
- Connection Management: Implement proper connection pooling and retry logic
- Context Management: Maintain conversation context efficiently
- Error Recovery: Graceful handling of server failures
- Caching: Cache responses where appropriate to improve performance
Enterprise Deploymentβ
- Transport Security: Use HTTPS/WSS for all communications
- Network Isolation: Deploy servers in secure network segments
- Audit Logging: Comprehensive audit trails for compliance
- Backup & Recovery: Regular backups of server configurations and data
- 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.