@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,9 @@
1
+ export interface ResourceBudget {
2
+ push(chunk: Uint8Array): void;
3
+ finish(): void;
4
+ }
5
+ /** Explicit resource reads support at most 16 MiB decoded. JSON-escaped base64
6
+ * needs up to eight wire bytes per decoded byte (plus padding); text needs six.
7
+ * URI/metadata/RPC/SSE overhead has a separate 64 KiB cap, not unused payload
8
+ * allowance. Unbounded requests retain the transport's default 4 MiB cap. */
9
+ export declare function createResourceBudget(maxBytes: number, sse: boolean): ResourceBudget;
@@ -0,0 +1,206 @@
1
+ import { McpError } from "./errors.js";
2
+ /** An incremental allocation guard, not a replacement JSON validator. Only strings
3
+ * at result.contents[*].text/blob count. The normal parser validates the envelope
4
+ * and content afterwards. Keys/escapes can cross arbitrary transport chunks. */
5
+ function resourceCounter(maxBytes, payloadByte) {
6
+ const stack = [];
7
+ let inString = false;
8
+ let isKey = false;
9
+ let key = "";
10
+ let escape = false;
11
+ let hex;
12
+ let kind;
13
+ let bytes = 0;
14
+ let highSurrogate = false;
15
+ let base64Characters = 0;
16
+ const valuePath = () => {
17
+ const parent = stack.at(-1);
18
+ return parent === undefined
19
+ ? []
20
+ : [...parent.path, parent.array ? "*" : parent.key];
21
+ };
22
+ function character(char) {
23
+ if (isKey) {
24
+ // Only short protocol keys matter; don't accumulate attacker-sized keys.
25
+ if (key.length < 32)
26
+ key += char;
27
+ return;
28
+ }
29
+ if (kind === "text") {
30
+ const code = char.charCodeAt(0);
31
+ if (code >= 0xdc00 && code <= 0xdfff && highSurrogate)
32
+ bytes += 1;
33
+ else
34
+ bytes += code < 0x80 ? 1 : code < 0x800 ? 2 : 3;
35
+ highSurrogate = code >= 0xd800 && code <= 0xdbff;
36
+ }
37
+ else if (kind === "blob" && char !== "=") {
38
+ // Every non-padding base64 character contributes six bits. Counting before
39
+ // atob/Buffer allocation handles all three padding cases exactly.
40
+ const previous = Math.floor((base64Characters * 6) / 8);
41
+ base64Characters++;
42
+ bytes += Math.floor((base64Characters * 6) / 8) - previous;
43
+ }
44
+ if (bytes > maxBytes)
45
+ throw new McpError("Resource decoded byte limit exceeded");
46
+ }
47
+ return (text) => {
48
+ // Iterate UTF-16 units so raw and escaped surrogate pairs count identically.
49
+ for (let i = 0; i < text.length; i++) {
50
+ const char = text[i];
51
+ if (inString) {
52
+ if (!isKey &&
53
+ kind !== undefined &&
54
+ (char !== '"' || escape || hex !== undefined))
55
+ payloadByte(char);
56
+ if (hex !== undefined) {
57
+ hex += char;
58
+ if (hex.length === 4) {
59
+ character(String.fromCharCode(Number.parseInt(hex, 16)));
60
+ hex = undefined;
61
+ }
62
+ }
63
+ else if (escape) {
64
+ escape = false;
65
+ if (char === "u")
66
+ hex = "";
67
+ else
68
+ character({ b: "\b", f: "\f", n: "\n", r: "\r", t: "\t" }[char] ?? char);
69
+ }
70
+ else if (char === "\\")
71
+ escape = true;
72
+ else if (char === '"') {
73
+ inString = false;
74
+ if (isKey) {
75
+ const parent = stack.at(-1);
76
+ if (parent !== undefined)
77
+ parent.key = key;
78
+ }
79
+ }
80
+ else
81
+ character(char);
82
+ continue;
83
+ }
84
+ const parent = stack.at(-1);
85
+ if (char === '"') {
86
+ inString = true;
87
+ isKey = parent !== undefined && !parent.array && parent.keyNext;
88
+ key = "";
89
+ highSurrogate = false;
90
+ base64Characters = 0;
91
+ const path = valuePath();
92
+ kind =
93
+ !isKey &&
94
+ path.length === 4 &&
95
+ path[0] === "result" &&
96
+ path[1] === "contents" &&
97
+ path[2] === "*"
98
+ ? path[3] === "text"
99
+ ? "text"
100
+ : path[3] === "blob"
101
+ ? "blob"
102
+ : undefined
103
+ : undefined;
104
+ }
105
+ else if (char === "{" || char === "[") {
106
+ if (stack.length >= 64)
107
+ throw new McpError("Resource JSON depth limit exceeded");
108
+ stack.push({
109
+ path: valuePath(),
110
+ array: char === "[",
111
+ key: "",
112
+ keyNext: true,
113
+ });
114
+ }
115
+ else if (char === "}" || char === "]")
116
+ stack.pop();
117
+ else if (char === ":" && parent !== undefined)
118
+ parent.keyNext = false;
119
+ else if (char === "," && parent !== undefined)
120
+ parent.keyNext = true;
121
+ }
122
+ };
123
+ }
124
+ /** Explicit resource reads support at most 16 MiB decoded. JSON-escaped base64
125
+ * needs up to eight wire bytes per decoded byte (plus padding); text needs six.
126
+ * URI/metadata/RPC/SSE overhead has a separate 64 KiB cap, not unused payload
127
+ * allowance. Unbounded requests retain the transport's default 4 MiB cap. */
128
+ export function createResourceBudget(maxBytes, sse) {
129
+ if (!Number.isSafeInteger(maxBytes) || maxBytes < 0)
130
+ throw new McpError("maxDecodedBytes must be a nonnegative safe integer");
131
+ maxBytes = Math.min(maxBytes, 16 * 1024 * 1024);
132
+ const maxEnvelopeBytes = 64 * 1024;
133
+ const maxWireBytes = Math.ceil(maxBytes / 3) * 24 + maxEnvelopeBytes;
134
+ let decodedWireBytes = 0;
135
+ let payloadWireBytes = 0;
136
+ function payloadByte(char) {
137
+ const code = char.charCodeAt(0);
138
+ payloadWireBytes +=
139
+ code < 0x80
140
+ ? 1
141
+ : code < 0x800
142
+ ? 2
143
+ : code >= 0xd800 && code <= 0xdbff
144
+ ? 0
145
+ : code >= 0xdc00 && code <= 0xdfff
146
+ ? 4
147
+ : 3;
148
+ }
149
+ let wireBytes = 0;
150
+ const decoder = new TextDecoder();
151
+ let count = resourceCounter(maxBytes, payloadByte);
152
+ let prefix = "";
153
+ let data = false;
154
+ let lineStarted = false;
155
+ let previousCR = false;
156
+ function feed(text) {
157
+ if (!sse) {
158
+ count(text);
159
+ return;
160
+ }
161
+ for (let i = 0; i < text.length; i++) {
162
+ const char = text[i];
163
+ if (char === "\n" && previousCR) {
164
+ previousCR = false;
165
+ continue;
166
+ }
167
+ previousCR = char === "\r";
168
+ if (char === "\r" || char === "\n") {
169
+ if (!lineStarted)
170
+ count = resourceCounter(maxBytes, payloadByte);
171
+ else if (data)
172
+ count("\n");
173
+ prefix = "";
174
+ data = false;
175
+ lineStarted = false;
176
+ }
177
+ else {
178
+ lineStarted = true;
179
+ if (data)
180
+ count(char);
181
+ else if (prefix.length < 5) {
182
+ prefix += char;
183
+ if (prefix === "data:")
184
+ data = true;
185
+ }
186
+ }
187
+ }
188
+ }
189
+ function accept(text) {
190
+ decodedWireBytes += Buffer.byteLength(text, "utf8");
191
+ feed(text);
192
+ if (decodedWireBytes - payloadWireBytes > maxEnvelopeBytes)
193
+ throw new McpError("Resource metadata/envelope byte limit exceeded");
194
+ }
195
+ return {
196
+ push(chunk) {
197
+ wireBytes += chunk.byteLength;
198
+ if (wireBytes > maxWireBytes)
199
+ throw new McpError("Resource wire byte budget exceeded");
200
+ accept(decoder.decode(chunk, { stream: true }));
201
+ },
202
+ finish() {
203
+ accept(decoder.decode());
204
+ },
205
+ };
206
+ }
@@ -0,0 +1,115 @@
1
+ import { type McpValidationContext, type Skill, type Task, type DetailedTask } from "./types.js";
2
+ export declare const McpToolSchema: import("arktype/internal/variants/object.ts").ObjectType<{
3
+ name: string;
4
+ inputSchema: Record<string, unknown>;
5
+ title?: string;
6
+ description?: string;
7
+ outputSchema?: Record<string, unknown>;
8
+ annotations?: {
9
+ title?: string;
10
+ readOnlyHint?: boolean;
11
+ destructiveHint?: boolean;
12
+ idempotentHint?: boolean;
13
+ openWorldHint?: boolean;
14
+ };
15
+ icons?: unknown[];
16
+ _meta?: Record<string, unknown>;
17
+ }, {}>;
18
+ export type McpTool = typeof McpToolSchema.infer;
19
+ export declare const PromptSchema: import("arktype/internal/variants/object.ts").ObjectType<{
20
+ name: string;
21
+ title?: string;
22
+ description?: string;
23
+ arguments?: {
24
+ name: string;
25
+ description?: string;
26
+ required?: boolean;
27
+ }[];
28
+ icons?: unknown[];
29
+ _meta?: Record<string, unknown>;
30
+ }, {}>;
31
+ export declare const ResourceSchema: import("arktype/internal/variants/object.ts").ObjectType<{
32
+ uri: string;
33
+ name: string;
34
+ title?: string;
35
+ description?: string;
36
+ mimeType?: string;
37
+ size?: number;
38
+ annotations?: Record<string, unknown>;
39
+ icons?: unknown[];
40
+ _meta?: Record<string, unknown>;
41
+ }, {}>;
42
+ export declare const TemplateSchema: import("arktype/internal/variants/object.ts").ObjectType<{
43
+ uriTemplate: string;
44
+ name: string;
45
+ title?: string;
46
+ description?: string;
47
+ mimeType?: string;
48
+ annotations?: Record<string, unknown>;
49
+ icons?: unknown[];
50
+ _meta?: Record<string, unknown>;
51
+ }, {}>;
52
+ export declare const SkillSchema: import("arktype/internal/variants/object.ts").ObjectType<{
53
+ uri: string;
54
+ frontmatter: {
55
+ [x: string]: unknown;
56
+ name: string;
57
+ description: string;
58
+ };
59
+ resources: unknown;
60
+ _meta?: Record<string, unknown>;
61
+ }, {}>;
62
+ export declare const TaskHandleSchema: import("arktype/internal/variants/object.ts").ObjectType<{
63
+ taskId: string;
64
+ status: "cancelled" | "input_required" | "working" | "completed" | "failed";
65
+ createdAt: string;
66
+ lastUpdatedAt: string;
67
+ ttlMs: number | null;
68
+ pollIntervalMs?: number;
69
+ statusMessage?: string;
70
+ _meta?: Record<string, unknown>;
71
+ }, {}>;
72
+ export declare const ToolCallResult: import("arktype/internal/variants/object.ts").ObjectType<{
73
+ content: unknown;
74
+ isError?: boolean;
75
+ structuredContent?: unknown;
76
+ _meta?: Record<string, unknown>;
77
+ }, {}>;
78
+ export declare const PromptResult: import("arktype/internal/variants/object.ts").ObjectType<{
79
+ messages: unknown[];
80
+ description?: string;
81
+ _meta?: Record<string, unknown>;
82
+ }, {}>;
83
+ export declare const CompletionResult: import("arktype/internal/variants/object.ts").ObjectType<{
84
+ completion: {
85
+ values: string[];
86
+ total?: number;
87
+ hasMore?: boolean;
88
+ };
89
+ }, {}>;
90
+ export declare const DiscoverResult: import("arktype/internal/variants/object.ts").ObjectType<{
91
+ supportedVersions: string[];
92
+ capabilities: Record<string, unknown>;
93
+ instructions?: string;
94
+ _meta?: Record<string, unknown>;
95
+ }, {}>;
96
+ export declare const JsonRpcResponse: import("arktype/internal/variants/object.ts").ObjectType<{
97
+ jsonrpc: "2.0";
98
+ id: string | number | null;
99
+ result?: unknown;
100
+ error?: {
101
+ code: number;
102
+ message: string;
103
+ data?: unknown;
104
+ };
105
+ }, {}>;
106
+ export declare function record(value: unknown, label?: string): Record<string, unknown>;
107
+ /** Tokens are protocol integers (not fractional progress values) or strings. */
108
+ export declare function validateProgressToken(value: unknown): asserts value is string | number;
109
+ export declare function validateInputRequests(value: unknown, context?: McpValidationContext): void;
110
+ export declare function validateInputResponses(value: unknown): void;
111
+ export declare function validateTask(value: unknown, detailed?: boolean, context?: McpValidationContext): Task | DetailedTask;
112
+ export declare function validateSkill(value: unknown): Skill;
113
+ export declare function validateRequest(method: string, value: unknown, context?: McpValidationContext): Record<string, unknown>;
114
+ export declare function validateResult(method: string, value: unknown, context?: McpValidationContext): Record<string, unknown>;
115
+ export declare function validateNotification(method: string, value: unknown, context?: McpValidationContext): Record<string, unknown>;