apcore-mcp 0.6.0 → 0.7.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/README.md +181 -13
- package/dist/auth/index.d.ts +8 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +6 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/jwt.d.ts +59 -0
- package/dist/auth/jwt.d.ts.map +1 -0
- package/dist/auth/jwt.js +95 -0
- package/dist/auth/jwt.js.map +1 -0
- package/dist/auth/storage.d.ts +18 -0
- package/dist/auth/storage.d.ts.map +1 -0
- package/dist/auth/storage.js +19 -0
- package/dist/auth/storage.js.map +1 -0
- package/dist/auth/types.d.ts +21 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +8 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +37 -2
- package/dist/cli.js.map +1 -1
- package/dist/explorer/handler.d.ts +10 -1
- package/dist/explorer/handler.d.ts.map +1 -1
- package/dist/explorer/handler.js +47 -21
- package/dist/explorer/handler.js.map +1 -1
- package/dist/explorer/html.d.ts +2 -2
- package/dist/explorer/html.d.ts.map +1 -1
- package/dist/explorer/html.js +126 -47
- package/dist/explorer/html.js.map +1 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -5
- package/dist/index.js.map +1 -1
- package/dist/server/context.d.ts +5 -2
- package/dist/server/context.d.ts.map +1 -1
- package/dist/server/context.js +7 -5
- package/dist/server/context.js.map +1 -1
- package/dist/server/router.d.ts.map +1 -1
- package/dist/server/router.js +4 -2
- package/dist/server/router.js.map +1 -1
- package/dist/server/transport.d.ts +34 -1
- package/dist/server/transport.d.ts.map +1 -1
- package/dist/server/transport.js +149 -60
- package/dist/server/transport.js.map +1 -1
- package/package.json +6 -11
package/README.md
CHANGED
|
@@ -16,12 +16,12 @@ Converts apcore module registries into [Model Context Protocol (MCP)](https://mo
|
|
|
16
16
|
- **Annotation Mapping** — Map module annotations to MCP hints and OpenAI description suffixes
|
|
17
17
|
- **Error Mapping** — Sanitize internal errors for safe client-facing responses
|
|
18
18
|
- **Dynamic Registration** — Listen for registry changes and update tools at runtime
|
|
19
|
+
- **Tool Explorer** — Browser-based UI for browsing schemas and testing tools interactively
|
|
19
20
|
- **CLI** — Launch an MCP server from the command line
|
|
20
21
|
|
|
21
22
|
## Requirements
|
|
22
23
|
|
|
23
24
|
- Node.js >= 18.0.0
|
|
24
|
-
- apcore (peer dependency)
|
|
25
25
|
|
|
26
26
|
## Installation
|
|
27
27
|
|
|
@@ -29,6 +29,8 @@ Converts apcore module registries into [Model Context Protocol (MCP)](https://mo
|
|
|
29
29
|
npm install apcore-mcp
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
+
`apcore-js` is included as a direct dependency — no separate install needed.
|
|
33
|
+
|
|
32
34
|
## Quick Start
|
|
33
35
|
|
|
34
36
|
### Programmatic API
|
|
@@ -77,6 +79,73 @@ npx apcore-mcp --extensions-dir ./extensions --transport sse --port 8000
|
|
|
77
79
|
| `--name` | `apcore-mcp` | MCP server name |
|
|
78
80
|
| `--version` | package version | MCP server version |
|
|
79
81
|
| `--log-level` | `INFO` | `DEBUG`, `INFO`, `WARNING`, `ERROR` |
|
|
82
|
+
| `--explorer` | off | Enable the browser-based Tool Explorer UI (HTTP only) |
|
|
83
|
+
| `--explorer-prefix` | `/explorer` | URL prefix for the explorer UI |
|
|
84
|
+
| `--allow-execute` | off | Allow tool execution from the explorer UI |
|
|
85
|
+
| `--jwt-secret` | — | JWT secret key for Bearer token authentication |
|
|
86
|
+
| `--jwt-algorithm` | `HS256` | JWT algorithm |
|
|
87
|
+
| `--jwt-audience` | — | Expected JWT audience claim |
|
|
88
|
+
| `--jwt-issuer` | — | Expected JWT issuer claim |
|
|
89
|
+
| `--jwt-require-auth` | `true` | Require auth (use `--no-jwt-require-auth` for permissive mode) |
|
|
90
|
+
| `--exempt-paths` | `/health,/metrics` | Comma-separated paths exempt from auth |
|
|
91
|
+
|
|
92
|
+
## MCP Client Configuration
|
|
93
|
+
|
|
94
|
+
### Claude Desktop
|
|
95
|
+
|
|
96
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
|
97
|
+
|
|
98
|
+
```json
|
|
99
|
+
{
|
|
100
|
+
"mcpServers": {
|
|
101
|
+
"apcore": {
|
|
102
|
+
"command": "npx",
|
|
103
|
+
"args": ["apcore-mcp", "--extensions-dir", "/path/to/your/extensions"]
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Claude Code
|
|
110
|
+
|
|
111
|
+
Add to `.mcp.json` in your project root:
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"mcpServers": {
|
|
116
|
+
"apcore": {
|
|
117
|
+
"command": "npx",
|
|
118
|
+
"args": ["apcore-mcp", "--extensions-dir", "./extensions"]
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Cursor
|
|
125
|
+
|
|
126
|
+
Add to `.cursor/mcp.json` in your project root:
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"mcpServers": {
|
|
131
|
+
"apcore": {
|
|
132
|
+
"command": "npx",
|
|
133
|
+
"args": ["apcore-mcp", "--extensions-dir", "./extensions"]
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Remote HTTP access
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
npx apcore-mcp --extensions-dir ./extensions \
|
|
143
|
+
--transport streamable-http \
|
|
144
|
+
--host 0.0.0.0 \
|
|
145
|
+
--port 9000
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Connect any MCP client to `http://your-host:9000/mcp`.
|
|
80
149
|
|
|
81
150
|
## API Reference
|
|
82
151
|
|
|
@@ -93,10 +162,101 @@ function serve(
|
|
|
93
162
|
port?: number;
|
|
94
163
|
name?: string;
|
|
95
164
|
version?: string;
|
|
165
|
+
explorer?: boolean;
|
|
166
|
+
explorerPrefix?: string;
|
|
167
|
+
allowExecute?: boolean;
|
|
168
|
+
authenticator?: Authenticator;
|
|
169
|
+
exemptPaths?: string[];
|
|
96
170
|
}
|
|
97
171
|
): Promise<void>;
|
|
98
172
|
```
|
|
99
173
|
|
|
174
|
+
### Tool Explorer
|
|
175
|
+
|
|
176
|
+
When `explorer: true` is passed to `serve()`, a browser-based Tool Explorer UI is mounted on HTTP transports. It provides an interactive page for browsing tool schemas and testing tool execution.
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
await serve(registry, {
|
|
180
|
+
transport: "streamable-http",
|
|
181
|
+
explorer: true,
|
|
182
|
+
allowExecute: true,
|
|
183
|
+
});
|
|
184
|
+
// Open http://127.0.0.1:8000/explorer/ in a browser
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
**Endpoints:**
|
|
188
|
+
|
|
189
|
+
| Endpoint | Description |
|
|
190
|
+
|----------|-------------|
|
|
191
|
+
| `GET /explorer/` | Interactive HTML page (self-contained, no external dependencies) |
|
|
192
|
+
| `GET /explorer/tools` | JSON array of all tools with name, description, annotations |
|
|
193
|
+
| `GET /explorer/tools/<name>` | Full tool detail with inputSchema |
|
|
194
|
+
| `POST /explorer/tools/<name>/call` | Execute a tool (requires `allowExecute: true`) |
|
|
195
|
+
|
|
196
|
+
- **HTTP transports only** (`streamable-http`, `sse`). Silently ignored for `stdio`.
|
|
197
|
+
- **Execution disabled by default** — set `allowExecute: true` to enable Try-it.
|
|
198
|
+
- **Custom prefix** — use `explorerPrefix: "/browse"` to mount at a different path.
|
|
199
|
+
- **Authorization UI** — Swagger-UI-style Authorization input field. Paste a Bearer token to authenticate tool execution requests. Generated cURL commands automatically include the Authorization header.
|
|
200
|
+
|
|
201
|
+
### JWT Authentication
|
|
202
|
+
|
|
203
|
+
apcore-mcp supports JWT Bearer token authentication for HTTP-based transports.
|
|
204
|
+
|
|
205
|
+
#### Programmatic Usage
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
import { serve, JWTAuthenticator } from "apcore-mcp";
|
|
209
|
+
|
|
210
|
+
const authenticator = new JWTAuthenticator({
|
|
211
|
+
secret: "your-secret-key",
|
|
212
|
+
algorithms: ["HS256"],
|
|
213
|
+
audience: "my-app",
|
|
214
|
+
issuer: "auth-service",
|
|
215
|
+
// Map custom claims to Identity fields
|
|
216
|
+
claimMapping: {
|
|
217
|
+
id: "sub",
|
|
218
|
+
type: "type",
|
|
219
|
+
roles: "roles",
|
|
220
|
+
attrs: ["email", "org"], // Extra claims → Identity.attrs
|
|
221
|
+
},
|
|
222
|
+
// Claims that must be present in the token (default: ["sub"])
|
|
223
|
+
requireClaims: ["sub", "email"],
|
|
224
|
+
// Set to false for permissive mode (allow unauthenticated requests)
|
|
225
|
+
requireAuth: true,
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
await serve(executor, {
|
|
229
|
+
transport: "streamable-http",
|
|
230
|
+
authenticator,
|
|
231
|
+
// Custom exempt paths (default: ["/health", "/metrics"])
|
|
232
|
+
exemptPaths: ["/health", "/metrics", "/status"],
|
|
233
|
+
});
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
#### CLI Flags
|
|
237
|
+
|
|
238
|
+
| Flag | Default | Description |
|
|
239
|
+
|------|---------|-------------|
|
|
240
|
+
| `--jwt-secret` | — | JWT secret key for Bearer token authentication |
|
|
241
|
+
| `--jwt-algorithm` | `HS256` | JWT algorithm |
|
|
242
|
+
| `--jwt-audience` | — | Expected audience claim |
|
|
243
|
+
| `--jwt-issuer` | — | Expected issuer claim |
|
|
244
|
+
| `--jwt-require-auth` | `true` | Require auth. Use `--no-jwt-require-auth` for permissive mode |
|
|
245
|
+
| `--exempt-paths` | `/health,/metrics` | Comma-separated paths exempt from auth |
|
|
246
|
+
|
|
247
|
+
#### curl Examples
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
# Authenticated request
|
|
251
|
+
curl -X POST http://localhost:8000/mcp \
|
|
252
|
+
-H "Content-Type: application/json" \
|
|
253
|
+
-H "Authorization: Bearer <your-jwt-token>" \
|
|
254
|
+
-d '{"jsonrpc":"2.0","method":"tools/list","id":1}'
|
|
255
|
+
|
|
256
|
+
# Health check (always exempt)
|
|
257
|
+
curl http://localhost:8000/health
|
|
258
|
+
```
|
|
259
|
+
|
|
100
260
|
### `toOpenaiTools(registryOrExecutor, options?)`
|
|
101
261
|
|
|
102
262
|
Export apcore modules as OpenAI-compatible tool definitions.
|
|
@@ -127,20 +287,39 @@ src/
|
|
|
127
287
|
├── index.ts # Public API: serve(), toOpenaiTools()
|
|
128
288
|
├── cli.ts # CLI entry point
|
|
129
289
|
├── types.ts # TypeScript interfaces
|
|
290
|
+
├── helpers.ts # reportProgress() / elicit() helpers
|
|
130
291
|
├── adapters/
|
|
131
292
|
│ ├── schema.ts # JSON Schema $ref inlining
|
|
132
293
|
│ ├── annotations.ts # Module annotations -> MCP hints
|
|
133
294
|
│ ├── errors.ts # Error sanitization
|
|
134
295
|
│ └── idNormalizer.ts # Dot-notation <-> dash-notation
|
|
296
|
+
├── auth/
|
|
297
|
+
│ ├── jwt.ts # JWT Bearer token authenticator
|
|
298
|
+
│ ├── storage.ts # AsyncLocalStorage identity propagation
|
|
299
|
+
│ └── types.ts # Authenticator / Identity interfaces
|
|
135
300
|
├── converters/
|
|
136
301
|
│ └── openai.ts # OpenAI tool definition converter
|
|
302
|
+
├── explorer/
|
|
303
|
+
│ ├── handler.ts # Explorer HTTP route handler
|
|
304
|
+
│ └── html.ts # Self-contained HTML/CSS/JS page
|
|
137
305
|
└── server/
|
|
138
306
|
├── factory.ts # MCP Server creation & handler registration
|
|
139
307
|
├── router.ts # Tool call execution routing
|
|
308
|
+
├── context.ts # BridgeContext for executor call chains
|
|
140
309
|
├── transport.ts # Transport lifecycle (stdio/HTTP/SSE)
|
|
141
310
|
└── listener.ts # Dynamic registry event listener
|
|
142
311
|
```
|
|
143
312
|
|
|
313
|
+
## Examples
|
|
314
|
+
|
|
315
|
+
See [examples/README.md](examples/README.md) for runnable demos covering both class-based modules and zero-code-intrusion wrapping via the `module()` factory.
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
# Launch all 5 example modules with the Tool Explorer UI
|
|
319
|
+
npx tsx examples/run.ts
|
|
320
|
+
# Open http://127.0.0.1:8000/explorer/
|
|
321
|
+
```
|
|
322
|
+
|
|
144
323
|
## Development
|
|
145
324
|
|
|
146
325
|
```bash
|
|
@@ -165,18 +344,7 @@ npm run dev
|
|
|
165
344
|
|
|
166
345
|
## Testing
|
|
167
346
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
| Module | Coverage |
|
|
171
|
-
|---|---|
|
|
172
|
-
| annotations.ts | 100% |
|
|
173
|
-
| idNormalizer.ts | 100% |
|
|
174
|
-
| factory.ts | 100% |
|
|
175
|
-
| router.ts | 100% |
|
|
176
|
-
| errors.ts | 98.8% |
|
|
177
|
-
| schema.ts | 97.0% |
|
|
178
|
-
| openai.ts | 91.7% |
|
|
179
|
-
| listener.ts | 89.7% |
|
|
347
|
+
284 tests across 22 test suites.
|
|
180
348
|
|
|
181
349
|
## License
|
|
182
350
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth module barrel exports.
|
|
3
|
+
*/
|
|
4
|
+
export type { Authenticator, Identity } from "./types.js";
|
|
5
|
+
export { JWTAuthenticator } from "./jwt.js";
|
|
6
|
+
export type { ClaimMapping, JWTAuthenticatorOptions } from "./jwt.js";
|
|
7
|
+
export { identityStorage, getCurrentIdentity } from "./storage.js";
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,YAAY,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JWT Authenticator — verifies Bearer tokens and maps claims to Identity.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the Python `JWTAuthenticator` from apcore-mcp-python.
|
|
5
|
+
*/
|
|
6
|
+
import type { IncomingMessage } from "node:http";
|
|
7
|
+
import jwt from "jsonwebtoken";
|
|
8
|
+
import { type Identity } from "apcore-js";
|
|
9
|
+
import type { Authenticator } from "./types.js";
|
|
10
|
+
/** Mapping from JWT claims to Identity fields. */
|
|
11
|
+
export interface ClaimMapping {
|
|
12
|
+
/** JWT claim for Identity.id. Default: "sub" */
|
|
13
|
+
id?: string;
|
|
14
|
+
/** JWT claim for Identity.type. Default: "type" */
|
|
15
|
+
type?: string;
|
|
16
|
+
/** JWT claim for Identity.roles. Default: "roles" */
|
|
17
|
+
roles?: string;
|
|
18
|
+
/** Extra claims to copy into Identity.attrs. */
|
|
19
|
+
attrs?: string[];
|
|
20
|
+
}
|
|
21
|
+
/** Options for constructing a JWTAuthenticator. */
|
|
22
|
+
export interface JWTAuthenticatorOptions {
|
|
23
|
+
/** Secret key (symmetric) or public key (asymmetric) for token verification. */
|
|
24
|
+
secret: string;
|
|
25
|
+
/** Allowed algorithms. Default: ["HS256"] */
|
|
26
|
+
algorithms?: jwt.Algorithm[];
|
|
27
|
+
/** Expected audience claim. */
|
|
28
|
+
audience?: string;
|
|
29
|
+
/** Expected issuer claim. */
|
|
30
|
+
issuer?: string;
|
|
31
|
+
/** Custom claim-to-Identity field mapping. */
|
|
32
|
+
claimMapping?: ClaimMapping;
|
|
33
|
+
/** Claims that must be present in the token. Default: ["sub"] */
|
|
34
|
+
requireClaims?: string[];
|
|
35
|
+
/** If true (default), unauthenticated requests are rejected. If false, they proceed without identity. */
|
|
36
|
+
requireAuth?: boolean;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Authenticator that verifies JWT Bearer tokens from the Authorization header.
|
|
40
|
+
*
|
|
41
|
+
* Returns an Identity on success, or `null` if:
|
|
42
|
+
* - No Authorization header is present
|
|
43
|
+
* - The header is not a valid "Bearer <token>" format
|
|
44
|
+
* - The token fails verification (expired, wrong signature, etc.)
|
|
45
|
+
*/
|
|
46
|
+
export declare class JWTAuthenticator implements Authenticator {
|
|
47
|
+
private readonly _secret;
|
|
48
|
+
private readonly _algorithms;
|
|
49
|
+
private readonly _audience?;
|
|
50
|
+
private readonly _issuer?;
|
|
51
|
+
private readonly _claimMapping;
|
|
52
|
+
private readonly _requireClaims;
|
|
53
|
+
private readonly _requireAuth;
|
|
54
|
+
constructor(options: JWTAuthenticatorOptions);
|
|
55
|
+
/** Whether unauthenticated requests should be rejected. */
|
|
56
|
+
get requireAuth(): boolean;
|
|
57
|
+
authenticate(req: IncomingMessage): Promise<Identity | null>;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=jwt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../src/auth/jwt.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,GAAG,MAAM,cAAc,CAAC;AAC/B,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,kDAAkD;AAClD,MAAM,WAAW,YAAY;IAC3B,gDAAgD;IAChD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,mDAAmD;IACnD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,mDAAmD;AACnD,MAAM,WAAW,uBAAuB;IACtC,gFAAgF;IAChF,MAAM,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,UAAU,CAAC,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC;IAC7B,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6BAA6B;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,iEAAiE;IACjE,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,yGAAyG;IACzG,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,qBAAa,gBAAiB,YAAW,aAAa;IACpD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAkB;IAC9C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA+D;IAC7F,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAW;IAC1C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAU;gBAE3B,OAAO,EAAE,uBAAuB;IAe5C,2DAA2D;IAC3D,IAAI,WAAW,IAAI,OAAO,CAEzB;IAEK,YAAY,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;CAsDnE"}
|
package/dist/auth/jwt.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JWT Authenticator — verifies Bearer tokens and maps claims to Identity.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the Python `JWTAuthenticator` from apcore-mcp-python.
|
|
5
|
+
*/
|
|
6
|
+
import jwt from "jsonwebtoken";
|
|
7
|
+
import { createIdentity } from "apcore-js";
|
|
8
|
+
/**
|
|
9
|
+
* Authenticator that verifies JWT Bearer tokens from the Authorization header.
|
|
10
|
+
*
|
|
11
|
+
* Returns an Identity on success, or `null` if:
|
|
12
|
+
* - No Authorization header is present
|
|
13
|
+
* - The header is not a valid "Bearer <token>" format
|
|
14
|
+
* - The token fails verification (expired, wrong signature, etc.)
|
|
15
|
+
*/
|
|
16
|
+
export class JWTAuthenticator {
|
|
17
|
+
_secret;
|
|
18
|
+
_algorithms;
|
|
19
|
+
_audience;
|
|
20
|
+
_issuer;
|
|
21
|
+
_claimMapping;
|
|
22
|
+
_requireClaims;
|
|
23
|
+
_requireAuth;
|
|
24
|
+
constructor(options) {
|
|
25
|
+
this._secret = options.secret;
|
|
26
|
+
this._algorithms = options.algorithms ?? ["HS256"];
|
|
27
|
+
this._audience = options.audience;
|
|
28
|
+
this._issuer = options.issuer;
|
|
29
|
+
this._claimMapping = {
|
|
30
|
+
id: options.claimMapping?.id ?? "sub",
|
|
31
|
+
type: options.claimMapping?.type ?? "type",
|
|
32
|
+
roles: options.claimMapping?.roles ?? "roles",
|
|
33
|
+
attrs: options.claimMapping?.attrs,
|
|
34
|
+
};
|
|
35
|
+
this._requireClaims = options.requireClaims ?? ["sub"];
|
|
36
|
+
this._requireAuth = options.requireAuth ?? true;
|
|
37
|
+
}
|
|
38
|
+
/** Whether unauthenticated requests should be rejected. */
|
|
39
|
+
get requireAuth() {
|
|
40
|
+
return this._requireAuth;
|
|
41
|
+
}
|
|
42
|
+
async authenticate(req) {
|
|
43
|
+
const authHeader = req.headers.authorization;
|
|
44
|
+
if (!authHeader)
|
|
45
|
+
return null;
|
|
46
|
+
// Must be "Bearer <token>"
|
|
47
|
+
const parts = authHeader.split(" ");
|
|
48
|
+
if (parts.length !== 2 || parts[0].toLowerCase() !== "bearer")
|
|
49
|
+
return null;
|
|
50
|
+
const token = parts[1];
|
|
51
|
+
if (!token)
|
|
52
|
+
return null;
|
|
53
|
+
try {
|
|
54
|
+
const verifyOptions = {
|
|
55
|
+
algorithms: this._algorithms,
|
|
56
|
+
};
|
|
57
|
+
if (this._audience)
|
|
58
|
+
verifyOptions.audience = this._audience;
|
|
59
|
+
if (this._issuer)
|
|
60
|
+
verifyOptions.issuer = this._issuer;
|
|
61
|
+
const payload = jwt.verify(token, this._secret, verifyOptions);
|
|
62
|
+
// payload can be string (rare) or JwtPayload object
|
|
63
|
+
if (typeof payload === "string")
|
|
64
|
+
return null;
|
|
65
|
+
const claims = payload;
|
|
66
|
+
// Check required claims are present
|
|
67
|
+
for (const claim of this._requireClaims) {
|
|
68
|
+
if (!(claim in claims))
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
const rawId = claims[this._claimMapping.id];
|
|
72
|
+
if (rawId === undefined || rawId === null)
|
|
73
|
+
return null;
|
|
74
|
+
const id = String(rawId);
|
|
75
|
+
const type = String(claims[this._claimMapping.type] ?? "user");
|
|
76
|
+
const rawRoles = claims[this._claimMapping.roles];
|
|
77
|
+
const roles = Array.isArray(rawRoles) ? rawRoles.map(String) : [];
|
|
78
|
+
// Extract attrs from payload
|
|
79
|
+
const attrs = {};
|
|
80
|
+
if (this._claimMapping.attrs) {
|
|
81
|
+
for (const key of this._claimMapping.attrs) {
|
|
82
|
+
if (key in claims) {
|
|
83
|
+
attrs[key] = claims[key];
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return createIdentity(id, type, roles, attrs);
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
// Verification failed (expired, invalid signature, etc.)
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=jwt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../src/auth/jwt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Identity propagation via AsyncLocalStorage.
|
|
3
|
+
*
|
|
4
|
+
* Replaces Python's ContextVar pattern for propagating the authenticated
|
|
5
|
+
* identity through the async call chain without explicit parameter passing.
|
|
6
|
+
*/
|
|
7
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
8
|
+
import type { Identity } from "apcore-js";
|
|
9
|
+
/** AsyncLocalStorage instance that carries the current Identity through async scopes. */
|
|
10
|
+
export declare const identityStorage: AsyncLocalStorage<Identity | null>;
|
|
11
|
+
/**
|
|
12
|
+
* Get the current Identity from the async context.
|
|
13
|
+
*
|
|
14
|
+
* Returns `null` if called outside an `identityStorage.run()` scope
|
|
15
|
+
* or if the scope was entered with a `null` identity.
|
|
16
|
+
*/
|
|
17
|
+
export declare function getCurrentIdentity(): Identity | null;
|
|
18
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/auth/storage.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C,yFAAyF;AACzF,eAAO,MAAM,eAAe,oCAA2C,CAAC;AAExE;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,QAAQ,GAAG,IAAI,CAEpD"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Identity propagation via AsyncLocalStorage.
|
|
3
|
+
*
|
|
4
|
+
* Replaces Python's ContextVar pattern for propagating the authenticated
|
|
5
|
+
* identity through the async call chain without explicit parameter passing.
|
|
6
|
+
*/
|
|
7
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
8
|
+
/** AsyncLocalStorage instance that carries the current Identity through async scopes. */
|
|
9
|
+
export const identityStorage = new AsyncLocalStorage();
|
|
10
|
+
/**
|
|
11
|
+
* Get the current Identity from the async context.
|
|
12
|
+
*
|
|
13
|
+
* Returns `null` if called outside an `identityStorage.run()` scope
|
|
14
|
+
* or if the scope was entered with a `null` identity.
|
|
15
|
+
*/
|
|
16
|
+
export function getCurrentIdentity() {
|
|
17
|
+
return identityStorage.getStore() ?? null;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/auth/storage.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGrD,yFAAyF;AACzF,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,iBAAiB,EAAmB,CAAC;AAExE;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO,eAAe,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication interfaces for apcore-mcp.
|
|
3
|
+
*
|
|
4
|
+
* Re-exports the Identity type from apcore-js and defines the
|
|
5
|
+
* Authenticator interface that transport-level auth implementations must satisfy.
|
|
6
|
+
*/
|
|
7
|
+
import type { IncomingMessage } from "node:http";
|
|
8
|
+
import type { Identity } from "apcore-js";
|
|
9
|
+
export type { Identity };
|
|
10
|
+
/**
|
|
11
|
+
* Authenticator interface — implemented by auth strategies (e.g. JWT).
|
|
12
|
+
*
|
|
13
|
+
* `authenticate()` inspects incoming HTTP headers and returns an Identity
|
|
14
|
+
* for authenticated requests, or `null` for unauthenticated/invalid requests.
|
|
15
|
+
*/
|
|
16
|
+
export interface Authenticator {
|
|
17
|
+
authenticate(req: IncomingMessage): Promise<Identity | null>;
|
|
18
|
+
/** Whether unauthenticated requests should be rejected. Default true. */
|
|
19
|
+
readonly requireAuth?: boolean;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAG1C,YAAY,EAAE,QAAQ,EAAE,CAAC;AAEzB;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,YAAY,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;IAC7D,yEAAyE;IACzE,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;CAChC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;;;;GAOG;AA4CH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAgJ1C"}
|
package/dist/cli.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import { existsSync, statSync } from "node:fs";
|
|
11
11
|
import { resolve } from "node:path";
|
|
12
12
|
import { parseArgs } from "node:util";
|
|
13
|
-
import { serve, VERSION } from "./index.js";
|
|
13
|
+
import { serve, VERSION, JWTAuthenticator } from "./index.js";
|
|
14
14
|
function printUsage() {
|
|
15
15
|
console.log(`
|
|
16
16
|
apcore-mcp v${VERSION} - Automatic MCP Server for apcore modules
|
|
@@ -31,6 +31,13 @@ Options:
|
|
|
31
31
|
--explorer Enable the browser-based Tool Explorer UI (HTTP only)
|
|
32
32
|
--explorer-prefix <path> URL prefix for the explorer UI (default: /explorer)
|
|
33
33
|
--allow-execute Allow tool execution from the explorer UI
|
|
34
|
+
--jwt-secret <string> JWT secret key for Bearer token authentication
|
|
35
|
+
--jwt-algorithm <alg> JWT algorithm (default: HS256)
|
|
36
|
+
--jwt-audience <string> Expected JWT audience claim
|
|
37
|
+
--jwt-issuer <string> Expected JWT issuer claim
|
|
38
|
+
--jwt-require-auth Require auth (default: true)
|
|
39
|
+
--jwt-permissive Permissive mode: allow unauthenticated requests (overrides --jwt-require-auth)
|
|
40
|
+
--exempt-paths <paths> Comma-separated paths exempt from auth (default: /health,/metrics)
|
|
34
41
|
--help Show this help message
|
|
35
42
|
`);
|
|
36
43
|
}
|
|
@@ -53,6 +60,13 @@ export async function main() {
|
|
|
53
60
|
explorer: { type: "boolean", default: false },
|
|
54
61
|
"explorer-prefix": { type: "string", default: "/explorer" },
|
|
55
62
|
"allow-execute": { type: "boolean", default: false },
|
|
63
|
+
"jwt-secret": { type: "string" },
|
|
64
|
+
"jwt-algorithm": { type: "string" },
|
|
65
|
+
"jwt-audience": { type: "string" },
|
|
66
|
+
"jwt-issuer": { type: "string" },
|
|
67
|
+
"jwt-require-auth": { type: "boolean", default: true },
|
|
68
|
+
"jwt-permissive": { type: "boolean", default: false },
|
|
69
|
+
"exempt-paths": { type: "string" },
|
|
56
70
|
help: { type: "boolean", default: false },
|
|
57
71
|
},
|
|
58
72
|
strict: true,
|
|
@@ -116,10 +130,29 @@ export async function main() {
|
|
|
116
130
|
}
|
|
117
131
|
// Validate log-level
|
|
118
132
|
const logLevel = values["log-level"];
|
|
119
|
-
const validLogLevels = ["DEBUG", "INFO", "WARNING", "ERROR"];
|
|
133
|
+
const validLogLevels = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"];
|
|
120
134
|
if (logLevel && !validLogLevels.includes(logLevel)) {
|
|
121
135
|
fail(`--log-level must be one of: ${validLogLevels.join(", ")}. Got '${logLevel}'.`);
|
|
122
136
|
}
|
|
137
|
+
// Build JWT authenticator if --jwt-secret is provided
|
|
138
|
+
const jwtSecret = values["jwt-secret"];
|
|
139
|
+
const jwtRequireAuth = values["jwt-permissive"] ? false : values["jwt-require-auth"];
|
|
140
|
+
const authenticator = jwtSecret
|
|
141
|
+
? new JWTAuthenticator({
|
|
142
|
+
secret: jwtSecret,
|
|
143
|
+
algorithms: values["jwt-algorithm"]
|
|
144
|
+
? [values["jwt-algorithm"]]
|
|
145
|
+
: undefined,
|
|
146
|
+
audience: values["jwt-audience"],
|
|
147
|
+
issuer: values["jwt-issuer"],
|
|
148
|
+
requireAuth: jwtRequireAuth,
|
|
149
|
+
})
|
|
150
|
+
: undefined;
|
|
151
|
+
// Parse exempt paths
|
|
152
|
+
const exemptPathsRaw = values["exempt-paths"];
|
|
153
|
+
const exemptPaths = exemptPathsRaw
|
|
154
|
+
? exemptPathsRaw.split(",").map((p) => p.trim())
|
|
155
|
+
: undefined;
|
|
123
156
|
// Launch the MCP server
|
|
124
157
|
try {
|
|
125
158
|
await serve(registry, {
|
|
@@ -132,6 +165,8 @@ export async function main() {
|
|
|
132
165
|
explorer: values.explorer,
|
|
133
166
|
explorerPrefix: values["explorer-prefix"],
|
|
134
167
|
allowExecute: values["allow-execute"],
|
|
168
|
+
authenticator,
|
|
169
|
+
exemptPaths,
|
|
135
170
|
});
|
|
136
171
|
}
|
|
137
172
|
catch (error) {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|