@xpufx/paseo-mcp-tools 0.1.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/LICENSE +21 -0
- package/README.md +84 -0
- package/client/__snapshots__/attribution.test.tsx.snap +170 -0
- package/client/commands.ts +113 -0
- package/client/mcp-query.tsx +39 -0
- package/client/pill.tsx +886 -0
- package/client/timeline.tsx +136 -0
- package/client/vendor/paseo-plugin-helper/command-center.ts +43 -0
- package/client/vendor/paseo-plugin-helper/components/AboutSection.tsx +493 -0
- package/client/vendor/paseo-plugin-helper/components/AttentionBeacon.tsx +250 -0
- package/client/vendor/paseo-plugin-helper/components/Badge.tsx +156 -0
- package/client/vendor/paseo-plugin-helper/components/Button.tsx +178 -0
- package/client/vendor/paseo-plugin-helper/components/Card.tsx +225 -0
- package/client/vendor/paseo-plugin-helper/components/CodeBlock.tsx +196 -0
- package/client/vendor/paseo-plugin-helper/components/Collapsible.tsx +277 -0
- package/client/vendor/paseo-plugin-helper/components/CommandBox.tsx +172 -0
- package/client/vendor/paseo-plugin-helper/components/CopyButton.tsx +180 -0
- package/client/vendor/paseo-plugin-helper/components/DataTable.tsx +200 -0
- package/client/vendor/paseo-plugin-helper/components/EmptyState.tsx +97 -0
- package/client/vendor/paseo-plugin-helper/components/HighlightedText.tsx +70 -0
- package/client/vendor/paseo-plugin-helper/components/InlineButton.tsx +73 -0
- package/client/vendor/paseo-plugin-helper/components/KeyValue.tsx +446 -0
- package/client/vendor/paseo-plugin-helper/components/MetricGauge.tsx +247 -0
- package/client/vendor/paseo-plugin-helper/components/ProgressBar.tsx +117 -0
- package/client/vendor/paseo-plugin-helper/components/Responsive.tsx +53 -0
- package/client/vendor/paseo-plugin-helper/components/SearchInput.tsx +118 -0
- package/client/vendor/paseo-plugin-helper/components/SectionHeader.tsx +80 -0
- package/client/vendor/paseo-plugin-helper/components/Select.tsx +215 -0
- package/client/vendor/paseo-plugin-helper/components/StatusDot.tsx +80 -0
- package/client/vendor/paseo-plugin-helper/components/Tabs.tsx +319 -0
- package/client/vendor/paseo-plugin-helper/components/TextInput.tsx +150 -0
- package/client/vendor/paseo-plugin-helper/components/Toggle.tsx +163 -0
- package/client/vendor/paseo-plugin-helper/components/TruncatedText.tsx +157 -0
- package/client/vendor/paseo-plugin-helper/components/index.ts +25 -0
- package/client/vendor/paseo-plugin-helper/custom-pills.tsx +224 -0
- package/client/vendor/paseo-plugin-helper/forge-icon.tsx +79 -0
- package/client/vendor/paseo-plugin-helper/host.ts +277 -0
- package/client/vendor/paseo-plugin-helper/icon.tsx +39 -0
- package/client/vendor/paseo-plugin-helper/index.ts +28 -0
- package/client/vendor/paseo-plugin-helper/layout/ActionBar.tsx +49 -0
- package/client/vendor/paseo-plugin-helper/layout/FormRow.tsx +103 -0
- package/client/vendor/paseo-plugin-helper/layout/Grid.tsx +65 -0
- package/client/vendor/paseo-plugin-helper/layout/ModalBody.tsx +378 -0
- package/client/vendor/paseo-plugin-helper/layout/ModalContent.tsx +49 -0
- package/client/vendor/paseo-plugin-helper/layout/Row.tsx +39 -0
- package/client/vendor/paseo-plugin-helper/layout/Stack.tsx +39 -0
- package/client/vendor/paseo-plugin-helper/layout/index.ts +7 -0
- package/client/vendor/paseo-plugin-helper/panel.tsx +81 -0
- package/client/vendor/paseo-plugin-helper/pill.tsx +884 -0
- package/client/vendor/paseo-plugin-helper/query-refresh.ts +79 -0
- package/client/vendor/paseo-plugin-helper/query.ts +66 -0
- package/client/vendor/paseo-plugin-helper/settings-screen.tsx +372 -0
- package/client/vendor/paseo-plugin-helper/settings.ts +181 -0
- package/client/vendor/paseo-plugin-helper/shared-settings.ts +46 -0
- package/client/vendor/paseo-plugin-helper/snapshot.ts +68 -0
- package/client/vendor/paseo-plugin-helper/surface.tsx +80 -0
- package/client/vendor/paseo-plugin-helper/theme/color-utils.ts +118 -0
- package/client/vendor/paseo-plugin-helper/theme/flair.ts +76 -0
- package/client/vendor/paseo-plugin-helper/theme/host-variables.ts +121 -0
- package/client/vendor/paseo-plugin-helper/theme/index.ts +7 -0
- package/client/vendor/paseo-plugin-helper/theme/provider.tsx +214 -0
- package/client/vendor/paseo-plugin-helper/theme/responsive.ts +213 -0
- package/client/vendor/paseo-plugin-helper/theme/tokens.ts +161 -0
- package/client/vendor/paseo-plugin-helper/theme/useResponsive.ts +57 -0
- package/client/vendor/paseo-plugin-helper/utils/clipboard.ts +149 -0
- package/client/vendor/paseo-plugin-helper/utils/haptics.ts +34 -0
- package/docs/TEST_METHODOLOGY.md +29 -0
- package/package.json +41 -0
- package/paseo-plugin.json +4 -0
- package/scripts/version.mjs +4 -0
- package/server/discovery/extract.ts +277 -0
- package/server/discovery/types.ts +23 -0
- package/server/health/health.ts +274 -0
- package/server/inject.ts +32 -0
- package/server/mcp.ts +365 -0
- package/server/providers/README.md +51 -0
- package/server/providers/antigravity.ts +22 -0
- package/server/providers/catalog.ts +6 -0
- package/server/providers/claude.ts +21 -0
- package/server/providers/codex.ts +85 -0
- package/server/providers/family.ts +24 -0
- package/server/providers/index.ts +11 -0
- package/server/providers/opencode.ts +95 -0
- package/server/providers/paseo.ts +112 -0
- package/server/providers/pi.ts +39 -0
- package/server/settings.ts +19 -0
- package/server/vendor/paseo-plugin-helper/agent.ts +85 -0
- package/server/vendor/paseo-plugin-helper/custom-pills.ts +344 -0
- package/server/vendor/paseo-plugin-helper/index.ts +18 -0
- package/server/vendor/paseo-plugin-helper/jsonc.ts +78 -0
- package/server/vendor/paseo-plugin-helper/logger.ts +210 -0
- package/server/vendor/paseo-plugin-helper/mcp/client.ts +349 -0
- package/server/vendor/paseo-plugin-helper/mcp/http-client.ts +399 -0
- package/server/vendor/paseo-plugin-helper/mcp/index.ts +5 -0
- package/server/vendor/paseo-plugin-helper/mcp/process-killer.ts +65 -0
- package/server/vendor/paseo-plugin-helper/mcp/ring-buffer.ts +29 -0
- package/server/vendor/paseo-plugin-helper/mcp/types.ts +41 -0
- package/server/vendor/paseo-plugin-helper/mcp-config.ts +367 -0
- package/server/vendor/paseo-plugin-helper/mcp-injection.ts +85 -0
- package/server/vendor/paseo-plugin-helper/network.ts +91 -0
- package/server/vendor/paseo-plugin-helper/plugins.ts +160 -0
- package/server/vendor/paseo-plugin-helper/process.ts +186 -0
- package/server/vendor/paseo-plugin-helper/redact.ts +86 -0
- package/server/vendor/paseo-plugin-helper/rpc-guard.ts +77 -0
- package/server/vendor/paseo-plugin-helper/settings.ts +97 -0
- package/server/vendor/paseo-plugin-helper/shared-settings.ts +243 -0
- package/server/vendor/paseo-plugin-helper/storage.ts +244 -0
- package/server/vendor/paseo-plugin-helper/system.ts +128 -0
- package/server/vendor/paseo-plugin-helper/task.ts +116 -0
- package/server/vendor/paseo-plugin-helper/version.ts +153 -0
- package/server/vendor/paseo-plugin-helper/workspace-beacon.ts +418 -0
- package/shared/mcp.ts +207 -0
- package/shared/vendor/paseo-plugin-helper/README.md +11 -0
- package/shared/vendor/paseo-plugin-helper/async.ts +35 -0
- package/shared/vendor/paseo-plugin-helper/custom-pills.ts +169 -0
- package/shared/vendor/paseo-plugin-helper/forge.ts +110 -0
- package/shared/vendor/paseo-plugin-helper/formatters.ts +271 -0
- package/shared/vendor/paseo-plugin-helper/highlight.ts +184 -0
- package/shared/vendor/paseo-plugin-helper/index.ts +10 -0
- package/shared/vendor/paseo-plugin-helper/rpc.ts +72 -0
- package/shared/vendor/paseo-plugin-helper/settings.ts +138 -0
- package/shared/vendor/paseo-plugin-helper/suite-settings.ts +17 -0
- package/shared/vendor/paseo-plugin-helper/suppressed.ts +31 -0
- package/shared/vendor/paseo-plugin-helper/types.ts +36 -0
- package/shared/version.ts +2 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 xpufx
|
|
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,84 @@
|
|
|
1
|
+
# paseo-mcp-tools plugin
|
|
2
|
+
|
|
3
|
+
> **⚠️ WIP — use at your own risk.** Not release-ready; APIs and behavior may change without notice.
|
|
4
|
+
|
|
5
|
+
Provides an inline UI for checking MCP servers available to an agent session with additional functionality per MCP, such as listing and directly executing MCP tools with auto-generated input forms. Uses the most authoritative list per provider CLI and verifies actual session inclusion with live probes.
|
|
6
|
+
|
|
7
|
+
(**Paseo** is an agent orchestrator: AI coding agents run on paseo daemons, each managing workspaces, tools, and permissions.)
|
|
8
|
+
|
|
9
|
+
Built on [paseo-plugin-helper](https://github.com/xpufx/paseo/tree/main/packages/paseo-plugin-helper), the shared Paseo plugin runtime.
|
|
10
|
+
|
|
11
|
+
## Screenshots
|
|
12
|
+
|
|
13
|
+
| MCP Servers | Diagnostics | Settings |
|
|
14
|
+
| :---: | :---: | :---: |
|
|
15
|
+
| <img src="screenshots/mcp-servers.png" width="100%" alt="MCP Servers" /> | <img src="screenshots/mcp-diagnostic.png" width="100%" alt="Diagnostics" /> | <img src="screenshots/mcp-settings.png" width="100%" alt="Settings" /> |
|
|
16
|
+
|
|
17
|
+
| Server Details | Tool Execution |
|
|
18
|
+
| :---: | :---: |
|
|
19
|
+
| <img src="screenshots/mcp-server-details.png" width="100%" alt="Server Details" /> | <img src="screenshots/mcp-execute.png" width="100%" alt="Tool Execution" /> |
|
|
20
|
+
|
|
21
|
+
## What it does
|
|
22
|
+
|
|
23
|
+
- **Pill** above the composer shows `MCP n` (live servers for that agent). Badge updates via `mcp.list`, shared between pill and modal.
|
|
24
|
+
- **Live discovery** per-CLI via isolated `providers/<id>.ts` (`opencode` → `opencode mcp list`, `claude` → `~/.claude.json` live, `antigravity` → `~/.gemini/config/mcp_config.json`, etc.) + Paseo-injected `StoredAgentRecord.mcpServers`. Groups by `source.label`, dedupes by name.
|
|
25
|
+
- **Paseo Built-in Host MCP**: Automatically discovers Paseo's host daemon control plane (`/mcp/agents?callerAgentId=...`) as a first-class MCP server (`Paseo (Builtin)`), exposing all 60+ live tools (workspaces, browser automation, schedules, terminals, agent orchestration).
|
|
26
|
+
- **Detail & Live Health**: Server tap reveals real-time status dots, latency, server instructions, and full tool declarations.
|
|
27
|
+
- **Interactive Tool Runner (User Execution)**: Users can execute any discovered MCP tool directly from the UI without prompting the agent. Features a dynamic schema-driven form with `*REQUIRED` validation, type coercion (boolean, number, object, array, union/nullable types), live tool execution via host RPC (`mcp.call_tool`), and output inspection with 1-tap clipboard copying.
|
|
28
|
+
- **Real-Time Tool Search**: Server Detail view features a real-time search input filtering across tool names and descriptions, making servers with large command sets (like Paseo, Forgejo, Chrome DevTools) fast and easy to navigate.
|
|
29
|
+
- **Diagnostics**: Full polymorphic probe checklist verifying paths, permissions, and agent records across hosts.
|
|
30
|
+
|
|
31
|
+
## Supported Providers
|
|
32
|
+
|
|
33
|
+
| Provider | Probe Mechanism | Status |
|
|
34
|
+
|---|---|---|
|
|
35
|
+
| **Paseo** (`paseo`) | Built-in host daemon MCP control plane (`~/.paseo/config.json` + live daemon HTTP session) | **Fully tested & verified (60+ tools)** |
|
|
36
|
+
| **Antigravity** (`antigravity`, `antigravity-acp`) | Global `~/.gemini/config/mcp_config.json` + `~/.antigravity/mcp_config.json` | **Fully tested & verified** |
|
|
37
|
+
| **OpenCode** (`opencode`) | Live `opencode mcp list` daemon CLI command + config | **Fully tested & verified** |
|
|
38
|
+
| **Pi** (`pi`) | User canonical `~/.pi/.mcp.json` / project overrides + heuristics | **Fully tested & verified** |
|
|
39
|
+
| **Claude** (`claude`) | User `~/.claude.json` / project `.claude.json` heuristics | **Tested against real active configs** *(without live subscription session)* |
|
|
40
|
+
| **CodeX** (`codex`) | Global `~/.codex/config.toml` / project `.codex/config.toml` | **Provided as-is** *(without guarantees)* |
|
|
41
|
+
|
|
42
|
+
## Dropping in New Providers
|
|
43
|
+
|
|
44
|
+
Adding a new tool/CLI probe (e.g. Cursor, Windsurf, Zed, Roo, Cline) is black-box and takes 2 simple steps:
|
|
45
|
+
1. Create `providers/<id>.ts` declaring candidate config paths using `discoverFromCandidates()` (or live CLI RPC) with `export default <id>Probe`.
|
|
46
|
+
2. Add a 1-line re-export to `providers/catalog.ts`: `export { default as <id> } from "./<id>";`.
|
|
47
|
+
|
|
48
|
+
See the complete step-by-step guide in the [write-mcp-provider skill](.agents/skills/write-mcp-provider/SKILL.md) (`.agents/skills/write-mcp-provider/SKILL.md`). Run `npm test` to automatically verify the probe satisfies the contract.
|
|
49
|
+
|
|
50
|
+
## Layout
|
|
51
|
+
|
|
52
|
+
| File | Owns |
|
|
53
|
+
|---|---|
|
|
54
|
+
| [`index.ts`](index.ts) | Wiring only: `handle(mcp.list)`, `handle(mcp.read)`, `handle(mcp.health)`, `handle(mcp.call_tool)`, `handle(mcp.diagnose)`, `addClientSide` |
|
|
55
|
+
| [`mcp.shared.ts`](mcp.shared.ts) | zod RPC contracts & shared types (`ToolInfoSchema`, `callMcpTool`, etc.) |
|
|
56
|
+
| [`mcp.server.ts`](mcp.server.ts) | `discoverLiveServers()`, tool runner execution bridge, and polymorphic diagnostic handlers |
|
|
57
|
+
| [`discovery/extract.ts`](discovery/extract.ts) | Universal heuristic MCP parser (JSON/JSONC, comments, trailing commas, URL safe) & candidate discovery |
|
|
58
|
+
| [`discovery/types.ts`](discovery/types.ts) | Core contracts (`McpProbe`, `ProbeContext`, `ProbeResult`) |
|
|
59
|
+
| [`providers/<id>.ts`](providers/) | Per-CLI live probe (isolated, contract `McpProbe`: `antigravity.ts`, `claude.ts`, etc.) |
|
|
60
|
+
| [`providers/paseo.ts`](providers/paseo.ts) | Dedicated host daemon probe discovering Paseo control plane & tools |
|
|
61
|
+
| [`providers/catalog.ts`](providers/catalog.ts) | 1-line re-export catalog for zero-boilerplate probe registration |
|
|
62
|
+
| [`health/health.server.ts`](health/health.server.ts) | Generic MCP SDK client (`instructions`, schema-aware `tools`, and `callMcpServerTool`) |
|
|
63
|
+
| [`mcp-query.client.tsx`](mcp-query.client.tsx) | `useMcpQuery` shared pill/modal, 30m timer + manual Refresh |
|
|
64
|
+
| [`pill.client.tsx`](pill.client.tsx) | Pill, modal, server details, diagnostics, real-time search, and interactive Tool Runner UI |
|
|
65
|
+
| [`scripts/version.mjs`](scripts/version.mjs) | Offline build-time version stamper (tag / beta-[hash]) |
|
|
66
|
+
| [`docs/TEST_METHODOLOGY.md`](docs/TEST_METHODOLOGY.md) | Test procedures, adapter verification, and QA methodology |
|
|
67
|
+
|
|
68
|
+
## Install & Updates
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# from git (recommended)
|
|
72
|
+
paseo plugin add xpufx/paseo-mcp-tools
|
|
73
|
+
|
|
74
|
+
# update to latest release
|
|
75
|
+
paseo plugin update mcp-tools
|
|
76
|
+
|
|
77
|
+
# or from a local checkout (path-linked for development)
|
|
78
|
+
paseo plugin install "$PWD"
|
|
79
|
+
|
|
80
|
+
# reload daemon process after local edits
|
|
81
|
+
paseo plugin reload mcp-tools
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
`pluginsEnabled: true` required. Use `paseo plugin logs mcp-tools` for diagnostics and runtime logs. Failed reload stays failed (Paseo doesn't restore).
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`attribution labels on shared surfaces > labels the MCP tool call card 1`] = `
|
|
4
|
+
<View
|
|
5
|
+
style={
|
|
6
|
+
{
|
|
7
|
+
"alignItems": "center",
|
|
8
|
+
"flexDirection": "row",
|
|
9
|
+
"gap": 8,
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
>
|
|
13
|
+
<Text
|
|
14
|
+
style={
|
|
15
|
+
{
|
|
16
|
+
"color": "#00aa00",
|
|
17
|
+
"fontSize": 13,
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
>
|
|
21
|
+
●
|
|
22
|
+
</Text>
|
|
23
|
+
<View
|
|
24
|
+
style={
|
|
25
|
+
{
|
|
26
|
+
"flex": 1,
|
|
27
|
+
"minWidth": 0,
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
>
|
|
31
|
+
<Text
|
|
32
|
+
numberOfLines={1}
|
|
33
|
+
style={
|
|
34
|
+
{
|
|
35
|
+
"color": "#000000",
|
|
36
|
+
"fontFamily": "monospace",
|
|
37
|
+
"fontSize": 13,
|
|
38
|
+
"fontWeight": "600",
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
>
|
|
42
|
+
forgejo
|
|
43
|
+
__
|
|
44
|
+
list_branches
|
|
45
|
+
</Text>
|
|
46
|
+
<Text
|
|
47
|
+
style={
|
|
48
|
+
{
|
|
49
|
+
"color": "#666666",
|
|
50
|
+
"fontSize": 11,
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
>
|
|
54
|
+
MCP tool call
|
|
55
|
+
completed
|
|
56
|
+
</Text>
|
|
57
|
+
<ViaMcpTools
|
|
58
|
+
colors={
|
|
59
|
+
{
|
|
60
|
+
"foreground": "#000000",
|
|
61
|
+
"foregroundMuted": "#666666",
|
|
62
|
+
"statusDanger": "#ff0000",
|
|
63
|
+
"statusSuccess": "#00aa00",
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/>
|
|
67
|
+
</View>
|
|
68
|
+
</View>
|
|
69
|
+
`;
|
|
70
|
+
|
|
71
|
+
exports[`attribution labels on shared surfaces > labels the health digest card 1`] = `
|
|
72
|
+
<View
|
|
73
|
+
style={
|
|
74
|
+
{
|
|
75
|
+
"gap": 2,
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
>
|
|
79
|
+
<Text
|
|
80
|
+
style={
|
|
81
|
+
{
|
|
82
|
+
"color": "#000000",
|
|
83
|
+
"fontSize": 13,
|
|
84
|
+
"fontWeight": "600",
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
>
|
|
88
|
+
MCP fleet health:
|
|
89
|
+
3 healthy / 0 degraded / 1 down of 4
|
|
90
|
+
</Text>
|
|
91
|
+
<Text
|
|
92
|
+
style={
|
|
93
|
+
{
|
|
94
|
+
"color": "#666666",
|
|
95
|
+
"fontSize": 11,
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
>
|
|
99
|
+
Checked
|
|
100
|
+
2026-09-06T00:00:00.000Z
|
|
101
|
+
</Text>
|
|
102
|
+
<ViaMcpTools
|
|
103
|
+
colors={
|
|
104
|
+
{
|
|
105
|
+
"foreground": "#000000",
|
|
106
|
+
"foregroundMuted": "#666666",
|
|
107
|
+
"statusDanger": "#ff0000",
|
|
108
|
+
"statusSuccess": "#00aa00",
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/>
|
|
112
|
+
</View>
|
|
113
|
+
`;
|
|
114
|
+
|
|
115
|
+
exports[`attribution labels on shared surfaces > labels the slash result card 1`] = `
|
|
116
|
+
<View
|
|
117
|
+
style={
|
|
118
|
+
{
|
|
119
|
+
"gap": 4,
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
>
|
|
123
|
+
<Text
|
|
124
|
+
style={
|
|
125
|
+
{
|
|
126
|
+
"color": "#000000",
|
|
127
|
+
"fontSize": 13,
|
|
128
|
+
"fontWeight": "600",
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
>
|
|
132
|
+
MCP probe
|
|
133
|
+
</Text>
|
|
134
|
+
<Text
|
|
135
|
+
selectable={true}
|
|
136
|
+
style={
|
|
137
|
+
{
|
|
138
|
+
"color": "#000000",
|
|
139
|
+
"fontFamily": "monospace",
|
|
140
|
+
"fontSize": 12,
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
>
|
|
144
|
+
4 servers
|
|
145
|
+
</Text>
|
|
146
|
+
<ViaMcpTools
|
|
147
|
+
colors={
|
|
148
|
+
{
|
|
149
|
+
"foreground": "#000000",
|
|
150
|
+
"foregroundMuted": "#666666",
|
|
151
|
+
"statusDanger": "#ff0000",
|
|
152
|
+
"statusSuccess": "#00aa00",
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/>
|
|
156
|
+
</View>
|
|
157
|
+
`;
|
|
158
|
+
|
|
159
|
+
exports[`attribution labels on shared surfaces > labels the via footer 1`] = `
|
|
160
|
+
<Text
|
|
161
|
+
style={
|
|
162
|
+
{
|
|
163
|
+
"color": "#666666",
|
|
164
|
+
"fontSize": 10,
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
>
|
|
168
|
+
via mcp-tools
|
|
169
|
+
</Text>
|
|
170
|
+
`;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { PluginAgentCommandContext, PluginClientContext } from "@getpaseo/plugin/client";
|
|
2
|
+
import { buildHealthDigest } from "../shared/mcp";
|
|
3
|
+
import { callMcpTool, checkMcpHealth, listMcp } from "../shared/mcp";
|
|
4
|
+
|
|
5
|
+
function truncate(text: string, maxLength: number): string {
|
|
6
|
+
if (text.length <= maxLength) return text;
|
|
7
|
+
return `${text.slice(0, maxLength)}... (truncated)`;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async function appendSlashResult(
|
|
11
|
+
ctx: PluginAgentCommandContext,
|
|
12
|
+
title: string,
|
|
13
|
+
body: string,
|
|
14
|
+
): Promise<void> {
|
|
15
|
+
await ctx.paseo.agents.ref(ctx.agent.id).timeline.append({
|
|
16
|
+
type: "plugin",
|
|
17
|
+
id: "mcp-slash",
|
|
18
|
+
kind: "mcp-slash-result",
|
|
19
|
+
version: 1,
|
|
20
|
+
data: { title, body: truncate(body, 4000) },
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function registerMcpCommands(client: PluginClientContext): () => void {
|
|
25
|
+
const removers = [
|
|
26
|
+
client.addSlashCommand({
|
|
27
|
+
name: "mcp",
|
|
28
|
+
description: "Probe servers, check health, or run an MCP tool",
|
|
29
|
+
argumentHint: "[probe|health [server]|run server tool [json-args]]",
|
|
30
|
+
context: "agent",
|
|
31
|
+
async onSubmit(ctx) {
|
|
32
|
+
const { args, agent, paseo, rpc } = ctx;
|
|
33
|
+
const agentId = agent.id;
|
|
34
|
+
const [sub, ...rest] = args.trim().split(/\s+/);
|
|
35
|
+
try {
|
|
36
|
+
if (!sub || sub === "probe") {
|
|
37
|
+
const res = await rpc(listMcp, { agentId });
|
|
38
|
+
await appendSlashResult(
|
|
39
|
+
ctx,
|
|
40
|
+
"MCP probe",
|
|
41
|
+
`${res.servers.length} server(s) via ${res.provider}: ${res.servers.map((s) => s.name).join(", ") || "none"}`,
|
|
42
|
+
);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (sub === "health") {
|
|
46
|
+
const filter = rest[0]?.toLowerCase();
|
|
47
|
+
const res = await rpc(checkMcpHealth, { agentId });
|
|
48
|
+
const rows = filter
|
|
49
|
+
? res.results.filter((r) => r.name.toLowerCase().includes(filter))
|
|
50
|
+
: res.results;
|
|
51
|
+
const counts = {
|
|
52
|
+
healthy: rows.filter((r) => r.status === "healthy").length,
|
|
53
|
+
degraded: rows.filter((r) => r.status === "degraded").length,
|
|
54
|
+
down: rows.filter((r) => r.status === "down").length,
|
|
55
|
+
total: rows.length,
|
|
56
|
+
};
|
|
57
|
+
await paseo.agents.ref(agentId).timeline.append({
|
|
58
|
+
type: "plugin",
|
|
59
|
+
id: "mcp-health",
|
|
60
|
+
kind: "mcp-health-digest",
|
|
61
|
+
version: 1,
|
|
62
|
+
data: buildHealthDigest(counts),
|
|
63
|
+
});
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (sub === "run") {
|
|
67
|
+
const [serverRef, toolName, ...argParts] = rest;
|
|
68
|
+
const list = await rpc(listMcp, { agentId });
|
|
69
|
+
const server = list.servers.find((s) => s.id === serverRef || s.name === serverRef);
|
|
70
|
+
if (!server || !toolName) {
|
|
71
|
+
await appendSlashResult(ctx, "MCP run", "Usage: /mcp run <server> <tool> [json-args]");
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
let parsed: Record<string, unknown> = {};
|
|
75
|
+
if (argParts.length > 0) {
|
|
76
|
+
try {
|
|
77
|
+
parsed = JSON.parse(argParts.join(" ")) as Record<string, unknown>;
|
|
78
|
+
} catch {
|
|
79
|
+
await appendSlashResult(ctx, "MCP run", "Arguments must be a JSON object.");
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const out = await rpc(callMcpTool, {
|
|
84
|
+
agentId,
|
|
85
|
+
serverId: server.id,
|
|
86
|
+
toolName,
|
|
87
|
+
arguments: parsed,
|
|
88
|
+
});
|
|
89
|
+
const text = out.content.map((c) => String((c as { text?: unknown }).text ?? JSON.stringify(c))).join("\n\n");
|
|
90
|
+
await appendSlashResult(ctx, `MCP run ${toolName}`, out.isError ? `Error:\n${text}` : text || "(empty result)");
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
await appendSlashResult(ctx, "MCP", "Usage: /mcp [probe|health [server]|run server tool [json-args]]");
|
|
94
|
+
} catch (e) {
|
|
95
|
+
await appendSlashResult(ctx, "MCP error", e instanceof Error ? e.message : String(e));
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
}),
|
|
99
|
+
client.addCommandCenterItem({
|
|
100
|
+
id: "reprobe-mcp",
|
|
101
|
+
title: "Re-probe MCP servers",
|
|
102
|
+
icon: "Plug",
|
|
103
|
+
keywords: ["mcp", "refresh", "health"],
|
|
104
|
+
context: "agent",
|
|
105
|
+
async onSelect({ agent, rpc }) {
|
|
106
|
+
await rpc(listMcp, { agentId: agent.id });
|
|
107
|
+
},
|
|
108
|
+
}),
|
|
109
|
+
];
|
|
110
|
+
return () => {
|
|
111
|
+
removers.forEach((remove) => remove());
|
|
112
|
+
};
|
|
113
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { REFRESH_INTERVALS, useRpcQuery, type RefreshRate } from "paseo-plugin-helper/client";
|
|
2
|
+
import { checkMcpHealth, listMcp } from "../shared/mcp";
|
|
3
|
+
|
|
4
|
+
export function useMcpQuery(agentId: string) {
|
|
5
|
+
return useRpcQuery(listMcp, { agentId }, {
|
|
6
|
+
staleTime: 0,
|
|
7
|
+
gcTime: 5 * 60_000,
|
|
8
|
+
refetchOnMount: "always",
|
|
9
|
+
refetchOnWindowFocus: false,
|
|
10
|
+
enabled: Boolean(agentId),
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function useMcpHealthQuery(
|
|
15
|
+
agentId: string,
|
|
16
|
+
serverId: string | undefined,
|
|
17
|
+
opts: { isOpen?: boolean; rate?: RefreshRate } = {},
|
|
18
|
+
) {
|
|
19
|
+
const { isOpen = true, rate = "30s" } = opts;
|
|
20
|
+
const interval = !isOpen ? false : (REFRESH_INTERVALS[rate] ?? false);
|
|
21
|
+
return useRpcQuery(checkMcpHealth, { agentId, serverId }, {
|
|
22
|
+
staleTime: 0,
|
|
23
|
+
gcTime: 5 * 60_000,
|
|
24
|
+
refetchOnMount: "always",
|
|
25
|
+
refetchOnWindowFocus: false,
|
|
26
|
+
refetchInterval: interval,
|
|
27
|
+
enabled: isOpen && Boolean(agentId),
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function countServers(data: { servers: Array<unknown>; paseoTools: Array<unknown> } | undefined): number {
|
|
32
|
+
if (!data) return 0;
|
|
33
|
+
return data.servers.length + data.paseoTools.length;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function countMcpOnly(data: { servers: Array<unknown> } | undefined): number {
|
|
37
|
+
if (!data) return 0;
|
|
38
|
+
return data.servers.length;
|
|
39
|
+
}
|