@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 +21 -0
- package/README.md +39 -2
- package/dist/index.cjs +56 -0
- package/dist/index.d.cts +26 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +27 -0
- package/package.json +50 -3
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
|
-
#
|
|
1
|
+
# @exposify/nestjs
|
|
2
2
|
|
|
3
|
-
|
|
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
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -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.d.ts
ADDED
|
@@ -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.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
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
|
}
|