@exposify/express 0.3.13 → 0.3.14
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/README.md +12 -11
- package/dist/index.cjs +8 -8
- package/dist/index.js +8 -8
- package/dist/scan-preload.cjs +2 -2
- package/dist/scan-preload.js +2 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -35,10 +35,10 @@ and exception filters apply exactly as for any HTTP client, so a guarded
|
|
|
35
35
|
route refuses an agent without credentials and a `ValidationPipe` error
|
|
36
36
|
reaches the agent as an actionable 400. `npx @exposify/express setup` and
|
|
37
37
|
`inspect` find `src/main.ts` from `nest-cli.json` and load it with your
|
|
38
|
-
`ts-node`/`swc-node`. The Fastify platform isn't supported yet. See
|
|
39
|
-
`examples/nest-demo
|
|
38
|
+
`ts-node`/`swc-node`. The Fastify platform isn't supported yet. See the
|
|
39
|
+
[`nest-demo` example](https://github.com/ayadagain/agentready/tree/main/examples/nest-demo).
|
|
40
40
|
|
|
41
|
-
With `@nestjs/swagger`, [`@exposify/nestjs`](
|
|
41
|
+
With `@nestjs/swagger`, [`@exposify/nestjs`](https://github.com/ayadagain/agentready/tree/main/packages/nestjs) does this in one line
|
|
42
42
|
(`mountAiReady(app)`) and adds `@McpExposed()` / `@McpHidden()` /
|
|
43
43
|
`@McpDescribe()` decorators. Or pass the document yourself, and tools get its
|
|
44
44
|
DTO schemas and `@ApiOperation` summaries:
|
|
@@ -188,7 +188,7 @@ same way. `loginVerify: { path, fields, body? }` names the second step;
|
|
|
188
188
|
**No login found, and no sign-in method in the dashboard?** Then agents use
|
|
189
189
|
your app signed out: `/mcp` doesn't ask them to sign in, and your own checks
|
|
190
190
|
decide what they can do. The startup log says which it is
|
|
191
|
-
(`[
|
|
191
|
+
(`[exposify] How agents sign in: ...`), and so does the dashboard's "How
|
|
192
192
|
agents sign in" page. Adding a sign-in method there takes effect within a
|
|
193
193
|
minute.
|
|
194
194
|
|
|
@@ -273,17 +273,17 @@ On boot (`npm run dev`, or in production), right after your routes
|
|
|
273
273
|
register, `aiReady()` prints one line saying whether MCP is up:
|
|
274
274
|
|
|
275
275
|
```
|
|
276
|
-
[
|
|
276
|
+
[exposify] MCP ready at /mcp: 6 tools (4 read, 1 write, search_docs), 1 write route hidden (opt in with exposed()), 2 docs indexed, auth: passthrough
|
|
277
277
|
```
|
|
278
278
|
|
|
279
279
|
When something's wrong, the line names the problem and a fix instead:
|
|
280
280
|
|
|
281
281
|
```
|
|
282
|
-
[
|
|
282
|
+
[exposify] MCP failed to start: <reason>
|
|
283
283
|
fix: <what to do>
|
|
284
|
-
[
|
|
284
|
+
[exposify] warning: MCP is up at /mcp but exposes no route tools
|
|
285
285
|
fix: register app.use(aiReady()) before your routers, ...
|
|
286
|
-
[
|
|
286
|
+
[exposify] warning: can't verify access tokens from oauth.issuer https://...: <reason>
|
|
287
287
|
fix: make oauth.issuer match the tokens' `iss` exactly ...
|
|
288
288
|
```
|
|
289
289
|
|
|
@@ -385,6 +385,7 @@ default above.
|
|
|
385
385
|
`req.ip`, `req.hostname`, `req.protocol` and `trust proxy` see the agent
|
|
386
386
|
exactly as they would for a direct request, never as localhost.
|
|
387
387
|
|
|
388
|
-
See the
|
|
389
|
-
|
|
390
|
-
`@exposify
|
|
388
|
+
See the
|
|
389
|
+
[repo README](https://github.com/ayadagain/agentready#readme) for the full
|
|
390
|
+
picture across all `@exposify/*` packages, including
|
|
391
|
+
[`@exposify/supabase`](https://github.com/ayadagain/agentready/tree/main/packages/supabase).
|
package/dist/index.cjs
CHANGED
|
@@ -184,7 +184,7 @@ function warnMountSkipped() {
|
|
|
184
184
|
warnedAboutSkippedMount = true;
|
|
185
185
|
try {
|
|
186
186
|
console.warn(
|
|
187
|
-
`[
|
|
187
|
+
`[exposify] skipped one or more mounted routers: their mount path could not be determined automatically, so routes under them will not be exposed as tools. If aiReady() is registered before they're mounted, this is usually automatic (Express 5's mount recorder); otherwise pass them explicitly via aiReady({ mounts: { "/path": router } }).`
|
|
188
188
|
);
|
|
189
189
|
} catch {
|
|
190
190
|
}
|
|
@@ -341,7 +341,7 @@ async function loadOpenApi(cwd, option, warn) {
|
|
|
341
341
|
|
|
342
342
|
// src/surface.ts
|
|
343
343
|
var import_core4 = require("@exposify/core");
|
|
344
|
-
var warnOnce = (m) => console.warn(`[
|
|
344
|
+
var warnOnce = (m) => console.warn(`[exposify] warning: ${m}`);
|
|
345
345
|
var NULL_BODY_STATUSES = /* @__PURE__ */ new Set([101, 103, 204, 205, 304]);
|
|
346
346
|
var IDENTITY_HEADERS = ["host", "forwarded", "x-forwarded-for", "x-forwarded-proto", "x-forwarded-host", "x-forwarded-port"];
|
|
347
347
|
var DISPATCH_HEADER = "x-exposify-dispatch";
|
|
@@ -553,7 +553,7 @@ var import_core7 = require("@exposify/core");
|
|
|
553
553
|
var AIREADY_OPTIONS_TAG = /* @__PURE__ */ Symbol.for("exposify.express.aiReadyOptions");
|
|
554
554
|
var MCP_PATH = "/mcp";
|
|
555
555
|
var PRM_ROOT = "/.well-known/oauth-protected-resource";
|
|
556
|
-
var LOG_PREFIX = "[
|
|
556
|
+
var LOG_PREFIX = "[exposify]";
|
|
557
557
|
function toolsSummary(routes, docs, cfg) {
|
|
558
558
|
const counts = (0, import_core6.countTools)(routes, cfg);
|
|
559
559
|
const details = counts.hiddenWrites > 0 ? [`${counts.hiddenWrites} write route${counts.hiddenWrites === 1 ? "" : "s"} hidden (opt in with exposed())`] : [];
|
|
@@ -681,7 +681,7 @@ function aiReady(options = {}) {
|
|
|
681
681
|
const login = loginOf(req.app);
|
|
682
682
|
if (!login) return next();
|
|
683
683
|
void serveLoginPage(req, res, login).catch((err) => {
|
|
684
|
-
console.warn("[
|
|
684
|
+
console.warn("[exposify] sign-in form failed:", err);
|
|
685
685
|
if (!res.headersSent) res.writeHead(503).end("sign-in is unavailable");
|
|
686
686
|
});
|
|
687
687
|
return;
|
|
@@ -699,7 +699,7 @@ function aiReady(options = {}) {
|
|
|
699
699
|
}
|
|
700
700
|
if (path !== MCP_PATH && !path.startsWith(`${MCP_PATH}/`)) return next();
|
|
701
701
|
if (disabled) {
|
|
702
|
-
res.writeHead(503).end("
|
|
702
|
+
res.writeHead(503).end("exposify is disabled due to an internal error");
|
|
703
703
|
return;
|
|
704
704
|
}
|
|
705
705
|
const authorized = gate ? gate.check(headersOf(req)).then(async (result) => {
|
|
@@ -707,7 +707,7 @@ function aiReady(options = {}) {
|
|
|
707
707
|
await sendWebResponse(res, result.response);
|
|
708
708
|
return null;
|
|
709
709
|
}, (err) => {
|
|
710
|
-
console.warn("[
|
|
710
|
+
console.warn("[exposify] oauth gate failed:", err);
|
|
711
711
|
if (!res.headersSent) res.writeHead(503).end("authorization check failed");
|
|
712
712
|
return null;
|
|
713
713
|
}) : brokerGate ? report(req, resourceOf(req, path, MCP_PATH)).then(async (verdict) => {
|
|
@@ -717,7 +717,7 @@ function aiReady(options = {}) {
|
|
|
717
717
|
await sendWebResponse(res, result.response);
|
|
718
718
|
return null;
|
|
719
719
|
}).catch((err) => {
|
|
720
|
-
console.warn("[
|
|
720
|
+
console.warn("[exposify] broker check failed:", err);
|
|
721
721
|
if (!res.headersSent) res.writeHead(503).end("authorization check failed");
|
|
722
722
|
return null;
|
|
723
723
|
}) : Promise.resolve({});
|
|
@@ -752,7 +752,7 @@ function aiReady(options = {}) {
|
|
|
752
752
|
err
|
|
753
753
|
);
|
|
754
754
|
}
|
|
755
|
-
if (!res.headersSent) res.writeHead(503).end("
|
|
755
|
+
if (!res.headersSent) res.writeHead(503).end("exposify failed to initialize");
|
|
756
756
|
});
|
|
757
757
|
};
|
|
758
758
|
async function serveLoginPage(req, res, login) {
|
package/dist/index.js
CHANGED
|
@@ -185,7 +185,7 @@ function warnMountSkipped() {
|
|
|
185
185
|
warnedAboutSkippedMount = true;
|
|
186
186
|
try {
|
|
187
187
|
console.warn(
|
|
188
|
-
`[
|
|
188
|
+
`[exposify] skipped one or more mounted routers: their mount path could not be determined automatically, so routes under them will not be exposed as tools. If aiReady() is registered before they're mounted, this is usually automatic (Express 5's mount recorder); otherwise pass them explicitly via aiReady({ mounts: { "/path": router } }).`
|
|
189
189
|
);
|
|
190
190
|
} catch {
|
|
191
191
|
}
|
|
@@ -342,7 +342,7 @@ async function loadOpenApi(cwd, option, warn) {
|
|
|
342
342
|
|
|
343
343
|
// src/surface.ts
|
|
344
344
|
import { applyOpenApi } from "@exposify/core";
|
|
345
|
-
var warnOnce = (m) => console.warn(`[
|
|
345
|
+
var warnOnce = (m) => console.warn(`[exposify] warning: ${m}`);
|
|
346
346
|
var NULL_BODY_STATUSES = /* @__PURE__ */ new Set([101, 103, 204, 205, 304]);
|
|
347
347
|
var IDENTITY_HEADERS = ["host", "forwarded", "x-forwarded-for", "x-forwarded-proto", "x-forwarded-host", "x-forwarded-port"];
|
|
348
348
|
var DISPATCH_HEADER = "x-exposify-dispatch";
|
|
@@ -561,7 +561,7 @@ import {
|
|
|
561
561
|
var AIREADY_OPTIONS_TAG = /* @__PURE__ */ Symbol.for("exposify.express.aiReadyOptions");
|
|
562
562
|
var MCP_PATH = "/mcp";
|
|
563
563
|
var PRM_ROOT = "/.well-known/oauth-protected-resource";
|
|
564
|
-
var LOG_PREFIX = "[
|
|
564
|
+
var LOG_PREFIX = "[exposify]";
|
|
565
565
|
function toolsSummary(routes, docs, cfg) {
|
|
566
566
|
const counts = countTools(routes, cfg);
|
|
567
567
|
const details = counts.hiddenWrites > 0 ? [`${counts.hiddenWrites} write route${counts.hiddenWrites === 1 ? "" : "s"} hidden (opt in with exposed())`] : [];
|
|
@@ -689,7 +689,7 @@ function aiReady(options = {}) {
|
|
|
689
689
|
const login = loginOf(req.app);
|
|
690
690
|
if (!login) return next();
|
|
691
691
|
void serveLoginPage(req, res, login).catch((err) => {
|
|
692
|
-
console.warn("[
|
|
692
|
+
console.warn("[exposify] sign-in form failed:", err);
|
|
693
693
|
if (!res.headersSent) res.writeHead(503).end("sign-in is unavailable");
|
|
694
694
|
});
|
|
695
695
|
return;
|
|
@@ -707,7 +707,7 @@ function aiReady(options = {}) {
|
|
|
707
707
|
}
|
|
708
708
|
if (path !== MCP_PATH && !path.startsWith(`${MCP_PATH}/`)) return next();
|
|
709
709
|
if (disabled) {
|
|
710
|
-
res.writeHead(503).end("
|
|
710
|
+
res.writeHead(503).end("exposify is disabled due to an internal error");
|
|
711
711
|
return;
|
|
712
712
|
}
|
|
713
713
|
const authorized = gate ? gate.check(headersOf(req)).then(async (result) => {
|
|
@@ -715,7 +715,7 @@ function aiReady(options = {}) {
|
|
|
715
715
|
await sendWebResponse(res, result.response);
|
|
716
716
|
return null;
|
|
717
717
|
}, (err) => {
|
|
718
|
-
console.warn("[
|
|
718
|
+
console.warn("[exposify] oauth gate failed:", err);
|
|
719
719
|
if (!res.headersSent) res.writeHead(503).end("authorization check failed");
|
|
720
720
|
return null;
|
|
721
721
|
}) : brokerGate ? report(req, resourceOf(req, path, MCP_PATH)).then(async (verdict) => {
|
|
@@ -725,7 +725,7 @@ function aiReady(options = {}) {
|
|
|
725
725
|
await sendWebResponse(res, result.response);
|
|
726
726
|
return null;
|
|
727
727
|
}).catch((err) => {
|
|
728
|
-
console.warn("[
|
|
728
|
+
console.warn("[exposify] broker check failed:", err);
|
|
729
729
|
if (!res.headersSent) res.writeHead(503).end("authorization check failed");
|
|
730
730
|
return null;
|
|
731
731
|
}) : Promise.resolve({});
|
|
@@ -760,7 +760,7 @@ function aiReady(options = {}) {
|
|
|
760
760
|
err
|
|
761
761
|
);
|
|
762
762
|
}
|
|
763
|
-
if (!res.headersSent) res.writeHead(503).end("
|
|
763
|
+
if (!res.headersSent) res.writeHead(503).end("exposify failed to initialize");
|
|
764
764
|
});
|
|
765
765
|
};
|
|
766
766
|
async function serveLoginPage(req, res, login) {
|
package/dist/scan-preload.cjs
CHANGED
|
@@ -2363,7 +2363,7 @@ function hostedResolverFromEnv() {
|
|
|
2363
2363
|
if (!key) return void 0;
|
|
2364
2364
|
if (!parseExposifyKey(key)) {
|
|
2365
2365
|
try {
|
|
2366
|
-
console.warn(`[
|
|
2366
|
+
console.warn(`[exposify] warning: ${EXPOSIFY_KEY_ENV} isn't a secret key from the Exposify dashboard (exk_...); ignoring it`);
|
|
2367
2367
|
} catch {
|
|
2368
2368
|
}
|
|
2369
2369
|
return void 0;
|
|
@@ -6782,7 +6782,7 @@ function warnMountSkipped() {
|
|
|
6782
6782
|
warnedAboutSkippedMount = true;
|
|
6783
6783
|
try {
|
|
6784
6784
|
console.warn(
|
|
6785
|
-
`[
|
|
6785
|
+
`[exposify] skipped one or more mounted routers: their mount path could not be determined automatically, so routes under them will not be exposed as tools. If aiReady() is registered before they're mounted, this is usually automatic (Express 5's mount recorder); otherwise pass them explicitly via aiReady({ mounts: { "/path": router } }).`
|
|
6786
6786
|
);
|
|
6787
6787
|
} catch {
|
|
6788
6788
|
}
|
package/dist/scan-preload.js
CHANGED
|
@@ -2367,7 +2367,7 @@ function hostedResolverFromEnv() {
|
|
|
2367
2367
|
if (!key) return void 0;
|
|
2368
2368
|
if (!parseExposifyKey(key)) {
|
|
2369
2369
|
try {
|
|
2370
|
-
console.warn(`[
|
|
2370
|
+
console.warn(`[exposify] warning: ${EXPOSIFY_KEY_ENV} isn't a secret key from the Exposify dashboard (exk_...); ignoring it`);
|
|
2371
2371
|
} catch {
|
|
2372
2372
|
}
|
|
2373
2373
|
return void 0;
|
|
@@ -6786,7 +6786,7 @@ function warnMountSkipped() {
|
|
|
6786
6786
|
warnedAboutSkippedMount = true;
|
|
6787
6787
|
try {
|
|
6788
6788
|
console.warn(
|
|
6789
|
-
`[
|
|
6789
|
+
`[exposify] skipped one or more mounted routers: their mount path could not be determined automatically, so routes under them will not be exposed as tools. If aiReady() is registered before they're mounted, this is usually automatic (Express 5's mount recorder); otherwise pass them explicitly via aiReady({ mounts: { "/path": router } }).`
|
|
6790
6790
|
);
|
|
6791
6791
|
} catch {
|
|
6792
6792
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exposify/express",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.14",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
"prepack": "yarn build"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@exposify/cli": "0.0.
|
|
30
|
-
"@exposify/core": "0.3.
|
|
29
|
+
"@exposify/cli": "0.0.9",
|
|
30
|
+
"@exposify/core": "0.3.19"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"express": ">=4 <6"
|