@adia-ai/mcp 0.8.37

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.
@@ -0,0 +1,11 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+
3
+ /**
4
+ * Builds the A2UI protocol MCP server (4 tools: validate_document,
5
+ * get_registry_map, get_wiring_registry, protocol_status) with no transport
6
+ * attached. Exported for tests and for `scripts/build/generate-mcp-tools-md.mjs`;
7
+ * the module's own top-level `isEntryPoint()` guard is what actually starts a
8
+ * stdio transport when this file is run directly (`node server.js`), not when
9
+ * it is imported.
10
+ */
11
+ export function createServer(): McpServer;
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env node
2
+ import { realpathSync } from "node:fs";
3
+ import { fileURLToPath } from "node:url";
4
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
+ import { registerProtocolTools } from "./tools/protocol.js";
7
+ function createServer() {
8
+ const server = new McpServer({
9
+ name: "a2ui-protocol",
10
+ version: "0.1.0"
11
+ });
12
+ registerProtocolTools(server);
13
+ return server;
14
+ }
15
+ async function main() {
16
+ const server = createServer();
17
+ const transport = new StdioServerTransport();
18
+ await server.connect(transport);
19
+ console.error("[a2ui-protocol-mcp] stdio transport ready (4 protocol tools)");
20
+ }
21
+ function isEntryPoint() {
22
+ if (typeof process === "undefined" || !process.argv[1]) return false;
23
+ try {
24
+ return realpathSync(process.argv[1]) === realpathSync(fileURLToPath(import.meta.url));
25
+ } catch {
26
+ return false;
27
+ }
28
+ }
29
+ if (isEntryPoint()) {
30
+ main().catch((err) => {
31
+ console.error("[a2ui-protocol-mcp] fatal:", err);
32
+ if (typeof process !== "undefined") process.exit(1);
33
+ });
34
+ }
35
+ export {
36
+ createServer
37
+ };
@@ -0,0 +1,106 @@
1
+ import { z } from "zod";
2
+ import { registry, wiringRegistry } from "@adia-ai/a2ui";
3
+ import { validateSchema } from "@adia-ai/a2ui/validate";
4
+ const VALIDATE_DOCUMENT_DESCRIPTION = `Validate A2UI messages against the protocol: message envelope shape, flat-adjacency child references, component types resolvable in the runtime registry, and the semantic checks the renderer relies on (Card content model, renderable content, slot addressing).
5
+
6
+ This is the PROTOCOL-side form of validation. It needs no catalog and no corpus, so it validates any A2UI document from any producer. For catalog-aware validation (per-component prop schemas via the v0.9 catalog) plus anti-pattern scoring, use gen-ui-mcp's \`validate_schema\` instead.`;
7
+ const GET_REGISTRY_MAP_DESCRIPTION = `Get the A2UI protocol registry: every component type name mapped to the custom-element tag that renders it.
8
+
9
+ This is the registry view \u2014 the authoritative answer to "what types exist and what does each one render to". It carries no descriptions, categories, or prop schemas: those are catalog data and live on gen-ui-mcp's \`get_component_map\` tool instead. Alias types (several type names resolving to one tag, e.g. Toggle and Switch both -> switch-ui) are reported as such.`;
10
+ const GET_WIRING_REGISTRY_DESCRIPTION = `Get the A2UI wiring registry: controller types, action-handler names, and data-URI resolver schemes the runtime can resolve.
11
+
12
+ Read live from the runtime's wiringRegistry, so it cannot drift from what the renderer will actually accept. The richer authoring knowledge base (UI event payloads, refresh strategies, value sources, association types) is generation-side \u2014 see gen-ui-mcp's \`get_wiring_catalog\` tool instead.`;
13
+ const PROTOCOL_STATUS_DESCRIPTION = `Returns operational status of this A2UI protocol MCP server: transport and protocol-registry stats. Reports on the protocol server only \u2014 gen-ui-mcp's \`server_status\` tool reports its own corpus-side status separately.`;
14
+ function buildRegistryView() {
15
+ const byTag = /* @__PURE__ */ new Map();
16
+ for (const [type, tag] of registry.entries()) {
17
+ const list = byTag.get(tag);
18
+ if (list) list.push(type);
19
+ else byTag.set(tag, [type]);
20
+ }
21
+ const entries = [...byTag.entries()].map(([tag, types]) => ({
22
+ type: types[0],
23
+ tag,
24
+ aliases: types.slice(1)
25
+ })).sort((a, b) => a.type.localeCompare(b.type));
26
+ return { totalTypes: registry.size, totalTags: byTag.size, entries };
27
+ }
28
+ function buildWiringView() {
29
+ return {
30
+ controllers: [...wiringRegistry.controllers.keys()].sort(),
31
+ handlers: [...wiringRegistry.handlers.keys()].sort(),
32
+ uriSchemes: [...wiringRegistry.resolvers.keys()].sort()
33
+ };
34
+ }
35
+ function registerProtocolTools(server) {
36
+ server.tool(
37
+ "validate_document",
38
+ VALIDATE_DOCUMENT_DESCRIPTION,
39
+ {
40
+ messages: z.string().describe("JSON array of A2UI messages (a single message object is also accepted)")
41
+ },
42
+ async ({ messages }) => {
43
+ try {
44
+ const parsed = JSON.parse(messages);
45
+ const msgs = Array.isArray(parsed) ? parsed : [parsed];
46
+ const result = validateSchema(msgs);
47
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
48
+ } catch (err) {
49
+ const e = err instanceof Error ? err : new Error(String(err));
50
+ return { content: [{ type: "text", text: `Parse error: ${e.message}` }], isError: true };
51
+ }
52
+ }
53
+ );
54
+ server.tool(
55
+ "get_registry_map",
56
+ GET_REGISTRY_MAP_DESCRIPTION,
57
+ {},
58
+ async () => {
59
+ const view = buildRegistryView();
60
+ return { content: [{ type: "text", text: JSON.stringify(view, null, 2) }] };
61
+ }
62
+ );
63
+ server.tool(
64
+ "get_wiring_registry",
65
+ GET_WIRING_REGISTRY_DESCRIPTION,
66
+ {},
67
+ async () => {
68
+ return { content: [{ type: "text", text: JSON.stringify(buildWiringView(), null, 2) }] };
69
+ }
70
+ );
71
+ server.tool(
72
+ "protocol_status",
73
+ PROTOCOL_STATUS_DESCRIPTION,
74
+ {},
75
+ async () => {
76
+ const view = buildRegistryView();
77
+ const wiring = buildWiringView();
78
+ const transport = "stdio";
79
+ return {
80
+ content: [
81
+ {
82
+ type: "text",
83
+ text: JSON.stringify(
84
+ {
85
+ server: "@adia-ai/mcp (protocol)",
86
+ transport,
87
+ protocol: {
88
+ registryTypes: view.totalTypes,
89
+ registryTags: view.totalTags,
90
+ wiringControllers: wiring.controllers.length,
91
+ wiringHandlers: wiring.handlers.length,
92
+ uriSchemes: wiring.uriSchemes.length
93
+ }
94
+ },
95
+ null,
96
+ 2
97
+ )
98
+ }
99
+ ]
100
+ };
101
+ }
102
+ );
103
+ }
104
+ export {
105
+ registerProtocolTools
106
+ };