@wrongstack/mcp 1.0.29 → 1.0.33
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/dist/client-stdio-protocol.d.ts +24 -0
- package/dist/client-stdio.d.ts +32 -0
- package/dist/client.d.ts +5 -10
- package/dist/index.js +800 -408
- package/dist/registry-catalog-operations.d.ts +29 -0
- package/dist/registry-catalog.d.ts +2 -0
- package/dist/registry-slots.d.ts +4 -0
- package/dist/registry.d.ts +4 -1
- package/dist/server-dispatch.d.ts +160 -0
- package/dist/server-http.d.ts +60 -0
- package/dist/server-stdio.d.ts +19 -0
- package/dist/server.d.ts +6 -181
- package/dist/sse-reader.d.ts +2 -0
- package/dist/transport-sse.d.ts +2 -0
- package/dist/transport-streamable.d.ts +2 -0
- package/dist/wrap-tool.d.ts +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type MCPInsertionPolicy, type MCPPromptInsertion, type MCPResourceInsertion } from './content-selection.js';
|
|
2
|
+
import type { MCPGetPromptResult, MCPPrompt, MCPReadResourceResult, MCPResource, MCPResourceTemplate } from './protocol.js';
|
|
3
|
+
import type { MCPRegistryCatalog } from './registry-types.js';
|
|
4
|
+
export interface RegistryCatalogOperationsHost {
|
|
5
|
+
servers: Map<string, import('./registry-slots.js').ServerSlot>;
|
|
6
|
+
disabledServers: Map<string, import('@wrongstack/core/types').MCPServerConfig>;
|
|
7
|
+
requireSlot: (name: string) => import('./registry-slots.js').ServerSlot;
|
|
8
|
+
withConnectedClient: <T>(name: string, run: (client: import('./client.js').MCPClient, assertCurrent: () => void) => Promise<T>) => Promise<T>;
|
|
9
|
+
persistCapabilityManifest: (slot: import('./registry-slots.js').ServerSlot) => Promise<void>;
|
|
10
|
+
readResource: (name: string, uri: string) => Promise<import('./protocol.js').MCPReadResourceResult>;
|
|
11
|
+
getPrompt: (serverName: string, promptName: string, args?: Record<string, string> | undefined) => Promise<import('./protocol.js').MCPGetPromptResult>;
|
|
12
|
+
}
|
|
13
|
+
export declare function getCatalog(this: RegistryCatalogOperationsHost, name: string): MCPRegistryCatalog | undefined;
|
|
14
|
+
export declare function listResources(this: RegistryCatalogOperationsHost, name: string, opts?: {
|
|
15
|
+
refresh?: boolean;
|
|
16
|
+
}): Promise<MCPResource[]>;
|
|
17
|
+
export declare function listResourceTemplates(this: RegistryCatalogOperationsHost, name: string, opts?: {
|
|
18
|
+
refresh?: boolean;
|
|
19
|
+
}): Promise<MCPResourceTemplate[]>;
|
|
20
|
+
export declare function readResource(this: RegistryCatalogOperationsHost, name: string, uri: string): Promise<MCPReadResourceResult>;
|
|
21
|
+
export declare function selectResourceForInsertion(this: RegistryCatalogOperationsHost, name: string, uri: string, policy?: MCPInsertionPolicy | undefined): Promise<MCPResourceInsertion>;
|
|
22
|
+
export declare function subscribeResource(this: RegistryCatalogOperationsHost, name: string, uri: string): Promise<void>;
|
|
23
|
+
export declare function unsubscribeResource(this: RegistryCatalogOperationsHost, name: string, uri: string): Promise<void>;
|
|
24
|
+
export declare function listPrompts(this: RegistryCatalogOperationsHost, name: string, opts?: {
|
|
25
|
+
refresh?: boolean;
|
|
26
|
+
}): Promise<MCPPrompt[]>;
|
|
27
|
+
export declare function getPrompt(this: RegistryCatalogOperationsHost, serverName: string, promptName: string, args?: Record<string, string> | undefined): Promise<MCPGetPromptResult>;
|
|
28
|
+
export declare function selectPromptForInsertion(this: RegistryCatalogOperationsHost, serverName: string, promptName: string, args?: Record<string, string> | undefined, policy?: MCPInsertionPolicy | undefined): Promise<MCPPromptInsertion>;
|
|
29
|
+
//# sourceMappingURL=registry-catalog-operations.d.ts.map
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { ConnectionState } from './contracts.js';
|
|
2
2
|
import type { MCPPrompt, MCPResource, MCPResourceTemplate, MCPServerMetadata } from './protocol.js';
|
|
3
|
+
import type { ServerSlot } from './registry-slots.js';
|
|
3
4
|
import type { MCPRegistryCatalog } from './registry-types.js';
|
|
5
|
+
export declare function advanceCatalogVersion(slot: ServerSlot, kind: 'resources' | 'resourceTemplates' | 'prompts'): number;
|
|
4
6
|
export declare function collectCatalogPages<Page extends {
|
|
5
7
|
nextCursor?: string | undefined;
|
|
6
8
|
}, Item>(load: (cursor?: string | undefined) => Promise<Page>, select: (page: Page) => Item[]): Promise<Item[]>;
|
package/dist/registry-slots.d.ts
CHANGED
|
@@ -26,6 +26,8 @@ export interface ServerSlot {
|
|
|
26
26
|
resources?: MCPResource[] | undefined;
|
|
27
27
|
resourceTemplates?: MCPResourceTemplate[] | undefined;
|
|
28
28
|
prompts?: MCPPrompt[] | undefined;
|
|
29
|
+
/** Orders refreshes and list-change invalidations independently per catalog. */
|
|
30
|
+
catalogVersions?: Partial<Record<'resources' | 'resourceTemplates' | 'prompts', number>> | undefined;
|
|
29
31
|
/** Serializes replacements so rapid list-change notifications cannot restore stale data. */
|
|
30
32
|
manifestWrite?: Promise<void> | undefined;
|
|
31
33
|
attempts: number;
|
|
@@ -39,6 +41,8 @@ export interface ServerSlot {
|
|
|
39
41
|
lastUsed: number;
|
|
40
42
|
/** Single-flight guard so concurrent first-calls trigger only one connect. */
|
|
41
43
|
connecting?: Promise<MCPClient | undefined> | undefined;
|
|
44
|
+
/** Invalidates asynchronous startup work when a stop interrupts it. */
|
|
45
|
+
startupGeneration?: number | undefined;
|
|
42
46
|
/** Whether this lazy server's resolver wrappers are registered (register once). */
|
|
43
47
|
registeredLazy: boolean;
|
|
44
48
|
/**
|
package/dist/registry.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { MCPServerConfig } from '@wrongstack/core/types';
|
|
2
2
|
import type { MCPAuthorizationStartResult, MCPAuthorizationStatus } from './authorization-manager.js';
|
|
3
3
|
import type { MCPClient } from './client.js';
|
|
4
|
-
import {
|
|
4
|
+
import type { MCPInsertionPolicy, MCPPromptInsertion, MCPResourceInsertion } from './content-selection.js';
|
|
5
5
|
import type { ConnectionState } from './contracts.js';
|
|
6
6
|
import { type MCPOperationListener, type MCPServerOperationalHealth } from './operations.js';
|
|
7
7
|
import type { MCPGetPromptResult, MCPPrompt, MCPReadResourceResult, MCPResource, MCPResourceTemplate } from './protocol.js';
|
|
@@ -139,6 +139,8 @@ export declare class MCPRegistry {
|
|
|
139
139
|
refresh?: boolean;
|
|
140
140
|
}): Promise<MCPPrompt[]>;
|
|
141
141
|
getPrompt(serverName: string, promptName: string, args?: Record<string, string> | undefined): Promise<MCPGetPromptResult>;
|
|
142
|
+
/** Keep all remote requests awake and reject results from superseded clients. */
|
|
143
|
+
private withConnectedClient;
|
|
142
144
|
selectPromptForInsertion(serverName: string, promptName: string, args?: Record<string, string> | undefined, policy?: MCPInsertionPolicy | undefined): Promise<MCPPromptInsertion>;
|
|
143
145
|
/**
|
|
144
146
|
* Resolve the live tool names for a slot — the registered names in normal
|
|
@@ -201,5 +203,6 @@ export declare class MCPRegistry {
|
|
|
201
203
|
private recordFailure;
|
|
202
204
|
private recordOperation;
|
|
203
205
|
private attemptConnect;
|
|
206
|
+
private registryCatalogOperationsHost;
|
|
204
207
|
}
|
|
205
208
|
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import type { MCPPromptArgument, MCPPromptMessage, MCPResourceContents } from './protocol.js';
|
|
2
|
+
/**
|
|
3
|
+
* Server-side MCP. The mirror image of `MCPClient`: instead of consuming a
|
|
4
|
+
* remote MCP server, this lets WrongStack *be* an MCP server — exposing its
|
|
5
|
+
* tools to any MCP client (Claude Desktop, another agent, an IDE) over a
|
|
6
|
+
* JSON-RPC 2.0 stream.
|
|
7
|
+
*
|
|
8
|
+
* The protocol core (`MCPServer`) is transport-agnostic: feed it a raw JSON
|
|
9
|
+
* line via `handleMessage`, get back a response string (or `null` for
|
|
10
|
+
* notifications). `serveStdio` wires it to stdin/stdout for the canonical
|
|
11
|
+
* stdio transport.
|
|
12
|
+
*/
|
|
13
|
+
/** A tool descriptor advertised over `tools/list`. */
|
|
14
|
+
export interface MCPServerTool {
|
|
15
|
+
name: string;
|
|
16
|
+
description?: string | undefined;
|
|
17
|
+
inputSchema: Record<string, unknown>;
|
|
18
|
+
}
|
|
19
|
+
/** The result of a `tools/call`, as the host produces it. */
|
|
20
|
+
export interface MCPServerCallResult {
|
|
21
|
+
/** Text or pre-built MCP content blocks. Strings are wrapped as a text block. */
|
|
22
|
+
content: unknown;
|
|
23
|
+
isError: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Bridges the MCP server to a tool backend (in the CLI, the `ToolRegistry`).
|
|
27
|
+
* Kept narrow so the protocol core has no dependency on `@wrongstack/core`.
|
|
28
|
+
*/
|
|
29
|
+
export interface MCPServerToolHost {
|
|
30
|
+
listTools(): MCPServerTool[] | Promise<MCPServerTool[]>;
|
|
31
|
+
callTool(name: string, args: Record<string, unknown>, opts?: {
|
|
32
|
+
signal?: AbortSignal | undefined;
|
|
33
|
+
}): Promise<MCPServerCallResult>;
|
|
34
|
+
}
|
|
35
|
+
export interface MCPServerResource {
|
|
36
|
+
uri: string;
|
|
37
|
+
name: string;
|
|
38
|
+
title?: string | undefined;
|
|
39
|
+
description?: string | undefined;
|
|
40
|
+
mimeType?: string | undefined;
|
|
41
|
+
size?: number | undefined;
|
|
42
|
+
contents: MCPResourceContents[];
|
|
43
|
+
}
|
|
44
|
+
export interface MCPServerPrompt {
|
|
45
|
+
name: string;
|
|
46
|
+
title?: string | undefined;
|
|
47
|
+
description?: string | undefined;
|
|
48
|
+
arguments?: MCPPromptArgument[] | undefined;
|
|
49
|
+
/** Static rich messages, or a text template using {{argument}} placeholders. */
|
|
50
|
+
messages?: MCPPromptMessage[] | undefined;
|
|
51
|
+
template?: string | undefined;
|
|
52
|
+
}
|
|
53
|
+
export interface MCPServerLogger {
|
|
54
|
+
warn?(msg: string): void;
|
|
55
|
+
info?(msg: string): void;
|
|
56
|
+
}
|
|
57
|
+
export interface MCPServerOptions {
|
|
58
|
+
host: MCPServerToolHost;
|
|
59
|
+
/** Advertised in the `initialize` handshake. Defaults to the wrongstack identity. */
|
|
60
|
+
serverInfo?: {
|
|
61
|
+
name: string;
|
|
62
|
+
version: string;
|
|
63
|
+
};
|
|
64
|
+
logger?: MCPServerLogger | undefined;
|
|
65
|
+
/** Explicit allowlist only; omitted means this server exposes no resources. */
|
|
66
|
+
resources?: MCPServerResource[] | undefined;
|
|
67
|
+
/** Explicit allowlist only; omitted means this server exposes no prompts. */
|
|
68
|
+
prompts?: MCPServerPrompt[] | undefined;
|
|
69
|
+
/**
|
|
70
|
+
* `InitializeResult.instructions`: how and when to use this server. Clients
|
|
71
|
+
* that honour it (Claude Code does) put it in front of the model.
|
|
72
|
+
*/
|
|
73
|
+
instructions?: string | undefined;
|
|
74
|
+
}
|
|
75
|
+
export interface JsonRpcRequest {
|
|
76
|
+
jsonrpc?: string | undefined;
|
|
77
|
+
id?: number | string | null | undefined;
|
|
78
|
+
method?: string | undefined;
|
|
79
|
+
params?: unknown | undefined;
|
|
80
|
+
}
|
|
81
|
+
export declare const PARSE_ERROR = -32700;
|
|
82
|
+
export declare const INVALID_REQUEST = -32600;
|
|
83
|
+
export declare const METHOD_NOT_FOUND = -32601;
|
|
84
|
+
export declare const INVALID_PARAMS = -32602;
|
|
85
|
+
export declare const INTERNAL_ERROR = -32603;
|
|
86
|
+
export declare class MCPServer {
|
|
87
|
+
private readonly host;
|
|
88
|
+
private readonly serverInfo;
|
|
89
|
+
private readonly logger?;
|
|
90
|
+
private readonly resources;
|
|
91
|
+
private readonly prompts;
|
|
92
|
+
private readonly instructions;
|
|
93
|
+
private readonly inFlightRequests;
|
|
94
|
+
constructor(opts: MCPServerOptions);
|
|
95
|
+
/**
|
|
96
|
+
* Handle one raw JSON-RPC line. Returns the response JSON string for
|
|
97
|
+
* requests, or `null` for notifications (no `id`) and for blank input —
|
|
98
|
+
* the caller should write the string to its output stream when non-null.
|
|
99
|
+
*/
|
|
100
|
+
handleMessage(raw: string): Promise<string | null>;
|
|
101
|
+
private dispatch;
|
|
102
|
+
/**
|
|
103
|
+
* WS-026: enforce the `inputSchema` this server advertises on `tools/list`.
|
|
104
|
+
*
|
|
105
|
+
* `tools/call` used to forward `params.arguments` to the host verbatim after
|
|
106
|
+
* checking only that it was a non-array object — so every `enum`, `required`,
|
|
107
|
+
* `additionalProperties: false`, and numeric bound in the published schema
|
|
108
|
+
* was advisory. A client (or an attacker who reached the transport) could
|
|
109
|
+
* send `{mode: "../../etc"}` to a tool whose schema declares
|
|
110
|
+
* `enum: ["read","write"]` and the tool would receive it. Publishing a
|
|
111
|
+
* contract and not enforcing it is worse than publishing none: downstream
|
|
112
|
+
* tools are written against the schema they declared.
|
|
113
|
+
*
|
|
114
|
+
* SCOPE: `validateAgainstSchema` is the shared validator that also gates the
|
|
115
|
+
* agent's own tool executor. It checks `type`, `enum`, `required`, recurses
|
|
116
|
+
* through `properties`/`items`, enforces numeric bounds
|
|
117
|
+
* (`minimum`/`maximum`), rejects unknown keys on strict-closed objects
|
|
118
|
+
* (`additionalProperties: false`), validates the `additionalProperties`
|
|
119
|
+
* subschema form against unknown-key values, applies `patternProperties`
|
|
120
|
+
* to matching keys, enforces string lengths (`minLength`/`maxLength`) and
|
|
121
|
+
* `pattern`, array lengths (`minItems`/`maxItems`/`uniqueItems`), and the
|
|
122
|
+
* combinators `allOf`/`anyOf`/`oneOf` (all landed 2026-09-11). Still
|
|
123
|
+
* advisory per the 2026-09-11 usage survey: `const` and `$ref` — declared
|
|
124
|
+
* only in the techstack rulebook, which validates with its own
|
|
125
|
+
* `validateRulebook`, not this validator.
|
|
126
|
+
*
|
|
127
|
+
* Unknown tool names are left alone — the host owns that error, and
|
|
128
|
+
* answering "no such tool" here would fork the message for no benefit.
|
|
129
|
+
*/
|
|
130
|
+
private assertArgumentsMatchSchema;
|
|
131
|
+
private encodeError;
|
|
132
|
+
}
|
|
133
|
+
/** Cap on how many schema violations are echoed back in one error message. */
|
|
134
|
+
export declare const MAX_REPORTED_SCHEMA_ERRORS = 5;
|
|
135
|
+
/**
|
|
136
|
+
* Marks a `tools/call` rejected by {@link MCPServer.assertArgumentsMatchSchema}
|
|
137
|
+
* so `handleMessage` can answer with JSON-RPC `-32602 Invalid params` rather
|
|
138
|
+
* than the generic internal-error code every other throw maps to.
|
|
139
|
+
*/
|
|
140
|
+
export declare class InvalidToolArgumentsError extends Error {
|
|
141
|
+
readonly name = "InvalidToolArgumentsError";
|
|
142
|
+
}
|
|
143
|
+
export declare const SERVER_PAGE_SIZE = 100;
|
|
144
|
+
export declare function paginate<T>(items: T[], params: unknown): {
|
|
145
|
+
items: T[];
|
|
146
|
+
nextCursor?: string | undefined;
|
|
147
|
+
};
|
|
148
|
+
export declare function paramsRecord(params: unknown): Record<string, unknown>;
|
|
149
|
+
export declare function requiredParamString(params: unknown, field: string, method: string): string;
|
|
150
|
+
export declare function stringRecord(value: unknown, label: string): Record<string, string>;
|
|
151
|
+
export declare function renderPromptTemplate(template: string, args: Record<string, string>): string;
|
|
152
|
+
export declare const METHOD_NOT_FOUND_SENTINEL: unique symbol;
|
|
153
|
+
export declare function isMCPContentBlock(c: unknown): boolean;
|
|
154
|
+
/** Normalize a host result's content into MCP content blocks. */
|
|
155
|
+
export declare function toContentBlocks(content: unknown): Array<{
|
|
156
|
+
type: string;
|
|
157
|
+
[key: string]: unknown;
|
|
158
|
+
}>;
|
|
159
|
+
export declare function stringifyItem(c: unknown): string;
|
|
160
|
+
//# sourceMappingURL=server-dispatch.d.ts.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { type IncomingMessage, type ServerResponse } from 'node:http';
|
|
2
|
+
import type { MCPServer, MCPServerLogger } from './server-dispatch.js';
|
|
3
|
+
export interface ServeHttpOptions {
|
|
4
|
+
/** TCP port. 0 picks an ephemeral port (resolved in the handle). Default 0. */
|
|
5
|
+
port?: number | undefined;
|
|
6
|
+
/** Bind address. Default '127.0.0.1' (loopback only). */
|
|
7
|
+
host?: string | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* Bearer token required on every request (`Authorization: Bearer <token>`).
|
|
10
|
+
* REQUIRED when binding to a non-loopback host — `serveHttp` refuses to
|
|
11
|
+
* expose tools to the network without one.
|
|
12
|
+
*/
|
|
13
|
+
token?: string | undefined;
|
|
14
|
+
logger?: MCPServerLogger | undefined;
|
|
15
|
+
}
|
|
16
|
+
export interface ServeHttpHandle {
|
|
17
|
+
port: number;
|
|
18
|
+
host: string;
|
|
19
|
+
url: string;
|
|
20
|
+
close(): Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
export declare function isLoopbackHost(host: string): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Run an `MCPServer` over HTTP: POST a single JSON-RPC request, get the JSON
|
|
25
|
+
* response (notifications → 202 with no body). Reuses `handleMessage`, so the
|
|
26
|
+
* protocol is identical to the stdio transport.
|
|
27
|
+
*
|
|
28
|
+
* Security: binds to loopback by default. Binding to any other host (e.g.
|
|
29
|
+
* `0.0.0.0`) REQUIRES a `token` — otherwise this rejects, because it would
|
|
30
|
+
* otherwise expose tool execution to the whole network unauthenticated.
|
|
31
|
+
*/
|
|
32
|
+
export declare function serveHttp(server: MCPServer, opts?: ServeHttpOptions): Promise<ServeHttpHandle>;
|
|
33
|
+
export declare function handleHttpRequest(server: MCPServer, req: IncomingMessage, res: ServerResponse, token: string | undefined, log: MCPServerLogger | undefined, boundHost: string): Promise<void>;
|
|
34
|
+
/** Hostnames that always denote this machine, regardless of the bind address. */
|
|
35
|
+
export declare function isLoopbackHostname(hostname: string): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Reject a request whose `Origin` names a site other than this server.
|
|
38
|
+
*
|
|
39
|
+
* A missing `Origin` is accepted: the clients this transport exists for
|
|
40
|
+
* (Claude Desktop, IDE extensions, `curl`) are not browsers and never send
|
|
41
|
+
* one. A browser, which is the threat here, always attaches it on a
|
|
42
|
+
* cross-origin request and cannot forge it.
|
|
43
|
+
*/
|
|
44
|
+
export declare function originIsAcceptable(req: IncomingMessage, boundHost: string): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Pin the `Host` header to the bound address. Without this, an attacker
|
|
47
|
+
* registers `evil.example → 127.0.0.1`, gets a victim's browser to load a page
|
|
48
|
+
* there, and every request is same-origin by the browser's reckoning while
|
|
49
|
+
* landing on this server (DNS rebinding).
|
|
50
|
+
*/
|
|
51
|
+
export declare function hostHeaderIsAcceptable(req: IncomingMessage, boundHost: string): boolean;
|
|
52
|
+
/** `application/json`, with or without parameters such as `; charset=utf-8`. */
|
|
53
|
+
export declare function isJsonContentType(value: string | undefined): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Constant-time bearer comparison. `auth !== expected` short-circuits on the
|
|
56
|
+
* first differing byte, which leaks the token prefix to a caller that can time
|
|
57
|
+
* responses — and a local attacker can time them very precisely.
|
|
58
|
+
*/
|
|
59
|
+
export declare function bearerTokenMatches(header: string | undefined, token: string): boolean;
|
|
60
|
+
//# sourceMappingURL=server-http.d.ts.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { MCPServer } from './server-dispatch.js';
|
|
2
|
+
export interface ServeStdioHandle {
|
|
3
|
+
/** Stop reading and detach listeners. Does not exit the process. */
|
|
4
|
+
close(): void;
|
|
5
|
+
/** Resolves when the input stream ends (EOF). */
|
|
6
|
+
done: Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
export interface ServeStdioOptions {
|
|
9
|
+
stdin?: NodeJS.ReadableStream | undefined;
|
|
10
|
+
stdout?: NodeJS.WritableStream | undefined;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Run an `MCPServer` over stdio: newline-delimited JSON-RPC in on stdin,
|
|
14
|
+
* responses out on stdout. CRITICAL: nothing else may write to stdout while
|
|
15
|
+
* this runs — it is the JSON-RPC channel. Route all logging to stderr.
|
|
16
|
+
*/
|
|
17
|
+
export declare function serveStdio(server: MCPServer, opts?: ServeStdioOptions): ServeStdioHandle;
|
|
18
|
+
export declare const HTTP_BODY_CAP: number;
|
|
19
|
+
//# sourceMappingURL=server-stdio.d.ts.map
|
package/dist/server.d.ts
CHANGED
|
@@ -1,182 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
* JSON-RPC 2.0 stream.
|
|
8
|
-
*
|
|
9
|
-
* The protocol core (`MCPServer`) is transport-agnostic: feed it a raw JSON
|
|
10
|
-
* line via `handleMessage`, get back a response string (or `null` for
|
|
11
|
-
* notifications). `serveStdio` wires it to stdin/stdout for the canonical
|
|
12
|
-
* stdio transport.
|
|
13
|
-
*/
|
|
14
|
-
/** A tool descriptor advertised over `tools/list`. */
|
|
15
|
-
export interface MCPServerTool {
|
|
16
|
-
name: string;
|
|
17
|
-
description?: string | undefined;
|
|
18
|
-
inputSchema: Record<string, unknown>;
|
|
19
|
-
}
|
|
20
|
-
/** The result of a `tools/call`, as the host produces it. */
|
|
21
|
-
export interface MCPServerCallResult {
|
|
22
|
-
/** Text or pre-built MCP content blocks. Strings are wrapped as a text block. */
|
|
23
|
-
content: unknown;
|
|
24
|
-
isError: boolean;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Bridges the MCP server to a tool backend (in the CLI, the `ToolRegistry`).
|
|
28
|
-
* Kept narrow so the protocol core has no dependency on `@wrongstack/core`.
|
|
29
|
-
*/
|
|
30
|
-
export interface MCPServerToolHost {
|
|
31
|
-
listTools(): MCPServerTool[] | Promise<MCPServerTool[]>;
|
|
32
|
-
callTool(name: string, args: Record<string, unknown>, opts?: {
|
|
33
|
-
signal?: AbortSignal | undefined;
|
|
34
|
-
}): Promise<MCPServerCallResult>;
|
|
35
|
-
}
|
|
36
|
-
export interface MCPServerResource {
|
|
37
|
-
uri: string;
|
|
38
|
-
name: string;
|
|
39
|
-
title?: string | undefined;
|
|
40
|
-
description?: string | undefined;
|
|
41
|
-
mimeType?: string | undefined;
|
|
42
|
-
size?: number | undefined;
|
|
43
|
-
contents: MCPResourceContents[];
|
|
44
|
-
}
|
|
45
|
-
export interface MCPServerPrompt {
|
|
46
|
-
name: string;
|
|
47
|
-
title?: string | undefined;
|
|
48
|
-
description?: string | undefined;
|
|
49
|
-
arguments?: MCPPromptArgument[] | undefined;
|
|
50
|
-
/** Static rich messages, or a text template using {{argument}} placeholders. */
|
|
51
|
-
messages?: MCPPromptMessage[] | undefined;
|
|
52
|
-
template?: string | undefined;
|
|
53
|
-
}
|
|
54
|
-
export interface MCPServerLogger {
|
|
55
|
-
warn?(msg: string): void;
|
|
56
|
-
info?(msg: string): void;
|
|
57
|
-
}
|
|
58
|
-
export interface MCPServerOptions {
|
|
59
|
-
host: MCPServerToolHost;
|
|
60
|
-
/** Advertised in the `initialize` handshake. Defaults to the wrongstack identity. */
|
|
61
|
-
serverInfo?: {
|
|
62
|
-
name: string;
|
|
63
|
-
version: string;
|
|
64
|
-
};
|
|
65
|
-
logger?: MCPServerLogger | undefined;
|
|
66
|
-
/** Explicit allowlist only; omitted means this server exposes no resources. */
|
|
67
|
-
resources?: MCPServerResource[] | undefined;
|
|
68
|
-
/** Explicit allowlist only; omitted means this server exposes no prompts. */
|
|
69
|
-
prompts?: MCPServerPrompt[] | undefined;
|
|
70
|
-
/**
|
|
71
|
-
* `InitializeResult.instructions`: how and when to use this server. Clients
|
|
72
|
-
* that honour it (Claude Code does) put it in front of the model.
|
|
73
|
-
*/
|
|
74
|
-
instructions?: string | undefined;
|
|
75
|
-
}
|
|
76
|
-
export declare class MCPServer {
|
|
77
|
-
private readonly host;
|
|
78
|
-
private readonly serverInfo;
|
|
79
|
-
private readonly logger?;
|
|
80
|
-
private readonly resources;
|
|
81
|
-
private readonly prompts;
|
|
82
|
-
private readonly instructions;
|
|
83
|
-
private readonly inFlightRequests;
|
|
84
|
-
constructor(opts: MCPServerOptions);
|
|
85
|
-
/**
|
|
86
|
-
* Handle one raw JSON-RPC line. Returns the response JSON string for
|
|
87
|
-
* requests, or `null` for notifications (no `id`) and for blank input —
|
|
88
|
-
* the caller should write the string to its output stream when non-null.
|
|
89
|
-
*/
|
|
90
|
-
handleMessage(raw: string): Promise<string | null>;
|
|
91
|
-
private dispatch;
|
|
92
|
-
/**
|
|
93
|
-
* WS-026: enforce the `inputSchema` this server advertises on `tools/list`.
|
|
94
|
-
*
|
|
95
|
-
* `tools/call` used to forward `params.arguments` to the host verbatim after
|
|
96
|
-
* checking only that it was a non-array object — so every `enum`, `required`,
|
|
97
|
-
* `additionalProperties: false`, and numeric bound in the published schema
|
|
98
|
-
* was advisory. A client (or an attacker who reached the transport) could
|
|
99
|
-
* send `{mode: "../../etc"}` to a tool whose schema declares
|
|
100
|
-
* `enum: ["read","write"]` and the tool would receive it. Publishing a
|
|
101
|
-
* contract and not enforcing it is worse than publishing none: downstream
|
|
102
|
-
* tools are written against the schema they declared.
|
|
103
|
-
*
|
|
104
|
-
* SCOPE: `validateAgainstSchema` is the shared validator that also gates the
|
|
105
|
-
* agent's own tool executor. It checks `type`, `enum`, `required`, recurses
|
|
106
|
-
* through `properties`/`items`, enforces numeric bounds
|
|
107
|
-
* (`minimum`/`maximum`), rejects unknown keys on strict-closed objects
|
|
108
|
-
* (`additionalProperties: false`), validates the `additionalProperties`
|
|
109
|
-
* subschema form against unknown-key values, applies `patternProperties`
|
|
110
|
-
* to matching keys, enforces string lengths (`minLength`/`maxLength`) and
|
|
111
|
-
* `pattern`, array lengths (`minItems`/`maxItems`/`uniqueItems`), and the
|
|
112
|
-
* combinators `allOf`/`anyOf`/`oneOf` (all landed 2026-09-11). Still
|
|
113
|
-
* advisory per the 2026-09-11 usage survey: `const` and `$ref` — declared
|
|
114
|
-
* only in the techstack rulebook, which validates with its own
|
|
115
|
-
* `validateRulebook`, not this validator.
|
|
116
|
-
*
|
|
117
|
-
* Unknown tool names are left alone — the host owns that error, and
|
|
118
|
-
* answering "no such tool" here would fork the message for no benefit.
|
|
119
|
-
*/
|
|
120
|
-
private assertArgumentsMatchSchema;
|
|
121
|
-
private encodeError;
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Marks a `tools/call` rejected by {@link MCPServer.assertArgumentsMatchSchema}
|
|
125
|
-
* so `handleMessage` can answer with JSON-RPC `-32602 Invalid params` rather
|
|
126
|
-
* than the generic internal-error code every other throw maps to.
|
|
127
|
-
*/
|
|
128
|
-
export declare class InvalidToolArgumentsError extends Error {
|
|
129
|
-
readonly name = "InvalidToolArgumentsError";
|
|
130
|
-
}
|
|
131
|
-
/** Normalize a host result's content into MCP content blocks. */
|
|
132
|
-
export declare function toContentBlocks(content: unknown): Array<{
|
|
133
|
-
type: string;
|
|
134
|
-
[key: string]: unknown;
|
|
135
|
-
}>;
|
|
136
|
-
export interface ServeStdioHandle {
|
|
137
|
-
/** Stop reading and detach listeners. Does not exit the process. */
|
|
138
|
-
close(): void;
|
|
139
|
-
/** Resolves when the input stream ends (EOF). */
|
|
140
|
-
done: Promise<void>;
|
|
141
|
-
}
|
|
142
|
-
export interface ServeStdioOptions {
|
|
143
|
-
stdin?: NodeJS.ReadableStream | undefined;
|
|
144
|
-
stdout?: NodeJS.WritableStream | undefined;
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Run an `MCPServer` over stdio: newline-delimited JSON-RPC in on stdin,
|
|
148
|
-
* responses out on stdout. CRITICAL: nothing else may write to stdout while
|
|
149
|
-
* this runs — it is the JSON-RPC channel. Route all logging to stderr.
|
|
150
|
-
*/
|
|
151
|
-
export declare function serveStdio(server: MCPServer, opts?: ServeStdioOptions): ServeStdioHandle;
|
|
152
|
-
export interface ServeHttpOptions {
|
|
153
|
-
/** TCP port. 0 picks an ephemeral port (resolved in the handle). Default 0. */
|
|
154
|
-
port?: number | undefined;
|
|
155
|
-
/** Bind address. Default '127.0.0.1' (loopback only). */
|
|
156
|
-
host?: string | undefined;
|
|
157
|
-
/**
|
|
158
|
-
* Bearer token required on every request (`Authorization: Bearer <token>`).
|
|
159
|
-
* REQUIRED when binding to a non-loopback host — `serveHttp` refuses to
|
|
160
|
-
* expose tools to the network without one.
|
|
161
|
-
*/
|
|
162
|
-
token?: string | undefined;
|
|
163
|
-
logger?: MCPServerLogger | undefined;
|
|
164
|
-
}
|
|
165
|
-
export interface ServeHttpHandle {
|
|
166
|
-
port: number;
|
|
167
|
-
host: string;
|
|
168
|
-
url: string;
|
|
169
|
-
close(): Promise<void>;
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Run an `MCPServer` over HTTP: POST a single JSON-RPC request, get the JSON
|
|
173
|
-
* response (notifications → 202 with no body). Reuses `handleMessage`, so the
|
|
174
|
-
* protocol is identical to the stdio transport.
|
|
175
|
-
*
|
|
176
|
-
* Security: binds to loopback by default. Binding to any other host (e.g.
|
|
177
|
-
* `0.0.0.0`) REQUIRES a `token` — otherwise this rejects, because it would
|
|
178
|
-
* otherwise expose tool execution to the whole network unauthenticated.
|
|
179
|
-
*/
|
|
180
|
-
export declare function serveHttp(server: MCPServer, opts?: ServeHttpOptions): Promise<ServeHttpHandle>;
|
|
181
|
-
export declare function handleHttpRequest(server: MCPServer, req: IncomingMessage, res: ServerResponse, token: string | undefined, log: MCPServerLogger | undefined, boundHost: string): Promise<void>;
|
|
1
|
+
export type { MCPServerCallResult, MCPServerLogger, MCPServerOptions, MCPServerPrompt, MCPServerResource, MCPServerTool, MCPServerToolHost, } from './server-dispatch.js';
|
|
2
|
+
export { InvalidToolArgumentsError, MCPServer, toContentBlocks } from './server-dispatch.js';
|
|
3
|
+
export type { ServeHttpHandle, ServeHttpOptions } from './server-http.js';
|
|
4
|
+
export { handleHttpRequest, serveHttp } from './server-http.js';
|
|
5
|
+
export type { ServeStdioHandle, ServeStdioOptions } from './server-stdio.js';
|
|
6
|
+
export { serveStdio } from './server-stdio.js';
|
|
182
7
|
//# sourceMappingURL=server.d.ts.map
|
package/dist/sse-reader.d.ts
CHANGED
package/dist/transport-sse.d.ts
CHANGED
|
@@ -13,6 +13,8 @@ export declare class SSETransport extends BaseHTTPTransport {
|
|
|
13
13
|
private _nextId;
|
|
14
14
|
private readerDone;
|
|
15
15
|
private closed;
|
|
16
|
+
private toolCatalogVersion;
|
|
17
|
+
private toolCatalogRevision;
|
|
16
18
|
private readLoopAbort?;
|
|
17
19
|
private reader?;
|
|
18
20
|
/** POST target announced by the server's `endpoint` event. */
|
|
@@ -8,6 +8,8 @@ import { BaseHTTPTransport, type HttpTransportOptions } from './transport-base.j
|
|
|
8
8
|
export declare class StreamableHTTPTransport extends BaseHTTPTransport {
|
|
9
9
|
private _nextId;
|
|
10
10
|
private closed;
|
|
11
|
+
private toolCatalogVersion;
|
|
12
|
+
private toolCatalogRevision;
|
|
11
13
|
private sessionId?;
|
|
12
14
|
constructor(opts: HttpTransportOptions);
|
|
13
15
|
protected genId(): number;
|
package/dist/wrap-tool.d.ts
CHANGED
|
@@ -16,5 +16,5 @@ export interface MCPToolCallObserver {
|
|
|
16
16
|
ok: boolean;
|
|
17
17
|
}, caller?: ElicitationRequester | undefined): void;
|
|
18
18
|
}
|
|
19
|
-
export declare function wrapMCPTool(serverName: string, mcpTool: MCPTool, client: MCPClientResolver, permission?: Permission, observer?: MCPToolCallObserver | undefined): Tool;
|
|
19
|
+
export declare function wrapMCPTool(serverName: string, mcpTool: MCPTool, client: MCPClientResolver, permission?: Permission, sandboxTrust?: boolean, observer?: MCPToolCallObserver | undefined): Tool;
|
|
20
20
|
//# sourceMappingURL=wrap-tool.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wrongstack/mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.33",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "WrongStack Model Context Protocol client and registry: stdio, SSE, and streamable HTTP transports.",
|
|
6
6
|
"repository": {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"!dist/**/*.map"
|
|
27
27
|
],
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@wrongstack/core": "1.0.
|
|
29
|
+
"@wrongstack/core": "1.0.33",
|
|
30
30
|
"undici": "^8.10.2"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|