@czap/mcp-server 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 +21 -0
- package/README.md +13 -0
- package/dist/dispatch.d.ts +46 -0
- package/dist/dispatch.d.ts.map +1 -0
- package/dist/dispatch.js +141 -0
- package/dist/dispatch.js.map +1 -0
- package/dist/http-server.d.ts +17 -0
- package/dist/http-server.d.ts.map +1 -0
- package/dist/http-server.js +65 -0
- package/dist/http-server.js.map +1 -0
- package/dist/http.d.ts +33 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +66 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/jsonrpc.d.ts +129 -0
- package/dist/jsonrpc.d.ts.map +1 -0
- package/dist/jsonrpc.js +169 -0
- package/dist/jsonrpc.js.map +1 -0
- package/dist/start.d.ts +13 -0
- package/dist/start.d.ts.map +1 -0
- package/dist/start.js +17 -0
- package/dist/start.js.map +1 -0
- package/dist/stdio-server.d.ts +12 -0
- package/dist/stdio-server.d.ts.map +1 -0
- package/dist/stdio-server.js +18 -0
- package/dist/stdio-server.js.map +1 -0
- package/dist/stdio.d.ts +29 -0
- package/dist/stdio.d.ts.map +1 -0
- package/dist/stdio.js +49 -0
- package/dist/stdio.js.map +1 -0
- package/package.json +54 -0
- package/src/czap-cli-shim.d.ts +3 -0
- package/src/dispatch.ts +177 -0
- package/src/http-server.ts +69 -0
- package/src/http.ts +78 -0
- package/src/index.ts +31 -0
- package/src/jsonrpc.ts +243 -0
- package/src/start.ts +23 -0
- package/src/stdio-server.ts +19 -0
- package/src/stdio.ts +54 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-2026 Eassa Ayoub <eassa@heyoub.dev>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# `@czap/mcp-server`
|
|
2
|
+
|
|
3
|
+
Model Context Protocol (MCP) server that forwards tool calls to the `czap` CLI (LiteShip tooling). Vocabulary: [../../docs/GLOSSARY.md](../../docs/GLOSSARY.md).
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @czap/mcp-server @czap/cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`@czap/cli` is a required peer dependency. Install both packages at the same semver.
|
|
12
|
+
|
|
13
|
+
See [docs/RELEASING.md](https://github.com/heyoub/LiteShip/blob/main/docs/RELEASING.md).
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool dispatch — maps tools/call params to czap CLI command
|
|
3
|
+
* executions. Captures CLI stdout and returns it as MCP text content.
|
|
4
|
+
*
|
|
5
|
+
* Entry point `dispatch` accepts a typed JSON-RPC `Request | Notification`
|
|
6
|
+
* (post-`JsonRpcServer.parse` classification) and produces a
|
|
7
|
+
* `JsonRpcResponse | null`. `null` is returned for notifications: per
|
|
8
|
+
* JSON-RPC 2.0 §4.1 the server MUST NOT send a response for them.
|
|
9
|
+
*
|
|
10
|
+
* `dispatchToolCall` remains exported for tests that exercise the CLI
|
|
11
|
+
* dispatch path directly without going through the JSON-RPC envelope.
|
|
12
|
+
*
|
|
13
|
+
* @module
|
|
14
|
+
*/
|
|
15
|
+
import { type JsonRpcNotification, type JsonRpcRequest, type JsonRpcResponse } from './jsonrpc.js';
|
|
16
|
+
/** Shape of an MCP tools/call parameter object. */
|
|
17
|
+
export interface McpToolCall {
|
|
18
|
+
readonly name: string;
|
|
19
|
+
readonly arguments: Record<string, unknown>;
|
|
20
|
+
}
|
|
21
|
+
/** MCP tools/call result envelope. */
|
|
22
|
+
export interface McpToolResult {
|
|
23
|
+
readonly content: ReadonlyArray<{
|
|
24
|
+
type: 'text';
|
|
25
|
+
text: string;
|
|
26
|
+
}>;
|
|
27
|
+
readonly isError: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Route a parsed JSON-RPC message to its method handler.
|
|
31
|
+
*
|
|
32
|
+
* Returns `null` for notifications (§4.1: notifications MUST NOT receive
|
|
33
|
+
* a response). For requests, returns either a success or an error
|
|
34
|
+
* response. Internal handler exceptions are caught and surfaced as
|
|
35
|
+
* `-32603 Internal error` per §5.1.
|
|
36
|
+
*/
|
|
37
|
+
export declare function dispatch(msg: JsonRpcRequest | JsonRpcNotification): Promise<JsonRpcResponse | null>;
|
|
38
|
+
/** Translate a tools/call into argv, run the CLI, capture stdout. */
|
|
39
|
+
export declare function dispatchToolCall(call: McpToolCall): Promise<McpToolResult>;
|
|
40
|
+
/** Static list of MCP tools produced by czap's CLI. */
|
|
41
|
+
export declare function listTools(): ReadonlyArray<{
|
|
42
|
+
name: string;
|
|
43
|
+
description: string;
|
|
44
|
+
inputSchema: object;
|
|
45
|
+
}>;
|
|
46
|
+
//# sourceMappingURL=dispatch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../src/dispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,eAAe,EAMrB,MAAM,cAAc,CAAC;AA4BtB,mDAAmD;AACnD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC7C;AAED,sCAAsC;AACtC,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,wBAAsB,QAAQ,CAC5B,GAAG,EAAE,cAAc,GAAG,mBAAmB,GACxC,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAqBjC;AAiCD,qEAAqE;AACrE,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAkBhF;AAeD,uDAAuD;AACvD,wBAAgB,SAAS,IAAI,aAAa,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAarG"}
|
package/dist/dispatch.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool dispatch — maps tools/call params to czap CLI command
|
|
3
|
+
* executions. Captures CLI stdout and returns it as MCP text content.
|
|
4
|
+
*
|
|
5
|
+
* Entry point `dispatch` accepts a typed JSON-RPC `Request | Notification`
|
|
6
|
+
* (post-`JsonRpcServer.parse` classification) and produces a
|
|
7
|
+
* `JsonRpcResponse | null`. `null` is returned for notifications: per
|
|
8
|
+
* JSON-RPC 2.0 §4.1 the server MUST NOT send a response for them.
|
|
9
|
+
*
|
|
10
|
+
* `dispatchToolCall` remains exported for tests that exercise the CLI
|
|
11
|
+
* dispatch path directly without going through the JSON-RPC envelope.
|
|
12
|
+
*
|
|
13
|
+
* @module
|
|
14
|
+
*/
|
|
15
|
+
import { errorResponse, successResponse, MethodNotFound, InvalidParams, InternalError, } from './jsonrpc.js';
|
|
16
|
+
/**
|
|
17
|
+
* Sentinel for invalid-params throws inside method invocations. Caught
|
|
18
|
+
* by `dispatch` and mapped to JSON-RPC 2.0 §5.1 code -32602 (the spec
|
|
19
|
+
* code for malformed parameters). Generic `Error`s remain -32603
|
|
20
|
+
* (Internal error).
|
|
21
|
+
*/
|
|
22
|
+
class InvalidParamsError extends Error {
|
|
23
|
+
detail;
|
|
24
|
+
constructor(message, detail) {
|
|
25
|
+
super(message);
|
|
26
|
+
this.detail = detail;
|
|
27
|
+
this.name = 'InvalidParamsError';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
let cachedRun;
|
|
31
|
+
/** Lazy-load `@czap/cli` so `@czap/mcp-server` does not declare a package dependency cycle. */
|
|
32
|
+
async function getRun() {
|
|
33
|
+
if (!cachedRun) {
|
|
34
|
+
const mod = await import('@czap/cli');
|
|
35
|
+
cachedRun = mod.run;
|
|
36
|
+
}
|
|
37
|
+
return cachedRun;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Route a parsed JSON-RPC message to its method handler.
|
|
41
|
+
*
|
|
42
|
+
* Returns `null` for notifications (§4.1: notifications MUST NOT receive
|
|
43
|
+
* a response). For requests, returns either a success or an error
|
|
44
|
+
* response. Internal handler exceptions are caught and surfaced as
|
|
45
|
+
* `-32603 Internal error` per §5.1.
|
|
46
|
+
*/
|
|
47
|
+
export async function dispatch(msg) {
|
|
48
|
+
const isNotification = !('id' in msg);
|
|
49
|
+
const id = isNotification ? null : msg.id;
|
|
50
|
+
try {
|
|
51
|
+
const result = await invoke(msg);
|
|
52
|
+
if (isNotification)
|
|
53
|
+
return null;
|
|
54
|
+
if (result.kind === 'method-not-found') {
|
|
55
|
+
return errorResponse(id, MethodNotFound, 'method not found', { method: msg.method });
|
|
56
|
+
}
|
|
57
|
+
return successResponse(id, result.value);
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
if (isNotification) {
|
|
61
|
+
const notificationAck = null;
|
|
62
|
+
return notificationAck;
|
|
63
|
+
}
|
|
64
|
+
if (err instanceof InvalidParamsError) {
|
|
65
|
+
return errorResponse(id, InvalidParams, err.message, err.detail);
|
|
66
|
+
}
|
|
67
|
+
return errorResponse(id, InternalError, 'Internal error', { detail: String(err) });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function ok(value) {
|
|
71
|
+
return { kind: 'ok', value };
|
|
72
|
+
}
|
|
73
|
+
async function invoke(msg) {
|
|
74
|
+
switch (msg.method) {
|
|
75
|
+
case 'tools/list':
|
|
76
|
+
return ok({ tools: listTools() });
|
|
77
|
+
case 'tools/call': {
|
|
78
|
+
const params = msg.params;
|
|
79
|
+
if (!params || typeof params.name !== 'string') {
|
|
80
|
+
// Per §5.1, malformed params → -32602. InvalidParamsError sentinel
|
|
81
|
+
// is mapped to InvalidParams in dispatch's catch block.
|
|
82
|
+
throw new InvalidParamsError('tools/call requires { name: string, arguments: object }', { received: params });
|
|
83
|
+
}
|
|
84
|
+
const result = await dispatchToolCall(params);
|
|
85
|
+
return ok(result);
|
|
86
|
+
}
|
|
87
|
+
default:
|
|
88
|
+
return { kind: 'method-not-found' };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/** Translate a tools/call into argv, run the CLI, capture stdout. */
|
|
92
|
+
export async function dispatchToolCall(call) {
|
|
93
|
+
const args = buildArgv(call);
|
|
94
|
+
const originalWrite = process.stdout.write.bind(process.stdout);
|
|
95
|
+
let captured = '';
|
|
96
|
+
process.stdout.write = ((chunk) => {
|
|
97
|
+
captured += typeof chunk === 'string' ? chunk : Buffer.from(chunk).toString();
|
|
98
|
+
return true;
|
|
99
|
+
});
|
|
100
|
+
try {
|
|
101
|
+
const run = await getRun();
|
|
102
|
+
const code = await run(args);
|
|
103
|
+
return {
|
|
104
|
+
content: [{ type: 'text', text: captured.trim() }],
|
|
105
|
+
isError: code !== 0,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
finally {
|
|
109
|
+
process.stdout.write = originalWrite;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function buildArgv(call) {
|
|
113
|
+
const segments = call.name.split('.');
|
|
114
|
+
const args = [];
|
|
115
|
+
for (const [k, v] of Object.entries(call.arguments)) {
|
|
116
|
+
if (typeof v === 'boolean') {
|
|
117
|
+
if (v)
|
|
118
|
+
args.push(`--${k}`);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
args.push(`--${k}=${String(v)}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return [...segments, ...args];
|
|
125
|
+
}
|
|
126
|
+
/** Static list of MCP tools produced by czap's CLI. */
|
|
127
|
+
export function listTools() {
|
|
128
|
+
return [
|
|
129
|
+
{ name: 'describe', description: 'Dump capsule catalog schema', inputSchema: { type: 'object', properties: { format: { type: 'string', enum: ['json', 'mcp'] } } } },
|
|
130
|
+
{ name: 'scene.compile', description: 'Compile a scene capsule', inputSchema: { type: 'object', required: ['scene'], properties: { scene: { type: 'string' } } } },
|
|
131
|
+
{ name: 'scene.render', description: 'Render scene to mp4', inputSchema: { type: 'object', required: ['scene', 'output'], properties: { scene: { type: 'string' }, output: { type: 'string' } } } },
|
|
132
|
+
{ name: 'scene.verify', description: 'Run scene generated tests', inputSchema: { type: 'object', required: ['scene'], properties: { scene: { type: 'string' } } } },
|
|
133
|
+
{ name: 'asset.analyze', description: 'Run cachedProjection on asset', inputSchema: { type: 'object', required: ['asset', 'projection'], properties: { asset: { type: 'string' }, projection: { type: 'string', enum: ['beat', 'onset', 'waveform'] } } } },
|
|
134
|
+
{ name: 'asset.verify', description: 'Verify asset capsule', inputSchema: { type: 'object', required: ['asset'], properties: { asset: { type: 'string' } } } },
|
|
135
|
+
{ name: 'capsule.inspect', description: 'Inspect a capsule manifest entry', inputSchema: { type: 'object', required: ['id'], properties: { id: { type: 'string' } } } },
|
|
136
|
+
{ name: 'capsule.verify', description: 'Verify capsule generated tests', inputSchema: { type: 'object', required: ['id'], properties: { id: { type: 'string' } } } },
|
|
137
|
+
{ name: 'capsule.list', description: 'List capsules filtered by kind', inputSchema: { type: 'object', properties: { kind: { type: 'string' } } } },
|
|
138
|
+
{ name: 'gauntlet', description: 'Run the full gauntlet', inputSchema: { type: 'object', properties: { 'dry-run': { type: 'boolean' } } } },
|
|
139
|
+
];
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=dispatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../src/dispatch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP HTTP server bootstrap. The pure handler logic lives in `http.ts`
|
|
3
|
+
* (exported as `handleRequest` / `respond`). This module owns the
|
|
4
|
+
* Node http server lifecycle (createServer + listen + SIGINT-await) and
|
|
5
|
+
* is excluded from coverage because the bootstrap path can only be
|
|
6
|
+
* exercised by the integration spawn at tests/integration/mcp/http.test.ts —
|
|
7
|
+
* Windows can't deliver SIGINT to spawned subprocesses cleanly, so a
|
|
8
|
+
* unit test would hang.
|
|
9
|
+
*
|
|
10
|
+
* Splitting this out lets the rest of the transport stay in coverage with
|
|
11
|
+
* no `c8 ignore` annotations.
|
|
12
|
+
*
|
|
13
|
+
* @module
|
|
14
|
+
*/
|
|
15
|
+
/** Run the MCP HTTP server bound to `bind` (e.g. ":3838" or "127.0.0.1:8080"). */
|
|
16
|
+
export declare function runHttp(bind: string): Promise<void>;
|
|
17
|
+
//# sourceMappingURL=http-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-server.d.ts","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,kFAAkF;AAClF,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAyCzD"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP HTTP server bootstrap. The pure handler logic lives in `http.ts`
|
|
3
|
+
* (exported as `handleRequest` / `respond`). This module owns the
|
|
4
|
+
* Node http server lifecycle (createServer + listen + SIGINT-await) and
|
|
5
|
+
* is excluded from coverage because the bootstrap path can only be
|
|
6
|
+
* exercised by the integration spawn at tests/integration/mcp/http.test.ts —
|
|
7
|
+
* Windows can't deliver SIGINT to spawned subprocesses cleanly, so a
|
|
8
|
+
* unit test would hang.
|
|
9
|
+
*
|
|
10
|
+
* Splitting this out lets the rest of the transport stay in coverage with
|
|
11
|
+
* no `c8 ignore` annotations.
|
|
12
|
+
*
|
|
13
|
+
* @module
|
|
14
|
+
*/
|
|
15
|
+
import { createServer } from 'node:http';
|
|
16
|
+
import { handleRequest } from './http.js';
|
|
17
|
+
/** Run the MCP HTTP server bound to `bind` (e.g. ":3838" or "127.0.0.1:8080"). */
|
|
18
|
+
export async function runHttp(bind) {
|
|
19
|
+
const m = bind.match(/^(?:([^:]+))?:(\d+)$/);
|
|
20
|
+
const host = m?.[1] ?? '127.0.0.1';
|
|
21
|
+
const port = Number(m?.[2] ?? bind);
|
|
22
|
+
const server = createServer(async (req, res) => {
|
|
23
|
+
if (req.method !== 'POST') {
|
|
24
|
+
res.statusCode = 405;
|
|
25
|
+
res.end();
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
let body = '';
|
|
29
|
+
for await (const chunk of req)
|
|
30
|
+
body += String(chunk);
|
|
31
|
+
const response = await handleRequest(body);
|
|
32
|
+
res.setHeader('content-type', 'application/json');
|
|
33
|
+
if (response === null) {
|
|
34
|
+
// §4.1: notifications produce no body. Use 204 No Content.
|
|
35
|
+
res.statusCode = 204;
|
|
36
|
+
res.end();
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
res.end(JSON.stringify(response));
|
|
40
|
+
});
|
|
41
|
+
await new Promise((resolve) => server.listen(port, host, () => resolve()));
|
|
42
|
+
// Resolve the actual bound port — when callers pass :0 they want the
|
|
43
|
+
// ephemeral port the OS chose, not the literal 0 they requested.
|
|
44
|
+
const addr = server.address();
|
|
45
|
+
const boundPort = typeof addr === 'object' && addr ? addr.port : port;
|
|
46
|
+
process.stdout.write(JSON.stringify({
|
|
47
|
+
status: 'ok', command: 'mcp',
|
|
48
|
+
transport: 'http',
|
|
49
|
+
url: `http://${host}:${boundPort}/`,
|
|
50
|
+
}) + '\n');
|
|
51
|
+
await new Promise((resolve) => {
|
|
52
|
+
process.on('SIGINT', () => {
|
|
53
|
+
server.close();
|
|
54
|
+
resolve();
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
if (import.meta.url === `file://${process.argv[1]}` || process.argv[1]?.endsWith('http-server.ts') || process.argv[1]?.endsWith('http.ts')) {
|
|
59
|
+
const bind = process.argv[2] ?? ':0';
|
|
60
|
+
runHttp(bind).catch((err) => {
|
|
61
|
+
process.stderr.write(JSON.stringify({ error: String(err) }) + '\n');
|
|
62
|
+
process.exit(1);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=http-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-server.js","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"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"}
|
package/dist/http.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP HTTP transport — POST /, body is a JSON-RPC 2.0 request.
|
|
3
|
+
* Pure JSON-RPC handler logic lives here. The Node `createServer` +
|
|
4
|
+
* `listen` + `SIGINT`-await bootstrap lives in `./http-server.ts`,
|
|
5
|
+
* excluded from coverage because Windows can't deliver SIGINT to
|
|
6
|
+
* spawned subprocesses cleanly.
|
|
7
|
+
*
|
|
8
|
+
* Routes incoming bodies through `JsonRpcServer.parse` for the same
|
|
9
|
+
* conformance properties as the stdio transport: parse errors → -32700,
|
|
10
|
+
* notifications produce no body, batches handled per §6.
|
|
11
|
+
*
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
import { type JsonRpcResponse, type ParseOutcome } from './jsonrpc.js';
|
|
15
|
+
/**
|
|
16
|
+
* Resolve a parse outcome to its wire response, or `null` if the spec
|
|
17
|
+
* requires no response (notification, or pure-notification batch).
|
|
18
|
+
*
|
|
19
|
+
* Exported so unit tests can exercise every branch without spinning up a
|
|
20
|
+
* real HTTP server (Windows can't deliver SIGINT to subprocess for the
|
|
21
|
+
* full integration path).
|
|
22
|
+
*/
|
|
23
|
+
export declare function respond(outcome: ParseOutcome): Promise<JsonRpcResponse | readonly JsonRpcResponse[] | null>;
|
|
24
|
+
/**
|
|
25
|
+
* Pure wire handler — accepts a JSON-RPC body string, returns the response
|
|
26
|
+
* envelope (or null for notification-only batches). Drives the HTTP server's
|
|
27
|
+
* request path; extracted so unit tests cover every parse-outcome branch
|
|
28
|
+
* without spawning a server process.
|
|
29
|
+
*/
|
|
30
|
+
export declare function handleRequest(body: string): Promise<JsonRpcResponse | readonly JsonRpcResponse[] | null>;
|
|
31
|
+
import './http-server.js';
|
|
32
|
+
export { runHttp } from './http-server.js';
|
|
33
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,YAAY,EAIlB,MAAM,cAAc,CAAC;AAEtB;;;;;;;GAOG;AACH,wBAAsB,OAAO,CAC3B,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,eAAe,GAAG,SAAS,eAAe,EAAE,GAAG,IAAI,CAAC,CAsB9D;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,eAAe,GAAG,SAAS,eAAe,EAAE,GAAG,IAAI,CAAC,CAG9D;AAMD,OAAO,kBAAkB,CAAC;AAE1B,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/http.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP HTTP transport — POST /, body is a JSON-RPC 2.0 request.
|
|
3
|
+
* Pure JSON-RPC handler logic lives here. The Node `createServer` +
|
|
4
|
+
* `listen` + `SIGINT`-await bootstrap lives in `./http-server.ts`,
|
|
5
|
+
* excluded from coverage because Windows can't deliver SIGINT to
|
|
6
|
+
* spawned subprocesses cleanly.
|
|
7
|
+
*
|
|
8
|
+
* Routes incoming bodies through `JsonRpcServer.parse` for the same
|
|
9
|
+
* conformance properties as the stdio transport: parse errors → -32700,
|
|
10
|
+
* notifications produce no body, batches handled per §6.
|
|
11
|
+
*
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
import { dispatch } from './dispatch.js';
|
|
15
|
+
import { JsonRpcServer, errorResponse, ParseError, InvalidRequest, } from './jsonrpc.js';
|
|
16
|
+
/**
|
|
17
|
+
* Resolve a parse outcome to its wire response, or `null` if the spec
|
|
18
|
+
* requires no response (notification, or pure-notification batch).
|
|
19
|
+
*
|
|
20
|
+
* Exported so unit tests can exercise every branch without spinning up a
|
|
21
|
+
* real HTTP server (Windows can't deliver SIGINT to subprocess for the
|
|
22
|
+
* full integration path).
|
|
23
|
+
*/
|
|
24
|
+
export async function respond(outcome) {
|
|
25
|
+
switch (outcome.kind) {
|
|
26
|
+
case 'parse-error':
|
|
27
|
+
return errorResponse(null, ParseError, 'Parse error');
|
|
28
|
+
case 'invalid-request':
|
|
29
|
+
return errorResponse(outcome.id, InvalidRequest, 'Invalid Request');
|
|
30
|
+
case 'notification':
|
|
31
|
+
await dispatch(outcome.message);
|
|
32
|
+
return null;
|
|
33
|
+
case 'request':
|
|
34
|
+
return dispatch(outcome.message);
|
|
35
|
+
case 'batch': {
|
|
36
|
+
const responses = [];
|
|
37
|
+
for (const sub of outcome.outcomes) {
|
|
38
|
+
const r = await respond(sub);
|
|
39
|
+
if (r === null)
|
|
40
|
+
continue;
|
|
41
|
+
if (Array.isArray(r))
|
|
42
|
+
responses.push(...r);
|
|
43
|
+
else
|
|
44
|
+
responses.push(r);
|
|
45
|
+
}
|
|
46
|
+
return responses.length > 0 ? responses : null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Pure wire handler — accepts a JSON-RPC body string, returns the response
|
|
52
|
+
* envelope (or null for notification-only batches). Drives the HTTP server's
|
|
53
|
+
* request path; extracted so unit tests cover every parse-outcome branch
|
|
54
|
+
* without spawning a server process.
|
|
55
|
+
*/
|
|
56
|
+
export async function handleRequest(body) {
|
|
57
|
+
const outcome = JsonRpcServer.parse(body);
|
|
58
|
+
return respond(outcome);
|
|
59
|
+
}
|
|
60
|
+
// Re-export the bootstrap so callers (start.ts) can keep using `import { runHttp } from './http.js'`.
|
|
61
|
+
// The bootstrap module also installs a top-level direct-invoke guard for
|
|
62
|
+
// the integration spawn entrypoint (`tsx packages/mcp-server/src/http.ts ...`).
|
|
63
|
+
// We import that module for its side effect so the spawn keeps working.
|
|
64
|
+
import './http-server.js';
|
|
65
|
+
export { runHttp } from './http-server.js';
|
|
66
|
+
//# sourceMappingURL=http.js.map
|
package/dist/http.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EACL,aAAa,EAGb,aAAa,EACb,UAAU,EACV,cAAc,GACf,MAAM,cAAc,CAAC;AAEtB;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,OAAqB;IAErB,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;QACrB,KAAK,aAAa;YAChB,OAAO,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;QACxD,KAAK,iBAAiB;YACpB,OAAO,aAAa,CAAC,OAAO,CAAC,EAAE,EAAE,cAAc,EAAE,iBAAiB,CAAC,CAAC;QACtE,KAAK,cAAc;YACjB,MAAM,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAChC,OAAO,IAAI,CAAC;QACd,KAAK,SAAS;YACZ,OAAO,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACnC,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,MAAM,SAAS,GAAsB,EAAE,CAAC;YACxC,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;gBACnC,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;gBAC7B,IAAI,CAAC,KAAK,IAAI;oBAAE,SAAS;gBACzB,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;oBAAE,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;;oBACtC,SAAS,CAAC,IAAI,CAAC,CAAoB,CAAC,CAAC;YAC5C,CAAC;YACD,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;QACjD,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAY;IAEZ,MAAM,OAAO,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1C,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC;AAC1B,CAAC;AAED,sGAAsG;AACtG,yEAAyE;AACzE,gFAAgF;AAChF,wEAAwE;AACxE,OAAO,kBAAkB,CAAC;AAE1B,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** `@czap/mcp-server` — MCP bridge for **LiteShip**; forwards tools to the `czap` CLI + capsule factory. */
|
|
2
|
+
export { start } from './start.js';
|
|
3
|
+
export type { StartOpts } from './start.js';
|
|
4
|
+
export { listTools, dispatchToolCall, dispatch } from './dispatch.js';
|
|
5
|
+
export type { McpToolCall, McpToolResult } from './dispatch.js';
|
|
6
|
+
export { runStdio } from './stdio.js';
|
|
7
|
+
export { runHttp } from './http.js';
|
|
8
|
+
export { JsonRpcServer, jsonRpcServerCapsule, parse, errorResponse, successResponse, ParseError, InvalidRequest, MethodNotFound, InvalidParams, InternalError, } from './jsonrpc.js';
|
|
9
|
+
export type { JsonRpcId, JsonRpcRequest, JsonRpcNotification, JsonRpcResponse, JsonRpcSuccess, JsonRpcErrorResponse, ParseOutcome, } from './jsonrpc.js';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4GAA4G;AAE5G,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACtE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,KAAK,EACL,aAAa,EACb,eAAe,EACf,UAAU,EACV,cAAc,EACd,cAAc,EACd,aAAa,EACb,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,SAAS,EACT,cAAc,EACd,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,oBAAoB,EACpB,YAAY,GACb,MAAM,cAAc,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** `@czap/mcp-server` — MCP bridge for **LiteShip**; forwards tools to the `czap` CLI + capsule factory. */
|
|
2
|
+
export { start } from './start.js';
|
|
3
|
+
export { listTools, dispatchToolCall, dispatch } from './dispatch.js';
|
|
4
|
+
export { runStdio } from './stdio.js';
|
|
5
|
+
export { runHttp } from './http.js';
|
|
6
|
+
// JSON-RPC 2.0 kernel — reusable beyond MCP.
|
|
7
|
+
export { JsonRpcServer, jsonRpcServerCapsule, parse, errorResponse, successResponse, ParseError, InvalidRequest, MethodNotFound, InvalidParams, InternalError, } from './jsonrpc.js';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4GAA4G;AAE5G,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEtE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,6CAA6C;AAC7C,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,KAAK,EACL,aAAa,EACb,eAAe,EACf,UAAU,EACV,cAAc,EACd,cAAc,EACd,aAAa,EACb,aAAa,GACd,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JsonRpcServer — framework-free JSON-RPC 2.0 kernel.
|
|
3
|
+
*
|
|
4
|
+
* Parses incoming wire bytes, classifies them as Request | Notification |
|
|
5
|
+
* Batch | InvalidRequest | ParseError, and produces responses (or null
|
|
6
|
+
* for notifications, which MUST NOT receive a response per §4.1).
|
|
7
|
+
*
|
|
8
|
+
* Exposed as a `pureTransform` arm capsule `mcp.jsonrpc-server` so it
|
|
9
|
+
* appears in the manifest and can be reused by future JSON-RPC surfaces
|
|
10
|
+
* beyond MCP.
|
|
11
|
+
*
|
|
12
|
+
* Conformance: JSON-RPC 2.0 specification (https://www.jsonrpc.org/specification).
|
|
13
|
+
* §3 — `jsonrpc: "2.0"` required.
|
|
14
|
+
* §4 — Request vs Notification distinguished by presence of `id`.
|
|
15
|
+
* §4.1 — A Notification MUST NOT receive a Response.
|
|
16
|
+
* §4.2 — Parse errors MUST emit a Response with code -32700, id null.
|
|
17
|
+
* §5 — Response is `result` XOR `error`.
|
|
18
|
+
* §5.1 — Standard error codes.
|
|
19
|
+
* §6 — Batch: array of requests/notifications. Empty array → -32600.
|
|
20
|
+
*
|
|
21
|
+
* @module
|
|
22
|
+
*/
|
|
23
|
+
/** Per §4: `id` is string, number, or null. Absent = notification. */
|
|
24
|
+
export type JsonRpcId = string | number | null;
|
|
25
|
+
/** A JSON-RPC 2.0 request (has `id`). */
|
|
26
|
+
export interface JsonRpcRequest {
|
|
27
|
+
readonly jsonrpc: '2.0';
|
|
28
|
+
readonly id: JsonRpcId;
|
|
29
|
+
readonly method: string;
|
|
30
|
+
readonly params?: readonly unknown[] | Record<string, unknown>;
|
|
31
|
+
}
|
|
32
|
+
/** A JSON-RPC 2.0 notification (no `id`). Per §4.1 MUST NOT be responded to. */
|
|
33
|
+
export interface JsonRpcNotification {
|
|
34
|
+
readonly jsonrpc: '2.0';
|
|
35
|
+
readonly method: string;
|
|
36
|
+
readonly params?: readonly unknown[] | Record<string, unknown>;
|
|
37
|
+
}
|
|
38
|
+
/** Successful response per §5. */
|
|
39
|
+
export interface JsonRpcSuccess {
|
|
40
|
+
readonly jsonrpc: '2.0';
|
|
41
|
+
readonly id: JsonRpcId;
|
|
42
|
+
readonly result: unknown;
|
|
43
|
+
}
|
|
44
|
+
/** Error response per §5 + §5.1. */
|
|
45
|
+
export interface JsonRpcErrorResponse {
|
|
46
|
+
readonly jsonrpc: '2.0';
|
|
47
|
+
readonly id: JsonRpcId;
|
|
48
|
+
readonly error: {
|
|
49
|
+
readonly code: number;
|
|
50
|
+
readonly message: string;
|
|
51
|
+
readonly data?: unknown;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/** Either a success or error response. */
|
|
55
|
+
export type JsonRpcResponse = JsonRpcSuccess | JsonRpcErrorResponse;
|
|
56
|
+
export declare const ParseError: -32700;
|
|
57
|
+
export declare const InvalidRequest: -32600;
|
|
58
|
+
export declare const MethodNotFound: -32601;
|
|
59
|
+
export declare const InvalidParams: -32602;
|
|
60
|
+
export declare const InternalError: -32603;
|
|
61
|
+
/** Discriminated union of every parse outcome the kernel produces. */
|
|
62
|
+
export type ParseOutcome = {
|
|
63
|
+
readonly kind: 'request';
|
|
64
|
+
readonly message: JsonRpcRequest;
|
|
65
|
+
} | {
|
|
66
|
+
readonly kind: 'notification';
|
|
67
|
+
readonly message: JsonRpcNotification;
|
|
68
|
+
} | {
|
|
69
|
+
readonly kind: 'batch';
|
|
70
|
+
readonly outcomes: readonly ParseOutcome[];
|
|
71
|
+
} | {
|
|
72
|
+
readonly kind: 'parse-error';
|
|
73
|
+
} | {
|
|
74
|
+
readonly kind: 'invalid-request';
|
|
75
|
+
readonly id: JsonRpcId;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Parse a single JSON-RPC line. Distinguishes:
|
|
79
|
+
* - parse failure → `parse-error` (§4.2)
|
|
80
|
+
* - empty array → `invalid-request` per §6
|
|
81
|
+
* - non-object scalar → `invalid-request`
|
|
82
|
+
* - object with bad `jsonrpc`/`method` → `invalid-request`
|
|
83
|
+
* - object with `id` present → `request`
|
|
84
|
+
* - object without `id` → `notification`
|
|
85
|
+
* - non-empty array → `batch` with per-element outcomes
|
|
86
|
+
*
|
|
87
|
+
* Note (§4 id-vs-notification): `"id": null` is a Request with id null,
|
|
88
|
+
* not a notification. Only an absent id field marks a notification.
|
|
89
|
+
*/
|
|
90
|
+
declare function _parse(line: string): ParseOutcome;
|
|
91
|
+
/** Construct a -32700 / -32600 / -32601 / -32602 / -32603 error response. */
|
|
92
|
+
declare function _errorResponse(id: JsonRpcId, code: number, message: string, data?: unknown): JsonRpcErrorResponse;
|
|
93
|
+
/** Construct a success response (§5). */
|
|
94
|
+
declare function _successResponse(id: JsonRpcId, result: unknown): JsonRpcSuccess;
|
|
95
|
+
export declare const parse: typeof _parse;
|
|
96
|
+
export declare const errorResponse: typeof _errorResponse;
|
|
97
|
+
export declare const successResponse: typeof _successResponse;
|
|
98
|
+
/**
|
|
99
|
+
* Capsule definition for the kernel — placed in the catalog under the
|
|
100
|
+
* `pureTransform` arm so the factory compiler emits a generated test +
|
|
101
|
+
* bench pair and the manifest tracks the kernel's content address.
|
|
102
|
+
*/
|
|
103
|
+
export declare const jsonRpcServerCapsule: import("@czap/core").CapsuleDef<"pureTransform", string, {
|
|
104
|
+
kind: string;
|
|
105
|
+
}, unknown>;
|
|
106
|
+
/** Namespaced public surface of the kernel. */
|
|
107
|
+
export declare const JsonRpcServer: {
|
|
108
|
+
readonly parse: typeof _parse;
|
|
109
|
+
readonly errorResponse: typeof _errorResponse;
|
|
110
|
+
readonly successResponse: typeof _successResponse;
|
|
111
|
+
};
|
|
112
|
+
export declare namespace JsonRpcServer {
|
|
113
|
+
/** Discriminated parse outcome. */
|
|
114
|
+
type Outcome = ParseOutcome;
|
|
115
|
+
/** Wire-shape request (§4). */
|
|
116
|
+
type Request = JsonRpcRequest;
|
|
117
|
+
/** Wire-shape notification (§4.1). */
|
|
118
|
+
type Notification = JsonRpcNotification;
|
|
119
|
+
/** Wire-shape response (§5). */
|
|
120
|
+
type Response = JsonRpcResponse;
|
|
121
|
+
/** Wire-shape success response. */
|
|
122
|
+
type Success = JsonRpcSuccess;
|
|
123
|
+
/** Wire-shape error response. */
|
|
124
|
+
type Error = JsonRpcErrorResponse;
|
|
125
|
+
/** Id type per §4. */
|
|
126
|
+
type Id = JsonRpcId;
|
|
127
|
+
}
|
|
128
|
+
export {};
|
|
129
|
+
//# sourceMappingURL=jsonrpc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonrpc.d.ts","sourceRoot":"","sources":["../src/jsonrpc.ts"],"names":[],"mappings":"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"}
|