build method

  1. @override
Future<void> build(
  1. BuildStep buildStep
)

Generates the outputs for a given BuildStep.

Implementation

@override
Future<void> build(BuildStep buildStep) async {
  final inputId = buildStep.inputId;
  final resolver = buildStep.resolver;

  if (!await resolver.isLibrary(inputId)) return;

  final library = await buildStep.resolver.libraryFor(inputId);

  // Single pass: find the first @Server annotation in the library and
  // resolve every field we care about. Returns null when the library
  // carries no @Server (or deprecated @Mcp typedef).
  final config = _extractServerConfig(library);
  if (config == null) return;

  // Aggregate tools from this library AND all its package-local imports
  final tools = await _extractAllTools(
    library,
    config.toolPrefix,
    config.autoClassPrefix,
    config.annotationsDefault,
  );

  if (tools.isEmpty) return; // No tools found anywhere

  // Aggregate prompts from this library AND all its package-local imports
  final prompts = await _extractAllPrompts(library);

  // Conditionally generate MCP server code (gated by generateMcp flag)
  if (config.generateMcp) {
    // Generate the appropriate server code based on transport type
    final generated = config.transport == 'http'
        ? HttpTemplate.generate(
            tools,
            config.port,
            config.address,
            codeMode: config.codeMode,
            codeModeTimeout: config.codeModeTimeout,
            logErrors: config.logErrors,
            prompts: prompts,
            corsOrigins: config.corsOrigins,
          )
        : StdioTemplate.generate(
            tools,
            codeMode: config.codeMode,
            codeModeTimeout: config.codeModeTimeout,
            logErrors: config.logErrors,
            prompts: prompts,
          );

    // Write the generated server code
    await buildStep.writeAsString(
      inputId.changeExtension('.mcp.dart'),
      generated,
    );

    // Optionally generate JSON metadata file
    if (config.generateJson) {
      final jsonMetadata = _generateJsonMetadata(tools, prompts: prompts);
      await buildStep.writeAsString(
        inputId.changeExtension('.mcp.json'),
        jsonEncode(jsonMetadata),
      );
    }
  }

  // Conditionally generate REST/OpenAPI output (gated by generateRest flag)
  if (config.generateRest) {
    final openApiSpec = OpenApiBuilder.build(
      tools,
      config.transport,
      config.port,
      config.address,
    );
    await buildStep.writeAsString(
      inputId.changeExtension('.openapi.json'),
      const JsonEncoder.withIndent('  ').convert(openApiSpec),
    );

    // Generate .openapi.dart REST server
    final openApiDartCode = OpenApiDartTemplate.generate(
      tools,
      config.port,
      config.address,
      openApiSpec,
      logErrors: config.logErrors,
    );
    await buildStep.writeAsString(
      inputId.changeExtension('.openapi.dart'),
      openApiDartCode,
    );
  }
}