@zenalexa/unicli 0.213.1 → 0.213.3
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/AGENTS.md +1 -1
- package/README.md +4 -4
- package/README.zh-CN.md +3 -3
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +11 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/describe.d.ts +26 -0
- package/dist/commands/describe.d.ts.map +1 -0
- package/dist/commands/describe.js +230 -0
- package/dist/commands/describe.js.map +1 -0
- package/dist/commands/dev.js +1 -1
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/dispatch.d.ts +14 -3
- package/dist/commands/dispatch.d.ts.map +1 -1
- package/dist/commands/dispatch.js +141 -81
- package/dist/commands/dispatch.js.map +1 -1
- package/dist/commands/health.d.ts.map +1 -1
- package/dist/commands/health.js +1 -1
- package/dist/commands/health.js.map +1 -1
- package/dist/commands/skills.d.ts.map +1 -1
- package/dist/commands/skills.js +1 -1
- package/dist/commands/skills.js.map +1 -1
- package/dist/constants.d.ts +2 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +2 -0
- package/dist/constants.js.map +1 -1
- package/dist/discovery/loader.d.ts +8 -0
- package/dist/discovery/loader.d.ts.map +1 -1
- package/dist/discovery/loader.js +22 -1
- package/dist/discovery/loader.js.map +1 -1
- package/dist/engine/args.d.ts +83 -0
- package/dist/engine/args.d.ts.map +1 -0
- package/dist/engine/args.js +260 -0
- package/dist/engine/args.js.map +1 -0
- package/dist/engine/executor.d.ts +20 -1
- package/dist/engine/executor.d.ts.map +1 -1
- package/dist/engine/executor.js +11 -2
- package/dist/engine/executor.js.map +1 -1
- package/dist/engine/harden.d.ts +48 -0
- package/dist/engine/harden.d.ts.map +1 -0
- package/dist/engine/harden.js +327 -0
- package/dist/engine/harden.js.map +1 -0
- package/dist/engine/invoke.d.ts +16 -0
- package/dist/engine/invoke.d.ts.map +1 -0
- package/dist/engine/invoke.js +15 -0
- package/dist/engine/invoke.js.map +1 -0
- package/dist/engine/kernel/compile.d.ts +30 -0
- package/dist/engine/kernel/compile.d.ts.map +1 -0
- package/dist/engine/kernel/compile.js +167 -0
- package/dist/engine/kernel/compile.js.map +1 -0
- package/dist/engine/kernel/execute.d.ts +35 -0
- package/dist/engine/kernel/execute.d.ts.map +1 -0
- package/dist/engine/kernel/execute.js +221 -0
- package/dist/engine/kernel/execute.js.map +1 -0
- package/dist/engine/kernel/types.d.ts +49 -0
- package/dist/engine/kernel/types.d.ts.map +1 -0
- package/dist/engine/kernel/types.js +9 -0
- package/dist/engine/kernel/types.js.map +1 -0
- package/dist/engine/kernel/ulid.d.ts +21 -0
- package/dist/engine/kernel/ulid.d.ts.map +1 -0
- package/dist/engine/kernel/ulid.js +76 -0
- package/dist/engine/kernel/ulid.js.map +1 -0
- package/dist/engine/template.d.ts.map +1 -1
- package/dist/engine/template.js +11 -0
- package/dist/engine/template.js.map +1 -1
- package/dist/manifest.json +1 -1
- package/dist/mcp/dispatch.d.ts +46 -0
- package/dist/mcp/dispatch.d.ts.map +1 -0
- package/dist/mcp/dispatch.js +109 -0
- package/dist/mcp/dispatch.js.map +1 -0
- package/dist/mcp/handler.d.ts +30 -0
- package/dist/mcp/handler.d.ts.map +1 -0
- package/dist/mcp/handler.js +293 -0
- package/dist/mcp/handler.js.map +1 -0
- package/dist/mcp/http-transport.d.ts +16 -0
- package/dist/mcp/http-transport.d.ts.map +1 -0
- package/dist/mcp/http-transport.js +124 -0
- package/dist/mcp/http-transport.js.map +1 -0
- package/dist/mcp/server.d.ts +17 -33
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +31 -742
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/sse-transport.js.map +1 -1
- package/dist/mcp/streamable-http/handle-post.d.ts +23 -0
- package/dist/mcp/streamable-http/handle-post.d.ts.map +1 -0
- package/dist/mcp/streamable-http/handle-post.js +357 -0
- package/dist/mcp/streamable-http/handle-post.js.map +1 -0
- package/dist/mcp/streamable-http/index.d.ts +45 -0
- package/dist/mcp/streamable-http/index.d.ts.map +1 -0
- package/dist/mcp/streamable-http/index.js +150 -0
- package/dist/mcp/streamable-http/index.js.map +1 -0
- package/dist/mcp/streamable-http/session.d.ts +85 -0
- package/dist/mcp/streamable-http/session.d.ts.map +1 -0
- package/dist/mcp/streamable-http/session.js +104 -0
- package/dist/mcp/streamable-http/session.js.map +1 -0
- package/dist/mcp/streamable-http.d.ts +7 -85
- package/dist/mcp/streamable-http.d.ts.map +1 -1
- package/dist/mcp/streamable-http.js +6 -568
- package/dist/mcp/streamable-http.js.map +1 -1
- package/dist/mcp/tools.d.ts +57 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +237 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/output/envelope.d.ts +29 -0
- package/dist/output/envelope.d.ts.map +1 -1
- package/dist/output/envelope.js +6 -0
- package/dist/output/envelope.js.map +1 -1
- package/dist/output/next-actions.d.ts +18 -0
- package/dist/output/next-actions.d.ts.map +1 -0
- package/dist/output/next-actions.js +64 -0
- package/dist/output/next-actions.js.map +1 -0
- package/dist/output/projection.d.ts +93 -0
- package/dist/output/projection.d.ts.map +1 -0
- package/dist/output/projection.js +255 -0
- package/dist/output/projection.js.map +1 -0
- package/dist/protocol/acp-helpers.d.ts +32 -0
- package/dist/protocol/acp-helpers.d.ts.map +1 -0
- package/dist/protocol/acp-helpers.js +175 -0
- package/dist/protocol/acp-helpers.js.map +1 -0
- package/dist/protocol/acp.d.ts +2 -27
- package/dist/protocol/acp.d.ts.map +1 -1
- package/dist/protocol/acp.js +7 -170
- package/dist/protocol/acp.js.map +1 -1
- package/dist/types.d.ts +32 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +13 -2
- package/src/adapters/1688/item.yaml +1 -0
- package/src/adapters/1688/store.yaml +1 -0
- package/src/adapters/36kr/article.yaml +1 -0
- package/src/adapters/amazon/bestsellers.yaml +2 -0
- package/src/adapters/amazon/movers-shakers.yaml +2 -0
- package/src/adapters/amazon/new-releases.yaml +2 -0
- package/src/adapters/amazon/rankings.yaml +1 -0
- package/src/adapters/apple-podcasts/episodes.yaml +1 -0
- package/src/adapters/arxiv/paper.yaml +1 -0
- package/src/adapters/audacity/convert.yaml +1 -0
- package/src/adapters/audacity/effects.yaml +1 -0
- package/src/adapters/audacity/info.yaml +1 -0
- package/src/adapters/audacity/mix.yaml +1 -0
- package/src/adapters/audacity/normalize.yaml +1 -0
- package/src/adapters/audacity/spectrogram.yaml +1 -0
- package/src/adapters/audacity/split-channels.yaml +1 -0
- package/src/adapters/audacity/trim.yaml +1 -0
- package/src/adapters/bilibili/favorites.yaml +1 -0
- package/src/adapters/blender/animation.yaml +2 -0
- package/src/adapters/blender/camera.yaml +1 -0
- package/src/adapters/blender/convert.yaml +1 -0
- package/src/adapters/blender/export.yaml +1 -0
- package/src/adapters/blender/import.yaml +1 -0
- package/src/adapters/blender/info.yaml +1 -0
- package/src/adapters/blender/lighting.yaml +1 -0
- package/src/adapters/blender/materials.yaml +1 -0
- package/src/adapters/blender/objects.yaml +1 -0
- package/src/adapters/blender/render.yaml +2 -0
- package/src/adapters/blender/scene.yaml +1 -0
- package/src/adapters/blender/screenshot.yaml +2 -0
- package/src/adapters/blender/script.yaml +1 -0
- package/src/adapters/boss/detail.yaml +2 -0
- package/src/adapters/cloudcompare/info.yaml +1 -0
- package/src/adapters/coupang/add-to-cart.yaml +1 -0
- package/src/adapters/ctrip/search.yaml +1 -0
- package/src/adapters/douban/download.yaml +1 -0
- package/src/adapters/douban/photos.yaml +1 -0
- package/src/adapters/douban/subject.yaml +2 -0
- package/src/adapters/doubao-web/detail.yaml +1 -0
- package/src/adapters/doubao-web/meeting-summary.yaml +1 -0
- package/src/adapters/doubao-web/meeting-transcript.yaml +1 -0
- package/src/adapters/drawio/export.yaml +2 -0
- package/src/adapters/facebook/join-group.yaml +2 -0
- package/src/adapters/ffmpeg/compress.yaml +2 -0
- package/src/adapters/ffmpeg/concat.yaml +1 -0
- package/src/adapters/ffmpeg/convert.yaml +1 -0
- package/src/adapters/ffmpeg/extract-audio.yaml +2 -0
- package/src/adapters/ffmpeg/gif.yaml +2 -0
- package/src/adapters/ffmpeg/normalize.yaml +2 -0
- package/src/adapters/ffmpeg/probe.yaml +1 -0
- package/src/adapters/ffmpeg/resize.yaml +2 -0
- package/src/adapters/ffmpeg/subtitles.yaml +2 -0
- package/src/adapters/ffmpeg/thumbnail.yaml +2 -0
- package/src/adapters/ffmpeg/trim.yaml +2 -0
- package/src/adapters/freecad/assembly.yaml +1 -0
- package/src/adapters/freecad/bom.yaml +1 -0
- package/src/adapters/freecad/boolean.yaml +1 -0
- package/src/adapters/freecad/check.yaml +1 -0
- package/src/adapters/freecad/convert.yaml +1 -0
- package/src/adapters/freecad/export-stl.yaml +1 -0
- package/src/adapters/freecad/import.yaml +1 -0
- package/src/adapters/freecad/info.yaml +1 -0
- package/src/adapters/freecad/macro.yaml +1 -0
- package/src/adapters/freecad/measure.yaml +1 -0
- package/src/adapters/freecad/mesh.yaml +1 -0
- package/src/adapters/freecad/properties.yaml +1 -0
- package/src/adapters/freecad/render.yaml +1 -0
- package/src/adapters/freecad/section.yaml +1 -0
- package/src/adapters/freecad/sketch.yaml +1 -0
- package/src/adapters/gimp/adjust.yaml +1 -0
- package/src/adapters/gimp/batch.yaml +1 -0
- package/src/adapters/gimp/convert.yaml +1 -0
- package/src/adapters/gimp/crop.yaml +1 -0
- package/src/adapters/gimp/filter.yaml +1 -0
- package/src/adapters/gimp/flip.yaml +1 -0
- package/src/adapters/gimp/info.yaml +1 -0
- package/src/adapters/gimp/layers.yaml +1 -0
- package/src/adapters/gimp/merge-layers.yaml +1 -0
- package/src/adapters/gimp/resize.yaml +1 -0
- package/src/adapters/gimp/rotate.yaml +1 -0
- package/src/adapters/gimp/text.yaml +1 -0
- package/src/adapters/godot/scene-export.yaml +1 -0
- package/src/adapters/hackernews/comments.yaml +1 -0
- package/src/adapters/hackernews/item.yaml +1 -0
- package/src/adapters/hf/top.yaml +1 -0
- package/src/adapters/imagemagick/composite.yaml +1 -0
- package/src/adapters/imagemagick/convert.yaml +1 -0
- package/src/adapters/imagemagick/identify.yaml +1 -0
- package/src/adapters/imagemagick/montage.yaml +1 -0
- package/src/adapters/imagemagick/resize.yaml +1 -0
- package/src/adapters/imdb/person.yaml +1 -0
- package/src/adapters/imdb/reviews.yaml +1 -0
- package/src/adapters/imdb/title.yaml +1 -0
- package/src/adapters/inkscape/convert.yaml +2 -0
- package/src/adapters/inkscape/export.yaml +2 -0
- package/src/adapters/inkscape/optimize.yaml +2 -0
- package/src/adapters/instagram/stories.yaml +1 -0
- package/src/adapters/jd/item.yaml +1 -0
- package/src/adapters/jike/post.yaml +2 -0
- package/src/adapters/jike/topic.yaml +2 -0
- package/src/adapters/kdenlive/info.yaml +1 -0
- package/src/adapters/kdenlive/render.yaml +1 -0
- package/src/adapters/krita/batch.yaml +1 -0
- package/src/adapters/krita/convert.yaml +1 -0
- package/src/adapters/krita/export.yaml +1 -0
- package/src/adapters/krita/info.yaml +1 -0
- package/src/adapters/libreoffice/convert.yaml +1 -0
- package/src/adapters/libreoffice/print.yaml +1 -0
- package/src/adapters/linear/issue-update.yaml +1 -0
- package/src/adapters/linux-do/category.yaml +1 -0
- package/src/adapters/linux-do/topic.yaml +1 -0
- package/src/adapters/macos/calendar-create.yaml +1 -0
- package/src/adapters/macos/finder-copy.yaml +1 -0
- package/src/adapters/macos/finder-move.yaml +1 -0
- package/src/adapters/macos/finder-new-folder.yaml +1 -0
- package/src/adapters/macos/finder-tags.yaml +1 -0
- package/src/adapters/macos/open.yaml +2 -0
- package/src/adapters/macos/screen-recording.yaml +1 -0
- package/src/adapters/macos/screenshot.yaml +1 -0
- package/src/adapters/macos/spotlight.yaml +1 -0
- package/src/adapters/macos/wallpaper.yaml +1 -0
- package/src/adapters/medium/article.yaml +1 -0
- package/src/adapters/mermaid/render.yaml +1 -0
- package/src/adapters/minimax/tts.yaml +1 -0
- package/src/adapters/motion-studio/component-get.yaml +1 -0
- package/src/adapters/musescore/convert.yaml +2 -0
- package/src/adapters/musescore/export.yaml +2 -0
- package/src/adapters/musescore/info.yaml +1 -0
- package/src/adapters/musescore/instruments.yaml +1 -0
- package/src/adapters/musescore/transpose.yaml +1 -0
- package/src/adapters/netease-music/playlist.yaml +1 -0
- package/src/adapters/netease-music/top.yaml +1 -0
- package/src/adapters/notebooklm/get.yaml +1 -0
- package/src/adapters/notebooklm/history.yaml +1 -0
- package/src/adapters/notebooklm/note-list.yaml +1 -0
- package/src/adapters/notebooklm/notes-get.yaml +1 -0
- package/src/adapters/notebooklm/open.yaml +1 -0
- package/src/adapters/notebooklm/source-fulltext.yaml +1 -0
- package/src/adapters/notebooklm/source-get.yaml +1 -0
- package/src/adapters/notebooklm/source-guide.yaml +1 -0
- package/src/adapters/notebooklm/source-list.yaml +1 -0
- package/src/adapters/notebooklm/summary.yaml +1 -0
- package/src/adapters/novita/status.yaml +1 -0
- package/src/adapters/obs/screenshot.yaml +1 -0
- package/src/adapters/obsidian/open.yaml +1 -0
- package/src/adapters/ones/login.yaml +1 -0
- package/src/adapters/ones/task.yaml +1 -0
- package/src/adapters/pandoc/convert.yaml +1 -0
- package/src/adapters/paperreview/feedback.yaml +2 -0
- package/src/adapters/paperreview/review.yaml +2 -0
- package/src/adapters/paperreview/submit.yaml +2 -0
- package/src/adapters/pixiv/detail.yaml +1 -0
- package/src/adapters/pixiv/download.yaml +2 -0
- package/src/adapters/quark/ls.yaml +1 -0
- package/src/adapters/reddit/comments.yaml +2 -0
- package/src/adapters/renderdoc/capture-list.yaml +1 -0
- package/src/adapters/renderdoc/frame-export.yaml +1 -0
- package/src/adapters/reuters/article.yaml +2 -0
- package/src/adapters/shotcut/info.yaml +1 -0
- package/src/adapters/shotcut/render.yaml +1 -0
- package/src/adapters/sinablog/article.yaml +1 -0
- package/src/adapters/sinablog/user.yaml +1 -0
- package/src/adapters/sketch/artboards.yaml +1 -0
- package/src/adapters/sketch/export.yaml +1 -0
- package/src/adapters/sketch/symbols.yaml +1 -0
- package/src/adapters/smzdm/article.yaml +1 -0
- package/src/adapters/stackoverflow/question.yaml +1 -0
- package/src/adapters/stagehand/wrap-observe.yaml +1 -0
- package/src/adapters/steam/wishlist.yaml +1 -0
- package/src/adapters/tieba/read.yaml +1 -0
- package/src/adapters/tiktok/comment.yaml +1 -0
- package/src/adapters/tiktok/like.yaml +1 -0
- package/src/adapters/tiktok/save.yaml +1 -0
- package/src/adapters/tiktok/unlike.yaml +1 -0
- package/src/adapters/tiktok/unsave.yaml +1 -0
- package/src/adapters/twitch/streams.yaml +1 -0
- package/src/adapters/twitter/quotes.yaml +2 -0
- package/src/adapters/twitter/retweets.yaml +1 -0
- package/src/adapters/v2ex/replies.yaml +1 -0
- package/src/adapters/v2ex/topic.yaml +1 -0
- package/src/adapters/vscode/install-ext.yaml +1 -0
- package/src/adapters/vscode/open.yaml +1 -0
- package/src/adapters/web/read.yaml +1 -0
- package/src/adapters/weibo/comments.yaml +1 -0
- package/src/adapters/weibo/post.yaml +1 -0
- package/src/adapters/weixin/download.yaml +1 -0
- package/src/adapters/wiremock/create-stub.yaml +2 -0
- package/src/adapters/wiremock/delete-stub.yaml +1 -0
- package/src/adapters/wiremock/verify.yaml +1 -0
- package/src/adapters/xianyu/item.yaml +1 -0
- package/src/adapters/xiaoe/catalog.yaml +1 -0
- package/src/adapters/xiaoe/content.yaml +1 -0
- package/src/adapters/xiaoe/detail.yaml +1 -0
- package/src/adapters/xiaoe/play-url.yaml +1 -0
- package/src/adapters/xiaoyuzhou/podcast.yaml +2 -0
- package/src/adapters/yollomi/edit.yaml +2 -0
- package/src/adapters/yollomi/remove-bg.yaml +2 -0
- package/src/adapters/yollomi/restore.yaml +2 -0
- package/src/adapters/yollomi/upload.yaml +2 -0
- package/src/adapters/yollomi/upscale.yaml +2 -0
- package/src/adapters/youtube/playlist.yaml +1 -0
- package/src/adapters/yt-dlp/download.yaml +2 -0
- package/src/adapters/yt-dlp/extract-audio.yaml +2 -0
- package/src/adapters/yt-dlp/info.yaml +1 -0
- package/src/adapters/zhihu/answer.yaml +1 -0
- package/src/adapters/zhihu/answers.yaml +2 -0
- package/src/adapters/zhihu/article.yaml +1 -0
- package/src/adapters/zhihu/articles.yaml +2 -0
- package/src/adapters/zhihu/collections.yaml +2 -0
- package/src/adapters/zhihu/columns.yaml +2 -0
- package/src/adapters/zhihu/comment.yaml +1 -0
- package/src/adapters/zhihu/download.yaml +1 -0
- package/src/adapters/zhihu/followers.yaml +2 -0
- package/src/adapters/zhihu/following.yaml +2 -0
- package/src/adapters/zhihu/pins.yaml +2 -0
- package/src/adapters/zhihu/question.yaml +1 -0
- package/src/adapters/zhihu/topic.yaml +1 -0
- package/src/adapters/zhihu/topics.yaml +1 -0
- package/src/adapters/zhihu/user.yaml +2 -0
- package/src/adapters/zoom/join.yaml +1 -0
- package/src/adapters/zsxq/search.yaml +1 -0
- package/src/adapters/zsxq/topic.yaml +1 -0
- package/src/adapters/zsxq/topics.yaml +1 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool-call dispatcher — the bridge between JSON-RPC tool invocations
|
|
3
|
+
* and the invocation kernel.
|
|
4
|
+
*
|
|
5
|
+
* v0.213.3 R2: every MCP tool call funnels through `execute()` so the CLI
|
|
6
|
+
* and MCP surfaces produce byte-identical envelopes (modulo trace_id and
|
|
7
|
+
* duration_ms). Flat `params` shape preserved for D2 backward compat.
|
|
8
|
+
*
|
|
9
|
+
* Shape contract (backward compat with v0.213.2 and earlier):
|
|
10
|
+
* - success → `{ content: [{type:"text", text: JSON.stringify({count, results}, null, 2)}],
|
|
11
|
+
* structuredContent: { type: "json", data: {count, results} } }`
|
|
12
|
+
* - error → `{ isError: true, content, structuredContent.data.suggestion, _meta }`
|
|
13
|
+
* - warnings flow to `_meta.warnings` so agents can inspect them
|
|
14
|
+
*/
|
|
15
|
+
import { buildInvocation, execute } from "../engine/kernel/execute.js";
|
|
16
|
+
import { coerceLimit } from "../engine/args.js";
|
|
17
|
+
/**
|
|
18
|
+
* 10 KB threshold above which MCP clients (Claude Code, Zed) may truncate
|
|
19
|
+
* tool output. When exceeded, we attach `_meta.anthropic/maxResultSizeChars`
|
|
20
|
+
* to raise the cap to 100 KB for this call.
|
|
21
|
+
*/
|
|
22
|
+
export const MAX_RESULT_SIZE_CHARS = 10_000;
|
|
23
|
+
/**
|
|
24
|
+
* Annotate a tool result with `_meta.anthropic/maxResultSizeChars` when the
|
|
25
|
+
* serialized payload exceeds MAX_RESULT_SIZE_CHARS.
|
|
26
|
+
*/
|
|
27
|
+
export function annotateIfLarge(result) {
|
|
28
|
+
const totalChars = result.content.reduce((sum, c) => sum + c.text.length, 0);
|
|
29
|
+
if (totalChars > MAX_RESULT_SIZE_CHARS) {
|
|
30
|
+
return {
|
|
31
|
+
...result,
|
|
32
|
+
_meta: {
|
|
33
|
+
...result._meta,
|
|
34
|
+
"anthropic/maxResultSizeChars": 100_000,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
function withWarnings(result, warnings) {
|
|
41
|
+
if (warnings.length === 0)
|
|
42
|
+
return result;
|
|
43
|
+
return {
|
|
44
|
+
...result,
|
|
45
|
+
_meta: { ...result._meta, warnings: [...warnings] },
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Execute a resolved (adapter, command) pair via the invocation kernel and
|
|
50
|
+
* shape the result into the MCP `McpToolResult` envelope. Used by both the
|
|
51
|
+
* default `unicli_run` tool and every expanded `unicli_<site>_<command>`.
|
|
52
|
+
*/
|
|
53
|
+
export async function runResolvedCommand(adapter, cmd, cmdName, args) {
|
|
54
|
+
// MCP preserves the flat-params contract. Apply the default `limit: 20`
|
|
55
|
+
// only when the adapter declares a `limit` arg — the kernel's ajv
|
|
56
|
+
// validator runs in strict mode (`additionalProperties: false`), so
|
|
57
|
+
// passing an undeclared `limit` would trip usage errors for adapters
|
|
58
|
+
// that don't paginate.
|
|
59
|
+
const declaresLimit = (cmd.adapterArgs ?? []).some((a) => a.name === "limit");
|
|
60
|
+
const mergedArgs = declaresLimit
|
|
61
|
+
? { limit: 20, ...args }
|
|
62
|
+
: { ...args };
|
|
63
|
+
if (declaresLimit && args.limit !== undefined) {
|
|
64
|
+
const coerced = coerceLimit(args.limit);
|
|
65
|
+
if (coerced !== undefined)
|
|
66
|
+
mergedArgs.limit = coerced;
|
|
67
|
+
}
|
|
68
|
+
const inv = buildInvocation("mcp", adapter.name, cmdName, {
|
|
69
|
+
args: mergedArgs,
|
|
70
|
+
source: "mcp",
|
|
71
|
+
});
|
|
72
|
+
if (!inv) {
|
|
73
|
+
// Already filtered by handleRunCommand / handleExpandedTool before this
|
|
74
|
+
// point; still, guard so a misrouted call doesn't crash the server.
|
|
75
|
+
const errorData = {
|
|
76
|
+
error: `Unknown command: ${adapter.name} ${cmdName}`,
|
|
77
|
+
suggestion: "Use unicli_list to see available commands.",
|
|
78
|
+
};
|
|
79
|
+
return {
|
|
80
|
+
content: [{ type: "text", text: JSON.stringify(errorData, null, 2) }],
|
|
81
|
+
structuredContent: { type: "json", data: errorData },
|
|
82
|
+
isError: true,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
const result = await execute(inv);
|
|
86
|
+
if (result.error) {
|
|
87
|
+
const errorData = {
|
|
88
|
+
error: result.error.message,
|
|
89
|
+
code: result.error.code,
|
|
90
|
+
adapter_path: result.error.adapter_path,
|
|
91
|
+
step: result.error.step,
|
|
92
|
+
suggestion: result.error.suggestion,
|
|
93
|
+
trace_id: inv.trace_id,
|
|
94
|
+
};
|
|
95
|
+
const base = {
|
|
96
|
+
content: [{ type: "text", text: JSON.stringify(errorData, null, 2) }],
|
|
97
|
+
structuredContent: { type: "json", data: errorData },
|
|
98
|
+
isError: true,
|
|
99
|
+
};
|
|
100
|
+
return withWarnings(base, result.warnings);
|
|
101
|
+
}
|
|
102
|
+
const data = { count: result.results.length, results: result.results };
|
|
103
|
+
const base = {
|
|
104
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
105
|
+
structuredContent: { type: "json", data },
|
|
106
|
+
};
|
|
107
|
+
return withWarnings(base, result.warnings);
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=dispatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../src/mcp/dispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAehD;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAC;AAE5C;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,MAAqB;IACnD,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC7E,IAAI,UAAU,GAAG,qBAAqB,EAAE,CAAC;QACvC,OAAO;YACL,GAAG,MAAM;YACT,KAAK,EAAE;gBACL,GAAG,MAAM,CAAC,KAAK;gBACf,8BAA8B,EAAE,OAAO;aACxC;SACF,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,YAAY,CACnB,MAAqB,EACrB,QAAkB;IAElB,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IACzC,OAAO;QACL,GAAG,MAAM;QACT,KAAK,EAAE,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,GAAG,QAAQ,CAAC,EAAE;KACpD,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,OAAwB,EACxB,GAAmB,EACnB,OAAe,EACf,IAA6B;IAE7B,wEAAwE;IACxE,kEAAkE;IAClE,oEAAoE;IACpE,qEAAqE;IACrE,uBAAuB;IACvB,MAAM,aAAa,GAAG,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;IAC9E,MAAM,UAAU,GAA4B,aAAa;QACvD,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE;QACxB,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC;IAChB,IAAI,aAAa,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC9C,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxC,IAAI,OAAO,KAAK,SAAS;YAAE,UAAU,CAAC,KAAK,GAAG,OAAO,CAAC;IACxD,CAAC;IAED,MAAM,GAAG,GAAG,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE;QACxD,IAAI,EAAE,UAAU;QAChB,MAAM,EAAE,KAAK;KACd,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,wEAAwE;QACxE,oEAAoE;QACpE,MAAM,SAAS,GAAG;YAChB,KAAK,EAAE,oBAAoB,OAAO,CAAC,IAAI,IAAI,OAAO,EAAE;YACpD,UAAU,EAAE,4CAA4C;SACzD,CAAC;QACF,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;YACrE,iBAAiB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE;YACpD,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;IAElC,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,MAAM,SAAS,GAAG;YAChB,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO;YAC3B,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI;YACvB,YAAY,EAAE,MAAM,CAAC,KAAK,CAAC,YAAY;YACvC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI;YACvB,UAAU,EAAE,MAAM,CAAC,KAAK,CAAC,UAAU;YACnC,QAAQ,EAAE,GAAG,CAAC,QAAQ;SACvB,CAAC;QACF,MAAM,IAAI,GAAkB;YAC1B,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;YACrE,iBAAiB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE;YACpD,OAAO,EAAE,IAAI;SACd,CAAC;QACF,OAAO,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,IAAI,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;IACvE,MAAM,IAAI,GAAkB;QAC1B,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QAChE,iBAAiB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;KAC1C,CAAC;IACF,OAAO,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP JSON-RPC dispatch — `buildHandler(tools)` returns the per-request
|
|
3
|
+
* handler used by every transport (stdio, HTTP, Streamable HTTP).
|
|
4
|
+
*
|
|
5
|
+
* Extracted from `server.ts` so the top-level file only owns bootstrap,
|
|
6
|
+
* arg parsing, and transport wiring. This module owns:
|
|
7
|
+
* - `initialize` / `ping` / `tools/list` / `tools/call` method dispatch
|
|
8
|
+
* - The four built-in meta-tools (`unicli_list` / `unicli_run` /
|
|
9
|
+
* `unicli_search` / `unicli_explore` + deprecated aliases)
|
|
10
|
+
* - Fallthrough to expanded-tool dispatch via `./dispatch.ts`
|
|
11
|
+
*/
|
|
12
|
+
import { type McpTool } from "./tools.js";
|
|
13
|
+
export interface JsonRpcRequest {
|
|
14
|
+
jsonrpc: "2.0";
|
|
15
|
+
id?: number | string | null;
|
|
16
|
+
method: string;
|
|
17
|
+
params?: Record<string, unknown>;
|
|
18
|
+
}
|
|
19
|
+
export interface JsonRpcResponse {
|
|
20
|
+
jsonrpc: "2.0";
|
|
21
|
+
id: number | string | null;
|
|
22
|
+
result?: unknown;
|
|
23
|
+
error?: {
|
|
24
|
+
code: number;
|
|
25
|
+
message: string;
|
|
26
|
+
data?: unknown;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export declare function buildHandler(tools: McpTool[]): (req: JsonRpcRequest) => JsonRpcResponse | undefined | Promise<JsonRpcResponse | undefined>;
|
|
30
|
+
//# sourceMappingURL=handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/mcp/handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH,OAAO,EAAoB,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AAI5D,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAC3D;AAoSD,wBAAgB,YAAY,CAC1B,KAAK,EAAE,OAAO,EAAE,GACf,CACD,GAAG,EAAE,cAAc,KAChB,eAAe,GAAG,SAAS,GAAG,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC,CAkCtE"}
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP JSON-RPC dispatch — `buildHandler(tools)` returns the per-request
|
|
3
|
+
* handler used by every transport (stdio, HTTP, Streamable HTTP).
|
|
4
|
+
*
|
|
5
|
+
* Extracted from `server.ts` so the top-level file only owns bootstrap,
|
|
6
|
+
* arg parsing, and transport wiring. This module owns:
|
|
7
|
+
* - `initialize` / `ping` / `tools/list` / `tools/call` method dispatch
|
|
8
|
+
* - The four built-in meta-tools (`unicli_list` / `unicli_run` /
|
|
9
|
+
* `unicli_search` / `unicli_explore` + deprecated aliases)
|
|
10
|
+
* - Fallthrough to expanded-tool dispatch via `./dispatch.ts`
|
|
11
|
+
*/
|
|
12
|
+
import { getAllAdapters, listCommands, resolveCommand } from "../registry.js";
|
|
13
|
+
import { annotateIfLarge, runResolvedCommand, } from "./dispatch.js";
|
|
14
|
+
import { expandedRegistry } from "./tools.js";
|
|
15
|
+
import { MCP_PROTOCOL_VERSION, VERSION } from "../constants.js";
|
|
16
|
+
import { resolveElicitation } from "./elicitation.js";
|
|
17
|
+
function handleListAdapters(params) {
|
|
18
|
+
let commands = listCommands();
|
|
19
|
+
const site = params.site;
|
|
20
|
+
const type = params.type;
|
|
21
|
+
if (site)
|
|
22
|
+
commands = commands.filter((c) => c.site.includes(site));
|
|
23
|
+
if (type)
|
|
24
|
+
commands = commands.filter((c) => c.type === type);
|
|
25
|
+
const adapters = getAllAdapters();
|
|
26
|
+
const siteMap = new Map();
|
|
27
|
+
for (const cmd of commands) {
|
|
28
|
+
let entry = siteMap.get(cmd.site);
|
|
29
|
+
if (!entry) {
|
|
30
|
+
const adapter = adapters.find((a) => a.name === cmd.site);
|
|
31
|
+
entry = { type: adapter?.type ?? cmd.type, commands: [] };
|
|
32
|
+
siteMap.set(cmd.site, entry);
|
|
33
|
+
}
|
|
34
|
+
entry.commands.push({ name: cmd.command, description: cmd.description });
|
|
35
|
+
}
|
|
36
|
+
const result = Array.from(siteMap.entries()).map(([name, info]) => ({
|
|
37
|
+
site: name,
|
|
38
|
+
type: info.type,
|
|
39
|
+
commands: info.commands,
|
|
40
|
+
}));
|
|
41
|
+
const data = {
|
|
42
|
+
total_sites: result.length,
|
|
43
|
+
total_commands: commands.length,
|
|
44
|
+
adapters: result,
|
|
45
|
+
};
|
|
46
|
+
return {
|
|
47
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
48
|
+
structuredContent: { type: "json", data },
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
async function handleRunCommand(params) {
|
|
52
|
+
const site = params.site;
|
|
53
|
+
const command = params.command;
|
|
54
|
+
const args = params.args ?? {};
|
|
55
|
+
if (!site || !command) {
|
|
56
|
+
const errorData = { error: "site and command are required" };
|
|
57
|
+
return {
|
|
58
|
+
content: [{ type: "text", text: JSON.stringify(errorData) }],
|
|
59
|
+
structuredContent: { type: "json", data: errorData },
|
|
60
|
+
isError: true,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
const resolved = resolveCommand(site, command);
|
|
64
|
+
if (!resolved) {
|
|
65
|
+
const adapters = getAllAdapters();
|
|
66
|
+
const matchingSites = adapters
|
|
67
|
+
.filter((a) => a.name.includes(site))
|
|
68
|
+
.map((a) => ({
|
|
69
|
+
site: a.name,
|
|
70
|
+
commands: Object.keys(a.commands),
|
|
71
|
+
}));
|
|
72
|
+
const errorData = {
|
|
73
|
+
error: `Unknown command: ${site} ${command}`,
|
|
74
|
+
suggestion: matchingSites.length > 0
|
|
75
|
+
? `Did you mean one of these? ${JSON.stringify(matchingSites)}`
|
|
76
|
+
: "Use list_adapters to see all available commands.",
|
|
77
|
+
};
|
|
78
|
+
return {
|
|
79
|
+
content: [{ type: "text", text: JSON.stringify(errorData, null, 2) }],
|
|
80
|
+
structuredContent: { type: "json", data: errorData },
|
|
81
|
+
isError: true,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
return runResolvedCommand(resolved.adapter, resolved.command, command, args);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Expanded-tool dispatcher — look up `unicli_<site>_<command>` in the
|
|
88
|
+
* registry populated by buildExpandedTools / buildDeferredTools.
|
|
89
|
+
*/
|
|
90
|
+
async function handleExpandedTool(toolName, args) {
|
|
91
|
+
if (!toolName.startsWith("unicli_"))
|
|
92
|
+
return undefined;
|
|
93
|
+
const entry = expandedRegistry.get(toolName);
|
|
94
|
+
if (!entry)
|
|
95
|
+
return undefined;
|
|
96
|
+
return runResolvedCommand(entry.adapter, entry.cmd, entry.cmdName, args);
|
|
97
|
+
}
|
|
98
|
+
function initializeResponse(id) {
|
|
99
|
+
return {
|
|
100
|
+
jsonrpc: "2.0",
|
|
101
|
+
id,
|
|
102
|
+
result: {
|
|
103
|
+
protocolVersion: MCP_PROTOCOL_VERSION,
|
|
104
|
+
capabilities: {
|
|
105
|
+
tools: { listChanged: false },
|
|
106
|
+
elicitation: { supported: true },
|
|
107
|
+
},
|
|
108
|
+
serverInfo: { name: "unicli", version: VERSION },
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
async function dispatchBuiltin(id, name, toolArgs) {
|
|
113
|
+
switch (name) {
|
|
114
|
+
case "unicli_list":
|
|
115
|
+
case "list_adapters": {
|
|
116
|
+
const result = handleListAdapters(toolArgs);
|
|
117
|
+
return { jsonrpc: "2.0", id, result: annotateIfLarge(result) };
|
|
118
|
+
}
|
|
119
|
+
case "unicli_run":
|
|
120
|
+
case "run_command": {
|
|
121
|
+
const result = await handleRunCommand(toolArgs);
|
|
122
|
+
return { jsonrpc: "2.0", id, result: annotateIfLarge(result) };
|
|
123
|
+
}
|
|
124
|
+
case "unicli_search":
|
|
125
|
+
return dispatchSearch(id, toolArgs);
|
|
126
|
+
case "unicli_explore":
|
|
127
|
+
case "unicli_discover":
|
|
128
|
+
return dispatchExplore(id, toolArgs);
|
|
129
|
+
}
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
132
|
+
async function dispatchSearch(id, toolArgs) {
|
|
133
|
+
const searchQuery = toolArgs.query;
|
|
134
|
+
const searchLimit = toolArgs.limit || 5;
|
|
135
|
+
if (!searchQuery) {
|
|
136
|
+
return {
|
|
137
|
+
jsonrpc: "2.0",
|
|
138
|
+
id,
|
|
139
|
+
error: { code: -32602, message: "Missing required parameter: query" },
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
const { search: searchFn } = await import("../discovery/search.js");
|
|
143
|
+
const results = searchFn(searchQuery, searchLimit);
|
|
144
|
+
const data = {
|
|
145
|
+
query: searchQuery,
|
|
146
|
+
count: results.length,
|
|
147
|
+
results: results.map((r) => ({
|
|
148
|
+
command: `unicli ${r.site} ${r.command}`,
|
|
149
|
+
site: r.site,
|
|
150
|
+
name: r.command,
|
|
151
|
+
description: r.description,
|
|
152
|
+
score: r.score,
|
|
153
|
+
category: r.category,
|
|
154
|
+
usage: r.usage,
|
|
155
|
+
})),
|
|
156
|
+
};
|
|
157
|
+
return {
|
|
158
|
+
jsonrpc: "2.0",
|
|
159
|
+
id,
|
|
160
|
+
result: annotateIfLarge({
|
|
161
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
162
|
+
structuredContent: { type: "json", data },
|
|
163
|
+
}),
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
async function dispatchExplore(id, toolArgs) {
|
|
167
|
+
const discoverUrl = toolArgs.url;
|
|
168
|
+
const discoverGoal = toolArgs.goal;
|
|
169
|
+
if (!discoverUrl) {
|
|
170
|
+
return {
|
|
171
|
+
jsonrpc: "2.0",
|
|
172
|
+
id,
|
|
173
|
+
error: { code: -32602, message: "Missing required parameter: url" },
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
if (!discoverUrl.startsWith("http://") &&
|
|
177
|
+
!discoverUrl.startsWith("https://")) {
|
|
178
|
+
return {
|
|
179
|
+
jsonrpc: "2.0",
|
|
180
|
+
id,
|
|
181
|
+
error: {
|
|
182
|
+
code: -32602,
|
|
183
|
+
message: "URL must start with http:// or https://",
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
const [{ execFile: ef }, { promisify: prom }] = await Promise.all([
|
|
188
|
+
import("node:child_process"),
|
|
189
|
+
import("node:util"),
|
|
190
|
+
]);
|
|
191
|
+
const execFileP = prom(ef);
|
|
192
|
+
const discoverArgs = ["generate", discoverUrl, "--json"];
|
|
193
|
+
if (discoverGoal)
|
|
194
|
+
discoverArgs.push("--goal", discoverGoal);
|
|
195
|
+
try {
|
|
196
|
+
const { stdout } = await execFileP("unicli", discoverArgs, {
|
|
197
|
+
timeout: 120_000,
|
|
198
|
+
encoding: "utf-8",
|
|
199
|
+
});
|
|
200
|
+
return {
|
|
201
|
+
jsonrpc: "2.0",
|
|
202
|
+
id,
|
|
203
|
+
result: annotateIfLarge({
|
|
204
|
+
content: [{ type: "text", text: stdout }],
|
|
205
|
+
}),
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
catch (err) {
|
|
209
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
210
|
+
return {
|
|
211
|
+
jsonrpc: "2.0",
|
|
212
|
+
id,
|
|
213
|
+
result: annotateIfLarge({
|
|
214
|
+
content: [{ type: "text", text: JSON.stringify({ error: message }) }],
|
|
215
|
+
isError: true,
|
|
216
|
+
}),
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
async function handleToolsCall(id, req) {
|
|
221
|
+
const params = req.params;
|
|
222
|
+
if (!params?.name) {
|
|
223
|
+
return {
|
|
224
|
+
jsonrpc: "2.0",
|
|
225
|
+
id,
|
|
226
|
+
error: { code: -32602, message: "Missing tool name" },
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
const toolArgs = params.arguments ?? {};
|
|
230
|
+
const builtin = await dispatchBuiltin(id, params.name, toolArgs);
|
|
231
|
+
if (builtin)
|
|
232
|
+
return builtin;
|
|
233
|
+
const result = await handleExpandedTool(params.name, toolArgs);
|
|
234
|
+
if (result) {
|
|
235
|
+
return { jsonrpc: "2.0", id, result: annotateIfLarge(result) };
|
|
236
|
+
}
|
|
237
|
+
return {
|
|
238
|
+
jsonrpc: "2.0",
|
|
239
|
+
id,
|
|
240
|
+
error: {
|
|
241
|
+
code: -32602,
|
|
242
|
+
message: `Unknown tool: ${params.name}. Use unicli_list to see available commands.`,
|
|
243
|
+
},
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
function handleElicitationResponse(id, req) {
|
|
247
|
+
const elicitParams = req.params;
|
|
248
|
+
if (elicitParams?.id == null || !elicitParams?.response) {
|
|
249
|
+
return {
|
|
250
|
+
jsonrpc: "2.0",
|
|
251
|
+
id,
|
|
252
|
+
error: {
|
|
253
|
+
code: -32602,
|
|
254
|
+
message: "Missing id or response in elicitation/response",
|
|
255
|
+
},
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
const resolved = resolveElicitation(elicitParams.id, elicitParams.response);
|
|
259
|
+
return { jsonrpc: "2.0", id, result: { resolved } };
|
|
260
|
+
}
|
|
261
|
+
export function buildHandler(tools) {
|
|
262
|
+
return function handleRequest(req) {
|
|
263
|
+
const id = req.id ?? null;
|
|
264
|
+
switch (req.method) {
|
|
265
|
+
case "initialize":
|
|
266
|
+
return initializeResponse(id);
|
|
267
|
+
case "notifications/initialized":
|
|
268
|
+
// Notifications have no response — transports already guard `if (response)`.
|
|
269
|
+
return undefined;
|
|
270
|
+
case "tools/list":
|
|
271
|
+
return { jsonrpc: "2.0", id, result: { tools } };
|
|
272
|
+
case "tools/call":
|
|
273
|
+
return handleToolsCall(id, req);
|
|
274
|
+
case "elicitation/response":
|
|
275
|
+
return handleElicitationResponse(id, req);
|
|
276
|
+
case "ping":
|
|
277
|
+
return { jsonrpc: "2.0", id, result: {} };
|
|
278
|
+
default:
|
|
279
|
+
if (id !== null && id !== undefined) {
|
|
280
|
+
return {
|
|
281
|
+
jsonrpc: "2.0",
|
|
282
|
+
id,
|
|
283
|
+
error: {
|
|
284
|
+
code: -32601,
|
|
285
|
+
message: `Method not found: ${req.method}`,
|
|
286
|
+
},
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
return undefined;
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
//# sourceMappingURL=handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/mcp/handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple JSON-RPC over HTTP transport for MCP.
|
|
3
|
+
*
|
|
4
|
+
* POST /mcp accepts a single JSON-RPC envelope and returns a single JSON
|
|
5
|
+
* response. GET /mcp returns server info — handy for health checks from a
|
|
6
|
+
* browser.
|
|
7
|
+
*
|
|
8
|
+
* Note: this is intentionally NOT a full MCP Streamable HTTP transport —
|
|
9
|
+
* no SSE event stream, no session resume. See `./streamable-http.ts` for
|
|
10
|
+
* that. Most clients that "speak HTTP" to MCP only need request/response,
|
|
11
|
+
* and starting with the simpler shape means zero new dependencies and a
|
|
12
|
+
* tiny attack surface.
|
|
13
|
+
*/
|
|
14
|
+
import type { buildHandler } from "./handler.js";
|
|
15
|
+
export declare function startHttp(handler: ReturnType<typeof buildHandler>, port: number, authEnabled?: boolean): Promise<void>;
|
|
16
|
+
//# sourceMappingURL=http-transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-transport.d.ts","sourceRoot":"","sources":["../../src/mcp/http-transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAWH,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,cAAc,CAAC;AAyFjE,wBAAsB,SAAS,CAC7B,OAAO,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,EACxC,IAAI,EAAE,MAAM,EACZ,WAAW,UAAQ,GAClB,OAAO,CAAC,IAAI,CAAC,CA+Bf"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple JSON-RPC over HTTP transport for MCP.
|
|
3
|
+
*
|
|
4
|
+
* POST /mcp accepts a single JSON-RPC envelope and returns a single JSON
|
|
5
|
+
* response. GET /mcp returns server info — handy for health checks from a
|
|
6
|
+
* browser.
|
|
7
|
+
*
|
|
8
|
+
* Note: this is intentionally NOT a full MCP Streamable HTTP transport —
|
|
9
|
+
* no SSE event stream, no session resume. See `./streamable-http.ts` for
|
|
10
|
+
* that. Most clients that "speak HTTP" to MCP only need request/response,
|
|
11
|
+
* and starting with the simpler shape means zero new dependencies and a
|
|
12
|
+
* tiny attack surface.
|
|
13
|
+
*/
|
|
14
|
+
import { createServer, } from "node:http";
|
|
15
|
+
import { getAllAdapters, listCommands } from "../registry.js";
|
|
16
|
+
import { handleOAuthRoute, createOAuthMiddleware } from "./oauth.js";
|
|
17
|
+
import { VERSION } from "../constants.js";
|
|
18
|
+
import { DEFAULT_TOOL_NAMES } from "./tools.js";
|
|
19
|
+
const MAX_BODY = 1_048_576; // 1 MB
|
|
20
|
+
function writeJson(res, code, payload) {
|
|
21
|
+
res.writeHead(code, { "Content-Type": "application/json" });
|
|
22
|
+
res.end(JSON.stringify(payload));
|
|
23
|
+
}
|
|
24
|
+
function serveHealth(res) {
|
|
25
|
+
const adapterCount = getAllAdapters().length;
|
|
26
|
+
const commandCount = listCommands().length;
|
|
27
|
+
const defaultToolCount = DEFAULT_TOOL_NAMES.size;
|
|
28
|
+
let expandedCount = defaultToolCount;
|
|
29
|
+
for (const adapter of getAllAdapters()) {
|
|
30
|
+
expandedCount += Object.keys(adapter.commands).length;
|
|
31
|
+
}
|
|
32
|
+
writeJson(res, 200, {
|
|
33
|
+
status: "ok",
|
|
34
|
+
adapters: adapterCount,
|
|
35
|
+
commands: commandCount,
|
|
36
|
+
tools: { default: defaultToolCount, expanded: expandedCount },
|
|
37
|
+
version: VERSION,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
async function consumeBody(req, res) {
|
|
41
|
+
const chunks = [];
|
|
42
|
+
let bodySize = 0;
|
|
43
|
+
return await new Promise((resolve) => {
|
|
44
|
+
req.on("data", (chunk) => {
|
|
45
|
+
bodySize += chunk.length;
|
|
46
|
+
if (bodySize > MAX_BODY) {
|
|
47
|
+
writeJson(res, 413, {
|
|
48
|
+
jsonrpc: "2.0",
|
|
49
|
+
id: null,
|
|
50
|
+
error: { code: -32600, message: "Request too large" },
|
|
51
|
+
});
|
|
52
|
+
req.destroy();
|
|
53
|
+
resolve(null);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
chunks.push(chunk);
|
|
57
|
+
});
|
|
58
|
+
req.on("end", () => resolve(Buffer.concat(chunks)));
|
|
59
|
+
req.on("error", () => resolve(null));
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
async function dispatchPost(req, res, handler) {
|
|
63
|
+
const bodyBuf = await consumeBody(req, res);
|
|
64
|
+
if (!bodyBuf)
|
|
65
|
+
return;
|
|
66
|
+
const body = bodyBuf.toString("utf-8");
|
|
67
|
+
let parsed;
|
|
68
|
+
try {
|
|
69
|
+
parsed = JSON.parse(body);
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
writeJson(res, 400, {
|
|
73
|
+
jsonrpc: "2.0",
|
|
74
|
+
id: null,
|
|
75
|
+
error: { code: -32700, message: "Parse error" },
|
|
76
|
+
});
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
const response = await handler(parsed);
|
|
81
|
+
if (!response) {
|
|
82
|
+
res.writeHead(204);
|
|
83
|
+
res.end();
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
writeJson(res, 200, response);
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
90
|
+
writeJson(res, 500, {
|
|
91
|
+
jsonrpc: "2.0",
|
|
92
|
+
id: parsed.id ?? null,
|
|
93
|
+
error: { code: -32603, message: `Internal error: ${message}` },
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
export async function startHttp(handler, port, authEnabled = false) {
|
|
98
|
+
const oauthMiddleware = authEnabled ? createOAuthMiddleware() : null;
|
|
99
|
+
const server = createServer((req, res) => {
|
|
100
|
+
if (authEnabled && handleOAuthRoute(req, res))
|
|
101
|
+
return;
|
|
102
|
+
if (req.method === "GET" &&
|
|
103
|
+
(req.url === "/" || req.url === "/mcp" || req.url === "/health")) {
|
|
104
|
+
serveHealth(res);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (req.method !== "POST" || req.url !== "/mcp") {
|
|
108
|
+
writeJson(res, 404, { error: "POST /mcp" });
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (oauthMiddleware?.(req, res))
|
|
112
|
+
return;
|
|
113
|
+
void dispatchPost(req, res, handler);
|
|
114
|
+
});
|
|
115
|
+
await new Promise((resolve, reject) => {
|
|
116
|
+
server.once("error", reject);
|
|
117
|
+
server.listen(port, "127.0.0.1", () => {
|
|
118
|
+
server.off("error", reject);
|
|
119
|
+
resolve();
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
process.stderr.write(`unicli MCP server v${VERSION} — HTTP transport on http://127.0.0.1:${port}/mcp\n`);
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=http-transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-transport.js","sourceRoot":"","sources":["../../src/mcp/http-transport.ts"],"names":[],"mappings":"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"}
|