optimus-mcp-client
Version:
Optimus Security MCP Client - TypeScript implementation
229 lines • 10.6 kB
JavaScript
import { FastMCP } from 'fastmcp';
import { z } from 'zod';
import * as fs from 'node:fs';
import * as path from 'node:path';
import * as crypto from 'node:crypto';
import stringify from 'json-stable-stringify';
export class OptimusSecurityTool {
loadEnvFile() {
const envVars = {};
// Try to find the environment file in common locations
const possiblePaths = [
path.join(process.cwd(), 'optimus.env'),
path.join(process.cwd(), '..', 'optimus.env'),
path.join(process.cwd(), '..', '..', 'optimus.env')
];
let envPath = null;
for (const tryPath of possiblePaths) {
if (fs.existsSync(tryPath)) {
envPath = tryPath;
break;
}
}
if (envPath) {
const content = fs.readFileSync(envPath, 'utf8');
const lines = content.split('\n');
for (const line of lines) {
const trimmedLine = line.trim();
if (trimmedLine.startsWith('#') || !trimmedLine || !trimmedLine.includes('=')) {
continue;
}
const [key, ...valueParts] = trimmedLine.split('=');
const value = valueParts.join('=');
envVars[key] = value;
}
}
else {
throw new Error(`No optimus.env file found. Tried: ${possiblePaths.join(', ')}`);
}
return envVars;
}
getOptimusSecurityEndpoint() {
const envVars = this.loadEnvFile();
const endpoint = envVars['OPTIMUS_ENDPOINT'];
if (!endpoint) {
throw new Error('OPTIMUS_ENDPOINT not found in optimus.env file');
}
return endpoint;
}
getAuthCredentials() {
// Use EXACT same environment loading as generate_curl.py
const envVars = this.loadEnvFile();
const keyId = envVars['OPTIMUS_KEY_ID'];
const token = envVars['OPTIMUS_TOKEN'];
if (!keyId || !token) {
throw new Error('Missing required credentials in environment file');
}
return { keyId, token };
}
createRequestSignature(data, token, timestamp) {
try {
// Create canonical request with compact formatting - EXACTLY like Python's json.dumps(payload, sort_keys=True, separators=(',', ':'))
// Use json-stable-stringify with compact formatting to match Python's separators=(',', ':')
const canonicalRequest = stringify(data, { space: '' }) || '';
// Escape Unicode characters like Python does - apply to the entire string
const escapedRequest = canonicalRequest.replace(/[^\x00-\x7F]/g, (char) => {
// Escape Unicode characters like Python does
return '\\u' + ('0000' + char.charCodeAt(0).toString(16)).slice(-4);
});
// String to sign includes timestamp and request body - EXACTLY like Python's f"{timestamp}:{json.dumps(payload, sort_keys=True, separators=(',', ':'))}"
const stringToSign = `${timestamp}:${escapedRequest}`;
// Create HMAC signature - EXACTLY like Python's hmac.new()
const signature = crypto
.createHmac('sha256', token)
.update(stringToSign)
.digest('hex');
return signature;
}
catch (e) {
throw new Error(`Error creating signature: ${e}`);
}
}
prepareWorkingContext(workingContext) {
try {
const parsed = JSON.parse(workingContext);
return parsed; // Return the parsed object, not a string
}
catch {
return {}; // Return empty object, not string
}
}
extractOptimusParams(input) {
// Use dynamic parameters including working_context and version_control
// Keep both in their original string format for signature generation
return {
"text": input.text,
"reason_for_use": input.reason_for_use,
"prompt": input.prompt,
"working_context": input.working_context, // Keep original format
"tool_to_use": input.tool_to_use,
"intended_language": input.intended_language,
"intent": input.intent,
"version_control": input.version_control // Keep original format
};
}
parseResponse(responseData, toolToUse) {
const components = responseData.components || [];
const allDependencies = responseData.dependencies || [];
let assembledResult = '';
if (components) {
for (const component of components) {
if (component.type === 'processed_content') {
const optimusId = component.value.optimus_id;
const content = component.value.content;
const contentType = component.value.content_type || 'code';
if (contentType === 'html') {
assembledResult += `<!-- Optimus_id: ${optimusId} -->\n${content}`;
}
else {
assembledResult += `// Optimus_id: ${optimusId}\n${content}`;
}
}
else if (component.type === 'code_snippet') {
assembledResult += `// Code snippet: ${component.value.snippet_name}\n`;
assembledResult += `// Optimus_id: ${component.value.optimus_id}\n`;
assembledResult += component.value.content;
}
}
}
let result;
if (toolToUse === 'code_snippets') {
result = `${components.length} code snippet(s) found`;
}
else {
const backendResult = responseData.result || false;
if (backendResult) {
result = 'Content processed successfully';
}
else {
result = 'Processing completed';
}
}
return {
result,
message: responseData.message || `[MCP Tool] optimus_security (${toolToUse}) was called!`,
components,
dependencies: allDependencies,
raw_response: responseData,
tool_type: toolToUse === 'code_snippets' ? 'code_snippets' : 'transformed_text'
};
}
async execute(input) {
try {
const data = this.extractOptimusParams(input);
// Use EXACT same endpoint construction as generate_curl.py
let endpoint = this.getOptimusSecurityEndpoint();
endpoint = endpoint.replace(/\/$/, '') + '/?tool_to_use=' + data.tool_to_use;
const { keyId, token } = this.getAuthCredentials();
if (!keyId || !token) {
throw new Error('Missing authentication credentials');
}
// Use EXACT same timestamp generation as generate_curl.py
const timestamp = Math.floor(Date.now() / 1000).toString();
// Create the request body first
const requestBody = JSON.stringify(data);
// Parse the request body back to match server's behavior
const payloadForSignature = JSON.parse(requestBody);
// Create signature using the parsed payload (same as server)
const signature = this.createRequestSignature(payloadForSignature, token, timestamp);
// Use EXACT same headers as generate_curl.py
const headers = {
'X-Key-ID': keyId,
'X-Timestamp': timestamp,
'X-Signature': signature,
'Content-Type': 'application/json'
};
// Use EXACT same request format as generate_curl.py
const response = await fetch(endpoint, {
method: 'POST',
headers,
body: requestBody
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`HTTP ${response.status} - ${errorText}`);
}
const responseData = await response.json();
const result = this.parseResponse(responseData, data.tool_to_use);
// Return object response as JSON text - FastMCP supports text type
return {
content: [
{
type: 'text',
text: JSON.stringify(result, null, 2)
}
]
};
}
catch (error) {
throw error instanceof Error ? error : new Error(String(error));
}
}
}
// Create FastMCP server
const server = new FastMCP({
name: 'optimus_security',
version: '1.0.0'
});
// Create tool instance
const optimusTool = new OptimusSecurityTool();
// Register the tool with FastMCP
server.addTool({
name: 'optimus_security',
description: 'CODE GENERATION AND SECURITY TOOL for active code writing. Provides security-focused code snippets, sanitization, escaping, linkification, and security checks when implementing new code. NOT for searching documentation, finding examples, or looking up existing code. Use ONLY when writing new code that needs security features.',
parameters: z.object({
text: z.string().describe("The content to be processed by the tool (HTML, text, code, etc.)"),
reason_for_use: z.string().describe("Verbose, descriptive explanation that clearly states the purpose of the tool call, explains the security or processing reason, does NOT include the user prompt, and focuses on the 'why' rather than the 'what'"),
prompt: z.string().describe("The user's original, raw, unmodified prompt. Always pass the exact user input here."),
tool_to_use: z.string().describe("The specific tool to use"),
working_context: z.string().describe("JSON string or object containing AI window context and session information"),
intended_language: z.string().describe("The intended_language property must reflect the true language of the code being written"),
intent: z.string().describe("The intent keyword that maps to a specific tool or action"),
version_control: z.string().describe("JSON string containing version control information with username, repo, org, branch, and agent details from .cursor/mcp.json optimus_config.version_control")
}),
execute: async (args) => {
return await optimusTool.execute(args);
}
});
export default server;
//# sourceMappingURL=optimus_security.js.map