Blinksbuy MCP适配器(规范JSON v1.1)
AI自动化平台——模型上下文协议适配器
*版本:1.1·铁路部署就绪*
______________________________________________________________________
概述
这 MCP适配器 是所有外部渠道(网络、移动、语音、聊天、WhatsApp、ElevenLabs等)进入 模型上下文协议(MCP)平台.
它转换 原始客户端消息 进入a 标准JSON信封(v1.1) MCP编排者理解。\ 它还将MCP的规范响应转换回上游系统可以使用的与通道无关的JSON格式(TTS、聊天客户端、UI等)
此适配器可确保 所有通道使用一个统一的协议,实现一致性:
- 可观察性(跟踪/span/消息ID)
- LLM提示上下文
- 会话连续性
- 微服务安全路由
- 多租户行为
- 未来的多模式输入(音频、图像、事件等)
______________________________________________________________________
主要特点
- LLM就绪 –带有可选的LLM提示(型号、温度等)
- 微服务安全 –下游故障的标准化误差包络。
- 适配器无关 –适用于网络、语音、移动、WhatsApp等。
- 可追溯的 –
trace_id,span_id,message_id对于每一条消息。 - 版本可控 –规范信封v1.1,向后兼容v1.0。
- 面向未来的多式联运 –支持
type: text | audio | image | event.
______________________________________________________________________
环境变量
| 变量 | 描述 | 示例 |
|---|---|---|
MCP_URL | MCP编排器的URL /orchestrate | https://mcp-service.up.railway.app/orchestrate |
API_KEY 或 API_KEYS | 一个或多个允许的API密钥 | abc123,xyz789 |
______________________________________________________________________
认证
每一个规范请求 必须 包括:
X-API-Key: 没有有效密钥的请求将返回:
401 Unauthorized(无钥匙)403 Forbidden(无效密钥)
______________________________________________________________________
API终点
GET /health
基本健康检查。
答复:
{
"status": "ok",
"service": "mcp_adapter_python",
"mcp_url": "https://mcp-service.up.railway.app/orchestrate"
}______________________________________________________________________
POST /canonical/message (主要终点)
通道无关的规范消息网关。
标题:
X-API-Key:
Content-Type: application/json正文(规范请求信封v1.1–文本示例):
{
"version": "1.1",
"timestamp": "2025-11-21T21:28:56.146Z",
"context": {
"channel": "web",
"device": "browser",
"locale": "en-US",
"tenant": "blinksbuy",
"client_app": "elevenlabs",
"llm": {
"model_hint": "gpt-4.1-mini",
"temperature": 0.2
}
},
"session": {
"session_id": "user-123:web",
"conversation_id": "conv-001",
"user_id": "user-123",
"turn": 3
},
"request": {
"type": "text",
"text": "Can you read me the menu?",
"intent_override": null,
"metadata": {
"raw_transcript": "can you read me the menu",
"confidence": 0.97
}
},
"observability": {
"trace_id": "trace-abc-123",
"span_id": "span-inbound-1",
"message_id": "msg-0001"
}
}______________________________________________________________________
多模式示例(音频)
{
"version": "1.1",
"timestamp": "2025-11-21T21:30:00Z",
"context": {
"channel": "voice",
"device": "iphone",
"locale": "en-US",
"tenant": "blinksbuy",
"client_app": "elevenlabs"
},
"session": {
"session_id": "voice-user-44",
"conversation_id": "conv-331",
"user_id": "voice-user-44",
"turn": 12
},
"request": {
"type": "audio",
"audio_url": "https://cdn.you/audio.wav",
"transcript": "I would like to order garlic chicken"
},
"observability": {
"trace_id": "trace-22aa1bb3",
"span_id": "span-991",
"message_id": "msg-0002"
}
}______________________________________________________________________
规范响应(成功)
{
"version": "1.1",
"timestamp": "2025-11-21T21:28:56.146Z",
"context": {
"channel": "web",
"device": "browser",
"locale": "en-US",
"tenant": "blinksbuy",
"client_app": "elevenlabs"
},
"session": {
"session_id": "user-123:web",
"conversation_id": "conv-001",
"user_id": "user-123",
"turn": 4,
"route": "food_ordering.menu"
},
"response": {
"status": "success",
"code": 200,
"type": "text",
"text": "Here is the menu from Uno Bistro:\n\n1. Garlic Chicken – 500\n2. Sizzling Pata – 650\n3. Sisig – 400",
"metadata": {
"source": "mcp_orchestrator",
"duration_ms": 16250.315
}
},
"error": null,
"observability": {
"trace_id": "trace-abc-123",
"span_id": "span-outbound-1",
"message_id": "msg-0003"
}
}______________________________________________________________________
规范响应(错误)
{
"version": "1.1",
"timestamp": "2025-11-21T21:28:56.146Z",
"context": {
"channel": "web",
"device": "browser",
"locale": "en-US",
"tenant": "blinksbuy",
"client_app": "elevenlabs"
},
"session": {
"session_id": "user-123:web",
"conversation_id": "conv-001",
"user_id": "user-123",
"turn": 4,
"route": null
},
"response": {
"status": "error",
"code": 502,
"type": "text",
"text": null,
"metadata": {
"source": "mcp_adapter",
"duration_ms": 112.529
}
},
"error": {
"type": "MCP_ORCHESTRATOR_ERROR",
"code": 502,
"message": "MCP orchestrator error: 503 Service Unavailable",
"retryable": false,
"details": {
"mcp_url": "https://your-mcp-service.railway.app/orchestrate"
}
},
"observability": {
"trace_id": "trace-abc-123",
"span_id": "span-error-1",
"message_id": "msg-err-001"
}
}______________________________________________________________________
使用Postman进行测试
- 设置标题:
- X-API-Key: - Content-Type: application/json
- 邮寄至:
- https:///canonical/message
- 粘贴规范请求JSON正文并发送。
______________________________________________________________________
客户端集成和代码小部件
本节将展示不同客户端如何向Blinksbuy MCP适配器发送规范请求。
所有示例都针对规范文本端点:
POST https:///canonical/message
X-API-Key:
Content-Type: application/json请求体使用上面显示的规范JSON信封v1.1结构。
Python(请求)
import requests
import uuid
from datetime import datetime, timezone
API_KEY = "adapter-super-secret-key-1"
BASE_URL = "https://"
ENDPOINT = f"{BASE_URL}/canonical/message"
def build_payload(user_id: str, text: str) -> dict:
now = datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
session_id = f"{user_id}:web"
conversation_id = f"conv-{uuid.uuid4()}"
return {
"version": "1.1",
"timestamp": now,
"context": {
"channel": "web",
"device": "browser",
"locale": "en-US",
"tenant": "blinksbuy",
"client_app": "python-example",
"llm": {
"model_hint": "gpt-4.1-mini",
"temperature": 0.2,
},
},
"session": {
"session_id": session_id,
"conversation_id": conversation_id,
"user_id": user_id,
"turn": 1,
},
"request": {
"type": "text",
"text": text,
"intent_override": None,
"metadata": {
"raw_transcript": text,
"confidence": 1.0,
},
},
"observability": {
"trace_id": f"trace-{uuid.uuid4()}",
"span_id": f"span-{uuid.uuid4()}",
"message_id": f"msg-{uuid.uuid4()}",
},
}
def send_message(user_id: str, text: str):
headers = {
"X-API-Key": API_KEY,
"Content-Type": "application/json",
}
payload = build_payload(user_id, text)
resp = requests.post(ENDPOINT, json=payload, headers=headers, timeout=30)
resp.raise_for_status()
return resp.json()
if __name__ == "__main__":
response = send_message("user-123", "Can you read me the menu?")
print("Adapter response:")
print(response)Node.js(fetch)
import fetch from "node-fetch";
import { randomUUID } from "crypto";
const API_KEY = "adapter-super-secret-key-1";
const BASE_URL = "https://";
const ENDPOINT = `${BASE_URL}/canonical/message`;
function buildPayload(userId, text) {
const now = new Date().toISOString();
const sessionId = `${userId}:web`;
const conversationId = `conv-${randomUUID()}`;
return {
version: "1.1",
timestamp: now,
context: {
channel: "web",
device: "node",
locale: "en-US",
tenant: "blinksbuy",
client_app: "node-example",
llm: {
model_hint: "gpt-4.1-mini",
temperature: 0.2,
},
},
session: {
session_id: sessionId,
conversation_id: conversationId,
user_id: userId,
turn: 1,
},
request: {
type: "text",
text,
intent_override: null,
metadata: {
raw_transcript: text,
confidence: 1.0,
},
},
observability: {
trace_id: `trace-${randomUUID()}`,
span_id: `span-${randomUUID()}`,
message_id: `msg-${randomUUID()}`,
},
};
}
async function sendMessage(userId, text) {
const payload = buildPayload(userId, text);
const resp = await fetch(ENDPOINT, {
method: "POST",
headers: {
"X-API-Key": API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
});
if (!resp.ok) {
const errorText = await resp.text();
throw new Error(`Adapter error ${resp.status}: ${errorText}`);
}
const data = await resp.json();
console.log("Adapter response:", data);
}
sendMessage("user-123", "Can you read me the menu?").catch(console.error);浏览器HTML+JavaScript
注意:对于生产,不要在客户端代码中直接公开您的API密钥;使用后端代理。此示例用于内部测试和演示。
Blinksbuy MCP Adapter Demo
Blinksbuy MCP Adapter Demo
Message:
Send
const API_KEY = "adapter-super-secret-key-1"; // Do not expose in production
const BASE_URL = "https://";
const ENDPOINT = BASE_URL + "/canonical/message";
function buildPayload(userId, text) {
const now = new Date().toISOString();
const sessionId = userId + ":web";
const conversationId = "conv-" + crypto.randomUUID();
return {
version: "1.1",
timestamp: now,
context: {
channel: "web",
device: "browser",
locale: "en-US",
tenant: "blinksbuy",
client_app: "browser-example",
llm: {
model_hint: "gpt-4.1-mini",
temperature: 0.2,
},
},
session: {
session_id: sessionId,
conversation_id: conversationId,
user_id: userId,
turn: 1,
},
request: {
type: "text",
text: text,
intent_override: null,
metadata: {
raw_transcript: text,
confidence: 1.0,
},
},
observability: {
trace_id: "trace-" + crypto.randomUUID(),
span_id: "span-" + crypto.randomUUID(),
message_id: "msg-" + crypto.randomUUID(),
},
};
}
async function sendMessage(text) {
const userId = "web-demo-user";
const payload = buildPayload(userId, text);
const resp = await fetch(ENDPOINT, {
method: "POST",
headers: {
"X-API-Key": API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
});
const responseBox = document.getElementById("response-box");
if (!resp.ok) {
const errorText = await resp.text();
responseBox.textContent = "Error " + resp.status + ":\n" + errorText;
return;
}
const data = await resp.json();
responseBox.textContent = JSON.stringify(data, null, 2);
}
document.getElementById("send-btn").addEventListener("click", () => {
const text = document.getElementById("user-input").value;
sendMessage(text).catch((err) => {
document.getElementById("response-box").textContent = String(err);
});
});
PowerShell(调用RestMethod)
$endpoint = "https:///canonical/message"
$apiKey = "adapter-super-secret-key-1"
$userId = "ps-user-" + [guid]::NewGuid().ToString()
$sessionId = "$userId:web"
$conversationId = "conv-" + [guid]::NewGuid().ToString()
$traceId = "trace-" + [guid]::NewGuid().ToString()
$spanId = "span-" + [guid]::NewGuid().ToString()
$messageId = "msg-" + [guid]::NewGuid().ToString()
$text = "Hello from PowerShell. Can you read me the menu?"
$headers = @{
"Content-Type" = "application/json"
"X-API-Key" = $apiKey
}
$payload = @{
version = "1.1"
timestamp = (Get-Date).ToUniversalTime().ToString("o")
context = @{
channel = "web"
device = "powershell"
locale = "en-US"
tenant = "blinksbuy"
client_app = "powershell-client"
llm = @{
model_hint = "gpt-4.1-mini"
temperature = 0.2
}
}
session = @{
session_id = $sessionId
conversation_id = $conversationId
user_id = $userId
turn = 1
}
request = @{
type = "text"
text = $text
metadata = @{
raw_transcript = $text
confidence = 1.0
}
}
observability = @{
trace_id = $traceId
span_id = $spanId
message_id = $messageId
}
}
$json = $payload | ConvertTo-Json -Depth 10
$response = Invoke-RestMethod -Uri $endpoint -Method Post -Body $json -Headers $headers
$response | ConvertTo-Json -Depth 10邮差收藏(JSON)
您可以将以下收藏导入Postman(导入→ 原始文本):
{
"info": {
"name": "Blinksbuy MCP Adapter",
"_postman_id": "d5fd2fb2-9e09-49e3-9c8a-338b4a43c5bb",
"description": "Postman collection for testing the Blinksbuy MCP-compatible canonical message endpoint.",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"item": [
{
"name": "Canonical Message (Text)",
"request": {
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json"
},
{
"key": "X-API-Key",
"value": "{{API_KEY}}",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"version\": \"1.1\",\n \"timestamp\": \"{{timestamp}}\",\n \"context\": {\n \"channel\": \"web\",\n \"device\": \"postman\",\n \"locale\": \"en-US\",\n \"tenant\": \"blinksbuy\",\n \"client_app\": \"postman-client\",\n \"llm\": {\n \"model_hint\": \"gpt-4.1-mini\",\n \"temperature\": 0.2\n }\n },\n \"session\": {\n \"session_id\": \"{{session_id}}\",\n \"conversation_id\": \"{{conversation_id}}\",\n \"user_id\": \"{{user_id}}\",\n \"turn\": 1\n },\n \"request\": {\n \"type\": \"text\",\n \"text\": \"Hello from Postman. Can you read me the menu?\",\n \"intent_override\": null,\n \"metadata\": {\n \"raw_transcript\": \"Hello from Postman. Can you read me the menu?\",\n \"confidence\": 1.0\n }\n },\n \"observability\": {\n \"trace_id\": \"{{trace_id}}\",\n \"span_id\": \"{{span_id}}\",\n \"message_id\": \"{{message_id}}\"\n }\n}"
},
"url": {
"raw": "{{BASE_URL}}/canonical/message",
"host": [
"{{BASE_URL}}"
],
"path": [
"canonical",
"message"
]
}
},
"response": []
}
],
"event": [
{
"listen": "prerequest",
"script": {
"exec": [
"pm.variables.set("timestamp", new Date().toISOString());",
"pm:variables.set("user_id", "postman-user-" + crypto.randomUUID());",
"pm.variables.set("session_id", pm.variables.get("user_id") + ":web");",
"pm.variables.set("conversation_id", "conv-" + crypto.randomUUID());",
"pm.variables.set("trace_id", "trace-" + crypto.randomUUID());",
"pm.variables.set("span_id", "span-" + crypto.randomUUID());",
"pm.variables.set("message_id", "msg-" + crypto.randomUUID());"
],
"type": "text/javascript"
}
}
],
"variable": [
{
"key": "BASE_URL",
"value": "https://",
"type": "string"
},
{
"key": "API_KEY",
"value": "adapter-super-secret-key-1",
"type": "string"
}
]
}______________________________________________________________________
铁路部署
这个项目是 铁路准备就绪:
Procfile提供:
web: uvicorn app:app --host 0.0.0.0 --port ${PORT:-8000}- 铁路将:
- 从安装依赖项 requirements.txt - 检测Procfile - 公开指定的服务 $PORT
设置您的MCP_URL和API_KEY/API_KEYS在 铁路→ 变量.
______________________________________________________________________
项目结构
blinksbuy_mcp_adapter/
├── app.py # FastAPI app with Canonical v1.1 adapter logic
├── README.md # This documentation
├── requirements.txt # Python dependencies
├── Procfile # Railway process definition
└── .env.example # Example env vars (for local dev)______________________________________________________________________
总结
Blinksbuy MCP适配器是:
- 渠道无关
- 多租户和多地区
- LLM意识和多模式准备
- 端到端可追溯
- 专为现代AI自动化平台设计
- 已准备好在上部署 铁路 开箱即用
