{segments.map((segment, i) => {
if (segment.type === 'text') {
return
;
}
if (segment.type === 'tool') {
if (segment.frontendAction) {
return
;
}
return
;
}
return null;
})}
);
}
function ToolCard({ segment }) {
const isRunning = segment.status === 'running';
const isError = segment.status === 'error';
return (
{isRunning && }
{segment.tool}
{!isRunning && (isError ? : )}
{segment.args && (
{JSON.stringify(segment.args, null, 2)}
)}
{segment.result && (
{JSON.stringify(segment.result, null, 2)}
)}
{segment.error &&
{segment.error}
}
);
}
```
The tool card should be compact by default (just tool name + status icon) with collapsible sections for args and result, so it doesn't dominate the reading flow. While a tool is running (`status: 'running'`), show a spinner. When complete, show a check or error icon.
### Handling `__frontendAction` in Tool Results
When the AI calls certain tools (e.g., QR code, data view, payment, secret reveal), the tool result contains a `__frontendAction` object. This signals the frontend to render a special UI component **inline in the bubble at the tool segment's position** instead of the default collapsible ToolCard. This is already handled in the segments code above — when `segment.frontendAction` is present, render an `ActionCard` instead of a `ToolCard`.
The `extractFrontendAction` helper unwraps the action from various MCP response formats:
```js
function extractFrontendAction(result) {
if (!result) return null;
if (result.__frontendAction) return result.__frontendAction;
// Unwrap MCP wrapper format: result → result.result → content[].text → JSON
let data = result;
if (result?.result?.content) data = result.result;
if (data?.content && Array.isArray(data.content)) {
const textContent = data.content.find(c => c.type === 'text');
if (textContent?.text) {
try {
const parsed = JSON.parse(textContent.text);
if (parsed?.__frontendAction) return parsed.__frontendAction;
} catch { /* not JSON */ }
}
}
return null;
}
```
### Frontend Action Types
| Action Type | Component | Description |
|-------------|-----------|-------------|
| `qrcode` | `QrCodeActionCard` | Renders any string value as a QR code card |
| `dataView` | `DataViewActionCard` | Fetches a Business API route and renders a grid or gallery |
| `payment` | `PaymentActionCard` | "Pay Now" button that opens Stripe checkout modal |
#### QR Code Action (`type: "qrcode"`)
Triggered by the `showQrCode` MCP tool. Renders a QR code card from any string value.
```json
{
"__frontendAction": {
"type": "qrcode",
"value": "https://example.com/invite/ABC123",
"title": "Invite Link",
"subtitle": "Scan to open"
}
}
```
#### Data View Action (`type: "dataView"`)
Triggered by `showBusinessApiListInFrontEnd` or `showBusinessApiGalleryInFrontEnd`.
Frontend calls the provided Business API route using the user's bearer token, then renders:
- `viewType: "grid"` as tabular rows/columns
- `viewType: "gallery"` as image-first cards
```json
{
"__frontendAction": {
"type": "dataView",
"viewType": "grid",
"title": "Recent Orders",
"serviceName": "commerce",
"apiName": "listOrders",
"routePath": "/v1/listorders",
"httpMethod": "GET",
"queryParams": { "pageNo": 1, "pageRowCount": 10 },
"columns": [
{ "field": "id", "label": "Order ID" },
{ "field": "orderAmount", "label": "Amount", "format": "currency" }
]
}
}
```
#### Payment Action (`type: "payment"`)
Triggered by the `initiatePayment` MCP tool. Renders a payment card with amount and a "Pay Now" button.
```json
{
"__frontendAction": {
"type": "payment",
"orderId": "uuid",
"orderType": "order",
"serviceName": "commerce",
"amount": 99.99,
"currency": "USD",
"description": "Order #abc123"
}
}
```
### Conversation Management
```js
// List user's conversations
GET /api/chat/conversations
// Get conversation history
GET /api/chat/conversations/:conversationId
// Delete a conversation
DELETE /api/chat/conversations/:conversationId
```
---
## MCP Tool Discovery & Direct Invocation
The MCP BFF exposes endpoints for discovering and directly calling MCP tools (useful for debugging or building custom UIs).
### GET /api/tools — List All Tools
```js
const response = await fetch(`${mcpBffUrl}/api/tools`, { headers });
const { tools, count } = await response.json();
// tools: [{ name, description, inputSchema, service }, ...]
```
### GET /api/tools/service/:serviceName — List Service Tools
```js
const response = await fetch(`${mcpBffUrl}/api/tools/service/commerce`, { headers });
const { tools } = await response.json();
```
### POST /api/tools/call — Call a Tool Directly
```js
const response = await fetch(`${mcpBffUrl}/api/tools/call`, {
method: 'POST',
headers,
body: JSON.stringify({
toolName: "listProducts",
args: { page: 1, limit: 10 },
}),
});
const result = await response.json();
```
### GET /api/tools/status — Connection Status
```js
const status = await fetch(`${mcpBffUrl}/api/tools/status`, { headers });
// Returns health of each MCP service connection
```
### POST /api/tools/refresh — Reconnect Services
```js
await fetch(`${mcpBffUrl}/api/tools/refresh`, { method: 'POST', headers });
// Reconnects to all MCP services and refreshes the tool registry
```
---
## Elasticsearch API
The MCP BFF provides direct access to Elasticsearch for searching, filtering, and aggregating data across all project indices.
All Elasticsearch endpoints are under `/api/elastic`.
### GET /api/elastic/allIndices — List Project Indices
Returns all Elasticsearch indices belonging to this project (prefixed with `linkedin_`).
```js
const indices = await fetch(`${mcpBffUrl}/api/elastic/allIndices`, { headers });
// ["linkedin_products", "linkedin_orders", ...]
```
### POST /api/elastic/:indexName/rawsearch — Raw Elasticsearch Query
Execute a raw Elasticsearch query on a specific index.
```js
const response = await fetch(`${mcpBffUrl}/api/elastic/products/rawsearch`, {
method: 'POST',
headers,
body: JSON.stringify({
query: {
bool: {
must: [
{ match: { status: "active" } },
{ range: { price: { gte: 10, lte: 100 } } }
]
}
},
size: 20,
from: 0,
sort: [{ createdAt: "desc" }]
}),
});
const { total, hits, aggregations, took } = await response.json();
// hits: [{ _id, _index, _score, _source: { ...document... } }, ...]
```
Note: The index name is automatically prefixed with `linkedin_` if not already prefixed.
### POST /api/elastic/:indexName/search — Simplified Search
A higher-level search API with built-in support for filters, sorting, and pagination.
```js
const response = await fetch(`${mcpBffUrl}/api/elastic/products/search`, {
method: 'POST',
headers,
body: JSON.stringify({
search: "wireless headphones", // Full-text search
filters: { status: "active" }, // Field filters
sort: { field: "createdAt", order: "desc" },
page: 1,
limit: 25,
}),
});
```
### POST /api/elastic/:indexName/aggregate — Aggregations
Run aggregation queries for analytics and dashboards.
```js
const response = await fetch(`${mcpBffUrl}/api/elastic/orders/aggregate`, {
method: 'POST',
headers,
body: JSON.stringify({
aggs: {
status_counts: { terms: { field: "status.keyword" } },
total_revenue: { sum: { field: "amount" } },
monthly_orders: {
date_histogram: { field: "createdAt", calendar_interval: "month" }
}
},
query: { range: { createdAt: { gte: "now-1y" } } }
}),
});
```
### GET /api/elastic/:indexName/mapping — Index Mapping
Get the field mapping for an index (useful for building dynamic filter UIs).
```js
const mapping = await fetch(`${mcpBffUrl}/api/elastic/products/mapping`, { headers });
```
### POST /api/elastic/:indexName/ai-search — AI-Assisted Search
Uses the configured AI model to convert a natural-language query into an Elasticsearch query.
```js
const response = await fetch(`${mcpBffUrl}/api/elastic/orders/ai-search`, {
method: 'POST',
headers,
body: JSON.stringify({
query: "orders over $100 from last month that are still pending",
}),
});
// Returns: { total, hits, generatedQuery, ... }
```
---
## Log API
The MCP BFF provides log viewing endpoints for monitoring application behavior.
### GET /api/logs — Query Logs
```js
const response = await fetch(`${mcpBffUrl}/api/logs?page=1&limit=50&logType=2&service=commerce&search=payment`, {
headers,
});
```
**Query Parameters:**
- `page` — Page number (default: 1)
- `limit` — Items per page (default: 50)
- `logType` — 0=INFO, 1=WARNING, 2=ERROR
- `service` — Filter by service name
- `search` — Search in subject and message
- `from` / `to` — Date range (ISO strings)
- `requestId` — Filter by request ID
### GET /api/logs/stream — Real-time Console Stream (SSE)
Streams real-time console output from all services via Server-Sent Events.
```js
const eventSource = new EventSource(`${mcpBffUrl}/api/logs/stream?services=commerce,auth`, {
headers: { 'Authorization': `Bearer ${accessToken}` },
});
eventSource.addEventListener('log', (event) => {
const logEntry = JSON.parse(event.data);
// { service, timestamp, level, message, ... }
});
```
---
## Available Services
The MCP BFF connects to the following backend services:
| Service | Description |
|---------|-------------|
| `auth` | Authentication, user management, sessions |
| `jobApplication` | Microservice handling job postings (created by recruiters/company admins), job applications (created by users), allowing job search, application submission, and status update workflows. Enforces business rules around application status, admin controls, and lets professionals apply and track job applications .within the network. |
| `networking` | Handles professional networking logic for user-to-user connections: manages connection requests, accepted relationships, listing/removal, permissions, and state transitions. Publishes connection lifecycle events for notification... |
| `company` | Handles company profiles, company admin assignments, company following, and posting company updates/news. Enables professionals to follow companies, get updates, and enables admins to manage company presence.. |
| `content` | Handles creation, editing, and deletion of user posts (with attachments and visibility), user post feed aggregation, and post engagement (likes, comments). All with post-level visibility control (public/private).. |
| `messaging` | Handles direct, private 1:1 and group messaging between users, conversation management, and message history/storage.. |
| `profile` | Handles user professional profiles, including experience, education, skills, languages, certifications, profile photo, and visibility controls. Enables recruiter search, elastic-style indexing, and profile editing, with all data linked to authenticated users.. |
| `agentHub` | AI Agent Hub |
Each service exposes MCP tools that the AI can call through the BFF. Use `GET /api/tools` to discover all available tools at runtime, or `GET /api/tools/service/:serviceName` to list tools for a specific service.
---
## MCP as Internal API Gateway
The MCP-BFF service can also be used by the frontend as an **internal API gateway** for tool-based interactions. This is separate from external AI tool connections — it is meant for frontend code that needs to call backend tools programmatically.
### Direct Tool Calls (REST)
Use the REST tool invocation endpoints for programmatic access from frontend code:
```js
// List all available tools
const tools = await fetch(`${mcpBffUrl}/api/tools`, { headers });
// Call a specific tool directly
const result = await fetch(`${mcpBffUrl}/api/tools/call`, {
method: 'POST',
headers,
body: JSON.stringify({
toolName: 'listProducts',
args: { page: 1, limit: 10 },
}),
});
```
### AI-Orchestrated Calls (Chat API)
For AI-driven interactions, use the chat streaming API documented above (`POST /api/chat/stream`). The AI model decides which tools to call based on the user's message.
Both approaches use the user's JWT access token for authentication — the MCP-BFF forwards it to the correct backend service.
---
## MCP Connection Info for Profile Page
The user's **profile page** should include an informational section explaining how to connect external AI tools (Cursor, Claude Desktop, Lovable, Windsurf, etc.) to this application's backend via MCP.
### What to Display
The MCP-BFF exposes a **unified MCP endpoint** that aggregates tools from all backend services into a single connection point:
| Environment | URL |
|-------------|-----|
| **Preview** | `https://linkedin.prw.mindbricks.com/mcpbff-api/mcp` |
| **Staging** | `https://linkedin-stage.mindbricks.co/mcpbff-api/mcp` |
| **Production** | `https://linkedin.mindbricks.co/mcpbff-api/mcp` |
For legacy MCP clients that don't support StreamableHTTP, an SSE fallback is available at the same URL with `/sse` appended (e.g., `.../mcpbff-api/mcp/sse`).
### Profile Page UI Requirements
Add an **"MCP Connection"** or **"Connect External AI Tools"** card/section to the profile page with:
1. **Endpoint URL** — Display the MCP endpoint URL for the current environment with a copy-to-clipboard button.
2. **Ready-to-Copy Configs** — Show copy-to-clipboard config snippets for popular tools:
**Cursor** (`.cursor/mcp.json`):
```json
{
"mcpServers": {
"linkedin": {
"url": "https://linkedin.prw.mindbricks.com/mcpbff-api/mcp",
"headers": {
"Authorization": "Bearer your_access_token_here"
}
}
}
}
```
**Claude Desktop** (`claude_desktop_config.json`):
```json
{
"mcpServers": {
"linkedin": {
"url": "https://linkedin.prw.mindbricks.com/mcpbff-api/mcp",
"headers": {
"Authorization": "Bearer your_access_token_here"
}
}
}
}
```
3. **Auth Note** — Note that users should replace `your_access_token_here` with a valid JWT access token from the login API.
4. **OAuth Note** — Display a note that OAuth authentication is not currently supported for MCP connections.
5. **Available Tools** — Optionally show a summary of available tool categories (e.g., "CRUD operations for all data objects, custom business APIs, file operations") or link to the tools discovery endpoint (`GET /api/tools`).
---
**After this prompt, the user may give you new instructions to update the output of this prompt or provide subsequent prompts about the project.**
---