apcore-mcp 0.6.1 → 0.8.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 +169 -12
- package/dist/adapters/annotations.d.ts.map +1 -1
- package/dist/adapters/annotations.js +3 -0
- package/dist/adapters/annotations.js.map +1 -1
- package/dist/adapters/approval.d.ts +35 -0
- package/dist/adapters/approval.d.ts.map +1 -0
- package/dist/adapters/approval.js +53 -0
- package/dist/adapters/approval.js.map +1 -0
- package/dist/adapters/errors.d.ts +6 -2
- package/dist/adapters/errors.d.ts.map +1 -1
- package/dist/adapters/errors.js +71 -4
- package/dist/adapters/errors.js.map +1 -1
- package/dist/adapters/index.d.ts +2 -0
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +1 -0
- package/dist/adapters/index.js.map +1 -1
- 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 +77 -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 +16 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -4
- 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/factory.d.ts.map +1 -1
- package/dist/server/factory.js +17 -1
- package/dist/server/factory.js.map +1 -1
- package/dist/server/router.d.ts +6 -0
- package/dist/server/router.d.ts.map +1 -1
- package/dist/server/router.js +27 -4
- 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/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -1
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -16,6 +16,7 @@ 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
|
|
@@ -78,6 +79,73 @@ npx apcore-mcp --extensions-dir ./extensions --transport sse --port 8000
|
|
|
78
79
|
| `--name` | `apcore-mcp` | MCP server name |
|
|
79
80
|
| `--version` | package version | MCP server version |
|
|
80
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`.
|
|
81
149
|
|
|
82
150
|
## API Reference
|
|
83
151
|
|
|
@@ -94,10 +162,101 @@ function serve(
|
|
|
94
162
|
port?: number;
|
|
95
163
|
name?: string;
|
|
96
164
|
version?: string;
|
|
165
|
+
explorer?: boolean;
|
|
166
|
+
explorerPrefix?: string;
|
|
167
|
+
allowExecute?: boolean;
|
|
168
|
+
authenticator?: Authenticator;
|
|
169
|
+
exemptPaths?: string[];
|
|
97
170
|
}
|
|
98
171
|
): Promise<void>;
|
|
99
172
|
```
|
|
100
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
|
+
|
|
101
260
|
### `toOpenaiTools(registryOrExecutor, options?)`
|
|
102
261
|
|
|
103
262
|
Export apcore modules as OpenAI-compatible tool definitions.
|
|
@@ -128,16 +287,25 @@ src/
|
|
|
128
287
|
├── index.ts # Public API: serve(), toOpenaiTools()
|
|
129
288
|
├── cli.ts # CLI entry point
|
|
130
289
|
├── types.ts # TypeScript interfaces
|
|
290
|
+
├── helpers.ts # reportProgress() / elicit() helpers
|
|
131
291
|
├── adapters/
|
|
132
292
|
│ ├── schema.ts # JSON Schema $ref inlining
|
|
133
293
|
│ ├── annotations.ts # Module annotations -> MCP hints
|
|
134
294
|
│ ├── errors.ts # Error sanitization
|
|
135
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
|
|
136
300
|
├── converters/
|
|
137
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
|
|
138
305
|
└── server/
|
|
139
306
|
├── factory.ts # MCP Server creation & handler registration
|
|
140
307
|
├── router.ts # Tool call execution routing
|
|
308
|
+
├── context.ts # BridgeContext for executor call chains
|
|
141
309
|
├── transport.ts # Transport lifecycle (stdio/HTTP/SSE)
|
|
142
310
|
└── listener.ts # Dynamic registry event listener
|
|
143
311
|
```
|
|
@@ -176,18 +344,7 @@ npm run dev
|
|
|
176
344
|
|
|
177
345
|
## Testing
|
|
178
346
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
| Module | Coverage |
|
|
182
|
-
|---|---|
|
|
183
|
-
| annotations.ts | 100% |
|
|
184
|
-
| idNormalizer.ts | 100% |
|
|
185
|
-
| factory.ts | 100% |
|
|
186
|
-
| router.ts | 100% |
|
|
187
|
-
| errors.ts | 98.8% |
|
|
188
|
-
| schema.ts | 97.0% |
|
|
189
|
-
| openai.ts | 91.7% |
|
|
190
|
-
| listener.ts | 89.7% |
|
|
347
|
+
284 tests across 22 test suites.
|
|
191
348
|
|
|
192
349
|
## License
|
|
193
350
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"annotations.d.ts","sourceRoot":"","sources":["../../src/adapters/annotations.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEzE,qBAAa,gBAAgB;IAC3B;;;;;;;;;OASG;IACH,gBAAgB,CAAC,WAAW,EAAE,iBAAiB,GAAG,IAAI,GAAG,kBAAkB;IAoB3E;;;;;;;;;;;OAWG;IACH,mBAAmB,CAAC,WAAW,EAAE,iBAAiB,GAAG,IAAI,GAAG,MAAM;
|
|
1
|
+
{"version":3,"file":"annotations.d.ts","sourceRoot":"","sources":["../../src/adapters/annotations.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEzE,qBAAa,gBAAgB;IAC3B;;;;;;;;;OASG;IACH,gBAAgB,CAAC,WAAW,EAAE,iBAAiB,GAAG,IAAI,GAAG,kBAAkB;IAoB3E;;;;;;;;;;;OAWG;IACH,mBAAmB,CAAC,WAAW,EAAE,iBAAiB,GAAG,IAAI,GAAG,MAAM;IAmClE;;;;OAIG;IACH,mBAAmB,CAAC,WAAW,EAAE,iBAAiB,GAAG,IAAI,GAAG,OAAO;CAOpE"}
|
|
@@ -56,6 +56,7 @@ export class AnnotationMapper {
|
|
|
56
56
|
idempotent: false,
|
|
57
57
|
requires_approval: false,
|
|
58
58
|
open_world: true,
|
|
59
|
+
streaming: false,
|
|
59
60
|
};
|
|
60
61
|
const parts = [];
|
|
61
62
|
if (annotations.readonly !== DEFAULTS.readonly)
|
|
@@ -68,6 +69,8 @@ export class AnnotationMapper {
|
|
|
68
69
|
parts.push(`requires_approval=${annotations.requiresApproval}`);
|
|
69
70
|
if (annotations.openWorld !== DEFAULTS.open_world)
|
|
70
71
|
parts.push(`open_world=${annotations.openWorld}`);
|
|
72
|
+
if (annotations.streaming !== DEFAULTS.streaming)
|
|
73
|
+
parts.push(`streaming=${annotations.streaming}`);
|
|
71
74
|
if (parts.length === 0) {
|
|
72
75
|
return "";
|
|
73
76
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"annotations.js","sourceRoot":"","sources":["../../src/adapters/annotations.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,MAAM,OAAO,gBAAgB;IAC3B;;;;;;;;;OASG;IACH,gBAAgB,CAAC,WAAqC;QACpD,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;YACzB,OAAO;gBACL,YAAY,EAAE,KAAK;gBACnB,eAAe,EAAE,KAAK;gBACtB,cAAc,EAAE,KAAK;gBACrB,aAAa,EAAE,IAAI;gBACnB,KAAK,EAAE,IAAI;aACZ,CAAC;QACJ,CAAC;QAED,OAAO;YACL,YAAY,EAAE,WAAW,CAAC,QAAQ;YAClC,eAAe,EAAE,WAAW,CAAC,WAAW;YACxC,cAAc,EAAE,WAAW,CAAC,UAAU;YACtC,aAAa,EAAE,WAAW,CAAC,SAAS;YACpC,KAAK,EAAE,IAAI;SACZ,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;OAWG;IACH,mBAAmB,CAAC,WAAqC;QACvD,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;YACzB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,QAAQ,GAA4B;YACxC,QAAQ,EAAE,KAAK;YACf,WAAW,EAAE,KAAK;YAClB,UAAU,EAAE,KAAK;YACjB,iBAAiB,EAAE,KAAK;YACxB,UAAU,EAAE,IAAI;SACjB,CAAC;QAEF,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,IAAI,WAAW,CAAC,QAAQ,KAAK,QAAQ,CAAC,QAAQ;YAC5C,KAAK,CAAC,IAAI,CAAC,YAAY,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC;QACjD,IAAI,WAAW,CAAC,WAAW,KAAK,QAAQ,CAAC,WAAW;YAClD,KAAK,CAAC,IAAI,CAAC,eAAe,WAAW,CAAC,WAAW,EAAE,CAAC,CAAC;QACvD,IAAI,WAAW,CAAC,UAAU,KAAK,QAAQ,CAAC,UAAU;YAChD,KAAK,CAAC,IAAI,CAAC,cAAc,WAAW,CAAC,UAAU,EAAE,CAAC,CAAC;QACrD,IAAI,WAAW,CAAC,gBAAgB,KAAK,QAAQ,CAAC,iBAAiB;YAC7D,KAAK,CAAC,IAAI,CAAC,qBAAqB,WAAW,CAAC,gBAAgB,EAAE,CAAC,CAAC;QAClE,IAAI,WAAW,CAAC,SAAS,KAAK,QAAQ,CAAC,UAAU;YAC/C,KAAK,CAAC,IAAI,CAAC,cAAc,WAAW,CAAC,SAAS,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"annotations.js","sourceRoot":"","sources":["../../src/adapters/annotations.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,MAAM,OAAO,gBAAgB;IAC3B;;;;;;;;;OASG;IACH,gBAAgB,CAAC,WAAqC;QACpD,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;YACzB,OAAO;gBACL,YAAY,EAAE,KAAK;gBACnB,eAAe,EAAE,KAAK;gBACtB,cAAc,EAAE,KAAK;gBACrB,aAAa,EAAE,IAAI;gBACnB,KAAK,EAAE,IAAI;aACZ,CAAC;QACJ,CAAC;QAED,OAAO;YACL,YAAY,EAAE,WAAW,CAAC,QAAQ;YAClC,eAAe,EAAE,WAAW,CAAC,WAAW;YACxC,cAAc,EAAE,WAAW,CAAC,UAAU;YACtC,aAAa,EAAE,WAAW,CAAC,SAAS;YACpC,KAAK,EAAE,IAAI;SACZ,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;OAWG;IACH,mBAAmB,CAAC,WAAqC;QACvD,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;YACzB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,QAAQ,GAA4B;YACxC,QAAQ,EAAE,KAAK;YACf,WAAW,EAAE,KAAK;YAClB,UAAU,EAAE,KAAK;YACjB,iBAAiB,EAAE,KAAK;YACxB,UAAU,EAAE,IAAI;YAChB,SAAS,EAAE,KAAK;SACjB,CAAC;QAEF,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,IAAI,WAAW,CAAC,QAAQ,KAAK,QAAQ,CAAC,QAAQ;YAC5C,KAAK,CAAC,IAAI,CAAC,YAAY,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC;QACjD,IAAI,WAAW,CAAC,WAAW,KAAK,QAAQ,CAAC,WAAW;YAClD,KAAK,CAAC,IAAI,CAAC,eAAe,WAAW,CAAC,WAAW,EAAE,CAAC,CAAC;QACvD,IAAI,WAAW,CAAC,UAAU,KAAK,QAAQ,CAAC,UAAU;YAChD,KAAK,CAAC,IAAI,CAAC,cAAc,WAAW,CAAC,UAAU,EAAE,CAAC,CAAC;QACrD,IAAI,WAAW,CAAC,gBAAgB,KAAK,QAAQ,CAAC,iBAAiB;YAC7D,KAAK,CAAC,IAAI,CAAC,qBAAqB,WAAW,CAAC,gBAAgB,EAAE,CAAC,CAAC;QAClE,IAAI,WAAW,CAAC,SAAS,KAAK,QAAQ,CAAC,UAAU;YAC/C,KAAK,CAAC,IAAI,CAAC,cAAc,WAAW,CAAC,SAAS,EAAE,CAAC,CAAC;QACpD,IAAI,WAAW,CAAC,SAAS,KAAK,QAAQ,CAAC,SAAS;YAC9C,KAAK,CAAC,IAAI,CAAC,aAAa,WAAW,CAAC,SAAS,EAAE,CAAC,CAAC;QAEnD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,OAAO,qBAAqB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;IAClD,CAAC;IAED;;;;OAIG;IACH,mBAAmB,CAAC,WAAqC;QACvD,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;YACzB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,WAAW,CAAC,gBAAgB,CAAC;IACtC,CAAC;CACF"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ElicitationApprovalHandler: bridges MCP elicitation to apcore's approval system.
|
|
3
|
+
*
|
|
4
|
+
* Uses the MCP elicit callback (injected into Context.data) to present
|
|
5
|
+
* approval requests to the human user via the MCP client.
|
|
6
|
+
*/
|
|
7
|
+
export interface ApprovalRequest {
|
|
8
|
+
moduleId: string;
|
|
9
|
+
description?: string | null;
|
|
10
|
+
arguments: Record<string, unknown>;
|
|
11
|
+
context?: {
|
|
12
|
+
data?: Record<string, unknown>;
|
|
13
|
+
} | null;
|
|
14
|
+
}
|
|
15
|
+
export interface ApprovalResult {
|
|
16
|
+
status: "approved" | "rejected" | "timeout" | "pending";
|
|
17
|
+
reason?: string | null;
|
|
18
|
+
}
|
|
19
|
+
export declare class ElicitationApprovalHandler {
|
|
20
|
+
/**
|
|
21
|
+
* Request approval via MCP elicitation.
|
|
22
|
+
*
|
|
23
|
+
* Extracts the elicit callback from request.context.data, builds
|
|
24
|
+
* an approval message, and maps the elicit response to an ApprovalResult.
|
|
25
|
+
*/
|
|
26
|
+
requestApproval(request: ApprovalRequest): Promise<ApprovalResult>;
|
|
27
|
+
/**
|
|
28
|
+
* Check status of an existing approval.
|
|
29
|
+
*
|
|
30
|
+
* Phase B (async polling) is not supported via MCP elicitation since
|
|
31
|
+
* elicitation is stateless.
|
|
32
|
+
*/
|
|
33
|
+
checkApproval(_approvalId: string): Promise<ApprovalResult>;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=approval.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval.d.ts","sourceRoot":"","sources":["../../src/adapters/approval.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAAG,IAAI,CAAC;CACrD;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC;IACxD,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,qBAAa,0BAA0B;IACrC;;;;;OAKG;IACG,eAAe,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;IAsCxE;;;;;OAKG;IACG,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CAGlE"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ElicitationApprovalHandler: bridges MCP elicitation to apcore's approval system.
|
|
3
|
+
*
|
|
4
|
+
* Uses the MCP elicit callback (injected into Context.data) to present
|
|
5
|
+
* approval requests to the human user via the MCP client.
|
|
6
|
+
*/
|
|
7
|
+
import { MCP_ELICIT_KEY } from "../helpers.js";
|
|
8
|
+
export class ElicitationApprovalHandler {
|
|
9
|
+
/**
|
|
10
|
+
* Request approval via MCP elicitation.
|
|
11
|
+
*
|
|
12
|
+
* Extracts the elicit callback from request.context.data, builds
|
|
13
|
+
* an approval message, and maps the elicit response to an ApprovalResult.
|
|
14
|
+
*/
|
|
15
|
+
async requestApproval(request) {
|
|
16
|
+
const data = request.context?.data ?? null;
|
|
17
|
+
if (data === null) {
|
|
18
|
+
return { status: "rejected", reason: "No context available for elicitation" };
|
|
19
|
+
}
|
|
20
|
+
const elicitCallback = data[MCP_ELICIT_KEY];
|
|
21
|
+
if (!elicitCallback) {
|
|
22
|
+
return { status: "rejected", reason: "No elicitation callback available" };
|
|
23
|
+
}
|
|
24
|
+
const message = `Approval required for tool: ${request.moduleId}\n\n` +
|
|
25
|
+
`${request.description ?? ""}\n\n` +
|
|
26
|
+
`Arguments: ${JSON.stringify(request.arguments)}`;
|
|
27
|
+
let result;
|
|
28
|
+
try {
|
|
29
|
+
result = await elicitCallback(message);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return { status: "rejected", reason: "Elicitation request failed" };
|
|
33
|
+
}
|
|
34
|
+
if (result === null || result === undefined) {
|
|
35
|
+
return { status: "rejected", reason: "Elicitation returned no response" };
|
|
36
|
+
}
|
|
37
|
+
const action = result.action;
|
|
38
|
+
if (action === "accept") {
|
|
39
|
+
return { status: "approved" };
|
|
40
|
+
}
|
|
41
|
+
return { status: "rejected", reason: `User action: ${action}` };
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Check status of an existing approval.
|
|
45
|
+
*
|
|
46
|
+
* Phase B (async polling) is not supported via MCP elicitation since
|
|
47
|
+
* elicitation is stateless.
|
|
48
|
+
*/
|
|
49
|
+
async checkApproval(_approvalId) {
|
|
50
|
+
return { status: "rejected", reason: "Phase B not supported via MCP elicitation" };
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=approval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval.js","sourceRoot":"","sources":["../../src/adapters/approval.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAc/C,MAAM,OAAO,0BAA0B;IACrC;;;;;OAKG;IACH,KAAK,CAAC,eAAe,CAAC,OAAwB;QAC5C,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,EAAE,IAAI,IAAI,IAAI,CAAC;QAC3C,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClB,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,sCAAsC,EAAE,CAAC;QAChF,CAAC;QAED,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,CAE7B,CAAC;QAEd,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,mCAAmC,EAAE,CAAC;QAC7E,CAAC;QAED,MAAM,OAAO,GACX,+BAA+B,OAAO,CAAC,QAAQ,MAAM;YACrD,GAAG,OAAO,CAAC,WAAW,IAAI,EAAE,MAAM;YAClC,cAAc,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QAEpD,IAAI,MAAoE,CAAC;QACzE,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,CAAC;QACzC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,4BAA4B,EAAE,CAAC;QACtE,CAAC;QAED,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YAC5C,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,kCAAkC,EAAE,CAAC;QAC5E,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC7B,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;YACxB,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;QAChC,CAAC;QAED,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,gBAAgB,MAAM,EAAE,EAAE,CAAC;IAClE,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,aAAa,CAAC,WAAmB;QACrC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,2CAA2C,EAAE,CAAC;IACrF,CAAC;CACF"}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* ErrorMapper - Maps apcore errors to MCP-compatible error responses.
|
|
3
3
|
*
|
|
4
4
|
* Handles ModuleError instances with specific error codes, sanitizes
|
|
5
|
-
* internal error details,
|
|
6
|
-
* field-level detail.
|
|
5
|
+
* internal error details, formats schema validation errors with
|
|
6
|
+
* field-level detail, and extracts AI guidance fields.
|
|
7
7
|
*/
|
|
8
8
|
import type { McpErrorResponse } from "../types.js";
|
|
9
9
|
export declare class ErrorMapper {
|
|
@@ -14,6 +14,10 @@ export declare class ErrorMapper {
|
|
|
14
14
|
* Applies sanitization and formatting rules based on the error code.
|
|
15
15
|
*/
|
|
16
16
|
toMcpError(error: unknown): McpErrorResponse;
|
|
17
|
+
/**
|
|
18
|
+
* Extract AI guidance fields from error and attach non-undefined values to result.
|
|
19
|
+
*/
|
|
20
|
+
private _attachAiGuidance;
|
|
17
21
|
/**
|
|
18
22
|
* Duck-type check for ModuleError-like objects.
|
|
19
23
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/adapters/errors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/adapters/errors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAgBpD,qBAAa,WAAW;IACtB;;;;;OAKG;IACH,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB;IA2G5C;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAazB;;;;OAIG;IACH,OAAO,CAAC,cAAc;IAetB;;;;;OAKG;IACH,OAAO,CAAC,sBAAsB;CA4B/B"}
|
package/dist/adapters/errors.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* ErrorMapper - Maps apcore errors to MCP-compatible error responses.
|
|
3
3
|
*
|
|
4
4
|
* Handles ModuleError instances with specific error codes, sanitizes
|
|
5
|
-
* internal error details,
|
|
6
|
-
* field-level detail.
|
|
5
|
+
* internal error details, formats schema validation errors with
|
|
6
|
+
* field-level detail, and extracts AI guidance fields.
|
|
7
7
|
*/
|
|
8
8
|
import { ErrorCodes } from "../types.js";
|
|
9
9
|
/** Internal error codes that should be sanitized to a generic message. */
|
|
@@ -12,6 +12,12 @@ const INTERNAL_ERROR_CODES = new Set([
|
|
|
12
12
|
ErrorCodes.CIRCULAR_CALL,
|
|
13
13
|
ErrorCodes.CALL_FREQUENCY_EXCEEDED,
|
|
14
14
|
]);
|
|
15
|
+
/**
|
|
16
|
+
* AI guidance field names on the MCP wire format (camelCase).
|
|
17
|
+
* Both Python and TypeScript output identical camelCase keys in MCP responses.
|
|
18
|
+
* Python reads snake_case from apcore errors and maps to camelCase on output.
|
|
19
|
+
*/
|
|
20
|
+
const _AI_GUIDANCE_FIELDS = ["retryable", "aiGuidance", "userFixable", "suggestion"];
|
|
15
21
|
export class ErrorMapper {
|
|
16
22
|
/**
|
|
17
23
|
* Convert an error to an MCP error response.
|
|
@@ -45,20 +51,69 @@ export class ErrorMapper {
|
|
|
45
51
|
// Schema validation error -> formatted with field-level details
|
|
46
52
|
if (code === ErrorCodes.SCHEMA_VALIDATION_ERROR) {
|
|
47
53
|
const message = this._formatValidationError(details);
|
|
48
|
-
|
|
54
|
+
const result = {
|
|
49
55
|
isError: true,
|
|
50
56
|
errorType: ErrorCodes.SCHEMA_VALIDATION_ERROR,
|
|
51
57
|
message,
|
|
52
58
|
details,
|
|
53
59
|
};
|
|
60
|
+
this._attachAiGuidance(error, result);
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
// Approval pending -> narrow details to approvalId only
|
|
64
|
+
// NOTE: apcore-js may use camelCase (approvalId) or snake_case (approval_id).
|
|
65
|
+
// Check both to stay compatible with either convention.
|
|
66
|
+
if (code === ErrorCodes.APPROVAL_PENDING) {
|
|
67
|
+
const idKey = details && "approvalId" in details
|
|
68
|
+
? "approvalId"
|
|
69
|
+
: details && "approval_id" in details
|
|
70
|
+
? "approval_id"
|
|
71
|
+
: null;
|
|
72
|
+
const narrowed = idKey
|
|
73
|
+
? { approvalId: details[idKey] }
|
|
74
|
+
: null;
|
|
75
|
+
const result = {
|
|
76
|
+
isError: true,
|
|
77
|
+
errorType: code,
|
|
78
|
+
message: error.message,
|
|
79
|
+
details: narrowed,
|
|
80
|
+
};
|
|
81
|
+
this._attachAiGuidance(error, result);
|
|
82
|
+
return result;
|
|
83
|
+
}
|
|
84
|
+
// Approval timeout -> mark as retryable
|
|
85
|
+
if (code === ErrorCodes.APPROVAL_TIMEOUT) {
|
|
86
|
+
const result = {
|
|
87
|
+
isError: true,
|
|
88
|
+
errorType: code,
|
|
89
|
+
message: error.message,
|
|
90
|
+
details,
|
|
91
|
+
retryable: true,
|
|
92
|
+
};
|
|
93
|
+
this._attachAiGuidance(error, result);
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
96
|
+
// Approval denied -> extract reason from details
|
|
97
|
+
if (code === ErrorCodes.APPROVAL_DENIED) {
|
|
98
|
+
const reason = details ? details.reason : undefined;
|
|
99
|
+
const result = {
|
|
100
|
+
isError: true,
|
|
101
|
+
errorType: code,
|
|
102
|
+
message: error.message,
|
|
103
|
+
details: reason ? { reason } : details,
|
|
104
|
+
};
|
|
105
|
+
this._attachAiGuidance(error, result);
|
|
106
|
+
return result;
|
|
54
107
|
}
|
|
55
108
|
// Other known ModuleError codes -> pass through
|
|
56
|
-
|
|
109
|
+
const result = {
|
|
57
110
|
isError: true,
|
|
58
111
|
errorType: code,
|
|
59
112
|
message: error.message,
|
|
60
113
|
details,
|
|
61
114
|
};
|
|
115
|
+
this._attachAiGuidance(error, result);
|
|
116
|
+
return result;
|
|
62
117
|
}
|
|
63
118
|
// Unknown/unexpected exceptions -> generic error
|
|
64
119
|
return {
|
|
@@ -68,6 +123,18 @@ export class ErrorMapper {
|
|
|
68
123
|
details: null,
|
|
69
124
|
};
|
|
70
125
|
}
|
|
126
|
+
/**
|
|
127
|
+
* Extract AI guidance fields from error and attach non-undefined values to result.
|
|
128
|
+
*/
|
|
129
|
+
_attachAiGuidance(error, result) {
|
|
130
|
+
for (const field of _AI_GUIDANCE_FIELDS) {
|
|
131
|
+
const value = error[field];
|
|
132
|
+
if (value !== undefined && value !== null && result[field] === undefined) {
|
|
133
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
134
|
+
result[field] = value;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
71
138
|
/**
|
|
72
139
|
* Duck-type check for ModuleError-like objects.
|
|
73
140
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/adapters/errors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,0EAA0E;AAC1E,MAAM,oBAAoB,GAAgB,IAAI,GAAG,CAAC;IAChD,UAAU,CAAC,mBAAmB;IAC9B,UAAU,CAAC,aAAa;IACxB,UAAU,CAAC,uBAAuB;CACnC,CAAC,CAAC;AAEH,MAAM,OAAO,WAAW;IACtB;;;;;OAKG;IACH,UAAU,CAAC,KAAc;QACvB,+CAA+C;QAC/C,IAAI,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;YACxB,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;YAE9B,0CAA0C;YAC1C,IAAI,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnC,OAAO;oBACL,OAAO,EAAE,IAAI;oBACb,SAAS,EAAE,IAAI;oBACf,OAAO,EAAE,yBAAyB;oBAClC,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;YAED,wCAAwC;YACxC,IAAI,IAAI,KAAK,UAAU,CAAC,UAAU,EAAE,CAAC;gBACnC,OAAO;oBACL,OAAO,EAAE,IAAI;oBACb,SAAS,EAAE,UAAU,CAAC,UAAU;oBAChC,OAAO,EAAE,eAAe;oBACxB,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;YAED,gEAAgE;YAChE,IAAI,IAAI,KAAK,UAAU,CAAC,uBAAuB,EAAE,CAAC;gBAChD,MAAM,OAAO,GAAG,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;gBACrD,
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/adapters/errors.ts"],"names":[],"mappings":"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"}
|
package/dist/adapters/index.d.ts
CHANGED
|
@@ -5,4 +5,6 @@ export { SchemaConverter } from "./schema.js";
|
|
|
5
5
|
export { AnnotationMapper } from "./annotations.js";
|
|
6
6
|
export { ErrorMapper } from "./errors.js";
|
|
7
7
|
export { ModuleIDNormalizer } from "./idNormalizer.js";
|
|
8
|
+
export { ElicitationApprovalHandler } from "./approval.js";
|
|
9
|
+
export type { ApprovalRequest, ApprovalResult } from "./approval.js";
|
|
8
10
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAC3D,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/adapters/index.js
CHANGED
|
@@ -5,4 +5,5 @@ export { SchemaConverter } from "./schema.js";
|
|
|
5
5
|
export { AnnotationMapper } from "./annotations.js";
|
|
6
6
|
export { ErrorMapper } from "./errors.js";
|
|
7
7
|
export { ModuleIDNormalizer } from "./idNormalizer.js";
|
|
8
|
+
export { ElicitationApprovalHandler } from "./approval.js";
|
|
8
9
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -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"}
|