@mcp-layer/schema 1.0.3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -9
- package/package.json +4 -4
- package/src/index.js +43 -6
- package/types/index.d.ts +26 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @mcp-layer/schema
|
|
2
2
|
|
|
3
|
-
`@mcp-layer/schema` extracts MCP server definitions (tools, resources, prompts, templates, and MCP Apps metadata) and normalizes them into a unified
|
|
3
|
+
`@mcp-layer/schema` extracts MCP server definitions (tools, resources, prompts, templates, and MCP Apps metadata) and normalizes them into a unified schema backed by Zod 4. The output is designed for downstream generators that need a single contract to build CLIs, REST endpoints, UI renderers, or additional MCP layers without re-parsing the MCP protocol surface.
|
|
4
4
|
|
|
5
5
|
## Table of Contents
|
|
6
6
|
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
- [MCP Apps support](#mcp-apps-support)
|
|
12
12
|
- [Generator guidance](#generator-guidance)
|
|
13
13
|
- [Responsibilities and lifecycle](#responsibilities-and-lifecycle)
|
|
14
|
+
- [API Reference](#api-reference)
|
|
14
15
|
- [Error handling](#error-handling)
|
|
15
16
|
- [JSON Schema vs Zod](#json-schema-vs-zod)
|
|
16
17
|
- [Runtime Error Reference](#runtime-error-reference)
|
|
@@ -30,7 +31,7 @@ yarn add @mcp-layer/schema
|
|
|
30
31
|
```js
|
|
31
32
|
import { load } from '@mcp-layer/config';
|
|
32
33
|
import { connect } from '@mcp-layer/connect';
|
|
33
|
-
import { extract } from '@mcp-layer/schema';
|
|
34
|
+
import { composeCatalog, extract } from '@mcp-layer/schema';
|
|
34
35
|
|
|
35
36
|
const config = await load(undefined, process.cwd());
|
|
36
37
|
const session = await connect(config, 'demo');
|
|
@@ -39,15 +40,37 @@ const output = await extract(session);
|
|
|
39
40
|
console.log(output.server.info);
|
|
40
41
|
console.log(output.items[0]);
|
|
41
42
|
await session.close();
|
|
43
|
+
|
|
44
|
+
const catalog = composeCatalog({
|
|
45
|
+
server: {
|
|
46
|
+
info: { name: 'demo', version: '1.0.0' },
|
|
47
|
+
capabilities: { tools: {} },
|
|
48
|
+
instructions: 'Use the local catalog.',
|
|
49
|
+
},
|
|
50
|
+
tools: [{
|
|
51
|
+
name: 'echo',
|
|
52
|
+
description: 'Echo text.',
|
|
53
|
+
inputSchema: {
|
|
54
|
+
type: 'object',
|
|
55
|
+
properties: {
|
|
56
|
+
text: { type: 'string' },
|
|
57
|
+
},
|
|
58
|
+
required: ['text'],
|
|
59
|
+
},
|
|
60
|
+
}],
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
console.log(catalog.items[0]);
|
|
42
64
|
```
|
|
43
65
|
|
|
44
66
|
## What this package does
|
|
45
67
|
|
|
46
|
-
1) Reads the MCP server capabilities and metadata from the live client connection
|
|
68
|
+
1) Reads the MCP server capabilities and metadata from the live client connection with `extract(session)`.
|
|
47
69
|
2) Calls MCP list endpoints (`tools/list`, `resources/list`, `resources/templates/list`, `prompts/list`) using pagination.
|
|
48
|
-
3)
|
|
49
|
-
4)
|
|
50
|
-
5)
|
|
70
|
+
3) Composes the same normalized catalog shape from raw definitions with `composeCatalog(...)` when a live session is not available yet.
|
|
71
|
+
4) Normalizes everything into a unified, type-discriminated schema so generators can consume a single list.
|
|
72
|
+
5) Wraps tool input/output JSON Schemas into Zod validators backed by Ajv, while preserving the original JSON Schema.
|
|
73
|
+
6) Converts prompt arguments into a lightweight JSON Schema so prompts and tools share the same `detail.input` shape.
|
|
51
74
|
|
|
52
75
|
## Output shape (authoritative)
|
|
53
76
|
|
|
@@ -82,7 +105,7 @@ Type discriminator:
|
|
|
82
105
|
```js
|
|
83
106
|
detail: {
|
|
84
107
|
input: {
|
|
85
|
-
schema, // Zod schema (Ajv-backed)
|
|
108
|
+
schema, // Zod 4 schema (Ajv-backed)
|
|
86
109
|
json, // original JSON Schema
|
|
87
110
|
error // optional Ajv compile error message
|
|
88
111
|
},
|
|
@@ -143,10 +166,30 @@ Suggested uses for the unified schema:
|
|
|
143
166
|
|
|
144
167
|
## Responsibilities and lifecycle
|
|
145
168
|
|
|
146
|
-
-
|
|
169
|
+
- `extract(session)` does not open or close connections. It expects a live `Session` from `@mcp-layer/connect` or `@mcp-layer/attach`.
|
|
147
170
|
- You are responsible for calling `session.close()` after extraction.
|
|
171
|
+
- `composeCatalog(...)` is pure and does not require a connection.
|
|
148
172
|
- If the server doesn't advertise a capability (tools/resources/prompts), extraction skips that surface.
|
|
149
173
|
|
|
174
|
+
## API Reference
|
|
175
|
+
|
|
176
|
+
### `composeCatalog(input = {})`
|
|
177
|
+
|
|
178
|
+
Build a catalog from MCP data that is already available. This function does not connect to a server.
|
|
179
|
+
|
|
180
|
+
- **Input:** an optional `server` object with `info`, `capabilities`, and `instructions`, plus optional `tools`, `resources`, `templates`, and `prompts` arrays.
|
|
181
|
+
- **Result:** `{ server, items }`. Missing values become `undefined` or add no items. Tool input and output schemas use Zod 4 and Ajv.
|
|
182
|
+
- **Errors:** Ajv compile errors appear in the item's `error` field. This function does not make MCP calls.
|
|
183
|
+
|
|
184
|
+
### `extract(session)`
|
|
185
|
+
|
|
186
|
+
Read a catalog from an active `Session`.
|
|
187
|
+
|
|
188
|
+
- **Input:** a connected `Session` from `@mcp-layer/connect` or `@mcp-layer/attach`.
|
|
189
|
+
- **Result:** `Promise<{ server, items }>` with the same shape as `composeCatalog`.
|
|
190
|
+
- **Errors:** if `session.client` is missing, this function throws `LayerError` with reference `error-49ae61`. It passes MCP call errors to the caller.
|
|
191
|
+
- **Lifecycle:** this function does not close the session.
|
|
192
|
+
|
|
150
193
|
## Error handling
|
|
151
194
|
|
|
152
195
|
- Schema compilation uses Ajv under the hood. If a tool exposes an invalid JSON Schema, extraction still succeeds but `detail.input.error` or `detail.output.error` will be populated for that item.
|
|
@@ -155,7 +198,7 @@ Suggested uses for the unified schema:
|
|
|
155
198
|
|
|
156
199
|
## JSON Schema vs Zod
|
|
157
200
|
|
|
158
|
-
Zod
|
|
201
|
+
The `schema` field contains a Zod 4 validator backed by Ajv. Call `.parse()` or `.safeParse()` to validate data. The original JSON Schema stays in `detail.input.json` and `detail.output.json` for generators that need OpenAPI, JSON Schema, or another schema format.
|
|
159
202
|
|
|
160
203
|
## Runtime Error Reference
|
|
161
204
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mcp-layer/schema",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Extract and normalize MCP schemas into a unified Zod-based format.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -34,12 +34,12 @@
|
|
|
34
34
|
"access": "public"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"ajv": "^8.
|
|
38
|
-
"zod": "^
|
|
37
|
+
"ajv": "^8.20.0",
|
|
38
|
+
"zod": "^4.6.7",
|
|
39
39
|
"@mcp-layer/error": "0.2.1"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@mcp-layer/attach": "1.
|
|
42
|
+
"@mcp-layer/attach": "1.2.0",
|
|
43
43
|
"@mcp-layer/config": "1.0.2",
|
|
44
44
|
"@mcp-layer/connect": "1.2.1",
|
|
45
45
|
"@mcp-layer/test-server": "1.0.4"
|
package/src/index.js
CHANGED
|
@@ -416,6 +416,45 @@ function normalize(data) {
|
|
|
416
416
|
return list;
|
|
417
417
|
}
|
|
418
418
|
|
|
419
|
+
/**
|
|
420
|
+
* Derive advertised capabilities from the provided raw MCP definition sets.
|
|
421
|
+
* @param {{ tools?: Array<Record<string, unknown>>, resources?: Array<Record<string, unknown>>, templates?: Array<Record<string, unknown>>, prompts?: Array<Record<string, unknown>> }} data - Raw MCP definition sets.
|
|
422
|
+
* @returns {Record<string, unknown> | undefined}
|
|
423
|
+
*/
|
|
424
|
+
function capabilities(data) {
|
|
425
|
+
const caps = {};
|
|
426
|
+
|
|
427
|
+
if (Array.isArray(data.tools)) caps.tools = {};
|
|
428
|
+
if (Array.isArray(data.resources) || Array.isArray(data.templates)) caps.resources = {};
|
|
429
|
+
if (Array.isArray(data.prompts)) caps.prompts = {};
|
|
430
|
+
|
|
431
|
+
return Object.keys(caps).length > 0 ? caps : undefined;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Compose a unified catalog from raw MCP definitions without a live session.
|
|
436
|
+
* This lets adapters bootstrap routes from already-known tool/resource shapes
|
|
437
|
+
* while keeping the output identical to `extract(session)`.
|
|
438
|
+
*
|
|
439
|
+
* @param {{ server?: { info?: Record<string, unknown>, capabilities?: Record<string, unknown>, instructions?: string }, tools?: Array<Record<string, unknown>>, resources?: Array<Record<string, unknown>>, templates?: Array<Record<string, unknown>>, prompts?: Array<Record<string, unknown>> }} input - Raw server metadata and MCP definitions.
|
|
440
|
+
* @returns {{ server: { info: Record<string, unknown> | undefined, capabilities: Record<string, unknown> | undefined, instructions: string | undefined }, items: Array<Record<string, unknown>> }}
|
|
441
|
+
*/
|
|
442
|
+
export function composeCatalog(input = {}) {
|
|
443
|
+
const server = isrecord(input.server) ? input.server : {};
|
|
444
|
+
const info = isrecord(server.info) ? server.info : undefined;
|
|
445
|
+
const caps = isrecord(server.capabilities) ? server.capabilities : capabilities(input);
|
|
446
|
+
const instructions = typeof server.instructions === 'string' ? server.instructions : undefined;
|
|
447
|
+
|
|
448
|
+
return {
|
|
449
|
+
server: {
|
|
450
|
+
info,
|
|
451
|
+
capabilities: caps,
|
|
452
|
+
instructions,
|
|
453
|
+
},
|
|
454
|
+
items: normalize(input),
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
|
|
419
458
|
/**
|
|
420
459
|
* Extract MCP tool/resource/prompt schemas into a unified Zod-backed format.
|
|
421
460
|
* @param {import('@mcp-layer/session').Session} link - Active session with a connected MCP server.
|
|
@@ -451,14 +490,12 @@ export async function extract(link) {
|
|
|
451
490
|
|
|
452
491
|
if (caps && caps.prompts) data.prompts = await prompts(client);
|
|
453
492
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
return {
|
|
493
|
+
return composeCatalog({
|
|
457
494
|
server: {
|
|
458
495
|
info,
|
|
459
496
|
capabilities: caps,
|
|
460
|
-
instructions
|
|
497
|
+
instructions,
|
|
461
498
|
},
|
|
462
|
-
|
|
463
|
-
};
|
|
499
|
+
...data,
|
|
500
|
+
});
|
|
464
501
|
}
|
package/types/index.d.ts
CHANGED
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compose a unified catalog from raw MCP definitions without a live session.
|
|
3
|
+
* This lets adapters bootstrap routes from already-known tool/resource shapes
|
|
4
|
+
* while keeping the output identical to `extract(session)`.
|
|
5
|
+
*
|
|
6
|
+
* @param {{ server?: { info?: Record<string, unknown>, capabilities?: Record<string, unknown>, instructions?: string }, tools?: Array<Record<string, unknown>>, resources?: Array<Record<string, unknown>>, templates?: Array<Record<string, unknown>>, prompts?: Array<Record<string, unknown>> }} input - Raw server metadata and MCP definitions.
|
|
7
|
+
* @returns {{ server: { info: Record<string, unknown> | undefined, capabilities: Record<string, unknown> | undefined, instructions: string | undefined }, items: Array<Record<string, unknown>> }}
|
|
8
|
+
*/
|
|
9
|
+
export function composeCatalog(input?: {
|
|
10
|
+
server?: {
|
|
11
|
+
info?: Record<string, unknown>;
|
|
12
|
+
capabilities?: Record<string, unknown>;
|
|
13
|
+
instructions?: string;
|
|
14
|
+
};
|
|
15
|
+
tools?: Array<Record<string, unknown>>;
|
|
16
|
+
resources?: Array<Record<string, unknown>>;
|
|
17
|
+
templates?: Array<Record<string, unknown>>;
|
|
18
|
+
prompts?: Array<Record<string, unknown>>;
|
|
19
|
+
}): {
|
|
20
|
+
server: {
|
|
21
|
+
info: Record<string, unknown> | undefined;
|
|
22
|
+
capabilities: Record<string, unknown> | undefined;
|
|
23
|
+
instructions: string | undefined;
|
|
24
|
+
};
|
|
25
|
+
items: Array<Record<string, unknown>>;
|
|
26
|
+
};
|
|
1
27
|
/**
|
|
2
28
|
* Extract MCP tool/resource/prompt schemas into a unified Zod-backed format.
|
|
3
29
|
* @param {import('@mcp-layer/session').Session} link - Active session with a connected MCP server.
|