@sentropic/h2a-cli 0.23.0 → 0.25.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.
Files changed (76) hide show
  1. package/dist/cli-contract.d.ts.map +1 -1
  2. package/dist/cli-contract.js +24 -0
  3. package/dist/cli-contract.js.map +1 -1
  4. package/dist/cli.d.ts.map +1 -1
  5. package/dist/cli.js +219 -1
  6. package/dist/cli.js.map +1 -1
  7. package/dist/index.d.ts +2 -1
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +1 -0
  10. package/dist/index.js.map +1 -1
  11. package/dist/mcp.d.ts +1 -1
  12. package/dist/mcp.d.ts.map +1 -1
  13. package/dist/mcp.js +1 -0
  14. package/dist/mcp.js.map +1 -1
  15. package/dist/runtime/identity/live.d.ts.map +1 -1
  16. package/dist/runtime/identity/live.js +15 -1
  17. package/dist/runtime/identity/live.js.map +1 -1
  18. package/dist/runtime/mcp/handlers.d.ts +13 -0
  19. package/dist/runtime/mcp/handlers.d.ts.map +1 -1
  20. package/dist/runtime/mcp/handlers.js +83 -1
  21. package/dist/runtime/mcp/handlers.js.map +1 -1
  22. package/dist/runtime/mcp/server.d.ts.map +1 -1
  23. package/dist/runtime/mcp/server.js +3 -1
  24. package/dist/runtime/mcp/server.js.map +1 -1
  25. package/dist/runtime/mcp/tools.d.ts.map +1 -1
  26. package/dist/runtime/mcp/tools.js +26 -0
  27. package/dist/runtime/mcp/tools.js.map +1 -1
  28. package/dist/runtime/mcp-http/app.d.ts +12 -0
  29. package/dist/runtime/mcp-http/app.d.ts.map +1 -0
  30. package/dist/runtime/mcp-http/app.js +61 -0
  31. package/dist/runtime/mcp-http/app.js.map +1 -0
  32. package/dist/runtime/mcp-http/hosted-mcp-server.d.ts +14 -0
  33. package/dist/runtime/mcp-http/hosted-mcp-server.d.ts.map +1 -0
  34. package/dist/runtime/mcp-http/hosted-mcp-server.js +38 -0
  35. package/dist/runtime/mcp-http/hosted-mcp-server.js.map +1 -0
  36. package/dist/runtime/mcp-http/index.d.ts +14 -0
  37. package/dist/runtime/mcp-http/index.d.ts.map +1 -0
  38. package/dist/runtime/mcp-http/index.js +14 -0
  39. package/dist/runtime/mcp-http/index.js.map +1 -0
  40. package/dist/runtime/mcp-http/main.d.ts +2 -0
  41. package/dist/runtime/mcp-http/main.d.ts.map +1 -0
  42. package/dist/runtime/mcp-http/main.js +14 -0
  43. package/dist/runtime/mcp-http/main.js.map +1 -0
  44. package/dist/runtime/mcp-http/oauth/config.d.ts +33 -0
  45. package/dist/runtime/mcp-http/oauth/config.d.ts.map +1 -0
  46. package/dist/runtime/mcp-http/oauth/config.js +31 -0
  47. package/dist/runtime/mcp-http/oauth/config.js.map +1 -0
  48. package/dist/runtime/mcp-http/oauth/crypto.d.ts +5 -0
  49. package/dist/runtime/mcp-http/oauth/crypto.d.ts.map +1 -0
  50. package/dist/runtime/mcp-http/oauth/crypto.js +19 -0
  51. package/dist/runtime/mcp-http/oauth/crypto.js.map +1 -0
  52. package/dist/runtime/mcp-http/oauth/file-store.d.ts +40 -0
  53. package/dist/runtime/mcp-http/oauth/file-store.d.ts.map +1 -0
  54. package/dist/runtime/mcp-http/oauth/file-store.js +101 -0
  55. package/dist/runtime/mcp-http/oauth/file-store.js.map +1 -0
  56. package/dist/runtime/mcp-http/oauth/hono-oauth-router.d.ts +5 -0
  57. package/dist/runtime/mcp-http/oauth/hono-oauth-router.d.ts.map +1 -0
  58. package/dist/runtime/mcp-http/oauth/hono-oauth-router.js +83 -0
  59. package/dist/runtime/mcp-http/oauth/hono-oauth-router.js.map +1 -0
  60. package/dist/runtime/mcp-http/oauth/redirect-uri.d.ts +11 -0
  61. package/dist/runtime/mcp-http/oauth/redirect-uri.d.ts.map +1 -0
  62. package/dist/runtime/mcp-http/oauth/redirect-uri.js +29 -0
  63. package/dist/runtime/mcp-http/oauth/redirect-uri.js.map +1 -0
  64. package/dist/runtime/mcp-http/oauth/single-tenant-provider.d.ts +68 -0
  65. package/dist/runtime/mcp-http/oauth/single-tenant-provider.d.ts.map +1 -0
  66. package/dist/runtime/mcp-http/oauth/single-tenant-provider.js +238 -0
  67. package/dist/runtime/mcp-http/oauth/single-tenant-provider.js.map +1 -0
  68. package/dist/runtime/mcp-http/readonly-allowlist.d.ts +24 -0
  69. package/dist/runtime/mcp-http/readonly-allowlist.d.ts.map +1 -0
  70. package/dist/runtime/mcp-http/readonly-allowlist.js +43 -0
  71. package/dist/runtime/mcp-http/readonly-allowlist.js.map +1 -0
  72. package/dist/runtime/mcp-http/serve.d.ts +30 -0
  73. package/dist/runtime/mcp-http/serve.d.ts.map +1 -0
  74. package/dist/runtime/mcp-http/serve.js +53 -0
  75. package/dist/runtime/mcp-http/serve.js.map +1 -0
  76. package/package.json +6 -2
@@ -0,0 +1,38 @@
1
+ /**
2
+ * EVO-12 hosted MCP server — wraps the EXISTING in-process h2a tool dispatch
3
+ * (`McpServer.callTool`) behind an SDK `Server`, exposing ONLY the read-only
4
+ * allowlist. `dispatchHostedTool` refuses any non-allowlisted tool name
5
+ * (defense-in-depth: a signing/private-key tool is never reachable here, even
6
+ * if the wire asked for it).
7
+ */
8
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
9
+ import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
10
+ import { currentCliVersion } from "../upgrade/index.js";
11
+ import { H2A_CLI_MCP_TOOL_DESCRIPTORS } from "../mcp/tools.js";
12
+ import { hostedReadOnlyDescriptors, isHostedReadOnlyTool } from "./readonly-allowlist.js";
13
+ export function dispatchHostedTool(h2a, name, args) {
14
+ if (!isHostedReadOnlyTool(name)) {
15
+ return {
16
+ content: [{ type: "text", text: `tool '${name}' is not exposed on the hosted read-only surface` }],
17
+ isError: true
18
+ };
19
+ }
20
+ const result = h2a.callTool(name, args);
21
+ if (result && typeof result === "object" && "error" in result && typeof result.error === "string") {
22
+ return { content: [{ type: "text", text: result.error }], isError: true };
23
+ }
24
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
25
+ }
26
+ /** SDK Server exposing only the read-only allowlist, dispatching to the h2a callTool. */
27
+ export function buildHostedMcpServer(h2a) {
28
+ const server = new Server({ name: "h2a", version: currentCliVersion() }, { capabilities: { tools: { listChanged: true } } });
29
+ const announced = hostedReadOnlyDescriptors(H2A_CLI_MCP_TOOL_DESCRIPTORS).map((d) => ({
30
+ name: d.name,
31
+ description: d.description,
32
+ inputSchema: d.inputSchema
33
+ }));
34
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: announced }));
35
+ server.setRequestHandler(CallToolRequestSchema, async (req) => dispatchHostedTool(h2a, req.params.name, req.params.arguments ?? {}));
36
+ return server;
37
+ }
38
+ //# sourceMappingURL=hosted-mcp-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hosted-mcp-server.js","sourceRoot":"","sources":["../../../src/runtime/mcp-http/hosted-mcp-server.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EACL,qBAAqB,EAErB,sBAAsB,EACvB,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,4BAA4B,EAAE,MAAM,iBAAiB,CAAC;AAE/D,OAAO,EAAE,yBAAyB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAE1F,MAAM,UAAU,kBAAkB,CAChC,GAAc,EACd,IAAY,EACZ,IAAyC;IAEzC,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,CAAC;QAChC,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,IAAI,kDAAkD,EAAE,CAAC;YAClG,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACxC,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,IAAI,MAAM,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QAClG,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC5E,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AAChF,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,oBAAoB,CAAC,GAAc;IACjD,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,EAC7C,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,EAAE,CACnD,CAAC;IAEF,MAAM,SAAS,GAAG,yBAAyB,CAAC,4BAA4B,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACpF,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,WAAW,EAAE,CAAC,CAAC,WAAsC;KACtD,CAAC,CAAC,CAAC;IAEJ,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;IACrF,MAAM,CAAC,iBAAiB,CACtB,qBAAqB,EACrB,KAAK,EAAE,GAAG,EAA2B,EAAE,CACrC,kBAAkB,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CACvE,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * EVO-12 hosted MCP over HTTP + self-AS OAuth (mcp-wave pattern), exposing the
3
+ * h2a read-only tool surface for claude.ai enrollment. Core is dep-free; this
4
+ * lives in @sentropic/h2a-cli.
5
+ */
6
+ export { H2A_HOSTED_READONLY_TOOLS, hostedReadOnlyDescriptors, isHostedReadOnlyTool, toolTakesPrivateKey } from "./readonly-allowlist.js";
7
+ export { buildHostedMcpServer, dispatchHostedTool } from "./hosted-mcp-server.js";
8
+ export { createHostedApp, type HostedAppDeps } from "./app.js";
9
+ export { startHostedServer, buildHostedConfigFromEnv, type HostedEnv, type HostedConfig, type StartedHostedServer } from "./serve.js";
10
+ export { FileOAuthStore } from "./oauth/file-store.js";
11
+ export { SingleTenantOAuthProvider } from "./oauth/single-tenant-provider.js";
12
+ export { buildOAuthRoutes } from "./oauth/hono-oauth-router.js";
13
+ export { oauthConfigFromEnv, H2A_HOSTED_OAUTH_SCOPE, type H2AHostedOAuthConfig, type H2AHostedOAuthEnv } from "./oauth/config.js";
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtime/mcp-http/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,yBAAyB,EACzB,yBAAyB,EACzB,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAClF,OAAO,EAAE,eAAe,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAC/D,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACzB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACvB,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * EVO-12 hosted MCP over HTTP + self-AS OAuth (mcp-wave pattern), exposing the
3
+ * h2a read-only tool surface for claude.ai enrollment. Core is dep-free; this
4
+ * lives in @sentropic/h2a-cli.
5
+ */
6
+ export { H2A_HOSTED_READONLY_TOOLS, hostedReadOnlyDescriptors, isHostedReadOnlyTool, toolTakesPrivateKey } from "./readonly-allowlist.js";
7
+ export { buildHostedMcpServer, dispatchHostedTool } from "./hosted-mcp-server.js";
8
+ export { createHostedApp } from "./app.js";
9
+ export { startHostedServer, buildHostedConfigFromEnv } from "./serve.js";
10
+ export { FileOAuthStore } from "./oauth/file-store.js";
11
+ export { SingleTenantOAuthProvider } from "./oauth/single-tenant-provider.js";
12
+ export { buildOAuthRoutes } from "./oauth/hono-oauth-router.js";
13
+ export { oauthConfigFromEnv, H2A_HOSTED_OAUTH_SCOPE } from "./oauth/config.js";
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/runtime/mcp-http/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,yBAAyB,EACzB,yBAAyB,EACzB,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAClF,OAAO,EAAE,eAAe,EAAsB,MAAM,UAAU,CAAC;AAC/D,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EAIzB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EAGvB,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../src/runtime/mcp-http/main.ts"],"names":[],"mappings":""}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * EVO-12 hosted MCP — runnable entrypoint (Docker CMD / `node dist/runtime/mcp-http/main.js`).
3
+ * Reads the deploy env and serves the OAuth-gated read-only MCP over HTTP.
4
+ */
5
+ import { startHostedServer } from "./serve.js";
6
+ startHostedServer()
7
+ .then((s) => {
8
+ process.stderr.write(`h2a hosted MCP (EVO-12) listening on :${s.port}\n`);
9
+ })
10
+ .catch((e) => {
11
+ process.stderr.write(`h2a hosted MCP failed to start: ${e instanceof Error ? e.message : String(e)}\n`);
12
+ process.exit(1);
13
+ });
14
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../../../src/runtime/mcp-http/main.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/C,iBAAiB,EAAE;KAChB,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;IACV,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;AAC5E,CAAC,CAAC;KACD,KAAK,CAAC,CAAC,CAAU,EAAE,EAAE;IACpB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mCAAmC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACxG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * EVO-12 hosted OAuth — runtime config (ported from mcp-wave; decoupled from
3
+ * the Wave env type — takes a plain input object so it is unit-testable).
4
+ *
5
+ * Scope is read-only (`h2a:read`) — the hosted surface exposes only read tools
6
+ * (DEC-116 key custody; see ../readonly-allowlist).
7
+ */
8
+ export declare const H2A_HOSTED_OAUTH_SCOPE = "h2a:read";
9
+ export interface H2AHostedOAuthEnv {
10
+ PUBLIC_BASE_URL: string;
11
+ OAUTH_ISSUER_URL: string;
12
+ OAUTH_CONSENT_SECRET?: string;
13
+ OAUTH_ALLOWED_REDIRECT_URIS: string;
14
+ OAUTH_ACCESS_TOKEN_TTL_SECONDS: number;
15
+ OAUTH_REFRESH_TOKEN_TTL_SECONDS: number;
16
+ OAUTH_AUTH_CODE_TTL_SECONDS: number;
17
+ NODE_ENV?: string;
18
+ }
19
+ export interface H2AHostedOAuthConfig {
20
+ issuerUrl: URL;
21
+ publicBaseUrl: URL;
22
+ resourceServerUrl: URL;
23
+ resourceMetadataUrl: string;
24
+ consentSecret: string;
25
+ allowedRedirectUris: readonly string[];
26
+ accessTokenTtlSeconds: number;
27
+ refreshTokenTtlSeconds: number;
28
+ authCodeTtlSeconds: number;
29
+ nodeEnv: string;
30
+ }
31
+ export declare function parseOAuthCsv(value: string): string[];
32
+ export declare function oauthConfigFromEnv(env: H2AHostedOAuthEnv): H2AHostedOAuthConfig;
33
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../src/runtime/mcp-http/oauth/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,eAAO,MAAM,sBAAsB,aAAa,CAAC;AAEjD,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,2BAA2B,EAAE,MAAM,CAAC;IACpC,8BAA8B,EAAE,MAAM,CAAC;IACvC,+BAA+B,EAAE,MAAM,CAAC;IACxC,2BAA2B,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,GAAG,CAAC;IACf,aAAa,EAAE,GAAG,CAAC;IACnB,iBAAiB,EAAE,GAAG,CAAC;IACvB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAKrD;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,iBAAiB,GAAG,oBAAoB,CAe/E"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * EVO-12 hosted OAuth — runtime config (ported from mcp-wave; decoupled from
3
+ * the Wave env type — takes a plain input object so it is unit-testable).
4
+ *
5
+ * Scope is read-only (`h2a:read`) — the hosted surface exposes only read tools
6
+ * (DEC-116 key custody; see ../readonly-allowlist).
7
+ */
8
+ export const H2A_HOSTED_OAUTH_SCOPE = "h2a:read";
9
+ export function parseOAuthCsv(value) {
10
+ return value
11
+ .split(",")
12
+ .map((item) => item.trim())
13
+ .filter((item) => item.length > 0);
14
+ }
15
+ export function oauthConfigFromEnv(env) {
16
+ const publicBaseUrl = new URL(env.PUBLIC_BASE_URL);
17
+ const issuerUrl = new URL(env.OAUTH_ISSUER_URL);
18
+ return {
19
+ issuerUrl,
20
+ publicBaseUrl,
21
+ resourceServerUrl: new URL("/mcp", publicBaseUrl),
22
+ resourceMetadataUrl: new URL("/.well-known/oauth-protected-resource/mcp", publicBaseUrl).href,
23
+ consentSecret: env.OAUTH_CONSENT_SECRET ?? "local-dev-consent",
24
+ allowedRedirectUris: parseOAuthCsv(env.OAUTH_ALLOWED_REDIRECT_URIS),
25
+ accessTokenTtlSeconds: env.OAUTH_ACCESS_TOKEN_TTL_SECONDS,
26
+ refreshTokenTtlSeconds: env.OAUTH_REFRESH_TOKEN_TTL_SECONDS,
27
+ authCodeTtlSeconds: env.OAUTH_AUTH_CODE_TTL_SECONDS,
28
+ nodeEnv: env.NODE_ENV ?? "development"
29
+ };
30
+ }
31
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../../src/runtime/mcp-http/oauth/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,CAAC,MAAM,sBAAsB,GAAG,UAAU,CAAC;AA0BjD,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,OAAO,KAAK;SACT,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,GAAsB;IACvD,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACnD,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAChD,OAAO;QACL,SAAS;QACT,aAAa;QACb,iBAAiB,EAAE,IAAI,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC;QACjD,mBAAmB,EAAE,IAAI,GAAG,CAAC,2CAA2C,EAAE,aAAa,CAAC,CAAC,IAAI;QAC7F,aAAa,EAAE,GAAG,CAAC,oBAAoB,IAAI,mBAAmB;QAC9D,mBAAmB,EAAE,aAAa,CAAC,GAAG,CAAC,2BAA2B,CAAC;QACnE,qBAAqB,EAAE,GAAG,CAAC,8BAA8B;QACzD,sBAAsB,EAAE,GAAG,CAAC,+BAA+B;QAC3D,kBAAkB,EAAE,GAAG,CAAC,2BAA2B;QACnD,OAAO,EAAE,GAAG,CAAC,QAAQ,IAAI,aAAa;KACvC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function randomToken(byteLength?: number): string;
2
+ export declare function sha256Hex(value: string): string;
3
+ export declare function tokenHashPrefix(tokenHash: string): string;
4
+ export declare function timingSafeEqualString(a: string, b: string): boolean;
5
+ //# sourceMappingURL=crypto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../../../src/runtime/mcp-http/oauth/crypto.ts"],"names":[],"mappings":"AAKA,wBAAgB,WAAW,CAAC,UAAU,SAAK,GAAG,MAAM,CAEnD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAInE"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * EVO-12 hosted OAuth — token crypto helpers (ported from mcp-wave, generic).
3
+ */
4
+ import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
5
+ export function randomToken(byteLength = 32) {
6
+ return randomBytes(byteLength).toString("base64url");
7
+ }
8
+ export function sha256Hex(value) {
9
+ return createHash("sha256").update(value).digest("hex");
10
+ }
11
+ export function tokenHashPrefix(tokenHash) {
12
+ return tokenHash.slice(0, 12);
13
+ }
14
+ export function timingSafeEqualString(a, b) {
15
+ const left = Buffer.from(sha256Hex(a), "hex");
16
+ const right = Buffer.from(sha256Hex(b), "hex");
17
+ return timingSafeEqual(left, right);
18
+ }
19
+ //# sourceMappingURL=crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../../../src/runtime/mcp-http/oauth/crypto.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEvE,MAAM,UAAU,WAAW,CAAC,UAAU,GAAG,EAAE;IACzC,OAAO,WAAW,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,CAAS,EAAE,CAAS;IACxD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAC/C,OAAO,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACtC,CAAC"}
@@ -0,0 +1,40 @@
1
+ import type { OAuthRegisteredClientsStore } from "@modelcontextprotocol/sdk/server/auth/clients.js";
2
+ import type { OAuthClientInformationFull } from "@modelcontextprotocol/sdk/shared/auth.js";
3
+ export interface StoredAuthorizationCode {
4
+ codeHash: string;
5
+ clientId: string;
6
+ redirectUri: string;
7
+ codeChallenge: string;
8
+ scopes: string[];
9
+ resource: string;
10
+ createdAt: number;
11
+ expiresAt: number;
12
+ consumedAt?: number;
13
+ }
14
+ export interface StoredToken {
15
+ tokenHash: string;
16
+ tokenType: "access" | "refresh";
17
+ clientId: string;
18
+ scopes: string[];
19
+ resource: string;
20
+ issuedAt: number;
21
+ expiresAt: number;
22
+ revokedAt?: number;
23
+ parentRefreshTokenHash?: string;
24
+ }
25
+ export declare class FileOAuthStore implements OAuthRegisteredClientsStore {
26
+ readonly path: string;
27
+ private snapshot;
28
+ constructor(path: string);
29
+ load(): Promise<void>;
30
+ getClient(clientId: string): Promise<OAuthClientInformationFull | undefined>;
31
+ registerClient(client: OAuthClientInformationFull): Promise<OAuthClientInformationFull>;
32
+ putAuthorizationCode(code: string, record: Omit<StoredAuthorizationCode, "codeHash" | "consumedAt">): Promise<void>;
33
+ getAuthorizationCode(code: string, nowSeconds: number): Promise<StoredAuthorizationCode | undefined>;
34
+ consumeAuthorizationCode(code: string, nowSeconds: number): Promise<StoredAuthorizationCode | undefined>;
35
+ putToken(token: string, record: Omit<StoredToken, "tokenHash" | "revokedAt">): Promise<StoredToken>;
36
+ findToken(token: string): Promise<StoredToken | undefined>;
37
+ revokeToken(token: string, nowSeconds: number): Promise<void>;
38
+ private persist;
39
+ }
40
+ //# sourceMappingURL=file-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-store.d.ts","sourceRoot":"","sources":["../../../../src/runtime/mcp-http/oauth/file-store.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,kDAAkD,CAAC;AACpG,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,0CAA0C,CAAC;AAI3F,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,QAAQ,GAAG,SAAS,CAAC;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AASD,qBAAa,cAAe,YAAW,2BAA2B;IAGpD,QAAQ,CAAC,IAAI,EAAE,MAAM;IAFjC,OAAO,CAAC,QAAQ,CAA6E;gBAExE,IAAI,EAAE,MAAM;IAE3B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAkBrB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,0BAA0B,GAAG,SAAS,CAAC;IAI5E,cAAc,CAAC,MAAM,EAAE,0BAA0B,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAMvF,oBAAoB,CACxB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,IAAI,CAAC,uBAAuB,EAAE,UAAU,GAAG,YAAY,CAAC,GAC/D,OAAO,CAAC,IAAI,CAAC;IAMV,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,GAAG,SAAS,CAAC;IAMpG,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,GAAG,SAAS,CAAC;IASxG,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,WAAW,GAAG,WAAW,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC;IAQnG,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IAI1D,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAQrD,OAAO;CAmBtB"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * EVO-12 hosted OAuth — file-backed store for DCR clients, auth codes, tokens
3
+ * (ported from mcp-wave; generic, atomic-persist). Holds only OAuth artifacts
4
+ * (hashed codes/tokens) — never an h2a ed25519 private key.
5
+ */
6
+ import { mkdir, open, readFile, rename, writeFile } from "node:fs/promises";
7
+ import { dirname } from "node:path";
8
+ import { sha256Hex } from "./crypto.js";
9
+ export class FileOAuthStore {
10
+ path;
11
+ snapshot = { version: 1, clients: {}, authorizationCodes: {}, tokens: {} };
12
+ constructor(path) {
13
+ this.path = path;
14
+ }
15
+ async load() {
16
+ try {
17
+ const parsed = JSON.parse(await readFile(this.path, "utf8"));
18
+ this.snapshot = {
19
+ version: 1,
20
+ clients: parsed.clients ?? {},
21
+ authorizationCodes: parsed.authorizationCodes ?? {},
22
+ tokens: parsed.tokens ?? {}
23
+ };
24
+ }
25
+ catch (error) {
26
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
27
+ await this.persist();
28
+ return;
29
+ }
30
+ throw error;
31
+ }
32
+ }
33
+ async getClient(clientId) {
34
+ return this.snapshot.clients[clientId];
35
+ }
36
+ async registerClient(client) {
37
+ this.snapshot.clients[client.client_id] = client;
38
+ await this.persist();
39
+ return client;
40
+ }
41
+ async putAuthorizationCode(code, record) {
42
+ const codeHash = sha256Hex(code);
43
+ this.snapshot.authorizationCodes[codeHash] = { ...record, codeHash };
44
+ await this.persist();
45
+ }
46
+ async getAuthorizationCode(code, nowSeconds) {
47
+ const record = this.snapshot.authorizationCodes[sha256Hex(code)];
48
+ if (!record || record.consumedAt || record.expiresAt <= nowSeconds)
49
+ return undefined;
50
+ return record;
51
+ }
52
+ async consumeAuthorizationCode(code, nowSeconds) {
53
+ const codeHash = sha256Hex(code);
54
+ const record = this.snapshot.authorizationCodes[codeHash];
55
+ if (!record || record.consumedAt || record.expiresAt <= nowSeconds)
56
+ return undefined;
57
+ record.consumedAt = nowSeconds;
58
+ await this.persist();
59
+ return record;
60
+ }
61
+ async putToken(token, record) {
62
+ const tokenHash = sha256Hex(token);
63
+ const stored = { ...record, tokenHash };
64
+ this.snapshot.tokens[tokenHash] = stored;
65
+ await this.persist();
66
+ return stored;
67
+ }
68
+ async findToken(token) {
69
+ return this.snapshot.tokens[sha256Hex(token)];
70
+ }
71
+ async revokeToken(token, nowSeconds) {
72
+ const record = this.snapshot.tokens[sha256Hex(token)];
73
+ if (record && record.revokedAt === undefined) {
74
+ record.revokedAt = nowSeconds;
75
+ await this.persist();
76
+ }
77
+ }
78
+ async persist() {
79
+ await mkdir(dirname(this.path), { recursive: true });
80
+ const body = `${JSON.stringify(this.snapshot, null, 2)}\n`;
81
+ const tempPath = `${this.path}.${process.pid}.${Date.now()}.tmp`;
82
+ await writeFile(tempPath, body, { mode: 0o600 });
83
+ const handle = await open(tempPath, "r");
84
+ try {
85
+ await handle.sync();
86
+ }
87
+ catch (error) {
88
+ // Windows rejects fsync on some handles with EPERM, and exotic FUSE/CI
89
+ // filesystems return ENOSYS. The durability hint is best-effort; the
90
+ // rename below still provides atomic replace on every platform.
91
+ const code = error.code;
92
+ if (code !== "EPERM" && code !== "ENOSYS")
93
+ throw error;
94
+ }
95
+ finally {
96
+ await handle.close();
97
+ }
98
+ await rename(tempPath, this.path);
99
+ }
100
+ }
101
+ //# sourceMappingURL=file-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-store.js","sourceRoot":"","sources":["../../../../src/runtime/mcp-http/oauth/file-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { Hono } from "hono";
2
+ import { type H2AHostedOAuthConfig } from "./config.js";
3
+ import type { SingleTenantOAuthProvider } from "./single-tenant-provider.js";
4
+ export declare function buildOAuthRoutes(provider: SingleTenantOAuthProvider, oauth: H2AHostedOAuthConfig): Hono;
5
+ //# sourceMappingURL=hono-oauth-router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hono-oauth-router.d.ts","sourceRoot":"","sources":["../../../../src/runtime/mcp-http/oauth/hono-oauth-router.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAyC,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC/F,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAE7E,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,yBAAyB,EAAE,KAAK,EAAE,oBAAoB,GAAG,IAAI,CAsFvG"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * EVO-12 hosted OAuth — authorization-server + protected-resource routes
3
+ * (ported from mcp-wave). Standard endpoints (DCR, token+PKCE, revoke,
4
+ * well-known metadata) come from `@hono/mcp/auth`; only `/authorize` is custom
5
+ * (operator consent secret gate, single-tenant). resourceName = "h2a".
6
+ */
7
+ import { authenticateClient, clientRegistrationHandler, createOAuthMetadata, revokeHandler, tokenHandler, wellKnownRouter } from "@hono/mcp/auth";
8
+ import { OAuthError, ServerError } from "@modelcontextprotocol/sdk/server/auth/errors.js";
9
+ import { Hono } from "hono";
10
+ import { H2A_HOSTED_OAUTH_SCOPE as OAUTH_SCOPE } from "./config.js";
11
+ export function buildOAuthRoutes(provider, oauth) {
12
+ const sdkProvider = provider;
13
+ const clientsStore = provider.clientsStore;
14
+ const router = new Hono();
15
+ // RFC 8414: issuer identifier must equal the metadata-URL value (no trailing
16
+ // slash) — a URL object would normalize to a trailing slash that claude.ai rejects.
17
+ const issuer = oauth.issuerUrl.href.replace(/\/+$/, "");
18
+ const oauthMetadata = createOAuthMetadata({
19
+ provider: sdkProvider,
20
+ issuerUrl: issuer,
21
+ baseUrl: oauth.publicBaseUrl,
22
+ scopesSupported: [OAUTH_SCOPE]
23
+ });
24
+ router.route("/", wellKnownRouter({
25
+ oauthMetadata,
26
+ resourceServerUrl: oauth.resourceServerUrl,
27
+ scopesSupported: [OAUTH_SCOPE],
28
+ resourceName: "h2a"
29
+ }));
30
+ // Also serve PRM at the unsuffixed path (the bearerAuth 401 advertises it there).
31
+ router.get("/.well-known/oauth-protected-resource", (c) => c.json({
32
+ resource: oauth.resourceServerUrl.href,
33
+ authorization_servers: [issuer],
34
+ bearer_methods_supported: ["header"],
35
+ scopes_supported: [OAUTH_SCOPE],
36
+ resource_name: "h2a"
37
+ }));
38
+ router.post("/register", clientRegistrationHandler({ clientsStore }));
39
+ router.post("/token", authenticateClient({ clientsStore }), tokenHandler(sdkProvider));
40
+ router.post("/revoke", authenticateClient({ clientsStore }), revokeHandler(sdkProvider));
41
+ router.on(["GET", "POST"], "/authorize", async (c) => {
42
+ c.header("Cache-Control", "no-store");
43
+ const raw = c.req.method === "POST"
44
+ ? (await c.req.parseBody())
45
+ : c.req.query();
46
+ const clientId = raw["client_id"];
47
+ if (!clientId) {
48
+ return c.json({ error: "invalid_request", error_description: "missing client_id" }, 400);
49
+ }
50
+ const client = await provider.clientsStore.getClient(clientId);
51
+ if (!client) {
52
+ return c.json({ error: "invalid_client", error_description: "unknown client_id" }, 400);
53
+ }
54
+ const redirectUri = raw["redirect_uri"] ?? client.redirect_uris[0] ?? "";
55
+ const scopeRaw = raw["scope"];
56
+ const stateRaw = raw["state"];
57
+ const resourceRaw = raw["resource"];
58
+ const params = {
59
+ redirectUri,
60
+ codeChallenge: raw["code_challenge"] ?? "",
61
+ ...(scopeRaw !== undefined && { scopes: scopeRaw.split(" ") }),
62
+ ...(stateRaw !== undefined && { state: stateRaw }),
63
+ ...(resourceRaw !== undefined && { resource: new URL(resourceRaw) })
64
+ };
65
+ try {
66
+ const consentSecret = raw["consent_secret"];
67
+ const outcome = await provider.authorizeRequest(client, params, {
68
+ method: c.req.method,
69
+ ...(consentSecret !== undefined && { consentSecret })
70
+ });
71
+ if (outcome.kind === "consent") {
72
+ return c.html(outcome.html, outcome.status);
73
+ }
74
+ return c.redirect(outcome.location, 302);
75
+ }
76
+ catch (e) {
77
+ const err = e instanceof OAuthError ? e : new ServerError("Internal Server Error");
78
+ return c.json(err.toResponseObject(), err instanceof ServerError ? 500 : 400);
79
+ }
80
+ });
81
+ return router;
82
+ }
83
+ //# sourceMappingURL=hono-oauth-router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hono-oauth-router.js","sourceRoot":"","sources":["../../../../src/runtime/mcp-http/oauth/hono-oauth-router.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * EVO-12 hosted OAuth — redirect-uri allow checks (ported from mcp-wave;
3
+ * decoupled from the Wave env type — takes a plain nodeEnv string).
4
+ *
5
+ * claude.ai's connector uses fixed redirect URIs
6
+ * (https://claude.ai|claude.com/api/mcp/auth_callback) — those must be in
7
+ * `allowedRedirectUris`. Loopback is allowed only outside production (local dev).
8
+ */
9
+ export declare function redirectUriAllowed(redirectUri: string, allowedRedirectUris: readonly string[], nodeEnv: string): boolean;
10
+ export declare function allRedirectUrisAllowed(redirectUris: readonly string[], allowedRedirectUris: readonly string[], nodeEnv: string): boolean;
11
+ //# sourceMappingURL=redirect-uri.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redirect-uri.d.ts","sourceRoot":"","sources":["../../../../src/runtime/mcp-http/oauth/redirect-uri.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EACnB,mBAAmB,EAAE,SAAS,MAAM,EAAE,EACtC,OAAO,EAAE,MAAM,GACd,OAAO,CAiBT;AAED,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,SAAS,MAAM,EAAE,EAC/B,mBAAmB,EAAE,SAAS,MAAM,EAAE,EACtC,OAAO,EAAE,MAAM,GACd,OAAO,CAET"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * EVO-12 hosted OAuth — redirect-uri allow checks (ported from mcp-wave;
3
+ * decoupled from the Wave env type — takes a plain nodeEnv string).
4
+ *
5
+ * claude.ai's connector uses fixed redirect URIs
6
+ * (https://claude.ai|claude.com/api/mcp/auth_callback) — those must be in
7
+ * `allowedRedirectUris`. Loopback is allowed only outside production (local dev).
8
+ */
9
+ const LOOPBACK_HOSTS = new Set(["localhost", "127.0.0.1", "::1"]);
10
+ export function redirectUriAllowed(redirectUri, allowedRedirectUris, nodeEnv) {
11
+ let parsed;
12
+ try {
13
+ parsed = new URL(redirectUri);
14
+ }
15
+ catch {
16
+ return false;
17
+ }
18
+ if (allowedRedirectUris.includes(parsed.href)) {
19
+ return true;
20
+ }
21
+ if (nodeEnv !== "production" && LOOPBACK_HOSTS.has(parsed.hostname)) {
22
+ return parsed.protocol === "http:" || parsed.protocol === "https:";
23
+ }
24
+ return false;
25
+ }
26
+ export function allRedirectUrisAllowed(redirectUris, allowedRedirectUris, nodeEnv) {
27
+ return redirectUris.every((uri) => redirectUriAllowed(uri, allowedRedirectUris, nodeEnv));
28
+ }
29
+ //# sourceMappingURL=redirect-uri.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redirect-uri.js","sourceRoot":"","sources":["../../../../src/runtime/mcp-http/oauth/redirect-uri.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC;AAElE,MAAM,UAAU,kBAAkB,CAChC,WAAmB,EACnB,mBAAsC,EACtC,OAAe;IAEf,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,mBAAmB,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,OAAO,KAAK,YAAY,IAAI,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpE,OAAO,MAAM,CAAC,QAAQ,KAAK,OAAO,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAC;IACrE,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,YAA+B,EAC/B,mBAAsC,EACtC,OAAe;IAEf,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,kBAAkB,CAAC,GAAG,EAAE,mBAAmB,EAAE,OAAO,CAAC,CAAC,CAAC;AAC5F,CAAC"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * EVO-12 hosted OAuth — single-tenant authorization server (ported from
3
+ * mcp-wave). Implements the MCP SDK OAuthServerProvider surface: DCR client
4
+ * registration (redirect-uri allowlisted), operator-consent authorize,
5
+ * auth-code + PKCE exchange, refresh, access-token verify/revoke. Scope is
6
+ * read-only `h2a:read`. The OAuth tokens grant access to the read-only MCP tool
7
+ * surface only — never to any signing tool / private key (DEC-116). The
8
+ * client never receives an h2a private key.
9
+ */
10
+ import type { OAuthRegisteredClientsStore } from "@modelcontextprotocol/sdk/server/auth/clients.js";
11
+ import type { AuthorizationParams } from "@modelcontextprotocol/sdk/server/auth/provider.js";
12
+ import type { AuthInfo } from "@modelcontextprotocol/sdk/server/auth/types.js";
13
+ import type { OAuthClientInformationFull, OAuthTokenRevocationRequest, OAuthTokens } from "@modelcontextprotocol/sdk/shared/auth.js";
14
+ import type { FileOAuthStore } from "./file-store.js";
15
+ export type AuthorizeOutcome = {
16
+ kind: "consent";
17
+ status: 200 | 401;
18
+ html: string;
19
+ } | {
20
+ kind: "redirect";
21
+ location: string;
22
+ };
23
+ interface ProviderOptions {
24
+ store: FileOAuthStore;
25
+ nodeEnv: string;
26
+ issuerUrl: URL;
27
+ publicBaseUrl: URL;
28
+ resourceServerUrl: URL;
29
+ consentSecret: string;
30
+ allowedRedirectUris: readonly string[];
31
+ authCodeTtlSeconds: number;
32
+ accessTokenTtlSeconds: number;
33
+ refreshTokenTtlSeconds: number;
34
+ nowSeconds?: () => number;
35
+ }
36
+ interface IssueCodeParams {
37
+ redirectUri: string;
38
+ codeChallenge: string;
39
+ scopes: string[];
40
+ resource?: URL;
41
+ state?: string;
42
+ }
43
+ type WideClientsStore = Omit<OAuthRegisteredClientsStore, "registerClient"> & {
44
+ registerClient?(client: OAuthClientInformationFull): OAuthClientInformationFull | Promise<OAuthClientInformationFull>;
45
+ };
46
+ export declare class SingleTenantOAuthProvider {
47
+ private readonly opts;
48
+ readonly clientsStore: WideClientsStore;
49
+ constructor(opts: ProviderOptions);
50
+ private nowSeconds;
51
+ authorizeRequest(client: OAuthClientInformationFull, params: AuthorizationParams, input: {
52
+ method: string;
53
+ consentSecret?: string;
54
+ }): Promise<AuthorizeOutcome>;
55
+ issueAuthorizationCode(client: OAuthClientInformationFull, params: IssueCodeParams): Promise<string>;
56
+ private renderConsentForm;
57
+ challengeForAuthorizationCode(_client: OAuthClientInformationFull, authorizationCode: string): Promise<string>;
58
+ exchangeAuthorizationCode(client: OAuthClientInformationFull, authorizationCode: string, _codeVerifier?: string, redirectUri?: string, resource?: URL): Promise<OAuthTokens>;
59
+ exchangeRefreshToken(client: OAuthClientInformationFull, refreshToken: string, scopes?: string[], resource?: URL): Promise<OAuthTokens>;
60
+ verifyAccessToken(token: string): Promise<AuthInfo>;
61
+ revokeToken(_client: OAuthClientInformationFull, request: OAuthTokenRevocationRequest): Promise<void>;
62
+ issueTokensForTests(client: OAuthClientInformationFull): Promise<OAuthTokens>;
63
+ private issueTokens;
64
+ private normalizeScopes;
65
+ private normalizeResource;
66
+ }
67
+ export {};
68
+ //# sourceMappingURL=single-tenant-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"single-tenant-provider.d.ts","sourceRoot":"","sources":["../../../../src/runtime/mcp-http/oauth/single-tenant-provider.ts"],"names":[],"mappings":"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"}