pi-mcp-adapter 1.4.1 → 1.5.1

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/CHANGELOG.md CHANGED
@@ -5,6 +5,29 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [Unreleased]
9
+
10
+ ### Changed
11
+ - Added `pi-package` keyword for npm discoverability (pi v0.50.0 package system)
12
+
13
+ ## [1.5.0] - 2026-01-22
14
+
15
+ ### Changed
16
+ - **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()`).
17
+
18
+ ### Added
19
+ - **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.
20
+ - **`isError: true` on error responses** - JSON parse errors and type validation errors now properly set `isError: true` to indicate failure to the LLM.
21
+
22
+ ### Migration
23
+ ```typescript
24
+ // Before (1.4.x)
25
+ mcp({ tool: "my_tool", args: { key: "value" } })
26
+
27
+ // After (1.5.0)
28
+ mcp({ tool: "my_tool", args: '{"key": "value"}' })
29
+ ```
30
+
8
31
  ## [1.4.1] - 2026-01-19
9
32
 
10
33
  ### Changed
package/README.md CHANGED
@@ -6,7 +6,7 @@ https://github.com/user-attachments/assets/4b7c66ff-e27e-4639-b195-22c3db406a5a
6
6
 
7
7
  ## Why This Exists
8
8
 
9
- Mario wrote about [why you might not need MCP](https://mariozechner.at/posts/2025-11-02-what-if-you-dont-need-mcp/). The problem: each MCP server dumps dozens of tools into your context. Playwright alone eats 13k tokens. Connect a few servers and you've burned half your context window before the conversation starts.
9
+ 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.
10
10
 
11
11
  His take: skip MCP entirely, write simple CLI tools instead.
12
12
 
@@ -50,9 +50,11 @@ chrome_devtools_take_screenshot
50
50
  fullPage (boolean) - Full page instead of viewport
51
51
  ```
52
52
  ```
53
- mcp({ tool: "chrome_devtools_take_screenshot", args: { format: "png" } })
53
+ mcp({ tool: "chrome_devtools_take_screenshot", args: '{"format": "png"}' })
54
54
  ```
55
55
 
56
+ Note: `args` is a JSON string, not an object.
57
+
56
58
  Two calls instead of 26 tools cluttering the context.
57
59
 
58
60
  ## Config
@@ -102,7 +104,7 @@ Supported: `cursor`, `claude-code`, `claude-desktop`, `vscode`, `windsurf`, `cod
102
104
  |------|---------|
103
105
  | Search | `mcp({ search: "screenshot navigate" })` |
104
106
  | Describe | `mcp({ describe: "tool_name" })` |
105
- | Call | `mcp({ tool: "...", args: {...} })` |
107
+ | Call | `mcp({ tool: "...", args: '{"key": "value"}' })` |
106
108
  | Status | `mcp({ })` or `mcp({ server: "name" })` |
107
109
 
108
110
  Search includes parameter schemas by default. Space-separated words are OR'd.
package/index.ts CHANGED
@@ -175,13 +175,13 @@ Usage:
175
175
  mcp({ server: "name" }) → List tools from server
176
176
  mcp({ search: "query" }) → Search for tools (includes schemas, space-separated words OR'd)
177
177
  mcp({ describe: "tool_name" }) → Show tool details and parameters
178
- mcp({ tool: "name", args: {...} }) → Call a tool
178
+ mcp({ tool: "name", args: '{"key": "value"}' }) → Call a tool (args is JSON string)
179
179
 
180
180
  Mode: tool (call) > describe > search > server (list) > nothing (status)`,
181
181
  parameters: Type.Object({
182
182
  // Call mode
183
183
  tool: Type.Optional(Type.String({ description: "Tool name to call (e.g., 'xcodebuild_list_sims')" })),
184
- args: Type.Optional(Type.Record(Type.String(), Type.Unknown(), { description: "Arguments for tool call" })),
184
+ args: Type.Optional(Type.String({ description: "Arguments as JSON string (e.g., '{\"key\": \"value\"}')" })),
185
185
  // Describe mode
186
186
  describe: Type.Optional(Type.String({ description: "Tool name to describe (shows parameters)" })),
187
187
  // Search mode
@@ -193,13 +193,35 @@ Mode: tool (call) > describe > search > server (list) > nothing (status)`,
193
193
  }),
194
194
  async execute(_toolCallId, params: {
195
195
  tool?: string;
196
- args?: Record<string, unknown>;
196
+ args?: string;
197
197
  describe?: string;
198
198
  search?: string;
199
199
  regex?: boolean;
200
200
  includeSchemas?: boolean;
201
201
  server?: string;
202
202
  }) {
203
+ // Parse args from JSON string if provided
204
+ let parsedArgs: Record<string, unknown> | undefined;
205
+ if (params.args) {
206
+ try {
207
+ parsedArgs = JSON.parse(params.args);
208
+ if (typeof parsedArgs !== "object" || parsedArgs === null || Array.isArray(parsedArgs)) {
209
+ const gotType = Array.isArray(parsedArgs) ? "array" : parsedArgs === null ? "null" : typeof parsedArgs;
210
+ return {
211
+ content: [{ type: "text", text: `Invalid args: expected a JSON object, got ${gotType}` }],
212
+ isError: true,
213
+ details: { error: "invalid_args_type" },
214
+ };
215
+ }
216
+ } catch (e) {
217
+ return {
218
+ content: [{ type: "text", text: `Invalid args JSON: ${e instanceof Error ? e.message : e}` }],
219
+ isError: true,
220
+ details: { error: "invalid_args" },
221
+ };
222
+ }
223
+ }
224
+
203
225
  // Wait for init if still in progress
204
226
  if (!state && initPromise) {
205
227
  try {
@@ -220,7 +242,7 @@ Mode: tool (call) > describe > search > server (list) > nothing (status)`,
220
242
 
221
243
  // Mode resolution: tool > describe > search > server > status
222
244
  if (params.tool) {
223
- return executeCall(state, params.tool, params.args);
245
+ return executeCall(state, params.tool, parsedArgs);
224
246
  }
225
247
  if (params.describe) {
226
248
  return executeDescribe(state, params.describe);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-mcp-adapter",
3
- "version": "1.4.1",
3
+ "version": "1.5.1",
4
4
  "description": "MCP (Model Context Protocol) adapter extension for Pi coding agent",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -13,6 +13,7 @@
13
13
  "url": "https://github.com/nicobailon/pi-mcp-adapter"
14
14
  },
15
15
  "keywords": [
16
+ "pi-package",
16
17
  "pi",
17
18
  "mcp",
18
19
  "model-context-protocol",
@@ -23,7 +24,9 @@
23
24
  "llm"
24
25
  ],
25
26
  "pi": {
26
- "extensions": ["./index.ts"]
27
+ "extensions": [
28
+ "./index.ts"
29
+ ]
27
30
  },
28
31
  "files": [
29
32
  "cli.js",