@codai/romai-mcp
Version:
ROMAI Ultimate MCP Server - All-in-One Enterprise Solution with 26+ Integrated Tools
1,518 lines (1,439 loc) • 72.1 kB
JavaScript
#!/usr/bin/env node
import { Command } from 'commander';
import { randomUUID } from 'crypto';
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
import { loadConfigFromEnv, RomaiCore } from '@codai/romai-core';
import dotenv from 'dotenv';
var EnterpriseLogger = class _EnterpriseLogger {
static instance;
metrics = [];
auditTrail = [];
constructor() {
}
static getInstance() {
if (!_EnterpriseLogger.instance) {
_EnterpriseLogger.instance = new _EnterpriseLogger();
}
return _EnterpriseLogger.instance;
}
/**
* Create a new request context with correlation ID
*/
createRequestContext(method, userId, organizationId) {
return {
requestId: randomUUID(),
userId,
organizationId,
method,
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
source: "mcp-server",
version: "0.2.0"
};
}
/**
* Log MCP request with structured data
*/
logRequest(context, params) {
const logEntry = {
level: "info",
...context,
type: "mcp_request",
params: this.sanitizeParams(params),
message: `MCP Request: ${context.method}`
};
console.log(JSON.stringify(logEntry));
this.recordAuditEvent({
eventId: randomUUID(),
eventType: "request",
severity: "info",
details: { params },
context
});
}
/**
* Log MCP response with performance metrics
*/
logResponse(context, result, duration) {
const logEntry = {
level: "info",
...context,
type: "mcp_response",
result: this.sanitizeResult(result),
duration_ms: duration,
message: `MCP Response: ${context.method} (${duration}ms)`
};
console.log(JSON.stringify(logEntry));
this.recordMetric({
name: "mcp_request_duration",
value: duration,
unit: "ms",
labels: {
method: context.method,
userId: context.userId || "anonymous",
organizationId: context.organizationId || "default"
},
timestamp: (/* @__PURE__ */ new Date()).toISOString()
});
this.recordAuditEvent({
eventId: randomUUID(),
eventType: "response",
severity: "info",
details: { duration, success: true },
context
});
}
/**
* Log error with full context and stack trace
*/
logError(context, error, details) {
const logEntry = {
level: "error",
...context,
type: "mcp_error",
error: {
name: error.name,
message: error.message,
stack: error.stack
},
details: details || {},
message: `MCP Error: ${context.method} - ${error.message}`
};
console.error(JSON.stringify(logEntry));
this.recordMetric({
name: "mcp_request_errors",
value: 1,
unit: "count",
labels: {
method: context.method,
errorType: error.name,
userId: context.userId || "anonymous",
organizationId: context.organizationId || "default"
},
timestamp: (/* @__PURE__ */ new Date()).toISOString()
});
this.recordAuditEvent({
eventId: randomUUID(),
eventType: "error",
severity: "error",
details: { error: error.message, stack: error.stack, ...details },
context
});
}
/**
* Record performance metric for analytics
*/
recordMetric(metric) {
this.metrics.push(metric);
if (this.metrics.length > 1e3) {
this.metrics = this.metrics.slice(-1e3);
}
}
/**
* Record audit event for compliance
*/
recordAuditEvent(event) {
this.auditTrail.push(event);
if (this.auditTrail.length > 500) {
this.auditTrail = this.auditTrail.slice(-500);
}
}
/**
* Get performance analytics
*/
getAnalytics(timeWindow = 36e5) {
const cutoff = new Date(Date.now() - timeWindow);
const recentMetrics = this.metrics.filter((m) => new Date(m.timestamp) > cutoff);
const requestMetrics = recentMetrics.filter((m) => m.name === "mcp_request_duration");
const errorMetrics = recentMetrics.filter((m) => m.name === "mcp_request_errors");
const methodCounts = requestMetrics.reduce((acc, metric) => {
const method = metric.labels.method;
acc[method] = (acc[method] || 0) + 1;
return acc;
}, {});
const topMethods = Object.entries(methodCounts).map(([method, count]) => ({ method, count })).sort((a, b) => b.count - a.count).slice(0, 5);
return {
requestCount: requestMetrics.length,
averageResponseTime: requestMetrics.length > 0 ? requestMetrics.reduce((sum, m) => sum + m.value, 0) / requestMetrics.length : 0,
errorRate: requestMetrics.length > 0 ? errorMetrics.length / requestMetrics.length * 100 : 0,
topMethods,
performanceMetrics: recentMetrics
};
}
/**
* Get audit trail for compliance
*/
getAuditTrail(timeWindow = 36e5) {
const cutoff = new Date(Date.now() - timeWindow);
return this.auditTrail.filter((event) => new Date(event.context.timestamp) > cutoff);
}
/**
* Generate compliance report
*/
generateComplianceReport() {
const last24h = 24 * 60 * 60 * 1e3;
const recentEvents = this.getAuditTrail(last24h);
const totalRequests = recentEvents.filter((e) => e.eventType === "request").length;
const authenticatedRequests = recentEvents.filter(
(e) => e.eventType === "request" && e.context.userId
).length;
const errorEvents = recentEvents.filter((e) => e.eventType === "error").length;
const criticalEvents = recentEvents.filter((e) => e.severity === "critical").length;
return {
totalRequests,
authenticatedRequests,
errorEvents,
criticalEvents,
dataIntegrity: true,
// Enhanced validation in production
auditCoverage: totalRequests > 0 ? recentEvents.length / totalRequests * 100 : 100
};
}
/**
* Sanitize sensitive data from parameters
*/
sanitizeParams(params) {
if (!params || typeof params !== "object") return params;
const sanitized = { ...params };
const sensitiveFields = ["password", "token", "key", "secret", "apiKey"];
for (const field of sensitiveFields) {
if (sanitized[field]) {
sanitized[field] = "[REDACTED]";
}
}
return sanitized;
}
/**
* Sanitize sensitive data from results
*/
sanitizeResult(result) {
if (!result || typeof result !== "object") return result;
const resultStr = JSON.stringify(result);
if (resultStr.length > 1e3) {
return {
_truncated: true,
_size: resultStr.length,
preview: resultStr.substring(0, 200) + "..."
};
}
return result;
}
};
var enterpriseLogger = EnterpriseLogger.getInstance();
// src/monitoring/metrics-collector.ts
var MetricsCollector = class _MetricsCollector {
static instance;
startTime;
requestCount = 0;
errorCount = 0;
lastRequestTime = 0;
constructor() {
this.startTime = Date.now();
}
static getInstance() {
if (!_MetricsCollector.instance) {
_MetricsCollector.instance = new _MetricsCollector();
}
return _MetricsCollector.instance;
}
/**
* Collect system performance metrics
*/
collectSystemMetrics() {
const memoryUsage = process.memoryUsage();
const uptime = process.uptime();
return {
memoryUsage: {
rss: memoryUsage.rss,
heapUsed: memoryUsage.heapUsed,
heapTotal: memoryUsage.heapTotal,
external: memoryUsage.external
},
cpuUsage: process.cpuUsage().user / 1e6,
// Convert to seconds
uptime,
timestamp: (/* @__PURE__ */ new Date()).toISOString()
};
}
/**
* Track request metrics
*/
trackRequest() {
this.requestCount++;
this.lastRequestTime = Date.now();
}
/**
* Track error metrics
*/
trackError() {
this.errorCount++;
}
/**
* Get current performance summary
*/
getPerformanceSummary() {
const uptime = Date.now() - this.startTime;
const requestsPerSecond = this.requestCount / (uptime / 1e3);
const errorRate = this.requestCount > 0 ? this.errorCount / this.requestCount * 100 : 0;
const memoryUsageMB = process.memoryUsage().heapUsed / 1024 / 1024;
let systemHealth = "excellent";
if (errorRate > 10 || memoryUsageMB > 500) {
systemHealth = "critical";
} else if (errorRate > 5 || memoryUsageMB > 200) {
systemHealth = "warning";
} else if (errorRate > 1 || memoryUsageMB > 100) {
systemHealth = "good";
}
return {
uptime,
totalRequests: this.requestCount,
totalErrors: this.errorCount,
errorRate,
requestsPerSecond,
memoryUsageMB,
systemHealth
};
}
/**
* Generate Prometheus-compatible metrics
*/
generatePrometheusMetrics() {
const summary = this.getPerformanceSummary();
const systemMetrics = this.collectSystemMetrics();
return `
# HELP romai_requests_total Total number of MCP requests
# TYPE romai_requests_total counter
romai_requests_total ${summary.totalRequests}
# HELP romai_errors_total Total number of MCP errors
# TYPE romai_errors_total counter
romai_errors_total ${summary.totalErrors}
# HELP romai_request_rate_per_second Current request rate
# TYPE romai_request_rate_per_second gauge
romai_request_rate_per_second ${summary.requestsPerSecond.toFixed(2)}
# HELP romai_error_rate_percent Current error rate percentage
# TYPE romai_error_rate_percent gauge
romai_error_rate_percent ${summary.errorRate.toFixed(2)}
# HELP romai_memory_usage_bytes Current memory usage in bytes
# TYPE romai_memory_usage_bytes gauge
romai_memory_usage_bytes ${systemMetrics.memoryUsage.heapUsed}
# HELP romai_uptime_seconds Server uptime in seconds
# TYPE romai_uptime_seconds gauge
romai_uptime_seconds ${systemMetrics.uptime.toFixed(0)}
# HELP romai_system_health System health status (0=critical, 1=warning, 2=good, 3=excellent)
# TYPE romai_system_health gauge
romai_system_health ${this.getHealthScore(summary.systemHealth)}
`.trim();
}
/**
* Generate OpenTelemetry-compatible metrics
*/
generateOpenTelemetryMetrics() {
const summary = this.getPerformanceSummary();
const systemMetrics = this.collectSystemMetrics();
const timestamp = Date.now();
return [
{
name: "romai_requests_total",
description: "Total number of MCP requests",
unit: "requests",
type: "counter",
value: summary.totalRequests,
labels: { service: "romai-mcp", version: "0.2.0" },
timestamp
},
{
name: "romai_errors_total",
description: "Total number of MCP errors",
unit: "errors",
type: "counter",
value: summary.totalErrors,
labels: { service: "romai-mcp", version: "0.2.0" },
timestamp
},
{
name: "romai_request_duration_seconds",
description: "Request duration in seconds",
unit: "seconds",
type: "histogram",
value: 0,
// Updated per request
labels: { service: "romai-mcp", version: "0.2.0" },
timestamp
},
{
name: "romai_memory_usage_bytes",
description: "Current memory usage in bytes",
unit: "bytes",
type: "gauge",
value: systemMetrics.memoryUsage.heapUsed,
labels: { service: "romai-mcp", version: "0.2.0", type: "heap" },
timestamp
},
{
name: "romai_system_health_score",
description: "System health score",
unit: "score",
type: "gauge",
value: this.getHealthScore(summary.systemHealth),
labels: { service: "romai-mcp", version: "0.2.0" },
timestamp
}
];
}
/**
* Collect business intelligence metrics
*/
collectBusinessMetrics(activeUsers = 0, organizationsCount = 1) {
const summary = this.getPerformanceSummary();
return {
activeUsers,
organizationsCount,
requestsPerSecond: summary.requestsPerSecond,
revenueMetrics: {
dailyActiveUsers: activeUsers,
monthlyActiveUsers: activeUsers,
// Enhanced in production
apiCallsUsed: summary.totalRequests,
quotaUtilization: 0
// Calculated based on plan limits
},
timestamp: (/* @__PURE__ */ new Date()).toISOString()
};
}
/**
* Generate health score from status
*/
getHealthScore(health) {
switch (health) {
case "excellent":
return 3;
case "good":
return 2;
case "warning":
return 1;
case "critical":
return 0;
default:
return 0;
}
}
/**
* Reset metrics (for testing)
*/
reset() {
this.requestCount = 0;
this.errorCount = 0;
this.startTime = Date.now();
}
};
var metricsCollector = MetricsCollector.getInstance();
// src/monitoring/request-tracer.ts
var RequestTracer = class _RequestTracer {
static instance;
activeTraces = /* @__PURE__ */ new Map();
completedTraces = [];
constructor() {
}
static getInstance() {
if (!_RequestTracer.instance) {
_RequestTracer.instance = new _RequestTracer();
}
return _RequestTracer.instance;
}
/**
* Start tracing a new request
*/
startTrace(method, params, userId, organizationId) {
const context = enterpriseLogger.createRequestContext(method, userId, organizationId);
const trace = {
requestId: context.requestId,
method,
startTime: Date.now(),
status: "pending",
userId,
organizationId,
metadata: {
params: this.sanitizeForTrace(params),
userAgent: "Claude Desktop MCP",
serverVersion: "0.2.0"
}
};
this.activeTraces.set(context.requestId, trace);
enterpriseLogger.logRequest(context, params);
metricsCollector.trackRequest();
return context;
}
/**
* Complete a request trace with success
*/
completeTrace(requestId, result) {
const trace = this.activeTraces.get(requestId);
if (!trace) return;
const endTime = Date.now();
const duration = endTime - trace.startTime;
trace.endTime = endTime;
trace.duration = duration;
trace.status = "completed";
trace.metadata.result = this.sanitizeForTrace(result);
this.activeTraces.delete(requestId);
this.completedTraces.push(trace);
if (this.completedTraces.length > 1e3) {
this.completedTraces = this.completedTraces.slice(-1e3);
}
const context = this.createContextFromTrace(trace);
enterpriseLogger.logResponse(context, result, duration);
}
/**
* Fail a request trace with error
*/
failTrace(requestId, error, details) {
const trace = this.activeTraces.get(requestId);
if (!trace) return;
const endTime = Date.now();
const duration = endTime - trace.startTime;
trace.endTime = endTime;
trace.duration = duration;
trace.status = "failed";
trace.metadata.error = {
name: error.name,
message: error.message,
stack: error.stack
};
trace.metadata.errorDetails = details;
this.activeTraces.delete(requestId);
this.completedTraces.push(trace);
if (this.completedTraces.length > 1e3) {
this.completedTraces = this.completedTraces.slice(-1e3);
}
const context = this.createContextFromTrace(trace);
enterpriseLogger.logError(context, error, details);
metricsCollector.trackError();
}
/**
* Get active traces for monitoring
*/
getActiveTraces() {
return Array.from(this.activeTraces.values());
}
/**
* Get completed traces for analysis
*/
getCompletedTraces(limit = 100) {
return this.completedTraces.slice(-limit);
}
/**
* Get performance statistics
*/
getPerformanceStats(timeWindow = 36e5) {
const cutoff = Date.now() - timeWindow;
const recentTraces = this.completedTraces.filter((t) => (t.endTime || 0) > cutoff);
const successfulRequests = recentTraces.filter((t) => t.status === "completed").length;
const failedRequests = recentTraces.filter((t) => t.status === "failed").length;
const totalRequests = recentTraces.length;
const durations = recentTraces.filter((t) => t.duration !== void 0).map((t) => t.duration).sort((a, b) => a - b);
const averageResponseTime = durations.length > 0 ? durations.reduce((sum, d) => sum + d, 0) / durations.length : 0;
const p95Index = Math.floor(durations.length * 0.95);
const p99Index = Math.floor(durations.length * 0.99);
const p95ResponseTime = durations[p95Index] || 0;
const p99ResponseTime = durations[p99Index] || 0;
const requestsPerMinute = totalRequests / (timeWindow / 1e3) * 60;
const methodStats = {};
recentTraces.forEach((trace) => {
if (trace.duration) {
if (!methodStats[trace.method]) {
methodStats[trace.method] = { totalTime: 0, count: 0 };
}
methodStats[trace.method].totalTime += trace.duration;
methodStats[trace.method].count += 1;
}
});
const topSlowMethods = Object.entries(methodStats).map(([method, stats]) => ({
method,
averageTime: stats.totalTime / stats.count,
count: stats.count
})).sort((a, b) => b.averageTime - a.averageTime).slice(0, 5);
return {
totalRequests,
successfulRequests,
failedRequests,
averageResponseTime,
p95ResponseTime,
p99ResponseTime,
requestsPerMinute,
topSlowMethods
};
}
/**
* Get detailed trace by request ID
*/
getTraceById(requestId) {
return this.activeTraces.get(requestId) || this.completedTraces.find((t) => t.requestId === requestId);
}
/**
* Clean up old traces to prevent memory leaks
*/
cleanup() {
const cutoff = Date.now() - 24 * 60 * 60 * 1e3;
this.completedTraces = this.completedTraces.filter((t) => (t.endTime || 0) > cutoff);
const staleCutoff = Date.now() - 60 * 60 * 1e3;
for (const [requestId, trace] of this.activeTraces.entries()) {
if (trace.startTime < staleCutoff) {
trace.status = "failed";
trace.endTime = Date.now();
trace.duration = trace.endTime - trace.startTime;
trace.metadata.error = { message: "Request timeout - cleaned up by system" };
this.completedTraces.push(trace);
this.activeTraces.delete(requestId);
}
}
}
/**
* Create log context from trace
*/
createContextFromTrace(trace) {
return {
requestId: trace.requestId,
userId: trace.userId,
organizationId: trace.organizationId,
method: trace.method,
timestamp: new Date(trace.startTime).toISOString(),
source: "mcp-server",
version: "0.2.0"
};
}
/**
* Sanitize data for tracing (remove sensitive info)
*/
sanitizeForTrace(data) {
if (!data || typeof data !== "object") return data;
const sanitized = { ...data };
const sensitiveFields = ["password", "token", "key", "secret", "apiKey"];
for (const field of sensitiveFields) {
if (sanitized[field]) {
sanitized[field] = "[REDACTED]";
}
}
const dataStr = JSON.stringify(sanitized);
if (dataStr.length > 500) {
return {
_truncated: true,
_size: dataStr.length,
preview: JSON.parse(dataStr.substring(0, 200) + "}")
};
}
return sanitized;
}
};
var requestTracer = RequestTracer.getInstance();
var RomaiMcpServerEnhanced = class {
server;
romaiCore;
constructor() {
this.server = new Server(
{
name: "romai-mcp-enhanced",
version: "0.2.0"
},
{
capabilities: {
tools: {},
resources: {},
prompts: {}
}
}
);
const config = loadConfigFromEnv();
this.romaiCore = new RomaiCore(config);
this.setupToolHandlers();
this.setupResourceHandlers();
this.setupPromptHandlers();
this.setupErrorHandling();
}
setupResourceHandlers() {
this.server.setRequestHandler(ListResourcesRequestSchema, async () => {
return {
resources: [
{
uri: "romai://romania/business-guide",
name: "Romanian Business Guide",
description: "Comprehensive guide for doing business in Romania",
mimeType: "text/markdown"
},
{
uri: "romai://romania/cultural-insights",
name: "Romanian Cultural Insights",
description: "Cultural context and etiquette for Romanian business",
mimeType: "text/markdown"
},
{
uri: "romai://romania/legal-framework",
name: "Romanian Legal Framework",
description: "Overview of Romanian business law and regulations",
mimeType: "text/markdown"
},
{
uri: "romai://templates/business-email-ro",
name: "Romanian Business Email Templates",
description: "Professional email templates in Romanian",
mimeType: "text/markdown"
},
{
uri: "romai://data/market-analysis",
name: "Romanian Market Analysis Data",
description: "Current market trends and analysis for Romania",
mimeType: "application/json"
}
]
};
});
this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
const { uri } = request.params;
switch (uri) {
case "romai://romania/business-guide":
return {
contents: [
{
uri,
mimeType: "text/markdown",
text: await this.getBusinessGuideContent()
}
]
};
case "romai://romania/cultural-insights":
return {
contents: [
{
uri,
mimeType: "text/markdown",
text: await this.getCulturalInsightsContent()
}
]
};
case "romai://romania/legal-framework":
return {
contents: [
{
uri,
mimeType: "text/markdown",
text: await this.getLegalFrameworkContent()
}
]
};
case "romai://templates/business-email-ro":
return {
contents: [
{
uri,
mimeType: "text/markdown",
text: await this.getEmailTemplatesContent()
}
]
};
case "romai://data/market-analysis":
return {
contents: [
{
uri,
mimeType: "application/json",
text: JSON.stringify(await this.getMarketAnalysisData(), null, 2)
}
]
};
default:
throw new Error(`Resource not found: ${uri}`);
}
});
}
setupPromptHandlers() {
this.server.setRequestHandler(ListPromptsRequestSchema, async () => {
return {
prompts: [
{
name: "romanian-business-analysis",
description: "Analyze business opportunities in Romanian market",
arguments: [
{
name: "industry",
description: "Industry sector to analyze",
required: true
},
{
name: "target_market",
description: "Target market segment",
required: false
}
]
},
{
name: "cultural-adaptation-strategy",
description: "Develop strategy for cultural adaptation in Romania",
arguments: [
{
name: "business_type",
description: "Type of business or service",
required: true
},
{
name: "origin_country",
description: "Country of origin for the business",
required: false
}
]
},
{
name: "romanian-customer-persona",
description: "Create detailed Romanian customer personas",
arguments: [
{
name: "product_category",
description: "Product or service category",
required: true
},
{
name: "region",
description: "Romanian region (Bucharest, Cluj, Timisoara, etc.)",
required: false
}
]
},
{
name: "romanian-marketing-strategy",
description: "Develop marketing strategy for Romanian market",
arguments: [
{
name: "campaign_type",
description: "Type of marketing campaign",
required: true
},
{
name: "budget_range",
description: "Budget range for the campaign",
required: false
}
]
},
{
name: "legal-compliance-checklist",
description: "Generate compliance checklist for Romanian business operations",
arguments: [
{
name: "business_activity",
description: "Primary business activity",
required: true
},
{
name: "company_size",
description: "Company size (startup, SME, enterprise)",
required: false
}
]
}
]
};
});
this.server.setRequestHandler(GetPromptRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
switch (name) {
case "romanian-business-analysis":
return {
description: "Comprehensive Romanian business market analysis",
messages: [
{
role: "user",
content: {
type: "text",
text: await this.generateBusinessAnalysisPrompt(args)
}
}
]
};
case "cultural-adaptation-strategy":
return {
description: "Romanian cultural adaptation strategy development",
messages: [
{
role: "user",
content: {
type: "text",
text: await this.generateCulturalAdaptationPrompt(args)
}
}
]
};
case "romanian-customer-persona":
return {
description: "Detailed Romanian customer persona creation",
messages: [
{
role: "user",
content: {
type: "text",
text: await this.generateCustomerPersonaPrompt(args)
}
}
]
};
case "romanian-marketing-strategy":
return {
description: "Romanian market-specific marketing strategy",
messages: [
{
role: "user",
content: {
type: "text",
text: await this.generateMarketingStrategyPrompt(args)
}
}
]
};
case "legal-compliance-checklist":
return {
description: "Romanian legal compliance checklist",
messages: [
{
role: "user",
content: {
type: "text",
text: await this.generateComplianceChecklistPrompt(args)
}
}
]
};
default:
throw new Error(`Prompt not found: ${name}`);
}
});
}
setupToolHandlers() {
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "romai_intelligence",
description: "Ask ROMAI for intelligent analysis and problem-solving in Romanian or English",
inputSchema: {
type: "object",
properties: {
query: {
type: "string",
description: "The question or problem to analyze"
},
language: {
type: "string",
enum: ["ro", "en"],
description: "Language for the response (Romanian or English)",
default: "ro"
},
domain: {
type: "string",
description: "Domain context (e.g., technology, business, science)",
default: "general"
},
context: {
type: "string",
description: "Additional context for the query"
}
},
required: ["query"]
}
},
{
name: "romai_romanian_expert",
description: "Get expert advice on Romanian culture, language, business, and local context",
inputSchema: {
type: "object",
properties: {
query: {
type: "string",
description: "Your question about Romania"
},
category: {
type: "string",
enum: [
"culture",
"business",
"language",
"history",
"travel",
"legal",
"education"
],
description: "Category of Romanian expertise needed",
default: "general"
}
},
required: ["query"]
}
},
{
name: "romai_problem_solver",
description: "General problem-solving with step-by-step analysis and practical solutions",
inputSchema: {
type: "object",
properties: {
problem: {
type: "string",
description: "The problem to solve"
},
constraints: {
type: "string",
description: "Any constraints or limitations"
},
goals: {
type: "string",
description: "Desired outcomes or goals"
},
language: {
type: "string",
enum: ["ro", "en"],
description: "Response language",
default: "ro"
}
},
required: ["problem"]
}
},
{
name: "romai_code_assistant",
description: "Romanian-first coding assistant for programming help and code generation",
inputSchema: {
type: "object",
properties: {
request: {
type: "string",
description: "Your coding question or request"
},
language: {
type: "string",
description: "Programming language (e.g., JavaScript, Python, TypeScript)"
},
framework: {
type: "string",
description: "Framework or library context"
},
explain_in: {
type: "string",
enum: ["ro", "en"],
description: "Language for explanations",
default: "ro"
}
},
required: ["request"]
}
},
{
name: "romai_health_check",
description: "Check the health status of ROMAI services",
inputSchema: {
type: "object",
properties: {}
}
},
// New enterprise tools
{
name: "romai_market_intelligence",
description: "Advanced Romanian market intelligence and competitive analysis",
inputSchema: {
type: "object",
properties: {
industry: {
type: "string",
description: "Industry sector for analysis"
},
region: {
type: "string",
description: "Specific Romanian region or nationwide",
default: "nationwide"
},
analysis_type: {
type: "string",
enum: ["competitive", "market_size", "trends", "opportunities", "risks"],
description: "Type of market analysis",
default: "comprehensive"
},
time_horizon: {
type: "string",
enum: ["current", "6_months", "1_year", "3_years"],
description: "Analysis time horizon",
default: "current"
}
},
required: ["industry"]
}
},
{
name: "romai_regulatory_advisor",
description: "Romanian regulatory and compliance guidance",
inputSchema: {
type: "object",
properties: {
business_type: {
type: "string",
description: "Type of business or industry"
},
regulation_area: {
type: "string",
enum: ["company_formation", "tax", "employment", "data_privacy", "industry_specific"],
description: "Area of regulatory guidance needed"
},
company_size: {
type: "string",
enum: ["startup", "sme", "enterprise"],
description: "Company size category",
default: "sme"
}
},
required: ["business_type", "regulation_area"]
}
}
]
};
});
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (!request.params) {
throw new Error("Request params are undefined");
}
const { name, arguments: args } = request.params;
try {
switch (name) {
case "romai_intelligence":
return await this.handleIntelligenceRequest(args);
case "romai_romanian_expert":
return await this.handleRomanianExpertRequest(args);
case "romai_problem_solver":
return await this.handleProblemSolverRequest(args);
case "romai_code_assistant":
return await this.handleCodeAssistantRequest(args);
case "romai_health_check":
return await this.handleHealthCheck(args);
case "romai_market_intelligence":
return await this.handleMarketIntelligenceRequest(args);
case "romai_regulatory_advisor":
return await this.handleRegulatoryAdvisorRequest(args);
default:
return {
content: [
{
type: "text",
text: `Unknown tool: ${name}`
}
],
isError: true
};
}
} catch (error) {
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
return {
content: [
{
type: "text",
text: `Error executing tool ${name}: ${errorMessage}`
}
],
isError: true
};
}
});
}
// Resource content generators
async getBusinessGuideContent() {
return `# Romanian Business Guide
## Executive Summary
This comprehensive guide provides essential information for international businesses entering the Romanian market.
## Key Business Insights
- GDP: \u20AC250+ billion (2024)
- EU Member since 2007
- Strategic location between Western Europe and Asia
- Growing tech and services sectors
- Skilled multilingual workforce
## Market Entry Strategies
1. **Direct Investment**: Establish local presence
2. **Joint Ventures**: Partner with Romanian companies
3. **Licensing**: License products/services to local partners
4. **Acquisition**: Acquire existing Romanian businesses
## Business Culture
- **Relationship-focused**: Personal connections matter
- **Formal communication**: Professional titles and formal address
- **Punctuality**: Being on time is highly valued
- **Decision-making**: Often hierarchical, involving senior management
## Key Industries
- **Technology**: Software development, IT services
- **Manufacturing**: Automotive, textiles, machinery
- **Energy**: Renewable energy, oil & gas
- **Agriculture**: Grains, wine, organic products
- **Tourism**: Mountain resorts, coastal destinations
## Legal Considerations
- Romanian Commercial Code governs business operations
- EU regulations apply (GDPR, competition law)
- Corporate tax rate: 16%
- VAT rate: 19%
- Employment law protections for workers
## Success Factors
1. Understand local market preferences
2. Build strong relationships with partners
3. Comply with EU and Romanian regulations
4. Invest in local talent and training
5. Adapt products/services to local needs`;
}
async getCulturalInsightsContent() {
return `# Romanian Cultural Insights for Business
## Communication Style
- **Directness**: Romanians appreciate honest, straightforward communication
- **Formality**: Use formal titles and "Dumneavoastr\u0103" (formal you) in business
- **Language**: Many professionals speak English, but Romanian language skills are valued
- **Non-verbal**: Firm handshakes, maintaining eye contact shows respect
## Business Etiquette
- **Meetings**: Start with small talk, but transition to business promptly
- **Dress Code**: Conservative, professional attire expected
- **Gifts**: Modest business gifts are appreciated but not required
- **Dining**: Business lunches common, wait for host to begin eating
## Religious and Social Considerations
- **Orthodox Christianity**: Majority religion, respect religious holidays
- **Family Values**: Family is central to Romanian culture
- **National Pride**: Romanians are proud of their history and culture
- **Regional Differences**: Urban vs. rural cultural variations
## Holiday Calendar
- **New Year**: January 1-2
- **Epiphany**: January 6
- **Easter**: Orthodox Easter (varies)
- **Labor Day**: May 1
- **Children's Day**: June 1
- **Assumption**: August 15
- **St. Andrew's Day**: November 30
- **National Day**: December 1
- **Christmas**: December 25-26
## Business Relationship Building
1. **Personal Connection**: Invest time in getting to know partners
2. **Trust Building**: Consistency and reliability are crucial
3. **Long-term Perspective**: Focus on sustainable partnerships
4. **Local Presence**: Having local representatives shows commitment
5. **Cultural Sensitivity**: Show interest in Romanian culture and history`;
}
async getLegalFrameworkContent() {
return `# Romanian Legal Framework for Business
## Company Formation
### Legal Entities
- **SRL (Societate cu R\u0103spundere Limitat\u0103)**: Limited Liability Company
- **SA (Societate pe Ac\u021Biuni)**: Joint Stock Company
- **Branch Office**: Foreign company representative office
- **Representative Office**: Liaison office (no commercial activity)
### Registration Requirements
- Minimum share capital: RON 200 for SRL, RON 90,000 for SA
- Registration with Trade Register (ONRC)
- Tax registration with ANAF
- Social security registration
- Bank account opening
## Tax System
### Corporate Taxation
- **Corporate Income Tax**: 16%
- **Micro-enterprise Tax**: 1% of turnover (for eligible small companies)
- **Dividend Tax**: 5% (EU residents), 16% (non-EU)
- **Transfer Pricing**: Arm's length principle applies
### VAT System
- **Standard Rate**: 19%
- **Reduced Rates**: 9% (certain foods, books), 5% (medicines, hotels)
- **VAT Registration**: Mandatory if turnover exceeds RON 300,000
- **EU VAT**: Reverse charge mechanism applies
## Employment Law
### Worker Rights
- **Working Hours**: Maximum 40 hours/week
- **Minimum Wage**: Updated annually by government
- **Annual Leave**: Minimum 20 working days
- **Maternity Leave**: 126 days paid leave
- **Notice Period**: 20 working days standard
### Employer Obligations
- Social security contributions: ~25-30% of gross salary
- Health insurance: Mandatory coverage
- Work safety: Compliance with EU standards
- Collective bargaining: Recognize trade unions
## Data Protection
### GDPR Compliance
- **Data Processing**: Lawful basis required
- **Consent**: Clear and unambiguous
- **Data Subjects Rights**: Access, rectification, erasure
- **Data Breaches**: 72-hour notification requirement
- **DPO**: Required for certain activities
## Intellectual Property
### Protection Mechanisms
- **Trademarks**: Registration with OSIM
- **Patents**: National and European patents
- **Copyright**: Automatic protection
- **Industrial Designs**: Registration available
- **Trade Secrets**: Protected under law
## Dispute Resolution
### Court System
- **First Instance Courts**: Local jurisdiction
- **Appeal Courts**: Regional jurisdiction
- **High Court**: Supreme court of appeals
- **Administrative Courts**: Public law disputes
### Alternative Dispute Resolution
- **Arbitration**: Recognized and enforceable
- **Mediation**: Encouraged for commercial disputes
- **Conciliation**: Available for labor disputes`;
}
async getEmailTemplatesContent() {
return `# Romanian Business Email Templates
## Formal Business Introduction
**Subject**: Introducere oficial\u0103 - [Company Name]
Stimate Domnule/Stimat\u0103 Doamn\u0103 [Last Name],
Numele meu este [Your Name] \u0219i reprezint compania [Company Name]. V\u0103 contactez \xEEn leg\u0103tur\u0103 cu [specific purpose/opportunity].
[Company Name] este specializat\u0103 \xEEn [brief company description] \u0219i am identificat o poten\u021Bial\u0103 colaborare cu organiza\u021Bia dumneavoastr\u0103.
A\u0219 aprecia posibilitatea unei \xEEnt\xE2lniri pentru a discuta aceast\u0103 oportunitate \xEEn detaliu. Sunt disponibil/disponibil\u0103 \xEEn [time period] \u0219i pot s\u0103 m\u0103 adaptez programului dumneavoastr\u0103.
V\u0103 mul\u021Bumesc pentru timpul acordat \u0219i a\u0219tept cu interes r\u0103spunsul dumneavoastr\u0103.
Cu stim\u0103,
[Your Name]
[Title]
[Company Name]
[Contact Information]
---
## Meeting Request
**Subject**: Solicitare \xEEnt\xE2lnire - Oportunitate de colaborare
Stima\u021Bi Domni,
Sper c\u0103 acest email v\u0103 g\u0103se\u0219te \xEEn cea mai bun\u0103 s\u0103n\u0103tate.
Doresc s\u0103 solicit o \xEEnt\xE2lnire pentru a discuta o propunere de colaborare care ar putea fi benefic\u0103 pentru ambele organiza\u021Bii.
Punctele principale de discu\u021Bie ar include:
- [Point 1]
- [Point 2]
- [Point 3]
Sunt flexibil/flexibil\u0103 \xEEn privin\u021Ba datei \u0219i orei \xEEnt\xE2lnirii. Putem organiza \xEEnt\xE2lnirea la sediul dumneavoastr\u0103, la biroul nostru, sau online, conform preferin\u021Belor dumneavoastr\u0103.
V\u0103 mul\u021Bumesc anticipat pentru considera\u021Bia acordat\u0103 solicit\u0103rii mele.
Cu respect,
[Your Name]
---
## Follow-up After Meeting
**Subject**: Mul\u021Bumiri pentru \xEEnt\xE2lnire \u0219i pa\u0219i urm\u0103tori
Stimate Domnule/Stimat\u0103 Doamn\u0103 [Name],
V\u0103 mul\u021Bumesc pentru timpul acordat \xEEn \xEEnt\xE2lnirea de azi. A fost o pl\u0103cere s\u0103 discut despre [meeting topic] \u0219i s\u0103 aflu mai multe despre [their company/projects].
Conform discu\u021Biilor noastre, voi:
- [Action item 1]
- [Action item 2]
- [Action item 3]
V\u0103 voi trimite [specific deliverable] p\xE2n\u0103 \xEEn data de [date].
Dac\u0103 ave\u021Bi \xEEntreb\u0103ri suplimentare sau ave\u021Bi nevoie de clarific\u0103ri, v\u0103 rog s\u0103 nu ezita\u021Bi s\u0103 m\u0103 contacta\u021Bi.
A\u0219tept cu interes continuarea colabor\u0103rii noastre.
Cu stim\u0103,
[Your Name]
---
## Project Proposal
**Subject**: Propunere de proiect - [Project Name]
Stima\u021Bi Domni,
Anexat la acest email ve\u021Bi g\u0103si propunerea detaliat\u0103 pentru proiectul [Project Name] despre care am discutat.
Propunerea include:
- Obiectivele proiectului
- Metodologia propus\u0103
- Cronograma de implementare
- Bugetul detaliat
- Echipa proiectului
Suntem convin\u0219i c\u0103 aceast\u0103 abordare va aduce beneficii semnificative organiza\u021Biei dumneavoastr\u0103 \u0219i suntem dornici s\u0103 \xEEncepem colaborarea.
Pentru orice clarific\u0103ri sau modific\u0103ri, sunt la dispozi\u021Bia dumneavoastr\u0103.
Cu respect,
[Your Name]
---
## Thank You Note
**Subject**: Mul\u021Bumiri pentru colaborare
Stimate colaboratori,
Prin acest email doresc s\u0103 v\u0103 mul\u021Bumesc pentru excelenta colaborare pe parcursul proiectului [Project Name].
Profesionalismul \u0219i dedicarea echipei dumneavoastr\u0103 au contribuit semnificativ la succesul acestui proiect. Rezultatele ob\u021Binute dep\u0103\u0219esc a\u0219tept\u0103rile ini\u021Biale.
Sper ca aceast\u0103 colaborare s\u0103 fie primul pas \xEEntr-un parteneriat de lung\u0103 durat\u0103 \xEEntre organiza\u021Biile noastre.
Cu recuno\u0219tin\u021B\u0103,
[Your Name]`;
}
async getMarketAnalysisData() {
return {
"market_overview": {
"gdp_2024": "\u20AC250.8 billion",
"gdp_growth_rate": "3.8%",
"population": "19.1 million",
"unemployment_rate": "5.2%",
"inflation_rate": "4.1%"
},
"key_sectors": {
"technology": {
"market_size": "\u20AC12.5 billion",
"growth_rate": "15.2%",
"key_players": ["UiPath", "eMAG", "Zitec", "Siveco"],
"opportunities": ["AI/ML", "Fintech", "E-commerce", "Cybersecurity"]
},
"manufacturing": {
"market_size": "\u20AC45.3 billion",
"growth_rate": "6.8%",
"key_players": ["Dacia", "Continental", "Michelin", "Pirelli"],
"opportunities": ["Automotive", "Electronics", "Textiles"]
},
"energy": {
"market_size": "\u20AC18.7 billion",
"growth_rate": "8.9%",
"key_players": ["Hidroelectrica", "OMV Petrom", "E.ON"],
"opportunities": ["Renewable energy", "Smart grid", "Energy storage"]
}
},
"regional_analysis": {
"bucuresti": {
"population": "2.15 million",
"gdp_per_capita": "\u20AC23,500",
"key_industries": ["Finance", "Technology", "Services"],
"business_environment": "Excellent"
},
"cluj_napoca": {
"population": "0.42 million",
"gdp_per_capita": "\u20AC19,800",
"key_industries": ["Technology", "Manufacturing", "Education"],
"business_environment": "Very Good"
},
"timisoara": {
"population": "0.38 million",
"gdp_per_capita": "\u20AC18,200",
"key_industries": ["Automotive", "Technology", "Manufacturing"],
"business_environment": "Good"
}
},
"investment_climate": {
"ease_of_doing_business": "Rank 55/190 globally",
"corruption_perception": "Rank 69/180 globally",
"competitiveness": "Rank 51/141 globally",
"innovation_index": "Rank 42/132 globally"
},
"market_trends": {
"digitalization": "Accelerating across all sectors",
"sustainability": "Growing focus on green initiatives",
"urbanization": "Continued migration to major cities",
"eu_integration": "Deeper integration with EU markets"
}
};
}
// Prompt generators
async generateBusinessAnalysisPrompt(args) {
const { industry, target_market = "general" } = args;
return `Ca expert \xEEn pia\u021Ba rom\xE2neasc\u0103, analizeaz\u0103 oportunit\u0103\u021Bile de business \xEEn industria "${industry}" pentru segmentul "${target_market}".
Include\u021Bi \xEEn analiz\u0103:
1. **Dimensiunea \u0219i cre\u0219terea pie\u021Bei**
- Valoarea actual\u0103 a pie\u021Bei \xEEn Rom\xE2nia
- Rata de cre\u0219tere anual\u0103 proiectat\u0103
- Factori care influen\u021Beaz\u0103 cre\u0219terea
2. **Analiza competi\u021Biei**
- Juc\u0103tori principali pe pia\u021B\u0103
- Punctele lor forte \u0219i sl\u0103biciuni
- Cotele de pia\u021B\u0103
- Strategiile predominante
3. **Analiza clien\u021Bilor**
- Profilul clientului \u021Bint\u0103 rom\xE2nesc
- Comportamentul de cump\u0103rare
- Preferin\u021Bele specifice pie\u021Bei rom\xE2ne\u0219ti
- Sensibilitatea la pre\u021B
4. **Oportunit\u0103\u021Bi de pia\u021B\u0103**
- Segmente neacoperite sau subacoperite
- Tendin\u021Be emergente
- Nevoi nesatisf\u0103cute ale clien\u021Bilor
- Avantaje competitive poten\u021Biale
5. **Riscuri \u0219i provoc\u0103ri**
- Bariere de intrare pe pia\u021B\u0103
- Riscuri regulatory sau legislative
- Volatilitatea economic\u0103
- Competi\u021Bia interna\u021Bional\u0103
6. **Recomand\u0103ri strategice**
- Strategia optim\u0103 de intrare pe pia\u021B\u0103
- Pozi\u021Bionarea recomandat\u0103
- Investi\u021Biile necesare
- Cronograma de implementare
Folose\u0219te date actuale despre economia rom\xE2neas