mcp-think-tank
Version:
Structured thinking and knowledge management tool for Model Context Protocol
246 lines (245 loc) • 9.82 kB
JavaScript
import { fileSystemAdapter } from './FileSystemAdapter.js';
import { networkAdapter } from './NetworkAdapter.js';
/**
* Integrates file and URL caching with FastMCP tools
* This demonstrates how to implement Story 3-G: Execution cache for file/URL reads
*/
export class AdapterIntegration {
/**
* Register cached file reading tools with FastMCP
* @param server FastMCP server instance
*/
static registerCachedFileTools(server) {
// Register a tool for reading files with caching
server.addTool({
name: 'cached_read_file',
description: 'Read a file with content-based caching',
parameters: {
type: 'object',
properties: {
filePath: {
type: 'string',
description: 'Path to the file to read'
},
encoding: {
type: 'string',
description: 'File encoding (defaults to utf8)',
enum: ['utf8', 'ascii', 'base64', 'hex', 'binary'],
default: 'utf8'
}
},
required: ['filePath']
},
execute: async (args, context) => {
try {
const content = await fileSystemAdapter.readFileAsText(args.filePath, args.encoding || 'utf8');
// Return TextContent format expected by FastMCP
return {
type: 'text',
text: content,
metadata: {
stats: fileSystemAdapter.getCacheStats()
}
};
}
catch (error) {
// Return error as text
return {
type: 'text',
text: `Failed to read file: ${error.message}`,
metadata: {
error: true,
stats: fileSystemAdapter.getCacheStats()
}
};
}
}
});
// Register a tool for reading JSON files with caching
server.addTool({
name: 'cached_read_json',
description: 'Read and parse a JSON file with content-based caching',
parameters: {
type: 'object',
properties: {
filePath: {
type: 'string',
description: 'Path to the JSON file to read'
}
},
required: ['filePath']
},
execute: async (args, context) => {
try {
const data = await fileSystemAdapter.readJsonFile(args.filePath);
// Return as JSON string
return {
type: 'text',
text: JSON.stringify(data, null, 2),
metadata: {
contentType: 'application/json',
stats: fileSystemAdapter.getCacheStats()
}
};
}
catch (error) {
return {
type: 'text',
text: `Failed to read JSON file: ${error.message}`,
metadata: {
error: true,
stats: fileSystemAdapter.getCacheStats()
}
};
}
}
});
}
/**
* Register cached URL fetching tools with FastMCP
* @param server FastMCP server instance
*/
static registerCachedNetworkTools(server) {
// Register a tool for fetching URLs with caching
server.addTool({
name: 'cached_fetch_url',
description: 'Fetch a URL with content-based caching',
parameters: {
type: 'object',
properties: {
url: {
type: 'string',
description: 'URL to fetch'
},
encoding: {
type: 'string',
description: 'Response encoding (defaults to utf8)',
enum: ['utf8', 'ascii', 'base64', 'hex', 'binary'],
default: 'utf8'
}
},
required: ['url']
},
execute: async (args, context) => {
try {
const content = await networkAdapter.fetchText(args.url, args.encoding || 'utf8');
return {
type: 'text',
text: content,
metadata: {
url: args.url,
stats: networkAdapter.getCacheStats()
}
};
}
catch (error) {
return {
type: 'text',
text: `Failed to fetch URL: ${error.message}`,
metadata: {
error: true,
url: args.url,
stats: networkAdapter.getCacheStats()
}
};
}
}
});
// Register a tool for fetching JSON from URLs with caching
server.addTool({
name: 'cached_fetch_json',
description: 'Fetch and parse JSON from a URL with content-based caching',
parameters: {
type: 'object',
properties: {
url: {
type: 'string',
description: 'URL to fetch JSON from'
}
},
required: ['url']
},
execute: async (args, context) => {
try {
const data = await networkAdapter.fetchJson(args.url);
return {
type: 'text',
text: JSON.stringify(data, null, 2),
metadata: {
contentType: 'application/json',
url: args.url,
stats: networkAdapter.getCacheStats()
}
};
}
catch (error) {
return {
type: 'text',
text: `Failed to fetch JSON: ${error.message}`,
metadata: {
error: true,
url: args.url,
stats: networkAdapter.getCacheStats()
}
};
}
}
});
}
/**
* Replace existing file reading tools with cached versions
* This shows how to update existing tools to use caching
* @param server FastMCP server instance
*/
static enhanceExistingTools(server) {
// Example of enhancing an existing tool with caching
// This is just a demonstration - actual implementation would depend on existing tools
// Hypothetical read_file tool enhancement
const existingReadFile = server.getToolByName?.('read_file');
if (existingReadFile) {
// Create a wrapped version of the tool
const cachedReadFile = {
...existingReadFile,
execute: async (args, context) => {
// If the params include a target_file or file property, use caching
if (args.target_file || args.file) {
const filePath = args.target_file || args.file;
try {
const content = await fileSystemAdapter.readFileAsText(filePath);
// Format the response to match the original tool's format
return existingReadFile.execute({
...args,
_cached_content: content // Provide the content to avoid reading the file again
}, context);
}
catch (error) {
// Fall back to original tool if caching fails
console.error(`[AdapterIntegration] Cache miss or error for ${filePath}:`, error);
return existingReadFile.execute(args, context);
}
}
// For other cases, use the original tool
return existingReadFile.execute(args, context);
}
};
// Replace the existing tool
// This would require access to the tools registry, which might not be directly accessible
// server.replaceTool(cachedReadFile);
// Alternatively, register as a new tool
// server.addTool({
// ...cachedReadFile,
// name: 'enhanced_read_file'
// });
}
}
/**
* Register all cached tools with FastMCP
* @param server FastMCP server instance
*/
static registerAll(server) {
this.registerCachedFileTools(server);
this.registerCachedNetworkTools(server);
// Uncomment to enhance existing tools
// this.enhanceExistingTools(server);
}
}