@exposify/nestjs 0.0.0-stage → 0.0.1

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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Exposify
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,40 @@
1
- # Temporary Holding Version
1
+ # @exposify/nestjs
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ NestJS integration for [Exposify](../../README.md): your controllers become MCP
4
+ tools that AI agents can call, with schemas and descriptions from
5
+ `@nestjs/swagger`.
6
+
7
+ ```ts
8
+ import { mountAiReady } from "@exposify/nestjs";
9
+
10
+ const app = await NestFactory.create(AppModule);
11
+ app.setGlobalPrefix("api");
12
+ mountAiReady(app); // MCP endpoint at /mcp
13
+ await app.listen(3000);
14
+ ```
15
+
16
+ ```ts
17
+ import { McpDescribe, McpExposed, McpHidden } from "@exposify/nestjs";
18
+
19
+ @Controller("orders")
20
+ export class OrdersController {
21
+ @Get() list() {} // reads are exposed by default
22
+
23
+ @Post() @McpDescribe({ name: "place_order", description: "Place an order; reserves stock." })
24
+ create(@Body() dto: CreateOrderDto) {} // writes need an opt-in
25
+
26
+ @Delete(":id") remove() {} // hidden (a write, no opt-in)
27
+
28
+ @Get("internal") @McpHidden() internal() {} // a read kept from agents
29
+ }
30
+ ```
31
+
32
+ - Tool calls go through Nest itself, so guards, pipes, interceptors and
33
+ filters apply exactly as for any HTTP client.
34
+ - Input schemas come from your DTOs' `@ApiProperty` metadata; descriptions
35
+ from `@ApiOperation({ summary })` unless `@McpDescribe` sets one.
36
+ - The decorators write an `x-exposify` extension into the Swagger document,
37
+ so they need `@nestjs/swagger` (a peer dependency). Without it, use
38
+ `@exposify/express`'s `aiReady({ expose: [...] })` directly.
39
+ - Express platform only (the Nest default); Fastify isn't supported yet.
40
+ - `npx exposify-express setup` / `inspect` / `describe` work on Nest projects.
package/dist/index.cjs ADDED
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ McpDescribe: () => McpDescribe,
24
+ McpExposed: () => McpExposed,
25
+ McpHidden: () => McpHidden,
26
+ aiReady: () => import_express2.aiReady,
27
+ mountAiReady: () => mountAiReady
28
+ });
29
+ module.exports = __toCommonJS(index_exports);
30
+ var import_swagger = require("@nestjs/swagger");
31
+ var import_core = require("@exposify/core");
32
+ var import_express = require("@exposify/express");
33
+ var import_express2 = require("@exposify/express");
34
+ var mark = (ext) => (0, import_swagger.ApiExtension)(import_core.EXPOSIFY_EXTENSION, ext);
35
+ function McpExposed() {
36
+ return mark({ expose: true });
37
+ }
38
+ function McpHidden() {
39
+ return mark({ hidden: true });
40
+ }
41
+ function McpDescribe(meta) {
42
+ return mark({ ...meta.name ? { name: meta.name } : {}, ...meta.description ? { description: meta.description } : {}, expose: true });
43
+ }
44
+ function mountAiReady(app, options = {}) {
45
+ const { swaggerConfig, openapi, ...rest } = options;
46
+ const document = openapi ?? import_swagger.SwaggerModule.createDocument(app, swaggerConfig ?? new import_swagger.DocumentBuilder().build());
47
+ app.use((0, import_express.aiReady)({ ...rest, openapi: document }));
48
+ }
49
+ // Annotate the CommonJS export names for ESM import in node:
50
+ 0 && (module.exports = {
51
+ McpDescribe,
52
+ McpExposed,
53
+ McpHidden,
54
+ aiReady,
55
+ mountAiReady
56
+ });
@@ -0,0 +1,26 @@
1
+ import { INestApplication } from '@nestjs/common';
2
+ import { OpenAPIObject } from '@nestjs/swagger';
3
+ import { ExpressAiReadyOptions } from '@exposify/express';
4
+ export { ExpressAiReadyOptions, aiReady } from '@exposify/express';
5
+
6
+ /** Let agents call this route (writes are hidden by default). */
7
+ declare function McpExposed(): MethodDecorator;
8
+ /** Keep this route away from agents (reads are exposed by default). */
9
+ declare function McpHidden(): MethodDecorator;
10
+ /** Expose this route with an explicit tool name and/or description. */
11
+ declare function McpDescribe(meta: {
12
+ name?: string;
13
+ description?: string;
14
+ }): MethodDecorator;
15
+ interface NestAiReadyOptions extends ExpressAiReadyOptions {
16
+ /** Base document for SwaggerModule.createDocument (title, version, ...). Default: an empty one. */
17
+ swaggerConfig?: Omit<OpenAPIObject, "paths">;
18
+ }
19
+ /**
20
+ * Builds the Swagger document for `app` (unless `openapi` is given) and mounts
21
+ * aiReady() with it. Call after NestFactory.create() and any setGlobalPrefix /
22
+ * enableVersioning, before app.listen().
23
+ */
24
+ declare function mountAiReady(app: INestApplication, options?: NestAiReadyOptions): void;
25
+
26
+ export { McpDescribe, McpExposed, McpHidden, type NestAiReadyOptions, mountAiReady };
@@ -0,0 +1,26 @@
1
+ import { INestApplication } from '@nestjs/common';
2
+ import { OpenAPIObject } from '@nestjs/swagger';
3
+ import { ExpressAiReadyOptions } from '@exposify/express';
4
+ export { ExpressAiReadyOptions, aiReady } from '@exposify/express';
5
+
6
+ /** Let agents call this route (writes are hidden by default). */
7
+ declare function McpExposed(): MethodDecorator;
8
+ /** Keep this route away from agents (reads are exposed by default). */
9
+ declare function McpHidden(): MethodDecorator;
10
+ /** Expose this route with an explicit tool name and/or description. */
11
+ declare function McpDescribe(meta: {
12
+ name?: string;
13
+ description?: string;
14
+ }): MethodDecorator;
15
+ interface NestAiReadyOptions extends ExpressAiReadyOptions {
16
+ /** Base document for SwaggerModule.createDocument (title, version, ...). Default: an empty one. */
17
+ swaggerConfig?: Omit<OpenAPIObject, "paths">;
18
+ }
19
+ /**
20
+ * Builds the Swagger document for `app` (unless `openapi` is given) and mounts
21
+ * aiReady() with it. Call after NestFactory.create() and any setGlobalPrefix /
22
+ * enableVersioning, before app.listen().
23
+ */
24
+ declare function mountAiReady(app: INestApplication, options?: NestAiReadyOptions): void;
25
+
26
+ export { McpDescribe, McpExposed, McpHidden, type NestAiReadyOptions, mountAiReady };
package/dist/index.js ADDED
@@ -0,0 +1,27 @@
1
+ // src/index.ts
2
+ import { ApiExtension, DocumentBuilder, SwaggerModule } from "@nestjs/swagger";
3
+ import { EXPOSIFY_EXTENSION } from "@exposify/core";
4
+ import { aiReady } from "@exposify/express";
5
+ import { aiReady as aiReady2 } from "@exposify/express";
6
+ var mark = (ext) => ApiExtension(EXPOSIFY_EXTENSION, ext);
7
+ function McpExposed() {
8
+ return mark({ expose: true });
9
+ }
10
+ function McpHidden() {
11
+ return mark({ hidden: true });
12
+ }
13
+ function McpDescribe(meta) {
14
+ return mark({ ...meta.name ? { name: meta.name } : {}, ...meta.description ? { description: meta.description } : {}, expose: true });
15
+ }
16
+ function mountAiReady(app, options = {}) {
17
+ const { swaggerConfig, openapi, ...rest } = options;
18
+ const document = openapi ?? SwaggerModule.createDocument(app, swaggerConfig ?? new DocumentBuilder().build());
19
+ app.use(aiReady({ ...rest, openapi: document }));
20
+ }
21
+ export {
22
+ McpDescribe,
23
+ McpExposed,
24
+ McpHidden,
25
+ aiReady2 as aiReady,
26
+ mountAiReady
27
+ };
package/package.json CHANGED
@@ -1,6 +1,53 @@
1
1
  {
2
2
  "name": "@exposify/nestjs",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.0.1",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsup src/index.ts --format esm,cjs --dts --clean",
21
+ "typecheck": "tsc --noEmit",
22
+ "prepack": "yarn build"
23
+ },
24
+ "dependencies": {
25
+ "@exposify/core": "0.3.13",
26
+ "@exposify/express": "0.3.9"
27
+ },
28
+ "peerDependencies": {
29
+ "@nestjs/common": "^11.0.0 || ^12.0.0",
30
+ "@nestjs/swagger": "^11.0.0 || ^12.0.0"
31
+ },
32
+ "devDependencies": {
33
+ "@nestjs/common": "^12.1.0",
34
+ "@nestjs/swagger": "^12.0.0",
35
+ "@types/node": "^22.0.0",
36
+ "reflect-metadata": "^0.2.2",
37
+ "rxjs": "^7.8.1",
38
+ "tsup": "^8.3.0",
39
+ "typescript": "^5.6.0"
40
+ },
41
+ "publishConfig": {
42
+ "access": "public"
43
+ },
44
+ "description": "NestJS integration for Exposify: @McpExposed/@McpHidden/@McpDescribe decorators and one-line mounting, with tool schemas and descriptions from @nestjs/swagger.",
45
+ "author": "Exposify",
46
+ "keywords": [
47
+ "mcp",
48
+ "model-context-protocol",
49
+ "nestjs",
50
+ "swagger",
51
+ "ai-agents"
52
+ ]
6
53
  }