@12-apps/mcp 3.3.0 → 3.4.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/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { J as JsonSchema, G as GeneratedTool, D as DispatchConfig, a as DispatchResult, b as ToolAnnotations, R as RequestAuth, T as ToolManifest } from './generate-Dx3cK8th.js';
2
2
  export { A as AuthResolver, c as GenerateOptions, O as OpenApiDocument, d as OpenApiOperation, e as OpenApiParameter, f as OpenApiRequestBody, g as OpenApiResponse, P as ParameterLocation, h as ToolParameter, i as generateTools } from './generate-Dx3cK8th.js';
3
3
  export { A as AI_CAPABILITIES, a as AI_PERMISSION_MODEL, b as AiCapability, c as AiConnectPromptSpec, d as AiHostBrand, e as AiHostConfigureStage, f as AiHostGuide, g as AiHostLink, h as AiProvider, i as aiConnectPrompt, j as aiHostGuides, p as providerForHostId } from './guide-DV5MQbCg.js';
4
+ import { z } from 'zod';
4
5
 
5
6
  /**
6
7
  * Raised when a JSON Schema cannot be turned into a flat, self-contained tool
@@ -23,6 +24,69 @@ declare class UnsupportedSchemaError extends Error {
23
24
  */
24
25
  declare function inlineSchemaRefs(schema: JsonSchema): JsonSchema;
25
26
 
27
+ /**
28
+ * How a route is DECLARED, one step before it becomes an OpenAPI operation and
29
+ * two before it becomes a tool.
30
+ *
31
+ * This package already owns everything downstream of an OpenAPI document —
32
+ * `generateTools` turns operations into tools, `dispatchTool` proxies a call,
33
+ * `redactResponseSchema`/`redactResponseBody` narrow both halves. What it did
34
+ * not own was the shape a consumer writes its routes down in, so every consumer
35
+ * declared its own. That is fine for one app and wrong for several: a monorepo
36
+ * where the shift routes, the lifecycle routes and the audit routes are each
37
+ * packaged separately needs those packages to produce endpoint lists the HOST
38
+ * can concatenate, which they can only do if they all mean the same thing by
39
+ * "an endpoint".
40
+ *
41
+ * Deliberately zod-shaped rather than JSON-Schema-shaped. A route validates its
42
+ * input with zod at runtime; describing it a second time in JSON Schema is a
43
+ * copy that drifts, and the drift is invisible — the manifest keeps advertising
44
+ * the shape the route stopped accepting. Converting zod → JSON Schema at
45
+ * generate time makes the validator the single source of truth.
46
+ *
47
+ * zod is a PEER dependency: it is referenced here as a type only, so this
48
+ * package pulls no copy of its own and cannot end up type-checking against a
49
+ * different one than the consumer declares its schemas with.
50
+ */
51
+ /** The methods an MCP-exposed route may use. */
52
+ type HttpMethod = "get" | "post" | "put" | "patch" | "delete";
53
+ interface McpEndpointBase {
54
+ /** Stable tool id — this becomes the MCP tool name, so renaming it is a
55
+ * breaking change for every agent that has learned the old one. */
56
+ operationId: string;
57
+ method: HttpMethod;
58
+ /** OpenAPI path template, e.g. `/api/products/{id}`. */
59
+ path: string;
60
+ /** What the tool is FOR, in the words an agent reads when choosing it. */
61
+ summary: string;
62
+ tags?: string[];
63
+ /** Object schema whose properties become query parameters. */
64
+ query?: z.ZodType;
65
+ /** Object schema whose properties become path parameters. */
66
+ params?: z.ZodType;
67
+ /** Request body schema (writes only). */
68
+ body?: z.ZodType;
69
+ }
70
+ /**
71
+ * A declared endpoint either answers 200 with a schema'd JSON body (the
72
+ * default) or 204 No Content (fire-and-forget writes).
73
+ *
74
+ * The union is what makes the two mutually exclusive: a 204 entry cannot carry
75
+ * a response schema, so a manifest can never advertise a body its route will
76
+ * not send — a mismatch an agent experiences as a tool that returns nothing
77
+ * where its own schema promised an object.
78
+ */
79
+ type McpEndpoint = McpEndpointBase & ({
80
+ /** Success status (defaults to 200 with a JSON body). */
81
+ status?: 200;
82
+ /** Success (200) response schema. */
83
+ response: z.ZodType;
84
+ } | {
85
+ /** 204 No Content — no response schema. */
86
+ status: 204;
87
+ response?: never;
88
+ });
89
+
26
90
  /** Raised when tool arguments cannot be routed onto the HTTP request. */
27
91
  declare class DispatchInputError extends Error {
28
92
  constructor(message: string);
@@ -404,4 +468,4 @@ interface AuthorizationServerMetadata {
404
468
  */
405
469
  declare function buildAuthorizationServerMetadata(input: AuthorizationServerMetadataInput): AuthorizationServerMetadata;
406
470
 
407
- export { type AuthorizationServerMetadata, type AuthorizationServerMetadataInput, type AuthorizationServerPaths, type BuildManifestOptions, DispatchConfig, DispatchInputError, DispatchResult, GeneratedTool, HTTP_STATUS_META_KEY, type JsonRpcRequest, type JsonRpcResponse, JsonSchema, MCP_PROTOCOL_VERSION, type McpJsonRpcOptions, type McpServerInfo, type McpToolDescriptor, type McpToolResult, PROTECTED_RESOURCE_METADATA_PATH, type ProtectedResourceMetadata, type ProtectedResourceMetadataInput, type RegistryOptions, RequestAuth, type SurfaceLock, type SurfaceLockCheck, ToolAnnotations, ToolManifest, type ToolRegistry, UNAUTHORIZED_CODE, UnsupportedSchemaError, bearerChallenge, buildAuthorizationServerMetadata, buildManifest, buildProtectedResourceMetadata, createToolRegistry, dispatchTool, handleMcpJsonRpc, inlineSchemaRefs, redactResponseBody, redactResponseSchema, serializeManifest, serializeSurfaceLock, surfaceDigest, surfaceLockProblem };
471
+ export { type AuthorizationServerMetadata, type AuthorizationServerMetadataInput, type AuthorizationServerPaths, type BuildManifestOptions, DispatchConfig, DispatchInputError, DispatchResult, GeneratedTool, HTTP_STATUS_META_KEY, type HttpMethod, type JsonRpcRequest, type JsonRpcResponse, JsonSchema, MCP_PROTOCOL_VERSION, type McpEndpoint, type McpJsonRpcOptions, type McpServerInfo, type McpToolDescriptor, type McpToolResult, PROTECTED_RESOURCE_METADATA_PATH, type ProtectedResourceMetadata, type ProtectedResourceMetadataInput, type RegistryOptions, RequestAuth, type SurfaceLock, type SurfaceLockCheck, ToolAnnotations, ToolManifest, type ToolRegistry, UNAUTHORIZED_CODE, UnsupportedSchemaError, bearerChallenge, buildAuthorizationServerMetadata, buildManifest, buildProtectedResourceMetadata, createToolRegistry, dispatchTool, handleMcpJsonRpc, inlineSchemaRefs, redactResponseBody, redactResponseSchema, serializeManifest, serializeSurfaceLock, surfaceDigest, surfaceLockProblem };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@12-apps/mcp",
3
- "version": "3.3.0",
3
+ "version": "3.4.0",
4
4
  "type": "module",
5
5
  "description": "App-agnostic MCP server core: generate one MCP tool per OpenAPI operation and proxy each call carrying the caller's bearer token (permission passthrough). Also ships the OAuth 2.1 authorization server (./oauth, ./hono: register/authorize/token, JWKS and both .well-known documents), the package-owned Prisma partial + migration for its three tables, the mcp:generate/mcp:check (./generate) and mcp:coverage (./coverage) gates, and the reusable AI-connect onboarding UI (./react).",
6
6
  "exports": {
@@ -51,7 +51,8 @@
51
51
  },
52
52
  "peerDependencies": {
53
53
  "react": ">=19.0.0",
54
- "hono": ">=4.0.0"
54
+ "hono": ">=4.0.0",
55
+ "zod": ">=4.0.0"
55
56
  },
56
57
  "devDependencies": {
57
58
  "@12-apps/eslint-config": "^1.20.0",
@@ -67,7 +68,8 @@
67
68
  "react-dom": "^19.2.0",
68
69
  "tsup": "^8.0.0",
69
70
  "typescript": "^5.8.2",
70
- "vitest": "^3.2.4"
71
+ "vitest": "^3.2.4",
72
+ "zod": "^4.3.5"
71
73
  },
72
74
  "engines": {
73
75
  "node": ">=22.0.0"
@@ -103,6 +105,9 @@
103
105
  "peerDependenciesMeta": {
104
106
  "hono": {
105
107
  "optional": true
108
+ },
109
+ "zod": {
110
+ "optional": true
106
111
  }
107
112
  }
108
113
  }
package/src/index.ts CHANGED
@@ -28,6 +28,11 @@ export {
28
28
  } from "./guide";
29
29
  export { generateTools } from "./openapi/generate";
30
30
  export { inlineSchemaRefs, UnsupportedSchemaError } from "./openapi/refs";
31
+ // The shape a route is DECLARED in, upstream of the OpenAPI document. It lives
32
+ // here so that packages which own a domain can ship that domain's endpoints and
33
+ // a host can concatenate them — which requires all of them to mean the same
34
+ // thing by "an endpoint". See `openapi/endpoint.ts`.
35
+ export type { McpEndpoint, HttpMethod } from "./openapi/endpoint";
31
36
  export type {
32
37
  OpenApiDocument,
33
38
  OpenApiOperation,
@@ -0,0 +1,71 @@
1
+ import type { z } from "zod";
2
+
3
+ /**
4
+ * How a route is DECLARED, one step before it becomes an OpenAPI operation and
5
+ * two before it becomes a tool.
6
+ *
7
+ * This package already owns everything downstream of an OpenAPI document —
8
+ * `generateTools` turns operations into tools, `dispatchTool` proxies a call,
9
+ * `redactResponseSchema`/`redactResponseBody` narrow both halves. What it did
10
+ * not own was the shape a consumer writes its routes down in, so every consumer
11
+ * declared its own. That is fine for one app and wrong for several: a monorepo
12
+ * where the shift routes, the lifecycle routes and the audit routes are each
13
+ * packaged separately needs those packages to produce endpoint lists the HOST
14
+ * can concatenate, which they can only do if they all mean the same thing by
15
+ * "an endpoint".
16
+ *
17
+ * Deliberately zod-shaped rather than JSON-Schema-shaped. A route validates its
18
+ * input with zod at runtime; describing it a second time in JSON Schema is a
19
+ * copy that drifts, and the drift is invisible — the manifest keeps advertising
20
+ * the shape the route stopped accepting. Converting zod → JSON Schema at
21
+ * generate time makes the validator the single source of truth.
22
+ *
23
+ * zod is a PEER dependency: it is referenced here as a type only, so this
24
+ * package pulls no copy of its own and cannot end up type-checking against a
25
+ * different one than the consumer declares its schemas with.
26
+ */
27
+
28
+ /** The methods an MCP-exposed route may use. */
29
+ export type HttpMethod = "get" | "post" | "put" | "patch" | "delete";
30
+
31
+ interface McpEndpointBase {
32
+ /** Stable tool id — this becomes the MCP tool name, so renaming it is a
33
+ * breaking change for every agent that has learned the old one. */
34
+ operationId: string;
35
+ method: HttpMethod;
36
+ /** OpenAPI path template, e.g. `/api/products/{id}`. */
37
+ path: string;
38
+ /** What the tool is FOR, in the words an agent reads when choosing it. */
39
+ summary: string;
40
+ tags?: string[];
41
+ /** Object schema whose properties become query parameters. */
42
+ query?: z.ZodType;
43
+ /** Object schema whose properties become path parameters. */
44
+ params?: z.ZodType;
45
+ /** Request body schema (writes only). */
46
+ body?: z.ZodType;
47
+ }
48
+
49
+ /**
50
+ * A declared endpoint either answers 200 with a schema'd JSON body (the
51
+ * default) or 204 No Content (fire-and-forget writes).
52
+ *
53
+ * The union is what makes the two mutually exclusive: a 204 entry cannot carry
54
+ * a response schema, so a manifest can never advertise a body its route will
55
+ * not send — a mismatch an agent experiences as a tool that returns nothing
56
+ * where its own schema promised an object.
57
+ */
58
+ export type McpEndpoint = McpEndpointBase &
59
+ (
60
+ | {
61
+ /** Success status (defaults to 200 with a JSON body). */
62
+ status?: 200;
63
+ /** Success (200) response schema. */
64
+ response: z.ZodType;
65
+ }
66
+ | {
67
+ /** 204 No Content — no response schema. */
68
+ status: 204;
69
+ response?: never;
70
+ }
71
+ );