@corbits/mcp 0.3.1 → 0.4.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 (124) hide show
  1. package/README.md +120 -26
  2. package/dist/auth/callback.d.ts +14 -0
  3. package/dist/auth/callback.js +79 -0
  4. package/dist/auth/challenge.d.ts +9 -0
  5. package/dist/auth/challenge.js +52 -0
  6. package/dist/auth/contracts.d.ts +18 -0
  7. package/dist/auth/contracts.js +19 -0
  8. package/dist/auth/http.d.ts +2 -0
  9. package/dist/auth/http.js +2 -0
  10. package/dist/auth/index.d.ts +6 -0
  11. package/dist/auth/index.js +6 -0
  12. package/dist/auth/login.d.ts +62 -0
  13. package/dist/auth/login.js +175 -0
  14. package/dist/auth/oauth-http.d.ts +6 -0
  15. package/dist/auth/oauth-http.js +32 -0
  16. package/dist/auth/resource-server.d.ts +25 -0
  17. package/dist/auth/resource-server.js +94 -0
  18. package/dist/auth/url-policy.d.ts +10 -0
  19. package/dist/auth/url-policy.js +35 -0
  20. package/dist/client/resource-budget.d.ts +1 -0
  21. package/dist/client/resource-budget.js +1 -0
  22. package/dist/client/transport.d.ts +10 -0
  23. package/dist/client/transport.js +1 -0
  24. package/dist/client.d.ts +208 -26
  25. package/dist/client.js +1128 -90
  26. package/dist/extensions/apps.d.ts +58 -0
  27. package/dist/extensions/apps.js +55 -0
  28. package/dist/extensions/elicitation.d.ts +18 -0
  29. package/dist/extensions/elicitation.js +55 -0
  30. package/dist/extensions/index.d.ts +5 -0
  31. package/dist/extensions/index.js +5 -0
  32. package/dist/extensions/maturity.d.ts +44 -0
  33. package/dist/extensions/maturity.js +24 -0
  34. package/dist/extensions/skills/contracts.d.ts +53 -0
  35. package/dist/extensions/skills/contracts.js +1 -0
  36. package/dist/extensions/skills/index.d.ts +52 -0
  37. package/dist/extensions/skills/index.js +402 -0
  38. package/dist/extensions/tasks/contracts.d.ts +39 -0
  39. package/dist/extensions/tasks/contracts.js +1 -0
  40. package/dist/extensions/tasks/file-store.d.ts +12 -0
  41. package/dist/extensions/tasks/file-store.js +152 -0
  42. package/dist/extensions/tasks/index.d.ts +82 -0
  43. package/dist/extensions/tasks/index.js +221 -0
  44. package/dist/extensions/tasks/record.d.ts +3 -0
  45. package/dist/extensions/tasks/record.js +37 -0
  46. package/dist/hub/discover.d.ts +5 -1
  47. package/dist/hub/discover.js +36 -13
  48. package/dist/index.d.ts +3 -2
  49. package/dist/index.js +4 -2
  50. package/dist/interchange/client/capabilities.d.ts +4 -0
  51. package/dist/interchange/client/capabilities.js +53 -0
  52. package/dist/interchange/client/catalog.d.ts +14 -0
  53. package/dist/interchange/client/catalog.js +52 -0
  54. package/dist/interchange/client/contracts.d.ts +47 -0
  55. package/dist/interchange/client/contracts.js +1 -0
  56. package/dist/interchange/client/projection.d.ts +6 -0
  57. package/dist/interchange/client/projection.js +92 -0
  58. package/dist/interchange/client/skills.d.ts +16 -0
  59. package/dist/interchange/client/skills.js +87 -0
  60. package/dist/interchange/client.d.ts +8 -0
  61. package/dist/interchange/client.js +6 -0
  62. package/dist/interchange/server/contracts.d.ts +65 -0
  63. package/dist/interchange/server/contracts.js +1 -0
  64. package/dist/interchange/server.d.ts +5 -0
  65. package/dist/interchange/server.js +172 -0
  66. package/dist/naming.d.ts +2 -0
  67. package/dist/naming.js +7 -0
  68. package/dist/oauth-discovery.d.ts +107 -1
  69. package/dist/oauth-discovery.js +292 -56
  70. package/dist/protocol/content.d.ts +35 -0
  71. package/dist/protocol/content.js +64 -0
  72. package/dist/protocol/envelopes.d.ts +14 -0
  73. package/dist/protocol/envelopes.js +22 -0
  74. package/dist/protocol/errors.d.ts +26 -0
  75. package/dist/protocol/errors.js +31 -0
  76. package/dist/protocol/extensions.d.ts +34 -0
  77. package/dist/protocol/extensions.js +86 -0
  78. package/dist/protocol/headers.d.ts +12 -0
  79. package/dist/protocol/headers.js +128 -0
  80. package/dist/protocol/index.d.ts +11 -0
  81. package/dist/protocol/index.js +11 -0
  82. package/dist/protocol/json-schema.d.ts +8 -0
  83. package/dist/protocol/json-schema.js +152 -0
  84. package/dist/protocol/legacy.d.ts +12 -0
  85. package/dist/protocol/legacy.js +18 -0
  86. package/dist/protocol/methods.d.ts +116 -0
  87. package/dist/protocol/methods.js +78 -0
  88. package/dist/protocol/resource-budget.d.ts +9 -0
  89. package/dist/protocol/resource-budget.js +206 -0
  90. package/dist/protocol/schemas.d.ts +115 -0
  91. package/dist/protocol/schemas.js +553 -0
  92. package/dist/protocol/types.d.ts +295 -0
  93. package/dist/protocol/types.js +3 -0
  94. package/dist/protocol/ui.d.ts +3 -0
  95. package/dist/protocol/ui.js +18 -0
  96. package/dist/server/contracts.d.ts +67 -0
  97. package/dist/server/contracts.js +1 -0
  98. package/dist/server/errors.d.ts +6 -0
  99. package/dist/server/errors.js +21 -0
  100. package/dist/server/extensions.d.ts +7 -0
  101. package/dist/server/extensions.js +61 -0
  102. package/dist/server/fixtures.d.ts +2 -0
  103. package/dist/server/fixtures.js +34 -0
  104. package/dist/server/legacy.d.ts +9 -0
  105. package/dist/server/legacy.js +435 -0
  106. package/dist/server/tools.d.ts +17 -0
  107. package/dist/server/tools.js +93 -0
  108. package/dist/server.d.ts +14 -0
  109. package/dist/server.js +406 -0
  110. package/dist/sidecar-bundle.d.ts +7 -7
  111. package/dist/sidecar-bundle.js +36 -29
  112. package/dist/test-server.js +12 -3
  113. package/dist/tool.d.ts +8 -0
  114. package/dist/tool.js +35 -19
  115. package/dist/url.js +8 -3
  116. package/docs/conformance.md +135 -0
  117. package/docs/integration-status.md +98 -0
  118. package/docs/legacy-server.md +58 -0
  119. package/docs/migration.md +143 -0
  120. package/docs/public-api.md +106 -0
  121. package/examples/README.md +28 -0
  122. package/examples/standalone-client.ts +14 -0
  123. package/examples/standalone-server.ts +37 -0
  124. package/package.json +40 -5
@@ -0,0 +1,58 @@
1
+ import type { McpUiResourceMeta, McpUiToolMeta, McpResourceContents } from "../protocol/index.js";
2
+ /** Metadata helpers only: this package does not render or sandbox HTML. */
3
+ export declare function isToolVisibleToModel(meta?: McpUiToolMeta): boolean;
4
+ export declare function assertAppToolCall(options: {
5
+ tool?: McpUiToolMeta;
6
+ appServerId: string;
7
+ targetServerId: string;
8
+ }): void;
9
+ export declare function getAppHostRequirements(meta?: McpUiResourceMeta): {
10
+ rendererProvided: false;
11
+ protocolVersion: "2026-01-26";
12
+ mimeType: "text/html;profile=mcp-app";
13
+ sandbox: {
14
+ separateOrigin: true;
15
+ proxyRequiredForWebHost: true;
16
+ permissions: readonly ["allow-scripts", "allow-same-origin"];
17
+ };
18
+ csp: {
19
+ connectDomains?: string[];
20
+ resourceDomains?: string[];
21
+ frameDomains?: string[];
22
+ baseUriDomains?: string[];
23
+ };
24
+ defaults: {
25
+ connectSrc: string;
26
+ resourceSrc: string;
27
+ frameSrc: string;
28
+ baseUri: string;
29
+ };
30
+ requestedPermissions: {
31
+ camera?: Record<string, never>;
32
+ microphone?: Record<string, never>;
33
+ geolocation?: Record<string, never>;
34
+ clipboardWrite?: Record<string, never>;
35
+ };
36
+ requestedDomain: string | undefined;
37
+ obligations: readonly ["enforce-declared-csp-without-loosening", "validate-message-origin-and-source", "initialize-before-delivery", "authorize-every-tool-call", "keep-result-meta-out-of-model-context", "user-consent-for-external-navigation"];
38
+ };
39
+ export interface McpAppHost {
40
+ /** Must implement sandbox, CSP and authenticated message bridge; not a transport flag. */
41
+ mount(resource: McpResourceContents, requirements: ReturnType<typeof getAppHostRequirements>): Promise<{
42
+ close(): Promise<void>;
43
+ }>;
44
+ authorizeTool(serverId: string, name: string, args: Record<string, unknown>): Promise<void>;
45
+ callTool(serverId: string, name: string, args: Record<string, unknown>): Promise<unknown>;
46
+ }
47
+ export declare function createAppHostBridge(host: McpAppHost): {
48
+ mount(resource: McpResourceContents, metadata?: McpUiResourceMeta): Promise<{
49
+ close(): Promise<void>;
50
+ }>;
51
+ call(options: {
52
+ appServerId: string;
53
+ targetServerId: string;
54
+ name: string;
55
+ arguments: Record<string, unknown>;
56
+ tool?: McpUiToolMeta;
57
+ }): Promise<unknown>;
58
+ };
@@ -0,0 +1,55 @@
1
+ /** Metadata helpers only: this package does not render or sandbox HTML. */
2
+ export function isToolVisibleToModel(meta) {
3
+ return meta?.visibility === undefined || meta.visibility.includes("model");
4
+ }
5
+ export function assertAppToolCall(options) {
6
+ if (!options.appServerId || options.appServerId !== options.targetServerId)
7
+ throw new Error("Cross-server app tool call prohibited");
8
+ if (options.tool?.visibility && !options.tool.visibility.includes("app"))
9
+ throw new Error("Tool is not app-callable");
10
+ }
11
+ export function getAppHostRequirements(meta = {}) {
12
+ return {
13
+ rendererProvided: false,
14
+ protocolVersion: "2026-01-26",
15
+ mimeType: "text/html;profile=mcp-app",
16
+ sandbox: {
17
+ separateOrigin: true,
18
+ proxyRequiredForWebHost: true,
19
+ permissions: ["allow-scripts", "allow-same-origin"],
20
+ },
21
+ // These are requested constraints, not a CSP header generator or approval.
22
+ csp: structuredClone(meta.csp ?? {}),
23
+ defaults: {
24
+ connectSrc: "'none'",
25
+ resourceSrc: "'none'",
26
+ frameSrc: "'none'",
27
+ baseUri: "'self'",
28
+ },
29
+ requestedPermissions: structuredClone(meta.permissions ?? {}),
30
+ requestedDomain: meta.domain,
31
+ obligations: [
32
+ "enforce-declared-csp-without-loosening",
33
+ "validate-message-origin-and-source",
34
+ "initialize-before-delivery",
35
+ "authorize-every-tool-call",
36
+ "keep-result-meta-out-of-model-context",
37
+ "user-consent-for-external-navigation",
38
+ ],
39
+ };
40
+ }
41
+ export function createAppHostBridge(host) {
42
+ return {
43
+ async mount(resource, metadata) {
44
+ if (!resource.uri.startsWith("ui://") ||
45
+ resource.mimeType !== "text/html;profile=mcp-app")
46
+ throw new Error("Unsupported Apps resource");
47
+ return host.mount(structuredClone(resource), getAppHostRequirements(metadata));
48
+ },
49
+ async call(options) {
50
+ assertAppToolCall(options);
51
+ await host.authorizeTool(options.targetServerId, options.name, options.arguments);
52
+ return host.callTool(options.targetServerId, options.name, options.arguments);
53
+ },
54
+ };
55
+ }
@@ -0,0 +1,18 @@
1
+ import type { ElicitRequestParams, ElicitRequestFormParams, ElicitRequestURLParams, ElicitResult, InputRequests, InputResponses } from "../protocol/index.js";
2
+ /** Request-aware host semantics shared by direct and durable task input.
3
+ * Wire shape validation remains owned by the common protocol module.
4
+ */
5
+ export declare function validateElicitationResponse(request: ElicitRequestParams, response: InputResponses[string]): void;
6
+ export interface McpElicitationHost {
7
+ form?(request: ElicitRequestFormParams, signal?: AbortSignal): Promise<ElicitResult>;
8
+ /** Host presents URL and obtains explicit user consent. Opening a URL is not acceptance. */
9
+ url?(request: ElicitRequestURLParams, signal?: AbortSignal): Promise<ElicitResult>;
10
+ }
11
+ /** Input has already passed the common wire validators. No sampling/roots capability implied. */
12
+ export declare function createElicitationRuntime(host: McpElicitationHost): {
13
+ capabilities: {
14
+ url?: {};
15
+ form?: {};
16
+ };
17
+ respond(requests: InputRequests, signal?: AbortSignal): Promise<InputResponses>;
18
+ };
@@ -0,0 +1,55 @@
1
+ import { validateInstance, validateInputRequests, validateInputResponses, } from "../protocol/index.js";
2
+ /** Request-aware host semantics shared by direct and durable task input.
3
+ * Wire shape validation remains owned by the common protocol module.
4
+ */
5
+ export function validateElicitationResponse(request, response) {
6
+ validateInputResponses({ response });
7
+ if (request.mode === "url" && response.content !== undefined)
8
+ throw new Error("URL elicitation cannot return form content");
9
+ if (response.action !== "accept" && response.content !== undefined)
10
+ throw new Error("Non-accept elicitation must omit content");
11
+ if (request.mode !== "url" && response.action === "accept")
12
+ validateInstance(request.requestedSchema, response.content ?? {});
13
+ }
14
+ /** Input has already passed the common wire validators. No sampling/roots capability implied. */
15
+ export function createElicitationRuntime(host) {
16
+ return {
17
+ capabilities: {
18
+ ...(host.form ? { form: {} } : {}),
19
+ ...(host.url ? { url: {} } : {}),
20
+ },
21
+ async respond(requests, signal) {
22
+ validateInputRequests(requests);
23
+ const responses = {};
24
+ for (const [key, request] of Object.entries(requests)) {
25
+ signal?.throwIfAborted();
26
+ if (request.method !== "elicitation/create")
27
+ throw new Error(`Unsupported host input: ${request.method}`);
28
+ const params = request.params;
29
+ let response;
30
+ if (params.mode === "url") {
31
+ const url = new URL(params.url);
32
+ if (url.protocol !== "https:" || url.username || url.password)
33
+ throw new Error("Unsafe elicitation URL");
34
+ if (!host.url)
35
+ throw new Error("URL elicitation host unavailable");
36
+ response = await host.url(structuredClone(params), signal);
37
+ }
38
+ else {
39
+ if (!host.form)
40
+ throw new Error("Form elicitation host unavailable");
41
+ response = await host.form(structuredClone(params), signal);
42
+ }
43
+ validateElicitationResponse(params, response);
44
+ signal?.throwIfAborted();
45
+ Object.defineProperty(responses, key, {
46
+ value: structuredClone(response),
47
+ enumerable: true,
48
+ configurable: true,
49
+ writable: true,
50
+ });
51
+ }
52
+ return responses;
53
+ },
54
+ };
55
+ }
@@ -0,0 +1,5 @@
1
+ export * from "./skills/index.js";
2
+ export * from "./tasks/index.js";
3
+ export * from "./apps.js";
4
+ export * from "./elicitation.js";
5
+ export * from "./maturity.js";
@@ -0,0 +1,5 @@
1
+ export * from "./skills/index.js";
2
+ export * from "./tasks/index.js";
3
+ export * from "./apps.js";
4
+ export * from "./elicitation.js";
5
+ export * from "./maturity.js";
@@ -0,0 +1,44 @@
1
+ export declare const extensionMaturity: Readonly<{
2
+ tasks: {
3
+ readonly id: "io.modelcontextprotocol/tasks";
4
+ readonly coreRevision: "2026-07-28";
5
+ readonly extensionRevision: "2026-07-28";
6
+ readonly sourceCommit: "b3d28aceaa6d49f5f92258e3d06b61ad6f111e84";
7
+ readonly maturity: "stable";
8
+ readonly enabledByDefault: false;
9
+ };
10
+ skills: {
11
+ readonly id: "io.modelcontextprotocol/skills";
12
+ readonly coreRevision: "2026-07-28";
13
+ readonly extensionRevision: "stable";
14
+ readonly sourceCommit: "c1aa87e4c381c82b99aa37471d0eae4ab50f9985";
15
+ readonly maturity: "stable";
16
+ readonly enabledByDefault: false;
17
+ };
18
+ apps: {
19
+ readonly id: "io.modelcontextprotocol/ui";
20
+ readonly coreRevision: "2026-07-28";
21
+ readonly extensionRevision: "2026-01-26";
22
+ readonly sourceCommit: "266a9e3b70dbd4a4f0546dda95da2a2c1a8be4b7";
23
+ readonly maturity: "released";
24
+ readonly enabledByDefault: false;
25
+ };
26
+ }>;
27
+ /** Negotiating a wire extension does not supply a renderer, approvals or durability. */
28
+ export declare function supportedHostExtensions(options: {
29
+ tasks?: {
30
+ durableStore: boolean;
31
+ recoverableExecutor: boolean;
32
+ inputHandler: boolean;
33
+ };
34
+ skills?: {
35
+ verifiedLoader: boolean;
36
+ contextProvenance: boolean;
37
+ executionGate: boolean;
38
+ };
39
+ apps?: {
40
+ sandboxRenderer: boolean;
41
+ cspEnforcement: boolean;
42
+ authenticatedBridge: boolean;
43
+ };
44
+ }): string[];
@@ -0,0 +1,24 @@
1
+ /** Upstream maturity, not transport support or a claim about host deployment. */
2
+ import { MCP_EXTENSIONS, MCP_EXT_TASKS, MCP_EXT_SKILLS, MCP_EXT_UI, } from "../protocol/index.js";
3
+ export const extensionMaturity = Object.freeze({
4
+ tasks: MCP_EXTENSIONS[MCP_EXT_TASKS],
5
+ skills: MCP_EXTENSIONS[MCP_EXT_SKILLS],
6
+ apps: MCP_EXTENSIONS[MCP_EXT_UI],
7
+ });
8
+ /** Negotiating a wire extension does not supply a renderer, approvals or durability. */
9
+ export function supportedHostExtensions(options) {
10
+ const ids = [];
11
+ if (options.tasks?.durableStore === true &&
12
+ options.tasks.recoverableExecutor === true &&
13
+ options.tasks.inputHandler === true)
14
+ ids.push(extensionMaturity.tasks.id);
15
+ if (options.skills?.verifiedLoader === true &&
16
+ options.skills.contextProvenance === true &&
17
+ options.skills.executionGate === true)
18
+ ids.push(extensionMaturity.skills.id);
19
+ if (options.apps?.sandboxRenderer === true &&
20
+ options.apps.cspEnforcement === true &&
21
+ options.apps.authenticatedBridge === true)
22
+ ids.push(extensionMaturity.apps.id);
23
+ return ids;
24
+ }
@@ -0,0 +1,53 @@
1
+ import type { Skill } from "../../protocol/index.js";
2
+ /** Host-assigned identities, never serverInfo.name or a bearer token. */
3
+ export interface McpSkillOrigin {
4
+ serverId: string;
5
+ tenantId: string;
6
+ principalId: string;
7
+ authorizationContextId: string;
8
+ }
9
+ export interface HeldSkill {
10
+ readonly origin: Readonly<McpSkillOrigin>;
11
+ readonly entry: Readonly<Skill>;
12
+ readonly identity: string;
13
+ readonly fingerprint: string;
14
+ }
15
+ export interface SkillApprovalReceipt {
16
+ identity: string;
17
+ fingerprint: string;
18
+ /** Explicit user consent to this skill, not to nested skills. */
19
+ approved: true;
20
+ execution: boolean;
21
+ }
22
+ export interface VerifiedSkillBytes {
23
+ held: HeldSkill;
24
+ uri: string;
25
+ bytes: Uint8Array;
26
+ /** Always untrusted MCP data; integrity is not authorship or trust. */
27
+ trust: "untrusted-mcp";
28
+ }
29
+ export interface McpSkillHostPolicy {
30
+ approve(held: HeldSkill): Promise<SkillApprovalReceipt>;
31
+ /** Install an all-code-execution-tool gate before admitting context. */
32
+ openActingWindow(held: HeldSkill, approval: SkillApprovalReceipt, guards: {
33
+ assertExecutionApproved(): void;
34
+ }): Promise<{
35
+ admit(content: VerifiedSkillBytes): Promise<void>;
36
+ /** Must remove context before returning; do not shorten the acting window. */
37
+ removeContext(): Promise<void>;
38
+ close(): Promise<void>;
39
+ }>;
40
+ }
41
+ export interface SkillLease {
42
+ readonly held: HeldSkill;
43
+ read(uri: string): Promise<VerifiedSkillBytes>;
44
+ /** Re-check for every host code-execution call; never widens existing grants. */
45
+ assertExecutionApproved(): void;
46
+ release(): Promise<void>;
47
+ }
48
+ export interface SkillSource {
49
+ /** Must use the origin's mediated transport and shared protocol validation. */
50
+ get(origin: McpSkillOrigin, uri: string): Promise<Skill>;
51
+ /** Decode a single matching resources/read text/blob to raw bytes. Enforce maxBytes while streaming. */
52
+ read(origin: McpSkillOrigin, uri: string, maxBytes: number): Promise<Uint8Array>;
53
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,52 @@
1
+ import type { Skill } from "../../protocol/index.js";
2
+ import type { HeldSkill, McpSkillHostPolicy, McpSkillOrigin, SkillLease, SkillSource, VerifiedSkillBytes } from "./contracts.js";
3
+ export type * from "./contracts.js";
4
+ export declare const SKILL_LIMITS: Readonly<{
5
+ resources: 512;
6
+ bytes: 16777216;
7
+ }>;
8
+ export declare function parseSkillFrontmatter(bytes: Uint8Array, uri: string): Skill["frontmatter"];
9
+ export declare function createSkillLoader(source: SkillSource, host?: McpSkillHostPolicy): {
10
+ hold: (origin: McpSkillOrigin, entry: Skill) => Promise<HeldSkill>;
11
+ verify: (held: HeldSkill, uri?: string) => Promise<VerifiedSkillBytes>;
12
+ activate: (held: HeldSkill) => Promise<SkillLease>;
13
+ get(origin: McpSkillOrigin, uri: string): Promise<HeldSkill>;
14
+ clear(): void;
15
+ };
16
+ /** In-memory immutable snapshot publisher. Host must authorize all methods using the same identity. */
17
+ export declare function createSkillPublisher(publications: readonly {
18
+ uri: string;
19
+ files: ReadonlyMap<string, Uint8Array>;
20
+ }[]): Promise<{
21
+ list(): {
22
+ resultType: "complete";
23
+ ttlMs: number;
24
+ cacheScope: "private";
25
+ skills: Skill[];
26
+ };
27
+ get(uri: string): {
28
+ resultType: "complete";
29
+ ttlMs: number;
30
+ cacheScope: "private";
31
+ skill: Skill;
32
+ };
33
+ read(uri: string): {
34
+ resultType: "complete";
35
+ ttlMs: number;
36
+ cacheScope: "private";
37
+ contents: {
38
+ uri: string;
39
+ blob: string;
40
+ }[];
41
+ };
42
+ directoryRead(uri: string): {
43
+ resultType: "complete";
44
+ ttlMs: number;
45
+ cacheScope: "private";
46
+ resources: {
47
+ uri: string;
48
+ name: string;
49
+ mimeType?: string;
50
+ }[];
51
+ };
52
+ }>;