@exposify/express 0.3.1 → 0.3.3
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 +94 -0
- package/package.json +8 -4
package/README.md
CHANGED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# @exposify/express — setup guide
|
|
2
|
+
|
|
3
|
+
Turn an existing Express app into an MCP server in one line: an
|
|
4
|
+
auto-generated **MCP endpoint** at `/mcp` lets AI agents (Claude, Cursor,
|
|
5
|
+
ChatGPT, or anything else speaking MCP) call your routes as tools, and an
|
|
6
|
+
embedded **knowledge base** built from your README/docs lets them understand
|
|
7
|
+
your product. No external services, no build step.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { aiReady } from "@exposify/express";
|
|
11
|
+
|
|
12
|
+
app.use(aiReady()); // MCP endpoint live at /mcp
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Auth is **passthrough**: every tool call carries exactly the caller's own
|
|
16
|
+
credentials (`Authorization`/`Cookie`), forwarded to your routes unchanged.
|
|
17
|
+
There is no separate authorization layer to configure or get wrong — an
|
|
18
|
+
agent can do exactly what the person it's acting for could already do.
|
|
19
|
+
|
|
20
|
+
## Exposure policy
|
|
21
|
+
|
|
22
|
+
- **Reads (GET/HEAD) are exposed automatically.** Writes are hidden by
|
|
23
|
+
default — opt them in explicitly, right where the route is defined:
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { aiReady, exposed, describe } from "@exposify/express";
|
|
27
|
+
import { z } from "zod";
|
|
28
|
+
|
|
29
|
+
app.post("/orders", exposed(createOrder));
|
|
30
|
+
|
|
31
|
+
// Or opt in while also enriching the tool's name/description/input schema:
|
|
32
|
+
app.post("/orders/:id/refund", describe(refundOrder, {
|
|
33
|
+
name: "refund_order",
|
|
34
|
+
description: "Refund an order. Reversible within 30 days.",
|
|
35
|
+
input: { id: z.string(), body: z.object({ reason: z.string() }) },
|
|
36
|
+
}));
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
- **`describe()`'s `input` envelope contract:** `input` is a flat Zod shape.
|
|
40
|
+
At call time, each top-level key is routed by name — a key matching one of
|
|
41
|
+
the route's `:param` segments becomes a path substitution, `query`
|
|
42
|
+
(expected to be an object) becomes the query string, `body` becomes the
|
|
43
|
+
JSON request body. Any other top-level key is silently dropped and never
|
|
44
|
+
reaches the route (a one-time warning is logged per tool at registration
|
|
45
|
+
if this happens) — nest fields under `body` or `query` instead of putting
|
|
46
|
+
them at the top level.
|
|
47
|
+
|
|
48
|
+
## Mounted routers
|
|
49
|
+
|
|
50
|
+
Routers mounted with `app.use(path, router)` **after** `aiReady()` (the
|
|
51
|
+
standard layout above) are discovered automatically on both Express 4 and 5.
|
|
52
|
+
Anything mounted *before* `aiReady()`, or a sub-app (Express can't
|
|
53
|
+
distinguish a sub-app from arbitrary middleware), needs an explicit entry:
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
app.use(aiReady({ mounts: { "/legacy": legacyRouter } }));
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Options
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
aiReady({
|
|
63
|
+
auth?: "passthrough" | "none", // default "passthrough"
|
|
64
|
+
docs?: string[], // default ["README.md", "docs/**/*.md"]
|
|
65
|
+
expose?: string[] | "*", // e.g. ["GET /trends"]; default unset
|
|
66
|
+
exclude?: string[], // picomatch globs against the route path
|
|
67
|
+
docsAuth?: "public" | "required", // default "public"
|
|
68
|
+
embedder?: (texts: string[]) => Promise<number[][]>,
|
|
69
|
+
telemetry?: { enabled: boolean; sink?(event): void; capturePayloads?: boolean },
|
|
70
|
+
cwd?: string, // default process.cwd()
|
|
71
|
+
mounts?: Record<string, unknown>, // explicit router/sub-app overrides
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Exposure precedence: an `exposed()`/`hidden()`/`describe()` marker on a
|
|
76
|
+
route always wins, then `exclude`, then `expose`, then the read/write
|
|
77
|
+
default above.
|
|
78
|
+
|
|
79
|
+
## Known limitations
|
|
80
|
+
|
|
81
|
+
- **Sub-apps** (`app.use(path, subApp)`) are never auto-detected on any
|
|
82
|
+
Express version — always list them in `mounts` explicitly.
|
|
83
|
+
- **Express 5** can't reflect a mounted router's own path, so auto-discovery
|
|
84
|
+
only works when `aiReady()` is registered *before* the mount. A router
|
|
85
|
+
mounted both before and after `aiReady()` ("straddle" mount) resolves
|
|
86
|
+
correctly on Express 4 but silently drops the earlier prefix on Express 5.
|
|
87
|
+
- In-process dispatch uses `light-my-request`, which splices Express's
|
|
88
|
+
process-wide request/response prototypes for the duration of each
|
|
89
|
+
dispatch — a narrow concurrency window under real concurrent traffic, a
|
|
90
|
+
known tradeoff tracked in `packages/express/src/surface.ts`.
|
|
91
|
+
|
|
92
|
+
See the [repo README](https://github.com/ayadagain/agentready#readme) for
|
|
93
|
+
the full picture across all `@exposify/*` packages, including
|
|
94
|
+
`@exposify/supabase`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exposify/express",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"prepack": "yarn build"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@exposify/core": "0.
|
|
26
|
+
"@exposify/core": "1.0.0",
|
|
27
27
|
"light-my-request": "^6.0.0"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
@@ -52,9 +52,13 @@
|
|
|
52
52
|
"bugs": {
|
|
53
53
|
"url": "https://github.com/ayadagain/agentready/issues"
|
|
54
54
|
},
|
|
55
|
-
"description": "
|
|
55
|
+
"description": "Turn an Express app into an MCP server in one line: routes become AI agent tools automatically, writes are opt-in, and the caller's own credentials pass straight through.",
|
|
56
56
|
"author": "Exposify",
|
|
57
57
|
"keywords": [
|
|
58
|
-
"
|
|
58
|
+
"mcp",
|
|
59
|
+
"model-context-protocol",
|
|
60
|
+
"express",
|
|
61
|
+
"ai-agents",
|
|
62
|
+
"llm-tools"
|
|
59
63
|
]
|
|
60
64
|
}
|