@wootsup/mcp 0.1.0-rc.9 → 0.3.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/CHANGELOG.md +148 -83
- package/README.md +36 -32
- package/SECURITY.md +15 -6
- package/dist/auth/keychain.d.ts +27 -1
- package/dist/auth/keychain.js +48 -2
- package/dist/auth/keychain.js.map +1 -1
- package/dist/cli-hint.d.ts +22 -0
- package/dist/cli-hint.js +55 -0
- package/dist/cli-hint.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +163 -22
- package/dist/index.js.map +1 -1
- package/dist/install-skill.js +1 -1
- package/dist/modules/apimapper/cache.d.ts +2 -2
- package/dist/modules/apimapper/cache.js +119 -29
- package/dist/modules/apimapper/cache.js.map +1 -1
- package/dist/modules/apimapper/client.d.ts +102 -1
- package/dist/modules/apimapper/client.js +631 -297
- package/dist/modules/apimapper/client.js.map +1 -1
- package/dist/modules/apimapper/connections-format.d.ts +51 -0
- package/dist/modules/apimapper/connections-format.js +261 -0
- package/dist/modules/apimapper/connections-format.js.map +1 -0
- package/dist/modules/apimapper/connections-trim.d.ts +82 -0
- package/dist/modules/apimapper/connections-trim.js +224 -0
- package/dist/modules/apimapper/connections-trim.js.map +1 -0
- package/dist/modules/apimapper/connections.d.ts +14 -2
- package/dist/modules/apimapper/connections.js +612 -153
- package/dist/modules/apimapper/connections.js.map +1 -1
- package/dist/modules/apimapper/credential-sanitizer.d.ts +5 -0
- package/dist/modules/apimapper/credential-sanitizer.js +60 -1
- package/dist/modules/apimapper/credential-sanitizer.js.map +1 -1
- package/dist/modules/apimapper/credentials-format.d.ts +21 -0
- package/dist/modules/apimapper/credentials-format.js +145 -0
- package/dist/modules/apimapper/credentials-format.js.map +1 -0
- package/dist/modules/apimapper/credentials.d.ts +12 -2
- package/dist/modules/apimapper/credentials.js +226 -73
- package/dist/modules/apimapper/credentials.js.map +1 -1
- package/dist/modules/apimapper/diagnose.d.ts +54 -2
- package/dist/modules/apimapper/diagnose.js +213 -12
- package/dist/modules/apimapper/diagnose.js.map +1 -1
- package/dist/modules/apimapper/elicitation.d.ts +54 -0
- package/dist/modules/apimapper/elicitation.js +90 -0
- package/dist/modules/apimapper/elicitation.js.map +1 -0
- package/dist/modules/apimapper/flows-format.d.ts +50 -0
- package/dist/modules/apimapper/flows-format.js +318 -0
- package/dist/modules/apimapper/flows-format.js.map +1 -0
- package/dist/modules/apimapper/flows.d.ts +13 -2
- package/dist/modules/apimapper/flows.js +312 -122
- package/dist/modules/apimapper/flows.js.map +1 -1
- package/dist/modules/apimapper/gateway/advanced-tool.d.ts +9 -0
- package/dist/modules/apimapper/gateway/advanced-tool.js +265 -0
- package/dist/modules/apimapper/gateway/advanced-tool.js.map +1 -0
- package/dist/modules/apimapper/gateway/capturing-server.d.ts +81 -0
- package/dist/modules/apimapper/gateway/capturing-server.js +87 -0
- package/dist/modules/apimapper/gateway/capturing-server.js.map +1 -0
- package/dist/modules/apimapper/gateway/essentials.d.ts +4 -0
- package/dist/modules/apimapper/gateway/essentials.js +35 -0
- package/dist/modules/apimapper/gateway/essentials.js.map +1 -0
- package/dist/modules/apimapper/gateway/test-support.d.ts +17 -0
- package/dist/modules/apimapper/gateway/test-support.js +43 -0
- package/dist/modules/apimapper/gateway/test-support.js.map +1 -0
- package/dist/modules/apimapper/get-skill.d.ts +3 -3
- package/dist/modules/apimapper/get-skill.js +47 -7
- package/dist/modules/apimapper/get-skill.js.map +1 -1
- package/dist/modules/apimapper/graph-builder.js +1 -1
- package/dist/modules/apimapper/graph-builder.js.map +1 -1
- package/dist/modules/apimapper/graph.d.ts +2 -2
- package/dist/modules/apimapper/graph.js +170 -35
- package/dist/modules/apimapper/graph.js.map +1 -1
- package/dist/modules/apimapper/index.d.ts +17 -1
- package/dist/modules/apimapper/index.js +68 -17
- package/dist/modules/apimapper/index.js.map +1 -1
- package/dist/modules/apimapper/inspect.d.ts +3 -2
- package/dist/modules/apimapper/inspect.js +97 -13
- package/dist/modules/apimapper/inspect.js.map +1 -1
- package/dist/modules/apimapper/library.d.ts +2 -2
- package/dist/modules/apimapper/library.js +665 -80
- package/dist/modules/apimapper/library.js.map +1 -1
- package/dist/modules/apimapper/license-format.d.ts +22 -0
- package/dist/modules/apimapper/license-format.js +149 -0
- package/dist/modules/apimapper/license-format.js.map +1 -0
- package/dist/modules/apimapper/license.d.ts +16 -2
- package/dist/modules/apimapper/license.js +62 -38
- package/dist/modules/apimapper/license.js.map +1 -1
- package/dist/modules/apimapper/local-sources.d.ts +2 -2
- package/dist/modules/apimapper/local-sources.js +44 -30
- package/dist/modules/apimapper/local-sources.js.map +1 -1
- package/dist/modules/apimapper/misc.d.ts +30 -2
- package/dist/modules/apimapper/misc.js +114 -49
- package/dist/modules/apimapper/misc.js.map +1 -1
- package/dist/modules/apimapper/node-schema.d.ts +52 -0
- package/dist/modules/apimapper/node-schema.js +70 -2
- package/dist/modules/apimapper/node-schema.js.map +1 -1
- package/dist/modules/apimapper/normalizers.d.ts +1 -0
- package/dist/modules/apimapper/normalizers.js +51 -0
- package/dist/modules/apimapper/normalizers.js.map +1 -1
- package/dist/modules/apimapper/onboarding.d.ts +78 -3
- package/dist/modules/apimapper/onboarding.js +428 -26
- package/dist/modules/apimapper/onboarding.js.map +1 -1
- package/dist/modules/apimapper/read-cache.d.ts +31 -2
- package/dist/modules/apimapper/read-cache.js +20 -6
- package/dist/modules/apimapper/read-cache.js.map +1 -1
- package/dist/modules/apimapper/render/_shared.d.ts +24 -0
- package/dist/modules/apimapper/render/_shared.js +84 -0
- package/dist/modules/apimapper/render/_shared.js.map +1 -0
- package/dist/modules/apimapper/render/dag.d.ts +18 -0
- package/dist/modules/apimapper/render/dag.js +70 -0
- package/dist/modules/apimapper/render/dag.js.map +1 -0
- package/dist/modules/apimapper/render/index.d.ts +2 -0
- package/dist/modules/apimapper/render/index.js +112 -0
- package/dist/modules/apimapper/render/index.js.map +1 -0
- package/dist/modules/apimapper/render/renderers/chart-bar.d.ts +2 -0
- package/dist/modules/apimapper/render/renderers/chart-bar.js +70 -0
- package/dist/modules/apimapper/render/renderers/chart-bar.js.map +1 -0
- package/dist/modules/apimapper/render/renderers/chart-line.d.ts +2 -0
- package/dist/modules/apimapper/render/renderers/chart-line.js +71 -0
- package/dist/modules/apimapper/render/renderers/chart-line.js.map +1 -0
- package/dist/modules/apimapper/render/renderers/diff.d.ts +2 -0
- package/dist/modules/apimapper/render/renderers/diff.js +154 -0
- package/dist/modules/apimapper/render/renderers/diff.js.map +1 -0
- package/dist/modules/apimapper/render/renderers/flow-diagram.d.ts +1 -0
- package/dist/modules/apimapper/render/renderers/flow-diagram.js +180 -0
- package/dist/modules/apimapper/render/renderers/flow-diagram.js.map +1 -0
- package/dist/modules/apimapper/render/renderers/json-tree.d.ts +2 -0
- package/dist/modules/apimapper/render/renderers/json-tree.js +87 -0
- package/dist/modules/apimapper/render/renderers/json-tree.js.map +1 -0
- package/dist/modules/apimapper/render/renderers/schema-diagram.d.ts +2 -0
- package/dist/modules/apimapper/render/renderers/schema-diagram.js +83 -0
- package/dist/modules/apimapper/render/renderers/schema-diagram.js.map +1 -0
- package/dist/modules/apimapper/render/renderers/table.d.ts +2 -0
- package/dist/modules/apimapper/render/renderers/table.js +75 -0
- package/dist/modules/apimapper/render/renderers/table.js.map +1 -0
- package/dist/modules/apimapper/render/schemas.d.ts +23 -0
- package/dist/modules/apimapper/render/schemas.js +56 -0
- package/dist/modules/apimapper/render/schemas.js.map +1 -0
- package/dist/modules/apimapper/render/secret-masking.d.ts +5 -0
- package/dist/modules/apimapper/render/secret-masking.js +51 -0
- package/dist/modules/apimapper/render/secret-masking.js.map +1 -0
- package/dist/modules/apimapper/render/sidecar.d.ts +21 -0
- package/dist/modules/apimapper/render/sidecar.js +66 -0
- package/dist/modules/apimapper/render/sidecar.js.map +1 -0
- package/dist/modules/apimapper/render/token-cap.d.ts +21 -0
- package/dist/modules/apimapper/render/token-cap.js +57 -0
- package/dist/modules/apimapper/render/token-cap.js.map +1 -0
- package/dist/modules/apimapper/schema.d.ts +2 -2
- package/dist/modules/apimapper/schema.js +92 -33
- package/dist/modules/apimapper/schema.js.map +1 -1
- package/dist/modules/apimapper/settings-format.d.ts +23 -0
- package/dist/modules/apimapper/settings-format.js +135 -0
- package/dist/modules/apimapper/settings-format.js.map +1 -0
- package/dist/modules/apimapper/settings.d.ts +2 -2
- package/dist/modules/apimapper/settings.js +100 -42
- package/dist/modules/apimapper/settings.js.map +1 -1
- package/dist/modules/apimapper/sites-tools.d.ts +29 -0
- package/dist/modules/apimapper/sites-tools.js +165 -0
- package/dist/modules/apimapper/sites-tools.js.map +1 -0
- package/dist/modules/apimapper/skill-resources.d.ts +2 -2
- package/dist/modules/apimapper/skill-resources.js.map +1 -1
- package/dist/modules/apimapper/token-baseline.harness.d.ts +91 -0
- package/dist/modules/apimapper/token-baseline.harness.js +291 -0
- package/dist/modules/apimapper/token-baseline.harness.js.map +1 -0
- package/dist/modules/apimapper/tool-result.d.ts +46 -0
- package/dist/modules/apimapper/tool-result.js +63 -0
- package/dist/modules/apimapper/tool-result.js.map +1 -0
- package/dist/modules/apimapper/toolslist-size.d.ts +56 -0
- package/dist/modules/apimapper/toolslist-size.js +192 -0
- package/dist/modules/apimapper/toolslist-size.js.map +1 -0
- package/dist/modules/apimapper/types.d.ts +44 -8
- package/dist/modules/apimapper/types.js +26 -1
- package/dist/modules/apimapper/types.js.map +1 -1
- package/dist/modules/apimapper/use-profile.d.ts +21 -0
- package/dist/modules/apimapper/use-profile.js +56 -2
- package/dist/modules/apimapper/use-profile.js.map +1 -1
- package/dist/modules/apimapper/whitelist-drift.d.ts +85 -0
- package/dist/modules/apimapper/whitelist-drift.js +360 -0
- package/dist/modules/apimapper/whitelist-drift.js.map +1 -0
- package/dist/modules/apimapper/workflows.d.ts +2 -2
- package/dist/modules/apimapper/workflows.js +202 -20
- package/dist/modules/apimapper/workflows.js.map +1 -1
- package/dist/modules/apimapper/yootheme-binding.d.ts +35 -0
- package/dist/modules/apimapper/yootheme-binding.js +186 -0
- package/dist/modules/apimapper/yootheme-binding.js.map +1 -0
- package/dist/platform/index.d.ts +56 -0
- package/dist/platform/index.js +195 -7
- package/dist/platform/index.js.map +1 -1
- package/dist/setup/detect-clients.d.ts +40 -1
- package/dist/setup/detect-clients.js +148 -1
- package/dist/setup/detect-clients.js.map +1 -1
- package/dist/setup/probe-handshake.js +40 -7
- package/dist/setup/probe-handshake.js.map +1 -1
- package/dist/setup/remove-config.d.ts +8 -0
- package/dist/setup/remove-config.js +145 -0
- package/dist/setup/remove-config.js.map +1 -0
- package/dist/setup/uninstall.d.ts +34 -0
- package/dist/setup/uninstall.js +147 -0
- package/dist/setup/uninstall.js.map +1 -0
- package/dist/setup-cli.d.ts +60 -0
- package/dist/setup-cli.js +155 -5
- package/dist/setup-cli.js.map +1 -1
- package/dist/sites/loader.d.ts +41 -0
- package/dist/sites/loader.js +119 -0
- package/dist/sites/loader.js.map +1 -0
- package/dist/sites/schema.d.ts +69 -0
- package/dist/sites/schema.js +71 -0
- package/dist/sites/schema.js.map +1 -0
- package/dist/sites/secret-resolver.d.ts +47 -0
- package/dist/sites/secret-resolver.js +150 -0
- package/dist/sites/secret-resolver.js.map +1 -0
- package/dist/skill-instructions.d.ts +1 -1
- package/dist/skill-instructions.js +5 -0
- package/dist/skill-instructions.js.map +1 -1
- package/dist/transports/stdio.js +4 -4
- package/dist/transports/stdio.js.map +1 -1
- package/dist/uninstall-skill.d.ts +27 -0
- package/dist/uninstall-skill.js +89 -0
- package/dist/uninstall-skill.js.map +1 -0
- package/docs/architecture.md +22 -22
- package/docs/customgraph-internal-migration.md +4 -4
- package/docs/security.md +2 -21
- package/docs/tools.md +40 -12
- package/manifest.json +77 -70
- package/package.json +68 -60
- package/skills/apimapper/SKILL.md +53 -7
- package/skills/apimapper/reference/conditional-style-multi-items.md +114 -0
- package/skills/apimapper/reference/jmespath-pitfalls.md +108 -0
- package/skills/apimapper/reference/joomla.md +1 -1
- package/skills/apimapper/reference/library-template-discovery.md +65 -0
- package/skills/apimapper/reference/merge-two-sources-on-key.md +99 -0
- package/skills/apimapper/reference/render.md +132 -0
- package/skills/apimapper/reference/troubleshooting.md +21 -1
- package/skills/apimapper/reference/yootheme.md +1 -1
- package/dist/auth/oauth-provider.d.ts +0 -68
- package/dist/auth/oauth-provider.js +0 -232
- package/dist/auth/oauth-provider.js.map +0 -1
- package/dist/server-http.d.ts +0 -22
- package/dist/server-http.js +0 -159
- package/dist/server-http.js.map +0 -1
- package/dist/transports/http.d.ts +0 -29
- package/dist/transports/http.js +0 -267
- package/dist/transports/http.js.map +0 -1
package/dist/server-http.js
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// src/server-http.ts — Phase 9.2 HTTP entry point.
|
|
3
|
-
//
|
|
4
|
-
// Boots the http+OAuth transport for the API Mapper MCP server. Used by:
|
|
5
|
-
// - `npm run start:http` (local dev / staging)
|
|
6
|
-
// - the future hosted service at mcp.wootsup.com (Phase 10+)
|
|
7
|
-
//
|
|
8
|
-
// The MCP handler bridges incoming JSON-RPC requests to a real
|
|
9
|
-
// SDK-managed McpServer via `createServer()` + `InMemoryTransport.createLinkedPair()`.
|
|
10
|
-
// Each HTTP request is serialised through the in-memory transport pair so
|
|
11
|
-
// the MCP server's full handler-registry runs (initialize, tools/list,
|
|
12
|
-
// tools/call all dispatch correctly). Tests can pass their own handler
|
|
13
|
-
// stub via `bootHttpServer({ mcpHandler })`.
|
|
14
|
-
import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
|
|
15
|
-
import { loadModules } from "@getimo/mcp-toolkit";
|
|
16
|
-
import { createHttpTransportServer } from "./transports/http.js";
|
|
17
|
-
import { createOAuthProvider } from "./auth/oauth-provider.js";
|
|
18
|
-
import { createServer } from "./index.js";
|
|
19
|
-
import { apimapperRestModule } from "./modules/apimapper/index.js";
|
|
20
|
-
const DEFAULT_PORT = (() => {
|
|
21
|
-
const env = process.env.APIMAPPER_HTTP_PORT;
|
|
22
|
-
const parsed = env ? Number.parseInt(env, 10) : NaN;
|
|
23
|
-
return Number.isFinite(parsed) ? parsed : 8901;
|
|
24
|
-
})();
|
|
25
|
-
/**
|
|
26
|
-
* Default MCP handler — closes Phase 9.2 "deferred SDK binding" gap
|
|
27
|
-
* (R7 audit finding 2026-05-18).
|
|
28
|
-
*
|
|
29
|
-
* Lazily boots a real McpServer + loads all api-mapper modules + connects
|
|
30
|
-
* it to one end of an InMemoryTransport pair. The HTTP handler-callback
|
|
31
|
-
* sends each incoming JSON-RPC request through the other end and awaits
|
|
32
|
-
* the matching response by id.
|
|
33
|
-
*
|
|
34
|
-
* This makes the HTTP transport functionally equivalent to stdio:
|
|
35
|
-
* initialize, tools/list, tools/call all dispatch through the same
|
|
36
|
-
* McpServer instance + tool registry that the stdio transport uses.
|
|
37
|
-
*/
|
|
38
|
-
let mcpHandlerSingleton = null;
|
|
39
|
-
let mcpServerSingleton = null;
|
|
40
|
-
let mcpModuleStatuses = [];
|
|
41
|
-
async function getDefaultMcpHandler() {
|
|
42
|
-
if (mcpHandlerSingleton)
|
|
43
|
-
return mcpHandlerSingleton;
|
|
44
|
-
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
|
45
|
-
const server = createServer();
|
|
46
|
-
mcpServerSingleton = server;
|
|
47
|
-
mcpModuleStatuses = await loadModules(server, [apimapperRestModule]);
|
|
48
|
-
await server.connect(serverTransport);
|
|
49
|
-
// The client end stays open for the lifetime of the HTTP server. Each
|
|
50
|
-
// HTTP request sends a JSON-RPC message in and registers a one-shot
|
|
51
|
-
// resolver keyed on the JSON-RPC id; the McpServer's reply lands on
|
|
52
|
-
// clientTransport.onmessage and resolves the matching pending promise.
|
|
53
|
-
await clientTransport.start();
|
|
54
|
-
const pending = new Map();
|
|
55
|
-
clientTransport.onmessage = (message) => {
|
|
56
|
-
const m = message;
|
|
57
|
-
if (m && m.id !== undefined && pending.has(m.id)) {
|
|
58
|
-
const resolve = pending.get(m.id);
|
|
59
|
-
pending.delete(m.id);
|
|
60
|
-
resolve(message);
|
|
61
|
-
}
|
|
62
|
-
// Server-initiated notifications (no id) are intentionally dropped —
|
|
63
|
-
// the HTTP transport is request/response only.
|
|
64
|
-
};
|
|
65
|
-
mcpHandlerSingleton = async (body) => {
|
|
66
|
-
const req = body;
|
|
67
|
-
// Notifications carry no id and expect no response. Forward + return
|
|
68
|
-
// 202-like empty body to caller.
|
|
69
|
-
if (req.id === undefined) {
|
|
70
|
-
try {
|
|
71
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- SDK message type is broader
|
|
72
|
-
await clientTransport.send(body);
|
|
73
|
-
}
|
|
74
|
-
catch {
|
|
75
|
-
/* ignore — notification fire-and-forget */
|
|
76
|
-
}
|
|
77
|
-
return { jsonrpc: "2.0", result: { ok: true } };
|
|
78
|
-
}
|
|
79
|
-
// Request/response: register resolver, send, await reply.
|
|
80
|
-
return new Promise((resolve) => {
|
|
81
|
-
const timer = setTimeout(() => {
|
|
82
|
-
if (pending.has(req.id)) {
|
|
83
|
-
pending.delete(req.id);
|
|
84
|
-
resolve({
|
|
85
|
-
jsonrpc: "2.0",
|
|
86
|
-
id: req.id,
|
|
87
|
-
error: { code: -32000, message: "HTTP→MCP dispatch timed out after 30s" },
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
}, 30_000);
|
|
91
|
-
pending.set(req.id, (msg) => {
|
|
92
|
-
clearTimeout(timer);
|
|
93
|
-
resolve(msg);
|
|
94
|
-
});
|
|
95
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- SDK message type is broader
|
|
96
|
-
void clientTransport.send(body).catch((err) => {
|
|
97
|
-
clearTimeout(timer);
|
|
98
|
-
pending.delete(req.id);
|
|
99
|
-
resolve({
|
|
100
|
-
jsonrpc: "2.0",
|
|
101
|
-
id: req.id,
|
|
102
|
-
error: { code: -32603, message: `dispatch failed: ${err.message}` },
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
};
|
|
107
|
-
return mcpHandlerSingleton;
|
|
108
|
-
}
|
|
109
|
-
/** Test-only — exposes the server + module load status for assertions. */
|
|
110
|
-
export function _testGetMcpServer() {
|
|
111
|
-
return { server: mcpServerSingleton, modules: mcpModuleStatuses };
|
|
112
|
-
}
|
|
113
|
-
export async function bootHttpServer(options = {}) {
|
|
114
|
-
const port = options.port ?? DEFAULT_PORT;
|
|
115
|
-
const oauth = createOAuthProvider();
|
|
116
|
-
const mcpHandler = options.mcpHandler ?? (await getDefaultMcpHandler());
|
|
117
|
-
const transport = await createHttpTransportServer({
|
|
118
|
-
port,
|
|
119
|
-
oauth,
|
|
120
|
-
mcpHandler,
|
|
121
|
-
publicBaseUrl: options.publicBaseUrl,
|
|
122
|
-
});
|
|
123
|
-
return { ...transport, oauth };
|
|
124
|
-
}
|
|
125
|
-
// ── CLI entry ──────────────────────────────────────────────────────────
|
|
126
|
-
// Only auto-boot when this file is executed as the process entrypoint
|
|
127
|
-
// (i.e. `node dist/server-http.js`), never when imported by tests.
|
|
128
|
-
const isEntry = (() => {
|
|
129
|
-
if (typeof process.argv[1] !== "string")
|
|
130
|
-
return false;
|
|
131
|
-
// import.meta.url is a file:// URL; argv[1] is a path. Map both to
|
|
132
|
-
// a comparable form.
|
|
133
|
-
try {
|
|
134
|
-
const argvUrl = new URL(`file://${process.argv[1]}`).href;
|
|
135
|
-
return argvUrl === import.meta.url;
|
|
136
|
-
}
|
|
137
|
-
catch {
|
|
138
|
-
return false;
|
|
139
|
-
}
|
|
140
|
-
})();
|
|
141
|
-
if (isEntry) {
|
|
142
|
-
bootHttpServer()
|
|
143
|
-
.then((s) => {
|
|
144
|
-
// eslint-disable-next-line no-console -- intentional startup log
|
|
145
|
-
console.error(`[apimapper-mcp] HTTP transport listening on ${s.url}`);
|
|
146
|
-
const shutdown = async () => {
|
|
147
|
-
await s.close();
|
|
148
|
-
process.exit(0);
|
|
149
|
-
};
|
|
150
|
-
process.on("SIGTERM", shutdown);
|
|
151
|
-
process.on("SIGINT", shutdown);
|
|
152
|
-
})
|
|
153
|
-
.catch((err) => {
|
|
154
|
-
// eslint-disable-next-line no-console -- intentional fatal log
|
|
155
|
-
console.error("[apimapper-mcp] HTTP boot failed:", err);
|
|
156
|
-
process.exit(1);
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
//# sourceMappingURL=server-http.js.map
|
package/dist/server-http.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"server-http.js","sourceRoot":"","sources":["../src/server-http.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { type Server } from "node:http";
|
|
2
|
-
import type { OAuthProvider } from "../auth/oauth-provider.js";
|
|
3
|
-
export interface HttpAuthInfo {
|
|
4
|
-
client_id: string;
|
|
5
|
-
scope: string;
|
|
6
|
-
}
|
|
7
|
-
export type McpHandler = (body: unknown, authInfo: HttpAuthInfo | null) => Promise<unknown>;
|
|
8
|
-
export interface HttpTransportOptions {
|
|
9
|
-
/** TCP port to bind. Use 0 for an ephemeral port. */
|
|
10
|
-
port: number;
|
|
11
|
-
/** OAuth provider state — typically a singleton per process. */
|
|
12
|
-
oauth: OAuthProvider;
|
|
13
|
-
/** MCP routing callback. Receives parsed JSON body + auth info. */
|
|
14
|
-
mcpHandler: McpHandler;
|
|
15
|
-
/**
|
|
16
|
-
* Public base URL used in OAuth metadata. Default: derived from the
|
|
17
|
-
* bound address (`http://127.0.0.1:<port>`).
|
|
18
|
-
*/
|
|
19
|
-
publicBaseUrl?: string;
|
|
20
|
-
}
|
|
21
|
-
export interface HttpTransportServer {
|
|
22
|
-
/** http.Server instance. */
|
|
23
|
-
server: Server;
|
|
24
|
-
/** Resolved base URL (with port). */
|
|
25
|
-
url: string;
|
|
26
|
-
/** Stop accepting new connections + close existing keep-alives. */
|
|
27
|
-
close(): Promise<void>;
|
|
28
|
-
}
|
|
29
|
-
export declare function createHttpTransportServer(options: HttpTransportOptions): Promise<HttpTransportServer>;
|
package/dist/transports/http.js
DELETED
|
@@ -1,267 +0,0 @@
|
|
|
1
|
-
// src/transports/http.ts — Phase 9.2.
|
|
2
|
-
//
|
|
3
|
-
// Native node:http server that exposes:
|
|
4
|
-
//
|
|
5
|
-
// GET /health — readiness probe
|
|
6
|
-
// GET /.well-known/oauth-authorization-server — RFC 8414 metadata
|
|
7
|
-
// POST /register — RFC 7591 Dynamic Client Registration
|
|
8
|
-
// GET /authorize — OAuth 2.0 Authorization endpoint
|
|
9
|
-
// POST /token — OAuth 2.0 Token endpoint
|
|
10
|
-
// POST /mcp — MCP JSON-RPC (Bearer-gated)
|
|
11
|
-
//
|
|
12
|
-
// The MCP routing is intentionally pluggable via the `mcpHandler` callback:
|
|
13
|
-
// this file is responsible ONLY for HTTP framing + OAuth auth. The boot
|
|
14
|
-
// entry `src/server-http.ts` glues this transport to a real MCP server by
|
|
15
|
-
// supplying a handler that uses the SDK's StreamableHTTPServerTransport.
|
|
16
|
-
//
|
|
17
|
-
// Why hand-rolled HTTP instead of Express? We already have @modelcontextprotocol/sdk
|
|
18
|
-
// + zod + clack as runtime deps; adding Express would balloon the DXT bundle
|
|
19
|
-
// for ~50 lines of routing logic we own outright.
|
|
20
|
-
import { createServer as createHttpServer } from "node:http";
|
|
21
|
-
// ── Helpers ────────────────────────────────────────────────────────────
|
|
22
|
-
function send(res, status, body, extraHeaders = {}) {
|
|
23
|
-
const payload = typeof body === "string" ? body : JSON.stringify(body);
|
|
24
|
-
res.writeHead(status, {
|
|
25
|
-
"content-type": typeof body === "string" ? "text/plain; charset=utf-8" : "application/json",
|
|
26
|
-
"content-length": String(Buffer.byteLength(payload)),
|
|
27
|
-
...extraHeaders,
|
|
28
|
-
});
|
|
29
|
-
res.end(payload);
|
|
30
|
-
}
|
|
31
|
-
function sendError(res, status, error, description) {
|
|
32
|
-
const body = { error };
|
|
33
|
-
if (description)
|
|
34
|
-
body.error_description = description;
|
|
35
|
-
send(res, status, body);
|
|
36
|
-
}
|
|
37
|
-
async function readBody(req) {
|
|
38
|
-
return new Promise((resolve, reject) => {
|
|
39
|
-
const chunks = [];
|
|
40
|
-
req.on("data", (c) => chunks.push(c));
|
|
41
|
-
req.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
|
|
42
|
-
req.on("error", reject);
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
function parseJson(raw) {
|
|
46
|
-
if (!raw)
|
|
47
|
-
return {};
|
|
48
|
-
try {
|
|
49
|
-
return JSON.parse(raw);
|
|
50
|
-
}
|
|
51
|
-
catch {
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
function getBearer(req) {
|
|
56
|
-
const hdr = req.headers["authorization"];
|
|
57
|
-
if (typeof hdr !== "string")
|
|
58
|
-
return null;
|
|
59
|
-
const m = /^Bearer\s+(.+)$/i.exec(hdr);
|
|
60
|
-
return m ? m[1] : null;
|
|
61
|
-
}
|
|
62
|
-
// ── Factory ────────────────────────────────────────────────────────────
|
|
63
|
-
export async function createHttpTransportServer(options) {
|
|
64
|
-
const { oauth, mcpHandler } = options;
|
|
65
|
-
// We compute the public base URL lazily — for port: 0 we need it after
|
|
66
|
-
// listen() resolves.
|
|
67
|
-
let publicBaseUrl = options.publicBaseUrl ?? "";
|
|
68
|
-
const server = createHttpServer(async (req, res) => {
|
|
69
|
-
try {
|
|
70
|
-
await handle(req, res);
|
|
71
|
-
}
|
|
72
|
-
catch (err) {
|
|
73
|
-
// Never let the listener throw — surface as a 500 with a sanitized body.
|
|
74
|
-
const msg = err instanceof Error ? err.message : "unknown_error";
|
|
75
|
-
sendError(res, 500, "server_error", msg);
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
async function handle(req, res) {
|
|
79
|
-
const url = new URL(req.url ?? "/", publicBaseUrl || "http://127.0.0.1");
|
|
80
|
-
const path = url.pathname;
|
|
81
|
-
const method = (req.method ?? "GET").toUpperCase();
|
|
82
|
-
// ── /health ──────────────────────────────────────────────────────
|
|
83
|
-
if (path === "/health" && method === "GET") {
|
|
84
|
-
send(res, 200, { status: "ok", transport: "http" });
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
// ── /.well-known/oauth-authorization-server ──────────────────────
|
|
88
|
-
if (path === "/.well-known/oauth-authorization-server" &&
|
|
89
|
-
method === "GET") {
|
|
90
|
-
send(res, 200, {
|
|
91
|
-
issuer: publicBaseUrl,
|
|
92
|
-
authorization_endpoint: `${publicBaseUrl}/authorize`,
|
|
93
|
-
token_endpoint: `${publicBaseUrl}/token`,
|
|
94
|
-
registration_endpoint: `${publicBaseUrl}/register`,
|
|
95
|
-
response_types_supported: ["code"],
|
|
96
|
-
grant_types_supported: ["authorization_code", "refresh_token"],
|
|
97
|
-
code_challenge_methods_supported: ["S256"],
|
|
98
|
-
token_endpoint_auth_methods_supported: ["none"],
|
|
99
|
-
scopes_supported: ["read", "write", "admin"],
|
|
100
|
-
});
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
// ── POST /register (RFC 7591 DCR) ────────────────────────────────
|
|
104
|
-
if (path === "/register" && method === "POST") {
|
|
105
|
-
const raw = await readBody(req);
|
|
106
|
-
const body = parseJson(raw);
|
|
107
|
-
if (body === null || typeof body !== "object") {
|
|
108
|
-
sendError(res, 400, "invalid_client_metadata", "body must be JSON");
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
const b = body;
|
|
112
|
-
const redirectUris = Array.isArray(b.redirect_uris)
|
|
113
|
-
? b.redirect_uris.filter((u) => typeof u === "string")
|
|
114
|
-
: [];
|
|
115
|
-
const clientName = typeof b.client_name === "string" ? b.client_name : undefined;
|
|
116
|
-
try {
|
|
117
|
-
const reg = oauth.registerClient({
|
|
118
|
-
redirect_uris: redirectUris,
|
|
119
|
-
client_name: clientName,
|
|
120
|
-
});
|
|
121
|
-
send(res, 201, reg);
|
|
122
|
-
}
|
|
123
|
-
catch (err) {
|
|
124
|
-
const msg = err instanceof Error ? err.message : "invalid_client_metadata";
|
|
125
|
-
sendError(res, 400, "invalid_client_metadata", msg);
|
|
126
|
-
}
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
// ── GET /authorize ───────────────────────────────────────────────
|
|
130
|
-
if (path === "/authorize" && method === "GET") {
|
|
131
|
-
const q = url.searchParams;
|
|
132
|
-
const clientId = q.get("client_id") ?? "";
|
|
133
|
-
const redirectUri = q.get("redirect_uri") ?? "";
|
|
134
|
-
const responseType = q.get("response_type") ?? "";
|
|
135
|
-
const codeChallenge = q.get("code_challenge") ?? "";
|
|
136
|
-
const codeChallengeMethod = q.get("code_challenge_method") ?? "";
|
|
137
|
-
const scope = q.get("scope") ?? "";
|
|
138
|
-
const state = q.get("state") ?? undefined;
|
|
139
|
-
if (responseType !== "code") {
|
|
140
|
-
sendError(res, 400, "unsupported_response_type");
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
const client = oauth.getClient(clientId);
|
|
144
|
-
if (!client) {
|
|
145
|
-
sendError(res, 400, "unknown_client");
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
if (!client.redirect_uris.includes(redirectUri)) {
|
|
149
|
-
sendError(res, 400, "invalid_redirect_uri");
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
if (codeChallengeMethod !== "S256") {
|
|
153
|
-
sendError(res, 400, "invalid_request", "code_challenge_method must be S256");
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
|
-
let code;
|
|
157
|
-
try {
|
|
158
|
-
code = oauth.issueCode({
|
|
159
|
-
client_id: clientId,
|
|
160
|
-
redirect_uri: redirectUri,
|
|
161
|
-
code_challenge: codeChallenge,
|
|
162
|
-
code_challenge_method: "S256",
|
|
163
|
-
scope,
|
|
164
|
-
state,
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
catch (err) {
|
|
168
|
-
const msg = err instanceof Error ? err.message : "invalid_request";
|
|
169
|
-
sendError(res, 400, "invalid_request", msg);
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
const cbUrl = new URL(redirectUri);
|
|
173
|
-
cbUrl.searchParams.set("code", code);
|
|
174
|
-
if (state !== undefined)
|
|
175
|
-
cbUrl.searchParams.set("state", state);
|
|
176
|
-
res.writeHead(302, { location: cbUrl.toString() });
|
|
177
|
-
res.end();
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
// ── POST /token ──────────────────────────────────────────────────
|
|
181
|
-
if (path === "/token" && method === "POST") {
|
|
182
|
-
const raw = await readBody(req);
|
|
183
|
-
const params = new URLSearchParams(raw);
|
|
184
|
-
const grantType = params.get("grant_type") ?? "";
|
|
185
|
-
try {
|
|
186
|
-
if (grantType === "authorization_code") {
|
|
187
|
-
const tokens = oauth.exchangeCode({
|
|
188
|
-
client_id: params.get("client_id") ?? "",
|
|
189
|
-
code: params.get("code") ?? "",
|
|
190
|
-
redirect_uri: params.get("redirect_uri") ?? "",
|
|
191
|
-
code_verifier: params.get("code_verifier") ?? "",
|
|
192
|
-
});
|
|
193
|
-
send(res, 200, tokens);
|
|
194
|
-
return;
|
|
195
|
-
}
|
|
196
|
-
if (grantType === "refresh_token") {
|
|
197
|
-
const tokens = oauth.refreshToken({
|
|
198
|
-
client_id: params.get("client_id") ?? "",
|
|
199
|
-
refresh_token: params.get("refresh_token") ?? "",
|
|
200
|
-
});
|
|
201
|
-
send(res, 200, tokens);
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
sendError(res, 400, "unsupported_grant_type");
|
|
205
|
-
}
|
|
206
|
-
catch (err) {
|
|
207
|
-
const msg = err instanceof Error ? err.message : "invalid_grant";
|
|
208
|
-
sendError(res, 400, "invalid_grant", msg);
|
|
209
|
-
}
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
// ── POST /mcp ────────────────────────────────────────────────────
|
|
213
|
-
if (path === "/mcp" && method === "POST") {
|
|
214
|
-
const token = getBearer(req);
|
|
215
|
-
if (!token) {
|
|
216
|
-
send(res, 401, { error: "unauthorized", error_description: "Bearer token required" }, {
|
|
217
|
-
"www-authenticate": `Bearer realm="${publicBaseUrl}", error="invalid_token"`,
|
|
218
|
-
});
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
const info = oauth.verifyAccessToken(token);
|
|
222
|
-
if (!info) {
|
|
223
|
-
send(res, 401, {
|
|
224
|
-
error: "invalid_token",
|
|
225
|
-
error_description: "Bearer token unknown or expired",
|
|
226
|
-
}, {
|
|
227
|
-
"www-authenticate": `Bearer realm="${publicBaseUrl}", error="invalid_token"`,
|
|
228
|
-
});
|
|
229
|
-
return;
|
|
230
|
-
}
|
|
231
|
-
const raw = await readBody(req);
|
|
232
|
-
const body = parseJson(raw);
|
|
233
|
-
if (body === null) {
|
|
234
|
-
sendError(res, 400, "invalid_request", "body must be JSON");
|
|
235
|
-
return;
|
|
236
|
-
}
|
|
237
|
-
const result = await mcpHandler(body, {
|
|
238
|
-
client_id: info.client_id,
|
|
239
|
-
scope: info.scope,
|
|
240
|
-
});
|
|
241
|
-
send(res, 200, result);
|
|
242
|
-
return;
|
|
243
|
-
}
|
|
244
|
-
// ── 404 fallback ─────────────────────────────────────────────────
|
|
245
|
-
sendError(res, 404, "not_found", `no route for ${method} ${path}`);
|
|
246
|
-
}
|
|
247
|
-
// Bind + resolve base URL
|
|
248
|
-
await new Promise((resolve) => server.listen(options.port, resolve));
|
|
249
|
-
const addr = server.address();
|
|
250
|
-
if (!publicBaseUrl) {
|
|
251
|
-
publicBaseUrl = `http://127.0.0.1:${addr.port}`;
|
|
252
|
-
}
|
|
253
|
-
else if (publicBaseUrl === "http://127.0.0.1" ||
|
|
254
|
-
publicBaseUrl === "http://localhost") {
|
|
255
|
-
publicBaseUrl = `${publicBaseUrl}:${addr.port}`;
|
|
256
|
-
}
|
|
257
|
-
return {
|
|
258
|
-
server,
|
|
259
|
-
url: publicBaseUrl,
|
|
260
|
-
close: () => new Promise((resolve, reject) => {
|
|
261
|
-
server.close((err) => (err ? reject(err) : resolve()));
|
|
262
|
-
// Force-close keep-alive sockets so tests don't hang.
|
|
263
|
-
server.closeAllConnections?.();
|
|
264
|
-
}),
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
//# sourceMappingURL=http.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/transports/http.ts"],"names":[],"mappings":"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"}
|