@descent-vtt/spec-harness 0.0.0 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +16 -0
- package/.claude-plugin/plugin.json +17 -0
- package/.mcp.json +12 -0
- package/CHANGELOG.md +46 -0
- package/README.md +127 -9
- package/bin/spec-harness.js +19 -0
- package/dist/audit.d.ts +69 -0
- package/dist/audit.js +93 -0
- package/dist/audit.js.map +1 -0
- package/dist/branch.d.ts +26 -0
- package/dist/branch.js +100 -0
- package/dist/branch.js.map +1 -0
- package/dist/briefs.d.ts +49 -0
- package/dist/briefs.js +111 -0
- package/dist/briefs.js.map +1 -0
- package/dist/cli.d.ts +14 -0
- package/dist/cli.js +245 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands.d.ts +18 -0
- package/dist/commands.js +224 -0
- package/dist/commands.js.map +1 -0
- package/dist/config.d.ts +57 -0
- package/dist/config.js +167 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +56 -0
- package/dist/context.js +125 -0
- package/dist/context.js.map +1 -0
- package/dist/document.d.ts +33 -0
- package/dist/document.js +9 -0
- package/dist/document.js.map +1 -0
- package/dist/fs.d.ts +29 -0
- package/dist/fs.js +85 -0
- package/dist/fs.js.map +1 -0
- package/dist/git.d.ts +57 -0
- package/dist/git.js +129 -0
- package/dist/git.js.map +1 -0
- package/dist/guard.d.ts +43 -0
- package/dist/guard.js +120 -0
- package/dist/guard.js.map +1 -0
- package/dist/hooks.d.ts +50 -0
- package/dist/hooks.js +109 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/junit.d.ts +30 -0
- package/dist/junit.js +166 -0
- package/dist/junit.js.map +1 -0
- package/dist/manifests.d.ts +52 -0
- package/dist/manifests.js +346 -0
- package/dist/manifests.js.map +1 -0
- package/dist/plugin.d.ts +45 -0
- package/dist/plugin.js +79 -0
- package/dist/plugin.js.map +1 -0
- package/dist/premises.d.ts +16 -0
- package/dist/premises.js +71 -0
- package/dist/premises.js.map +1 -0
- package/dist/probe.d.ts +108 -0
- package/dist/probe.js +203 -0
- package/dist/probe.js.map +1 -0
- package/dist/reader.d.ts +8 -0
- package/dist/reader.js +105 -0
- package/dist/reader.js.map +1 -0
- package/dist/round.d.ts +68 -0
- package/dist/round.js +339 -0
- package/dist/round.js.map +1 -0
- package/dist/rulings.d.ts +92 -0
- package/dist/rulings.js +160 -0
- package/dist/rulings.js.map +1 -0
- package/dist/sandbox.d.ts +28 -0
- package/dist/sandbox.js +110 -0
- package/dist/sandbox.js.map +1 -0
- package/dist/server.d.ts +13 -0
- package/dist/server.js +212 -0
- package/dist/server.js.map +1 -0
- package/dist/setup.d.ts +32 -0
- package/dist/setup.js +218 -0
- package/dist/setup.js.map +1 -0
- package/dist/siblings.d.ts +66 -0
- package/dist/siblings.js +134 -0
- package/dist/siblings.js.map +1 -0
- package/dist/types.d.ts +38 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/vendor/spec-core/jsonrpc/index.d.ts +2 -0
- package/dist/vendor/spec-core/jsonrpc/index.js +2 -0
- package/dist/vendor/spec-core/jsonrpc/index.js.map +1 -0
- package/dist/vendor/spec-core/jsonrpc/mcp.d.ts +157 -0
- package/dist/vendor/spec-core/jsonrpc/mcp.js +353 -0
- package/dist/vendor/spec-core/jsonrpc/mcp.js.map +1 -0
- package/dist/vendor/spec-core/markdown/frontmatter.d.ts +103 -0
- package/dist/vendor/spec-core/markdown/frontmatter.js +459 -0
- package/dist/vendor/spec-core/markdown/frontmatter.js.map +1 -0
- package/dist/vendor/spec-core/markdown/headings.d.ts +45 -0
- package/dist/vendor/spec-core/markdown/headings.js +199 -0
- package/dist/vendor/spec-core/markdown/headings.js.map +1 -0
- package/dist/vendor/spec-core/markdown/index.d.ts +5 -0
- package/dist/vendor/spec-core/markdown/index.js +4 -0
- package/dist/vendor/spec-core/markdown/index.js.map +1 -0
- package/dist/vendor/spec-core/markdown/layout.d.ts +39 -0
- package/dist/vendor/spec-core/markdown/layout.js +28 -0
- package/dist/vendor/spec-core/markdown/layout.js.map +1 -0
- package/dist/vendor/spec-core/markdown/links.d.ts +22 -0
- package/dist/vendor/spec-core/markdown/links.js +364 -0
- package/dist/vendor/spec-core/markdown/links.js.map +1 -0
- package/dist/vendor/spec-core/markdown/lists.d.ts +22 -0
- package/dist/vendor/spec-core/markdown/lists.js +127 -0
- package/dist/vendor/spec-core/markdown/lists.js.map +1 -0
- package/dist/vendor/spec-core/markdown/scan.d.ts +36 -0
- package/dist/vendor/spec-core/markdown/scan.js +439 -0
- package/dist/vendor/spec-core/markdown/scan.js.map +1 -0
- package/dist/vendor/spec-core/markdown/syntax.d.ts +75 -0
- package/dist/vendor/spec-core/markdown/syntax.js +181 -0
- package/dist/vendor/spec-core/markdown/syntax.js.map +1 -0
- package/dist/vendor/spec-core/markdown/tables.d.ts +18 -0
- package/dist/vendor/spec-core/markdown/tables.js +86 -0
- package/dist/vendor/spec-core/markdown/tables.js.map +1 -0
- package/dist/vendor/spec-core/markdown/types.d.ts +287 -0
- package/dist/vendor/spec-core/markdown/types.js +9 -0
- package/dist/vendor/spec-core/markdown/types.js.map +1 -0
- package/dist/vendor/spec-core/path/index.d.ts +1 -0
- package/dist/vendor/spec-core/path/index.js +2 -0
- package/dist/vendor/spec-core/path/index.js.map +1 -0
- package/dist/vendor/spec-core/path/posix.d.ts +83 -0
- package/dist/vendor/spec-core/path/posix.js +150 -0
- package/dist/vendor/spec-core/path/posix.js.map +1 -0
- package/dist/vendor/spec-core/pattern/automaton.d.ts +129 -0
- package/dist/vendor/spec-core/pattern/automaton.js +340 -0
- package/dist/vendor/spec-core/pattern/automaton.js.map +1 -0
- package/dist/vendor/spec-core/pattern/charset.d.ts +58 -0
- package/dist/vendor/spec-core/pattern/charset.js +116 -0
- package/dist/vendor/spec-core/pattern/charset.js.map +1 -0
- package/dist/vendor/spec-core/pattern/glob.d.ts +121 -0
- package/dist/vendor/spec-core/pattern/glob.js +481 -0
- package/dist/vendor/spec-core/pattern/glob.js.map +1 -0
- package/dist/vendor/spec-core/pattern/index.d.ts +6 -0
- package/dist/vendor/spec-core/pattern/index.js +4 -0
- package/dist/vendor/spec-core/pattern/index.js.map +1 -0
- package/dist/vendor/spec-core/pattern/regex.d.ts +67 -0
- package/dist/vendor/spec-core/pattern/regex.js +813 -0
- package/dist/vendor/spec-core/pattern/regex.js.map +1 -0
- package/dist/vendor/spec-core/text/index.d.ts +2 -0
- package/dist/vendor/spec-core/text/index.js +2 -0
- package/dist/vendor/spec-core/text/index.js.map +1 -0
- package/dist/vendor/spec-core/text/lines.d.ts +72 -0
- package/dist/vendor/spec-core/text/lines.js +156 -0
- package/dist/vendor/spec-core/text/lines.js.map +1 -0
- package/dist/versions.d.ts +42 -0
- package/dist/versions.js +57 -0
- package/dist/versions.js.map +1 -0
- package/dist/workspace.d.ts +77 -0
- package/dist/workspace.js +138 -0
- package/dist/workspace.js.map +1 -0
- package/hooks/hooks.json +28 -0
- package/package.json +86 -6
- package/skills/close-round/SKILL.md +38 -0
- package/skills/draft-brief/SKILL.md +64 -0
- package/skills/run-round/SKILL.md +46 -0
- package/skills/split-goal/SKILL.md +42 -0
- package/src/vendor/spec-core/LICENSE +21 -0
- package/src/vendor/spec-core/README.md +8 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Model Context Protocol over JSON-RPC 2.0, without an SDK.
|
|
3
|
+
*
|
|
4
|
+
* MCP over stdio is JSON-RPC 2.0, one message per line, and what a server must
|
|
5
|
+
* get right fits here: framing, the two eras of the protocol, and the methods
|
|
6
|
+
* that serve tools, resources and prompts. The official SDK brings a schema
|
|
7
|
+
* library and a dependency tree to do the same; every spec-* tool promises no
|
|
8
|
+
* runtime dependencies. Moved here from spec-guard (its ADR-0012), where it
|
|
9
|
+
* was first written and measured, so that a second server does not relearn it.
|
|
10
|
+
*
|
|
11
|
+
* Two eras, served side by side. Revisions up to 2025-11-25 open with an
|
|
12
|
+
* `initialize` handshake; 2026-07-28 has none, and every request carries its
|
|
13
|
+
* protocol version in `_meta`. Clients of both are in use - the newest
|
|
14
|
+
* revision is not yet the one most clients speak - so each request is
|
|
15
|
+
* classified on its own, by the rule the TypeScript SDK's server applies: a
|
|
16
|
+
* request that claims a version in `_meta` is modern and its claim is
|
|
17
|
+
* validated; anything else, `initialize` included, is legacy.
|
|
18
|
+
*
|
|
19
|
+
* Nothing here touches a stream or a file. A server is a function from one
|
|
20
|
+
* parsed message to the message owed back; `serveLines` binds one to any
|
|
21
|
+
* source of bytes with `on('data')`, which on Node is `process.stdin`.
|
|
22
|
+
*/
|
|
23
|
+
/** Revisions that carry their version on every request. Newest first. */
|
|
24
|
+
export declare const MODERN_PROTOCOL_VERSIONS: readonly string[];
|
|
25
|
+
/** Revisions negotiated by `initialize`, newest first - the SDK's own list. */
|
|
26
|
+
export declare const LEGACY_PROTOCOL_VERSIONS: readonly string[];
|
|
27
|
+
export declare const PROTOCOL_VERSION_KEY = "io.modelcontextprotocol/protocolVersion";
|
|
28
|
+
export declare const CLIENT_CAPABILITIES_KEY = "io.modelcontextprotocol/clientCapabilities";
|
|
29
|
+
export declare const CLIENT_INFO_KEY = "io.modelcontextprotocol/clientInfo";
|
|
30
|
+
export declare const SERVER_INFO_KEY = "io.modelcontextprotocol/serverInfo";
|
|
31
|
+
export declare const PARSE_ERROR = -32700;
|
|
32
|
+
export declare const INVALID_REQUEST = -32600;
|
|
33
|
+
export declare const METHOD_NOT_FOUND = -32601;
|
|
34
|
+
export declare const INVALID_PARAMS = -32602;
|
|
35
|
+
export declare const INTERNAL_ERROR = -32603;
|
|
36
|
+
/** Resource not found before 2026-07-28, which forbids it in favour of -32602. */
|
|
37
|
+
export declare const LEGACY_RESOURCE_NOT_FOUND = -32002;
|
|
38
|
+
export declare const UNSUPPORTED_PROTOCOL_VERSION = -32022;
|
|
39
|
+
export type RequestId = string | number;
|
|
40
|
+
export type Era = 'legacy' | 'modern';
|
|
41
|
+
export type JsonObject = Record<string, unknown>;
|
|
42
|
+
export interface ErrorObject {
|
|
43
|
+
readonly code: number;
|
|
44
|
+
readonly message: string;
|
|
45
|
+
readonly data?: unknown;
|
|
46
|
+
}
|
|
47
|
+
/** Everything a server here writes. It never sends a request. */
|
|
48
|
+
export type OutgoingMessage = {
|
|
49
|
+
readonly jsonrpc: '2.0';
|
|
50
|
+
readonly id: RequestId;
|
|
51
|
+
readonly result: JsonObject;
|
|
52
|
+
} | {
|
|
53
|
+
readonly jsonrpc: '2.0';
|
|
54
|
+
readonly id?: RequestId;
|
|
55
|
+
readonly error: ErrorObject;
|
|
56
|
+
};
|
|
57
|
+
/** An error that becomes a JSON-RPC error response with its code. */
|
|
58
|
+
export declare class ProtocolError extends Error {
|
|
59
|
+
readonly code: number;
|
|
60
|
+
readonly data: unknown;
|
|
61
|
+
constructor(code: number, message: string, data?: unknown);
|
|
62
|
+
}
|
|
63
|
+
export declare function isObject(value: unknown): value is JsonObject;
|
|
64
|
+
/** JSON-RPC allows a null id; MCP does not, and wants an integer if a number. */
|
|
65
|
+
export declare function isRequestId(value: unknown): value is RequestId;
|
|
66
|
+
/**
|
|
67
|
+
* What is wrong with a request's `_meta` once it claims a protocol version,
|
|
68
|
+
* or `undefined`. A claim is never ignored: a malformed one is an error, not
|
|
69
|
+
* a reason to fall back to the legacy handling.
|
|
70
|
+
*/
|
|
71
|
+
export declare function envelopeIssue(meta: JsonObject): string | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* The era a request belongs to, or the error that answers it instead.
|
|
74
|
+
*
|
|
75
|
+
* `initialize` is the legacy handshake unless it carries a valid modern claim.
|
|
76
|
+
* Any other request is modern exactly when `_meta` holds the version key - its
|
|
77
|
+
* presence is the claim, whatever its value - and legacy otherwise.
|
|
78
|
+
*/
|
|
79
|
+
export declare function classifyRequest(method: string, params: JsonObject | undefined): Era;
|
|
80
|
+
/** The version `initialize` settles on: the one asked for, or the newest legacy one. */
|
|
81
|
+
export declare function negotiateLegacyVersion(requested: unknown): string;
|
|
82
|
+
/** What a tool call produced: text for the model, and the same as data. */
|
|
83
|
+
export interface ToolOutcome {
|
|
84
|
+
readonly text: string;
|
|
85
|
+
readonly structured?: JsonObject | undefined;
|
|
86
|
+
readonly isError?: boolean | undefined;
|
|
87
|
+
}
|
|
88
|
+
export interface ToolDefinition {
|
|
89
|
+
/** The descriptor `tools/list` returns: name, title, description, inputSchema, annotations. */
|
|
90
|
+
readonly descriptor: JsonObject & {
|
|
91
|
+
readonly name: string;
|
|
92
|
+
};
|
|
93
|
+
/** Runs the tool. Arguments arrive as an object, unvalidated beyond that. */
|
|
94
|
+
call(args: JsonObject): Promise<ToolOutcome>;
|
|
95
|
+
}
|
|
96
|
+
export interface ResourceProvider {
|
|
97
|
+
/** Concrete resources, as `resources/list` returns them. */
|
|
98
|
+
list(): Promise<readonly JsonObject[]>;
|
|
99
|
+
/** URI templates, as `resources/templates/list` returns them. */
|
|
100
|
+
readonly templates?: readonly JsonObject[] | undefined;
|
|
101
|
+
/** The contents of one resource, or `null` when there is no such resource. */
|
|
102
|
+
read(uri: string): Promise<readonly JsonObject[] | null>;
|
|
103
|
+
}
|
|
104
|
+
export interface PromptDefinition {
|
|
105
|
+
/** The descriptor `prompts/list` returns: name, title, description, arguments. */
|
|
106
|
+
readonly descriptor: JsonObject & {
|
|
107
|
+
readonly name: string;
|
|
108
|
+
};
|
|
109
|
+
/** The messages the prompt expands to, given its arguments as strings. */
|
|
110
|
+
get(args: Readonly<Record<string, string>>): Promise<JsonObject>;
|
|
111
|
+
}
|
|
112
|
+
export interface McpServerDefinition {
|
|
113
|
+
readonly name: string;
|
|
114
|
+
readonly version: string;
|
|
115
|
+
/** Sent in the handshake: what the server is for, and when to call what. */
|
|
116
|
+
readonly instructions: string;
|
|
117
|
+
readonly tools?: readonly ToolDefinition[] | undefined;
|
|
118
|
+
readonly resources?: ResourceProvider | undefined;
|
|
119
|
+
readonly prompts?: readonly PromptDefinition[] | undefined;
|
|
120
|
+
/**
|
|
121
|
+
* Whether results other than a tool call's may be cached by a modern
|
|
122
|
+
* client, and for how long. Absent: every result is stale at once and
|
|
123
|
+
* private, which is right for a server that reads the repository afresh
|
|
124
|
+
* on each request.
|
|
125
|
+
*/
|
|
126
|
+
readonly cacheTtlMs?: number | undefined;
|
|
127
|
+
}
|
|
128
|
+
/** A tool's failure, reported to the model rather than as a protocol error it cannot read. */
|
|
129
|
+
export declare function toolError(text: string): ToolOutcome;
|
|
130
|
+
/**
|
|
131
|
+
* Arguments a tool does not declare, which the model should hear about rather
|
|
132
|
+
* than have silently dropped. `undefined` when there are none.
|
|
133
|
+
*/
|
|
134
|
+
export declare function unknownArguments(args: JsonObject, allowed: readonly string[]): ToolOutcome | undefined;
|
|
135
|
+
/**
|
|
136
|
+
* Builds the function that answers one parsed JSON-RPC message: the message
|
|
137
|
+
* to send back, or `null` when nothing is owed - a notification, or a
|
|
138
|
+
* response the client should not have sent.
|
|
139
|
+
*/
|
|
140
|
+
export declare function createMcpServer(definition: McpServerDefinition): (message: unknown) => Promise<OutgoingMessage | null>;
|
|
141
|
+
/** Anything that delivers bytes and says when it has finished: `process.stdin`, or a test's stand-in. */
|
|
142
|
+
export interface ByteSource {
|
|
143
|
+
on(event: 'data', listener: (chunk: Uint8Array) => void): unknown;
|
|
144
|
+
once(event: 'end', listener: () => void): unknown;
|
|
145
|
+
once(event: 'error', listener: (error: Error) => void): unknown;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Serves a handler over newline-delimited JSON-RPC until the input ends.
|
|
149
|
+
*
|
|
150
|
+
* Messages are split on `\n`; a CRLF line keeps its `\r`, which JSON reads
|
|
151
|
+
* as whitespace. Blank lines are skipped, and every response is written as a
|
|
152
|
+
* single line - `JSON.stringify` never emits a raw newline, which is what the
|
|
153
|
+
* binding requires. Requests are answered concurrently, in whatever order
|
|
154
|
+
* they finish. A request the client cancels gets no response. When the input
|
|
155
|
+
* closes, requests still running finish and then this resolves.
|
|
156
|
+
*/
|
|
157
|
+
export declare function serveLines(input: ByteSource, write: (line: string) => void, handle: (message: unknown) => Promise<OutgoingMessage | null>): Promise<void>;
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Model Context Protocol over JSON-RPC 2.0, without an SDK.
|
|
3
|
+
*
|
|
4
|
+
* MCP over stdio is JSON-RPC 2.0, one message per line, and what a server must
|
|
5
|
+
* get right fits here: framing, the two eras of the protocol, and the methods
|
|
6
|
+
* that serve tools, resources and prompts. The official SDK brings a schema
|
|
7
|
+
* library and a dependency tree to do the same; every spec-* tool promises no
|
|
8
|
+
* runtime dependencies. Moved here from spec-guard (its ADR-0012), where it
|
|
9
|
+
* was first written and measured, so that a second server does not relearn it.
|
|
10
|
+
*
|
|
11
|
+
* Two eras, served side by side. Revisions up to 2025-11-25 open with an
|
|
12
|
+
* `initialize` handshake; 2026-07-28 has none, and every request carries its
|
|
13
|
+
* protocol version in `_meta`. Clients of both are in use - the newest
|
|
14
|
+
* revision is not yet the one most clients speak - so each request is
|
|
15
|
+
* classified on its own, by the rule the TypeScript SDK's server applies: a
|
|
16
|
+
* request that claims a version in `_meta` is modern and its claim is
|
|
17
|
+
* validated; anything else, `initialize` included, is legacy.
|
|
18
|
+
*
|
|
19
|
+
* Nothing here touches a stream or a file. A server is a function from one
|
|
20
|
+
* parsed message to the message owed back; `serveLines` binds one to any
|
|
21
|
+
* source of bytes with `on('data')`, which on Node is `process.stdin`.
|
|
22
|
+
*/
|
|
23
|
+
/** Revisions that carry their version on every request. Newest first. */
|
|
24
|
+
export const MODERN_PROTOCOL_VERSIONS = ['2026-07-28'];
|
|
25
|
+
/** Revisions negotiated by `initialize`, newest first - the SDK's own list. */
|
|
26
|
+
export const LEGACY_PROTOCOL_VERSIONS = ['2025-11-25', '2025-06-18', '2025-03-26', '2024-11-05', '2024-10-07'];
|
|
27
|
+
export const PROTOCOL_VERSION_KEY = 'io.modelcontextprotocol/protocolVersion';
|
|
28
|
+
export const CLIENT_CAPABILITIES_KEY = 'io.modelcontextprotocol/clientCapabilities';
|
|
29
|
+
export const CLIENT_INFO_KEY = 'io.modelcontextprotocol/clientInfo';
|
|
30
|
+
export const SERVER_INFO_KEY = 'io.modelcontextprotocol/serverInfo';
|
|
31
|
+
export const PARSE_ERROR = -32700;
|
|
32
|
+
export const INVALID_REQUEST = -32600;
|
|
33
|
+
export const METHOD_NOT_FOUND = -32601;
|
|
34
|
+
export const INVALID_PARAMS = -32602;
|
|
35
|
+
export const INTERNAL_ERROR = -32603;
|
|
36
|
+
/** Resource not found before 2026-07-28, which forbids it in favour of -32602. */
|
|
37
|
+
export const LEGACY_RESOURCE_NOT_FOUND = -32002;
|
|
38
|
+
export const UNSUPPORTED_PROTOCOL_VERSION = -32022;
|
|
39
|
+
/** An error that becomes a JSON-RPC error response with its code. */
|
|
40
|
+
export class ProtocolError extends Error {
|
|
41
|
+
code;
|
|
42
|
+
data;
|
|
43
|
+
constructor(code, message, data) {
|
|
44
|
+
super(message);
|
|
45
|
+
this.name = 'ProtocolError';
|
|
46
|
+
this.code = code;
|
|
47
|
+
this.data = data;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
export function isObject(value) {
|
|
51
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
52
|
+
}
|
|
53
|
+
/** JSON-RPC allows a null id; MCP does not, and wants an integer if a number. */
|
|
54
|
+
export function isRequestId(value) {
|
|
55
|
+
return typeof value === 'string' || Number.isInteger(value);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* What is wrong with a request's `_meta` once it claims a protocol version,
|
|
59
|
+
* or `undefined`. A claim is never ignored: a malformed one is an error, not
|
|
60
|
+
* a reason to fall back to the legacy handling.
|
|
61
|
+
*/
|
|
62
|
+
export function envelopeIssue(meta) {
|
|
63
|
+
if (!(CLIENT_CAPABILITIES_KEY in meta))
|
|
64
|
+
return `${CLIENT_CAPABILITIES_KEY}: missing`;
|
|
65
|
+
if (typeof meta[PROTOCOL_VERSION_KEY] !== 'string')
|
|
66
|
+
return `${PROTOCOL_VERSION_KEY}: expected a string`;
|
|
67
|
+
if (!isObject(meta[CLIENT_CAPABILITIES_KEY]))
|
|
68
|
+
return `${CLIENT_CAPABILITIES_KEY}: expected an object`;
|
|
69
|
+
const info = meta[CLIENT_INFO_KEY];
|
|
70
|
+
if (info !== undefined && !(isObject(info) && typeof info['name'] === 'string' && typeof info['version'] === 'string')) {
|
|
71
|
+
return `${CLIENT_INFO_KEY}: expected an object with a string name and version`;
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The era a request belongs to, or the error that answers it instead.
|
|
77
|
+
*
|
|
78
|
+
* `initialize` is the legacy handshake unless it carries a valid modern claim.
|
|
79
|
+
* Any other request is modern exactly when `_meta` holds the version key - its
|
|
80
|
+
* presence is the claim, whatever its value - and legacy otherwise.
|
|
81
|
+
*/
|
|
82
|
+
export function classifyRequest(method, params) {
|
|
83
|
+
const meta = params?.['_meta'];
|
|
84
|
+
const claimed = isObject(meta) && PROTOCOL_VERSION_KEY in meta;
|
|
85
|
+
if (!claimed)
|
|
86
|
+
return 'legacy';
|
|
87
|
+
const issue = envelopeIssue(meta);
|
|
88
|
+
const version = meta[PROTOCOL_VERSION_KEY];
|
|
89
|
+
const supported = issue === undefined && MODERN_PROTOCOL_VERSIONS.includes(version);
|
|
90
|
+
if (method === 'initialize' && !supported)
|
|
91
|
+
return 'legacy';
|
|
92
|
+
if (issue !== undefined)
|
|
93
|
+
throw new ProtocolError(INVALID_PARAMS, `Invalid _meta envelope: ${issue}`);
|
|
94
|
+
if (!supported) {
|
|
95
|
+
throw new ProtocolError(UNSUPPORTED_PROTOCOL_VERSION, 'Unsupported protocol version', {
|
|
96
|
+
supported: [...MODERN_PROTOCOL_VERSIONS],
|
|
97
|
+
requested: version,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
return 'modern';
|
|
101
|
+
}
|
|
102
|
+
/** The version `initialize` settles on: the one asked for, or the newest legacy one. */
|
|
103
|
+
export function negotiateLegacyVersion(requested) {
|
|
104
|
+
return LEGACY_PROTOCOL_VERSIONS.includes(requested) ? requested : LEGACY_PROTOCOL_VERSIONS[0];
|
|
105
|
+
}
|
|
106
|
+
/** A tool's failure, reported to the model rather than as a protocol error it cannot read. */
|
|
107
|
+
export function toolError(text) {
|
|
108
|
+
return { text, isError: true };
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Arguments a tool does not declare, which the model should hear about rather
|
|
112
|
+
* than have silently dropped. `undefined` when there are none.
|
|
113
|
+
*/
|
|
114
|
+
export function unknownArguments(args, allowed) {
|
|
115
|
+
const unknown = Object.keys(args).filter((name) => !allowed.includes(name));
|
|
116
|
+
if (unknown.length === 0)
|
|
117
|
+
return undefined;
|
|
118
|
+
const list = unknown.map((name) => `"${name}"`).join(', ');
|
|
119
|
+
const takes = allowed.length === 0
|
|
120
|
+
? 'no arguments'
|
|
121
|
+
: allowed.length === 1
|
|
122
|
+
? allowed[0]
|
|
123
|
+
: `${allowed.slice(0, -1).join(', ')} and ${allowed[allowed.length - 1]}`;
|
|
124
|
+
return toolError(`Unknown argument${unknown.length === 1 ? '' : 's'} ${list}; this tool takes ${takes}.`);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Builds the function that answers one parsed JSON-RPC message: the message
|
|
128
|
+
* to send back, or `null` when nothing is owed - a notification, or a
|
|
129
|
+
* response the client should not have sent.
|
|
130
|
+
*/
|
|
131
|
+
export function createMcpServer(definition) {
|
|
132
|
+
const serverInfo = { name: definition.name, version: definition.version };
|
|
133
|
+
const tools = definition.tools ?? [];
|
|
134
|
+
const prompts = definition.prompts ?? [];
|
|
135
|
+
const capabilities = {
|
|
136
|
+
...(tools.length > 0 ? { tools: {} } : {}),
|
|
137
|
+
...(definition.resources !== undefined ? { resources: {} } : {}),
|
|
138
|
+
...(prompts.length > 0 ? { prompts: {} } : {}),
|
|
139
|
+
};
|
|
140
|
+
const refuseCursor = (params) => {
|
|
141
|
+
if (params?.['cursor'] !== undefined)
|
|
142
|
+
throw new ProtocolError(INVALID_PARAMS, 'Invalid cursor: this server does not paginate.');
|
|
143
|
+
};
|
|
144
|
+
const callTool = async (params) => {
|
|
145
|
+
const name = params['name'];
|
|
146
|
+
if (typeof name !== 'string')
|
|
147
|
+
throw new ProtocolError(INVALID_PARAMS, 'tools/call needs the name of a tool.');
|
|
148
|
+
const tool = tools.find((candidate) => candidate.descriptor.name === name);
|
|
149
|
+
if (tool === undefined)
|
|
150
|
+
throw new ProtocolError(INVALID_PARAMS, `Unknown tool: ${name}`);
|
|
151
|
+
const args = params['arguments'] ?? {};
|
|
152
|
+
if (!isObject(args))
|
|
153
|
+
throw new ProtocolError(INVALID_PARAMS, 'Tool arguments must be an object.');
|
|
154
|
+
let outcome;
|
|
155
|
+
try {
|
|
156
|
+
outcome = await tool.call(args);
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
outcome = toolError(`${definition.name} failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
content: [{ type: 'text', text: outcome.text }],
|
|
163
|
+
...(outcome.structured === undefined ? {} : { structuredContent: outcome.structured }),
|
|
164
|
+
...(outcome.isError === true ? { isError: true } : {}),
|
|
165
|
+
};
|
|
166
|
+
};
|
|
167
|
+
const readResource = async (params, era) => {
|
|
168
|
+
const uri = params['uri'];
|
|
169
|
+
if (typeof uri !== 'string')
|
|
170
|
+
throw new ProtocolError(INVALID_PARAMS, 'resources/read needs a uri.');
|
|
171
|
+
const contents = await definition.resources.read(uri);
|
|
172
|
+
if (contents === null) {
|
|
173
|
+
throw new ProtocolError(era === 'modern' ? INVALID_PARAMS : LEGACY_RESOURCE_NOT_FOUND, 'Resource not found', { uri });
|
|
174
|
+
}
|
|
175
|
+
return { contents: [...contents] };
|
|
176
|
+
};
|
|
177
|
+
const getPrompt = async (params) => {
|
|
178
|
+
const name = params['name'];
|
|
179
|
+
if (typeof name !== 'string')
|
|
180
|
+
throw new ProtocolError(INVALID_PARAMS, 'prompts/get needs the name of a prompt.');
|
|
181
|
+
const prompt = prompts.find((candidate) => candidate.descriptor.name === name);
|
|
182
|
+
if (prompt === undefined)
|
|
183
|
+
throw new ProtocolError(INVALID_PARAMS, `Unknown prompt: ${name}`);
|
|
184
|
+
const args = params['arguments'] ?? {};
|
|
185
|
+
if (!isObject(args) || !Object.values(args).every((value) => typeof value === 'string')) {
|
|
186
|
+
throw new ProtocolError(INVALID_PARAMS, 'Prompt arguments must be an object of strings.');
|
|
187
|
+
}
|
|
188
|
+
return prompt.get(args);
|
|
189
|
+
};
|
|
190
|
+
const dispatch = async (method, params, era) => {
|
|
191
|
+
const given = params ?? {};
|
|
192
|
+
if (era === 'legacy') {
|
|
193
|
+
if (method === 'initialize') {
|
|
194
|
+
return {
|
|
195
|
+
protocolVersion: negotiateLegacyVersion(given['protocolVersion']),
|
|
196
|
+
capabilities,
|
|
197
|
+
serverInfo,
|
|
198
|
+
instructions: definition.instructions,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
if (method === 'ping')
|
|
202
|
+
return {};
|
|
203
|
+
}
|
|
204
|
+
else if (method === 'server/discover') {
|
|
205
|
+
return { supportedVersions: [...MODERN_PROTOCOL_VERSIONS], capabilities, instructions: definition.instructions };
|
|
206
|
+
}
|
|
207
|
+
// A method for a capability the server did not declare does not exist on
|
|
208
|
+
// it: the answer is the one for any unknown method, not an empty list that
|
|
209
|
+
// reads as "declared, and empty".
|
|
210
|
+
const family = method.slice(0, method.indexOf('/') + 1);
|
|
211
|
+
if ((family === 'tools/' && tools.length === 0) ||
|
|
212
|
+
(family === 'resources/' && definition.resources === undefined) ||
|
|
213
|
+
(family === 'prompts/' && prompts.length === 0)) {
|
|
214
|
+
throw new ProtocolError(METHOD_NOT_FOUND, 'Method not found');
|
|
215
|
+
}
|
|
216
|
+
switch (method) {
|
|
217
|
+
case 'tools/list':
|
|
218
|
+
refuseCursor(params);
|
|
219
|
+
return { tools: tools.map((tool) => tool.descriptor) };
|
|
220
|
+
case 'tools/call':
|
|
221
|
+
return callTool(given);
|
|
222
|
+
case 'resources/list':
|
|
223
|
+
refuseCursor(params);
|
|
224
|
+
return { resources: [...(await definition.resources.list())] };
|
|
225
|
+
case 'resources/templates/list':
|
|
226
|
+
refuseCursor(params);
|
|
227
|
+
return { resourceTemplates: [...(definition.resources.templates ?? [])] };
|
|
228
|
+
case 'resources/read':
|
|
229
|
+
return readResource(given, era);
|
|
230
|
+
case 'prompts/list':
|
|
231
|
+
refuseCursor(params);
|
|
232
|
+
return { prompts: prompts.map((prompt) => prompt.descriptor) };
|
|
233
|
+
case 'prompts/get':
|
|
234
|
+
return getPrompt(given);
|
|
235
|
+
default:
|
|
236
|
+
throw new ProtocolError(METHOD_NOT_FOUND, 'Method not found');
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
/** The 2026-07-28 shape: a result type, caching hints where required, and identity. */
|
|
240
|
+
const modernResult = (method, result) => {
|
|
241
|
+
const cacheable = method !== 'tools/call';
|
|
242
|
+
return {
|
|
243
|
+
resultType: 'complete',
|
|
244
|
+
...result,
|
|
245
|
+
...(cacheable ? { ttlMs: definition.cacheTtlMs ?? 0, cacheScope: 'private' } : {}),
|
|
246
|
+
_meta: { [SERVER_INFO_KEY]: serverInfo },
|
|
247
|
+
};
|
|
248
|
+
};
|
|
249
|
+
return async (message) => {
|
|
250
|
+
if (!isObject(message)) {
|
|
251
|
+
return {
|
|
252
|
+
jsonrpc: '2.0',
|
|
253
|
+
error: {
|
|
254
|
+
code: INVALID_REQUEST,
|
|
255
|
+
message: Array.isArray(message) ? 'Invalid Request: batches are not supported' : 'Invalid Request',
|
|
256
|
+
},
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
const { id, method, params } = message;
|
|
260
|
+
if (message['jsonrpc'] === '2.0' && method === undefined && isRequestId(id) && ('result' in message || 'error' in message)) {
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
if (message['jsonrpc'] !== '2.0' || typeof method !== 'string' || (id !== undefined && !isRequestId(id))) {
|
|
264
|
+
return { jsonrpc: '2.0', ...(isRequestId(id) ? { id } : {}), error: { code: INVALID_REQUEST, message: 'Invalid Request' } };
|
|
265
|
+
}
|
|
266
|
+
if (id === undefined)
|
|
267
|
+
return null;
|
|
268
|
+
try {
|
|
269
|
+
if (params !== undefined && !isObject(params))
|
|
270
|
+
throw new ProtocolError(INVALID_PARAMS, 'params must be an object.');
|
|
271
|
+
const era = classifyRequest(method, params);
|
|
272
|
+
const result = await dispatch(method, params, era);
|
|
273
|
+
return { jsonrpc: '2.0', id, result: era === 'modern' ? modernResult(method, result) : result };
|
|
274
|
+
}
|
|
275
|
+
catch (error) {
|
|
276
|
+
const failure = error instanceof ProtocolError
|
|
277
|
+
? { code: error.code, message: error.message, data: error.data }
|
|
278
|
+
: { code: INTERNAL_ERROR, message: `Internal error: ${error instanceof Error ? error.message : String(error)}` };
|
|
279
|
+
return { jsonrpc: '2.0', id, error: failure };
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
/** The key a request is tracked under: `1` and `"1"` are different ids. */
|
|
284
|
+
function trackingKey(id) {
|
|
285
|
+
return `${typeof id}:${id}`;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Serves a handler over newline-delimited JSON-RPC until the input ends.
|
|
289
|
+
*
|
|
290
|
+
* Messages are split on `\n`; a CRLF line keeps its `\r`, which JSON reads
|
|
291
|
+
* as whitespace. Blank lines are skipped, and every response is written as a
|
|
292
|
+
* single line - `JSON.stringify` never emits a raw newline, which is what the
|
|
293
|
+
* binding requires. Requests are answered concurrently, in whatever order
|
|
294
|
+
* they finish. A request the client cancels gets no response. When the input
|
|
295
|
+
* closes, requests still running finish and then this resolves.
|
|
296
|
+
*/
|
|
297
|
+
export function serveLines(input, write, handle) {
|
|
298
|
+
return new Promise((resolve, reject) => {
|
|
299
|
+
const decoder = new TextDecoder();
|
|
300
|
+
let buffer = '';
|
|
301
|
+
let running = 0;
|
|
302
|
+
let ended = false;
|
|
303
|
+
const inFlight = new Set();
|
|
304
|
+
const cancelled = new Set();
|
|
305
|
+
const settle = () => {
|
|
306
|
+
if (ended && running === 0)
|
|
307
|
+
resolve();
|
|
308
|
+
};
|
|
309
|
+
const receive = (line) => {
|
|
310
|
+
if (line.trim() === '')
|
|
311
|
+
return;
|
|
312
|
+
let message;
|
|
313
|
+
try {
|
|
314
|
+
message = JSON.parse(line);
|
|
315
|
+
}
|
|
316
|
+
catch {
|
|
317
|
+
write(JSON.stringify({ jsonrpc: '2.0', error: { code: PARSE_ERROR, message: 'Parse error' } }));
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
if (isObject(message) && message['method'] === 'notifications/cancelled') {
|
|
321
|
+
const requestId = isObject(message['params']) ? message['params']['requestId'] : undefined;
|
|
322
|
+
if (isRequestId(requestId) && inFlight.has(trackingKey(requestId)))
|
|
323
|
+
cancelled.add(trackingKey(requestId));
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
const key = isObject(message) && typeof message['method'] === 'string' ? trackingKey(message['id']) : undefined;
|
|
327
|
+
inFlight.add(key);
|
|
328
|
+
running += 1;
|
|
329
|
+
void handle(message).then((response) => {
|
|
330
|
+
running -= 1;
|
|
331
|
+
inFlight.delete(key);
|
|
332
|
+
if (!cancelled.delete(key) && response !== null)
|
|
333
|
+
write(JSON.stringify(response));
|
|
334
|
+
settle();
|
|
335
|
+
});
|
|
336
|
+
};
|
|
337
|
+
input.on('data', (chunk) => {
|
|
338
|
+
buffer += decoder.decode(chunk, { stream: true });
|
|
339
|
+
for (let newline = buffer.indexOf('\n'); newline !== -1; newline = buffer.indexOf('\n')) {
|
|
340
|
+
const line = buffer.slice(0, newline);
|
|
341
|
+
buffer = buffer.slice(newline + 1);
|
|
342
|
+
receive(line);
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
input.once('end', () => {
|
|
346
|
+
ended = true;
|
|
347
|
+
receive(buffer + decoder.decode());
|
|
348
|
+
settle();
|
|
349
|
+
});
|
|
350
|
+
input.once('error', reject);
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
//# sourceMappingURL=mcp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../../../src/vendor/spec-core/jsonrpc/mcp.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The Model Context Protocol over JSON-RPC 2.0, without an SDK.\n *\n * MCP over stdio is JSON-RPC 2.0, one message per line, and what a server must\n * get right fits here: framing, the two eras of the protocol, and the methods\n * that serve tools, resources and prompts. The official SDK brings a schema\n * library and a dependency tree to do the same; every spec-* tool promises no\n * runtime dependencies. Moved here from spec-guard (its ADR-0012), where it\n * was first written and measured, so that a second server does not relearn it.\n *\n * Two eras, served side by side. Revisions up to 2025-11-25 open with an\n * `initialize` handshake; 2026-07-28 has none, and every request carries its\n * protocol version in `_meta`. Clients of both are in use - the newest\n * revision is not yet the one most clients speak - so each request is\n * classified on its own, by the rule the TypeScript SDK's server applies: a\n * request that claims a version in `_meta` is modern and its claim is\n * validated; anything else, `initialize` included, is legacy.\n *\n * Nothing here touches a stream or a file. A server is a function from one\n * parsed message to the message owed back; `serveLines` binds one to any\n * source of bytes with `on('data')`, which on Node is `process.stdin`.\n */\n\n/** Revisions that carry their version on every request. Newest first. */\nexport const MODERN_PROTOCOL_VERSIONS: readonly string[] = ['2026-07-28'];\n\n/** Revisions negotiated by `initialize`, newest first - the SDK's own list. */\nexport const LEGACY_PROTOCOL_VERSIONS: readonly string[] = ['2025-11-25', '2025-06-18', '2025-03-26', '2024-11-05', '2024-10-07'];\n\nexport const PROTOCOL_VERSION_KEY = 'io.modelcontextprotocol/protocolVersion';\nexport const CLIENT_CAPABILITIES_KEY = 'io.modelcontextprotocol/clientCapabilities';\nexport const CLIENT_INFO_KEY = 'io.modelcontextprotocol/clientInfo';\nexport const SERVER_INFO_KEY = 'io.modelcontextprotocol/serverInfo';\n\nexport const PARSE_ERROR = -32700;\nexport const INVALID_REQUEST = -32600;\nexport const METHOD_NOT_FOUND = -32601;\nexport const INVALID_PARAMS = -32602;\nexport const INTERNAL_ERROR = -32603;\n/** Resource not found before 2026-07-28, which forbids it in favour of -32602. */\nexport const LEGACY_RESOURCE_NOT_FOUND = -32002;\nexport const UNSUPPORTED_PROTOCOL_VERSION = -32022;\n\nexport type RequestId = string | number;\nexport type Era = 'legacy' | 'modern';\nexport type JsonObject = Record<string, unknown>;\n\nexport interface ErrorObject {\n readonly code: number;\n readonly message: string;\n readonly data?: unknown;\n}\n\n/** Everything a server here writes. It never sends a request. */\nexport type OutgoingMessage =\n | { readonly jsonrpc: '2.0'; readonly id: RequestId; readonly result: JsonObject }\n | { readonly jsonrpc: '2.0'; readonly id?: RequestId; readonly error: ErrorObject };\n\n/** An error that becomes a JSON-RPC error response with its code. */\nexport class ProtocolError extends Error {\n readonly code: number;\n readonly data: unknown;\n constructor(code: number, message: string, data?: unknown) {\n super(message);\n this.name = 'ProtocolError';\n this.code = code;\n this.data = data;\n }\n}\n\nexport function isObject(value: unknown): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** JSON-RPC allows a null id; MCP does not, and wants an integer if a number. */\nexport function isRequestId(value: unknown): value is RequestId {\n return typeof value === 'string' || Number.isInteger(value);\n}\n\n/**\n * What is wrong with a request's `_meta` once it claims a protocol version,\n * or `undefined`. A claim is never ignored: a malformed one is an error, not\n * a reason to fall back to the legacy handling.\n */\nexport function envelopeIssue(meta: JsonObject): string | undefined {\n if (!(CLIENT_CAPABILITIES_KEY in meta)) return `${CLIENT_CAPABILITIES_KEY}: missing`;\n if (typeof meta[PROTOCOL_VERSION_KEY] !== 'string') return `${PROTOCOL_VERSION_KEY}: expected a string`;\n if (!isObject(meta[CLIENT_CAPABILITIES_KEY])) return `${CLIENT_CAPABILITIES_KEY}: expected an object`;\n const info = meta[CLIENT_INFO_KEY];\n if (info !== undefined && !(isObject(info) && typeof info['name'] === 'string' && typeof info['version'] === 'string')) {\n return `${CLIENT_INFO_KEY}: expected an object with a string name and version`;\n }\n return undefined;\n}\n\n/**\n * The era a request belongs to, or the error that answers it instead.\n *\n * `initialize` is the legacy handshake unless it carries a valid modern claim.\n * Any other request is modern exactly when `_meta` holds the version key - its\n * presence is the claim, whatever its value - and legacy otherwise.\n */\nexport function classifyRequest(method: string, params: JsonObject | undefined): Era {\n const meta = params?.['_meta'];\n const claimed = isObject(meta) && PROTOCOL_VERSION_KEY in meta;\n if (!claimed) return 'legacy';\n const issue = envelopeIssue(meta);\n const version = meta[PROTOCOL_VERSION_KEY] as string;\n const supported = issue === undefined && MODERN_PROTOCOL_VERSIONS.includes(version);\n if (method === 'initialize' && !supported) return 'legacy';\n if (issue !== undefined) throw new ProtocolError(INVALID_PARAMS, `Invalid _meta envelope: ${issue}`);\n if (!supported) {\n throw new ProtocolError(UNSUPPORTED_PROTOCOL_VERSION, 'Unsupported protocol version', {\n supported: [...MODERN_PROTOCOL_VERSIONS],\n requested: version,\n });\n }\n return 'modern';\n}\n\n/** The version `initialize` settles on: the one asked for, or the newest legacy one. */\nexport function negotiateLegacyVersion(requested: unknown): string {\n return LEGACY_PROTOCOL_VERSIONS.includes(requested as string) ? (requested as string) : (LEGACY_PROTOCOL_VERSIONS[0] as string);\n}\n\n/* ------------------------------------------------------------------ servers */\n\n/** What a tool call produced: text for the model, and the same as data. */\nexport interface ToolOutcome {\n readonly text: string;\n readonly structured?: JsonObject | undefined;\n readonly isError?: boolean | undefined;\n}\n\nexport interface ToolDefinition {\n /** The descriptor `tools/list` returns: name, title, description, inputSchema, annotations. */\n readonly descriptor: JsonObject & { readonly name: string };\n /** Runs the tool. Arguments arrive as an object, unvalidated beyond that. */\n call(args: JsonObject): Promise<ToolOutcome>;\n}\n\nexport interface ResourceProvider {\n /** Concrete resources, as `resources/list` returns them. */\n list(): Promise<readonly JsonObject[]>;\n /** URI templates, as `resources/templates/list` returns them. */\n readonly templates?: readonly JsonObject[] | undefined;\n /** The contents of one resource, or `null` when there is no such resource. */\n read(uri: string): Promise<readonly JsonObject[] | null>;\n}\n\nexport interface PromptDefinition {\n /** The descriptor `prompts/list` returns: name, title, description, arguments. */\n readonly descriptor: JsonObject & { readonly name: string };\n /** The messages the prompt expands to, given its arguments as strings. */\n get(args: Readonly<Record<string, string>>): Promise<JsonObject>;\n}\n\nexport interface McpServerDefinition {\n readonly name: string;\n readonly version: string;\n /** Sent in the handshake: what the server is for, and when to call what. */\n readonly instructions: string;\n readonly tools?: readonly ToolDefinition[] | undefined;\n readonly resources?: ResourceProvider | undefined;\n readonly prompts?: readonly PromptDefinition[] | undefined;\n /**\n * Whether results other than a tool call's may be cached by a modern\n * client, and for how long. Absent: every result is stale at once and\n * private, which is right for a server that reads the repository afresh\n * on each request.\n */\n readonly cacheTtlMs?: number | undefined;\n}\n\n/** A tool's failure, reported to the model rather than as a protocol error it cannot read. */\nexport function toolError(text: string): ToolOutcome {\n return { text, isError: true };\n}\n\n/**\n * Arguments a tool does not declare, which the model should hear about rather\n * than have silently dropped. `undefined` when there are none.\n */\nexport function unknownArguments(args: JsonObject, allowed: readonly string[]): ToolOutcome | undefined {\n const unknown = Object.keys(args).filter((name) => !allowed.includes(name));\n if (unknown.length === 0) return undefined;\n const list = unknown.map((name) => `\"${name}\"`).join(', ');\n const takes =\n allowed.length === 0\n ? 'no arguments'\n : allowed.length === 1\n ? (allowed[0] as string)\n : `${allowed.slice(0, -1).join(', ')} and ${allowed[allowed.length - 1] as string}`;\n return toolError(`Unknown argument${unknown.length === 1 ? '' : 's'} ${list}; this tool takes ${takes}.`);\n}\n\n/**\n * Builds the function that answers one parsed JSON-RPC message: the message\n * to send back, or `null` when nothing is owed - a notification, or a\n * response the client should not have sent.\n */\nexport function createMcpServer(definition: McpServerDefinition): (message: unknown) => Promise<OutgoingMessage | null> {\n const serverInfo = { name: definition.name, version: definition.version };\n const tools = definition.tools ?? [];\n const prompts = definition.prompts ?? [];\n const capabilities: JsonObject = {\n ...(tools.length > 0 ? { tools: {} } : {}),\n ...(definition.resources !== undefined ? { resources: {} } : {}),\n ...(prompts.length > 0 ? { prompts: {} } : {}),\n };\n\n const refuseCursor = (params: JsonObject | undefined): void => {\n if (params?.['cursor'] !== undefined) throw new ProtocolError(INVALID_PARAMS, 'Invalid cursor: this server does not paginate.');\n };\n\n const callTool = async (params: JsonObject): Promise<JsonObject> => {\n const name = params['name'];\n if (typeof name !== 'string') throw new ProtocolError(INVALID_PARAMS, 'tools/call needs the name of a tool.');\n const tool = tools.find((candidate) => candidate.descriptor.name === name);\n if (tool === undefined) throw new ProtocolError(INVALID_PARAMS, `Unknown tool: ${name}`);\n const args = params['arguments'] ?? {};\n if (!isObject(args)) throw new ProtocolError(INVALID_PARAMS, 'Tool arguments must be an object.');\n let outcome: ToolOutcome;\n try {\n outcome = await tool.call(args);\n } catch (error) {\n outcome = toolError(`${definition.name} failed: ${error instanceof Error ? error.message : String(error)}`);\n }\n return {\n content: [{ type: 'text', text: outcome.text }],\n ...(outcome.structured === undefined ? {} : { structuredContent: outcome.structured }),\n ...(outcome.isError === true ? { isError: true } : {}),\n };\n };\n\n const readResource = async (params: JsonObject, era: Era): Promise<JsonObject> => {\n const uri = params['uri'];\n if (typeof uri !== 'string') throw new ProtocolError(INVALID_PARAMS, 'resources/read needs a uri.');\n const contents = await (definition.resources as ResourceProvider).read(uri);\n if (contents === null) {\n throw new ProtocolError(era === 'modern' ? INVALID_PARAMS : LEGACY_RESOURCE_NOT_FOUND, 'Resource not found', { uri });\n }\n return { contents: [...contents] };\n };\n\n const getPrompt = async (params: JsonObject): Promise<JsonObject> => {\n const name = params['name'];\n if (typeof name !== 'string') throw new ProtocolError(INVALID_PARAMS, 'prompts/get needs the name of a prompt.');\n const prompt = prompts.find((candidate) => candidate.descriptor.name === name);\n if (prompt === undefined) throw new ProtocolError(INVALID_PARAMS, `Unknown prompt: ${name}`);\n const args = params['arguments'] ?? {};\n if (!isObject(args) || !Object.values(args).every((value) => typeof value === 'string')) {\n throw new ProtocolError(INVALID_PARAMS, 'Prompt arguments must be an object of strings.');\n }\n return prompt.get(args as Record<string, string>);\n };\n\n const dispatch = async (method: string, params: JsonObject | undefined, era: Era): Promise<JsonObject> => {\n const given = params ?? {};\n if (era === 'legacy') {\n if (method === 'initialize') {\n return {\n protocolVersion: negotiateLegacyVersion(given['protocolVersion']),\n capabilities,\n serverInfo,\n instructions: definition.instructions,\n };\n }\n if (method === 'ping') return {};\n } else if (method === 'server/discover') {\n return { supportedVersions: [...MODERN_PROTOCOL_VERSIONS], capabilities, instructions: definition.instructions };\n }\n // A method for a capability the server did not declare does not exist on\n // it: the answer is the one for any unknown method, not an empty list that\n // reads as \"declared, and empty\".\n const family = method.slice(0, method.indexOf('/') + 1);\n if (\n (family === 'tools/' && tools.length === 0) ||\n (family === 'resources/' && definition.resources === undefined) ||\n (family === 'prompts/' && prompts.length === 0)\n ) {\n throw new ProtocolError(METHOD_NOT_FOUND, 'Method not found');\n }\n switch (method) {\n case 'tools/list':\n refuseCursor(params);\n return { tools: tools.map((tool) => tool.descriptor) };\n case 'tools/call':\n return callTool(given);\n case 'resources/list':\n refuseCursor(params);\n return { resources: [...(await (definition.resources as ResourceProvider).list())] };\n case 'resources/templates/list':\n refuseCursor(params);\n return { resourceTemplates: [...((definition.resources as ResourceProvider).templates ?? [])] };\n case 'resources/read':\n return readResource(given, era);\n case 'prompts/list':\n refuseCursor(params);\n return { prompts: prompts.map((prompt) => prompt.descriptor) };\n case 'prompts/get':\n return getPrompt(given);\n default:\n throw new ProtocolError(METHOD_NOT_FOUND, 'Method not found');\n }\n };\n\n /** The 2026-07-28 shape: a result type, caching hints where required, and identity. */\n const modernResult = (method: string, result: JsonObject): JsonObject => {\n const cacheable = method !== 'tools/call';\n return {\n resultType: 'complete',\n ...result,\n ...(cacheable ? { ttlMs: definition.cacheTtlMs ?? 0, cacheScope: 'private' } : {}),\n _meta: { [SERVER_INFO_KEY]: serverInfo },\n };\n };\n\n return async (message: unknown): Promise<OutgoingMessage | null> => {\n if (!isObject(message)) {\n return {\n jsonrpc: '2.0',\n error: {\n code: INVALID_REQUEST,\n message: Array.isArray(message) ? 'Invalid Request: batches are not supported' : 'Invalid Request',\n },\n };\n }\n const { id, method, params } = message;\n if (message['jsonrpc'] === '2.0' && method === undefined && isRequestId(id) && ('result' in message || 'error' in message)) {\n return null;\n }\n if (message['jsonrpc'] !== '2.0' || typeof method !== 'string' || (id !== undefined && !isRequestId(id))) {\n return { jsonrpc: '2.0', ...(isRequestId(id) ? { id } : {}), error: { code: INVALID_REQUEST, message: 'Invalid Request' } };\n }\n if (id === undefined) return null;\n try {\n if (params !== undefined && !isObject(params)) throw new ProtocolError(INVALID_PARAMS, 'params must be an object.');\n const era = classifyRequest(method, params);\n const result = await dispatch(method, params, era);\n return { jsonrpc: '2.0', id, result: era === 'modern' ? modernResult(method, result) : result };\n } catch (error) {\n const failure: ErrorObject =\n error instanceof ProtocolError\n ? { code: error.code, message: error.message, data: error.data }\n : { code: INTERNAL_ERROR, message: `Internal error: ${error instanceof Error ? error.message : String(error)}` };\n return { jsonrpc: '2.0', id, error: failure };\n }\n };\n}\n\n/* -------------------------------------------------------------------- lines */\n\n/** Anything that delivers bytes and says when it has finished: `process.stdin`, or a test's stand-in. */\nexport interface ByteSource {\n on(event: 'data', listener: (chunk: Uint8Array) => void): unknown;\n once(event: 'end', listener: () => void): unknown;\n once(event: 'error', listener: (error: Error) => void): unknown;\n}\n\n/** The key a request is tracked under: `1` and `\"1\"` are different ids. */\nfunction trackingKey(id: RequestId): string {\n return `${typeof id}:${id}`;\n}\n\n/**\n * Serves a handler over newline-delimited JSON-RPC until the input ends.\n *\n * Messages are split on `\\n`; a CRLF line keeps its `\\r`, which JSON reads\n * as whitespace. Blank lines are skipped, and every response is written as a\n * single line - `JSON.stringify` never emits a raw newline, which is what the\n * binding requires. Requests are answered concurrently, in whatever order\n * they finish. A request the client cancels gets no response. When the input\n * closes, requests still running finish and then this resolves.\n */\nexport function serveLines(\n input: ByteSource,\n write: (line: string) => void,\n handle: (message: unknown) => Promise<OutgoingMessage | null>,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const decoder = new TextDecoder();\n let buffer = '';\n let running = 0;\n let ended = false;\n const inFlight = new Set<string | undefined>();\n const cancelled = new Set<string | undefined>();\n const settle = (): void => {\n if (ended && running === 0) resolve();\n };\n\n const receive = (line: string): void => {\n if (line.trim() === '') return;\n let message: unknown;\n try {\n message = JSON.parse(line);\n } catch {\n write(JSON.stringify({ jsonrpc: '2.0', error: { code: PARSE_ERROR, message: 'Parse error' } }));\n return;\n }\n if (isObject(message) && message['method'] === 'notifications/cancelled') {\n const requestId = isObject(message['params']) ? message['params']['requestId'] : undefined;\n if (isRequestId(requestId) && inFlight.has(trackingKey(requestId))) cancelled.add(trackingKey(requestId));\n return;\n }\n const key = isObject(message) && typeof message['method'] === 'string' ? trackingKey(message['id'] as RequestId) : undefined;\n inFlight.add(key);\n running += 1;\n void handle(message).then((response) => {\n running -= 1;\n inFlight.delete(key);\n if (!cancelled.delete(key) && response !== null) write(JSON.stringify(response));\n settle();\n });\n };\n\n input.on('data', (chunk: Uint8Array) => {\n buffer += decoder.decode(chunk, { stream: true });\n for (let newline = buffer.indexOf('\\n'); newline !== -1; newline = buffer.indexOf('\\n')) {\n const line = buffer.slice(0, newline);\n buffer = buffer.slice(newline + 1);\n receive(line);\n }\n });\n input.once('end', () => {\n ended = true;\n receive(buffer + decoder.decode());\n settle();\n });\n input.once('error', reject);\n });\n}\n"]}
|