@docyrus/docyrus 0.0.19 → 0.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/agent-loader.js +37 -3
  2. package/agent-loader.js.map +2 -2
  3. package/main.js +498 -93
  4. package/main.js.map +4 -4
  5. package/package.json +14 -4
  6. package/resources/chrome-tools/browser-content.js +103 -0
  7. package/resources/chrome-tools/browser-cookies.js +35 -0
  8. package/resources/chrome-tools/browser-eval.js +53 -0
  9. package/resources/chrome-tools/browser-hn-scraper.js +108 -0
  10. package/resources/chrome-tools/browser-nav.js +44 -0
  11. package/resources/chrome-tools/browser-pick.js +162 -0
  12. package/resources/chrome-tools/browser-screenshot.js +34 -0
  13. package/resources/chrome-tools/browser-start.js +86 -0
  14. package/resources/pi-agent/extensions/answer.ts +532 -0
  15. package/resources/pi-agent/extensions/context.ts +578 -0
  16. package/resources/pi-agent/extensions/control.ts +1779 -0
  17. package/resources/pi-agent/extensions/diff.ts +218 -0
  18. package/resources/pi-agent/extensions/files.ts +199 -0
  19. package/resources/pi-agent/extensions/loop.ts +446 -0
  20. package/resources/pi-agent/extensions/multi-edit.ts +835 -0
  21. package/resources/pi-agent/extensions/notify.ts +88 -0
  22. package/resources/pi-agent/extensions/pi-mcp-adapter/CHANGELOG.md +192 -0
  23. package/resources/pi-agent/extensions/pi-mcp-adapter/LICENSE +21 -0
  24. package/resources/pi-agent/extensions/pi-mcp-adapter/README.md +296 -0
  25. package/resources/pi-agent/extensions/pi-mcp-adapter/app-bridge.bundle.js +67 -0
  26. package/resources/pi-agent/extensions/pi-mcp-adapter/cli.js +108 -0
  27. package/resources/pi-agent/extensions/pi-mcp-adapter/commands.ts +211 -0
  28. package/resources/pi-agent/extensions/pi-mcp-adapter/config.ts +227 -0
  29. package/resources/pi-agent/extensions/pi-mcp-adapter/consent-manager.ts +64 -0
  30. package/resources/pi-agent/extensions/pi-mcp-adapter/direct-tools.ts +301 -0
  31. package/resources/pi-agent/extensions/pi-mcp-adapter/errors.ts +219 -0
  32. package/resources/pi-agent/extensions/pi-mcp-adapter/glimpse-ui.ts +80 -0
  33. package/resources/pi-agent/extensions/pi-mcp-adapter/host-html-template.ts +427 -0
  34. package/resources/pi-agent/extensions/pi-mcp-adapter/index.ts +232 -0
  35. package/resources/pi-agent/extensions/pi-mcp-adapter/init.ts +319 -0
  36. package/resources/pi-agent/extensions/pi-mcp-adapter/lifecycle.ts +93 -0
  37. package/resources/pi-agent/extensions/pi-mcp-adapter/logger.ts +169 -0
  38. package/resources/pi-agent/extensions/pi-mcp-adapter/mcp-panel.ts +713 -0
  39. package/resources/pi-agent/extensions/pi-mcp-adapter/metadata-cache.ts +191 -0
  40. package/resources/pi-agent/extensions/pi-mcp-adapter/npx-resolver.ts +419 -0
  41. package/resources/pi-agent/extensions/pi-mcp-adapter/oauth-handler.ts +56 -0
  42. package/resources/pi-agent/extensions/pi-mcp-adapter/package.json +85 -0
  43. package/resources/pi-agent/extensions/pi-mcp-adapter/paths.ts +29 -0
  44. package/resources/pi-agent/extensions/pi-mcp-adapter/proxy-modes.ts +635 -0
  45. package/resources/pi-agent/extensions/pi-mcp-adapter/resource-tools.ts +17 -0
  46. package/resources/pi-agent/extensions/pi-mcp-adapter/server-manager.ts +330 -0
  47. package/resources/pi-agent/extensions/pi-mcp-adapter/state.ts +41 -0
  48. package/resources/pi-agent/extensions/pi-mcp-adapter/tool-metadata.ts +144 -0
  49. package/resources/pi-agent/extensions/pi-mcp-adapter/tool-registrar.ts +46 -0
  50. package/resources/pi-agent/extensions/pi-mcp-adapter/types.ts +367 -0
  51. package/resources/pi-agent/extensions/pi-mcp-adapter/ui-resource-handler.ts +145 -0
  52. package/resources/pi-agent/extensions/pi-mcp-adapter/ui-server.ts +623 -0
  53. package/resources/pi-agent/extensions/pi-mcp-adapter/ui-session.ts +384 -0
  54. package/resources/pi-agent/extensions/pi-mcp-adapter/ui-stream-types.ts +89 -0
  55. package/resources/pi-agent/extensions/pi-mcp-adapter/utils.ts +75 -0
  56. package/resources/pi-agent/extensions/prompt-editor.ts +1315 -0
  57. package/resources/pi-agent/extensions/prompt-url-widget.ts +158 -0
  58. package/resources/pi-agent/extensions/redraws.ts +24 -0
  59. package/resources/pi-agent/extensions/review.ts +2160 -0
  60. package/resources/pi-agent/extensions/todos.ts +2076 -0
  61. package/resources/pi-agent/extensions/tps.ts +47 -0
  62. package/resources/pi-agent/extensions/whimsical.ts +474 -0
  63. package/resources/pi-agent/prompts/coder-system.md +106 -0
  64. package/resources/pi-agent/skills/changelog-generator/SKILL.md +425 -0
  65. package/resources/pi-agent/skills/docyrus-chrome-devtools-cli/SKILL.md +80 -0
  66. package/resources/pi-agent/skills/docyrus-platform/SKILL.md +71 -0
  67. package/resources/pi-agent/skills/docyrus-platform/references/ai-capabilities.md +43 -0
  68. package/resources/pi-agent/skills/docyrus-platform/references/auth-and-multi-tenancy.md +35 -0
  69. package/resources/pi-agent/skills/docyrus-platform/references/automation-and-workflows.md +30 -0
  70. package/resources/pi-agent/skills/docyrus-platform/references/core-building-blocks.md +53 -0
  71. package/resources/pi-agent/skills/{docyrus-api-dev → docyrus-platform}/references/data-source-query-guide.md +32 -28
  72. package/resources/pi-agent/skills/docyrus-platform/references/developer-tools.md +28 -0
  73. package/resources/pi-agent/skills/docyrus-platform/references/docyrus-cli-usage.md +554 -0
  74. package/resources/pi-agent/skills/{docyrus-api-dev → docyrus-platform}/references/formula-design-guide-llm.md +15 -23
  75. package/resources/pi-agent/skills/docyrus-platform/references/integrations-and-events.md +60 -0
  76. package/resources/pi-agent/skills/docyrus-platform/references/platform-services.md +58 -0
  77. package/resources/pi-agent/skills/docyrus-platform/references/querying-and-data-operations.md +27 -0
  78. package/resources/pi-agent/prompts/coder-append-system.md +0 -19
  79. package/resources/pi-agent/skills/docyrus-ai/SKILL.md +0 -28
  80. package/resources/pi-agent/skills/docyrus-api-dev/SKILL.md +0 -161
  81. package/resources/pi-agent/skills/docyrus-api-dev/references/api-client.md +0 -349
  82. package/resources/pi-agent/skills/docyrus-api-dev/references/authentication.md +0 -238
  83. package/resources/pi-agent/skills/docyrus-api-dev/references/query-and-formulas.md +0 -592
  84. package/resources/pi-agent/skills/docyrus-api-doctor/SKILL.md +0 -70
  85. package/resources/pi-agent/skills/docyrus-api-doctor/references/checklist-details.md +0 -588
  86. package/resources/pi-agent/skills/docyrus-app-dev/SKILL.md +0 -159
  87. package/resources/pi-agent/skills/docyrus-app-dev/references/api-client-and-auth.md +0 -275
  88. package/resources/pi-agent/skills/docyrus-app-dev/references/collections-and-patterns.md +0 -352
  89. package/resources/pi-agent/skills/docyrus-app-dev/references/data-source-query-guide.md +0 -2059
  90. package/resources/pi-agent/skills/docyrus-app-dev/references/formula-design-guide-llm.md +0 -320
  91. package/resources/pi-agent/skills/docyrus-app-dev/references/query-guide.md +0 -525
  92. package/resources/pi-agent/skills/docyrus-app-ui-design/SKILL.md +0 -466
  93. package/resources/pi-agent/skills/docyrus-app-ui-design/references/component-selection-guide.md +0 -602
  94. package/resources/pi-agent/skills/docyrus-app-ui-design/references/icon-usage-guide.md +0 -463
  95. package/resources/pi-agent/skills/docyrus-app-ui-design/references/preferred-components-catalog.md +0 -242
  96. package/resources/pi-agent/skills/docyrus-apps/SKILL.md +0 -54
  97. package/resources/pi-agent/skills/docyrus-architect/SKILL.md +0 -174
  98. package/resources/pi-agent/skills/docyrus-architect/references/custom-query-guide.md +0 -410
  99. package/resources/pi-agent/skills/docyrus-architect/references/data-source-query-guide.md +0 -2059
  100. package/resources/pi-agent/skills/docyrus-architect/references/formula-design-guide-llm.md +0 -320
  101. package/resources/pi-agent/skills/docyrus-architect/references/formula-reference.md +0 -145
  102. package/resources/pi-agent/skills/docyrus-auth/SKILL.md +0 -100
  103. package/resources/pi-agent/skills/docyrus-cli-app/SKILL.md +0 -279
  104. package/resources/pi-agent/skills/docyrus-cli-app/references/cli-manifest.md +0 -532
  105. package/resources/pi-agent/skills/docyrus-cli-app/references/list-query-examples.md +0 -248
  106. package/resources/pi-agent/skills/docyrus-curl/SKILL.md +0 -32
  107. package/resources/pi-agent/skills/docyrus-discover/SKILL.md +0 -63
  108. package/resources/pi-agent/skills/docyrus-ds/SKILL.md +0 -95
  109. package/resources/pi-agent/skills/docyrus-env/SKILL.md +0 -21
  110. package/resources/pi-agent/skills/docyrus-studio/SKILL.md +0 -369
  111. package/resources/pi-agent/skills/docyrus-tui/SKILL.md +0 -15
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Desktop Notification Extension
3
+ *
4
+ * Sends a native desktop notification when the agent finishes and is waiting for input.
5
+ * Uses OSC 777 escape sequence - no external dependencies.
6
+ *
7
+ * Supported terminals: Ghostty, iTerm2, WezTerm, rxvt-unicode
8
+ * Not supported: Kitty (uses OSC 99), Terminal.app, Windows Terminal, Alacritty
9
+ */
10
+
11
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
12
+ import { Markdown, type MarkdownTheme } from "@mariozechner/pi-tui";
13
+
14
+ /**
15
+ * Send a desktop notification via OSC 777 escape sequence.
16
+ */
17
+ const notify = (title: string, body: string): void => {
18
+ // OSC 777 format: ESC ] 777 ; notify ; title ; body BEL
19
+ process.stdout.write(`\x1b]777;notify;${title};${body}\x07`);
20
+ };
21
+
22
+ const isTextPart = (part: unknown): part is { type: "text"; text: string } =>
23
+ Boolean(part && typeof part === "object" && "type" in part && part.type === "text" && "text" in part);
24
+
25
+ const extractLastAssistantText = (messages: Array<{ role?: string; content?: unknown }>): string | null => {
26
+ for (let i = messages.length - 1; i >= 0; i--) {
27
+ const message = messages[i];
28
+ if (message?.role !== "assistant") {
29
+ continue;
30
+ }
31
+
32
+ const content = message.content;
33
+ if (typeof content === "string") {
34
+ return content.trim() || null;
35
+ }
36
+
37
+ if (Array.isArray(content)) {
38
+ const text = content.filter(isTextPart).map((part) => part.text).join("\n").trim();
39
+ return text || null;
40
+ }
41
+
42
+ return null;
43
+ }
44
+
45
+ return null;
46
+ };
47
+
48
+ const plainMarkdownTheme: MarkdownTheme = {
49
+ heading: (text) => text,
50
+ link: (text) => text,
51
+ linkUrl: () => "",
52
+ code: (text) => text,
53
+ codeBlock: (text) => text,
54
+ codeBlockBorder: () => "",
55
+ quote: (text) => text,
56
+ quoteBorder: () => "",
57
+ hr: () => "",
58
+ listBullet: () => "",
59
+ bold: (text) => text,
60
+ italic: (text) => text,
61
+ strikethrough: (text) => text,
62
+ underline: (text) => text,
63
+ };
64
+
65
+ const simpleMarkdown = (text: string, width = 80): string => {
66
+ const markdown = new Markdown(text, 0, 0, plainMarkdownTheme);
67
+ return markdown.render(width).join("\n");
68
+ };
69
+
70
+ const formatNotification = (text: string | null): { title: string; body: string } => {
71
+ const simplified = text ? simpleMarkdown(text) : "";
72
+ const normalized = simplified.replace(/\s+/g, " ").trim();
73
+ if (!normalized) {
74
+ return { title: "Ready for input", body: "" };
75
+ }
76
+
77
+ const maxBody = 200;
78
+ const body = normalized.length > maxBody ? `${normalized.slice(0, maxBody - 1)}…` : normalized;
79
+ return { title: "π", body };
80
+ };
81
+
82
+ export default function (pi: ExtensionAPI) {
83
+ pi.on("agent_end", async (event) => {
84
+ const lastText = extractLastAssistantText(event.messages ?? []);
85
+ const { title, body } = formatNotification(lastText);
86
+ notify(title, body);
87
+ });
88
+ }
@@ -0,0 +1,192 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [2.2.0] - 2026-03-16
11
+
12
+ ### Added
13
+ - **MCP UI Integration** - Support for the [MCP UI](https://github.com/MCP-UI-Org/mcp-ui) standard. Tools with `_meta.ui.resourceUri` open interactive UIs:
14
+ - Bidirectional AppBridge communication (tool calls, messages, context updates)
15
+ - Works with both stdio and HTTP MCP servers
16
+ - User consent management for tool calls from UI (configurable: never/once-per-server/always)
17
+ - Keyboard shortcuts: Cmd/Ctrl+Enter to complete, Escape to cancel
18
+ - UI prompts/intents trigger agent turns via `pi.sendMessage({ triggerTurn: true })`
19
+ - `mcp({ action: "ui-messages" })` retrieves accumulated messages from UI sessions
20
+
21
+ - **Session reuse** - When the agent calls the same tool while its UI is already open, results push to the existing window instead of replacing it. Per-call stream IDs with independent sequences. Error results scoped to the individual call.
22
+
23
+ - **Glimpse integration** - MCP UI opens in a native macOS WKWebView window instead of a browser tab when [Glimpse](https://github.com/hazat/glimpse) is installed (`pi install npm:glimpseui`). Falls back to browser on non-macOS or when unavailable. Override with `MCP_UI_VIEWER=browser` or `MCP_UI_VIEWER=glimpse`.
24
+
25
+ - **Logger module** (`logger.ts`) - Centralized logging with levels (debug/info/warn/error), contextual child loggers, and `MCP_UI_DEBUG=1` env var.
26
+
27
+ - **Error types** (`errors.ts`) - Structured errors with recovery hints: `ResourceFetchError`, `ResourceParseError`, `BridgeConnectionError`, `ConsentError`, `SessionError`, `ServerError`, and `wrapError()` helper.
28
+
29
+ - **Test suite** - 178 tests covering consent manager, UI resource handler, host HTML template, logger, and error types.
30
+
31
+ - **Interactive visualizer example** (`examples/interactive-visualizer`) - Minimal MCP server demonstrating charts (bar/line/pie/doughnut via Chart.js), bidirectional messaging, and streaming.
32
+
33
+ ### Fixed
34
+ - Host-iframe timing: bridge now connects before loading iframe, fixing `ui/initialize` timeout on first load
35
+ - All internal `log.info` calls demoted to `log.debug` to eliminate stdout noise during normal use
36
+
37
+ ### Technical Notes
38
+ - Uses local minified AppBridge bundle (408KB) to avoid CDN Zod bundling issues
39
+ - Serves app HTML from `/ui-app` endpoint instead of blob URLs to avoid iframe issues
40
+ - SSE for real-time tool result streaming to browser
41
+
42
+ ## [2.1.2] - 2026-02-03
43
+
44
+ ### Changed
45
+ - Added demo video and `pi.video` field to package.json for pi package browser.
46
+
47
+ ## [2.1.0] - 2026-02-02
48
+
49
+ ### Added
50
+ - **Direct tool registration** - Promote specific MCP tools to first-class Pi tools via `directTools` config (per-server or global). Direct tools appear in the agent's tool list alongside builtins, so the LLM uses them without needing to search through the proxy first. Registers from cached metadata at startup — no server connections needed.
51
+ - **`/mcp` interactive panel** - New TUI overlay replacing the text-based status dump. Shows server connection status, tool lists with direct/proxy toggles, token cost estimates, inline reconnect, and auth notices. Changes written to config on save.
52
+ - **Auto-enriched proxy description** - The `mcp` proxy tool description now includes server names and tool counts from the metadata cache, so the LLM knows what's available without a search call (~30 extra tokens).
53
+ - **`MCP_DIRECT_TOOLS` env var** - Subagent processes receive their direct tool configuration via environment variable, keeping subagents lean by default.
54
+ - **First-run bootstrap** - Servers with `directTools` configured but no cache entry are connected during `session_start` to populate the cache. Direct tools become available after restart.
55
+ - Config provenance tracking for correct write-back to user/project/import sources
56
+ - Builtin name collision guard (skips direct tools that would shadow `read`, `write`, etc.)
57
+ - Cross-server name deduplication for `prefix: "none"` and `prefix: "short"` modes
58
+
59
+ ## [2.0.1] - 2026-02-01
60
+
61
+ ### Fixed
62
+ - Adapt execute signature to pi v0.51.0: add signal, onUpdate, ctx parameters
63
+
64
+ ## [2.0.0] - 2026-01-29
65
+
66
+ ### Changed
67
+ - **BREAKING: Lazy startup by default** - All servers now default to `lifecycle: "lazy"` and only connect when a tool call needs them. Previously all servers connected eagerly on session start. Set `lifecycle: "keep-alive"` or `lifecycle: "eager"` to restore the old behavior per-server.
68
+ - **Idle timeout** - Connected servers are automatically disconnected after 10 minutes of inactivity (configurable via `settings.idleTimeout` or per-server `idleTimeout`). Cached metadata keeps search/list working after disconnect. Set `idleTimeout: 0` to disable.
69
+ - `/mcp reconnect` accepts an optional server name to connect or reconnect a single server
70
+
71
+ ### Added
72
+ - **Metadata cache** - Tool and resource metadata persisted to `~/.pi/agent/mcp-cache.json`. Enables search/list/describe without live connections. Per-server config hashing with 7-day staleness. Multi-session safe via read-merge-write with per-process tmp files.
73
+ - **npx binary resolution** - Resolves npx package binaries to direct paths, eliminating the ~143 MB npm parent process per server. Persistent cache at `~/.pi/agent/mcp-npx-cache.json` with 24h TTL.
74
+ - **`mcp({ connect: "server-name" })` mode** - Explicitly trigger connection and metadata refresh for a named server
75
+ - **Failure backoff** - Servers that fail to connect are skipped for 60 seconds to avoid repeated connection storms
76
+ - **In-flight tracking** - Active tool calls prevent idle timeout from shutting down a server mid-request
77
+ - **Prefix-match fallback** - Tool calls with unrecognized names try to match a server prefix and lazy-connect the matching server
78
+ - Lifecycle options: `lazy` (default), `eager` (connect at startup, no auto-reconnect), `keep-alive` (unchanged)
79
+ - Per-server `idleTimeout` override and global `settings.idleTimeout`
80
+ - First-run bootstrap: connects all servers on first session to populate the cache
81
+
82
+ ### Fixed
83
+ - Connection close race condition: concurrent close + connect no longer orphans server processes
84
+ - **Fuzzy tool name matching** - Hyphens and underscores are treated as equivalent during tool lookup. MCP tools like `resolve-library-id` are now found when called as `resolve_library_id`, which LLMs naturally guess since the prefix separator is `_`.
85
+ - **Better "tool not found" errors** - When a server is identified (via prefix match or override) but the tool isn't found, the error now lists that server's available tools so the LLM can self-correct immediately instead of needing a separate list call
86
+
87
+ ## [1.6.0] - 2026-01-29
88
+
89
+ ### Added
90
+ - **Unified pi tool search** - `mcp({ search: "..." })` now searches both MCP tools and Pi tools (from installed extensions)
91
+ - Pi tools appear first in results with `[pi tool]` prefix
92
+ - Details object includes `server: "pi"` for pi tools
93
+ - Banner image for README
94
+
95
+ ## [1.5.1] - 2026-01-26
96
+
97
+ ### Changed
98
+ - Added `pi-package` keyword for npm discoverability (pi v0.50.0 package system)
99
+
100
+ ## [1.5.0] - 2026-01-22
101
+
102
+ ### Changed
103
+ - **BREAKING: `args` parameter is now a JSON string** - The `args` parameter which previously accepted an object now accepts a JSON string. This change was required for compatibility with Claude's Vertex AI API (`google-antigravity` provider) which rejects `patternProperties` in JSON schemas (generated by `Type.Record()`).
104
+
105
+ ### Added
106
+ - **Type validation for args** - Parsed args are now validated to ensure they're a JSON object (not null, array, or primitive). Clear error messages for invalid input.
107
+ - **`isError: true` on error responses** - JSON parse errors and type validation errors now properly set `isError: true` to indicate failure to the LLM.
108
+
109
+ ### Migration
110
+ ```typescript
111
+ // Before (1.4.x)
112
+ mcp({ tool: "my_tool", args: { key: "value" } })
113
+
114
+ // After (1.5.0)
115
+ mcp({ tool: "my_tool", args: '{"key": "value"}' })
116
+ ```
117
+
118
+ ## [1.4.1] - 2026-01-19
119
+
120
+ ### Changed
121
+
122
+ - Status bar shows server count instead of tool count ("MCP: 5 servers")
123
+
124
+ ## [1.4.0] - 2026-01-19
125
+
126
+ ### Changed
127
+
128
+ - **Non-blocking startup** - Pi starts immediately, MCP servers connect in background. First MCP call waits only if init isn't done yet.
129
+
130
+ ### Fixed
131
+
132
+ - Tool metadata now includes `inputSchema` after `/mcp reconnect` (was missing, breaking describe and error hints)
133
+
134
+ ## [1.3.0] - 2026-01-19
135
+
136
+ ### Changed
137
+
138
+ - **Parallel server connections** - All MCP servers now connect in parallel on startup instead of sequentially, significantly faster with many servers
139
+
140
+ ## [1.2.2] - 2026-01-19
141
+
142
+ ### Fixed
143
+
144
+ - Installer now downloads from `main` branch (renamed from `master`)
145
+
146
+ ## [1.2.1] - 2026-01-19
147
+
148
+ ### Added
149
+
150
+ - **npx installer** - Run `npx pi-mcp-adapter` to install (downloads files, installs deps, configures settings.json)
151
+
152
+ ## [1.1.0] - 2026-01-19
153
+
154
+ ### Changed
155
+
156
+ - **Search includes schemas by default** - Search results now include parameter schemas, reducing tool calls needed (search + call instead of search + describe + call)
157
+ - **Space-separated search terms match as OR** - `"navigate screenshot"` finds tools matching either word (like most search engines)
158
+ - **Suppress server stderr by default** - MCP server logs no longer clutter terminal on startup
159
+ - Use `includeSchemas: false` for compact output without schemas
160
+ - Use `debug: true` per-server to show stderr when troubleshooting
161
+
162
+ ## [1.0.0] - 2026-01-19
163
+
164
+ ### Added
165
+
166
+ - **Single unified `mcp` tool** with token-efficient architecture (~200 tokens vs ~15,000 for individual tools)
167
+ - **Five operation modes:**
168
+ - `mcp({})` - Show server status
169
+ - `mcp({ server: "name" })` - List tools from a server
170
+ - `mcp({ search: "query" })` - Search tools by name/description
171
+ - `mcp({ describe: "tool_name" })` - Show tool details and parameter schema
172
+ - `mcp({ tool: "name", args: {...} })` - Call a tool
173
+ - **Stdio transport** for local MCP servers (command + args)
174
+ - **HTTP transport** with automatic fallback (StreamableHTTP → SSE)
175
+ - **Config imports** from Cursor, Claude Code, Claude Desktop, VS Code, Windsurf, Codex
176
+ - **Resource tools** - MCP resources exposed as callable tools
177
+ - **OAuth support** - Token file-based authentication
178
+ - **Bearer token auth** - Static or environment variable tokens
179
+ - **Keep-alive connections** with automatic health checks and reconnection
180
+ - **Schema on-demand** - Parameter schemas shown in `describe` mode and error responses
181
+ - **Commands:**
182
+ - `/mcp` or `/mcp status` - Show server status
183
+ - `/mcp tools` - List all tools
184
+ - `/mcp reconnect` - Force reconnect all servers
185
+ - `/mcp-auth <server>` - Show OAuth setup instructions
186
+
187
+ ### Architecture
188
+
189
+ - Tools stored in metadata map, not registered individually with Pi
190
+ - MCP server validates arguments (no client-side schema conversion)
191
+ - Reconnect callback updates metadata after auto-reconnect
192
+ - Human-readable schema formatting for LLM consumption
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nico Bailon
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.
@@ -0,0 +1,296 @@
1
+ <p>
2
+ <img src="banner.png" alt="pi-mcp-adapter" width="1100">
3
+ </p>
4
+
5
+ # Pi MCP Adapter
6
+
7
+ Use MCP servers with [Pi](https://github.com/badlogic/pi-mono/) without burning your context window.
8
+
9
+ https://github.com/user-attachments/assets/4b7c66ff-e27e-4639-b195-22c3db406a5a
10
+
11
+ ## Why This Exists
12
+
13
+ Mario wrote about [why you might not need MCP](https://mariozechner.at/posts/2025-11-02-what-if-you-dont-need-mcp/). The problem: tool definitions are verbose. A single MCP server can burn 10k+ tokens, and you're paying that cost whether you use those tools or not. Connect a few servers and you've burned half your context window before the conversation starts.
14
+
15
+ His take: skip MCP entirely, write simple CLI tools instead.
16
+
17
+ But the MCP ecosystem has useful stuff - databases, browsers, APIs. This adapter gives you access without the bloat. One proxy tool (~200 tokens) instead of hundreds. The agent discovers what it needs on-demand. Servers only start when you actually use them.
18
+
19
+ ## Install
20
+
21
+ ```bash
22
+ pi install npm:pi-mcp-adapter
23
+ ```
24
+
25
+ Restart Pi after installation.
26
+
27
+ ## Quick Start
28
+
29
+ Create `~/.pi/agent/mcp.json`:
30
+
31
+ ```json
32
+ {
33
+ "mcpServers": {
34
+ "chrome-devtools": {
35
+ "command": "npx",
36
+ "args": ["-y", "chrome-devtools-mcp@latest"]
37
+ }
38
+ }
39
+ }
40
+ ```
41
+
42
+ Servers are **lazy by default** — they won't connect until you actually call one of their tools. The adapter caches tool metadata so search and describe work without live connections.
43
+
44
+ ```
45
+ mcp({ search: "screenshot" })
46
+ ```
47
+ ```
48
+ chrome_devtools_take_screenshot
49
+ Take a screenshot of the page or element.
50
+
51
+ Parameters:
52
+ format (enum: "png", "jpeg", "webp") [default: "png"]
53
+ fullPage (boolean) - Full page instead of viewport
54
+ ```
55
+ ```
56
+ mcp({ tool: "chrome_devtools_take_screenshot", args: '{"format": "png"}' })
57
+ ```
58
+
59
+ Note: `args` is a JSON string, not an object.
60
+
61
+ Two calls instead of 26 tools cluttering the context.
62
+
63
+ ## Config
64
+
65
+ ### Server Options
66
+
67
+ ```json
68
+ {
69
+ "mcpServers": {
70
+ "my-server": {
71
+ "command": "npx",
72
+ "args": ["-y", "some-mcp-server"],
73
+ "lifecycle": "lazy",
74
+ "idleTimeout": 10
75
+ }
76
+ }
77
+ }
78
+ ```
79
+
80
+ | Field | Description |
81
+ |-------|-------------|
82
+ | `command` | Executable for stdio transport |
83
+ | `args` | Command arguments |
84
+ | `env` | Environment variables (`${VAR}` interpolation) |
85
+ | `cwd` | Working directory |
86
+ | `url` | HTTP endpoint (StreamableHTTP with SSE fallback) |
87
+ | `auth` | `"bearer"` or `"oauth"` |
88
+ | `bearerToken` / `bearerTokenEnv` | Token or env var name |
89
+ | `lifecycle` | `"lazy"` (default), `"eager"`, or `"keep-alive"` |
90
+ | `idleTimeout` | Minutes before idle disconnect (overrides global) |
91
+ | `exposeResources` | Expose MCP resources as tools (default: true) |
92
+ | `directTools` | `true`, `string[]`, or `false` — register tools individually instead of through proxy |
93
+ | `debug` | Show server stderr (default: false) |
94
+
95
+ ### Lifecycle Modes
96
+
97
+ - **`lazy`** (default) — Don't connect at startup. Connect on first tool call. Disconnect after idle timeout. Cached metadata keeps search/list working without connections.
98
+ - **`eager`** — Connect at startup but don't auto-reconnect if the connection drops. No idle timeout by default (set `idleTimeout` explicitly to enable).
99
+ - **`keep-alive`** — Connect at startup. Auto-reconnect via health checks. No idle timeout. Use for servers you always need available.
100
+
101
+ ### Settings
102
+
103
+ ```json
104
+ {
105
+ "settings": {
106
+ "toolPrefix": "server",
107
+ "idleTimeout": 10
108
+ },
109
+ "mcpServers": { }
110
+ }
111
+ ```
112
+
113
+ | Setting | Description |
114
+ |---------|-------------|
115
+ | `toolPrefix` | `"server"` (default), `"short"` (strips `-mcp` suffix), or `"none"` |
116
+ | `idleTimeout` | Global idle timeout in minutes (default: 10, 0 to disable) |
117
+ | `directTools` | Global default for all servers (default: false). Per-server overrides this. |
118
+
119
+ Per-server `idleTimeout` overrides the global setting.
120
+
121
+ ### Direct Tools
122
+
123
+ By default, all MCP tools are accessed through the single `mcp` proxy tool. This keeps context small but means the LLM has to discover tools via search. If you want specific tools to show up directly in the agent's tool list — alongside `read`, `bash`, `edit`, etc. — add `directTools` to your config.
124
+
125
+ Per-server:
126
+
127
+ ```json
128
+ {
129
+ "mcpServers": {
130
+ "chrome-devtools": {
131
+ "command": "npx",
132
+ "args": ["-y", "chrome-devtools-mcp@latest"],
133
+ "directTools": true
134
+ },
135
+ "github": {
136
+ "command": "npx",
137
+ "args": ["-y", "@modelcontextprotocol/server-github"],
138
+ "directTools": ["search_repositories", "get_file_contents"]
139
+ },
140
+ "huge-server": {
141
+ "command": "npx",
142
+ "args": ["-y", "mega-mcp@latest"]
143
+ }
144
+ }
145
+ }
146
+ ```
147
+
148
+ | Value | Behavior |
149
+ |-------|----------|
150
+ | `true` | Register all tools from this server as individual Pi tools |
151
+ | `["tool_a", "tool_b"]` | Register only these tools (use original MCP names) |
152
+ | Omitted or `false` | Proxy only (default) |
153
+
154
+ To set a global default for all servers:
155
+
156
+ ```json
157
+ {
158
+ "settings": {
159
+ "directTools": true
160
+ },
161
+ "mcpServers": {
162
+ "huge-server": {
163
+ "directTools": false
164
+ }
165
+ }
166
+ }
167
+ ```
168
+
169
+ Per-server `directTools` overrides the global setting. The example above registers direct tools for every server except `huge-server`.
170
+
171
+ Each direct tool costs ~150-300 tokens in the system prompt (name + description + schema). Good for targeted sets of 5-20 tools. For servers with 75+ tools, stick with the proxy or pick specific tools with a `string[]`.
172
+
173
+ Direct tools register from the metadata cache (`~/.pi/agent/mcp-cache.json`), so no server connections are needed at startup. On the first session after adding `directTools` to a new server, the cache won't exist yet — tools fall back to proxy-only and the cache populates in the background. Restart Pi and they'll be available. To force it: `/mcp reconnect <server>` then restart.
174
+
175
+ **Interactive configuration:** Run `/mcp` to open an interactive panel showing all servers with connection status, tools, and direct/proxy toggles. You can reconnect servers, initiate OAuth, and toggle tools between direct and proxy — all from one overlay. Changes are written to your config file; restart Pi to apply.
176
+
177
+ **Subagent integration:** If you use the subagent extension, agents can request direct MCP tools in their frontmatter with `mcp:server-name` syntax. See the subagent README for details.
178
+
179
+ ### MCP UI Integration
180
+
181
+ MCP servers can ship interactive UIs via the [MCP UI](https://github.com/MCP-UI-Org/mcp-ui) standard. When you call a tool that has a UI resource, the adapter opens it in a native macOS window via [Glimpse](https://github.com/hazat/glimpse) if available, otherwise falls back to the browser.
182
+
183
+ **How it works:**
184
+
185
+ 1. Agent calls a tool like `launch_dashboard`
186
+ 2. The tool's metadata includes `_meta.ui.resourceUri` pointing to a UI resource
187
+ 3. pi-mcp-adapter fetches the UI HTML and opens it in an iframe
188
+ 4. The UI can call MCP tools and send messages back to the agent
189
+
190
+ **Native rendering:** On macOS, if [Glimpse](https://github.com/hazat/glimpse) is installed (`pi install npm:glimpseui`), UIs open in a native WKWebView window instead of a browser tab. Set `MCP_UI_VIEWER=browser` to force the browser, or `MCP_UI_VIEWER=glimpse` to require native rendering.
191
+
192
+ **Bidirectional communication:** The UI talks back. When it sends a prompt or intent, the message is stored and `triggerTurn()` wakes the agent. The agent retrieves messages via `mcp({ action: "ui-messages" })` and responds, enabling conversational UIs where the app and agent collaborate in real-time.
193
+
194
+ **Session reuse:** When the agent calls the same tool again while its UI is already open, the adapter pushes the new result to the existing window instead of replacing it. This enables live updates — the agent can refine a chart, add data, or respond to user input without losing the current view. Different tools still replace the session as before.
195
+
196
+ **Message types from UI:**
197
+
198
+ | Type | Purpose |
199
+ |------|---------|
200
+ | `prompt` | User message that triggers an agent response |
201
+ | `intent` | Structured action with name + params |
202
+ | `notify` | Fire-and-forget notification |
203
+ | `message` | Generic message payload |
204
+ | (custom) | Any other type forwarded as intent |
205
+
206
+ **Retrieving UI messages:**
207
+
208
+ ```
209
+ mcp({ action: "ui-messages" })
210
+ ```
211
+
212
+ Returns accumulated messages from UI sessions. Each message includes `type`, `sessionId`, `serverName`, `toolName`, and `timestamp`. Prompt messages include `prompt`, intent messages include `intent` and `params`.
213
+
214
+ **Browser controls:**
215
+
216
+ - **Cmd/Ctrl+Enter** — Complete and close
217
+ - **Escape** — Cancel and close
218
+ - **Done/Cancel buttons** — Same as keyboard shortcuts
219
+
220
+ **Technical notes:**
221
+
222
+ - Tool consent gates whether UIs can call MCP tools (never/once-per-server/always)
223
+ - Works with both stdio and HTTP MCP servers
224
+ - Uses a local 408KB AppBridge bundle (MCP SDK + Zod) for browser↔server communication
225
+
226
+ ### Local Example: Interactive Visualizer
227
+
228
+ A minimal MCP UI example at `examples/interactive-visualizer` demonstrating charts, bidirectional messaging, and streaming. From that directory:
229
+
230
+ ```bash
231
+ npm install
232
+ npm run build
233
+ npm run install-local
234
+ ```
235
+
236
+ Restart pi, then ask the agent to show a chart — it calls `show_chart` and opens the UI in Glimpse (macOS) or the browser. Use `npm run uninstall-local` to remove the MCP entry.
237
+
238
+ ### Import Existing Configs
239
+
240
+ Already have MCP set up elsewhere? Import it:
241
+
242
+ ```json
243
+ {
244
+ "imports": ["cursor", "claude-code", "claude-desktop"],
245
+ "mcpServers": { }
246
+ }
247
+ ```
248
+
249
+ Supported: `cursor`, `claude-code`, `claude-desktop`, `vscode`, `windsurf`, `codex`
250
+
251
+ ### Project Config
252
+
253
+ Add `.pi/mcp.json` in a project root for project-specific servers. Project config overrides global and imported servers.
254
+
255
+ ## Usage
256
+
257
+ | Mode | Example |
258
+ |------|---------|
259
+ | Status | `mcp({ })` |
260
+ | List server | `mcp({ server: "name" })` |
261
+ | Search | `mcp({ search: "screenshot navigate" })` |
262
+ | Describe | `mcp({ describe: "tool_name" })` |
263
+ | Call | `mcp({ tool: "...", args: '{"key": "value"}' })` |
264
+ | Connect | `mcp({ connect: "server-name" })` |
265
+ | UI messages | `mcp({ action: "ui-messages" })` |
266
+
267
+ Search includes both MCP tools and Pi tools (from extensions). Pi tools appear first with `[pi tool]` prefix. Space-separated words are OR'd.
268
+
269
+ Tool names are fuzzy-matched on hyphens and underscores — `context7_resolve_library_id` finds `context7_resolve-library-id`.
270
+
271
+ ## Commands
272
+
273
+ | Command | What it does |
274
+ |---------|--------------|
275
+ | `/mcp` | Interactive panel (server status, tool toggles, reconnect) |
276
+ | `/mcp tools` | List all tools |
277
+ | `/mcp reconnect` | Reconnect all servers |
278
+ | `/mcp reconnect <server>` | Connect or reconnect a single server |
279
+ | `/mcp-auth <server>` | OAuth setup |
280
+
281
+ ## How It Works
282
+
283
+ - One `mcp` tool in context (~200 tokens) instead of hundreds
284
+ - Servers are lazy by default — they connect on first tool call, not at startup
285
+ - Tool metadata is cached to disk so search/list/describe work without live connections
286
+ - Idle servers disconnect after 10 minutes (configurable), reconnect automatically on next use
287
+ - npx-based servers resolve to direct binary paths, skipping the ~143 MB npm parent process
288
+ - MCP server validates arguments, not the adapter
289
+ - Keep-alive servers get health checks and auto-reconnect
290
+ - Specific tools can be promoted from the proxy to first-class Pi tools via `directTools` config, so the LLM sees them directly instead of having to search
291
+
292
+ ## Limitations
293
+
294
+ - OAuth tokens obtained externally (no browser flow)
295
+ - No automatic token refresh
296
+ - Cross-session server sharing not yet implemented (each Pi session runs its own server processes)