/** * sh-mcp-ops tool registry — composition root. * * Registers exactly the ops-tier tools (design.md §3): internal-data, * knowledge-base, google-maps, gmail, calendar, tasks, reminders. Each package * factory is wired with the selected client — an in-memory dev client in * `SH_MCP_ENV=local`, or the real (stub) client in `aws` mode. * * IMPORTANT: we deliberately call each package's *factory* with an explicit * client rather than importing its pre-wired `tools` array, because some of * those arrays construct AWS clients at import time. Building clients here keeps * import-time side-effect-free (build-plan §7 "No I/O at import time"). * * The package factory signatures are intentionally inconsistent (build-plan §1); * each is wired to its own shape below. */ import { ToolRegistry, type ToolDef } from '@sh-mcp/shared'; // internal-data import { makeTools as makeInternalDataTools, RealDynamoClient, type InternalDataClient, InMemoryInternalDataClient, } from '@sh-mcp/internal-data'; // knowledge-base import { createKnowledgeBaseTools, createBedrockClientFromEnv, type KnowledgeBaseClient, InMemoryKnowledgeBaseClient, } from '@sh-mcp/knowledge-base'; // google-maps import { makeTools as makeMapsTools, GooglePlacesClient, type GoogleMapsClient, InMemoryGoogleMapsClient, } from '@sh-mcp/google-maps'; // gmail import { makeGmailTools, GmailApiClient, type GmailClient, type GoogleTokenProvider as GmailTokenProvider, InMemoryGmailClient, } from '@sh-mcp/gmail'; // calendar import { buildCalendarTools, GoogleCalendarClient, type CalendarClient, type GoogleTokenProvider as CalendarTokenProvider, InMemoryCalendarClient, } from '@sh-mcp/calendar'; // tasks import { buildTaskTools, DynamoDBTasksClient, type TasksClient, InMemoryTasksClient, } from '@sh-mcp/tasks'; // reminders import { buildReminderTools, AwsSchedulerClient, type SchedulerClient, InMemorySchedulerClient, } from '@sh-mcp/reminders'; import type { OpsConfig } from './config.js'; /** * A Google per-user token provider stub for `aws` mode. The REAL provider * (per-user OAuth refresh tokens, design.md §2.4) is a later phase; in this PR * `aws` mode is not runtime-exercised, so this throws if actually used. */ class StubGoogleTokenProvider implements GmailTokenProvider, CalendarTokenProvider { async getAccessToken(): Promise { throw new Error( 'Real per-user Google token provider is not implemented in Phase 1 ' + '(design.md §2.4 — deferred). Run with SH_MCP_ENV=local for a working server.', ); } } /** Build the ops registry for the given environment. */ export async function buildOpsRegistry(config: OpsConfig): Promise { const local = config.env === 'local'; // --- select clients (dev vs real) --- const internalDataClient: InternalDataClient = local ? new InMemoryInternalDataClient() : await RealDynamoClient.create(); const kbClient: KnowledgeBaseClient = local ? new InMemoryKnowledgeBaseClient() : createBedrockClientFromEnv(); const mapsClient: GoogleMapsClient = local ? new InMemoryGoogleMapsClient() : new GooglePlacesClient(config.googleMapsApiKey ?? ''); const tokenProvider = new StubGoogleTokenProvider(); const gmailClient: GmailClient = local ? new InMemoryGmailClient() : new GmailApiClient(tokenProvider); const calendarClient: CalendarClient = local ? new InMemoryCalendarClient() : new GoogleCalendarClient(tokenProvider); const tasksClient: TasksClient = local ? new InMemoryTasksClient() : new DynamoDBTasksClient(); const schedulerClient: SchedulerClient = local ? new InMemorySchedulerClient() : new AwsSchedulerClient({ targetArn: config.reminderTargetArn ?? '', roleArn: config.schedulerRoleArn ?? '', }); // --- register all ops-tier tools --- const registry = new ToolRegistry(); const all: ToolDef[] = [ ...makeInternalDataTools(internalDataClient), ...createKnowledgeBaseTools(kbClient), ...makeMapsTools(mapsClient), ...makeGmailTools(gmailClient), ...buildCalendarTools(calendarClient), ...buildTaskTools(tasksClient), ...buildReminderTools({ client: schedulerClient }), ].map((t) => t as ToolDef); for (const tool of all) registry.register(tool); return registry; }