@eclipse-glsp/protocol 2.7.0-next.24 → 2.7.0-next.26

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 (49) hide show
  1. package/lib/action-protocol/model-saving.d.ts +140 -5
  2. package/lib/action-protocol/model-saving.d.ts.map +1 -1
  3. package/lib/action-protocol/model-saving.js +40 -1
  4. package/lib/action-protocol/model-saving.js.map +1 -1
  5. package/lib/action-protocol/viewport.d.ts +22 -1
  6. package/lib/action-protocol/viewport.d.ts.map +1 -1
  7. package/lib/action-protocol/viewport.js +17 -1
  8. package/lib/action-protocol/viewport.js.map +1 -1
  9. package/lib/client-server-protocol/base-glsp-client.d.ts +2 -2
  10. package/lib/client-server-protocol/base-glsp-client.d.ts.map +1 -1
  11. package/lib/client-server-protocol/base-glsp-client.js +3 -2
  12. package/lib/client-server-protocol/base-glsp-client.js.map +1 -1
  13. package/lib/client-server-protocol/glsp-client.d.ts +7 -2
  14. package/lib/client-server-protocol/glsp-client.d.ts.map +1 -1
  15. package/lib/client-server-protocol/glsp-client.js.map +1 -1
  16. package/lib/client-server-protocol/glsp-server.d.ts +18 -1
  17. package/lib/client-server-protocol/glsp-server.d.ts.map +1 -1
  18. package/lib/client-server-protocol/glsp-server.js +3 -2
  19. package/lib/client-server-protocol/glsp-server.js.map +1 -1
  20. package/lib/client-server-protocol/jsonrpc/base-jsonrpc-glsp-client.d.ts +1 -1
  21. package/lib/client-server-protocol/jsonrpc/base-jsonrpc-glsp-client.d.ts.map +1 -1
  22. package/lib/client-server-protocol/jsonrpc/base-jsonrpc-glsp-client.js +4 -3
  23. package/lib/client-server-protocol/jsonrpc/base-jsonrpc-glsp-client.js.map +1 -1
  24. package/lib/client-server-protocol/mcp.d.ts +225 -0
  25. package/lib/client-server-protocol/mcp.d.ts.map +1 -0
  26. package/lib/client-server-protocol/mcp.js +75 -0
  27. package/lib/client-server-protocol/mcp.js.map +1 -0
  28. package/lib/index.d.ts +1 -0
  29. package/lib/index.d.ts.map +1 -1
  30. package/lib/index.js +1 -0
  31. package/lib/index.js.map +1 -1
  32. package/lib/utils/type-util.d.ts +8 -0
  33. package/lib/utils/type-util.d.ts.map +1 -1
  34. package/lib/utils/type-util.js +13 -1
  35. package/lib/utils/type-util.js.map +1 -1
  36. package/package.json +2 -2
  37. package/src/action-protocol/model-saving.spec.ts +127 -1
  38. package/src/action-protocol/model-saving.ts +171 -6
  39. package/src/action-protocol/viewport.spec.ts +37 -1
  40. package/src/action-protocol/viewport.ts +33 -1
  41. package/src/client-server-protocol/base-glsp-client.spec.ts +21 -6
  42. package/src/client-server-protocol/base-glsp-client.ts +3 -2
  43. package/src/client-server-protocol/glsp-client.ts +7 -3
  44. package/src/client-server-protocol/glsp-server.ts +19 -1
  45. package/src/client-server-protocol/jsonrpc/base-jsonrpc-glsp-client.spec.ts +10 -1
  46. package/src/client-server-protocol/jsonrpc/base-jsonrpc-glsp-client.ts +4 -3
  47. package/src/client-server-protocol/mcp.ts +256 -0
  48. package/src/index.ts +1 -0
  49. package/src/utils/type-util.ts +11 -0
@@ -0,0 +1,256 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2025-2026 EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the Eclipse Public License v. 2.0 which is available at
6
+ * http://www.eclipse.org/legal/epl-2.0.
7
+ *
8
+ * This Source Code may also be made available under the following Secondary
9
+ * Licenses when the conditions for such availability set forth in the Eclipse
10
+ * Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ * with the GNU Classpath Exception which is available at
12
+ * https://www.gnu.org/software/classpath/license.html.
13
+ *
14
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ ********************************************************************************/
16
+
17
+ import { AnyObject, hasObjectProp, hasStringProp } from '../utils/type-util';
18
+ import { InitializeParameters, InitializeResult } from './types';
19
+
20
+ /** Wire-protocol naming for the data-handler exposure mode (see {@link McpServerInitOptions.dataMode}). */
21
+ export type McpDataMode = 'resources' | 'tools';
22
+
23
+ /**
24
+ * Behavioral and tuning options that an MCP-aware GLSP client may pass through the
25
+ * `initialize` request. Every field here is safe for the IDE to control per-init: changing
26
+ * any of them cannot widen the network attack surface or relax the DNS-rebinding mitigation.
27
+ *
28
+ * Contrast with {@link McpServerDeployOptions}, which lists fields the adopter sets at
29
+ * deploy time and that are intentionally *not* exposed to init for security reasons. The
30
+ * split limits blast radius: behavioural fields like `port` may be negotiated by the IDE
31
+ * over the wire, while security-sensitive bind/policy fields stay adopter-controlled and
32
+ * cannot be widened by an MCP `initialize` payload.
33
+ *
34
+ * @experimental
35
+ */
36
+ export interface McpServerInitOptions {
37
+ /**
38
+ * How the data handlers are exposed to the MCP client. `'tools'` registers them as tools
39
+ * (default — most MCP clients support tools more reliably). `'resources'` registers them
40
+ * as URI-addressable Resources, the spec-aligned form, when the client is known to
41
+ * support it.
42
+ *
43
+ * @default 'tools'
44
+ */
45
+ dataMode?: McpDataMode;
46
+ /**
47
+ * The personality injected into MCP clients by reading the MCP server's instructions.
48
+ */
49
+ agentPersona?: string;
50
+ /**
51
+ * Maximum number of historical SSE events the in-memory event store retains per session.
52
+ * Older events are evicted (LRU by insert order) so memory stays bounded under long-running
53
+ * deployments. Must exceed the worst-case in-flight event count or a client reconnecting
54
+ * with a stale `Last-Event-ID` will find its resume point already evicted.
55
+ *
56
+ * @default 10000
57
+ */
58
+ eventStoreLimit?: number;
59
+ }
60
+
61
+ /**
62
+ * Security-sensitive bind/policy fields the adopter sets at deploy time on the server
63
+ * module. These fields are deliberately *not* part of the wire-protocol init schema — they
64
+ * are not reachable from {@link McpServerConfiguration.options}, and the launcher reads
65
+ * them only from the adopter-supplied defaults. The server-side runtime view that consumers
66
+ * `@inject` (the holder named {@link McpServerOptions}) carries the merged combined shape
67
+ * {@link McpServerOptions} = init ∩ deploy.
68
+ *
69
+ * Why these are deploy-only: an MCP client driven by an LLM should not be able to widen the
70
+ * server's network exposure or weaken its DNS-rebinding mitigation through an `initialize`
71
+ * payload.
72
+ *
73
+ * @experimental
74
+ */
75
+ export interface McpServerDeployOptions {
76
+ /**
77
+ * Host/interface the MCP HTTP server binds to. The launcher pins this to loopback by
78
+ * default; an adopter overrides via the server module's `McpServerDefaults` binding when
79
+ * they need a non-loopback bind.
80
+ *
81
+ * @default '127.0.0.1'
82
+ */
83
+ host?: string;
84
+ /**
85
+ * Allowed `Host` header values for the MCP HTTP endpoint. Requests whose `Host` header is
86
+ * not in this list are rejected with `403 Forbidden`. Spec MUST per the Streamable HTTP
87
+ * transport's DNS-rebinding mitigation.
88
+ *
89
+ * @default ['127.0.0.1', 'localhost']
90
+ */
91
+ allowedHosts?: string[];
92
+ /**
93
+ * Allowed `Origin` header values. When set, browser-originating requests with an `Origin`
94
+ * not in this list are rejected with `403 Forbidden`. Leave undefined to skip Origin
95
+ * checking (typical for desktop-IDE MCP clients which omit `Origin`); set explicitly when
96
+ * the deployment is fronted by a browser-based MCP client.
97
+ */
98
+ allowedOrigins?: string[];
99
+ /**
100
+ * Explicit acknowledgement that the operator accepts running an unauthenticated MCP
101
+ * endpoint on a non-loopback bind. The MCP server ships with NO built-in authentication;
102
+ * the default `host: '127.0.0.1'` is the only safe configuration without external
103
+ * fronting. Setting a non-loopback `host` (e.g., `'0.0.0.0'` for "easier dev access")
104
+ * WITHOUT setting this flag causes the launcher to refuse to start with an actionable
105
+ * error.
106
+ *
107
+ * Set to `true` only when an external mechanism (reverse proxy, mTLS, network ACL, etc.)
108
+ * authenticates traffic before it reaches the MCP endpoint. Deploy-only — like the other
109
+ * fields in this type, it is unreachable from the wire.
110
+ *
111
+ * @default false
112
+ */
113
+ acknowledgedNoAuth?: boolean;
114
+ }
115
+
116
+ /**
117
+ * Combined view of MCP server options as seen by the server-side runtime (defaults merged
118
+ * with the init-time overrides). Adopters supplying defaults via the server module's
119
+ * `McpServerDefaults` binding use this shape; per-init overrides use the narrower
120
+ * {@link McpServerInitOptions}.
121
+ *
122
+ * @experimental
123
+ */
124
+ export type McpServerOptions = McpServerInitOptions & McpServerDeployOptions;
125
+
126
+ /** @experimental */
127
+ export interface McpServerConfiguration {
128
+ /**
129
+ * The port on which the MCP server should be started. Defaults to `0` (a random available
130
+ * port). The resolved URL is reported in {@link McpInitializeResult.mcpServer.url} and as a
131
+ * tagged log line on the GLSP server's stdout (`[GLSP-MCP-Server]:Ready. ...`) so that
132
+ * IDE integrations can pick it up automatically (mirroring how the GLSP server itself
133
+ * reports its port).
134
+ *
135
+ * Why `port` lives here but `host` lives on {@link McpServerDeployOptions}: an IDE has a
136
+ * legitimate operational reason to pin a specific port (matching its MCP client config),
137
+ * and the security blast radius of port choice is local. `host`, by contrast, controls
138
+ * the bind interface — letting an init payload widen it from loopback would re-open the
139
+ * DNS-rebinding attack pattern that the Host/Origin checks mitigate.
140
+ */
141
+ port?: number;
142
+ /**
143
+ * The route on which the MCP server should be started.
144
+ */
145
+ route?: string;
146
+ /**
147
+ * The name of the MCP server.
148
+ */
149
+ name?: string;
150
+ /**
151
+ * Behavioral and tuning options the IDE may set per init. Security-sensitive bind/policy
152
+ * fields ({@link McpServerDeployOptions}) are intentionally not part of this shape.
153
+ */
154
+ options?: McpServerInitOptions;
155
+ }
156
+
157
+ /** @experimental */
158
+ export interface McpInitializeParameters extends InitializeParameters {
159
+ /**
160
+ * MCP server configuration parameters.
161
+ *
162
+ * **Presence is the opt-in signal.** The MCP server is started if and only if this key is
163
+ * defined in the initialize parameters; the value's content controls *how* it is configured.
164
+ * Omitting the key entirely disables MCP. Setting it to an empty object (`{ mcpServer: {} }`)
165
+ * enables MCP with all defaults. A populated object overrides specific fields.
166
+ *
167
+ * @example
168
+ * // Disable MCP (the default for most clients)
169
+ * { applicationId: '...', protocolVersion: '...' }
170
+ *
171
+ * @example
172
+ * // Enable MCP with all defaults
173
+ * { applicationId: '...', protocolVersion: '...', mcpServer: {} }
174
+ *
175
+ * @example
176
+ * // Enable MCP with a custom port
177
+ * { applicationId: '...', protocolVersion: '...', mcpServer: { port: 12345 } }
178
+ */
179
+ mcpServer?: McpServerConfiguration;
180
+ }
181
+
182
+ export namespace McpInitializeParameters {
183
+ /**
184
+ * Type guard that also doubles as the **opt-in check**: returns `true` iff `params.mcpServer`
185
+ * is defined (regardless of its content). Server-side code uses this to decide whether to
186
+ * start the MCP HTTP server at all. See {@link McpInitializeParameters.mcpServer} for the
187
+ * opt-in semantics.
188
+ */
189
+ export function is(params?: InitializeParameters): params is McpInitializeParameters {
190
+ return AnyObject.is(params) && hasObjectProp(params, 'mcpServer');
191
+ }
192
+
193
+ /**
194
+ * Returns the {@link McpServerConfiguration} from the given initialize parameters, or
195
+ * `undefined` if MCP is not opted in (i.e., `mcpServer` is missing). A return value of `{}`
196
+ * (an empty object) means "MCP is enabled, use all defaults" — distinct from `undefined`
197
+ * which means "MCP is not enabled."
198
+ */
199
+ export function getServerConfig(params?: InitializeParameters): McpServerConfiguration | undefined {
200
+ return is(params) ? params.mcpServer : undefined;
201
+ }
202
+ }
203
+
204
+ /** @experimental */
205
+ export interface McpServerResult {
206
+ /** The name of the MCP server. */
207
+ name: string;
208
+
209
+ /** The URL at which the MCP server is accessible. */
210
+ url: string;
211
+
212
+ /** Optional headers AI clients should include when connecting. */
213
+ headers?: Record<string, string>;
214
+ }
215
+
216
+ export namespace McpServerResult {
217
+ /** True when the candidate is shaped like {@link McpServerResult}. */
218
+ export function is(candidate: unknown): candidate is McpServerResult {
219
+ return AnyObject.is(candidate) && hasStringProp(candidate, 'name') && hasStringProp(candidate, 'url');
220
+ }
221
+ }
222
+
223
+ /**
224
+ * Initialize-result extension carrying the MCP server's announced URL. Returned by the
225
+ * GLSP server's `initialize` handshake when (and only when) MCP was opted into via
226
+ * {@link McpInitializeParameters.mcpServer}; otherwise the server returns a plain
227
+ * {@link InitializeResult} and callers should narrow with {@link McpInitializeResult.is}.
228
+ *
229
+ * @experimental
230
+ */
231
+ export interface McpInitializeResult extends InitializeResult {
232
+ mcpServer: McpServerResult;
233
+ }
234
+
235
+ export namespace McpInitializeResult {
236
+ /** Narrows to `McpInitializeResult` (i.e., asserts `mcpServer` is populated and well-shaped). */
237
+ export function is(result?: InitializeResult): result is McpInitializeResult {
238
+ return AnyObject.is(result) && hasObjectProp(result, 'mcpServer') && McpServerResult.is((result as McpInitializeResult).mcpServer);
239
+ }
240
+
241
+ /** Returns the {@link McpServerResult} from the given initialize result, or `undefined` if MCP is not announced. */
242
+ export function getServer(result?: InitializeResult): McpServerResult | undefined {
243
+ return is(result) ? result.mcpServer : undefined;
244
+ }
245
+
246
+ /**
247
+ * Attaches an {@link McpServerResult} announcement to a base {@link InitializeResult},
248
+ * returning the augmented {@link McpInitializeResult}. Server-side handshake code uses this
249
+ * instead of an in-place cast to keep the mutation typed.
250
+ */
251
+ export function attachServer(result: InitializeResult, server: McpServerResult): McpInitializeResult {
252
+ const augmented = result as McpInitializeResult;
253
+ augmented.mcpServer = server;
254
+ return augmented;
255
+ }
256
+ }
package/src/index.ts CHANGED
@@ -43,6 +43,7 @@ export * from './client-server-protocol/jsonrpc/glsp-jsonrpc-server';
43
43
  export * from './client-server-protocol/jsonrpc/websocket-connection';
44
44
  export * from './client-server-protocol/jsonrpc/worker-connection-provider';
45
45
  export * from './client-server-protocol/jsonrpc/ws-connection-provider';
46
+ export * from './client-server-protocol/mcp';
46
47
  export * from './client-server-protocol/types';
47
48
  export * from './model/default-types';
48
49
  export * from './model/model-schema';
@@ -67,6 +67,17 @@ export type PropertiesOfType<T, V> = Pick<T, KeysOfType<T, V>>;
67
67
  */
68
68
  export type MaybePromise<T> = T | PromiseLike<T>;
69
69
 
70
+ export namespace MaybePromise {
71
+ /**
72
+ * Type guard to check whether a given value is a {@link PromiseLike}.
73
+ * @param value The value to check.
74
+ * @returns `true` if the value is a `PromiseLike`.
75
+ */
76
+ export function isPromise<T = unknown>(value: MaybePromise<T>): value is PromiseLike<T> {
77
+ return AnyObject.is(value) && hasFunctionProp(value, 'then');
78
+ }
79
+ }
80
+
70
81
  /**
71
82
  * Utility type to describe typeguard functions.
72
83
  */