apcore-mcp 0.1.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.
Files changed (62) hide show
  1. package/README.md +183 -0
  2. package/dist/adapters/annotations.d.ts +37 -0
  3. package/dist/adapters/annotations.d.ts.map +1 -0
  4. package/dist/adapters/annotations.js +70 -0
  5. package/dist/adapters/annotations.js.map +1 -0
  6. package/dist/adapters/errors.d.ts +31 -0
  7. package/dist/adapters/errors.d.ts.map +1 -0
  8. package/dist/adapters/errors.js +113 -0
  9. package/dist/adapters/errors.js.map +1 -0
  10. package/dist/adapters/idNormalizer.d.ts +21 -0
  11. package/dist/adapters/idNormalizer.d.ts.map +1 -0
  12. package/dist/adapters/idNormalizer.js +25 -0
  13. package/dist/adapters/idNormalizer.js.map +1 -0
  14. package/dist/adapters/index.d.ts +8 -0
  15. package/dist/adapters/index.d.ts.map +1 -0
  16. package/dist/adapters/index.js +8 -0
  17. package/dist/adapters/index.js.map +1 -0
  18. package/dist/adapters/schema.d.ts +43 -0
  19. package/dist/adapters/schema.d.ts.map +1 -0
  20. package/dist/adapters/schema.js +106 -0
  21. package/dist/adapters/schema.js.map +1 -0
  22. package/dist/cli.d.ts +11 -0
  23. package/dist/cli.d.ts.map +1 -0
  24. package/dist/cli.js +131 -0
  25. package/dist/cli.js.map +1 -0
  26. package/dist/converters/index.d.ts +6 -0
  27. package/dist/converters/index.d.ts.map +1 -0
  28. package/dist/converters/index.js +5 -0
  29. package/dist/converters/index.js.map +1 -0
  30. package/dist/converters/openai.d.ts +93 -0
  31. package/dist/converters/openai.d.ts.map +1 -0
  32. package/dist/converters/openai.js +174 -0
  33. package/dist/converters/openai.js.map +1 -0
  34. package/dist/index.d.ts +44 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +82 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/server/factory.d.ts +56 -0
  39. package/dist/server/factory.d.ts.map +1 -0
  40. package/dist/server/factory.js +110 -0
  41. package/dist/server/factory.js.map +1 -0
  42. package/dist/server/index.d.ts +11 -0
  43. package/dist/server/index.d.ts.map +1 -0
  44. package/dist/server/index.js +8 -0
  45. package/dist/server/index.js.map +1 -0
  46. package/dist/server/listener.d.ts +59 -0
  47. package/dist/server/listener.d.ts.map +1 -0
  48. package/dist/server/listener.js +99 -0
  49. package/dist/server/listener.js.map +1 -0
  50. package/dist/server/router.d.ts +28 -0
  51. package/dist/server/router.d.ts.map +1 -0
  52. package/dist/server/router.js +50 -0
  53. package/dist/server/router.js.map +1 -0
  54. package/dist/server/transport.d.ts +63 -0
  55. package/dist/server/transport.d.ts.map +1 -0
  56. package/dist/server/transport.js +181 -0
  57. package/dist/server/transport.js.map +1 -0
  58. package/dist/types.d.ts +85 -0
  59. package/dist/types.d.ts.map +1 -0
  60. package/dist/types.js +9 -0
  61. package/dist/types.js.map +1 -0
  62. package/package.json +59 -0
package/README.md ADDED
@@ -0,0 +1,183 @@
1
+ <div align="center">
2
+ <img src="https://raw.githubusercontent.com/aipartnerup/apcore-mcp/main/apcore-mcp-logo.svg" alt="apcore-mcp logo" width="200"/>
3
+ </div>
4
+
5
+ # apcore-mcp
6
+
7
+ Automatic MCP Server & OpenAI Tools Bridge for [apcore](https://github.com/aipartnerup/apcore).
8
+
9
+ Converts apcore module registries into [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) tool definitions and [OpenAI-compatible function calling](https://platform.openai.com/docs/guides/function-calling) formats — zero boilerplate required.
10
+
11
+ ## Features
12
+
13
+ - **MCP Server** — Expose apcore modules as MCP tools over stdio, Streamable HTTP, or SSE
14
+ - **OpenAI Tools** — Convert modules to OpenAI function calling format with strict mode support
15
+ - **Schema Conversion** — Inline `$defs`/`$ref` from Pydantic-generated JSON Schema
16
+ - **Annotation Mapping** — Map module annotations to MCP hints and OpenAI description suffixes
17
+ - **Error Mapping** — Sanitize internal errors for safe client-facing responses
18
+ - **Dynamic Registration** — Listen for registry changes and update tools at runtime
19
+ - **CLI** — Launch an MCP server from the command line
20
+
21
+ ## Requirements
22
+
23
+ - Node.js >= 18.0.0
24
+ - apcore (peer dependency)
25
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ npm install apcore-mcp
30
+ ```
31
+
32
+ ## Quick Start
33
+
34
+ ### Programmatic API
35
+
36
+ ```typescript
37
+ import { serve, toOpenaiTools } from "apcore-mcp";
38
+
39
+ // Launch MCP server over stdio
40
+ await serve(executor);
41
+
42
+ // Launch over Streamable HTTP
43
+ await serve(executor, {
44
+ transport: "streamable-http",
45
+ host: "127.0.0.1",
46
+ port: 8000,
47
+ });
48
+
49
+ // Export OpenAI tool definitions
50
+ const tools = toOpenaiTools(registry, {
51
+ embedAnnotations: true,
52
+ strict: true,
53
+ });
54
+ ```
55
+
56
+ ### CLI
57
+
58
+ ```bash
59
+ # stdio (default)
60
+ npx apcore-mcp --extensions-dir ./extensions
61
+
62
+ # Streamable HTTP
63
+ npx apcore-mcp --extensions-dir ./extensions --transport streamable-http --port 8000
64
+
65
+ # SSE
66
+ npx apcore-mcp --extensions-dir ./extensions --transport sse --port 8000
67
+ ```
68
+
69
+ #### CLI Arguments
70
+
71
+ | Argument | Default | Description |
72
+ |---|---|---|
73
+ | `--extensions-dir` | *(required)* | Path to apcore extensions directory |
74
+ | `--transport` | `stdio` | `stdio`, `streamable-http`, or `sse` |
75
+ | `--host` | `127.0.0.1` | Host for HTTP transports |
76
+ | `--port` | `8000` | Port for HTTP transports (1-65535) |
77
+ | `--name` | `apcore-mcp` | MCP server name |
78
+ | `--version` | package version | MCP server version |
79
+ | `--log-level` | `INFO` | `DEBUG`, `INFO`, `WARNING`, `ERROR` |
80
+
81
+ ## API Reference
82
+
83
+ ### `serve(registryOrExecutor, options?)`
84
+
85
+ Launch an MCP Server that exposes all apcore modules as tools.
86
+
87
+ ```typescript
88
+ function serve(
89
+ registryOrExecutor: Registry | Executor,
90
+ options?: {
91
+ transport?: "stdio" | "streamable-http" | "sse";
92
+ host?: string;
93
+ port?: number;
94
+ name?: string;
95
+ version?: string;
96
+ }
97
+ ): Promise<void>;
98
+ ```
99
+
100
+ ### `toOpenaiTools(registryOrExecutor, options?)`
101
+
102
+ Export apcore modules as OpenAI-compatible tool definitions.
103
+
104
+ ```typescript
105
+ function toOpenaiTools(
106
+ registryOrExecutor: Registry | Executor,
107
+ options?: {
108
+ embedAnnotations?: boolean;
109
+ strict?: boolean;
110
+ tags?: string[];
111
+ prefix?: string;
112
+ }
113
+ ): OpenAIToolDef[];
114
+ ```
115
+
116
+ **Options:**
117
+
118
+ - `embedAnnotations` — Append annotation metadata to tool descriptions (default: `false`)
119
+ - `strict` — Enable OpenAI strict mode: adds `additionalProperties: false`, makes all properties required, wraps optional properties with nullable (default: `false`)
120
+ - `tags` — Filter modules by tags
121
+ - `prefix` — Filter modules by ID prefix
122
+
123
+ ## Architecture
124
+
125
+ ```
126
+ src/
127
+ ├── index.ts # Public API: serve(), toOpenaiTools()
128
+ ├── cli.ts # CLI entry point
129
+ ├── types.ts # TypeScript interfaces
130
+ ├── adapters/
131
+ │ ├── schema.ts # JSON Schema $ref inlining
132
+ │ ├── annotations.ts # Module annotations -> MCP hints
133
+ │ ├── errors.ts # Error sanitization
134
+ │ └── idNormalizer.ts # Dot-notation <-> dash-notation
135
+ ├── converters/
136
+ │ └── openai.ts # OpenAI tool definition converter
137
+ └── server/
138
+ ├── factory.ts # MCP Server creation & handler registration
139
+ ├── router.ts # Tool call execution routing
140
+ ├── transport.ts # Transport lifecycle (stdio/HTTP/SSE)
141
+ └── listener.ts # Dynamic registry event listener
142
+ ```
143
+
144
+ ## Development
145
+
146
+ ```bash
147
+ # Install dependencies
148
+ npm install
149
+
150
+ # Type check
151
+ npm run typecheck
152
+
153
+ # Run tests
154
+ npm test
155
+
156
+ # Run tests with coverage
157
+ npm run test:coverage
158
+
159
+ # Build
160
+ npm run build
161
+
162
+ # Watch mode
163
+ npm run dev
164
+ ```
165
+
166
+ ## Testing
167
+
168
+ 100 tests across 10 test suites with 96%+ line coverage:
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% |
180
+
181
+ ## License
182
+
183
+ Apache-2.0
@@ -0,0 +1,37 @@
1
+ /**
2
+ * AnnotationMapper - Maps apcore module annotations to MCP tool annotations.
3
+ *
4
+ * Converts between apcore's annotation format and the MCP protocol's
5
+ * hint-based annotation system. Also provides description suffix generation
6
+ * and approval requirement checking.
7
+ */
8
+ import type { ModuleAnnotations, McpAnnotationsDict } from "../types.js";
9
+ export declare class AnnotationMapper {
10
+ /**
11
+ * Convert apcore module annotations to MCP annotations dict.
12
+ *
13
+ * Returns default values when annotations are null:
14
+ * - read_only_hint: false
15
+ * - destructive_hint: false
16
+ * - idempotent_hint: false
17
+ * - open_world_hint: true
18
+ * - title: null
19
+ */
20
+ toMcpAnnotations(annotations: ModuleAnnotations | null): McpAnnotationsDict;
21
+ /**
22
+ * Generate a description suffix string from annotations.
23
+ *
24
+ * Returns a formatted string like:
25
+ * `\n\n[Annotations: readonly=true, destructive=false, ...]`
26
+ *
27
+ * Returns an empty string if annotations are null.
28
+ */
29
+ toDescriptionSuffix(annotations: ModuleAnnotations | null): string;
30
+ /**
31
+ * Check whether the annotations indicate the module requires approval.
32
+ *
33
+ * Returns false if annotations are null.
34
+ */
35
+ hasRequiresApproval(annotations: ModuleAnnotations | null): boolean;
36
+ }
37
+ //# sourceMappingURL=annotations.d.ts.map
@@ -0,0 +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;;;;;;;OAOG;IACH,mBAAmB,CAAC,WAAW,EAAE,iBAAiB,GAAG,IAAI,GAAG,MAAM;IAgBlE;;;;OAIG;IACH,mBAAmB,CAAC,WAAW,EAAE,iBAAiB,GAAG,IAAI,GAAG,OAAO;CAOpE"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * AnnotationMapper - Maps apcore module annotations to MCP tool annotations.
3
+ *
4
+ * Converts between apcore's annotation format and the MCP protocol's
5
+ * hint-based annotation system. Also provides description suffix generation
6
+ * and approval requirement checking.
7
+ */
8
+ export class AnnotationMapper {
9
+ /**
10
+ * Convert apcore module annotations to MCP annotations dict.
11
+ *
12
+ * Returns default values when annotations are null:
13
+ * - read_only_hint: false
14
+ * - destructive_hint: false
15
+ * - idempotent_hint: false
16
+ * - open_world_hint: true
17
+ * - title: null
18
+ */
19
+ toMcpAnnotations(annotations) {
20
+ if (annotations === null) {
21
+ return {
22
+ read_only_hint: false,
23
+ destructive_hint: false,
24
+ idempotent_hint: false,
25
+ open_world_hint: true,
26
+ title: null,
27
+ };
28
+ }
29
+ return {
30
+ read_only_hint: annotations.readonly,
31
+ destructive_hint: annotations.destructive,
32
+ idempotent_hint: annotations.idempotent,
33
+ open_world_hint: annotations.open_world,
34
+ title: null,
35
+ };
36
+ }
37
+ /**
38
+ * Generate a description suffix string from annotations.
39
+ *
40
+ * Returns a formatted string like:
41
+ * `\n\n[Annotations: readonly=true, destructive=false, ...]`
42
+ *
43
+ * Returns an empty string if annotations are null.
44
+ */
45
+ toDescriptionSuffix(annotations) {
46
+ if (annotations === null) {
47
+ return "";
48
+ }
49
+ const parts = [
50
+ `readonly=${annotations.readonly}`,
51
+ `destructive=${annotations.destructive}`,
52
+ `idempotent=${annotations.idempotent}`,
53
+ `requires_approval=${annotations.requires_approval}`,
54
+ `open_world=${annotations.open_world}`,
55
+ ];
56
+ return `\n\n[Annotations: ${parts.join(", ")}]`;
57
+ }
58
+ /**
59
+ * Check whether the annotations indicate the module requires approval.
60
+ *
61
+ * Returns false if annotations are null.
62
+ */
63
+ hasRequiresApproval(annotations) {
64
+ if (annotations === null) {
65
+ return false;
66
+ }
67
+ return annotations.requires_approval;
68
+ }
69
+ }
70
+ //# sourceMappingURL=annotations.js.map
@@ -0,0 +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,cAAc,EAAE,KAAK;gBACrB,gBAAgB,EAAE,KAAK;gBACvB,eAAe,EAAE,KAAK;gBACtB,eAAe,EAAE,IAAI;gBACrB,KAAK,EAAE,IAAI;aACZ,CAAC;QACJ,CAAC;QAED,OAAO;YACL,cAAc,EAAE,WAAW,CAAC,QAAQ;YACpC,gBAAgB,EAAE,WAAW,CAAC,WAAW;YACzC,eAAe,EAAE,WAAW,CAAC,UAAU;YACvC,eAAe,EAAE,WAAW,CAAC,UAAU;YACvC,KAAK,EAAE,IAAI;SACZ,CAAC;IACJ,CAAC;IAED;;;;;;;OAOG;IACH,mBAAmB,CAAC,WAAqC;QACvD,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;YACzB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,KAAK,GAAa;YACtB,YAAY,WAAW,CAAC,QAAQ,EAAE;YAClC,eAAe,WAAW,CAAC,WAAW,EAAE;YACxC,cAAc,WAAW,CAAC,UAAU,EAAE;YACtC,qBAAqB,WAAW,CAAC,iBAAiB,EAAE;YACpD,cAAc,WAAW,CAAC,UAAU,EAAE;SACvC,CAAC;QAEF,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,iBAAiB,CAAC;IACvC,CAAC;CACF"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * ErrorMapper - Maps apcore errors to MCP-compatible error responses.
3
+ *
4
+ * Handles ModuleError instances with specific error codes, sanitizes
5
+ * internal error details, and formats schema validation errors with
6
+ * field-level detail.
7
+ */
8
+ import type { McpErrorResponse } from "../types.js";
9
+ export declare class ErrorMapper {
10
+ /**
11
+ * Convert an error to an MCP error response.
12
+ *
13
+ * Duck-types the error to check for ModuleError properties (code, message, details).
14
+ * Applies sanitization and formatting rules based on the error code.
15
+ */
16
+ toMcpError(error: unknown): McpErrorResponse;
17
+ /**
18
+ * Duck-type check for ModuleError-like objects.
19
+ *
20
+ * Checks for `code` (string), `message` (string), and `details` properties.
21
+ */
22
+ private _isModuleError;
23
+ /**
24
+ * Format a schema validation error message with field-level details.
25
+ *
26
+ * Extracts the `errors` array from details and formats each entry
27
+ * as "field: message" lines appended to the base message.
28
+ */
29
+ private _formatValidationError;
30
+ }
31
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/adapters/errors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AASpD,qBAAa,WAAW;IACtB;;;;;OAKG;IACH,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB;IAuD5C;;;;OAIG;IACH,OAAO,CAAC,cAAc;IAetB;;;;;OAKG;IACH,OAAO,CAAC,sBAAsB;CA4B/B"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * ErrorMapper - Maps apcore errors to MCP-compatible error responses.
3
+ *
4
+ * Handles ModuleError instances with specific error codes, sanitizes
5
+ * internal error details, and formats schema validation errors with
6
+ * field-level detail.
7
+ */
8
+ /** Internal error codes that should be sanitized to a generic message. */
9
+ const INTERNAL_ERROR_CODES = new Set([
10
+ "CALL_DEPTH_EXCEEDED",
11
+ "CIRCULAR_CALL",
12
+ "CALL_FREQUENCY_EXCEEDED",
13
+ ]);
14
+ export class ErrorMapper {
15
+ /**
16
+ * Convert an error to an MCP error response.
17
+ *
18
+ * Duck-types the error to check for ModuleError properties (code, message, details).
19
+ * Applies sanitization and formatting rules based on the error code.
20
+ */
21
+ toMcpError(error) {
22
+ // Duck-type check for ModuleError-like objects
23
+ if (this._isModuleError(error)) {
24
+ const code = error.code;
25
+ const details = error.details;
26
+ // Internal error codes -> generic message
27
+ if (INTERNAL_ERROR_CODES.has(code)) {
28
+ return {
29
+ is_error: true,
30
+ error_type: code,
31
+ message: "Internal error occurred",
32
+ details: null,
33
+ };
34
+ }
35
+ // ACL denied -> sanitized access denied
36
+ if (code === "ACL_DENIED") {
37
+ return {
38
+ is_error: true,
39
+ error_type: "ACL_DENIED",
40
+ message: "Access denied",
41
+ details: null,
42
+ };
43
+ }
44
+ // Schema validation error -> formatted with field-level details
45
+ if (code === "SCHEMA_VALIDATION_ERROR") {
46
+ const message = this._formatValidationError(details);
47
+ return {
48
+ is_error: true,
49
+ error_type: "SCHEMA_VALIDATION_ERROR",
50
+ message,
51
+ details,
52
+ };
53
+ }
54
+ // Other known ModuleError codes -> pass through
55
+ return {
56
+ is_error: true,
57
+ error_type: code,
58
+ message: error.message,
59
+ details,
60
+ };
61
+ }
62
+ // Unknown/unexpected exceptions -> generic error
63
+ return {
64
+ is_error: true,
65
+ error_type: "INTERNAL_ERROR",
66
+ message: "Internal error occurred",
67
+ details: null,
68
+ };
69
+ }
70
+ /**
71
+ * Duck-type check for ModuleError-like objects.
72
+ *
73
+ * Checks for `code` (string), `message` (string), and `details` properties.
74
+ */
75
+ _isModuleError(error) {
76
+ if (error === null || typeof error !== "object") {
77
+ return false;
78
+ }
79
+ const obj = error;
80
+ return (typeof obj["code"] === "string" &&
81
+ typeof obj["message"] === "string" &&
82
+ "details" in obj);
83
+ }
84
+ /**
85
+ * Format a schema validation error message with field-level details.
86
+ *
87
+ * Extracts the `errors` array from details and formats each entry
88
+ * as "field: message" lines appended to the base message.
89
+ */
90
+ _formatValidationError(details) {
91
+ const baseMessage = "Schema validation failed";
92
+ if (details === null) {
93
+ return baseMessage;
94
+ }
95
+ const errors = details["errors"];
96
+ if (!Array.isArray(errors) || errors.length === 0) {
97
+ return baseMessage;
98
+ }
99
+ const fieldErrors = errors
100
+ .map((err) => {
101
+ if (err !== null && typeof err === "object") {
102
+ const entry = err;
103
+ const field = entry["field"] ?? "unknown";
104
+ const message = entry["message"] ?? "validation error";
105
+ return ` ${String(field)}: ${String(message)}`;
106
+ }
107
+ return ` ${String(err)}`;
108
+ })
109
+ .join("\n");
110
+ return `${baseMessage}:\n${fieldErrors}`;
111
+ }
112
+ }
113
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/adapters/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * ModuleIDNormalizer - Converts between apcore module IDs and MCP tool names.
3
+ *
4
+ * apcore uses dot-separated module IDs (e.g. "myorg.tools.search")
5
+ * while MCP tool names use hyphens (e.g. "myorg-tools-search").
6
+ */
7
+ export declare class ModuleIDNormalizer {
8
+ /**
9
+ * Normalize an apcore module ID to an MCP-compatible tool name.
10
+ *
11
+ * Replaces dots (`.`) with hyphens (`-`).
12
+ */
13
+ normalize(moduleId: string): string;
14
+ /**
15
+ * Denormalize an MCP tool name back to an apcore module ID.
16
+ *
17
+ * Replaces hyphens (`-`) with dots (`.`).
18
+ */
19
+ denormalize(toolName: string): string;
20
+ }
21
+ //# sourceMappingURL=idNormalizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idNormalizer.d.ts","sourceRoot":"","sources":["../../src/adapters/idNormalizer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,qBAAa,kBAAkB;IAC7B;;;;OAIG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAInC;;;;OAIG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;CAGtC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * ModuleIDNormalizer - Converts between apcore module IDs and MCP tool names.
3
+ *
4
+ * apcore uses dot-separated module IDs (e.g. "myorg.tools.search")
5
+ * while MCP tool names use hyphens (e.g. "myorg-tools-search").
6
+ */
7
+ export class ModuleIDNormalizer {
8
+ /**
9
+ * Normalize an apcore module ID to an MCP-compatible tool name.
10
+ *
11
+ * Replaces dots (`.`) with hyphens (`-`).
12
+ */
13
+ normalize(moduleId) {
14
+ return moduleId.replaceAll(".", "-");
15
+ }
16
+ /**
17
+ * Denormalize an MCP tool name back to an apcore module ID.
18
+ *
19
+ * Replaces hyphens (`-`) with dots (`.`).
20
+ */
21
+ denormalize(toolName) {
22
+ return toolName.replaceAll("-", ".");
23
+ }
24
+ }
25
+ //# sourceMappingURL=idNormalizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idNormalizer.js","sourceRoot":"","sources":["../../src/adapters/idNormalizer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,OAAO,kBAAkB;IAC7B;;;;OAIG;IACH,SAAS,CAAC,QAAgB;QACxB,OAAO,QAAQ,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACvC,CAAC;IAED;;;;OAIG;IACH,WAAW,CAAC,QAAgB;QAC1B,OAAO,QAAQ,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACvC,CAAC;CACF"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Adapter classes for converting between apcore and MCP/OpenAI formats.
3
+ */
4
+ export { SchemaConverter } from "./schema.js";
5
+ export { AnnotationMapper } from "./annotations.js";
6
+ export { ErrorMapper } from "./errors.js";
7
+ export { ModuleIDNormalizer } from "./idNormalizer.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Adapter classes for converting between apcore and MCP/OpenAI formats.
3
+ */
4
+ export { SchemaConverter } from "./schema.js";
5
+ export { AnnotationMapper } from "./annotations.js";
6
+ export { ErrorMapper } from "./errors.js";
7
+ export { ModuleIDNormalizer } from "./idNormalizer.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * SchemaConverter - Converts apcore module schemas to MCP-compatible JSON Schema.
3
+ *
4
+ * Handles deep copying, inlining $ref references, and ensuring schemas
5
+ * have the required `type: "object"` for MCP tool input/output schemas.
6
+ */
7
+ import type { JsonSchema, ModuleDescriptor } from "../types.js";
8
+ export declare class SchemaConverter {
9
+ /**
10
+ * Convert a module descriptor's input_schema to an MCP-compatible schema.
11
+ */
12
+ convertInputSchema(descriptor: ModuleDescriptor): JsonSchema;
13
+ /**
14
+ * Convert a module descriptor's output_schema to an MCP-compatible schema.
15
+ */
16
+ convertOutputSchema(descriptor: ModuleDescriptor): JsonSchema;
17
+ /**
18
+ * Apply all schema transformations: deep copy, inline $ref, ensure object type.
19
+ */
20
+ _convertSchema(schema: JsonSchema): JsonSchema;
21
+ /**
22
+ * Recursively inline `$ref` references using the provided $defs map.
23
+ *
24
+ * Handles dicts (objects), arrays, and primitive values.
25
+ * Skips the `$defs` key itself during traversal.
26
+ */
27
+ _inlineRefs(node: unknown, defs: Record<string, JsonSchema>): unknown;
28
+ /**
29
+ * Resolve a `$ref` path (e.g. `#/$defs/MyType`) against the $defs map.
30
+ *
31
+ * Returns a deep copy of the resolved definition to avoid mutation.
32
+ * Throws Error if the ref format is invalid or the definition is not found.
33
+ */
34
+ _resolveRef(refPath: string, defs: Record<string, JsonSchema>): JsonSchema;
35
+ /**
36
+ * Ensure the schema has `type: "object"`.
37
+ *
38
+ * - Empty schema -> `{ type: "object", properties: {} }`
39
+ * - Schema without `type` -> adds `type: "object"`
40
+ */
41
+ _ensureObjectType(schema: JsonSchema): JsonSchema;
42
+ }
43
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/adapters/schema.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEhE,qBAAa,eAAe;IAC1B;;OAEG;IACH,kBAAkB,CAAC,UAAU,EAAE,gBAAgB,GAAG,UAAU;IAI5D;;OAEG;IACH,mBAAmB,CAAC,UAAU,EAAE,gBAAgB,GAAG,UAAU;IAI7D;;OAEG;IACH,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU;IAe9C;;;;;OAKG;IACH,WAAW,CACT,IAAI,EAAE,OAAO,EACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAC/B,OAAO;IA8BV;;;;;OAKG;IACH,WAAW,CACT,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAC/B,UAAU;IAoBb;;;;;OAKG;IACH,iBAAiB,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU;CAclD"}