@zeke-02/docx-editor-agents 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/LICENSE +201 -0
- package/README.md +126 -0
- package/dist/agent-types-C8RvQB7n.d.mts +36 -0
- package/dist/agent-types-C8RvQB7n.d.ts +36 -0
- package/dist/ai-sdk/react.d.mts +57 -0
- package/dist/ai-sdk/react.d.ts +57 -0
- package/dist/ai-sdk/react.js +1 -0
- package/dist/ai-sdk/react.mjs +1 -0
- package/dist/ai-sdk/server.d.mts +80 -0
- package/dist/ai-sdk/server.d.ts +80 -0
- package/dist/ai-sdk/server.js +1 -0
- package/dist/ai-sdk/server.mjs +1 -0
- package/dist/ai-sdk/vue.d.ts +32 -0
- package/dist/ai-sdk/vue.js +1 -0
- package/dist/ai-sdk/vue.mjs +28 -0
- package/dist/bridge.d.mts +19 -0
- package/dist/bridge.d.ts +19 -0
- package/dist/bridge.js +1 -0
- package/dist/bridge.mjs +1 -0
- package/dist/chunk-24MVJKCP.mjs +8 -0
- package/dist/chunk-2RGRAPLW.js +5 -0
- package/dist/chunk-53PAUP4S.js +2 -0
- package/dist/chunk-AU3KR5IN.mjs +5 -0
- package/dist/chunk-KMEZXSKR.mjs +2 -0
- package/dist/chunk-RI5S75JY.js +8 -0
- package/dist/chunk-UNUH3LRU.mjs +1 -0
- package/dist/chunk-VXAJD6QK.js +1 -0
- package/dist/docx-editor-agents.css +2 -0
- package/dist/index.d.mts +178 -0
- package/dist/index.d.ts +178 -0
- package/dist/index.js +1 -0
- package/dist/index.mjs +1 -0
- package/dist/mcp.d.mts +200 -0
- package/dist/mcp.d.ts +200 -0
- package/dist/mcp.js +4 -0
- package/dist/mcp.mjs +4 -0
- package/dist/react.d.mts +251 -0
- package/dist/react.d.ts +251 -0
- package/dist/react.js +9 -0
- package/dist/react.mjs +9 -0
- package/dist/server-uWvnaIh-.d.mts +620 -0
- package/dist/server-uWvnaIh-.d.ts +620 -0
- package/dist/server.d.mts +35 -0
- package/dist/server.d.ts +35 -0
- package/dist/server.js +1 -0
- package/dist/server.mjs +1 -0
- package/dist/vue/components/AIContextMenu.d.ts +33 -0
- package/dist/vue/components/AIResponsePreview.d.ts +40 -0
- package/dist/vue/components/AgentChatLog.d.ts +37 -0
- package/dist/vue/components/AgentComposer.d.ts +30 -0
- package/dist/vue/components/AgentPanel.d.ts +49 -0
- package/dist/vue/components/AgentSuggestionChip.d.ts +10 -0
- package/dist/vue/components/AgentTimeline.d.ts +19 -0
- package/dist/vue/composables/useAgentBridge.d.ts +19 -0
- package/dist/vue/types.d.ts +5 -0
- package/dist/vue.d.ts +72 -0
- package/dist/vue.js +20 -0
- package/dist/vue.mjs +2026 -0
- package/package.json +157 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @zeke-02/docx-editor-agents
|
|
3
|
+
*
|
|
4
|
+
* Word-like API for AI document review.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* const reviewer = await DocxReviewer.fromBuffer(buffer, 'AI Reviewer');
|
|
9
|
+
*
|
|
10
|
+
* // Read
|
|
11
|
+
* const text = reviewer.getContentAsText();
|
|
12
|
+
*
|
|
13
|
+
* // Comment on a paragraph
|
|
14
|
+
* reviewer.addComment(5, 'Liability cap seems too low.');
|
|
15
|
+
*
|
|
16
|
+
* // Replace text (creates tracked change)
|
|
17
|
+
* reviewer.replace(5, '$50k', '$500k');
|
|
18
|
+
*
|
|
19
|
+
* // Or batch from LLM JSON response
|
|
20
|
+
* reviewer.applyReview({
|
|
21
|
+
* comments: [{ paragraphIndex: 5, text: 'Too low.' }],
|
|
22
|
+
* proposals: [{ paragraphIndex: 5, search: '$50k', replaceWith: '$500k' }],
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* const output = await reviewer.toBuffer();
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @packageDocumentation
|
|
29
|
+
* @public
|
|
30
|
+
*/
|
|
31
|
+
import { G as GetContentOptions, C as ContentBlock, a as CommentFilter, R as ReviewComment, b as ChangeFilter, c as ReviewChange, F as FoundMatch, S as SelectionInfo, A as AddCommentByParaIdOptions, d as ReplyOptions, P as ProposeChangeOptions, e as ApplyFormattingOptions, f as SetParagraphStyleOptions, g as PageContent, h as ContentChangeEvent, i as SelectionChangeEvent } from './server-uWvnaIh-.js';
|
|
32
|
+
export { j as AgentToolDefinition, k as AgentToolResult, B as BatchError, l as BatchResult, m as BatchReviewOptions, D as DocxReviewer, n as agentTools, o as createReviewerBridge, p as executeToolCall, q as getToolSchemas } from './server-uWvnaIh-.js';
|
|
33
|
+
import '@zeke-02/docx-editor-core/headless';
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Error classes for @zeke-02/docx-editor-agents
|
|
37
|
+
*/
|
|
38
|
+
declare class TextNotFoundError extends Error {
|
|
39
|
+
constructor(search: string, paragraphIndex?: number);
|
|
40
|
+
}
|
|
41
|
+
declare class ChangeNotFoundError extends Error {
|
|
42
|
+
constructor(id: number);
|
|
43
|
+
}
|
|
44
|
+
declare class CommentNotFoundError extends Error {
|
|
45
|
+
constructor(id: number);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Formal Word JS API parity contract.
|
|
50
|
+
*
|
|
51
|
+
* This file declares what subset of Microsoft Word's Office.js JavaScript API
|
|
52
|
+
* (https://learn.microsoft.com/en-us/javascript/api/word) we mirror, **at the
|
|
53
|
+
* type level**. It is checked at compile time: `EditorBridge` must satisfy
|
|
54
|
+
* `WordCompatBridge` (verified via the static assertion at the bottom).
|
|
55
|
+
*
|
|
56
|
+
* The assertion is the source of truth. If you change the bridge surface and
|
|
57
|
+
* forget to update parity, typecheck breaks.
|
|
58
|
+
*
|
|
59
|
+
* ## What we mirror (✓)
|
|
60
|
+
*
|
|
61
|
+
* | Word JS API | Our equivalent |
|
|
62
|
+
* | ----------------------------------- | ------------------------------------- |
|
|
63
|
+
* | `Range` (stable handle) | `paraId: string` |
|
|
64
|
+
* | `body.search(text)` → Ranges | `findText(query, opts) → FoundMatch[]`|
|
|
65
|
+
* | `range.insertComment(text)` | `addComment({paraId, text, search?})` |
|
|
66
|
+
* | `comment.reply(text)` | `replyTo(commentId, {text})` |
|
|
67
|
+
* | `comment.resolved = true` | `resolveComment(commentId)` |
|
|
68
|
+
* | `range.insertText(text, location)` | `proposeChange({paraId, search, replaceWith})` (3 modes via empty-string semantics) |
|
|
69
|
+
* | `document.getSelection()` | `getSelection() → SelectionInfo|null` |
|
|
70
|
+
* | `range.scrollIntoView()` | `scrollTo(paraId)` |
|
|
71
|
+
* | `commentCollection.getItems()` | `getComments(filter?)` |
|
|
72
|
+
* | `body.paragraphs.getItems()` | `getContent(opts?)` |
|
|
73
|
+
* | `document.body.text` | `getContentAsText(opts?)` |
|
|
74
|
+
* | `revisionCollection.getItems()` | `getChanges(filter?)` |
|
|
75
|
+
* | `Document.onContentChanged.add(...)`| `onContentChange(listener)` |
|
|
76
|
+
* | `Document.onSelectionChanged.add()` | `onSelectionChange(listener)` |
|
|
77
|
+
* | `Range.font.bold` / `italic` / `color` / `size` / `name` | `applyFormatting({paraId, search?, marks})` |
|
|
78
|
+
* | `ParagraphFormat.style` / `applyStyle(...)` | `setParagraphStyle({paraId, styleId})` |
|
|
79
|
+
*
|
|
80
|
+
* ## Beyond Word's surface (paged-document affordances)
|
|
81
|
+
*
|
|
82
|
+
* - `getPage(n)` / `getPages({from, to})` / `getTotalPages()` — Word's JS API
|
|
83
|
+
* doesn't model pages as first-class addressable units. We do, because the
|
|
84
|
+
* editor is paged. Backed by the layout-painter's page boundary state.
|
|
85
|
+
*
|
|
86
|
+
* ## Differences (intentional, documented)
|
|
87
|
+
*
|
|
88
|
+
* - All "insertText" overloads collapse into `proposeChange` with empty-string
|
|
89
|
+
* semantics: replaceWith="" deletes; search="" inserts at paragraph end;
|
|
90
|
+
* both non-empty replaces. Word has separate `insertText(...,'Replace')`,
|
|
91
|
+
* `insertText(...,'Before')`, etc.; we found three modes were enough and
|
|
92
|
+
* serialize cleaner for LLM tool calls.
|
|
93
|
+
* - Tracked changes are always *suggestions* in our world. Word lets the
|
|
94
|
+
* range mutate directly; we always go through the tracked-change path so
|
|
95
|
+
* the human keeps the final say. (This matches the agent UX.)
|
|
96
|
+
* - Word's `Range.context.sync()` is unnecessary — every call is one PM
|
|
97
|
+
* transaction.
|
|
98
|
+
* - Word's `Range` is a stateful object. Ours is a plain `{paraId, search?}`
|
|
99
|
+
* JSON value, so it survives JSON.stringify and works for tool calls / MCP.
|
|
100
|
+
*
|
|
101
|
+
* ## Out of scope (gaps we deliberately don't implement)
|
|
102
|
+
*
|
|
103
|
+
* - Paragraph creation (`body.insertParagraph`). Out of scope for v1.
|
|
104
|
+
* - Table mutation (insert row/col, delete cell). Read-only.
|
|
105
|
+
* - Headers / footers / sections.
|
|
106
|
+
* - `Range.getOoxml()` / `getHtml()`. Plain text only.
|
|
107
|
+
* - `customXmlParts` / `contentControls`.
|
|
108
|
+
* - Accept / reject tracked changes. Human-only by design.
|
|
109
|
+
*
|
|
110
|
+
* Future versions can grow these by extending this interface — typecheck
|
|
111
|
+
* will then enforce the new contract.
|
|
112
|
+
*/
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* The formal Word-JS-API parity surface. Each method maps to one or more
|
|
116
|
+
* Word API methods (named in the JSDoc above each member).
|
|
117
|
+
*
|
|
118
|
+
* If you change the EditorBridge surface, this interface must change too —
|
|
119
|
+
* the static assertion at the bottom of the file enforces it.
|
|
120
|
+
*/
|
|
121
|
+
interface WordCompatBridge {
|
|
122
|
+
/** Word: `document.body.text` (stringified, indexed lines). */
|
|
123
|
+
getContentAsText(options?: GetContentOptions): string;
|
|
124
|
+
/** Word: `body.paragraphs.getItems()`. */
|
|
125
|
+
getContent(options?: GetContentOptions): ContentBlock[];
|
|
126
|
+
/** Word: `commentCollection.getItems()`. */
|
|
127
|
+
getComments(filter?: CommentFilter): ReviewComment[];
|
|
128
|
+
/** Word: `revisionCollection.getItems()`. */
|
|
129
|
+
getChanges(filter?: ChangeFilter): ReviewChange[];
|
|
130
|
+
/** Word: `body.search(text)` returning Range[]. */
|
|
131
|
+
findText(query: string, options?: {
|
|
132
|
+
caseSensitive?: boolean;
|
|
133
|
+
limit?: number;
|
|
134
|
+
}): FoundMatch[];
|
|
135
|
+
/** Word: `document.getSelection()`. */
|
|
136
|
+
getSelection(): SelectionInfo | null;
|
|
137
|
+
/** Word: `range.insertComment(text)`. Anchored by paraId (Range handle). */
|
|
138
|
+
addComment(options: AddCommentByParaIdOptions): number | null;
|
|
139
|
+
/** Word: `comment.reply(text)`. */
|
|
140
|
+
replyTo(commentId: number, options: ReplyOptions): number | null;
|
|
141
|
+
/** Word: `comment.resolved = true`. */
|
|
142
|
+
resolveComment(commentId: number): void;
|
|
143
|
+
/**
|
|
144
|
+
* Word: `range.insertText(text, location)` collapsed into one verb.
|
|
145
|
+
* - replacement: search non-empty, replaceWith non-empty
|
|
146
|
+
* - deletion: search non-empty, replaceWith ""
|
|
147
|
+
* - insertion: search "", replaceWith non-empty (paragraph end)
|
|
148
|
+
*/
|
|
149
|
+
proposeChange(options: ProposeChangeOptions): boolean;
|
|
150
|
+
/**
|
|
151
|
+
* Word: `range.font.bold = true` / `range.font.italic = true` / etc.
|
|
152
|
+
* Applied to a paragraph or to a unique phrase within it. Direct edit,
|
|
153
|
+
* not a tracked change.
|
|
154
|
+
*/
|
|
155
|
+
applyFormatting(options: ApplyFormattingOptions): boolean;
|
|
156
|
+
/** Word: `paragraph.styleBuiltIn = ...` / `paragraph.style = 'Heading 1'`. */
|
|
157
|
+
setParagraphStyle(options: SetParagraphStyleOptions): boolean;
|
|
158
|
+
/**
|
|
159
|
+
* Read one rendered page (1-indexed). Word's JS API does not expose pages
|
|
160
|
+
* as first-class objects; we do because the editor is paged.
|
|
161
|
+
*/
|
|
162
|
+
getPage(pageNumber: number): PageContent | null;
|
|
163
|
+
/** Read a range of rendered pages (1-indexed, inclusive). */
|
|
164
|
+
getPages(options: {
|
|
165
|
+
from: number;
|
|
166
|
+
to: number;
|
|
167
|
+
}): PageContent[];
|
|
168
|
+
/** Total number of pages currently rendered. */
|
|
169
|
+
getTotalPages(): number;
|
|
170
|
+
/** Word: `range.scrollIntoView()`. */
|
|
171
|
+
scrollTo(paraId: string): boolean;
|
|
172
|
+
/** Word: `Document.onContentChanged.add(handler)`. Returns unsubscribe. */
|
|
173
|
+
onContentChange(listener: (event: ContentChangeEvent) => void): () => void;
|
|
174
|
+
/** Word: `Document.onSelectionChanged.add(handler)`. Returns unsubscribe. */
|
|
175
|
+
onSelectionChange(listener: (event: SelectionChangeEvent) => void): () => void;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export { ChangeNotFoundError, CommentNotFoundError, ContentBlock, GetContentOptions, ReviewChange, ReviewComment, TextNotFoundError, type WordCompatBridge };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'use strict';var chunkVXAJD6QK_js=require('./chunk-VXAJD6QK.js'),chunk2RGRAPLW_js=require('./chunk-2RGRAPLW.js'),chunkRI5S75JY_js=require('./chunk-RI5S75JY.js');Object.defineProperty(exports,"DocxReviewer",{enumerable:true,get:function(){return chunkVXAJD6QK_js.a}});Object.defineProperty(exports,"ChangeNotFoundError",{enumerable:true,get:function(){return chunk2RGRAPLW_js.g}});Object.defineProperty(exports,"CommentNotFoundError",{enumerable:true,get:function(){return chunk2RGRAPLW_js.h}});Object.defineProperty(exports,"TextNotFoundError",{enumerable:true,get:function(){return chunk2RGRAPLW_js.f}});Object.defineProperty(exports,"createReviewerBridge",{enumerable:true,get:function(){return chunk2RGRAPLW_js.m}});Object.defineProperty(exports,"agentTools",{enumerable:true,get:function(){return chunkRI5S75JY_js.a}});Object.defineProperty(exports,"executeToolCall",{enumerable:true,get:function(){return chunkRI5S75JY_js.b}});Object.defineProperty(exports,"getToolSchemas",{enumerable:true,get:function(){return chunkRI5S75JY_js.d}});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{a as DocxReviewer}from'./chunk-UNUH3LRU.mjs';export{g as ChangeNotFoundError,h as CommentNotFoundError,f as TextNotFoundError,m as createReviewerBridge}from'./chunk-AU3KR5IN.mjs';export{a as agentTools,b as executeToolCall,d as getToolSchemas}from'./chunk-24MVJKCP.mjs';
|
package/dist/mcp.d.mts
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @zeke-02/docx-editor-agents/mcp
|
|
3
|
+
*
|
|
4
|
+
* Model Context Protocol (MCP) server for the docx editor agent bridge.
|
|
5
|
+
*
|
|
6
|
+
* Two transports, same core:
|
|
7
|
+
* - `stdio`: classic MCP transport. Use `runStdioServer(bridge)` from a
|
|
8
|
+
* Node subprocess that Claude Desktop, Cursor, or any MCP-aware client
|
|
9
|
+
* will spawn. Newline-delimited JSON-RPC.
|
|
10
|
+
* - `direct`: call `new McpServer(bridge).handle(message)` if you have
|
|
11
|
+
* your own transport (WebSocket, `postMessage`, HTTP long-poll, etc.).
|
|
12
|
+
*
|
|
13
|
+
* The server is transport-agnostic and zero-dep. The stdio module reaches
|
|
14
|
+
* for `process.stdin` / `process.stdout` only when you call
|
|
15
|
+
* `runStdioServer` without explicit streams.
|
|
16
|
+
*
|
|
17
|
+
* @packageDocumentation
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
20
|
+
import { E as EditorBridge } from './server-uWvnaIh-.mjs';
|
|
21
|
+
import '@zeke-02/docx-editor-core/headless';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* MCP wire protocol (subset) — JSON-RPC 2.0 framing + the message types we
|
|
25
|
+
* actually implement. Zero dependencies. Pure functions; everything is unit-
|
|
26
|
+
* testable without a transport.
|
|
27
|
+
*
|
|
28
|
+
* This is NOT a full MCP SDK. We implement only what the server needs:
|
|
29
|
+
* - initialize / initialized
|
|
30
|
+
* - tools/list
|
|
31
|
+
* - tools/call
|
|
32
|
+
* - notifications/cancelled (no-op, accepted)
|
|
33
|
+
*
|
|
34
|
+
* Spec reference: https://spec.modelcontextprotocol.io
|
|
35
|
+
*/
|
|
36
|
+
type JsonRpcId = string | number | null;
|
|
37
|
+
interface JsonRpcRequest {
|
|
38
|
+
jsonrpc: '2.0';
|
|
39
|
+
id: JsonRpcId;
|
|
40
|
+
method: string;
|
|
41
|
+
params?: unknown;
|
|
42
|
+
}
|
|
43
|
+
interface JsonRpcNotification {
|
|
44
|
+
jsonrpc: '2.0';
|
|
45
|
+
method: string;
|
|
46
|
+
params?: unknown;
|
|
47
|
+
}
|
|
48
|
+
interface JsonRpcSuccess {
|
|
49
|
+
jsonrpc: '2.0';
|
|
50
|
+
id: JsonRpcId;
|
|
51
|
+
result: unknown;
|
|
52
|
+
}
|
|
53
|
+
interface JsonRpcError {
|
|
54
|
+
jsonrpc: '2.0';
|
|
55
|
+
id: JsonRpcId;
|
|
56
|
+
error: {
|
|
57
|
+
code: number;
|
|
58
|
+
message: string;
|
|
59
|
+
data?: unknown;
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
type JsonRpcResponse = JsonRpcSuccess | JsonRpcError;
|
|
63
|
+
type JsonRpcMessage = JsonRpcRequest | JsonRpcNotification | JsonRpcResponse;
|
|
64
|
+
/** Standard JSON-RPC error codes. We only ever emit JSON-RPC errors for
|
|
65
|
+
* protocol-level problems; tool execution failures use MCP's `isError`
|
|
66
|
+
* envelope inside a successful response, per spec. */
|
|
67
|
+
declare const ErrorCode: {
|
|
68
|
+
readonly ParseError: -32700;
|
|
69
|
+
readonly InvalidRequest: -32600;
|
|
70
|
+
readonly MethodNotFound: -32601;
|
|
71
|
+
readonly InvalidParams: -32602;
|
|
72
|
+
readonly InternalError: -32603;
|
|
73
|
+
};
|
|
74
|
+
interface McpInitializeResult {
|
|
75
|
+
protocolVersion: string;
|
|
76
|
+
capabilities: {
|
|
77
|
+
tools?: Record<string, unknown>;
|
|
78
|
+
};
|
|
79
|
+
serverInfo: {
|
|
80
|
+
name: string;
|
|
81
|
+
version: string;
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
interface McpToolDescriptor {
|
|
85
|
+
name: string;
|
|
86
|
+
description: string;
|
|
87
|
+
inputSchema: Record<string, unknown>;
|
|
88
|
+
}
|
|
89
|
+
interface McpToolsListResult {
|
|
90
|
+
tools: McpToolDescriptor[];
|
|
91
|
+
}
|
|
92
|
+
interface McpToolsCallParams {
|
|
93
|
+
name: string;
|
|
94
|
+
arguments?: Record<string, unknown>;
|
|
95
|
+
}
|
|
96
|
+
interface McpContent {
|
|
97
|
+
type: 'text';
|
|
98
|
+
text: string;
|
|
99
|
+
}
|
|
100
|
+
interface McpToolsCallResult {
|
|
101
|
+
content: McpContent[];
|
|
102
|
+
isError?: boolean;
|
|
103
|
+
}
|
|
104
|
+
declare function isJsonRpcRequest(m: unknown): m is JsonRpcRequest;
|
|
105
|
+
declare function isJsonRpcNotification(m: unknown): m is JsonRpcNotification;
|
|
106
|
+
declare function makeSuccess(id: JsonRpcId, result: unknown): JsonRpcSuccess;
|
|
107
|
+
declare function makeError(id: JsonRpcId, code: number, message: string, data?: unknown): JsonRpcError;
|
|
108
|
+
interface ParseResult {
|
|
109
|
+
/** Parsed messages. */
|
|
110
|
+
messages: JsonRpcMessage[];
|
|
111
|
+
/** Lines that failed to parse — caller should send a ParseError per line if it had a discernible id. */
|
|
112
|
+
parseErrors: string[];
|
|
113
|
+
/** Remaining buffer (no trailing newline yet). */
|
|
114
|
+
rest: string;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Parse newline-delimited JSON-RPC frames out of a buffer. Returns parsed
|
|
118
|
+
* messages plus any leftover bytes. Tolerates blank lines.
|
|
119
|
+
*/
|
|
120
|
+
declare function parseFrames(buffer: string): ParseResult;
|
|
121
|
+
/** Encode a JSON-RPC message as a single newline-terminated frame. */
|
|
122
|
+
declare function encodeFrame(message: JsonRpcMessage): string;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* MCP server core. Transport-agnostic — accepts a JsonRpcRequest, returns
|
|
126
|
+
* either a JsonRpcResponse or `null` (for notifications, which never reply).
|
|
127
|
+
*
|
|
128
|
+
* Wraps an EditorBridge: tools/list returns the bridge's tool schemas in MCP
|
|
129
|
+
* shape; tools/call dispatches via executeToolCall and converts the
|
|
130
|
+
* AgentToolResult into MCP CallToolResult content.
|
|
131
|
+
*/
|
|
132
|
+
|
|
133
|
+
interface McpServerOptions {
|
|
134
|
+
/** Server name reported in `initialize` response. Default: `@zeke-02/docx-editor-agents`. */
|
|
135
|
+
name?: string;
|
|
136
|
+
/** Server version. Default: `0.0.0` (override at build time). */
|
|
137
|
+
version?: string;
|
|
138
|
+
/** MCP protocol version we claim to speak. Default: `2025-06-18`. */
|
|
139
|
+
protocolVersion?: string;
|
|
140
|
+
}
|
|
141
|
+
declare class McpServer {
|
|
142
|
+
private readonly bridge;
|
|
143
|
+
private readonly opts;
|
|
144
|
+
constructor(bridge: EditorBridge, options?: McpServerOptions);
|
|
145
|
+
/**
|
|
146
|
+
* Handle one inbound message. Returns the response to send back, or `null`
|
|
147
|
+
* for notifications and other no-reply messages. Never throws.
|
|
148
|
+
*/
|
|
149
|
+
handle(message: JsonRpcMessage): JsonRpcResponse | null;
|
|
150
|
+
private handleInitialize;
|
|
151
|
+
private handleToolsList;
|
|
152
|
+
private handleToolsCall;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Stdio transport for the MCP server. Reads newline-delimited JSON-RPC from
|
|
157
|
+
* an input stream, dispatches via McpServer, writes responses to an output
|
|
158
|
+
* stream. Pure stream handling — no Node-only assumptions beyond "Readable
|
|
159
|
+
* has .on('data') and Writable has .write".
|
|
160
|
+
*
|
|
161
|
+
* For real Node usage:
|
|
162
|
+
* import { runStdioServer } from '@zeke-02/docx-editor-agents/mcp';
|
|
163
|
+
* runStdioServer(bridge);
|
|
164
|
+
*
|
|
165
|
+
* For tests, pass any EventEmitter-shaped Readable + a function-shaped
|
|
166
|
+
* Writable; see __tests__/mcp/stdio.test.ts.
|
|
167
|
+
*/
|
|
168
|
+
|
|
169
|
+
/** Minimal duck-typed input stream — anything with `on('data', cb)` works. */
|
|
170
|
+
interface InputStream {
|
|
171
|
+
on(event: 'data', listener: (chunk: Buffer | string) => void): unknown;
|
|
172
|
+
on(event: 'end', listener: () => void): unknown;
|
|
173
|
+
on(event: 'error', listener: (err: Error) => void): unknown;
|
|
174
|
+
}
|
|
175
|
+
/** Minimal duck-typed output stream — anything with a `write(string) => bool` works. */
|
|
176
|
+
interface OutputStream {
|
|
177
|
+
write(chunk: string): boolean | void;
|
|
178
|
+
}
|
|
179
|
+
interface StdioServerOptions extends McpServerOptions {
|
|
180
|
+
input?: InputStream;
|
|
181
|
+
output?: OutputStream;
|
|
182
|
+
/** Called with diagnostic strings (e.g. parse errors). Default: stderr. */
|
|
183
|
+
log?: (msg: string) => void;
|
|
184
|
+
}
|
|
185
|
+
interface StdioServerHandle {
|
|
186
|
+
/** Underlying server (for tests / introspection). */
|
|
187
|
+
server: McpServer;
|
|
188
|
+
/** Manually feed a raw chunk (used by tests; the live transport calls this internally). */
|
|
189
|
+
feed: (chunk: string | Buffer) => void;
|
|
190
|
+
/** Stop accepting input and reject further writes. Idempotent. */
|
|
191
|
+
close: () => void;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Wire an EditorBridge to a JSON-RPC stdio loop. Returns immediately; reading
|
|
195
|
+
* happens via the stream listeners. Designed to be testable: pass in fake
|
|
196
|
+
* streams, call `feed(...)` directly, then assert on what was written.
|
|
197
|
+
*/
|
|
198
|
+
declare function runStdioServer(bridge: EditorBridge, options?: StdioServerOptions): StdioServerHandle;
|
|
199
|
+
|
|
200
|
+
export { ErrorCode, type JsonRpcError, type JsonRpcId, type JsonRpcMessage, type JsonRpcNotification, type JsonRpcRequest, type JsonRpcResponse, type JsonRpcSuccess, type McpContent, type McpInitializeResult, McpServer, type McpServerOptions, type McpToolDescriptor, type McpToolsCallParams, type McpToolsCallResult, type McpToolsListResult, type StdioServerHandle, type StdioServerOptions, encodeFrame, isJsonRpcNotification, isJsonRpcRequest, makeError, makeSuccess, parseFrames, runStdioServer };
|
package/dist/mcp.d.ts
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @zeke-02/docx-editor-agents/mcp
|
|
3
|
+
*
|
|
4
|
+
* Model Context Protocol (MCP) server for the docx editor agent bridge.
|
|
5
|
+
*
|
|
6
|
+
* Two transports, same core:
|
|
7
|
+
* - `stdio`: classic MCP transport. Use `runStdioServer(bridge)` from a
|
|
8
|
+
* Node subprocess that Claude Desktop, Cursor, or any MCP-aware client
|
|
9
|
+
* will spawn. Newline-delimited JSON-RPC.
|
|
10
|
+
* - `direct`: call `new McpServer(bridge).handle(message)` if you have
|
|
11
|
+
* your own transport (WebSocket, `postMessage`, HTTP long-poll, etc.).
|
|
12
|
+
*
|
|
13
|
+
* The server is transport-agnostic and zero-dep. The stdio module reaches
|
|
14
|
+
* for `process.stdin` / `process.stdout` only when you call
|
|
15
|
+
* `runStdioServer` without explicit streams.
|
|
16
|
+
*
|
|
17
|
+
* @packageDocumentation
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
20
|
+
import { E as EditorBridge } from './server-uWvnaIh-.js';
|
|
21
|
+
import '@zeke-02/docx-editor-core/headless';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* MCP wire protocol (subset) — JSON-RPC 2.0 framing + the message types we
|
|
25
|
+
* actually implement. Zero dependencies. Pure functions; everything is unit-
|
|
26
|
+
* testable without a transport.
|
|
27
|
+
*
|
|
28
|
+
* This is NOT a full MCP SDK. We implement only what the server needs:
|
|
29
|
+
* - initialize / initialized
|
|
30
|
+
* - tools/list
|
|
31
|
+
* - tools/call
|
|
32
|
+
* - notifications/cancelled (no-op, accepted)
|
|
33
|
+
*
|
|
34
|
+
* Spec reference: https://spec.modelcontextprotocol.io
|
|
35
|
+
*/
|
|
36
|
+
type JsonRpcId = string | number | null;
|
|
37
|
+
interface JsonRpcRequest {
|
|
38
|
+
jsonrpc: '2.0';
|
|
39
|
+
id: JsonRpcId;
|
|
40
|
+
method: string;
|
|
41
|
+
params?: unknown;
|
|
42
|
+
}
|
|
43
|
+
interface JsonRpcNotification {
|
|
44
|
+
jsonrpc: '2.0';
|
|
45
|
+
method: string;
|
|
46
|
+
params?: unknown;
|
|
47
|
+
}
|
|
48
|
+
interface JsonRpcSuccess {
|
|
49
|
+
jsonrpc: '2.0';
|
|
50
|
+
id: JsonRpcId;
|
|
51
|
+
result: unknown;
|
|
52
|
+
}
|
|
53
|
+
interface JsonRpcError {
|
|
54
|
+
jsonrpc: '2.0';
|
|
55
|
+
id: JsonRpcId;
|
|
56
|
+
error: {
|
|
57
|
+
code: number;
|
|
58
|
+
message: string;
|
|
59
|
+
data?: unknown;
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
type JsonRpcResponse = JsonRpcSuccess | JsonRpcError;
|
|
63
|
+
type JsonRpcMessage = JsonRpcRequest | JsonRpcNotification | JsonRpcResponse;
|
|
64
|
+
/** Standard JSON-RPC error codes. We only ever emit JSON-RPC errors for
|
|
65
|
+
* protocol-level problems; tool execution failures use MCP's `isError`
|
|
66
|
+
* envelope inside a successful response, per spec. */
|
|
67
|
+
declare const ErrorCode: {
|
|
68
|
+
readonly ParseError: -32700;
|
|
69
|
+
readonly InvalidRequest: -32600;
|
|
70
|
+
readonly MethodNotFound: -32601;
|
|
71
|
+
readonly InvalidParams: -32602;
|
|
72
|
+
readonly InternalError: -32603;
|
|
73
|
+
};
|
|
74
|
+
interface McpInitializeResult {
|
|
75
|
+
protocolVersion: string;
|
|
76
|
+
capabilities: {
|
|
77
|
+
tools?: Record<string, unknown>;
|
|
78
|
+
};
|
|
79
|
+
serverInfo: {
|
|
80
|
+
name: string;
|
|
81
|
+
version: string;
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
interface McpToolDescriptor {
|
|
85
|
+
name: string;
|
|
86
|
+
description: string;
|
|
87
|
+
inputSchema: Record<string, unknown>;
|
|
88
|
+
}
|
|
89
|
+
interface McpToolsListResult {
|
|
90
|
+
tools: McpToolDescriptor[];
|
|
91
|
+
}
|
|
92
|
+
interface McpToolsCallParams {
|
|
93
|
+
name: string;
|
|
94
|
+
arguments?: Record<string, unknown>;
|
|
95
|
+
}
|
|
96
|
+
interface McpContent {
|
|
97
|
+
type: 'text';
|
|
98
|
+
text: string;
|
|
99
|
+
}
|
|
100
|
+
interface McpToolsCallResult {
|
|
101
|
+
content: McpContent[];
|
|
102
|
+
isError?: boolean;
|
|
103
|
+
}
|
|
104
|
+
declare function isJsonRpcRequest(m: unknown): m is JsonRpcRequest;
|
|
105
|
+
declare function isJsonRpcNotification(m: unknown): m is JsonRpcNotification;
|
|
106
|
+
declare function makeSuccess(id: JsonRpcId, result: unknown): JsonRpcSuccess;
|
|
107
|
+
declare function makeError(id: JsonRpcId, code: number, message: string, data?: unknown): JsonRpcError;
|
|
108
|
+
interface ParseResult {
|
|
109
|
+
/** Parsed messages. */
|
|
110
|
+
messages: JsonRpcMessage[];
|
|
111
|
+
/** Lines that failed to parse — caller should send a ParseError per line if it had a discernible id. */
|
|
112
|
+
parseErrors: string[];
|
|
113
|
+
/** Remaining buffer (no trailing newline yet). */
|
|
114
|
+
rest: string;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Parse newline-delimited JSON-RPC frames out of a buffer. Returns parsed
|
|
118
|
+
* messages plus any leftover bytes. Tolerates blank lines.
|
|
119
|
+
*/
|
|
120
|
+
declare function parseFrames(buffer: string): ParseResult;
|
|
121
|
+
/** Encode a JSON-RPC message as a single newline-terminated frame. */
|
|
122
|
+
declare function encodeFrame(message: JsonRpcMessage): string;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* MCP server core. Transport-agnostic — accepts a JsonRpcRequest, returns
|
|
126
|
+
* either a JsonRpcResponse or `null` (for notifications, which never reply).
|
|
127
|
+
*
|
|
128
|
+
* Wraps an EditorBridge: tools/list returns the bridge's tool schemas in MCP
|
|
129
|
+
* shape; tools/call dispatches via executeToolCall and converts the
|
|
130
|
+
* AgentToolResult into MCP CallToolResult content.
|
|
131
|
+
*/
|
|
132
|
+
|
|
133
|
+
interface McpServerOptions {
|
|
134
|
+
/** Server name reported in `initialize` response. Default: `@zeke-02/docx-editor-agents`. */
|
|
135
|
+
name?: string;
|
|
136
|
+
/** Server version. Default: `0.0.0` (override at build time). */
|
|
137
|
+
version?: string;
|
|
138
|
+
/** MCP protocol version we claim to speak. Default: `2025-06-18`. */
|
|
139
|
+
protocolVersion?: string;
|
|
140
|
+
}
|
|
141
|
+
declare class McpServer {
|
|
142
|
+
private readonly bridge;
|
|
143
|
+
private readonly opts;
|
|
144
|
+
constructor(bridge: EditorBridge, options?: McpServerOptions);
|
|
145
|
+
/**
|
|
146
|
+
* Handle one inbound message. Returns the response to send back, or `null`
|
|
147
|
+
* for notifications and other no-reply messages. Never throws.
|
|
148
|
+
*/
|
|
149
|
+
handle(message: JsonRpcMessage): JsonRpcResponse | null;
|
|
150
|
+
private handleInitialize;
|
|
151
|
+
private handleToolsList;
|
|
152
|
+
private handleToolsCall;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Stdio transport for the MCP server. Reads newline-delimited JSON-RPC from
|
|
157
|
+
* an input stream, dispatches via McpServer, writes responses to an output
|
|
158
|
+
* stream. Pure stream handling — no Node-only assumptions beyond "Readable
|
|
159
|
+
* has .on('data') and Writable has .write".
|
|
160
|
+
*
|
|
161
|
+
* For real Node usage:
|
|
162
|
+
* import { runStdioServer } from '@zeke-02/docx-editor-agents/mcp';
|
|
163
|
+
* runStdioServer(bridge);
|
|
164
|
+
*
|
|
165
|
+
* For tests, pass any EventEmitter-shaped Readable + a function-shaped
|
|
166
|
+
* Writable; see __tests__/mcp/stdio.test.ts.
|
|
167
|
+
*/
|
|
168
|
+
|
|
169
|
+
/** Minimal duck-typed input stream — anything with `on('data', cb)` works. */
|
|
170
|
+
interface InputStream {
|
|
171
|
+
on(event: 'data', listener: (chunk: Buffer | string) => void): unknown;
|
|
172
|
+
on(event: 'end', listener: () => void): unknown;
|
|
173
|
+
on(event: 'error', listener: (err: Error) => void): unknown;
|
|
174
|
+
}
|
|
175
|
+
/** Minimal duck-typed output stream — anything with a `write(string) => bool` works. */
|
|
176
|
+
interface OutputStream {
|
|
177
|
+
write(chunk: string): boolean | void;
|
|
178
|
+
}
|
|
179
|
+
interface StdioServerOptions extends McpServerOptions {
|
|
180
|
+
input?: InputStream;
|
|
181
|
+
output?: OutputStream;
|
|
182
|
+
/** Called with diagnostic strings (e.g. parse errors). Default: stderr. */
|
|
183
|
+
log?: (msg: string) => void;
|
|
184
|
+
}
|
|
185
|
+
interface StdioServerHandle {
|
|
186
|
+
/** Underlying server (for tests / introspection). */
|
|
187
|
+
server: McpServer;
|
|
188
|
+
/** Manually feed a raw chunk (used by tests; the live transport calls this internally). */
|
|
189
|
+
feed: (chunk: string | Buffer) => void;
|
|
190
|
+
/** Stop accepting input and reject further writes. Idempotent. */
|
|
191
|
+
close: () => void;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Wire an EditorBridge to a JSON-RPC stdio loop. Returns immediately; reading
|
|
195
|
+
* happens via the stream listeners. Designed to be testable: pass in fake
|
|
196
|
+
* streams, call `feed(...)` directly, then assert on what was written.
|
|
197
|
+
*/
|
|
198
|
+
declare function runStdioServer(bridge: EditorBridge, options?: StdioServerOptions): StdioServerHandle;
|
|
199
|
+
|
|
200
|
+
export { ErrorCode, type JsonRpcError, type JsonRpcId, type JsonRpcMessage, type JsonRpcNotification, type JsonRpcRequest, type JsonRpcResponse, type JsonRpcSuccess, type McpContent, type McpInitializeResult, McpServer, type McpServerOptions, type McpToolDescriptor, type McpToolsCallParams, type McpToolsCallResult, type McpToolsListResult, type StdioServerHandle, type StdioServerOptions, encodeFrame, isJsonRpcNotification, isJsonRpcRequest, makeError, makeSuccess, parseFrames, runStdioServer };
|
package/dist/mcp.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
'use strict';var chunkRI5S75JY_js=require('./chunk-RI5S75JY.js'),string_decoder=require('string_decoder');var i={ParseError:-32700,InvalidRequest:-32600,MethodNotFound:-32601,InvalidParams:-32602,InternalError:-32603};function v(t){return typeof t=="object"&&t!==null&&t.jsonrpc==="2.0"&&typeof t.method=="string"&&"id"in t}function I(t){return typeof t=="object"&&t!==null&&t.jsonrpc==="2.0"&&typeof t.method=="string"&&!("id"in t)}function u(t,r){return {jsonrpc:"2.0",id:t,result:r}}function p(t,r,e,o){return {jsonrpc:"2.0",id:t,error:o===void 0?{code:r,message:e}:{code:r,message:e,data:o}}}function y(t){let r=[],e=[],o=t.split(`
|
|
2
|
+
`),n=o.pop()??"";for(let c of o){let a=c.trim();if(a)try{r.push(JSON.parse(a));}catch{e.push(a);}}return {messages:r,parseErrors:e,rest:n}}function d(t){return JSON.stringify(t)+`
|
|
3
|
+
`}var T="2025-06-18",f=class{constructor(r,e={}){this.bridge=r,this.opts={name:e.name??"@zeke-02/docx-editor-agents",version:e.version??"0.0.0",protocolVersion:e.protocolVersion??T};}handle(r){if(!v(r))return null;let e=r;try{switch(e.method){case "initialize":return u(e.id,this.handleInitialize());case "tools/list":return u(e.id,this.handleToolsList());case "tools/call":return this.handleToolsCall(e);case "ping":return u(e.id,{});default:return p(e.id,i.MethodNotFound,`Method not found: ${e.method}`)}}catch(o){return p(e.id,i.InternalError,o instanceof Error?o.message:String(o))}}handleInitialize(){return {protocolVersion:this.opts.protocolVersion,capabilities:{tools:{}},serverInfo:{name:this.opts.name,version:this.opts.version}}}handleToolsList(){return {tools:chunkRI5S75JY_js.a.map(r=>({name:r.name,description:r.description,inputSchema:r.inputSchema}))}}handleToolsCall(r){let e=r.params;if(!e||typeof e.name!="string")return p(r.id,i.InvalidParams,'tools/call requires a "name" string');let o=e.arguments??{},n=chunkRI5S75JY_js.b(e.name,o,this.bridge),c=n.success?{content:[{type:"text",text:typeof n.data=="string"?n.data:JSON.stringify(n.data,null,2)}]}:{isError:true,content:[{type:"text",text:n.error??"Unknown tool error"}]};return u(r.id,c)}};var x=1024*1024;function b(t,r={}){let e=new f(t,r),o=r.input??(typeof process<"u"&&process.stdin?process.stdin:null),n=r.output??(typeof process<"u"&&process.stdout?process.stdout:null),c=r.log??(s=>{typeof process<"u"&&process.stderr&&process.stderr.write(s+`
|
|
4
|
+
`);});if(!o||!n)throw new Error("runStdioServer: no input/output stream available. Pass options.input and options.output, or run inside a Node process with stdin/stdout.");let a=n,h=new string_decoder.StringDecoder("utf8"),l="",R=false;function w(s){let g=e.handle(s);g!==null&&a.write(d(g));}function J(s){if(R)return;if(l+=typeof s=="string"?s:h.write(s),l.length>x){l="",c(`MCP buffer overflow (>${x} bytes without newline) \u2014 dropped`),a.write(d(p(null,i.ParseError,"Frame too large")));return}let{messages:g,parseErrors:E,rest:k}=y(l);l=k;for(let m of g)w(m);for(let m of E)c(`MCP parse error: ${m}`),a.write(d(p(null,i.ParseError,"Parse error",m)));}return o.on("data",J),o.on("end",()=>{R=true;}),o.on("error",s=>{c(`MCP input error: ${s.message}`),R=true;}),{server:e,feed:J,close(){R=true;}}}exports.ErrorCode=i;exports.McpServer=f;exports.encodeFrame=d;exports.isJsonRpcNotification=I;exports.isJsonRpcRequest=v;exports.makeError=p;exports.makeSuccess=u;exports.parseFrames=y;exports.runStdioServer=b;
|
package/dist/mcp.mjs
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import {a,b as b$1}from'./chunk-24MVJKCP.mjs';import {StringDecoder}from'string_decoder';var i={ParseError:-32700,InvalidRequest:-32600,MethodNotFound:-32601,InvalidParams:-32602,InternalError:-32603};function v(t){return typeof t=="object"&&t!==null&&t.jsonrpc==="2.0"&&typeof t.method=="string"&&"id"in t}function I(t){return typeof t=="object"&&t!==null&&t.jsonrpc==="2.0"&&typeof t.method=="string"&&!("id"in t)}function u(t,r){return {jsonrpc:"2.0",id:t,result:r}}function p(t,r,e,o){return {jsonrpc:"2.0",id:t,error:o===void 0?{code:r,message:e}:{code:r,message:e,data:o}}}function y(t){let r=[],e=[],o=t.split(`
|
|
2
|
+
`),n=o.pop()??"";for(let c of o){let a=c.trim();if(a)try{r.push(JSON.parse(a));}catch{e.push(a);}}return {messages:r,parseErrors:e,rest:n}}function d(t){return JSON.stringify(t)+`
|
|
3
|
+
`}var T="2025-06-18",f=class{constructor(r,e={}){this.bridge=r,this.opts={name:e.name??"@zeke-02/docx-editor-agents",version:e.version??"0.0.0",protocolVersion:e.protocolVersion??T};}handle(r){if(!v(r))return null;let e=r;try{switch(e.method){case "initialize":return u(e.id,this.handleInitialize());case "tools/list":return u(e.id,this.handleToolsList());case "tools/call":return this.handleToolsCall(e);case "ping":return u(e.id,{});default:return p(e.id,i.MethodNotFound,`Method not found: ${e.method}`)}}catch(o){return p(e.id,i.InternalError,o instanceof Error?o.message:String(o))}}handleInitialize(){return {protocolVersion:this.opts.protocolVersion,capabilities:{tools:{}},serverInfo:{name:this.opts.name,version:this.opts.version}}}handleToolsList(){return {tools:a.map(r=>({name:r.name,description:r.description,inputSchema:r.inputSchema}))}}handleToolsCall(r){let e=r.params;if(!e||typeof e.name!="string")return p(r.id,i.InvalidParams,'tools/call requires a "name" string');let o=e.arguments??{},n=b$1(e.name,o,this.bridge),c=n.success?{content:[{type:"text",text:typeof n.data=="string"?n.data:JSON.stringify(n.data,null,2)}]}:{isError:true,content:[{type:"text",text:n.error??"Unknown tool error"}]};return u(r.id,c)}};var x=1024*1024;function b(t,r={}){let e=new f(t,r),o=r.input??(typeof process<"u"&&process.stdin?process.stdin:null),n=r.output??(typeof process<"u"&&process.stdout?process.stdout:null),c=r.log??(s=>{typeof process<"u"&&process.stderr&&process.stderr.write(s+`
|
|
4
|
+
`);});if(!o||!n)throw new Error("runStdioServer: no input/output stream available. Pass options.input and options.output, or run inside a Node process with stdin/stdout.");let a=n,h=new StringDecoder("utf8"),l="",R=false;function w(s){let g=e.handle(s);g!==null&&a.write(d(g));}function J(s){if(R)return;if(l+=typeof s=="string"?s:h.write(s),l.length>x){l="",c(`MCP buffer overflow (>${x} bytes without newline) \u2014 dropped`),a.write(d(p(null,i.ParseError,"Frame too large")));return}let{messages:g,parseErrors:E,rest:k}=y(l);l=k;for(let m of g)w(m);for(let m of E)c(`MCP parse error: ${m}`),a.write(d(p(null,i.ParseError,"Parse error",m)));}return o.on("data",J),o.on("end",()=>{R=true;}),o.on("error",s=>{c(`MCP input error: ${s.message}`),R=true;}),{server:e,feed:J,close(){R=true;}}}export{i as ErrorCode,f as McpServer,d as encodeFrame,I as isJsonRpcNotification,v as isJsonRpcRequest,p as makeError,u as makeSuccess,y as parseFrames,b as runStdioServer};
|