@tanstack/ai-mcp
Version:
Host-side Model Context Protocol client for TanStack AI: discover and run MCP server tools, resources, and prompts in any adapter's chat() loop, with generated end-to-end types.
195 lines (194 loc) • 6.17 kB
JavaScript
import { isJsonObject, isNonEmptyString, isRecord, issues } from "./value.js";
//#region src/events/wire.ts
var DELIVERY_MODES = /* @__PURE__ */ new Set([
"poll",
"push",
"webhook"
]);
function isIsoDateTime(value) {
if (!/^\d{4}-\d{2}-\d{2}T/.test(value)) return false;
return !Number.isNaN(Date.parse(value));
}
function isDeliveryMode(value) {
return typeof value === "string" && DELIVERY_MODES.has(value);
}
function parseEventDefinition(value) {
if (!isRecord(value)) return void 0;
if (!isNonEmptyString(value.name)) return void 0;
if (!Array.isArray(value.delivery) || value.delivery.length === 0) return;
const delivery = [];
for (const mode of value.delivery) {
if (!isDeliveryMode(mode)) return void 0;
delivery.push(mode);
}
if (!("inputSchema" in value) || !("payloadSchema" in value)) return void 0;
const description = typeof value.description === "string" ? value.description : void 0;
const meta = isJsonObject(value._meta) ? value._meta : void 0;
return {
name: value.name,
...description === void 0 ? {} : { description },
delivery,
inputSchema: value.inputSchema,
payloadSchema: value.payloadSchema,
...meta === void 0 ? {} : { _meta: meta }
};
}
var listEventsResult = { "~standard": {
version: 1,
vendor: "tanstack-ai-mcp",
validate(value) {
if (!isRecord(value) || !Array.isArray(value.events)) return issues("events/list result must include an events array");
const events = [];
for (const item of value.events) {
const event = parseEventDefinition(item);
if (event === void 0) return issues("events/list contains an invalid event descriptor");
events.push(event);
}
const nextCursor = value.nextCursor;
if (nextCursor !== void 0 && typeof nextCursor !== "string") return issues("nextCursor must be a string");
return { value: {
events,
...nextCursor === void 0 ? {} : { nextCursor }
} };
}
} };
var DELIVERY_STATUS_TYPES = {
active: "boolean",
lastDeliveryAt: "string",
lastError: "string",
failedSince: "string",
throttled: "boolean",
retryAfterMs: "number"
};
function isDeliveryStatus(value) {
if (!isRecord(value)) return false;
return Object.entries(DELIVERY_STATUS_TYPES).every(([field, type]) => {
const fieldValue = value[field];
if (fieldValue === void 0) return true;
if (field === "lastError" && fieldValue === null) return true;
return typeof fieldValue === type;
});
}
/** `undefined` when absent, `null` when present but malformed. */
function parseDeliveryStatus(value) {
if (value === void 0) return void 0;
return isDeliveryStatus(value) ? value : null;
}
var subscribeResult = { "~standard": {
version: 1,
vendor: "tanstack-ai-mcp",
validate(value) {
if (!isRecord(value) || !isNonEmptyString(value.id)) return issues("events/subscribe result must include id");
if (typeof value.truncated !== "boolean") return issues("events/subscribe result must include truncated");
if (value.refreshBefore !== null && typeof value.refreshBefore !== "string") return issues("refreshBefore must be an ISO timestamp or null");
if (typeof value.refreshBefore === "string" && !isIsoDateTime(value.refreshBefore)) return issues("refreshBefore must be an ISO timestamp or null");
let cursor = null;
if (value.cursor === void 0 || value.cursor === null) cursor = null;
else if (typeof value.cursor === "string") cursor = value.cursor;
else return issues("cursor must be a string or null");
const deliveryStatus = parseDeliveryStatus(value.deliveryStatus);
if (deliveryStatus === null) return issues("deliveryStatus has a field of the wrong type");
return { value: {
id: value.id,
refreshBefore: value.refreshBefore,
cursor,
truncated: value.truncated,
...deliveryStatus === void 0 ? {} : { deliveryStatus }
} };
}
} };
function parseEventOccurrence(value) {
if (!isRecord(value)) return void 0;
if (!isNonEmptyString(value.eventId) || !isNonEmptyString(value.name)) return;
if (typeof value.timestamp !== "string" || !isIsoDateTime(value.timestamp)) return;
const data = value.data;
if (!isJsonObject(data)) return void 0;
const event = {
eventId: value.eventId,
name: value.name,
timestamp: value.timestamp,
data
};
if (value.cursor === void 0) return event;
if (value.cursor !== null && typeof value.cursor !== "string") return void 0;
event.cursor = value.cursor;
return event;
}
/**
* Classify a parsed webhook JSON body as an event or a control envelope.
*
* @experimental
*/
function classifyWebhookBody(json) {
if (!isRecord(json)) return {
kind: "invalid",
issue: "body must be an object"
};
if (typeof json.type === "string") {
if (json.type === "verification") {
if (!isNonEmptyString(json.challenge)) return {
kind: "invalid",
issue: "verification requires challenge"
};
return {
kind: "verification",
challenge: json.challenge
};
}
if (json.type === "gap") {
if (!isNonEmptyString(json.cursor)) return {
kind: "invalid",
issue: "gap requires cursor"
};
return {
kind: "gap",
cursor: json.cursor
};
}
if (json.type === "terminated") {
if (!isRecord(json.error)) return {
kind: "invalid",
issue: "terminated requires error"
};
if (typeof json.error.code !== "number") return {
kind: "invalid",
issue: "terminated error.code must be a number"
};
if (typeof json.error.message !== "string") return {
kind: "invalid",
issue: "terminated error.message must be a string"
};
return {
kind: "terminated",
error: {
code: json.error.code,
message: json.error.message,
...json.error.data === void 0 ? {} : { data: json.error.data }
}
};
}
return {
kind: "invalid",
issue: `unknown control type ${json.type}`
};
}
const event = parseEventOccurrence(json);
if (event === void 0) return {
kind: "invalid",
issue: "invalid event envelope"
};
return {
kind: "event",
event
};
}
var emptyResult = { "~standard": {
version: 1,
vendor: "tanstack-ai-mcp",
validate() {
return { value: {} };
}
} };
//#endregion
export { classifyWebhookBody, emptyResult, listEventsResult, subscribeResult };
//# sourceMappingURL=wire.js.map