#!/usr/bin/env node
// {{ display_name }} MCP server — generated by mcpify. Do not hand-edit.
//
// Harness Server entry point: boots the persistent MCP server loop for
// consumption by an agent harness (Claude Desktop, Cursor, custom
// orchestrators). Run directly (`node dist/index.js`) or via
// `{{ project_name }} start` / `{{ project_name }} http` (see cli.ts).

import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';

import { AuthManager, headerLocationFor } from './auth/auth-manager.js';
import { loadConfig } from './core/config-manager.js';
import { ComponentRegistry } from './core/component-registry.js';
import { HealthCheckManager } from './core/health-check-manager.js';
import { logger } from './core/logger.js';
import { connectStdio, createMcpServer } from './core/mcp-server.js';
import { installShutdownHandlers, onShutdown } from './core/shutdown-handler.js';
import { initTracing, shutdownTracing } from './core/tracing.js';
import { getCachedStore } from './data/store-repository.js';
import { startHttpServer } from './http/http-server.js';
import { registerTools } from './tools/register-tools.js';

/**
 * Bootstrap order (architecture.md's Runtime Target Architecture): config ->
 * logger -> registry -> shutdown-handler -> db -> auth -> services -> McpServer
 * -> register tools -> pick transport -> health checks.
 */
export async function main(): Promise<void> {
  const config = loadConfig();
  initTracing();
  installShutdownHandlers();
  onShutdown(shutdownTracing);

  const registry = new ComponentRegistry();
  const healthChecks = new HealthCheckManager(registry);

  const store = getCachedStore(config.api_version);
  healthChecks.register('store', async () => {
    await store.healthCheck();
  });

  const authManager = new AuthManager(config.auth_method);

  healthChecks.start();
  onShutdown(() => healthChecks.stop());

  if (config.transport === 'http') {
    {%- if "oauth1" in auth_method_keys %}
    if (config.auth_method === 'oauth1') {
      throw new Error(
        "OAuth1 is not supported over HTTP transport: its signature must be recomputed per " +
          "request against the destination URL using the server's consumer key/secret, which a " +
          'simple incoming-header relay cannot provide. Use stdio transport for OAuth1-authenticated ' +
          'APIs, or switch auth_method.',
      );
    }
    {%- endif %}
    const [headerLocation, headerName] = headerLocationFor(config.auth_method);
    // Each HTTP session gets its own McpServer instance (the SDK allows only
    // one `connect()` per instance — see http/http-server.ts), so `main`
    // hands the HTTP server a factory rather than a single pre-built one.
    const createSession = (): McpServer => {
      const server = createMcpServer();
      registerTools(server, { store, config, authManager });
      return server;
    };
    await startHttpServer(createSession, config, registry, headerLocation, headerName);
    logger.info({ host: config.host, port: config.port }, 'MCP server listening over HTTP');
  } else {
    const server = createMcpServer();
    registerTools(server, { store, config, authManager });
    await connectStdio(server);
  }
}

if (import.meta.url === `file://${process.argv[1]}`) {
  main().catch((error: unknown) => {
    logger.error({ err: error }, 'fatal error during startup');
    process.exit(1);
  });
}
