Skip to main content
Integrate the Char agent into your Angular application using standalone components and CUSTOM_ELEMENTS_SCHEMA.

Installation

Basic Usage

import { Component, Input, ViewChild, ElementRef, AfterViewInit, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import '@mcp-b/char/web-component';
import type { WebMCPAgentElement } from '@mcp-b/char/web-component';

@Component({
  selector: 'app-chat-widget',
  standalone: true,
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
  template: `<char-agent #agent></char-agent>`,
})
export class ChatWidgetComponent implements AfterViewInit {
  @Input() idToken!: string;
  @Input() clientId!: string;
  @ViewChild('agent') agentRef!: ElementRef<WebMCPAgentElement>;

  ngAfterViewInit() {
    this.agentRef.nativeElement.connect({ idToken: this.idToken, clientId: this.clientId });
  }
}

With Reactive Updates

Handle token changes with ngOnChanges:
import {
  Component,
  Input,
  ViewChild,
  ElementRef,
  AfterViewInit,
  OnChanges,
  SimpleChanges,
  CUSTOM_ELEMENTS_SCHEMA
} from '@angular/core';
import '@mcp-b/char/web-component';
import type { WebMCPAgentElement } from '@mcp-b/char/web-component';

@Component({
  selector: 'app-chat-widget',
  standalone: true,
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
  template: `
    @if (idToken) {
      <char-agent #agent></char-agent>
    }
  `,
})
export class ChatWidgetComponent implements AfterViewInit, OnChanges {
  @Input() idToken?: string;
  @Input() clientId?: string;
  @ViewChild('agent') agentRef?: ElementRef<WebMCPAgentElement>;

  ngAfterViewInit() {
    this.connectAgent();
  }

  ngOnChanges(changes: SimpleChanges) {
    if (changes['idToken'] && !changes['idToken'].firstChange) {
      this.connectAgent();
    }
  }

  private connectAgent() {
    if (this.idToken && this.clientId && this.agentRef) {
      this.agentRef.nativeElement.connect({ idToken: this.idToken, clientId: this.clientId });
    }
  }
}

With NgRx Store

If using NgRx for state management:
import { Component, ViewChild, ElementRef, AfterViewInit, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { Store } from '@ngrx/store';
import { selectIdToken } from './auth.selectors';
import '@mcp-b/char/web-component';
import type { WebMCPAgentElement } from '@mcp-b/char/web-component';

@Component({
  selector: 'app-chat-widget',
  standalone: true,
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
  template: `
    @if (idToken$ | async; as token) {
      <char-agent #agent></char-agent>
    }
  `,
})
export class ChatWidgetComponent implements AfterViewInit {
  @ViewChild('agent') agentRef?: ElementRef<WebMCPAgentElement>;
  idToken$ = this.store.select(selectIdToken);
  clientId = 'your-oidc-client-id';

  constructor(private store: Store) {}

  ngAfterViewInit() {
    this.idToken$.subscribe(token => {
      if (token && this.agentRef) {
        this.agentRef.nativeElement.connect({ idToken: token, clientId: this.clientId });
      }
    });
  }
}

Module-based Setup

For non-standalone components, add the schema to your module:
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { ChatWidgetComponent } from './chat-widget.component';

@NgModule({
  declarations: [ChatWidgetComponent],
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
  exports: [ChatWidgetComponent],
})
export class ChatWidgetModule {}

See Also