Add API/schema version metadata to REST and MCP responses
This commit is contained in:
parent
80f46a70c9
commit
3cb6feeb15
@ -23,6 +23,11 @@ Open:
|
||||
- Health: `http://localhost:8787/health`
|
||||
- MCP UI bundle descriptor: `http://localhost:8787/mcp/ui-bundle`
|
||||
|
||||
Version metadata:
|
||||
- REST and MCP tool responses include `api_version` and `schema_version`.
|
||||
- Current values: `api_version=0.3.0`, `schema_version=1.0.0`.
|
||||
- Compatibility policy (current): additive, backward-compatible fields may be introduced in the same API minor version.
|
||||
|
||||
## REST API
|
||||
|
||||
### `POST /compile`
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
import { compile, analyze } from "./compile.js";
|
||||
const API_VERSION = "0.3.0";
|
||||
const SCHEMA_VERSION = "1.0.0";
|
||||
|
||||
const SERVER_INFO = {
|
||||
name: "schemeta-mcp",
|
||||
@ -87,10 +89,20 @@ function toolListResult() {
|
||||
};
|
||||
}
|
||||
|
||||
function withEnvelopeMeta(payload) {
|
||||
return {
|
||||
api_version: API_VERSION,
|
||||
schema_version: SCHEMA_VERSION,
|
||||
...payload
|
||||
};
|
||||
}
|
||||
|
||||
function uiBundleDescriptor() {
|
||||
return {
|
||||
name: "schemeta-workspace",
|
||||
version: "0.2.0",
|
||||
api_version: API_VERSION,
|
||||
schema_version: SCHEMA_VERSION,
|
||||
entry: "/",
|
||||
title: "Schemeta Workspace",
|
||||
transport: "iframe"
|
||||
@ -104,7 +116,7 @@ function handleToolCall(name, args) {
|
||||
|
||||
if (name === "schemeta_compile") {
|
||||
const payload = decodePayload(args.payload);
|
||||
const result = compile(payload, args.options ?? {});
|
||||
const result = withEnvelopeMeta(compile(payload, args.options ?? {}));
|
||||
return {
|
||||
content: [{ type: "text", text: JSON.stringify(result) }],
|
||||
structuredContent: result,
|
||||
@ -114,7 +126,7 @@ function handleToolCall(name, args) {
|
||||
|
||||
if (name === "schemeta_analyze") {
|
||||
const payload = decodePayload(args.payload);
|
||||
const result = analyze(payload, args.options ?? {});
|
||||
const result = withEnvelopeMeta(analyze(payload, args.options ?? {}));
|
||||
return {
|
||||
content: [{ type: "text", text: JSON.stringify(result) }],
|
||||
structuredContent: result,
|
||||
|
||||
@ -9,6 +9,8 @@ const PORT = Number(process.env.PORT ?? "8787");
|
||||
const MAX_BODY_BYTES = Number(process.env.MAX_BODY_BYTES ?? 2 * 1024 * 1024);
|
||||
const CORS_ORIGIN = process.env.CORS_ORIGIN ?? "*";
|
||||
const FRONTEND_ROOT = join(process.cwd(), "frontend");
|
||||
const API_VERSION = "0.3.0";
|
||||
const SCHEMA_VERSION = "1.0.0";
|
||||
|
||||
const MIME_TYPES = {
|
||||
".html": "text/html; charset=utf-8",
|
||||
@ -123,6 +125,14 @@ function parsePayloadOptions(body) {
|
||||
};
|
||||
}
|
||||
|
||||
function withEnvelopeMeta(payload) {
|
||||
return {
|
||||
api_version: API_VERSION,
|
||||
schema_version: SCHEMA_VERSION,
|
||||
...payload
|
||||
};
|
||||
}
|
||||
|
||||
const server = createServer(async (req, res) => {
|
||||
if (!req.url || !req.method) {
|
||||
return json(res, 400, errorEnvelope("invalid_request", "Invalid request."));
|
||||
@ -141,6 +151,8 @@ const server = createServer(async (req, res) => {
|
||||
return json(res, 200, {
|
||||
ok: true,
|
||||
service: "schemeta",
|
||||
api_version: API_VERSION,
|
||||
schema_version: SCHEMA_VERSION,
|
||||
status: "ok",
|
||||
date: new Date().toISOString()
|
||||
});
|
||||
@ -151,6 +163,8 @@ const server = createServer(async (req, res) => {
|
||||
ok: true,
|
||||
name: "schemeta-workspace",
|
||||
version: "0.2.0",
|
||||
api_version: API_VERSION,
|
||||
schema_version: SCHEMA_VERSION,
|
||||
entry: "/",
|
||||
title: "Schemeta Workspace",
|
||||
transport: "iframe"
|
||||
@ -161,7 +175,7 @@ const server = createServer(async (req, res) => {
|
||||
try {
|
||||
const body = await readBody(req);
|
||||
const parsed = parsePayloadOptions(body);
|
||||
return json(res, 200, analyze(parsed.payload, parsed.options));
|
||||
return json(res, 200, withEnvelopeMeta(analyze(parsed.payload, parsed.options)));
|
||||
} catch (err) {
|
||||
if (err?.code === "PAYLOAD_TOO_LARGE") {
|
||||
return json(res, 413, errorEnvelope("payload_too_large", `Request body exceeds ${MAX_BODY_BYTES} bytes.`));
|
||||
@ -177,7 +191,7 @@ const server = createServer(async (req, res) => {
|
||||
try {
|
||||
const body = await readBody(req);
|
||||
const parsed = parsePayloadOptions(body);
|
||||
return json(res, 200, compile(parsed.payload, parsed.options));
|
||||
return json(res, 200, withEnvelopeMeta(compile(parsed.payload, parsed.options)));
|
||||
} catch (err) {
|
||||
if (err?.code === "PAYLOAD_TOO_LARGE") {
|
||||
return json(res, 413, errorEnvelope("payload_too_large", `Request body exceeds ${MAX_BODY_BYTES} bytes.`));
|
||||
@ -198,8 +212,10 @@ const server = createServer(async (req, res) => {
|
||||
const laidOut = applyLayoutToModel(model, { respectLocks: false });
|
||||
return json(res, 200, {
|
||||
ok: true,
|
||||
api_version: API_VERSION,
|
||||
schema_version: SCHEMA_VERSION,
|
||||
model: laidOut,
|
||||
compile: compile(laidOut, parsed.options)
|
||||
compile: withEnvelopeMeta(compile(laidOut, parsed.options))
|
||||
});
|
||||
} catch (err) {
|
||||
if (err?.code === "PAYLOAD_TOO_LARGE") {
|
||||
@ -221,8 +237,10 @@ const server = createServer(async (req, res) => {
|
||||
const laidOut = applyLayoutToModel(model, { respectLocks: true });
|
||||
return json(res, 200, {
|
||||
ok: true,
|
||||
api_version: API_VERSION,
|
||||
schema_version: SCHEMA_VERSION,
|
||||
model: laidOut,
|
||||
compile: compile(laidOut, parsed.options)
|
||||
compile: withEnvelopeMeta(compile(laidOut, parsed.options))
|
||||
});
|
||||
} catch (err) {
|
||||
if (err?.code === "PAYLOAD_TOO_LARGE") {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user