Skip to content

Commit ec1b59a

Browse files
feat: fix MCP server build and authentication
- Fix TypeScript compilation errors in index.ts and server.ts - Add optional initialize() method to ILighthouseService interface - Replace JWT authentication with direct API key usage for Lighthouse Web3 SDK - Remove problematic token endpoint requests causing 404 errors - Successfully build and run MCP server with real Lighthouse API integration - Add test script for running server with mock services
1 parent 6d142af commit ec1b59a

17 files changed

Lines changed: 772 additions & 55 deletions

apps/mcp-server/INTEGRATION.md

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# Lighthouse MCP Server - Real SDK Integration
2+
3+
This document describes the integration between the MCP server foundation (task 3) and the unified SDK wrapper (task 2).
4+
5+
## What Changed
6+
7+
The MCP server has been updated to use the real `LighthouseService` instead of the mock service:
8+
9+
### Key Changes
10+
11+
1. **Real Lighthouse Integration**: The server now uses `LighthouseService` which integrates with the actual Lighthouse SDK wrapper from task 2.
12+
13+
2. **Common Interface**: Created `ILighthouseService` interface that both mock and real services implement, ensuring compatibility.
14+
15+
3. **API Key Configuration**: Added `lighthouseApiKey` to server configuration, supporting both environment variable and command-line argument.
16+
17+
4. **Async Operations**: Updated all file operations to be properly async, matching the real SDK behavior.
18+
19+
## Usage
20+
21+
### Environment Setup
22+
23+
```bash
24+
export LIGHTHOUSE_API_KEY="your-lighthouse-api-key"
25+
```
26+
27+
### Command Line
28+
29+
```bash
30+
node dist/index.js --api-key "your-lighthouse-api-key"
31+
```
32+
33+
### Programmatic Usage
34+
35+
```typescript
36+
import { LighthouseMCPServer } from "@lighthouse-tooling/mcp-server";
37+
38+
const server = new LighthouseMCPServer({
39+
lighthouseApiKey: "your-api-key",
40+
logLevel: "info",
41+
});
42+
43+
await server.start();
44+
```
45+
46+
## MCP Tools Available
47+
48+
1. **lighthouse_upload_file**: Upload files to IPFS via Lighthouse
49+
2. **lighthouse_create_dataset**: Create managed datasets with metadata
50+
3. **lighthouse_fetch_file**: Download and optionally decrypt files
51+
52+
## Architecture
53+
54+
```
55+
AI Agent (Cursor/Claude)
56+
↓ MCP Protocol
57+
LighthouseMCPServer
58+
↓ Interface
59+
LighthouseService
60+
↓ SDK Wrapper
61+
LighthouseAISDK
62+
↓ HTTP API
63+
Lighthouse Infrastructure
64+
```
65+
66+
## Testing
67+
68+
The integration includes comprehensive tests:
69+
70+
```bash
71+
npm test -- integration.test.ts
72+
```
73+
74+
## Next Steps
75+
76+
- Task 4: Implement core MCP tools for file operations with real file handling
77+
- Task 5: Add encryption and access control features using Kavach SDK
78+
- Task 6: Implement dataset management functionality with versioning
79+
80+
## Error Handling
81+
82+
The real service includes:
83+
84+
- Retry logic with exponential backoff
85+
- Circuit breaker pattern for API failures
86+
- Comprehensive error logging
87+
- Authentication token refresh
88+
89+
## Performance
90+
91+
- Progress tracking for long-running operations
92+
- Connection pooling for API requests
93+
- Intelligent caching with LRU cache
94+
- Memory management and backpressure handling

apps/mcp-server/demo-test.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
const { LighthouseMCPServer } = require("./dist/server.js");
2-
const fs = require("fs");
1+
import { LighthouseMCPServer } from "./dist/server.js";
2+
import fs from "fs";
33

44
async function demo() {
55
const testFile = "./demo-test.txt";
@@ -12,6 +12,9 @@ async function demo() {
1212
enableMetrics: false,
1313
});
1414

15+
// Register tools
16+
await server.registerTools();
17+
1518
const registry = server.getRegistry();
1619
console.log("Server initialized with", registry.listTools().length, "tools\n");
1720

apps/mcp-server/src/config/server-config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export interface ServerConfig {
1010
port?: number;
1111
enableMetrics: boolean;
1212
metricsInterval: number;
13+
lighthouseApiKey?: string;
1314
}
1415

1516
export const DEFAULT_SERVER_CONFIG: ServerConfig = {
@@ -19,4 +20,5 @@ export const DEFAULT_SERVER_CONFIG: ServerConfig = {
1920
maxStorageSize: 1024 * 1024 * 1024, // 1GB
2021
enableMetrics: true,
2122
metricsInterval: 60000, // 1 minute
23+
lighthouseApiKey: process.env.LIGHTHOUSE_API_KEY,
2224
};

apps/mcp-server/src/handlers/ListResourcesHandler.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@
55
import { Logger } from "@lighthouse-tooling/shared";
66
import { MCPResponse } from "@lighthouse-tooling/types";
77
import { ResponseBuilder } from "../utils/response-builder.js";
8-
import { MockLighthouseService } from "../services/MockLighthouseService.js";
8+
import { ILighthouseService } from "../services/ILighthouseService.js";
99
import { MockDatasetService } from "../services/MockDatasetService.js";
1010

1111
export class ListResourcesHandler {
12-
private lighthouseService: MockLighthouseService;
12+
private lighthouseService: ILighthouseService;
1313
private datasetService: MockDatasetService;
1414
private logger: Logger;
1515

1616
constructor(
17-
lighthouseService: MockLighthouseService,
17+
lighthouseService: ILighthouseService,
1818
datasetService: MockDatasetService,
1919
logger?: Logger,
2020
) {
@@ -32,7 +32,8 @@ export class ListResourcesHandler {
3232
this.logger.info("Handling resources/list request", { requestId });
3333

3434
// Get all uploaded files
35-
const files = this.lighthouseService.listFiles();
35+
const filesResult = this.lighthouseService.listFiles();
36+
const files = Array.isArray(filesResult) ? filesResult : await filesResult;
3637

3738
// Get all datasets
3839
const datasets = this.datasetService.listDatasets();

apps/mcp-server/src/index.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { ServerConfig } from "./config/server-config.js";
88
// Export main server class
99
export { LighthouseMCPServer } from "./server.js";
1010
export { ToolRegistry } from "./registry/ToolRegistry.js";
11-
export { MockLighthouseService } from "./services/MockLighthouseService.js";
11+
export { LighthouseService } from "./services/LighthouseService.js";
1212
export { MockDatasetService } from "./services/MockDatasetService.js";
1313
export * from "./registry/types.js";
1414
export * from "./config/server-config.js";
@@ -28,7 +28,12 @@ async function main() {
2828
switch (arg) {
2929
case "--log-level":
3030
i++;
31-
if (args[i]) config.logLevel = args[i] as any;
31+
if (args[i]) {
32+
const level = args[i] as string;
33+
if (["debug", "info", "warn", "error"].includes(level)) {
34+
config.logLevel = level as "debug" | "info" | "warn" | "error";
35+
}
36+
}
3237
break;
3338
case "--max-storage":
3439
i++;
@@ -42,6 +47,10 @@ async function main() {
4247
i++;
4348
if (args[i]) config.version = args[i];
4449
break;
50+
case "--api-key":
51+
i++;
52+
if (args[i]) config.lighthouseApiKey = args[i];
53+
break;
4554
case "--help":
4655
console.log(`
4756
Lighthouse MCP Server
@@ -53,6 +62,7 @@ Options:
5362
--max-storage <bytes> Set maximum storage size in bytes [default: 1073741824]
5463
--name <name> Set server name [default: lighthouse-storage]
5564
--version <version> Set server version [default: 0.1.0]
65+
--api-key <key> Set Lighthouse API key (or use LIGHTHOUSE_API_KEY env var)
5666
--help Show this help message
5767
5868
Examples:

apps/mcp-server/src/server.ts

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ import { Logger } from "@lighthouse-tooling/shared";
1313
import { LIGHTHOUSE_MCP_TOOLS } from "@lighthouse-tooling/types";
1414

1515
import { ToolRegistry } from "./registry/ToolRegistry.js";
16-
import { MockLighthouseService } from "./services/MockLighthouseService.js";
16+
import { LighthouseService } from "./services/LighthouseService.js";
17+
import { ILighthouseService } from "./services/ILighthouseService.js";
1718
import { MockDatasetService } from "./services/MockDatasetService.js";
1819
import {
1920
ListToolsHandler,
@@ -26,7 +27,7 @@ import { ServerConfig, DEFAULT_SERVER_CONFIG } from "./config/server-config.js";
2627
export class LighthouseMCPServer {
2728
private server: Server;
2829
private registry: ToolRegistry;
29-
private lighthouseService: MockLighthouseService;
30+
private lighthouseService: ILighthouseService;
3031
private datasetService: MockDatasetService;
3132
private logger: Logger;
3233
private config: ServerConfig;
@@ -37,7 +38,13 @@ export class LighthouseMCPServer {
3738
private listResourcesHandler: ListResourcesHandler;
3839
private initializeHandler: InitializeHandler;
3940

40-
constructor(config: Partial<ServerConfig> = {}) {
41+
constructor(
42+
config: Partial<ServerConfig> = {},
43+
services?: {
44+
lighthouseService?: ILighthouseService;
45+
datasetService?: MockDatasetService;
46+
},
47+
) {
4148
this.config = { ...DEFAULT_SERVER_CONFIG, ...config };
4249

4350
// Initialize logger
@@ -61,8 +68,20 @@ export class LighthouseMCPServer {
6168
);
6269

6370
// Initialize services
64-
this.lighthouseService = new MockLighthouseService(this.config.maxStorageSize, this.logger);
65-
this.datasetService = new MockDatasetService(this.lighthouseService, this.logger);
71+
if (services?.lighthouseService) {
72+
this.lighthouseService = services.lighthouseService;
73+
} else {
74+
if (!this.config.lighthouseApiKey) {
75+
throw new Error("LIGHTHOUSE_API_KEY environment variable is required");
76+
}
77+
this.lighthouseService = new LighthouseService(this.config.lighthouseApiKey, this.logger);
78+
}
79+
80+
if (services?.datasetService) {
81+
this.datasetService = services.datasetService;
82+
} else {
83+
this.datasetService = new MockDatasetService(this.lighthouseService, this.logger);
84+
}
6685

6786
// Initialize registry
6887
this.registry = new ToolRegistry(this.logger);
@@ -201,7 +220,7 @@ export class LighthouseMCPServer {
201220

202221
// Handle ListResources
203222
this.server.setRequestHandler(ListResourcesRequestSchema, async () => {
204-
const files = this.lighthouseService.listFiles();
223+
const files = await this.lighthouseService.listFiles();
205224
const datasets = this.datasetService.listDatasets();
206225

207226
const resources = [
@@ -237,6 +256,11 @@ export class LighthouseMCPServer {
237256
version: this.config.version,
238257
});
239258

259+
// Initialize Lighthouse service
260+
if (this.lighthouseService.initialize) {
261+
await this.lighthouseService.initialize();
262+
}
263+
240264
// Register tools
241265
await this.registerTools();
242266

@@ -311,7 +335,7 @@ export class LighthouseMCPServer {
311335
getStats(): {
312336
registry: any;
313337
storage: any;
314-
datasets: any;
338+
datasets: unknown;
315339
} {
316340
return {
317341
registry: this.registry.getMetrics(),
@@ -330,7 +354,7 @@ export class LighthouseMCPServer {
330354
/**
331355
* Get lighthouse service instance (for testing)
332356
*/
333-
getLighthouseService(): MockLighthouseService {
357+
getLighthouseService(): ILighthouseService {
334358
return this.lighthouseService;
335359
}
336360

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/**
2+
* Common interface for Lighthouse services
3+
*/
4+
5+
import { UploadResult, DownloadResult, AccessCondition } from "@lighthouse-tooling/types";
6+
7+
export interface StoredFile {
8+
cid: string;
9+
filePath: string;
10+
size: number;
11+
encrypted: boolean;
12+
accessConditions?: AccessCondition[];
13+
tags?: string[];
14+
uploadedAt: Date;
15+
pinned: boolean;
16+
hash?: string;
17+
}
18+
19+
export interface ILighthouseService {
20+
/**
21+
* Initialize the service
22+
*/
23+
initialize?(): Promise<void>;
24+
25+
/**
26+
* Upload file
27+
*/
28+
uploadFile(params: {
29+
filePath: string;
30+
encrypt?: boolean;
31+
accessConditions?: AccessCondition[];
32+
tags?: string[];
33+
}): Promise<UploadResult>;
34+
35+
/**
36+
* Fetch/download file
37+
*/
38+
fetchFile(params: {
39+
cid: string;
40+
outputPath?: string;
41+
decrypt?: boolean;
42+
}): Promise<DownloadResult>;
43+
44+
/**
45+
* Pin file
46+
*/
47+
pinFile(cid: string): Promise<{ success: boolean; cid: string; pinned: boolean }>;
48+
49+
/**
50+
* Unpin file
51+
*/
52+
unpinFile(cid: string): Promise<{ success: boolean; cid: string; pinned: boolean }>;
53+
54+
/**
55+
* Get file info by CID
56+
*/
57+
getFileInfo(cid: string): StoredFile | undefined | Promise<StoredFile | undefined>;
58+
59+
/**
60+
* List all uploaded files
61+
*/
62+
listFiles(): StoredFile[] | Promise<StoredFile[]>;
63+
64+
/**
65+
* Get storage stats
66+
*/
67+
getStorageStats(): {
68+
fileCount: number;
69+
totalSize: number;
70+
maxSize: number;
71+
utilization: number;
72+
};
73+
74+
/**
75+
* Clear cache (for testing)
76+
*/
77+
clear(): void;
78+
}

0 commit comments

Comments
 (0)