@revealui/mcp 0.2.0 → 0.3.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/LICENSE +104 -17
- package/README.md +16 -3
- package/dist/index.d.ts +1 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -17
- package/dist/index.js.map +1 -1
- package/dist/servers/contracts.d.ts +23 -0
- package/dist/servers/contracts.d.ts.map +1 -0
- package/dist/servers/contracts.js +34 -0
- package/dist/servers/contracts.js.map +1 -0
- package/dist/servers/factories/contracts.d.ts +7272 -0
- package/dist/servers/factories/contracts.d.ts.map +1 -0
- package/dist/servers/factories/contracts.js +646 -0
- package/dist/servers/factories/contracts.js.map +1 -0
- package/dist/servers/neon.d.ts.map +1 -1
- package/dist/servers/neon.js +1 -5
- package/dist/servers/neon.js.map +1 -1
- package/dist/servers/next-devtools.d.ts.map +1 -1
- package/dist/servers/next-devtools.js +0 -4
- package/dist/servers/next-devtools.js.map +1 -1
- package/dist/servers/playwright.d.ts.map +1 -1
- package/dist/servers/playwright.js +0 -4
- package/dist/servers/playwright.js.map +1 -1
- package/dist/servers/revealui-content.d.ts.map +1 -1
- package/dist/servers/revealui-content.js +0 -4
- package/dist/servers/revealui-content.js.map +1 -1
- package/dist/servers/revealui-email.d.ts.map +1 -1
- package/dist/servers/revealui-email.js +0 -6
- package/dist/servers/revealui-email.js.map +1 -1
- package/dist/servers/revealui-memory.d.ts.map +1 -1
- package/dist/servers/revealui-memory.js +0 -4
- package/dist/servers/revealui-memory.js.map +1 -1
- package/dist/servers/revealui-stripe.d.ts.map +1 -1
- package/dist/servers/revealui-stripe.js +0 -4
- package/dist/servers/revealui-stripe.js.map +1 -1
- package/dist/servers/stripe.d.ts.map +1 -1
- package/dist/servers/stripe.js +1 -5
- package/dist/servers/stripe.js.map +1 -1
- package/dist/servers/supabase.d.ts.map +1 -1
- package/dist/servers/supabase.js +0 -4
- package/dist/servers/supabase.js.map +1 -1
- package/dist/servers/vercel.d.ts.map +1 -1
- package/dist/servers/vercel.js +1 -5
- package/dist/servers/vercel.js.map +1 -1
- package/package.json +10 -5
- package/LICENSE.commercial +0 -90
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../../src/servers/factories/contracts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAWnE,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AA8K3B,QAAA,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmO6B,CAAC;AAEnD,KAAK,YAAY,GAAG,MAAM,OAAO,eAAe,CAAC;AAEjD;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,YAAY,CAAC;AAMhD,eAAO,MAAM,qBAAqB,EAAiB,SAAS,MAAM,EAAE,CAAC;AACrE,eAAO,MAAM,wBAAwB,+CAAoB,CAAC;AAM1D;;;;;GAKG;AACH,MAAM,WAAW,uBAAuB;IACtC,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,sGAAsG;IACtG,OAAO,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAAC,oBAAoB,EAAE,uBAAuB,CAAC,CAqB3F;AAyBD,UAAU,eAAe;IACvB,OAAO,EAAE,IAAI,CAAC;IACd,QAAQ,EAAE,YAAY,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;CACf;AAED,UAAU,eAAe;IACvB,OAAO,EAAE,KAAK,CAAC;IACf,QAAQ,EAAE,YAAY,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,KAAK,CAAC;QACZ,IAAI,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;QACjC,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;CACJ;AAED,KAAK,cAAc,GAAG,eAAe,GAAG,eAAe,CAAC;AAExD,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,YAAY,EACtB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,OAAO,GACZ,cAAc,CAoChB;AA2ID,MAAM,WAAW,4BAA4B;IAC3C;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,CAAC,EAAE,4BAA4B,GAAG,MAAM,CA6JpF"}
|
|
@@ -0,0 +1,646 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Factory for the `revealui-contracts` MCP server.
|
|
3
|
+
*
|
|
4
|
+
* Phase 1 of the protocol-pyramid ADR
|
|
5
|
+
* (`docs/decisions/2026-05-03-contracts-protocol-pyramid.md`): exposes every
|
|
6
|
+
* `@revealui/contracts` category as MCP **resources** (read-only catalog of
|
|
7
|
+
* JSON Schemas) plus per-category MCP **tools** that parse a payload against
|
|
8
|
+
* the category's primary schema and return either the typed value or the
|
|
9
|
+
* Zod issues.
|
|
10
|
+
*
|
|
11
|
+
* ## Resources
|
|
12
|
+
*
|
|
13
|
+
* - `revealui-contracts://catalog` — discovery payload listing every
|
|
14
|
+
* category, its primary schema name, and every secondary schema name.
|
|
15
|
+
* - `revealui-contracts://<category>` — JSON document with
|
|
16
|
+
* `{ category, primarySchema, schemas: Record<name, JSONSchema7> }`.
|
|
17
|
+
*
|
|
18
|
+
* ## Tools
|
|
19
|
+
*
|
|
20
|
+
* - `contracts_list_categories` — returns the same payload as the
|
|
21
|
+
* `revealui-contracts://catalog` resource (tool form for clients that
|
|
22
|
+
* prefer tool-call ergonomics).
|
|
23
|
+
* - `contracts_get_schema` — returns the JSON Schema for a single
|
|
24
|
+
* `(category, schemaName?)` pair.
|
|
25
|
+
* - `contracts_validate_<category>` (one per registered category) —
|
|
26
|
+
* accepts `{ schema?: string, data: unknown }`, returns
|
|
27
|
+
* `{ success: true, data }` | `{ success: false, issues }`.
|
|
28
|
+
*
|
|
29
|
+
* ## Categories (17)
|
|
30
|
+
*
|
|
31
|
+
* Each category has a primary schema (the first secondary schema is the
|
|
32
|
+
* default for `validate` when `schema` is omitted) plus zero or more
|
|
33
|
+
* secondary schemas. Three of the categories (`devkit_profiles`,
|
|
34
|
+
* `providers`, `stripe_webhook_events`) lift TS-only `as const` arrays
|
|
35
|
+
* into `z.enum` for runtime validation; one (`content_validation`) lifts
|
|
36
|
+
* a TS interface into a small `z.object`. The others use the contracts
|
|
37
|
+
* package's hand-written or drizzle-zod-generated Zod schemas as-is.
|
|
38
|
+
*
|
|
39
|
+
* Out of scope for Phase 1 (no validation surface): `foundation`
|
|
40
|
+
* (meta-types only — `Contract<T>` is a generic), `actions`
|
|
41
|
+
* (class-based validator, not a Zod schema), `pricing` (TS interfaces),
|
|
42
|
+
* `database` (bridge utilities — covered by `generated`).
|
|
43
|
+
*
|
|
44
|
+
* ## License
|
|
45
|
+
*
|
|
46
|
+
* This server is **not** Pro-gated. `@revealui/contracts` is MIT and
|
|
47
|
+
* agent-side introspection of its schemas is meant to enable any client
|
|
48
|
+
* (Claude Code, Cursor, custom agents) to integrate cleanly. Pro-gating
|
|
49
|
+
* a public-package primitive would defeat the purpose.
|
|
50
|
+
*/
|
|
51
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
52
|
+
import { CallToolRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
53
|
+
import { z } from 'zod/v4';
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
// Imports — Zod schemas grouped by category
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
import { DEVKIT_PROFILES, LLM_PROVIDERS, RELEVANT_STRIPE_WEBHOOK_EVENTS, RVUI_TOKEN_CONFIG, } from '@revealui/contracts';
|
|
58
|
+
import { A2AAgentCardSchema, A2AArtifactSchema, A2AAuthSchema, A2ACapabilitiesSchema, A2AJsonRpcRequestSchema, A2AJsonRpcResponseSchema, A2AMessageSchema, A2APartSchema, A2AProviderSchema, A2ASendTaskParamsSchema, A2ASkillSchema, A2ATaskSchema, A2ATaskStateSchema, A2ATaskStatusSchema, } from '@revealui/contracts/a2a';
|
|
59
|
+
import { CollectionContract, ConfigContract } from '@revealui/contracts/admin';
|
|
60
|
+
import { AgentActionRecordSchema, AgentDefinitionSchema, AgentMemorySchema, AgentStateSchema, AgentContextSchema as AgentsContextSchema, ConversationMessageSchema, ConversationSchema, IntentSchema, IntentTypeSchema, MemorySourceSchema, MemoryTypeSchema, ToolDefinitionSchema, ToolParameterSchema, } from '@revealui/contracts/agents';
|
|
61
|
+
import { MFABackupCodeRequestSchema, MFADisableRequestSchema, MFASetupResponseSchema, MFAVerifyRequestSchema, PasskeyAuthenticateOptionsRequestSchema, PasskeyAuthenticateVerifyRequestSchema, PasskeyListResponseSchema, PasskeyRegisterOptionsRequestSchema, PasskeyRegisterVerifyRequestSchema, PasskeyUpdateRequestSchema, PasswordResetRequestSchema, PasswordResetTokenSchema, RecoveryRequestSchema, RecoveryVerifyRequestSchema, SignInRequestSchema, SignUpRequestSchema, } from '@revealui/contracts/api/auth';
|
|
62
|
+
import { ChatMessageSchema, ChatRequestSchema } from '@revealui/contracts/api/chat';
|
|
63
|
+
import { GDPRDeleteRequestSchema, GDPRExportRequestSchema } from '@revealui/contracts/api/gdpr';
|
|
64
|
+
import { AccordionBlockSchema, BlockMetaSchema, BlockSchema, BlockStyleSchema, ButtonBlockSchema, CodeBlockSchema, ColumnsBlockSchema, ComponentBlockSchema, DividerBlockSchema, EmbedBlockSchema, FormBlockSchema, GridBlockSchema, HeadingBlockSchema, HtmlBlockSchema, ImageBlockSchema, ListBlockSchema, QuoteBlockSchema, SpacerBlockSchema, TableBlockSchema, TabsBlockSchema, TextBlockSchema, VideoBlockSchema, } from '@revealui/contracts/content';
|
|
65
|
+
import { PageLockSchema, PageSchema, SessionSchema, SiteSchema, UserSchema, } from '@revealui/contracts/entities';
|
|
66
|
+
import { AccountsInsertSchema, AccountsSelectSchema, AgentContextsInsertSchema, AgentMemoriesInsertSchema, PagesInsertSchema, SessionsInsertSchema, SitesInsertSchema, UsersInsertSchema, UsersSelectSchema, } from '@revealui/contracts/generated/zod-schemas';
|
|
67
|
+
import { AgentActionDefinitionSchema, AgentConstraintSchema, AgentRelationSchema, AgentRepresentationSchema, DualEntitySchema, EmbeddingSchema, HumanRepresentationSchema, } from '@revealui/contracts/representation';
|
|
68
|
+
import { RotationEventSchema, RotationReasonSchema, SecretActorSchema, SecretActorTypeSchema, SecretAuditEventSchema, SecretAuditEventTypeSchema, SecretPathSchema, } from '@revealui/contracts/secrets';
|
|
69
|
+
import { IssueLocationSchema, SecurityCategorySchema, SecurityFindingSchema, SecurityRuleSchema, SecuritySeveritySchema, } from '@revealui/contracts/security';
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
// Derived schemas (lift TS-only constants into Zod for runtime validation)
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
const DevkitProfileIdSchema = z.enum(DEVKIT_PROFILES);
|
|
74
|
+
const LlmProviderSchema = z.enum(LLM_PROVIDERS);
|
|
75
|
+
const StripeWebhookEventSchema = z.enum(RELEVANT_STRIPE_WEBHOOK_EVENTS);
|
|
76
|
+
const ContentValidationConfigSchema = z.object({
|
|
77
|
+
maxDepth: z.number().int().positive(),
|
|
78
|
+
maxSizeBytes: z.number().int().positive(),
|
|
79
|
+
});
|
|
80
|
+
const RvuiTokenConfigSchema = z.object({
|
|
81
|
+
name: z.string(),
|
|
82
|
+
symbol: z.string(),
|
|
83
|
+
decimals: z.number().int().nonnegative(),
|
|
84
|
+
totalSupply: z.bigint().or(z.string()),
|
|
85
|
+
description: z.string(),
|
|
86
|
+
});
|
|
87
|
+
// biome-ignore lint/suspicious/noExplicitAny: Zod schemas vary in shape.
|
|
88
|
+
const SCHEMA_REGISTRY = {
|
|
89
|
+
a2a: {
|
|
90
|
+
primary: 'agentCard',
|
|
91
|
+
description: 'Agent-to-Agent (A2A) protocol contracts — AgentCard, Task, Message, Skill, Artifact, JSON-RPC envelopes.',
|
|
92
|
+
schemas: {
|
|
93
|
+
agentCard: A2AAgentCardSchema,
|
|
94
|
+
artifact: A2AArtifactSchema,
|
|
95
|
+
auth: A2AAuthSchema,
|
|
96
|
+
capabilities: A2ACapabilitiesSchema,
|
|
97
|
+
jsonRpcRequest: A2AJsonRpcRequestSchema,
|
|
98
|
+
jsonRpcResponse: A2AJsonRpcResponseSchema,
|
|
99
|
+
message: A2AMessageSchema,
|
|
100
|
+
part: A2APartSchema,
|
|
101
|
+
provider: A2AProviderSchema,
|
|
102
|
+
sendTaskParams: A2ASendTaskParamsSchema,
|
|
103
|
+
skill: A2ASkillSchema,
|
|
104
|
+
task: A2ATaskSchema,
|
|
105
|
+
taskState: A2ATaskStateSchema,
|
|
106
|
+
taskStatus: A2ATaskStatusSchema,
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
admin: {
|
|
110
|
+
primary: 'collection',
|
|
111
|
+
description: 'admin configuration contracts — CollectionContract + ConfigContract wrap typed admin shapes in the Contract<T> pattern.',
|
|
112
|
+
schemas: {
|
|
113
|
+
collection: CollectionContract.schema,
|
|
114
|
+
config: ConfigContract.schema,
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
agents: {
|
|
118
|
+
primary: 'agentMemory',
|
|
119
|
+
description: 'LLM agent behavior contracts — AgentMemory (semantic memory with embeddings), Conversation, AgentDefinition, Tool, Intent.',
|
|
120
|
+
schemas: {
|
|
121
|
+
agentActionRecord: AgentActionRecordSchema,
|
|
122
|
+
agentContext: AgentsContextSchema,
|
|
123
|
+
agentDefinition: AgentDefinitionSchema,
|
|
124
|
+
agentMemory: AgentMemorySchema,
|
|
125
|
+
agentState: AgentStateSchema,
|
|
126
|
+
conversation: ConversationSchema,
|
|
127
|
+
conversationMessage: ConversationMessageSchema,
|
|
128
|
+
intent: IntentSchema,
|
|
129
|
+
intentType: IntentTypeSchema,
|
|
130
|
+
memorySource: MemorySourceSchema,
|
|
131
|
+
memoryType: MemoryTypeSchema,
|
|
132
|
+
toolDefinition: ToolDefinitionSchema,
|
|
133
|
+
toolParameter: ToolParameterSchema,
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
api_auth: {
|
|
137
|
+
primary: 'signIn',
|
|
138
|
+
description: 'Auth API request/response contracts — sign-in, sign-up, password reset, MFA, passkey, recovery flows.',
|
|
139
|
+
schemas: {
|
|
140
|
+
signIn: SignInRequestSchema,
|
|
141
|
+
signUp: SignUpRequestSchema,
|
|
142
|
+
passwordReset: PasswordResetRequestSchema,
|
|
143
|
+
passwordResetToken: PasswordResetTokenSchema,
|
|
144
|
+
mfaSetupResponse: MFASetupResponseSchema,
|
|
145
|
+
mfaVerify: MFAVerifyRequestSchema,
|
|
146
|
+
mfaDisable: MFADisableRequestSchema,
|
|
147
|
+
mfaBackupCode: MFABackupCodeRequestSchema,
|
|
148
|
+
passkeyRegisterOptions: PasskeyRegisterOptionsRequestSchema,
|
|
149
|
+
passkeyRegisterVerify: PasskeyRegisterVerifyRequestSchema,
|
|
150
|
+
passkeyAuthenticateOptions: PasskeyAuthenticateOptionsRequestSchema,
|
|
151
|
+
passkeyAuthenticateVerify: PasskeyAuthenticateVerifyRequestSchema,
|
|
152
|
+
passkeyList: PasskeyListResponseSchema,
|
|
153
|
+
passkeyUpdate: PasskeyUpdateRequestSchema,
|
|
154
|
+
recovery: RecoveryRequestSchema,
|
|
155
|
+
recoveryVerify: RecoveryVerifyRequestSchema,
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
api_chat: {
|
|
159
|
+
primary: 'chatRequest',
|
|
160
|
+
description: 'Chat API contracts — ChatRequest body + ChatMessage shapes.',
|
|
161
|
+
schemas: {
|
|
162
|
+
chatRequest: ChatRequestSchema,
|
|
163
|
+
chatMessage: ChatMessageSchema,
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
api_gdpr: {
|
|
167
|
+
primary: 'gdprExport',
|
|
168
|
+
description: 'GDPR API contracts — data export and account deletion request shapes.',
|
|
169
|
+
schemas: {
|
|
170
|
+
gdprExport: GDPRExportRequestSchema,
|
|
171
|
+
gdprDelete: GDPRDeleteRequestSchema,
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
content: {
|
|
175
|
+
primary: 'block',
|
|
176
|
+
description: 'Content block contracts — discriminated union of 17 block variants (text, heading, image, code, table, columns, grid, form, etc.).',
|
|
177
|
+
schemas: {
|
|
178
|
+
block: BlockSchema,
|
|
179
|
+
blockMeta: BlockMetaSchema,
|
|
180
|
+
blockStyle: BlockStyleSchema,
|
|
181
|
+
accordion: AccordionBlockSchema,
|
|
182
|
+
button: ButtonBlockSchema,
|
|
183
|
+
code: CodeBlockSchema,
|
|
184
|
+
columns: ColumnsBlockSchema,
|
|
185
|
+
component: ComponentBlockSchema,
|
|
186
|
+
divider: DividerBlockSchema,
|
|
187
|
+
embed: EmbedBlockSchema,
|
|
188
|
+
form: FormBlockSchema,
|
|
189
|
+
grid: GridBlockSchema,
|
|
190
|
+
heading: HeadingBlockSchema,
|
|
191
|
+
html: HtmlBlockSchema,
|
|
192
|
+
image: ImageBlockSchema,
|
|
193
|
+
list: ListBlockSchema,
|
|
194
|
+
quote: QuoteBlockSchema,
|
|
195
|
+
spacer: SpacerBlockSchema,
|
|
196
|
+
table: TableBlockSchema,
|
|
197
|
+
tabs: TabsBlockSchema,
|
|
198
|
+
text: TextBlockSchema,
|
|
199
|
+
video: VideoBlockSchema,
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
content_validation: {
|
|
203
|
+
primary: 'config',
|
|
204
|
+
description: 'Lexical content validation config — limits applied by validateLexicalContent (max nesting depth + max payload bytes).',
|
|
205
|
+
schemas: {
|
|
206
|
+
config: ContentValidationConfigSchema,
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
devkit_profiles: {
|
|
210
|
+
primary: 'profileId',
|
|
211
|
+
description: 'DevKit profile id (Max-tier paywall feature) — one of revealui, agents, claude, cursor, zed.',
|
|
212
|
+
schemas: {
|
|
213
|
+
profileId: DevkitProfileIdSchema,
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
entities: {
|
|
217
|
+
primary: 'user',
|
|
218
|
+
description: 'Domain entity contracts — User, Site, Page, Session, plus PageLock. Add more secondary schemas in subsequent phases.',
|
|
219
|
+
schemas: {
|
|
220
|
+
user: UserSchema,
|
|
221
|
+
page: PageSchema,
|
|
222
|
+
pageLock: PageLockSchema,
|
|
223
|
+
session: SessionSchema,
|
|
224
|
+
site: SiteSchema,
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
generated: {
|
|
228
|
+
primary: 'usersInsert',
|
|
229
|
+
description: 'Drizzle-zod-generated Insert/Select schemas reflecting raw DB columns. Sample of the most-used tables (full set is 86+ schemas).',
|
|
230
|
+
schemas: {
|
|
231
|
+
accountsSelect: AccountsSelectSchema,
|
|
232
|
+
accountsInsert: AccountsInsertSchema,
|
|
233
|
+
agentContextsInsert: AgentContextsInsertSchema,
|
|
234
|
+
agentMemoriesInsert: AgentMemoriesInsertSchema,
|
|
235
|
+
pagesInsert: PagesInsertSchema,
|
|
236
|
+
sessionsInsert: SessionsInsertSchema,
|
|
237
|
+
sitesInsert: SitesInsertSchema,
|
|
238
|
+
usersSelect: UsersSelectSchema,
|
|
239
|
+
usersInsert: UsersInsertSchema,
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
providers: {
|
|
243
|
+
primary: 'providerId',
|
|
244
|
+
description: 'Supported LLM provider id — one of groq, huggingface, inference-snaps, ollama. Open models only.',
|
|
245
|
+
schemas: {
|
|
246
|
+
providerId: LlmProviderSchema,
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
representation: {
|
|
250
|
+
primary: 'dualEntity',
|
|
251
|
+
description: 'Dual representation layer — DualEntity wraps every entity with both Human and Agent views. Includes Embedding, AgentRepresentation, HumanRepresentation, AgentAction, AgentConstraint, AgentRelation.',
|
|
252
|
+
schemas: {
|
|
253
|
+
dualEntity: DualEntitySchema,
|
|
254
|
+
embedding: EmbeddingSchema,
|
|
255
|
+
agentRepresentation: AgentRepresentationSchema,
|
|
256
|
+
humanRepresentation: HumanRepresentationSchema,
|
|
257
|
+
agentActionDefinition: AgentActionDefinitionSchema,
|
|
258
|
+
agentConstraint: AgentConstraintSchema,
|
|
259
|
+
agentRelation: AgentRelationSchema,
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
revealcoin: {
|
|
263
|
+
primary: 'tokenConfig',
|
|
264
|
+
description: 'RevealCoin (RVC on chain, RVUI internal codename) token config schema lifted from the TS interface.',
|
|
265
|
+
schemas: {
|
|
266
|
+
tokenConfig: RvuiTokenConfigSchema,
|
|
267
|
+
},
|
|
268
|
+
},
|
|
269
|
+
secrets: {
|
|
270
|
+
primary: 'secretActor',
|
|
271
|
+
description: 'Revvault secret-management contracts — SecretPath, SecretActor, RotationEvent, SecretAuditEvent.',
|
|
272
|
+
schemas: {
|
|
273
|
+
secretActor: SecretActorSchema,
|
|
274
|
+
secretActorType: SecretActorTypeSchema,
|
|
275
|
+
secretPath: SecretPathSchema,
|
|
276
|
+
rotationEvent: RotationEventSchema,
|
|
277
|
+
rotationReason: RotationReasonSchema,
|
|
278
|
+
secretAuditEvent: SecretAuditEventSchema,
|
|
279
|
+
secretAuditEventType: SecretAuditEventTypeSchema,
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
security: {
|
|
283
|
+
primary: 'securityRule',
|
|
284
|
+
description: 'Security rule contracts — SecurityRule, SecurityFinding, severity/category enums, IssueLocation.',
|
|
285
|
+
schemas: {
|
|
286
|
+
securityRule: SecurityRuleSchema,
|
|
287
|
+
securityFinding: SecurityFindingSchema,
|
|
288
|
+
severity: SecuritySeveritySchema,
|
|
289
|
+
category: SecurityCategorySchema,
|
|
290
|
+
issueLocation: IssueLocationSchema,
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
stripe_webhook_events: {
|
|
294
|
+
primary: 'eventType',
|
|
295
|
+
description: 'Canonical Stripe webhook event types handled by RevealUI (subset of Stripe API events).',
|
|
296
|
+
schemas: {
|
|
297
|
+
eventType: StripeWebhookEventSchema,
|
|
298
|
+
},
|
|
299
|
+
},
|
|
300
|
+
};
|
|
301
|
+
const CATEGORIES = Object.keys(SCHEMA_REGISTRY);
|
|
302
|
+
// Constant exports for tests + runtime introspection.
|
|
303
|
+
// biome-ignore lint/suspicious/noExplicitAny: ZodTypeAny convenience for tests.
|
|
304
|
+
export const REGISTERED_CATEGORIES = CATEGORIES;
|
|
305
|
+
export const REVEALCOIN_TOKEN_DEFAULT = RVUI_TOKEN_CONFIG;
|
|
306
|
+
/**
|
|
307
|
+
* Build the contracts catalog: a snapshot of every registered category's
|
|
308
|
+
* JSON Schemas (computed via Zod v4's built-in `z.toJSONSchema()`), keyed
|
|
309
|
+
* first by category name, then by schema name within the category.
|
|
310
|
+
*
|
|
311
|
+
* Pure (no side effects, no external state). Safe to call multiple times;
|
|
312
|
+
* each call recomputes from `SCHEMA_REGISTRY`. Cheap enough that callers
|
|
313
|
+
* who want a long-lived snapshot (e.g. the MCP server's per-instance cache)
|
|
314
|
+
* can call once and memoize the result themselves.
|
|
315
|
+
*
|
|
316
|
+
* Some Zod constructs (e.g. discriminated unions with overlapping
|
|
317
|
+
* discriminators, recursive schemas without lazy guards, custom transforms)
|
|
318
|
+
* cannot be serialized to JSON Schema. For those entries, the catalog
|
|
319
|
+
* surfaces a placeholder `{ $comment: "JSON Schema serialization failed: ..." }`
|
|
320
|
+
* so the schema name still appears in the catalog; runtime validation
|
|
321
|
+
* (via `validatePayload`) is unaffected.
|
|
322
|
+
*/
|
|
323
|
+
export function getContractsCatalog() {
|
|
324
|
+
const out = {};
|
|
325
|
+
for (const cat of CATEGORIES) {
|
|
326
|
+
const entry = SCHEMA_REGISTRY[cat];
|
|
327
|
+
const schemaJson = {};
|
|
328
|
+
for (const [name, zodSchema] of Object.entries(entry.schemas)) {
|
|
329
|
+
try {
|
|
330
|
+
schemaJson[name] = z.toJSONSchema(zodSchema);
|
|
331
|
+
}
|
|
332
|
+
catch (err) {
|
|
333
|
+
schemaJson[name] = {
|
|
334
|
+
$comment: `JSON Schema serialization failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
out[cat] = {
|
|
339
|
+
schemas: schemaJson,
|
|
340
|
+
primary: entry.primary,
|
|
341
|
+
description: entry.description,
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
return out;
|
|
345
|
+
}
|
|
346
|
+
// ---------------------------------------------------------------------------
|
|
347
|
+
// Resource URI helpers
|
|
348
|
+
// ---------------------------------------------------------------------------
|
|
349
|
+
const RESOURCE_URI_PREFIX = 'revealui-contracts://';
|
|
350
|
+
const CATALOG_URI = `${RESOURCE_URI_PREFIX}catalog`;
|
|
351
|
+
function parseCategoryUri(uri) {
|
|
352
|
+
if (!uri.startsWith(RESOURCE_URI_PREFIX))
|
|
353
|
+
return null;
|
|
354
|
+
const rest = uri.slice(RESOURCE_URI_PREFIX.length);
|
|
355
|
+
if (!/^[a-z][a-z0-9_]*$/.test(rest))
|
|
356
|
+
return null;
|
|
357
|
+
if (!(rest in SCHEMA_REGISTRY))
|
|
358
|
+
return null;
|
|
359
|
+
return { category: rest };
|
|
360
|
+
}
|
|
361
|
+
export function validatePayload(category, schemaName, data) {
|
|
362
|
+
const entry = SCHEMA_REGISTRY[category];
|
|
363
|
+
// The `as const satisfies` literal makes `entry.schemas` a union of
|
|
364
|
+
// narrow per-category shapes. For runtime indexing by arbitrary string,
|
|
365
|
+
// widen to a record of ZodTypeAny — the unknown-key lookup is what we
|
|
366
|
+
// want here (caller supplied `schemaName`).
|
|
367
|
+
const schemasMap = entry.schemas;
|
|
368
|
+
const zodSchema = schemasMap[schemaName];
|
|
369
|
+
if (!zodSchema) {
|
|
370
|
+
return {
|
|
371
|
+
success: false,
|
|
372
|
+
category,
|
|
373
|
+
schema: schemaName,
|
|
374
|
+
issues: [
|
|
375
|
+
{
|
|
376
|
+
path: [],
|
|
377
|
+
message: `Unknown schema "${schemaName}" for category "${category}". Valid schemas: ${Object.keys(entry.schemas).join(', ')}.`,
|
|
378
|
+
code: 'unknown_schema',
|
|
379
|
+
},
|
|
380
|
+
],
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
const result = zodSchema.safeParse(data);
|
|
384
|
+
if (result.success) {
|
|
385
|
+
return { success: true, category, schema: schemaName, data: result.data };
|
|
386
|
+
}
|
|
387
|
+
return {
|
|
388
|
+
success: false,
|
|
389
|
+
category,
|
|
390
|
+
schema: schemaName,
|
|
391
|
+
issues: result.error.issues.map((i) => ({
|
|
392
|
+
path: i.path,
|
|
393
|
+
message: i.message,
|
|
394
|
+
code: i.code,
|
|
395
|
+
})),
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
// ---------------------------------------------------------------------------
|
|
399
|
+
// Tool catalog
|
|
400
|
+
// ---------------------------------------------------------------------------
|
|
401
|
+
const VALIDATE_TOOL_PREFIX = 'contracts_validate_';
|
|
402
|
+
function validateToolName(category) {
|
|
403
|
+
return `${VALIDATE_TOOL_PREFIX}${category}`;
|
|
404
|
+
}
|
|
405
|
+
function validateInputSchema(category) {
|
|
406
|
+
const entry = SCHEMA_REGISTRY[category];
|
|
407
|
+
const schemaNames = Object.keys(entry.schemas);
|
|
408
|
+
return {
|
|
409
|
+
type: 'object',
|
|
410
|
+
properties: {
|
|
411
|
+
schema: {
|
|
412
|
+
type: 'string',
|
|
413
|
+
enum: schemaNames,
|
|
414
|
+
description: `Optional schema name within "${category}". Defaults to "${entry.primary}". One of: ${schemaNames.join(', ')}.`,
|
|
415
|
+
},
|
|
416
|
+
data: {
|
|
417
|
+
description: 'JSON value to validate. Type depends on the chosen schema.',
|
|
418
|
+
},
|
|
419
|
+
},
|
|
420
|
+
required: ['data'],
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
function buildToolList() {
|
|
424
|
+
const tools = [];
|
|
425
|
+
// Discovery tools
|
|
426
|
+
tools.push({
|
|
427
|
+
name: 'contracts_list_categories',
|
|
428
|
+
description: 'List every contract category exposed by this server, with primary schema name and full schema-name list per category.',
|
|
429
|
+
inputSchema: { type: 'object', properties: {} },
|
|
430
|
+
});
|
|
431
|
+
tools.push({
|
|
432
|
+
name: 'contracts_get_schema',
|
|
433
|
+
description: 'Return the JSON Schema for a (category, schema) pair. Omit `schema` to get the category primary.',
|
|
434
|
+
inputSchema: {
|
|
435
|
+
type: 'object',
|
|
436
|
+
properties: {
|
|
437
|
+
category: {
|
|
438
|
+
type: 'string',
|
|
439
|
+
enum: CATEGORIES,
|
|
440
|
+
description: 'Contract category name.',
|
|
441
|
+
},
|
|
442
|
+
schema: {
|
|
443
|
+
type: 'string',
|
|
444
|
+
description: 'Optional schema name within the category. Defaults to the primary.',
|
|
445
|
+
},
|
|
446
|
+
},
|
|
447
|
+
required: ['category'],
|
|
448
|
+
},
|
|
449
|
+
});
|
|
450
|
+
// One validate tool per category
|
|
451
|
+
for (const cat of CATEGORIES) {
|
|
452
|
+
const entry = SCHEMA_REGISTRY[cat];
|
|
453
|
+
tools.push({
|
|
454
|
+
name: validateToolName(cat),
|
|
455
|
+
description: `Validate a JSON payload against a "${cat}" contract schema. ${entry.description}`,
|
|
456
|
+
inputSchema: validateInputSchema(cat),
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
return tools;
|
|
460
|
+
}
|
|
461
|
+
// ---------------------------------------------------------------------------
|
|
462
|
+
// Resource catalog
|
|
463
|
+
// ---------------------------------------------------------------------------
|
|
464
|
+
function buildResourceList() {
|
|
465
|
+
const resources = [
|
|
466
|
+
{
|
|
467
|
+
uri: CATALOG_URI,
|
|
468
|
+
name: 'catalog',
|
|
469
|
+
description: 'Complete contracts catalog: every category with its primary schema name, secondary schema names, and human description.',
|
|
470
|
+
mimeType: 'application/json',
|
|
471
|
+
},
|
|
472
|
+
];
|
|
473
|
+
for (const cat of CATEGORIES) {
|
|
474
|
+
const entry = SCHEMA_REGISTRY[cat];
|
|
475
|
+
resources.push({
|
|
476
|
+
uri: `${RESOURCE_URI_PREFIX}${cat}`,
|
|
477
|
+
name: cat,
|
|
478
|
+
description: entry.description,
|
|
479
|
+
mimeType: 'application/json',
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
return resources;
|
|
483
|
+
}
|
|
484
|
+
function buildCatalogPayload() {
|
|
485
|
+
const categories = CATEGORIES.map((cat) => {
|
|
486
|
+
const entry = SCHEMA_REGISTRY[cat];
|
|
487
|
+
return {
|
|
488
|
+
name: cat,
|
|
489
|
+
primary: entry.primary,
|
|
490
|
+
schemas: Object.keys(entry.schemas),
|
|
491
|
+
description: entry.description,
|
|
492
|
+
};
|
|
493
|
+
});
|
|
494
|
+
const totalSchemas = categories.reduce((acc, c) => acc + c.schemas.length, 0);
|
|
495
|
+
return { categories, totalCategories: categories.length, totalSchemas };
|
|
496
|
+
}
|
|
497
|
+
// ---------------------------------------------------------------------------
|
|
498
|
+
// Factory
|
|
499
|
+
// ---------------------------------------------------------------------------
|
|
500
|
+
/**
|
|
501
|
+
* Server name + version. Bump the version when the registry changes
|
|
502
|
+
* shape (adds/removes categories or top-level fields). The host
|
|
503
|
+
* `@revealui/mcp` package version stays separate.
|
|
504
|
+
*/
|
|
505
|
+
const SERVER_NAME = 'revealui-contracts';
|
|
506
|
+
const SERVER_VERSION = '0.1.0';
|
|
507
|
+
/**
|
|
508
|
+
* Create a fresh contracts MCP Server instance. Safe to call multiple
|
|
509
|
+
* times — each call returns an independent Server with its own request
|
|
510
|
+
* handlers and its own JSON Schema cache.
|
|
511
|
+
*/
|
|
512
|
+
export function createContractsServer(options) {
|
|
513
|
+
const server = new Server({ name: options?.serverName ?? SERVER_NAME, version: SERVER_VERSION }, { capabilities: { tools: {}, resources: {} } });
|
|
514
|
+
const jsonSchemaCache = getContractsCatalog();
|
|
515
|
+
const toolList = buildToolList();
|
|
516
|
+
const resourceList = buildResourceList();
|
|
517
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: toolList }));
|
|
518
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => ({ resources: resourceList }));
|
|
519
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
520
|
+
const uri = request.params.uri;
|
|
521
|
+
if (uri === CATALOG_URI) {
|
|
522
|
+
return {
|
|
523
|
+
contents: [
|
|
524
|
+
{
|
|
525
|
+
uri,
|
|
526
|
+
mimeType: 'application/json',
|
|
527
|
+
text: JSON.stringify(buildCatalogPayload(), null, 2),
|
|
528
|
+
},
|
|
529
|
+
],
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
const parsed = parseCategoryUri(uri);
|
|
533
|
+
if (!parsed) {
|
|
534
|
+
throw new Error(`Unknown resource URI (expected ${CATALOG_URI} or ${RESOURCE_URI_PREFIX}<category>): ${uri}`);
|
|
535
|
+
}
|
|
536
|
+
const cached = jsonSchemaCache[parsed.category];
|
|
537
|
+
return {
|
|
538
|
+
contents: [
|
|
539
|
+
{
|
|
540
|
+
uri,
|
|
541
|
+
mimeType: 'application/json',
|
|
542
|
+
text: JSON.stringify({
|
|
543
|
+
category: parsed.category,
|
|
544
|
+
primarySchema: cached.primary,
|
|
545
|
+
description: cached.description,
|
|
546
|
+
schemas: cached.schemas,
|
|
547
|
+
}, null, 2),
|
|
548
|
+
},
|
|
549
|
+
],
|
|
550
|
+
};
|
|
551
|
+
});
|
|
552
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
553
|
+
const toolName = request.params.name;
|
|
554
|
+
const args = (request.params.arguments ?? {});
|
|
555
|
+
try {
|
|
556
|
+
if (toolName === 'contracts_list_categories') {
|
|
557
|
+
return {
|
|
558
|
+
content: [{ type: 'text', text: JSON.stringify(buildCatalogPayload(), null, 2) }],
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
if (toolName === 'contracts_get_schema') {
|
|
562
|
+
const category = args.category;
|
|
563
|
+
const schemaName = args.schema;
|
|
564
|
+
if (typeof category !== 'string' || !(category in SCHEMA_REGISTRY)) {
|
|
565
|
+
return {
|
|
566
|
+
content: [
|
|
567
|
+
{
|
|
568
|
+
type: 'text',
|
|
569
|
+
text: `Error: Unknown category "${String(category)}". Valid: ${CATEGORIES.join(', ')}.`,
|
|
570
|
+
},
|
|
571
|
+
],
|
|
572
|
+
isError: true,
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
const cat = category;
|
|
576
|
+
const cached = jsonSchemaCache[cat];
|
|
577
|
+
const effectiveSchema = typeof schemaName === 'string' && schemaName.length > 0 ? schemaName : cached.primary;
|
|
578
|
+
const json = cached.schemas[effectiveSchema];
|
|
579
|
+
if (json === undefined) {
|
|
580
|
+
return {
|
|
581
|
+
content: [
|
|
582
|
+
{
|
|
583
|
+
type: 'text',
|
|
584
|
+
text: `Error: Unknown schema "${effectiveSchema}" for category "${cat}". Valid: ${Object.keys(cached.schemas).join(', ')}.`,
|
|
585
|
+
},
|
|
586
|
+
],
|
|
587
|
+
isError: true,
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
return {
|
|
591
|
+
content: [
|
|
592
|
+
{
|
|
593
|
+
type: 'text',
|
|
594
|
+
text: JSON.stringify({ category: cat, schema: effectiveSchema, jsonSchema: json }, null, 2),
|
|
595
|
+
},
|
|
596
|
+
],
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
if (toolName.startsWith(VALIDATE_TOOL_PREFIX)) {
|
|
600
|
+
const category = toolName.slice(VALIDATE_TOOL_PREFIX.length);
|
|
601
|
+
if (!(category in SCHEMA_REGISTRY)) {
|
|
602
|
+
return {
|
|
603
|
+
content: [
|
|
604
|
+
{
|
|
605
|
+
type: 'text',
|
|
606
|
+
text: `Error: Unknown category "${category}" derived from tool "${toolName}". Valid: ${CATEGORIES.join(', ')}.`,
|
|
607
|
+
},
|
|
608
|
+
],
|
|
609
|
+
isError: true,
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
const cat = category;
|
|
613
|
+
const entry = SCHEMA_REGISTRY[cat];
|
|
614
|
+
const schemaName = typeof args.schema === 'string' && args.schema.length > 0 ? args.schema : entry.primary;
|
|
615
|
+
if (!('data' in args)) {
|
|
616
|
+
return {
|
|
617
|
+
content: [{ type: 'text', text: `Error: "data" is required for ${toolName}.` }],
|
|
618
|
+
isError: true,
|
|
619
|
+
};
|
|
620
|
+
}
|
|
621
|
+
const result = validatePayload(cat, schemaName, args.data);
|
|
622
|
+
return {
|
|
623
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
624
|
+
isError: !result.success,
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
return {
|
|
628
|
+
content: [{ type: 'text', text: `Error: Unknown tool: ${toolName}` }],
|
|
629
|
+
isError: true,
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
catch (err) {
|
|
633
|
+
return {
|
|
634
|
+
content: [
|
|
635
|
+
{
|
|
636
|
+
type: 'text',
|
|
637
|
+
text: `Error: ${err instanceof Error ? err.message : String(err)}`,
|
|
638
|
+
},
|
|
639
|
+
],
|
|
640
|
+
isError: true,
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
});
|
|
644
|
+
return server;
|
|
645
|
+
}
|
|
646
|
+
//# sourceMappingURL=contracts.js.map
|