npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

mcp-chat-ui

v1.0.8

Published

React Chat UI SDK with speech, file upload, and task actions.

Downloads

514

Readme

MCP Chat UI SDK

React UI SDK that bundles a full chat experience with:

  • Login/init panel + session management
  • HTTP chat (no streaming/WS)
  • Speech-to-text and text-to-speech (Azure Speech SDK)
  • File uploads (SAS-based)
  • Task cards, take-action workflow, and document preview

Requirements

  • React 19 (peer dependency) and React DOM.
  • Node 18+ for build workflows.

Install

npm install mcp-chat-ui

Quick Start

Import styles once (e.g. in App.tsx):

import "mcp-chat-ui/styles.css";

Initialize the SDK

Initialize the SDK before rendering ChatUI:

import { Init } from "mcp-chat-ui";

const initConfig = {
  baseUrl: "https://apim.octopian.cloud",
  apiSubscriptionKey: "<apim-subscription-key>",
  loginSubscriptionKey: "<login-subscription-key>",
  token: "Bearer <token>",
  isDab: false,
  initializeChat: false,
  showInitPanel: true,
  contextWindow: "ComposeRequest",
  initializeLanguage: "ar-JO",
  initializeMessage: "",
};

Init(initConfig);

Render the UI (view config goes here):

import { ChatUI } from "mcp-chat-ui";

export default function App() {
  return (
    <ChatUI
      speechRegion="swedencentral"
      speechKey="<your-speech-key>"
      theme={{
        brand: "#0b1f33",
        panelBackground: "#ffffff",
        appBackground: "#f7f7f2",
        textMain: "#0b1f33",
      }}
      fonts={{
        base: "\"DM Sans\", system-ui, sans-serif",
      }}
    />
  );
}

Finalize a session (same API used by the Logout button):

import { FinalizeSession } from "mcp-chat-ui";

await FinalizeSession({
  domain: "dab.ae",
  token: "Bearer <token>",
  sessionId: "<session-id>",
});

If sessionId is omitted, the SDK uses the stored session ID.

Service Base URL

  • baseUrl drives the RequestStep, TransactionCatalog, Storage, Signature, and login endpoints used by the UI.
  • apiSubscriptionKey is sent to those service calls.
  • Chat initialization, chat messaging, and session finalization use the built-in MCP gateway base URL and API key (not baseUrl).

Initialize (Login) Flow

  • The login endpoint is derived from baseUrl.
  • apiSubscriptionKey is sent to the login endpoint (or override with loginSubscriptionKey).
  • token is required in Init (use an empty string if you plan to sign in via the panel and let it set the token).
  • initializeChat: true triggers initializeChat in ChatUI before the chat renders (shows a loading state with retry).
  • The login panel runs initializeChatClients followed by initializeChat.
  • If initializeChat is false, the chat waits until the user initializes from the login panel.

Token & Cache Notes

  • Tokens are normalized to the Bearer <token> format; if you pass a raw token it will be prefixed automatically.
  • The current auth token is stored in localStorage under chat.authToken.
  • Supplying a new token prop replaces the stored token.
  • When the token changes (detected during init), the SDK resets local state and clears cached data:
    • chat.msgs.* (message history per session)
    • chat.initCompleted.* (per-session init flags)
    • chat.serviceBaseUrl, chat.apiSubscriptionKey, chat.loginSubscriptionKey
    • chat.sessionId, chat.authToken, chat.contextWindow, chat.initUsername, chat.domain
    • speech.lang, speech.ttsLang
    • A new sessionId is generated and stored.
  • Logout calls FinalizeSession and clears local messages and session state.
  • Calling FinalizeSession() directly clears the same local storage keys and prefixes listed above.

Login From The UI

The SDK ships a Login panel (enabled by default). Click Login in the top bar, fill the fields (domain, username, password, context window, optional service/request step IDs, languages), then submit. The SDK stores common values in localStorage (session ID, auth token, domain, username) to keep continuity.

To hide the panel:

Init({ ...initConfig, showInitPanel: false });

To auto-initialize on load:

Init({ ...initConfig, initializeChat: true });

API Reference

Methods

import {
  Init,
  GetConfig,
  InitializeChatClients,
  FinalizeSession,
} from "mcp-chat-ui";
  • Init(config) (required): stores SDK config; must be called before rendering ChatUI.
  • GetConfig(): returns the last config passed to Init.
  • InitializeChatClients(options?): runs /api/initializeChatClients against the built-in MCP gateway. Options: { domain?, token? }.
  • FinalizeSession(options?): calls /api/deleteSessionContext against the built-in MCP gateway and clears SDK local storage. Options: { domain?, token?, sessionId? }.

Configuration

Init config (ChatUISDKConfig):

  • baseUrl (required): base URL for RequestStep/TransactionCatalog/Storage/Signature/login.
  • apiSubscriptionKey (required): subscription key for the base URL.
  • loginSubscriptionKey (required): login endpoint subscription key.
  • token (required): pre-set auth header value (include scheme).
  • isDab (required): if true, default domain is dab.ae, otherwise blank.
  • showInitPanel (optional, default true)
  • initializeChat (required)
  • contextWindow (required)
  • initializeLanguage (optional): locale sent to initializeChat (defaults to ar-JO).
  • initializeMessage (optional): initial message passed to initializeChat.

ChatUI props (ChatUIProps):

  • initServiceId, initRequestStepId
  • contextWindow, domain, token, initializeMessage
  • initPresets: optional { requester, provider } credentials used to prefill the preset buttons.
  • initialInitPreset: "requester" | "provider" | "custom" (default custom).
  • speechRegion, speechKey
  • speechLanguage or speechLang (transcription)
  • ttsLanguage or ttsLang
  • ttsVoiceMap: map of locale to Azure voice name.
  • theme: see tokens below.
  • fonts: { base, heading, mono }.
  • text: UI strings (login panel text is fixed and not configurable).
  • taskCardSize: { width?: number; height?: number } for task cards in the chat list.
  • onRequestAdded: called when AddRequestToolResult is a non-empty object.
  • onRequestProcessed: called when ProcessRequestToolResult is a non-empty object.

Theme Tokens

You can override any subset:

  • appBackground: main page background behind the chat surface.
  • panelBackground: main chat panel surface color.
  • panelBackgroundMuted: muted surface for translucent panels (top bar, composer).
  • panelBackgroundSubtle: lighter surface tint for subtle sections.
  • brand: primary brand color for buttons and accents.
  • brandHover: hover color for brand buttons.
  • brandAlpha30: brand color with ~30% alpha (badges/overlays).
  • brandAlpha40: brand color with ~40% alpha.
  • brandAlpha50: brand color with ~50% alpha.
  • textMain: primary text color.
  • textEmphasis: stronger text emphasis for headings.
  • textSupporting: secondary text color.
  • textMuted: muted body text color.
  • textSubtle: subtle labels and placeholders.
  • textDisabled: disabled or faint text color.
  • textOnBrand: text color used on brand backgrounds.
  • userMessageBackground: background color for user chat bubbles.
  • userMessageText: text color for user chat bubbles.
  • neutralLightest: light neutral background (50).
  • neutralLighter: light neutral background (100).
  • neutralMedium: neutral mid tone (400).
  • neutralDark: dark neutral (800).
  • neutralDarker: darkest neutral (900).
  • neutralDarker80: darkest neutral with ~80% alpha.
  • borderDefault: default border color.
  • accentBackground: accent background for info callouts.
  • accentText: accent text color for info callouts.
  • warningBackground: warning background for alerts.
  • warningText: warning text color for alerts.
  • errorBackground: error background for alerts.
  • errorText: error text color for alerts.
  • focusRing: subtle focus ring color.
  • focusRingStrong: stronger focus ring color.
  • outlineShadow: outline shadow color for buttons.
  • elevatedShadow: elevated shadow color for modals/cards.
  • selectOptionHover: select option hover/selected background color.
  • cardSelectedBackground: selected task card background color.

Legacy theme keys (e.g. primary, background, surface) are still accepted, but prefer the names above for new work.

Text Tokens

Override any subset of strings (login panel text is fixed):

<ChatUI
  text={{
    topBar: { clearButton: "Reset" },
    emptyState: { title: "Whats on the agenda today?" },
    composer: { placeholderDefault: "Ask me anything" },
  }}
/>;

Top bar:

  • topBar.sessionLabel
  • topBar.clearButton
  • topBar.clearTitle
  • topBar.logoutButton
  • topBar.logoutTitle
  • topBar.loginButton
  • topBar.loginTitle

Empty state:

  • emptyState.title

Composer:

  • composer.selectedTaskPrefix
  • composer.selectionLineTemplate (supports {id})
  • composer.selectedTaskClearTitle
  • composer.attachTitle
  • composer.placeholderAuthRequired
  • composer.placeholderDefault
  • composer.voiceStartTitle
  • composer.voiceStopTitle
  • composer.sendTitle

Voice overlay:

  • voiceOverlay.cancelTitle
  • voiceOverlay.confirmTitle

Message item:

  • messageItem.moreButton
  • messageItem.selectCardTitle
  • messageItem.stopReadingTitle
  • messageItem.readMessageTitle
  • messageItem.linkButtonLabel

Task cards:

  • taskCards.modalTitle
  • taskCards.takeActionButton
  • taskCards.showDocumentButton

Document viewer:

  • documentViewer.title
  • documentViewer.downloadButton
  • documentViewer.loading
  • documentViewer.iframeTitle
  • documentViewer.useGoogleViewer
  • documentViewer.useDirectViewer
  • documentViewer.errorSuffix
  • documentViewer.proceedButton

Take action:

  • takeAction.backAriaLabel
  • takeAction.closeAriaLabel
  • takeAction.actionTypeLabel
  • takeAction.selectActionPlaceholder
  • takeAction.approveOption
  • takeAction.rejectOption
  • takeAction.commentsLabel
  • takeAction.commentsPlaceholder
  • takeAction.noEditableAttributes
  • takeAction.selectSignaturePlaceholder
  • takeAction.selectOptionPlaceholder
  • takeAction.signaturePlaceholder
  • takeAction.cancelButton
  • takeAction.submitButton
  • takeAction.nextButton

Tool result:

  • toolResult.title

Alerts:

  • alerts.clearConfirm
  • alerts.clearFailedTemplate (supports {error})
  • alerts.fetchHistoryFailed
  • alerts.initMissingCredentials
  • alerts.initMissingBaseUrl
  • alerts.initMissingSubscriptionKey
  • alerts.initMissingEndpoint
  • alerts.initFailed
  • alerts.initNoToken
  • alerts.initChatFailedTemplate (supports {status}, {statusText}, {details})
  • alerts.initChatNetworkError
  • alerts.initChatErrorTemplate (supports {error})
  • alerts.initRequired
  • alerts.initNetworkError
  • alerts.initErrorTemplate (supports {error})

Errors:

  • errors.assistantMessageTemplate (supports {error})
  • errors.microphoneAccess
  • errors.transcriptionStart
  • errors.sasRequestFailedTemplate (supports {status}, {statusText}, {details})
  • errors.noSasEntries
  • errors.invalidSasEntry
  • errors.chatFailedTemplate (supports {status}, {statusText}, {details})
  • errors.takeActionAuthRequired
  • errors.takeActionMissingRequestStep
  • errors.takeActionMissingSignature
  • errors.takeActionNoDocument

Text Direction (LTR/RTL)

Chat layout direction is derived from language settings:

  • Chat layout direction (message alignment, list layout) is based on the transcription language. Set speechLanguage or speechLang to an RTL locale (for example ar, he, fa, ur, ps, dv, ku, ug, yi) to render the chat in RTL.
  • Composer input direction is auto-detected per input:
    • Uses the first strong RTL/LTR character you type.
    • Falls back to keyboard layout detection when available (navigator.keyboard.getLayoutMap()).
    • Falls back to the browser locale (navigator.language) if no direction is detected.

There is no explicit prop to force RTL/LTR; use speechLanguage/speechLang for chat layout direction and type an RTL character (or switch keyboard/layout) to flip the composer input direction.

Build

npm run build