apcore-mcp 0.9.0 → 0.10.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/README.md +23 -35
- package/dist/adapters/annotations.d.ts.map +1 -1
- package/dist/adapters/annotations.js +21 -14
- package/dist/adapters/annotations.js.map +1 -1
- package/dist/apcore-mcp.d.ts +150 -0
- package/dist/apcore-mcp.d.ts.map +1 -0
- package/dist/apcore-mcp.js +217 -0
- package/dist/apcore-mcp.js.map +1 -0
- package/dist/auth/hooks.d.ts +30 -0
- package/dist/auth/hooks.d.ts.map +1 -0
- package/dist/auth/hooks.js +31 -0
- package/dist/auth/hooks.js.map +1 -0
- package/dist/index.d.ts +21 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -17
- package/dist/index.js.map +1 -1
- package/dist/server/router.d.ts +16 -1
- package/dist/server/router.d.ts.map +1 -1
- package/dist/server/router.js +26 -3
- package/dist/server/router.js.map +1 -1
- package/dist/server/transport.d.ts +10 -9
- package/dist/server/transport.d.ts.map +1 -1
- package/dist/server/transport.js +33 -42
- 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 +1 -0
- package/dist/types.js.map +1 -1
- package/package.json +4 -3
- package/dist/explorer/handler.d.ts +0 -64
- package/dist/explorer/handler.d.ts.map +0 -1
- package/dist/explorer/handler.js +0 -187
- package/dist/explorer/handler.js.map +0 -1
- package/dist/explorer/html.d.ts +0 -9
- package/dist/explorer/html.d.ts.map +0 -1
- package/dist/explorer/html.js +0 -401
- package/dist/explorer/html.js.map +0 -1
- package/dist/explorer/index.d.ts +0 -6
- package/dist/explorer/index.d.ts.map +0 -1
- package/dist/explorer/index.js +0 -5
- package/dist/explorer/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -186,6 +186,29 @@ function serve(
|
|
|
186
186
|
): Promise<void>;
|
|
187
187
|
```
|
|
188
188
|
|
|
189
|
+
### `asyncServe(registryOrExecutor, options?)`
|
|
190
|
+
|
|
191
|
+
Embed the MCP server into a larger Node.js HTTP application. Returns an HTTP request handler and a close function for lifecycle management.
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
import { asyncServe } from "apcore-mcp";
|
|
195
|
+
|
|
196
|
+
const { handler, close } = await asyncServe(executor, {
|
|
197
|
+
name: "apcore-mcp",
|
|
198
|
+
explorer: true,
|
|
199
|
+
allowExecute: true,
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// Mount in a custom HTTP server
|
|
203
|
+
const server = http.createServer(handler);
|
|
204
|
+
server.listen(8000);
|
|
205
|
+
|
|
206
|
+
// Clean up when done
|
|
207
|
+
await close();
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Accepts the same options as `serve()` except `transport`, `host`, `port`, `onStartup`, and `onShutdown`.
|
|
211
|
+
|
|
189
212
|
### Tool Explorer
|
|
190
213
|
|
|
191
214
|
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.
|
|
@@ -295,37 +318,6 @@ function toOpenaiTools(
|
|
|
295
318
|
- `tags` — Filter modules by tags
|
|
296
319
|
- `prefix` — Filter modules by ID prefix
|
|
297
320
|
|
|
298
|
-
## Architecture
|
|
299
|
-
|
|
300
|
-
```
|
|
301
|
-
src/
|
|
302
|
-
├── index.ts # Public API: serve(), toOpenaiTools()
|
|
303
|
-
├── cli.ts # CLI entry point
|
|
304
|
-
├── types.ts # TypeScript interfaces
|
|
305
|
-
├── helpers.ts # reportProgress() / elicit() helpers
|
|
306
|
-
├── adapters/
|
|
307
|
-
│ ├── schema.ts # JSON Schema $ref inlining
|
|
308
|
-
│ ├── annotations.ts # Module annotations -> MCP hints
|
|
309
|
-
│ ├── errors.ts # Error sanitization
|
|
310
|
-
│ ├── idNormalizer.ts # Dot-notation <-> dash-notation
|
|
311
|
-
│ └── approval.ts # Elicitation-based approval handler
|
|
312
|
-
├── auth/
|
|
313
|
-
│ ├── jwt.ts # JWT Bearer token authenticator
|
|
314
|
-
│ ├── storage.ts # AsyncLocalStorage identity propagation
|
|
315
|
-
│ └── types.ts # Authenticator / Identity interfaces
|
|
316
|
-
├── converters/
|
|
317
|
-
│ └── openai.ts # OpenAI tool definition converter
|
|
318
|
-
├── explorer/
|
|
319
|
-
│ ├── handler.ts # Explorer HTTP route handler
|
|
320
|
-
│ └── html.ts # Self-contained HTML/CSS/JS page
|
|
321
|
-
└── server/
|
|
322
|
-
├── factory.ts # MCP Server creation & handler registration
|
|
323
|
-
├── router.ts # Tool call execution routing
|
|
324
|
-
├── context.ts # BridgeContext for executor call chains
|
|
325
|
-
├── transport.ts # Transport lifecycle (stdio/HTTP/SSE)
|
|
326
|
-
└── listener.ts # Dynamic registry event listener
|
|
327
|
-
```
|
|
328
|
-
|
|
329
321
|
## Examples
|
|
330
322
|
|
|
331
323
|
See [examples/README.md](examples/README.md) for runnable demos covering both class-based modules and zero-code-intrusion wrapping via the `module()` factory.
|
|
@@ -358,10 +350,6 @@ npm run build
|
|
|
358
350
|
npm run dev
|
|
359
351
|
```
|
|
360
352
|
|
|
361
|
-
## Testing
|
|
362
|
-
|
|
363
|
-
313 tests across 23 test suites.
|
|
364
|
-
|
|
365
353
|
## License
|
|
366
354
|
|
|
367
355
|
Apache-2.0
|
|
@@ -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;
|
|
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;AAczE,qBAAa,gBAAgB;IAC3B;;;;;;;;;OASG;IACH,gBAAgB,CAAC,WAAW,EAAE,iBAAiB,GAAG,IAAI,GAAG,kBAAkB;IAoB3E;;;;;;OAMG;IACH,mBAAmB,CAAC,WAAW,EAAE,iBAAiB,GAAG,IAAI,GAAG,MAAM;IAmDlE;;;;OAIG;IACH,mBAAmB,CAAC,WAAW,EAAE,iBAAiB,GAAG,IAAI,GAAG,OAAO;CAOpE"}
|
|
@@ -5,6 +5,17 @@
|
|
|
5
5
|
* hint-based annotation system. Also provides description suffix generation
|
|
6
6
|
* and approval requirement checking.
|
|
7
7
|
*/
|
|
8
|
+
/** Default annotation values matching apcore's ModuleAnnotations defaults. */
|
|
9
|
+
const DEFAULT_ANNOTATIONS = {
|
|
10
|
+
readonly: false,
|
|
11
|
+
destructive: false,
|
|
12
|
+
idempotent: false,
|
|
13
|
+
requiresApproval: false,
|
|
14
|
+
openWorld: true,
|
|
15
|
+
streaming: false,
|
|
16
|
+
cacheable: false,
|
|
17
|
+
paginated: false,
|
|
18
|
+
};
|
|
8
19
|
export class AnnotationMapper {
|
|
9
20
|
/**
|
|
10
21
|
* Convert apcore module annotations to MCP annotations dict.
|
|
@@ -45,14 +56,6 @@ export class AnnotationMapper {
|
|
|
45
56
|
if (annotations === null) {
|
|
46
57
|
return "";
|
|
47
58
|
}
|
|
48
|
-
const DEFAULTS = {
|
|
49
|
-
readonly: false,
|
|
50
|
-
destructive: false,
|
|
51
|
-
idempotent: false,
|
|
52
|
-
requires_approval: false,
|
|
53
|
-
open_world: true,
|
|
54
|
-
streaming: false,
|
|
55
|
-
};
|
|
56
59
|
const warnings = [];
|
|
57
60
|
if (annotations.destructive) {
|
|
58
61
|
warnings.push("WARNING: DESTRUCTIVE - This operation may irreversibly modify or " +
|
|
@@ -62,18 +65,22 @@ export class AnnotationMapper {
|
|
|
62
65
|
warnings.push("REQUIRES APPROVAL: Human confirmation is required before execution.");
|
|
63
66
|
}
|
|
64
67
|
const parts = [];
|
|
65
|
-
if (annotations.readonly !==
|
|
68
|
+
if (annotations.readonly !== DEFAULT_ANNOTATIONS.readonly)
|
|
66
69
|
parts.push(`readonly=${annotations.readonly}`);
|
|
67
|
-
if (annotations.destructive !==
|
|
70
|
+
if (annotations.destructive !== DEFAULT_ANNOTATIONS.destructive)
|
|
68
71
|
parts.push(`destructive=${annotations.destructive}`);
|
|
69
|
-
if (annotations.idempotent !==
|
|
72
|
+
if (annotations.idempotent !== DEFAULT_ANNOTATIONS.idempotent)
|
|
70
73
|
parts.push(`idempotent=${annotations.idempotent}`);
|
|
71
|
-
if (annotations.requiresApproval !==
|
|
74
|
+
if (annotations.requiresApproval !== DEFAULT_ANNOTATIONS.requiresApproval)
|
|
72
75
|
parts.push(`requires_approval=${annotations.requiresApproval}`);
|
|
73
|
-
if (annotations.openWorld !==
|
|
76
|
+
if (annotations.openWorld !== DEFAULT_ANNOTATIONS.openWorld)
|
|
74
77
|
parts.push(`open_world=${annotations.openWorld}`);
|
|
75
|
-
if (annotations.streaming !==
|
|
78
|
+
if (annotations.streaming !== DEFAULT_ANNOTATIONS.streaming)
|
|
76
79
|
parts.push(`streaming=${annotations.streaming}`);
|
|
80
|
+
if ((annotations.cacheable ?? false) !== DEFAULT_ANNOTATIONS.cacheable)
|
|
81
|
+
parts.push(`cacheable=${annotations.cacheable}`);
|
|
82
|
+
if ((annotations.paginated ?? false) !== DEFAULT_ANNOTATIONS.paginated)
|
|
83
|
+
parts.push(`paginated=${annotations.paginated}`);
|
|
77
84
|
if (warnings.length === 0 && parts.length === 0) {
|
|
78
85
|
return "";
|
|
79
86
|
}
|
|
@@ -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;;;;;;OAMG;IACH,mBAAmB,CAAC,WAAqC;QACvD,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;YACzB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,QAAQ,
|
|
1
|
+
{"version":3,"file":"annotations.js","sourceRoot":"","sources":["../../src/adapters/annotations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* APCoreMCP: Unified entry point for apcore-mcp.
|
|
3
|
+
*
|
|
4
|
+
* Wraps Registry discovery, MCP server creation, and OpenAI tool export
|
|
5
|
+
* into a single object with a simple API.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* // Minimal — just point to extensions
|
|
10
|
+
* const mcp = new APCoreMCP("./extensions");
|
|
11
|
+
* await mcp.serve();
|
|
12
|
+
*
|
|
13
|
+
* // With options
|
|
14
|
+
* const mcp = new APCoreMCP("./extensions", { name: "my-server", tags: ["public"] });
|
|
15
|
+
* await mcp.serve({ transport: "streamable-http", port: 9000, explorer: true });
|
|
16
|
+
*
|
|
17
|
+
* // Export OpenAI tools
|
|
18
|
+
* const tools = mcp.toOpenaiTools();
|
|
19
|
+
*
|
|
20
|
+
* // Embed into existing HTTP server
|
|
21
|
+
* const app = await mcp.asyncServe({ explorer: true });
|
|
22
|
+
* // app.handler is a Node.js request handler; call app.close() on shutdown
|
|
23
|
+
*
|
|
24
|
+
* // Use existing Registry or Executor
|
|
25
|
+
* const mcp = new APCoreMCP(registry);
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
import type { RegistryOrExecutor, Registry, Executor, OpenAIToolDef } from "./types.js";
|
|
29
|
+
import type { Authenticator } from "./auth/types.js";
|
|
30
|
+
import type { MetricsExporter } from "./server/transport.js";
|
|
31
|
+
import type { AsyncServeApp, ToOpenaiToolsOptions } from "./index.js";
|
|
32
|
+
/** Options for the APCoreMCP constructor. */
|
|
33
|
+
export interface APCoreMCPOptions {
|
|
34
|
+
/** MCP server name. Default: "apcore-mcp" */
|
|
35
|
+
name?: string;
|
|
36
|
+
/** MCP server version. Default: package version */
|
|
37
|
+
version?: string;
|
|
38
|
+
/** Filter modules by tags. */
|
|
39
|
+
tags?: string[] | null;
|
|
40
|
+
/** Filter modules by prefix. */
|
|
41
|
+
prefix?: string | null;
|
|
42
|
+
/** Minimum log level. */
|
|
43
|
+
logLevel?: "DEBUG" | "INFO" | "WARNING" | "ERROR" | "CRITICAL";
|
|
44
|
+
/** Enable input validation against schemas. Default: false */
|
|
45
|
+
validateInputs?: boolean;
|
|
46
|
+
/** Optional MetricsCollector for Prometheus /metrics endpoint. */
|
|
47
|
+
metricsCollector?: MetricsExporter;
|
|
48
|
+
/** Optional authenticator for request authentication (HTTP transports only). */
|
|
49
|
+
authenticator?: Authenticator;
|
|
50
|
+
/** If true (default), unauthenticated requests are rejected with 401. */
|
|
51
|
+
requireAuth?: boolean;
|
|
52
|
+
/** Custom paths exempt from authentication. */
|
|
53
|
+
exemptPaths?: string[];
|
|
54
|
+
/** Optional approval handler passed to the Executor. */
|
|
55
|
+
approvalHandler?: unknown;
|
|
56
|
+
/**
|
|
57
|
+
* Optional function that formats execution results into text for LLM consumption.
|
|
58
|
+
* When undefined, results are serialised with `JSON.stringify(result)`.
|
|
59
|
+
*/
|
|
60
|
+
outputFormatter?: (result: Record<string, unknown>) => string;
|
|
61
|
+
}
|
|
62
|
+
/** Options for APCoreMCP.serve() (transport + lifecycle subset). */
|
|
63
|
+
export interface APCoreMCPServeOptions {
|
|
64
|
+
/** Transport type. Default: "stdio" */
|
|
65
|
+
transport?: "stdio" | "streamable-http" | "sse";
|
|
66
|
+
/** Host address for HTTP-based transports. Default: "127.0.0.1" */
|
|
67
|
+
host?: string;
|
|
68
|
+
/** Port number for HTTP-based transports. Default: 8000 */
|
|
69
|
+
port?: number;
|
|
70
|
+
/** Callback invoked before the server starts. */
|
|
71
|
+
onStartup?: () => void | Promise<void>;
|
|
72
|
+
/** Callback invoked after the server stops. */
|
|
73
|
+
onShutdown?: () => void | Promise<void>;
|
|
74
|
+
/** Enable the browser-based Tool Explorer UI (HTTP only). Default: false */
|
|
75
|
+
explorer?: boolean;
|
|
76
|
+
/** URL prefix for the explorer. Default: "/explorer" */
|
|
77
|
+
explorerPrefix?: string;
|
|
78
|
+
/** Allow tool execution from the explorer UI. Default: false */
|
|
79
|
+
allowExecute?: boolean;
|
|
80
|
+
/** Title for the explorer UI page. */
|
|
81
|
+
explorerTitle?: string;
|
|
82
|
+
/** Project name shown in the explorer UI footer. */
|
|
83
|
+
explorerProjectName?: string;
|
|
84
|
+
/** Project URL shown in the explorer UI footer. */
|
|
85
|
+
explorerProjectUrl?: string;
|
|
86
|
+
}
|
|
87
|
+
/** Options for APCoreMCP.asyncServe() (embed subset). */
|
|
88
|
+
export interface APCoreMCPAsyncServeOptions {
|
|
89
|
+
/** Enable the browser-based Tool Explorer UI. Default: false */
|
|
90
|
+
explorer?: boolean;
|
|
91
|
+
/** URL prefix for the explorer. Default: "/explorer" */
|
|
92
|
+
explorerPrefix?: string;
|
|
93
|
+
/** Allow tool execution from the explorer UI. Default: false */
|
|
94
|
+
allowExecute?: boolean;
|
|
95
|
+
/** MCP endpoint path. Default: "/mcp" */
|
|
96
|
+
endpoint?: string;
|
|
97
|
+
}
|
|
98
|
+
export declare class APCoreMCP {
|
|
99
|
+
private _backend;
|
|
100
|
+
private readonly _options;
|
|
101
|
+
private _registry;
|
|
102
|
+
private _executor;
|
|
103
|
+
private readonly _extensionsDir;
|
|
104
|
+
/**
|
|
105
|
+
* Create an APCoreMCP instance.
|
|
106
|
+
*
|
|
107
|
+
* @param extensionsDirOrBackend - Path to an apcore extensions directory,
|
|
108
|
+
* or an existing Registry or Executor instance.
|
|
109
|
+
* @param options - Configuration options.
|
|
110
|
+
*/
|
|
111
|
+
constructor(extensionsDirOrBackend: string | RegistryOrExecutor, options?: APCoreMCPOptions);
|
|
112
|
+
/** The underlying apcore Registry. */
|
|
113
|
+
get registry(): Registry;
|
|
114
|
+
/** The underlying apcore Executor (resolved lazily). */
|
|
115
|
+
get executor(): Executor | undefined;
|
|
116
|
+
/** List all discovered module IDs that will be exposed as tools. */
|
|
117
|
+
get tools(): string[];
|
|
118
|
+
/**
|
|
119
|
+
* Build the full ServeOptions by merging constructor options with per-call overrides.
|
|
120
|
+
*/
|
|
121
|
+
private _buildServeOptions;
|
|
122
|
+
/**
|
|
123
|
+
* Resolve the backend (handles extensions dir lazy init).
|
|
124
|
+
*/
|
|
125
|
+
private _resolveBackend;
|
|
126
|
+
/**
|
|
127
|
+
* Launch the MCP server (blocks until shutdown).
|
|
128
|
+
*
|
|
129
|
+
* @param options - Transport and lifecycle options.
|
|
130
|
+
*/
|
|
131
|
+
serve(options?: APCoreMCPServeOptions): Promise<void>;
|
|
132
|
+
/**
|
|
133
|
+
* Build an embeddable MCP HTTP request handler.
|
|
134
|
+
*
|
|
135
|
+
* Unlike `serve()`, this does NOT create its own HTTP server. Returns a
|
|
136
|
+
* Node.js HTTP request handler and a close function.
|
|
137
|
+
*
|
|
138
|
+
* @param options - Embed options.
|
|
139
|
+
* @returns Object with `handler` and `close()`.
|
|
140
|
+
*/
|
|
141
|
+
asyncServe(options?: APCoreMCPAsyncServeOptions): Promise<AsyncServeApp>;
|
|
142
|
+
/**
|
|
143
|
+
* Export modules as OpenAI-compatible tool definitions.
|
|
144
|
+
*
|
|
145
|
+
* @param options - Conversion options (embedAnnotations, strict).
|
|
146
|
+
* @returns List of OpenAI tool definition dicts.
|
|
147
|
+
*/
|
|
148
|
+
toOpenaiTools(options?: ToOpenaiToolsOptions): OpenAIToolDef[];
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=apcore-mcp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apcore-mcp.d.ts","sourceRoot":"","sources":["../src/apcore-mcp.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* APCoreMCP: Unified entry point for apcore-mcp.
|
|
3
|
+
*
|
|
4
|
+
* Wraps Registry discovery, MCP server creation, and OpenAI tool export
|
|
5
|
+
* into a single object with a simple API.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* // Minimal — just point to extensions
|
|
10
|
+
* const mcp = new APCoreMCP("./extensions");
|
|
11
|
+
* await mcp.serve();
|
|
12
|
+
*
|
|
13
|
+
* // With options
|
|
14
|
+
* const mcp = new APCoreMCP("./extensions", { name: "my-server", tags: ["public"] });
|
|
15
|
+
* await mcp.serve({ transport: "streamable-http", port: 9000, explorer: true });
|
|
16
|
+
*
|
|
17
|
+
* // Export OpenAI tools
|
|
18
|
+
* const tools = mcp.toOpenaiTools();
|
|
19
|
+
*
|
|
20
|
+
* // Embed into existing HTTP server
|
|
21
|
+
* const app = await mcp.asyncServe({ explorer: true });
|
|
22
|
+
* // app.handler is a Node.js request handler; call app.close() on shutdown
|
|
23
|
+
*
|
|
24
|
+
* // Use existing Registry or Executor
|
|
25
|
+
* const mcp = new APCoreMCP(registry);
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
import { serve, asyncServe, toOpenaiTools, resolveRegistry, } from "./index.js";
|
|
29
|
+
export class APCoreMCP {
|
|
30
|
+
_backend;
|
|
31
|
+
_options;
|
|
32
|
+
_registry;
|
|
33
|
+
_executor;
|
|
34
|
+
_extensionsDir;
|
|
35
|
+
/**
|
|
36
|
+
* Create an APCoreMCP instance.
|
|
37
|
+
*
|
|
38
|
+
* @param extensionsDirOrBackend - Path to an apcore extensions directory,
|
|
39
|
+
* or an existing Registry or Executor instance.
|
|
40
|
+
* @param options - Configuration options.
|
|
41
|
+
*/
|
|
42
|
+
constructor(extensionsDirOrBackend, options = {}) {
|
|
43
|
+
// Validate upfront
|
|
44
|
+
const name = options.name ?? "apcore-mcp";
|
|
45
|
+
if (!name || name.length === 0) {
|
|
46
|
+
throw new Error("name must not be empty");
|
|
47
|
+
}
|
|
48
|
+
if (name.length > 255) {
|
|
49
|
+
throw new Error("name must not exceed 255 characters");
|
|
50
|
+
}
|
|
51
|
+
if (options.tags) {
|
|
52
|
+
for (const tag of options.tags) {
|
|
53
|
+
if (!tag || tag.length === 0) {
|
|
54
|
+
throw new Error("tags must not contain empty strings");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (options.prefix !== undefined && options.prefix !== null && options.prefix.length === 0) {
|
|
59
|
+
throw new Error("prefix must not be empty if provided");
|
|
60
|
+
}
|
|
61
|
+
this._options = { name, ...options };
|
|
62
|
+
if (typeof extensionsDirOrBackend === "string") {
|
|
63
|
+
// Defer discovery to first use — will be resolved lazily
|
|
64
|
+
this._backend = null;
|
|
65
|
+
this._extensionsDir = extensionsDirOrBackend;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
this._backend = extensionsDirOrBackend;
|
|
69
|
+
this._extensionsDir = undefined;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/** The underlying apcore Registry. */
|
|
73
|
+
get registry() {
|
|
74
|
+
if (!this._registry) {
|
|
75
|
+
if (this._backend !== null) {
|
|
76
|
+
this._registry = resolveRegistry(this._backend);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
throw new Error("Registry not yet resolved. Call serve() or asyncServe() first, " +
|
|
80
|
+
"or pass a Registry/Executor to the constructor.");
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return this._registry;
|
|
84
|
+
}
|
|
85
|
+
/** The underlying apcore Executor (resolved lazily). */
|
|
86
|
+
get executor() {
|
|
87
|
+
return this._executor;
|
|
88
|
+
}
|
|
89
|
+
/** List all discovered module IDs that will be exposed as tools. */
|
|
90
|
+
get tools() {
|
|
91
|
+
const reg = this.registry;
|
|
92
|
+
const result = reg.list({
|
|
93
|
+
tags: this._options.tags ?? undefined,
|
|
94
|
+
prefix: this._options.prefix ?? undefined,
|
|
95
|
+
});
|
|
96
|
+
// registry.list() may return ModuleDescriptor[] or string[] depending on apcore-js version
|
|
97
|
+
if (result.length === 0)
|
|
98
|
+
return [];
|
|
99
|
+
if (typeof result[0] === "string")
|
|
100
|
+
return result;
|
|
101
|
+
return result.map((d) => d.moduleId);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Build the full ServeOptions by merging constructor options with per-call overrides.
|
|
105
|
+
*/
|
|
106
|
+
_buildServeOptions(overrides = {}) {
|
|
107
|
+
return {
|
|
108
|
+
transport: overrides.transport,
|
|
109
|
+
host: overrides.host,
|
|
110
|
+
port: overrides.port,
|
|
111
|
+
name: this._options.name,
|
|
112
|
+
version: this._options.version,
|
|
113
|
+
validateInputs: this._options.validateInputs,
|
|
114
|
+
tags: this._options.tags,
|
|
115
|
+
prefix: this._options.prefix,
|
|
116
|
+
logLevel: this._options.logLevel,
|
|
117
|
+
onStartup: overrides.onStartup,
|
|
118
|
+
onShutdown: overrides.onShutdown,
|
|
119
|
+
metricsCollector: this._options.metricsCollector,
|
|
120
|
+
explorer: overrides.explorer,
|
|
121
|
+
explorerPrefix: overrides.explorerPrefix,
|
|
122
|
+
allowExecute: overrides.allowExecute,
|
|
123
|
+
explorerTitle: overrides.explorerTitle,
|
|
124
|
+
explorerProjectName: overrides.explorerProjectName,
|
|
125
|
+
explorerProjectUrl: overrides.explorerProjectUrl,
|
|
126
|
+
authenticator: this._options.authenticator,
|
|
127
|
+
requireAuth: this._options.requireAuth,
|
|
128
|
+
exemptPaths: this._options.exemptPaths,
|
|
129
|
+
approvalHandler: this._options.approvalHandler,
|
|
130
|
+
outputFormatter: this._options.outputFormatter,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Resolve the backend (handles extensions dir lazy init).
|
|
135
|
+
*/
|
|
136
|
+
async _resolveBackend() {
|
|
137
|
+
if (this._backend !== null)
|
|
138
|
+
return this._backend;
|
|
139
|
+
if (!this._extensionsDir) {
|
|
140
|
+
throw new Error("No backend configured");
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
144
|
+
const apcore = await import("apcore-js");
|
|
145
|
+
const RegistryClass = apcore.Registry ?? apcore.default?.Registry;
|
|
146
|
+
if (!RegistryClass) {
|
|
147
|
+
throw new Error("Cannot find Registry class in apcore-js");
|
|
148
|
+
}
|
|
149
|
+
const registry = new RegistryClass({ extensionsDir: this._extensionsDir });
|
|
150
|
+
if (typeof registry.discover === "function") {
|
|
151
|
+
await registry.discover();
|
|
152
|
+
}
|
|
153
|
+
this._registry = registry;
|
|
154
|
+
this._backend = registry;
|
|
155
|
+
return registry;
|
|
156
|
+
}
|
|
157
|
+
catch (err) {
|
|
158
|
+
throw new Error(`Failed to create Registry from extensions dir "${this._extensionsDir}". ` +
|
|
159
|
+
`Ensure apcore-js is installed. Original error: ${err}`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Launch the MCP server (blocks until shutdown).
|
|
164
|
+
*
|
|
165
|
+
* @param options - Transport and lifecycle options.
|
|
166
|
+
*/
|
|
167
|
+
async serve(options = {}) {
|
|
168
|
+
const backend = await this._resolveBackend();
|
|
169
|
+
await serve(backend, this._buildServeOptions(options));
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Build an embeddable MCP HTTP request handler.
|
|
173
|
+
*
|
|
174
|
+
* Unlike `serve()`, this does NOT create its own HTTP server. Returns a
|
|
175
|
+
* Node.js HTTP request handler and a close function.
|
|
176
|
+
*
|
|
177
|
+
* @param options - Embed options.
|
|
178
|
+
* @returns Object with `handler` and `close()`.
|
|
179
|
+
*/
|
|
180
|
+
async asyncServe(options = {}) {
|
|
181
|
+
const backend = await this._resolveBackend();
|
|
182
|
+
const asyncOpts = {
|
|
183
|
+
name: this._options.name,
|
|
184
|
+
version: this._options.version,
|
|
185
|
+
validateInputs: this._options.validateInputs,
|
|
186
|
+
tags: this._options.tags,
|
|
187
|
+
prefix: this._options.prefix,
|
|
188
|
+
logLevel: this._options.logLevel,
|
|
189
|
+
metricsCollector: this._options.metricsCollector,
|
|
190
|
+
explorer: options.explorer,
|
|
191
|
+
explorerPrefix: options.explorerPrefix,
|
|
192
|
+
allowExecute: options.allowExecute,
|
|
193
|
+
authenticator: this._options.authenticator,
|
|
194
|
+
requireAuth: this._options.requireAuth,
|
|
195
|
+
exemptPaths: this._options.exemptPaths,
|
|
196
|
+
approvalHandler: this._options.approvalHandler,
|
|
197
|
+
endpoint: options.endpoint,
|
|
198
|
+
outputFormatter: this._options.outputFormatter,
|
|
199
|
+
};
|
|
200
|
+
return asyncServe(backend, asyncOpts);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Export modules as OpenAI-compatible tool definitions.
|
|
204
|
+
*
|
|
205
|
+
* @param options - Conversion options (embedAnnotations, strict).
|
|
206
|
+
* @returns List of OpenAI tool definition dicts.
|
|
207
|
+
*/
|
|
208
|
+
toOpenaiTools(options = {}) {
|
|
209
|
+
const reg = this.registry;
|
|
210
|
+
return toOpenaiTools(reg, {
|
|
211
|
+
...options,
|
|
212
|
+
tags: this._options.tags ?? undefined,
|
|
213
|
+
prefix: this._options.prefix ?? undefined,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=apcore-mcp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apcore-mcp.js","sourceRoot":"","sources":["../src/apcore-mcp.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth hook builder for mcp-embedded-ui explorer integration.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the Python `_build_auth_hook` pattern from apcore-mcp-python.
|
|
5
|
+
* Bridges the Authenticator interface to mcp-embedded-ui's AuthHook,
|
|
6
|
+
* propagating identity through AsyncLocalStorage for the call chain.
|
|
7
|
+
*/
|
|
8
|
+
import type { Authenticator } from "./types.js";
|
|
9
|
+
/**
|
|
10
|
+
* Minimal incoming request shape accepted by the auth hook.
|
|
11
|
+
* Compatible with mcp-embedded-ui's IncomingRequest.
|
|
12
|
+
*/
|
|
13
|
+
interface IncomingRequest {
|
|
14
|
+
headers: Record<string, string | string[] | undefined>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Build an auth hook for mcp-embedded-ui that bridges to an Authenticator.
|
|
18
|
+
*
|
|
19
|
+
* The hook:
|
|
20
|
+
* 1. Extracts headers from the incoming request
|
|
21
|
+
* 2. Delegates to `authenticator.authenticate()` for token validation
|
|
22
|
+
* 3. Throws on auth failure (mcp-embedded-ui catches this and returns 401)
|
|
23
|
+
* 4. Wraps `next()` in `identityStorage.run()` so `getCurrentIdentity()` works
|
|
24
|
+
*
|
|
25
|
+
* @param authenticator - An Authenticator instance (e.g. JWTAuthenticator)
|
|
26
|
+
* @returns An auth hook function compatible with mcp-embedded-ui's AuthHook type
|
|
27
|
+
*/
|
|
28
|
+
export declare function buildExplorerAuthHook(authenticator: Authenticator): (req: IncomingRequest, next: () => Promise<Response>) => Promise<Response>;
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/auth/hooks.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGhD;;;GAGG;AACH,UAAU,eAAe;IACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;CACxD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,aAAa,GAC3B,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,CAS5E"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth hook builder for mcp-embedded-ui explorer integration.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the Python `_build_auth_hook` pattern from apcore-mcp-python.
|
|
5
|
+
* Bridges the Authenticator interface to mcp-embedded-ui's AuthHook,
|
|
6
|
+
* propagating identity through AsyncLocalStorage for the call chain.
|
|
7
|
+
*/
|
|
8
|
+
import { identityStorage } from "./storage.js";
|
|
9
|
+
/**
|
|
10
|
+
* Build an auth hook for mcp-embedded-ui that bridges to an Authenticator.
|
|
11
|
+
*
|
|
12
|
+
* The hook:
|
|
13
|
+
* 1. Extracts headers from the incoming request
|
|
14
|
+
* 2. Delegates to `authenticator.authenticate()` for token validation
|
|
15
|
+
* 3. Throws on auth failure (mcp-embedded-ui catches this and returns 401)
|
|
16
|
+
* 4. Wraps `next()` in `identityStorage.run()` so `getCurrentIdentity()` works
|
|
17
|
+
*
|
|
18
|
+
* @param authenticator - An Authenticator instance (e.g. JWTAuthenticator)
|
|
19
|
+
* @returns An auth hook function compatible with mcp-embedded-ui's AuthHook type
|
|
20
|
+
*/
|
|
21
|
+
export function buildExplorerAuthHook(authenticator) {
|
|
22
|
+
return async (req, next) => {
|
|
23
|
+
const shimReq = { headers: req.headers };
|
|
24
|
+
const identity = await authenticator.authenticate(shimReq);
|
|
25
|
+
if (!identity) {
|
|
26
|
+
throw new Error("Unauthorized");
|
|
27
|
+
}
|
|
28
|
+
return identityStorage.run(identity, next);
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/auth/hooks.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAU/C;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,qBAAqB,CACnC,aAA4B;IAE5B,OAAO,KAAK,EAAE,GAAoB,EAAE,IAA6B,EAAE,EAAE;QACnE,MAAM,OAAO,GAAG,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAgC,CAAC;QACvE,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QAC3D,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC;QAClC,CAAC;QACD,OAAO,eAAe,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC7C,CAAC,CAAC;AACJ,CAAC"}
|