@honua/mcp-server 0.0.10-alpha.0 → 0.1.0-beta.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 (176) hide show
  1. package/README.md +259 -15
  2. package/certification/geospatial-mcp-schemas/PROVENANCE.md +41 -0
  3. package/certification/geospatial-mcp-schemas/README.md +90 -0
  4. package/certification/geospatial-mcp-schemas/common/geoprocessing-error.schema.json +45 -0
  5. package/certification/geospatial-mcp-schemas/conformance/manifest.schema.json +79 -0
  6. package/certification/geospatial-mcp-schemas/index.json +390 -0
  7. package/certification/geospatial-mcp-schemas/resources/app-package.schema.json +20 -0
  8. package/certification/geospatial-mcp-schemas/resources/app-template.schema.json +15 -0
  9. package/certification/geospatial-mcp-schemas/resources/artifact.schema.json +69 -0
  10. package/certification/geospatial-mcp-schemas/resources/deployment.schema.json +27 -0
  11. package/certification/geospatial-mcp-schemas/resources/map-package.schema.json +21 -0
  12. package/certification/geospatial-mcp-schemas/resources/map-template.schema.json +15 -0
  13. package/certification/geospatial-mcp-schemas/resources/provenance.schema.json +50 -0
  14. package/certification/geospatial-mcp-schemas/resources/published-service.schema.json +21 -0
  15. package/certification/geospatial-mcp-schemas/resources/result-package.schema.json +64 -0
  16. package/certification/geospatial-mcp-schemas/resources/style.schema.json +12 -0
  17. package/certification/geospatial-mcp-schemas/resources/theme.schema.json +12 -0
  18. package/certification/geospatial-mcp-schemas/resources/workspace.schema.json +63 -0
  19. package/certification/geospatial-mcp-schemas/tools/apply_style_preset.schema.json +27 -0
  20. package/certification/geospatial-mcp-schemas/tools/buffer_features.schema.json +60 -0
  21. package/certification/geospatial-mcp-schemas/tools/cancel_job.schema.json +15 -0
  22. package/certification/geospatial-mcp-schemas/tools/clarify_intent.schema.json +69 -0
  23. package/certification/geospatial-mcp-schemas/tools/compose_mixed_protocol_map.schema.json +21 -0
  24. package/certification/geospatial-mcp-schemas/tools/create_app_package.schema.json +33 -0
  25. package/certification/geospatial-mcp-schemas/tools/create_map_package.schema.json +41 -0
  26. package/certification/geospatial-mcp-schemas/tools/edit_features.schema.json +74 -0
  27. package/certification/geospatial-mcp-schemas/tools/execute_plan.schema.json +64 -0
  28. package/certification/geospatial-mcp-schemas/tools/export_dataset.schema.json +60 -0
  29. package/certification/geospatial-mcp-schemas/tools/geocode_address.schema.json +36 -0
  30. package/certification/geospatial-mcp-schemas/tools/geocode_addresses.schema.json +34 -0
  31. package/certification/geospatial-mcp-schemas/tools/get_style.schema.json +40 -0
  32. package/certification/geospatial-mcp-schemas/tools/ground_candidates.schema.json +66 -0
  33. package/certification/geospatial-mcp-schemas/tools/ingest_dataset.schema.json +45 -0
  34. package/certification/geospatial-mcp-schemas/tools/join_features.schema.json +73 -0
  35. package/certification/geospatial-mcp-schemas/tools/list_capabilities.schema.json +21 -0
  36. package/certification/geospatial-mcp-schemas/tools/list_layers.schema.json +14 -0
  37. package/certification/geospatial-mcp-schemas/tools/overlay_features.schema.json +53 -0
  38. package/certification/geospatial-mcp-schemas/tools/plan_analysis.schema.json +19 -0
  39. package/certification/geospatial-mcp-schemas/tools/preview_app_package.schema.json +15 -0
  40. package/certification/geospatial-mcp-schemas/tools/preview_map_package.schema.json +17 -0
  41. package/certification/geospatial-mcp-schemas/tools/preview_package.schema.json +40 -0
  42. package/certification/geospatial-mcp-schemas/tools/propose_operation.schema.json +28 -0
  43. package/certification/geospatial-mcp-schemas/tools/publish_result.schema.json +29 -0
  44. package/certification/geospatial-mcp-schemas/tools/publish_service.schema.json +59 -0
  45. package/certification/geospatial-mcp-schemas/tools/query_features.schema.json +74 -0
  46. package/certification/geospatial-mcp-schemas/tools/refine_map_package.schema.json +22 -0
  47. package/certification/geospatial-mcp-schemas/tools/render_map.schema.json +60 -0
  48. package/certification/geospatial-mcp-schemas/tools/reproject_features.schema.json +49 -0
  49. package/certification/geospatial-mcp-schemas/tools/resolve_entity.schema.json +30 -0
  50. package/certification/geospatial-mcp-schemas/tools/solve_route.schema.json +39 -0
  51. package/certification/geospatial-mcp-schemas/tools/summarize_statistics.schema.json +71 -0
  52. package/certification/geospatial-mcp-schemas/tools/validate_package.schema.json +35 -0
  53. package/certification/geospatial-mcp-schemas/tools/validate_plan.schema.json +61 -0
  54. package/dist/src/capability.d.ts +48 -0
  55. package/dist/src/capability.d.ts.map +1 -0
  56. package/dist/src/capability.js +44 -0
  57. package/dist/src/certification/census-data.d.ts +33 -0
  58. package/dist/src/certification/census-data.d.ts.map +1 -0
  59. package/dist/src/certification/census-data.js +506 -0
  60. package/dist/src/certification/census-fixture-client.d.ts +7 -0
  61. package/dist/src/certification/census-fixture-client.d.ts.map +1 -0
  62. package/dist/src/certification/census-fixture-client.js +226 -0
  63. package/dist/src/certification/certifier.d.ts +125 -0
  64. package/dist/src/certification/certifier.d.ts.map +1 -0
  65. package/dist/src/certification/certifier.js +455 -0
  66. package/dist/src/certification/cli.d.ts +3 -0
  67. package/dist/src/certification/cli.d.ts.map +1 -0
  68. package/dist/src/certification/cli.js +63 -0
  69. package/dist/src/certification/contracts.d.ts +103 -0
  70. package/dist/src/certification/contracts.d.ts.map +1 -0
  71. package/dist/src/certification/contracts.js +245 -0
  72. package/dist/src/certification/fixture-client.d.ts +4 -0
  73. package/dist/src/certification/fixture-client.d.ts.map +1 -0
  74. package/dist/src/certification/fixture-client.js +113 -0
  75. package/dist/src/certification/fixtures.d.ts +45 -0
  76. package/dist/src/certification/fixtures.d.ts.map +1 -0
  77. package/dist/src/certification/fixtures.js +92 -0
  78. package/dist/src/certification/json-schema.d.ts +71 -0
  79. package/dist/src/certification/json-schema.d.ts.map +1 -0
  80. package/dist/src/certification/json-schema.js +172 -0
  81. package/dist/src/certification/lifecycle.d.ts +14 -0
  82. package/dist/src/certification/lifecycle.d.ts.map +1 -0
  83. package/dist/src/certification/lifecycle.js +326 -0
  84. package/dist/src/certification/mock-upstream.d.ts +29 -0
  85. package/dist/src/certification/mock-upstream.d.ts.map +1 -0
  86. package/dist/src/certification/mock-upstream.js +96 -0
  87. package/dist/src/certification/operator-catalog.d.ts +90 -0
  88. package/dist/src/certification/operator-catalog.d.ts.map +1 -0
  89. package/dist/src/certification/operator-catalog.js +650 -0
  90. package/dist/src/certification/report.d.ts +4 -0
  91. package/dist/src/certification/report.d.ts.map +1 -0
  92. package/dist/src/certification/report.js +103 -0
  93. package/dist/src/certification/run.d.ts +28 -0
  94. package/dist/src/certification/run.d.ts.map +1 -0
  95. package/dist/src/certification/run.js +32 -0
  96. package/dist/src/certification/schema-index.d.ts +94 -0
  97. package/dist/src/certification/schema-index.d.ts.map +1 -0
  98. package/dist/src/certification/schema-index.js +109 -0
  99. package/dist/src/certification/target.d.ts +48 -0
  100. package/dist/src/certification/target.d.ts.map +1 -0
  101. package/dist/src/certification/target.js +219 -0
  102. package/dist/src/eval/cli.d.ts +3 -0
  103. package/dist/src/eval/cli.d.ts.map +1 -0
  104. package/dist/src/eval/cli.js +118 -0
  105. package/dist/src/eval/corpus.d.ts +34 -0
  106. package/dist/src/eval/corpus.d.ts.map +1 -0
  107. package/dist/src/eval/corpus.js +150 -0
  108. package/dist/src/eval/drivers/anthropic.d.ts +14 -0
  109. package/dist/src/eval/drivers/anthropic.d.ts.map +1 -0
  110. package/dist/src/eval/drivers/anthropic.js +120 -0
  111. package/dist/src/eval/drivers/bedrock.d.ts +54 -0
  112. package/dist/src/eval/drivers/bedrock.d.ts.map +1 -0
  113. package/dist/src/eval/drivers/bedrock.js +178 -0
  114. package/dist/src/eval/drivers/deterministic.d.ts +17 -0
  115. package/dist/src/eval/drivers/deterministic.d.ts.map +1 -0
  116. package/dist/src/eval/drivers/deterministic.js +64 -0
  117. package/dist/src/eval/drivers/index.d.ts +34 -0
  118. package/dist/src/eval/drivers/index.d.ts.map +1 -0
  119. package/dist/src/eval/drivers/index.js +74 -0
  120. package/dist/src/eval/drivers/openai.d.ts +14 -0
  121. package/dist/src/eval/drivers/openai.d.ts.map +1 -0
  122. package/dist/src/eval/drivers/openai.js +136 -0
  123. package/dist/src/eval/grade.d.ts +14 -0
  124. package/dist/src/eval/grade.d.ts.map +1 -0
  125. package/dist/src/eval/grade.js +75 -0
  126. package/dist/src/eval/northstar-corpus.d.ts +3 -0
  127. package/dist/src/eval/northstar-corpus.d.ts.map +1 -0
  128. package/dist/src/eval/northstar-corpus.js +194 -0
  129. package/dist/src/eval/operator-corpus.d.ts +3 -0
  130. package/dist/src/eval/operator-corpus.d.ts.map +1 -0
  131. package/dist/src/eval/operator-corpus.js +193 -0
  132. package/dist/src/eval/report.d.ts +109 -0
  133. package/dist/src/eval/report.d.ts.map +1 -0
  134. package/dist/src/eval/report.js +133 -0
  135. package/dist/src/eval/runner.d.ts +28 -0
  136. package/dist/src/eval/runner.d.ts.map +1 -0
  137. package/dist/src/eval/runner.js +130 -0
  138. package/dist/src/eval/standalone-corpus.d.ts +3 -0
  139. package/dist/src/eval/standalone-corpus.d.ts.map +1 -0
  140. package/dist/src/eval/standalone-corpus.js +699 -0
  141. package/dist/src/eval/types.d.ts +118 -0
  142. package/dist/src/eval/types.d.ts.map +1 -0
  143. package/dist/src/eval/types.js +10 -0
  144. package/dist/src/helpers.d.ts +11 -0
  145. package/dist/src/helpers.d.ts.map +1 -1
  146. package/dist/src/helpers.js +22 -0
  147. package/dist/src/index.d.ts +31 -0
  148. package/dist/src/index.d.ts.map +1 -1
  149. package/dist/src/index.js +50 -4
  150. package/dist/src/provenance.d.ts +44 -0
  151. package/dist/src/provenance.d.ts.map +1 -0
  152. package/dist/src/provenance.js +37 -0
  153. package/dist/src/proxy.d.ts +46 -0
  154. package/dist/src/proxy.d.ts.map +1 -0
  155. package/dist/src/proxy.js +124 -0
  156. package/dist/src/resources/styles.d.ts +29 -0
  157. package/dist/src/resources/styles.d.ts.map +1 -0
  158. package/dist/src/resources/styles.js +76 -0
  159. package/dist/src/styles.d.ts +112 -0
  160. package/dist/src/styles.d.ts.map +1 -0
  161. package/dist/src/styles.js +144 -0
  162. package/dist/src/tools/apply-style-preset.d.ts +27 -0
  163. package/dist/src/tools/apply-style-preset.d.ts.map +1 -0
  164. package/dist/src/tools/apply-style-preset.js +41 -0
  165. package/dist/src/tools/count-features.d.ts.map +1 -1
  166. package/dist/src/tools/count-features.js +5 -4
  167. package/dist/src/tools/get-extent.d.ts.map +1 -1
  168. package/dist/src/tools/get-extent.js +6 -4
  169. package/dist/src/tools/get-style.d.ts +24 -0
  170. package/dist/src/tools/get-style.d.ts.map +1 -0
  171. package/dist/src/tools/get-style.js +39 -0
  172. package/dist/src/tools/list-services.d.ts.map +1 -1
  173. package/dist/src/tools/list-services.js +16 -1
  174. package/dist/src/tools/query-features.d.ts.map +1 -1
  175. package/dist/src/tools/query-features.js +4 -1
  176. package/package.json +28 -4
@@ -0,0 +1,103 @@
1
+ /** Render a human-readable Markdown summary of a certification report. */
2
+ export function renderMarkdown(report) {
3
+ const s = report.summary;
4
+ const status = s.pass ? "✅ PASS" : "❌ FAIL";
5
+ const lines = [];
6
+ lines.push(`# MCP Certification — ${report.server.name} v${report.server.version}`);
7
+ lines.push("");
8
+ lines.push(`**Result:** ${status}`);
9
+ lines.push("");
10
+ lines.push(`- Generated: \`${report.generatedAt}\``);
11
+ lines.push(`- Certified surface: ${report.protocol.surface}`);
12
+ lines.push(`- Target mode: \`${report.protocol.targetMode}\``);
13
+ lines.push(`- MCP transport: \`${report.protocol.mcpTransport}\``);
14
+ lines.push(`- Backend: \`${report.protocol.backend}\`${report.protocol.honuaTransport ? ` (Honua transport: \`${report.protocol.honuaTransport}\`)` : ""}`);
15
+ lines.push(`- Standard: \`${report.standard.source}\` (index ${report.standard.indexDate}, ${report.standard.dialect})`);
16
+ lines.push("");
17
+ const p = report.provenance;
18
+ lines.push("## Provenance");
19
+ lines.push("");
20
+ lines.push("| Field | Value |");
21
+ lines.push("| --- | --- |");
22
+ lines.push(`| Target | ${p.targetUrl} |`);
23
+ lines.push(`| Auth mode | \`${p.authMode}\` |`);
24
+ lines.push(`| Negotiated protocol | \`${p.protocolVersion ?? "n/a"}\` |`);
25
+ lines.push(`| Tools advertised | ${p.toolCount} |`);
26
+ lines.push(`| Suite git SHA | \`${p.suiteGitSha}\` (${p.suiteGitShaSource}) |`);
27
+ lines.push(`| Generated | \`${report.generatedAt}\` |`);
28
+ lines.push("");
29
+ lines.push("## Summary");
30
+ lines.push("");
31
+ lines.push("| Metric | Value |");
32
+ lines.push("| --- | ---: |");
33
+ lines.push(`| Tools discovered | ${s.toolsDiscovered} |`);
34
+ lines.push(`| Tools with valid inputSchema | ${s.toolsSchemaValid} / ${s.toolsDiscovered} |`);
35
+ lines.push(`| Tools conformance-checked | ${s.toolsConformanceChecked} |`);
36
+ lines.push(`| Tools conformant | ${s.toolsConformant} / ${s.toolsConformanceChecked} |`);
37
+ lines.push(`| Tools round-tripped | ${s.toolsRoundTripped} |`);
38
+ lines.push(`| Tools with output-schema validated | ${s.toolsOutputValidated} |`);
39
+ lines.push(`| Resources discovered | ${s.resourcesDiscovered} |`);
40
+ lines.push(`| Prompts discovered | ${s.promptsDiscovered} |`);
41
+ lines.push(`| Contracts checked | ${s.contractsPassed} / ${s.contractsChecked} passed |`);
42
+ lines.push(`| Contracts skipped | ${s.contractsSkipped} |`);
43
+ lines.push(`| Known gaps | ${s.knownGaps} |`);
44
+ lines.push(`| Failures | ${s.failures} |`);
45
+ lines.push("");
46
+ lines.push("## Tools");
47
+ lines.push("");
48
+ lines.push("| Tool | Schema | Standard | Conformant | Read-only | Round-trip | Output schema |");
49
+ lines.push("| --- | :---: | --- | :---: | :---: | :---: | :---: |");
50
+ for (const t of report.tools) {
51
+ const conformant = t.conformant === null ? "n/a" : t.conformant ? "yes" : "**NO**";
52
+ const outputCol = t.structuredOutputValidated === true
53
+ ? "validated"
54
+ : t.structuredOutputValidated === false
55
+ ? "**INVALID**"
56
+ : t.hasOutputSchema
57
+ ? "advertised"
58
+ : "no";
59
+ lines.push(`| \`${t.name}\` | ${t.schemaValid ? "valid" : "**invalid**"} | ${t.standardName ?? "—"} | ${conformant} | ${t.readOnly ? "yes" : "no"} | ${t.roundTrip} | ${outputCol} |`);
60
+ }
61
+ lines.push("");
62
+ lines.push("## Contracts");
63
+ lines.push("");
64
+ lines.push("| Contract | Target | Status | Detail |");
65
+ lines.push("| --- | --- | :---: | --- |");
66
+ for (const c of report.contracts) {
67
+ const icon = c.status === "passed" ? "✅" : c.status === "failed" ? "❌" : "➖";
68
+ lines.push(`| \`${c.contract}\` | \`${c.target}\` | ${icon} ${c.status} | ${c.detail} |`);
69
+ }
70
+ lines.push("");
71
+ const toolErrors = report.tools.filter((t) => t.errors.length > 0);
72
+ if (toolErrors.length > 0) {
73
+ lines.push("### Tool failures");
74
+ lines.push("");
75
+ for (const t of toolErrors) {
76
+ lines.push(`- \`${t.name}\``);
77
+ for (const e of t.errors) {
78
+ lines.push(` - ${e}`);
79
+ }
80
+ }
81
+ lines.push("");
82
+ }
83
+ if (report.resources.length > 0) {
84
+ lines.push("## Resources");
85
+ lines.push("");
86
+ for (const r of report.resources) {
87
+ lines.push(`- \`${r.name}\` — \`${r.uri}\``);
88
+ }
89
+ lines.push("");
90
+ }
91
+ if (report.knownGaps.length > 0) {
92
+ lines.push("## Known gaps");
93
+ lines.push("");
94
+ lines.push("These are standard capabilities not yet advertised as discrete tools, or advertised tools outside the standard. They are recorded, not failed.");
95
+ lines.push("");
96
+ for (const g of report.knownGaps) {
97
+ const family = g.family ? ` _(${g.family})_` : "";
98
+ lines.push(`- **${g.kind}** \`${g.name}\`${family} — ${g.detail}`);
99
+ }
100
+ lines.push("");
101
+ }
102
+ return `${lines.join("\n")}\n`;
103
+ }
@@ -0,0 +1,28 @@
1
+ import { type CertificationReport } from "./certifier.js";
2
+ import { type CertificationTarget } from "./target.js";
3
+ /**
4
+ * Programmatic certification runner.
5
+ *
6
+ * The certifier connects to one of three targets (selected by
7
+ * `HONUA_MCP_CERT_TARGET`) and certifies the honua `/mcp` OPERATOR surface — the
8
+ * real ~20-tool catalog with output schemas, structured errors, cursor
9
+ * pagination, and an auth boundary — never the retired 9-tool static server:
10
+ *
11
+ * - `offline` (default): an in-process streamable-HTTP mock of `/mcp`.
12
+ * Deterministic, zero network, gates every PR.
13
+ * - `remote` : a live `/mcp` (HONUA_MCP_REMOTE_URL + auth). workflow_dispatch.
14
+ * - `stdio-proxy` : the `honua-mcp-proxy` binary against an upstream, over stdio.
15
+ */
16
+ export interface RunOptions {
17
+ env?: NodeJS.ProcessEnv;
18
+ }
19
+ export declare function runCertification(options?: RunOptions): Promise<CertificationReport>;
20
+ /** Certify an already-opened target, closing it when done. */
21
+ export declare function certifyTarget(target: CertificationTarget, env?: NodeJS.ProcessEnv): Promise<CertificationReport>;
22
+ export interface ArtifactPaths {
23
+ json: string;
24
+ markdown: string;
25
+ }
26
+ /** Write the JSON + Markdown certification artifacts to disk. */
27
+ export declare function writeArtifacts(report: CertificationReport, paths: ArtifactPaths): void;
28
+ //# sourceMappingURL=run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/certification/run.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,mBAAmB,EAAW,MAAM,gBAAgB,CAAC;AAEnE,OAAO,EAAE,KAAK,mBAAmB,EAA2B,MAAM,aAAa,CAAC;AAEhF;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAED,wBAAsB,gBAAgB,CAAC,OAAO,GAAE,UAAe,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAI7F;AAED,8DAA8D;AAC9D,wBAAsB,aAAa,CACjC,MAAM,EAAE,mBAAmB,EAC3B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAAC,mBAAmB,CAAC,CAe9B;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,iEAAiE;AACjE,wBAAgB,cAAc,CAAC,MAAM,EAAE,mBAAmB,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI,CAGtF"}
@@ -0,0 +1,32 @@
1
+ import { writeFileSync } from "node:fs";
2
+ import { certify } from "./certifier.js";
3
+ import { renderMarkdown } from "./report.js";
4
+ import { openCertificationTarget } from "./target.js";
5
+ export async function runCertification(options = {}) {
6
+ const env = options.env ?? process.env;
7
+ const target = await openCertificationTarget(env);
8
+ return certifyTarget(target, env);
9
+ }
10
+ /** Certify an already-opened target, closing it when done. */
11
+ export async function certifyTarget(target, env = process.env) {
12
+ try {
13
+ return await certify({
14
+ client: target.client,
15
+ targetMode: target.mode,
16
+ backend: target.backend,
17
+ surface: target.serverLabel,
18
+ honuaTransport: target.honuaTransport,
19
+ authMode: target.authMode,
20
+ connectUnauthenticated: target.supportsUnauthenticatedPass ? () => target.connectUnauthenticated() : undefined,
21
+ env,
22
+ });
23
+ }
24
+ finally {
25
+ await target.close();
26
+ }
27
+ }
28
+ /** Write the JSON + Markdown certification artifacts to disk. */
29
+ export function writeArtifacts(report, paths) {
30
+ writeFileSync(paths.json, `${JSON.stringify(report, null, 2)}\n`, "utf8");
31
+ writeFileSync(paths.markdown, renderMarkdown(report), "utf8");
32
+ }
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Loader for the vendored geospatial-mcp JSON Schemas and their index.
3
+ *
4
+ * The schemas are vendored under `certification/geospatial-mcp-schemas/` (see
5
+ * that directory's `PROVENANCE.md`). Loading is filesystem-only and fully
6
+ * deterministic — no network access and no model/API calls.
7
+ */
8
+ export interface StandardToolEntry {
9
+ /** Bare taxonomy.md tool name (e.g. `query_features`). */
10
+ standardName: string;
11
+ /** Name the reference implementation advertises, or null when unimplemented. */
12
+ referenceToolName: string | null;
13
+ family: string;
14
+ /** Relative path of the schema file, e.g. `tools/query_features.schema.json`. */
15
+ schema: string;
16
+ implementationStatus: "implemented" | "known-gap";
17
+ notes?: string;
18
+ }
19
+ export interface StandardResourceEntry {
20
+ family: string;
21
+ uriForm: string;
22
+ schema: string;
23
+ shapeFidelity: string;
24
+ implementationStatus?: "implemented" | "known-gap";
25
+ notes?: string;
26
+ }
27
+ export interface SchemaIndex {
28
+ title: string;
29
+ date: string;
30
+ dialect: string;
31
+ tools: StandardToolEntry[];
32
+ resources: StandardResourceEntry[];
33
+ common: {
34
+ name: string;
35
+ schema: string;
36
+ role: string;
37
+ }[];
38
+ conformance?: {
39
+ name: string;
40
+ schema: string;
41
+ role: string;
42
+ }[];
43
+ }
44
+ /**
45
+ * Reference-implementation aliasing decision (SDK-local, NOT part of the
46
+ * vendored standard): the honua-server /mcp surface advertises
47
+ * `honua_dry_run_plan` alongside `honua_validate_plan`, both driven by the same
48
+ * partial-plan input schema (see the `validate_plan` entry's notes in the
49
+ * vendored index). The vendored `index.json` is a byte-exact copy of the
50
+ * upstream standard and must never be hand-edited to encode this, so the alias
51
+ * lives here in code instead.
52
+ */
53
+ export declare const REFERENCE_TOOL_ALIASES: Readonly<Record<string, string>>;
54
+ /**
55
+ * Platform-gated degradations (SDK-local, NOT part of the vendored standard).
56
+ *
57
+ * Some reference-shape tools require standard properties that are *platform
58
+ * bindings* — identifiers that only have meaning against a Honua
59
+ * publishing/authoring surface. The platform-free (standalone) front door
60
+ * (issue #369) has no such surface, so it intentionally degrades these tools to
61
+ * a non-error, client-side projection and legitimately omits the binding
62
+ * identifiers, keeping only the taxonomy essence.
63
+ *
64
+ * This maps an advertised reference tool name to the required standard
65
+ * properties it may shed WITHOUT counting as non-conformant on a platform-free
66
+ * target. It is deliberately narrow: it never relaxes read-addressing required
67
+ * properties (e.g. `honua_query_features` still must require serviceId+layerId),
68
+ * only true platform-authoring bindings. The vendored `index.json` and schema
69
+ * files are byte-exact copies of the upstream standard and must never be
70
+ * hand-edited to encode this, so the decision lives here in code instead.
71
+ *
72
+ * `honua_apply_style_preset`: the reference shape binds a StyleRef preset onto a
73
+ * PUBLISHED layer (serviceId+layerId) via the server OGC API – Styles authoring
74
+ * surface (ADR-0048). The platform-free surface resolves a preset for
75
+ * client-side application keyed on `styleId` alone (ADR-0028: never mutates
76
+ * server state), so it sheds serviceId+layerId.
77
+ */
78
+ export declare const PLATFORM_FREE_DEGRADATIONS: Readonly<Record<string, readonly string[]>>;
79
+ export type JsonSchema = Record<string, unknown>;
80
+ export declare const SCHEMA_ROOT: URL;
81
+ /** Load and cache the machine-readable schema index. */
82
+ export declare function loadSchemaIndex(): SchemaIndex;
83
+ /** Load and cache a single vendored schema by its index-relative path. */
84
+ export declare function loadSchemaFile(relativePath: string): JsonSchema;
85
+ /** Resolve the absolute on-disk path of the vendored schema root (for diagnostics). */
86
+ export declare function schemaRootPath(): string;
87
+ /**
88
+ * Build a lookup from the name a tool advertises (`referenceToolName`) to its
89
+ * standard schema entry. Only entries that name a reference tool are included.
90
+ * SDK-local reference aliases (see {@link REFERENCE_TOOL_ALIASES}) map extra
91
+ * advertised names onto the same standard entry.
92
+ */
93
+ export declare function buildReferenceToolLookup(index: SchemaIndex): Map<string, StandardToolEntry>;
94
+ //# sourceMappingURL=schema-index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-index.d.ts","sourceRoot":"","sources":["../../../src/certification/schema-index.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AAEH,MAAM,WAAW,iBAAiB;IAChC,0DAA0D;IAC1D,YAAY,EAAE,MAAM,CAAC;IACrB,gFAAgF;IAChF,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB,EAAE,aAAa,GAAG,WAAW,CAAC;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,oBAAoB,CAAC,EAAE,aAAa,GAAG,WAAW,CAAC;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,SAAS,EAAE,qBAAqB,EAAE,CAAC;IACnC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACzD,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAChE;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAEnE,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAElF,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAwBjD,eAAO,MAAM,WAAW,KAAsB,CAAC;AAK/C,wDAAwD;AACxD,wBAAgB,eAAe,IAAI,WAAW,CAM7C;AAED,0EAA0E;AAC1E,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,UAAU,CAS/D;AAED,uFAAuF;AACvF,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,WAAW,GAAG,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAc3F"}
@@ -0,0 +1,109 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { fileURLToPath } from "node:url";
3
+ /**
4
+ * Reference-implementation aliasing decision (SDK-local, NOT part of the
5
+ * vendored standard): the honua-server /mcp surface advertises
6
+ * `honua_dry_run_plan` alongside `honua_validate_plan`, both driven by the same
7
+ * partial-plan input schema (see the `validate_plan` entry's notes in the
8
+ * vendored index). The vendored `index.json` is a byte-exact copy of the
9
+ * upstream standard and must never be hand-edited to encode this, so the alias
10
+ * lives here in code instead.
11
+ */
12
+ export const REFERENCE_TOOL_ALIASES = {
13
+ honua_dry_run_plan: "honua_validate_plan",
14
+ };
15
+ /**
16
+ * Platform-gated degradations (SDK-local, NOT part of the vendored standard).
17
+ *
18
+ * Some reference-shape tools require standard properties that are *platform
19
+ * bindings* — identifiers that only have meaning against a Honua
20
+ * publishing/authoring surface. The platform-free (standalone) front door
21
+ * (issue #369) has no such surface, so it intentionally degrades these tools to
22
+ * a non-error, client-side projection and legitimately omits the binding
23
+ * identifiers, keeping only the taxonomy essence.
24
+ *
25
+ * This maps an advertised reference tool name to the required standard
26
+ * properties it may shed WITHOUT counting as non-conformant on a platform-free
27
+ * target. It is deliberately narrow: it never relaxes read-addressing required
28
+ * properties (e.g. `honua_query_features` still must require serviceId+layerId),
29
+ * only true platform-authoring bindings. The vendored `index.json` and schema
30
+ * files are byte-exact copies of the upstream standard and must never be
31
+ * hand-edited to encode this, so the decision lives here in code instead.
32
+ *
33
+ * `honua_apply_style_preset`: the reference shape binds a StyleRef preset onto a
34
+ * PUBLISHED layer (serviceId+layerId) via the server OGC API – Styles authoring
35
+ * surface (ADR-0048). The platform-free surface resolves a preset for
36
+ * client-side application keyed on `styleId` alone (ADR-0028: never mutates
37
+ * server state), so it sheds serviceId+layerId.
38
+ */
39
+ export const PLATFORM_FREE_DEGRADATIONS = {
40
+ honua_apply_style_preset: ["serviceId", "layerId"],
41
+ };
42
+ /**
43
+ * Resolved root of the vendored schema tree.
44
+ *
45
+ * The vendored schemas live at the package root under
46
+ * `certification/geospatial-mcp-schemas/`. This module runs from two locations:
47
+ * - compiled: `dist/src/certification/schema-index.js` (3 levels deep)
48
+ * - vitest: `src/certification/schema-index.ts` (2 levels deep)
49
+ * so we probe candidate depths and pick the one that exists on disk.
50
+ */
51
+ function resolveSchemaRoot() {
52
+ const candidates = ["../../../certification/geospatial-mcp-schemas/", "../../certification/geospatial-mcp-schemas/"];
53
+ for (const candidate of candidates) {
54
+ const url = new URL(candidate, import.meta.url);
55
+ if (existsSync(new URL("index.json", url))) {
56
+ return url;
57
+ }
58
+ }
59
+ // Fall back to the compiled-layout path; the loader will surface a clear
60
+ // ENOENT if the vendored schemas are genuinely missing.
61
+ return new URL(candidates[0], import.meta.url);
62
+ }
63
+ export const SCHEMA_ROOT = resolveSchemaRoot();
64
+ let cachedIndex;
65
+ const schemaCache = new Map();
66
+ /** Load and cache the machine-readable schema index. */
67
+ export function loadSchemaIndex() {
68
+ if (!cachedIndex) {
69
+ const indexPath = new URL("index.json", SCHEMA_ROOT);
70
+ cachedIndex = JSON.parse(readFileSync(indexPath, "utf8"));
71
+ }
72
+ return cachedIndex;
73
+ }
74
+ /** Load and cache a single vendored schema by its index-relative path. */
75
+ export function loadSchemaFile(relativePath) {
76
+ const cached = schemaCache.get(relativePath);
77
+ if (cached) {
78
+ return cached;
79
+ }
80
+ const path = new URL(relativePath, SCHEMA_ROOT);
81
+ const schema = JSON.parse(readFileSync(path, "utf8"));
82
+ schemaCache.set(relativePath, schema);
83
+ return schemaCache.get(relativePath);
84
+ }
85
+ /** Resolve the absolute on-disk path of the vendored schema root (for diagnostics). */
86
+ export function schemaRootPath() {
87
+ return fileURLToPath(SCHEMA_ROOT);
88
+ }
89
+ /**
90
+ * Build a lookup from the name a tool advertises (`referenceToolName`) to its
91
+ * standard schema entry. Only entries that name a reference tool are included.
92
+ * SDK-local reference aliases (see {@link REFERENCE_TOOL_ALIASES}) map extra
93
+ * advertised names onto the same standard entry.
94
+ */
95
+ export function buildReferenceToolLookup(index) {
96
+ const lookup = new Map();
97
+ for (const tool of index.tools) {
98
+ if (tool.referenceToolName) {
99
+ lookup.set(tool.referenceToolName, tool);
100
+ }
101
+ }
102
+ for (const [alias, canonical] of Object.entries(REFERENCE_TOOL_ALIASES)) {
103
+ const entry = lookup.get(canonical);
104
+ if (entry) {
105
+ lookup.set(alias, entry);
106
+ }
107
+ }
108
+ return lookup;
109
+ }
@@ -0,0 +1,48 @@
1
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import type { AuthMode } from "../provenance.js";
3
+ import { type ProxyOptions } from "../proxy.js";
4
+ /**
5
+ * Certification target selection.
6
+ *
7
+ * The certifier drives one of three targets, all reached through the SAME MCP
8
+ * client path the proxy uses so what's certified is the real operator surface,
9
+ * never the retired static server:
10
+ *
11
+ * - `offline` (CI default): a real in-process streamable-HTTP mock of the
12
+ * honua `/mcp` operator catalog. Gates every PR without a
13
+ * live server.
14
+ * - `remote` : a live streamable-HTTP `/mcp` (HONUA_MCP_REMOTE_URL + auth).
15
+ * Reuses the proxy's upstream connection logic verbatim.
16
+ * - `stdio-proxy` : spawns the `honua-mcp-proxy` binary against an upstream and
17
+ * certifies through stdio, proving the proxy chain end-to-end.
18
+ * - `standalone` : the PLATFORM-FREE front door (issue #369). Certifies the
19
+ * direct-SDK `createServer` surface against an in-process fixture
20
+ * of a PLAIN public FeatureServer (recorded census layer, no
21
+ * Honua surfaces). Proves the tools certify green against a
22
+ * non-Honua endpoint, with Honua-only tools skip-with-reason.
23
+ */
24
+ export type CertTargetMode = "offline" | "remote" | "stdio-proxy" | "standalone";
25
+ export interface CertificationTarget {
26
+ mode: CertTargetMode;
27
+ backend: "mock-upstream" | "live";
28
+ /** Human-readable label for the certified surface (artifact provenance). */
29
+ serverLabel: string;
30
+ /** How the authenticated client reached the surface (recorded in provenance). */
31
+ authMode: AuthMode;
32
+ honuaTransport: string | null;
33
+ /** Authenticated, connected MCP client. */
34
+ client: Client;
35
+ /** Whether an unauthenticated pass is possible for the auth contract. */
36
+ supportsUnauthenticatedPass: boolean;
37
+ /** Open a fresh, UNauthenticated client to the same surface (auth contract). */
38
+ connectUnauthenticated(): Promise<Client>;
39
+ close(): Promise<void>;
40
+ }
41
+ export declare function resolveTargetMode(env?: NodeJS.ProcessEnv): CertTargetMode;
42
+ /** Resolve the remote `/mcp` endpoint + credentials from the environment. */
43
+ export declare function resolveRemoteProxyOptions(env: NodeJS.ProcessEnv): ProxyOptions;
44
+ /** Resolve the built `honua-mcp-proxy` entry usable from src (vitest) or dist. */
45
+ export declare function resolveProxyEntry(): string;
46
+ /** Open the configured certification target. */
47
+ export declare function openCertificationTarget(env?: NodeJS.ProcessEnv): Promise<CertificationTarget>;
48
+ //# sourceMappingURL=target.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"target.d.ts","sourceRoot":"","sources":["../../../src/certification/target.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAInE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,KAAK,YAAY,EAAmB,MAAM,aAAa,CAAC;AAIjE;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,QAAQ,GAAG,aAAa,GAAG,YAAY,CAAC;AAEjF,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,eAAe,GAAG,MAAM,CAAC;IAClC,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,QAAQ,EAAE,QAAQ,CAAC;IACnB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,2BAA2B,EAAE,OAAO,CAAC;IACrC,gFAAgF;IAChF,sBAAsB,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,cAAc,CAQtF;AAED,6EAA6E;AAC7E,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,YAAY,CAc9E;AAED,kFAAkF;AAClF,wBAAgB,iBAAiB,IAAI,MAAM,CAc1C;AAED,gDAAgD;AAChD,wBAAsB,uBAAuB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAYhH"}
@@ -0,0 +1,219 @@
1
+ import { existsSync } from "node:fs";
2
+ import { fileURLToPath } from "node:url";
3
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
4
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
5
+ import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
6
+ import { createClientFromEnv, createServer } from "../index.js";
7
+ import { connectUpstream } from "../proxy.js";
8
+ import { createStandaloneFixtureClient } from "./census-fixture-client.js";
9
+ import { startMockUpstream } from "./mock-upstream.js";
10
+ export function resolveTargetMode(env = process.env) {
11
+ const raw = (env.HONUA_MCP_CERT_TARGET ?? "offline").trim().toLowerCase();
12
+ if (raw === "offline" || raw === "remote" || raw === "stdio-proxy" || raw === "standalone") {
13
+ return raw;
14
+ }
15
+ throw new Error(`HONUA_MCP_CERT_TARGET must be "offline", "remote", "stdio-proxy", or "standalone", received "${raw}"`);
16
+ }
17
+ /** Resolve the remote `/mcp` endpoint + credentials from the environment. */
18
+ export function resolveRemoteProxyOptions(env) {
19
+ const remoteUrl = env.HONUA_MCP_REMOTE_URL ?? env.HONUA_MCP_URL;
20
+ if (!remoteUrl) {
21
+ throw new Error("HONUA_MCP_REMOTE_URL is required for remote / stdio-proxy certification against a live /mcp.");
22
+ }
23
+ const parsed = new URL(remoteUrl);
24
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
25
+ throw new Error(`HONUA_MCP_REMOTE_URL must use http or https: ${remoteUrl}`);
26
+ }
27
+ return {
28
+ remoteUrl: parsed.toString(),
29
+ authToken: env.HONUA_MCP_AUTH_TOKEN,
30
+ apiKey: env.HONUA_API_KEY,
31
+ };
32
+ }
33
+ /** Resolve the built `honua-mcp-proxy` entry usable from src (vitest) or dist. */
34
+ export function resolveProxyEntry() {
35
+ const candidates = ["../proxy.js", "../../dist/src/proxy.js"];
36
+ for (const candidate of candidates) {
37
+ const url = new URL(candidate, import.meta.url);
38
+ if (url.protocol === "file:" && existsSync(url)) {
39
+ const path = fileURLToPath(url);
40
+ if (path.endsWith(".js")) {
41
+ return path;
42
+ }
43
+ }
44
+ }
45
+ throw new Error("Could not locate the built honua-mcp-proxy entry (dist/src/proxy.js). Run `npm run build` before stdio-proxy certification.");
46
+ }
47
+ /** Open the configured certification target. */
48
+ export async function openCertificationTarget(env = process.env) {
49
+ const mode = resolveTargetMode(env);
50
+ if (mode === "remote") {
51
+ return openRemoteTarget(env);
52
+ }
53
+ if (mode === "stdio-proxy") {
54
+ return openStdioProxyTarget(env);
55
+ }
56
+ if (mode === "standalone") {
57
+ return openStandaloneTarget(env);
58
+ }
59
+ return openOfflineTarget(env);
60
+ }
61
+ /**
62
+ * Open the platform-free standalone target: the direct-SDK `createServer` surface,
63
+ * reached over an in-memory MCP transport. By default it is wired to an in-process
64
+ * fixture of a plain public FeatureServer (recorded census layer, no Honua
65
+ * surfaces) — deterministic, no network, gates CI. When `HONUA_BASE_URL` is set
66
+ * (the scheduled live variant) it drives a REAL `HonuaClient` against that public
67
+ * FeatureServer/OGC endpoint instead. Either way there is no transport auth
68
+ * boundary, so the auth contracts skip-with-reason and the Honua-only style tools
69
+ * degrade to structured "not available on this target" results.
70
+ */
71
+ async function openStandaloneTarget(env) {
72
+ const live = typeof env.HONUA_BASE_URL === "string" && env.HONUA_BASE_URL.length > 0;
73
+ const client_ = live ? createClientFromEnv(env) : createStandaloneFixtureClient();
74
+ const server = createServer(client_);
75
+ const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
76
+ const client = new Client({ name: "honua-mcp-certifier", version: "1.0.0" });
77
+ await server.connect(serverTransport);
78
+ await client.connect(clientTransport);
79
+ return {
80
+ mode: "standalone",
81
+ backend: live ? "live" : "mock-upstream",
82
+ serverLabel: live
83
+ ? `honua-mcp standalone → ${env.HONUA_BASE_URL} (live public FeatureServer, no Honua surfaces)`
84
+ : "honua-mcp standalone → plain public FeatureServer (recorded census fixture, no Honua surfaces)",
85
+ authMode: "anonymous",
86
+ honuaTransport: env.HONUA_TRANSPORT ?? null,
87
+ client,
88
+ // A plain FeatureServer has no MCP transport auth boundary — the auth
89
+ // contracts skip-with-reason rather than assert an enforcement that a
90
+ // platform-free target does not (and should not) provide.
91
+ supportsUnauthenticatedPass: false,
92
+ connectUnauthenticated() {
93
+ return Promise.reject(new Error("standalone target has no auth boundary"));
94
+ },
95
+ async close() {
96
+ await client.close().catch(() => { });
97
+ await server.close().catch(() => { });
98
+ },
99
+ };
100
+ }
101
+ async function openOfflineTarget(env) {
102
+ const mock = await startMockUpstream();
103
+ const authedClients = [];
104
+ const client = await connectUpstream({ remoteUrl: mock.url, authToken: mock.authToken });
105
+ authedClients.push(client);
106
+ return {
107
+ mode: "offline",
108
+ backend: "mock-upstream",
109
+ serverLabel: "honua /mcp operator catalog (in-process streamable-HTTP mock)",
110
+ authMode: "bearer",
111
+ honuaTransport: env.HONUA_TRANSPORT ?? null,
112
+ client,
113
+ supportsUnauthenticatedPass: true,
114
+ async connectUnauthenticated() {
115
+ const unauth = await connectUpstream({ remoteUrl: mock.url });
116
+ authedClients.push(unauth);
117
+ return unauth;
118
+ },
119
+ async close() {
120
+ for (const c of authedClients) {
121
+ await c.close().catch(() => { });
122
+ }
123
+ await mock.close();
124
+ },
125
+ };
126
+ }
127
+ function resolveAuthMode(options) {
128
+ return options.authToken ? "bearer" : options.apiKey ? "api-key" : "anonymous";
129
+ }
130
+ async function openRemoteTarget(env) {
131
+ const options = resolveRemoteProxyOptions(env);
132
+ const clients = [];
133
+ const client = await connectUpstream(options);
134
+ clients.push(client);
135
+ return {
136
+ mode: "remote",
137
+ backend: "live",
138
+ serverLabel: `live honua /mcp (${options.remoteUrl})`,
139
+ authMode: resolveAuthMode(options),
140
+ honuaTransport: env.HONUA_TRANSPORT ?? null,
141
+ client,
142
+ supportsUnauthenticatedPass: true,
143
+ async connectUnauthenticated() {
144
+ const unauth = await connectUpstream({ remoteUrl: options.remoteUrl });
145
+ clients.push(unauth);
146
+ return unauth;
147
+ },
148
+ async close() {
149
+ for (const c of clients) {
150
+ await c.close().catch(() => { });
151
+ }
152
+ },
153
+ };
154
+ }
155
+ async function openStdioProxyTarget(env) {
156
+ const proxyEntry = resolveProxyEntry();
157
+ const clients = [];
158
+ // Upstream: a live /mcp when configured, otherwise the in-process mock.
159
+ let mock;
160
+ let upstreamUrl;
161
+ let upstreamToken;
162
+ let backend;
163
+ if (env.HONUA_MCP_REMOTE_URL ?? env.HONUA_MCP_URL) {
164
+ const options = resolveRemoteProxyOptions(env);
165
+ upstreamUrl = options.remoteUrl;
166
+ upstreamToken = options.authToken;
167
+ backend = "live";
168
+ }
169
+ else {
170
+ mock = await startMockUpstream();
171
+ upstreamUrl = mock.url;
172
+ upstreamToken = mock.authToken;
173
+ backend = "mock-upstream";
174
+ }
175
+ const spawnProxyClient = async (withAuth) => {
176
+ const childEnv = {
177
+ ...process.env,
178
+ HONUA_MCP_REMOTE_URL: upstreamUrl,
179
+ };
180
+ if (withAuth && upstreamToken) {
181
+ childEnv.HONUA_MCP_AUTH_TOKEN = upstreamToken;
182
+ }
183
+ else {
184
+ delete childEnv.HONUA_MCP_AUTH_TOKEN;
185
+ delete childEnv.HONUA_API_KEY;
186
+ }
187
+ const transport = new StdioClientTransport({
188
+ command: process.execPath,
189
+ args: [proxyEntry],
190
+ env: childEnv,
191
+ stderr: "inherit",
192
+ });
193
+ const c = new Client({ name: "honua-mcp-certifier", version: "1.0.0" });
194
+ await c.connect(transport);
195
+ clients.push(c);
196
+ return c;
197
+ };
198
+ const client = await spawnProxyClient(true);
199
+ return {
200
+ mode: "stdio-proxy",
201
+ backend,
202
+ serverLabel: `honua-mcp-proxy → ${backend === "live" ? upstreamUrl : "in-process mock /mcp"}`,
203
+ authMode: upstreamToken ? "bearer" : env.HONUA_API_KEY ? "api-key" : "anonymous",
204
+ honuaTransport: env.HONUA_TRANSPORT ?? null,
205
+ client,
206
+ supportsUnauthenticatedPass: true,
207
+ async connectUnauthenticated() {
208
+ return spawnProxyClient(false);
209
+ },
210
+ async close() {
211
+ for (const c of clients) {
212
+ await c.close().catch(() => { });
213
+ }
214
+ if (mock) {
215
+ await mock.close();
216
+ }
217
+ },
218
+ };
219
+ }
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../src/eval/cli.ts"],"names":[],"mappings":""}