React Chat UI SDK with speech, file upload, and task actions.
npm install mcp-chat-uibash
npm install mcp-chat-ui
`
Quick Start
Import styles once (e.g. in App.tsx):
`App.tsx
import "mcp-chat-ui/styles.css";
`
$3
Initialize the SDK before rendering ChatUI:
`ts
import { Init } from "mcp-chat-ui";
const initConfig = {
baseUrl: "https://apim.octopian.cloud",
apiSubscriptionKey: "",
loginSubscriptionKey: "",
token: "Bearer ",
isDab: false,
initializeChat: false,
showInitPanel: true,
contextWindow: "ComposeRequest",
initializeLanguage: "ar-JO",
initializeMessage: "",
};
Init(initConfig);
`
Render the UI (view config goes here):
`tsx
import { ChatUI } from "mcp-chat-ui";
export default function App() {
return (
speechRegion="swedencentral"
speechKey=""
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):
`ts
import { FinalizeSession } from "mcp-chat-ui";
await FinalizeSession({
domain: "dab.ae",
token: "Bearer ",
sessionId: "",
});
`
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 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:
`ts
Init({ ...initConfig, showInitPanel: false });
`
To auto-initialize on load:
`ts
Init({ ...initConfig, initializeChat: true });
`
API Reference
$3
`ts
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? }.
$3
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):
`tsx
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
`bash
npm run build
``