kitsune-mcp 0.11.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +101 -9
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -17,17 +17,16 @@
17
17
 
18
18
  ---
19
19
 
20
- ## What's new in v0.9.0
20
+ ## What's new in v0.12.0
21
21
 
22
- Friction-reduction release focused on first-run onboarding, credential visibility, and agent workflows.
22
+ Security, reliability, and quality-of-life release.
23
23
 
24
- - **`search()` shows credential status per result** `✅ ready` or `✗ needs BRAVE_API_KEY` inline, so you know before you shapeshift
25
- - **`shapeshift(server_id, source="local", confirm=True)`** force a local `npx`/`uvx` install without a Smithery key; `source="smithery"` forces HTTP; `source="official"` requires a verified registry listing
26
- - **`shiftback(uninstall=True)`**optionally removes the locally installed package (uvx fully removed via `uv tool uninstall`; npx cache clears automatically)
27
- - **`KITSUNE_TRUST=community`** env varskip the `confirm=True` gate permanently for trusted users and agents; set once via `key("KITSUNE_TRUST", "community")`
28
- - **First-run onboarding in `status()`**clean sessions now show a 5-step getting-started guide with an example flow
29
- - **Lean-mounting hint** — after a heavy `shapeshift()` the output suggests `tools=[...]` with a concrete tool name and token cost
30
- - **Registry failure reporting** — `search()` now shows `⚠️ Skipped: <name> (timeout)` when one registry is slow, so you know results are partial instead of silently incomplete
24
+ - **SSRF protection** — `fetch()` and `craft()` now block requests to private/loopback addresses (127.x, 10.x, 192.168.x, 169.254.x, localhost), consistent with `skill()`. Set `KITSUNE_ALLOW_LOCAL_FETCH=1` to allow local URLs in dev environments.
25
+ - **Parameter aliasing** — `from_timezone` is automatically remapped to `source_timezone`, `to` to `target`, `src`/`dst`/`dest` to `source`/`target`, and language variants. Works transparently for any server with non-intuitive param names (e.g. `mcp-server-time`). Closes #9.
26
+ - **Session persistence** `crafted_tools` and named `connect()` sessions survive server restarts. State is written to `~/.kitsune/state.json` on exit and restored on startup. Crafted tools are re-registered automatically.
27
+ - **Registration failures surface**if `mcp.add_tool()` throws during `shapeshift()`, the error is now shown inline (`⚠️ N tool(s) failed to register`) instead of being silently swallowed.
28
+ - **`auto()` prefers free stdio over Smithery HTTP** `mcp-server-time` (official, local, free) beats a Smithery HTTP equivalent when both match a query.
29
+ - **MCP Registry backfill** — all versions back to v0.9.0 are now listed in the MCP Registry (previously silently failing due to an OIDC change in the publisher tool).
31
30
 
32
31
  See [CHANGELOG.md](CHANGELOG.md) for the full list plus internal refactors and bug fixes.
33
32
 
@@ -71,6 +70,65 @@ Base overhead: **7 tools, ~650 tokens** ([measured](examples/benchmark.py)). Eac
71
70
 
72
71
  ---
73
72
 
73
+ ## vs. always-on connectors (Claude.ai, ChatGPT, Cursor)
74
+
75
+ Most clients now offer a "connector marketplace" — Notion, Gmail, Drive, Slack, Linear, etc. — one click to enable. The catch: **every enabled connector loads its full tool surface into the system prompt of every message, for the lifetime of the conversation.** You pay for it whether you use it or not.
76
+
77
+ Kitsune is lazy and parallel: one entry, every server reachable on demand, only the tools you actively call sit in context.
78
+
79
+ ### Notion, head to head (numbers measured live in this session)
80
+
81
+ | Setup | Resting context (every turn) | One Notion search | After cleanup |
82
+ |---|---:|---:|---:|
83
+ | Always-on Notion connector | **13,733 tokens** | 13,733 + reply | 13,733 forever |
84
+ | Kitsune — full Notion mounted | 3,000 tokens | 16,733 + reply | 3,000 |
85
+ | Kitsune — `shapeshift("notion-hosted", tools=["notion-search"])` | 3,000 tokens | **4,540** + reply | 3,000 (after `shiftback`) |
86
+
87
+ Over a 50-turn conversation:
88
+
89
+ - Always-on connector: 50 × 13,733 = **686,650 tokens** of repeated Notion overhead
90
+ - Kitsune lean: 50 × 3,000 + 5 turns × 1,540 = **157,700 tokens**
91
+
92
+ **77% reduction for the same workflow.** And Notion is just one connector.
93
+
94
+ ### The "but it's just one" trap
95
+
96
+ Real-world enabled-connector token costs (typical hosted MCPs):
97
+
98
+ - Notion ~13.7K · Gmail ~8K · Drive ~10K · Slack ~7K · Calendar ~5K
99
+
100
+ **Five connectors enabled = ~43K tokens per turn**, every turn, whether you mention them or not. Same five via Kitsune lean: ~3K resting, with a brief spike only on the turn where you actually use one.
101
+
102
+ For a 100-turn dev session: 4.3M tokens of waste vs ~310K. **You can have a 14× longer conversation before hitting context limits.**
103
+
104
+ ### The killer demo
105
+
106
+ ```
107
+ > compare("notion")
108
+
109
+ tokens tools src status id
110
+ 13,733 14 official live (oauth) notion-hosted
111
+ 18,349 22 npm live @notionhq/notion-mcp-server
112
+ ...
113
+
114
+ 💡 Cheapest ready-to-use: notion-hosted
115
+
116
+ > shapeshift("notion-hosted", tools=["notion-search"])
117
+ ✓ Mounted notion-search (~1,540 tokens)
118
+
119
+ > call("notion-search", {"query": "roadmap"})
120
+ [results]
121
+
122
+ > shiftback()
123
+ ✓ Released. Context returned to baseline.
124
+ ```
125
+
126
+ One tool. On demand. Off again. Same OAuth, same Notion endpoint (`mcp.notion.com/mcp`) — but tokens stay in `~/.kitsune/oauth/`, not on a third-party's servers.
127
+
128
+ > **Connectors charge rent. Kitsune charges per use.**
129
+
130
+ ---
131
+
74
132
  ## Built for two audiences
75
133
 
76
134
  ### Adaptive agents
@@ -101,6 +159,23 @@ No separate web UI. No isolated test environment. Test how your server actually
101
159
 
102
160
  ---
103
161
 
162
+ ## Why MCP — not a CLI skill
163
+
164
+ A CLI-based agent skill gives every agent the same surface. An MCP lets you design a completely different surface for each agent — down to the individual tool.
165
+
166
+ **1. Surgical token budgets.**
167
+ `shapeshift("brave-search", tools=["web_search"])` loads exactly one tool — ~300 tokens — instead of the full server schema. A specialized research agent can be wired to see only the three tools it ever needs. A coding agent sees a different three. Same underlying servers; different, purpose-built surfaces. Token overhead stays flat because context is opt-in, not always-on.
168
+
169
+ **2. On-the-fly server creation.**
170
+ CLI skills require something to already exist on disk. An MCP can be generated mid-session. An agent can call `craft(name, description, params, url)` to define a new tool backed by any HTTP endpoint — no install, no config change, no restart. One conversation. Any problem. New capability spun up and available to the same agent immediately.
171
+
172
+ **3. Fine-tune the surface via the Forge.**
173
+ `kitsune-forge` exposes the full toolkit — inspect, benchmark, craft, and test. You can prototype a tool, measure its latency, compare two competing servers, and lock in exactly the shape you want before your production agent ever sees it. The Forge is the workbench; the lean `kitsune-mcp` entry is what the agent runs with after you've dialed it in.
174
+
175
+ > The result: agents that carry only the tools they need for the current problem, can extend themselves on demand, and never waste tokens on capability they aren't using.
176
+
177
+ ---
178
+
104
179
  ## Two modes
105
180
 
106
181
  | | `kitsune-mcp` | `kitsune-forge` |
@@ -291,6 +366,23 @@ Before spawning any subprocess, Kitsune MCP validates the executable name:
291
366
 
292
367
  Arguments are passed directly to `asyncio.create_subprocess_exec` (never a shell), so they are not subject to shell interpretation.
293
368
 
369
+ ### OAuth 2.1 for hosted MCP servers
370
+
371
+ Many hosted MCP servers (Notion, Linear, Cloudflare) authenticate via OAuth 2.1 with Dynamic Client Registration rather than a static API key. Kitsune supports this automatically — pass the server URL directly:
372
+
373
+ ```python
374
+ inspect("https://mcp.notion.com/mcp")
375
+ # First use: browser opens, you approve, tokens are cached.
376
+ # Subsequent runs: cached token loaded silently, refreshed when expired.
377
+
378
+ shapeshift("https://mcp.notion.com/mcp")
379
+ call("notion-search", {"query": "..."})
380
+ ```
381
+
382
+ Kitsune probes `/.well-known/oauth-authorization-server` on the server origin; if present, it registers a client (RFC 7591) and runs the authorization code flow with PKCE S256. Tokens and client registrations are stored at `~/.kitsune/oauth/<origin>/` with mode `0600` — never in `.env`.
383
+
384
+ Headless or no-browser environments: set `KITSUNE_NO_BROWSER=1` to have Kitsune print the authorize URL for you to paste manually (a loopback listener still captures the callback).
385
+
294
386
  ### Credential warnings
295
387
 
296
388
  `shapeshift()` probes tool descriptions for unreferenced environment variable patterns. If a tool mentions `BRAVE_API_KEY` and that variable isn't set, you get a warning immediately — before you call anything:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kitsune-mcp",
3
- "version": "0.11.0",
3
+ "version": "0.13.0",
4
4
  "description": "The shape-shifting MCP hub — shapeshift() into 10,000+ MCP servers at runtime. One entry point, no restarts, 7 registries.",
5
5
  "mcpName": "io.github.kaiser-data/kitsune-mcp",
6
6
  "bin": {