- Fix Next.js build failure: remove duplicate route at (dashboard)/listings/[id] that conflicted with (public)/listings/[id] (same URL path in two route groups) - Fix 772 ESLint errors: auto-fix import ordering (import-x/order), remove unused imports/variables, convert empty interfaces to type aliases, replace require() with ESM imports, fix consistent-type-imports violations - Add CLAUDE.md for developer onboarding documentation - All checks pass: 0 lint errors, typecheck clean, 230 tests passing, build success Co-Authored-By: Paperclip <noreply@paperclip.ing>
66 lines
2.1 KiB
TypeScript
66 lines
2.1 KiB
TypeScript
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
import { Injectable, Inject, type OnModuleInit } from '@nestjs/common';
|
|
import type { Client as TypesenseClient } from 'typesense';
|
|
import { MCP_MODULE_OPTIONS } from './mcp.constants';
|
|
import type { McpModuleOptions } from './mcp.module';
|
|
|
|
@Injectable()
|
|
export class McpRegistryService implements OnModuleInit {
|
|
private readonly servers = new Map<string, McpServer>();
|
|
private typesenseClient: TypesenseClient | null = null;
|
|
|
|
constructor(
|
|
@Inject(MCP_MODULE_OPTIONS) private readonly options: McpModuleOptions,
|
|
) {}
|
|
|
|
async onModuleInit(): Promise<void> {
|
|
// Lazy import to avoid hard dependency at module load time
|
|
const { createPropertySearchServer } = await import('../property-search/property-search.server');
|
|
const { createMarketAnalyticsServer } = await import('../market-analytics/market-analytics.server');
|
|
const { createValuationServer } = await import('../valuation/valuation.server');
|
|
|
|
// Typesense client is injected from the host app via setTypesenseClient
|
|
// If not set by the time servers are needed, tools that require it will fail gracefully
|
|
if (this.typesenseClient) {
|
|
this.servers.set(
|
|
'property-search',
|
|
createPropertySearchServer({
|
|
typesenseClient: this.typesenseClient,
|
|
collectionName: this.options.typesenseCollectionName,
|
|
}),
|
|
);
|
|
|
|
this.servers.set(
|
|
'market-analytics',
|
|
createMarketAnalyticsServer({
|
|
typesenseClient: this.typesenseClient,
|
|
collectionName: this.options.typesenseCollectionName,
|
|
}),
|
|
);
|
|
}
|
|
|
|
this.servers.set(
|
|
'valuation',
|
|
createValuationServer({
|
|
aiServiceBaseUrl: this.options.aiServiceBaseUrl,
|
|
}),
|
|
);
|
|
}
|
|
|
|
setTypesenseClient(client: TypesenseClient): void {
|
|
this.typesenseClient = client;
|
|
}
|
|
|
|
getServer(name: string): McpServer | undefined {
|
|
return this.servers.get(name);
|
|
}
|
|
|
|
getServerNames(): string[] {
|
|
return Array.from(this.servers.keys());
|
|
}
|
|
|
|
getAllServers(): Map<string, McpServer> {
|
|
return this.servers;
|
|
}
|
|
}
|