kitsune-mcp 0.18.1 → 0.20.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/README.md +227 -166
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<div align="center">
|
|
3
3
|
<img src="https://raw.githubusercontent.com/kaiser-data/kitsune-mcp/main/kitsune-logo.png" alt="Kitsune MCP" width="160" />
|
|
4
4
|
<h1>🦊 Kitsune MCP</h1>
|
|
5
|
-
<p><strong>One
|
|
5
|
+
<p><strong>One entry in your config. Any MCP server on demand.<br/>5 tools at rest. Thousands available on request. No restarts.</strong></p>
|
|
6
6
|
</div>
|
|
7
7
|
|
|
8
8
|
[](https://pypi.org/project/kitsune-mcp/)
|
|
@@ -17,56 +17,93 @@
|
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
20
|
-
## What's new in v0.
|
|
20
|
+
## What's new in v0.20
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
- **GATEWAY** — `status()` detects other MCP servers active in your client configs and shows their context cost. `setup()` harvests their API keys and absorbs the servers for `shapeshift()`.
|
|
23
|
+
- **6-tool lean profile** — `status`, `search`, `auth`, `shapeshift`, `call`, `auto`. `auto()` is now first-class in the lean surface, not forge-only.
|
|
24
|
+
- **`auto()` with `server_hint`** — one-shot task execution: `auto("current time in Tokyo", server_hint="mcp-server-time")` infers args and returns the result directly. Arg extraction infers "Tokyo" → "Asia/Tokyo" automatically.
|
|
25
|
+
- **`setup()` wizard** — `setup(action="harvest")` extracts API keys from other servers' configs into `~/.kitsune/.env`. `setup(action="absorb")` registers those servers for `shapeshift()`. `setup(project=True)` writes a lean `.claude/mcp.json` for this project only.
|
|
23
26
|
|
|
24
|
-
|
|
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).
|
|
30
|
-
|
|
31
|
-
See [CHANGELOG.md](CHANGELOG.md) for the full list plus internal refactors and bug fixes.
|
|
27
|
+
See [CHANGELOG.md](CHANGELOG.md) for the full list.
|
|
32
28
|
|
|
33
29
|
---
|
|
34
30
|
|
|
35
|
-
##
|
|
36
|
-
|
|
37
|
-
In Japanese folklore, the Kitsune (狐) is a fox spirit of extraordinary intelligence and magical power. What makes it remarkable is how it grows: with age and wisdom, a Kitsune gains additional tails — each one representing a new ability it has mastered. It can shapeshift, take on any form it chooses, borrow the powers of others, and just as freely cast them off when the purpose is fulfilled. One fox. Many forms. Total fluidity.
|
|
31
|
+
## The problem: static tool loading
|
|
38
32
|
|
|
39
|
-
|
|
33
|
+
Every MCP server you add to your config loads **all** its tools at startup and keeps them there, every turn, whether used or not.
|
|
40
34
|
|
|
41
|
-
|
|
42
|
-
`shiftback()` — it returns to its true shape, ready to become something else.
|
|
35
|
+
Five servers means 3,000–20,000+ tokens of overhead on every request. Research on LLM tool use consistently shows accuracy degrades as the number of visible tools increases — the model has to reason about dozens of options before it can act on any of them.
|
|
43
36
|
|
|
44
|
-
|
|
37
|
+
```
|
|
38
|
+
20 tools in context → baseline performance
|
|
39
|
+
50 tools in context → measurable degradation in tool selection accuracy
|
|
40
|
+
100+ tools in context → significant drop; wrong tools called, arguments hallucinated
|
|
41
|
+
```
|
|
45
42
|
|
|
46
|
-
|
|
43
|
+
**The fix isn't a better model — it's a smaller menu.**
|
|
47
44
|
|
|
48
45
|
---
|
|
49
46
|
|
|
50
|
-
##
|
|
47
|
+
## GATEWAY — see what you're paying for
|
|
51
48
|
|
|
52
|
-
|
|
49
|
+
Once Kitsune is running, call `status()` to see what other MCP servers your clients are loading:
|
|
53
50
|
|
|
54
|
-
|
|
51
|
+
```
|
|
52
|
+
GATEWAY
|
|
53
|
+
⚠ 2 other server(s) active in claude-desktop (~16 extra tools in context)
|
|
54
|
+
Run setup() to harvest their credentials and reduce bloat
|
|
55
|
+
⚠ 1 other server(s) active in claude-code (~8 extra tools in context)
|
|
56
|
+
```
|
|
55
57
|
|
|
56
|
-
|
|
58
|
+
Kitsune can absorb those servers so you get a single lean config with everything still accessible on demand:
|
|
57
59
|
|
|
58
60
|
```
|
|
59
|
-
|
|
60
|
-
#
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
shiftback()
|
|
64
|
-
shapeshift("@modelcontextprotocol/server-github") # and again
|
|
61
|
+
setup() # preview what can be harvested
|
|
62
|
+
setup(action="harvest") # extract API keys → ~/.kitsune/.env (non-destructive)
|
|
63
|
+
setup(action="absorb") # register servers for shapeshift() (non-destructive)
|
|
64
|
+
setup(project=True) # write .claude/mcp.json with only Kitsune (this project only)
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Kitsune: RAG for your MCP ecosystem
|
|
68
70
|
|
|
69
|
-
|
|
71
|
+
Think of Kitsune the same way you think of RAG for documents: instead of loading all your knowledge into context upfront, you retrieve only what's relevant to the current query.
|
|
72
|
+
|
|
73
|
+
Kitsune does the same thing for MCP servers:
|
|
74
|
+
|
|
75
|
+
| RAG for documents | Kitsune for MCP |
|
|
76
|
+
|---|---|
|
|
77
|
+
| Index: all your docs | Registry: 10,000+ MCP servers across 7 sources |
|
|
78
|
+
| Query → retrieve relevant chunks | `search("web scraping")` → find matching servers |
|
|
79
|
+
| Inject only relevant content | `shapeshift("firecrawl", tools=["scrape"])` → mount only needed tools |
|
|
80
|
+
| Clear context when done | `shapeshift()` → unmount, context returns to baseline |
|
|
81
|
+
|
|
82
|
+
**5 tools at rest (~400 tokens). Any server on demand. Load exactly the tools the current task needs — 2 out of 20 if that's all you need.**
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
shapeshift("brave-search", tools=["web_search"]) # retrieve: 1 tool, ~300 tokens
|
|
86
|
+
# ... task done ...
|
|
87
|
+
shapeshift() # release: context back to ~400 tokens
|
|
88
|
+
shapeshift("supabase") # next task: different server, no restart
|
|
89
|
+
shapeshift()
|
|
90
|
+
shapeshift("@modelcontextprotocol/server-github") # and again
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Why Kitsune?
|
|
96
|
+
|
|
97
|
+
In Japanese folklore, the Kitsune (狐) is a fox spirit of extraordinary intelligence and magical power. What makes it remarkable is how it grows: with age and wisdom, a Kitsune gains additional tails — each one representing a new ability it has mastered. It can shapeshift, take on any form it chooses, borrow the powers of others, and just as freely cast them off when the purpose is fulfilled. One fox. Many forms. Total fluidity.
|
|
98
|
+
|
|
99
|
+
This tool works the same way.
|
|
100
|
+
|
|
101
|
+
`shapeshift("brave-search")` — the fox takes on a new form, its tools appear natively.
|
|
102
|
+
`shapeshift()` — it returns to its true shape, ready to become something else.
|
|
103
|
+
|
|
104
|
+
Each server it shapeshifts into is a new tail. Each capability borrowed and released cleanly. One entry in your config. Every server in the MCP ecosystem, on demand.
|
|
105
|
+
|
|
106
|
+
> *I am not Japanese, and I use this name with the highest respect for the mythology and culture it comes from. The parallel felt too precise to ignore — a spirit that shapeshifts between forms, gains new powers, and releases them at will. That is exactly what this tool does.*
|
|
70
107
|
|
|
71
108
|
---
|
|
72
109
|
|
|
@@ -76,30 +113,30 @@ Most clients now offer a "connector marketplace" — Notion, Gmail, Drive, Slack
|
|
|
76
113
|
|
|
77
114
|
Kitsune is lazy and parallel: one entry, every server reachable on demand, only the tools you actively call sit in context.
|
|
78
115
|
|
|
79
|
-
### Notion, head to head (numbers measured live
|
|
116
|
+
### Notion, head to head (numbers measured live)
|
|
80
117
|
|
|
81
118
|
| Setup | Resting context (every turn) | One Notion search | After cleanup |
|
|
82
119
|
|---|---:|---:|---:|
|
|
83
120
|
| Always-on Notion connector | **13,733 tokens** | 13,733 + reply | 13,733 forever |
|
|
84
|
-
| Kitsune — full Notion mounted |
|
|
85
|
-
| Kitsune — `shapeshift("notion-hosted", tools=["notion-search"])` |
|
|
121
|
+
| Kitsune — full Notion mounted | 400 tokens | ~14,133 + reply | 400 |
|
|
122
|
+
| Kitsune — `shapeshift("notion-hosted", tools=["notion-search"])` | 400 tokens | **~1,940** + reply | 400 (after `shapeshift()`) |
|
|
86
123
|
|
|
87
124
|
Over a 50-turn conversation:
|
|
88
125
|
|
|
89
126
|
- Always-on connector: 50 × 13,733 = **686,650 tokens** of repeated Notion overhead
|
|
90
|
-
- Kitsune lean: 50 ×
|
|
127
|
+
- Kitsune lean: 50 × 400 + 5 turns × 1,540 = **27,700 tokens**
|
|
91
128
|
|
|
92
|
-
**
|
|
129
|
+
**97% reduction for the same workflow.** And Notion is just one connector.
|
|
93
130
|
|
|
94
131
|
### The "but it's just one" trap
|
|
95
132
|
|
|
96
|
-
Real-world
|
|
133
|
+
Real-world always-on token costs (typical hosted MCPs):
|
|
97
134
|
|
|
98
135
|
- Notion ~13.7K · Gmail ~8K · Drive ~10K · Slack ~7K · Calendar ~5K
|
|
99
136
|
|
|
100
|
-
**Five connectors enabled = ~43K tokens per turn**, every turn, whether you mention them or not. Same five via Kitsune lean: ~
|
|
137
|
+
**Five connectors enabled = ~43K tokens per turn**, every turn, whether you mention them or not. Same five via Kitsune lean: ~420 tokens resting, with a brief spike only on the turn where you actually use one.
|
|
101
138
|
|
|
102
|
-
For a 100-turn dev session: 4.3M tokens of waste vs ~
|
|
139
|
+
For a 100-turn dev session: 4.3M tokens of waste vs ~40K. **You can have a 100× longer conversation before hitting context limits.**
|
|
103
140
|
|
|
104
141
|
### The killer demo
|
|
105
142
|
|
|
@@ -119,8 +156,8 @@ For a 100-turn dev session: 4.3M tokens of waste vs ~310K. **You can have a 14×
|
|
|
119
156
|
> call("notion-search", {"query": "roadmap"})
|
|
120
157
|
[results]
|
|
121
158
|
|
|
122
|
-
>
|
|
123
|
-
✓ Released. Context returned to baseline.
|
|
159
|
+
> shapeshift()
|
|
160
|
+
✓ Released. Context returned to baseline (~400 tokens).
|
|
124
161
|
```
|
|
125
162
|
|
|
126
163
|
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.
|
|
@@ -129,71 +166,56 @@ One tool. On demand. Off again. Same OAuth, same Notion endpoint (`mcp.notion.co
|
|
|
129
166
|
|
|
130
167
|
---
|
|
131
168
|
|
|
132
|
-
##
|
|
133
|
-
|
|
134
|
-
### Adaptive agents
|
|
135
|
-
|
|
136
|
-
An agent that loads everything upfront burns tokens on tools it never calls — and makes worse decisions because it sees too many options at once. An agent that mounts on demand is leaner, faster, and more focused:
|
|
137
|
-
|
|
138
|
-
- Shapeshift into only what the current task needs — shiftback when done
|
|
139
|
-
- `shapeshift(server_id, tools=[...])` to cherry-pick — load 2 tools from a server that has 20
|
|
140
|
-
- Chain across multiple servers in one session without touching config or restarting
|
|
141
|
-
- Token overhead stays flat: ~650 base + only what you load
|
|
142
|
-
|
|
143
|
-
Kitsune MCP is designed around the real economics of an agent loop.
|
|
144
|
-
|
|
145
|
-
### MCP developers
|
|
169
|
+
## The 6-tool surface
|
|
146
170
|
|
|
147
|
-
|
|
171
|
+
`kitsune-mcp` exposes exactly six tools at rest — enough to handle any task autonomously, find, mount, authenticate, call, and monitor any server in the ecosystem:
|
|
148
172
|
|
|
149
|
-
|
|
|
173
|
+
| Tool | What it does |
|
|
150
174
|
|---|---|
|
|
151
|
-
|
|
|
152
|
-
|
|
|
153
|
-
|
|
|
154
|
-
|
|
|
155
|
-
|
|
|
156
|
-
|
|
|
175
|
+
| `auto(task)` | **Intent router**: describe any task → Kitsune finds the right server, mounts it, and calls the right tool in one step. The front door for new users. |
|
|
176
|
+
| `search(query)` | Find servers across 7 registries. Returns ranked matches with token estimates. |
|
|
177
|
+
| `auth(target, value)` | Store an API key (`auth("BRAVE_API_KEY", "sk-...")`) or trigger OAuth 2.1 (`auth("https://mcp.notion.com/mcp")`). Writes to `~/.kitsune/.env`, active immediately. |
|
|
178
|
+
| `shapeshift(server_id, tools, source)` | **Mount**: server's tools become first-class native tools. **Unmount**: `shapeshift()` with no args releases current form. `tools=[...]` for lean load. |
|
|
179
|
+
| `call(tool_name, arguments)` | Call any tool — mounted or not. When shapeshifted, `server_id` is inferred. |
|
|
180
|
+
| `status()` | Current form, active connections (PID + RAM), token overhead, registry health. |
|
|
157
181
|
|
|
158
|
-
|
|
182
|
+
**Overhead at rest: ~420 tokens.** Each mount adds only what you load — `tools=["web_search"]` is ~300 tokens, not 1,500.
|
|
159
183
|
|
|
160
|
-
|
|
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.
|
|
184
|
+
Need evaluation tools (`inspect`, `test`, `bench`, `craft`, `compare`)? Use `kitsune-forge`:
|
|
168
185
|
|
|
169
|
-
|
|
170
|
-
|
|
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.
|
|
186
|
+
```json
|
|
187
|
+
{ "command": "kitsune-forge" }
|
|
188
|
+
```
|
|
176
189
|
|
|
177
190
|
---
|
|
178
191
|
|
|
179
|
-
##
|
|
192
|
+
## Specialized agent profiles
|
|
180
193
|
|
|
181
|
-
|
|
182
|
-
|---|---|---|
|
|
183
|
-
| **Purpose** | Adaptive agents, everyday mounting | MCP evaluation, benchmarking, crafting |
|
|
184
|
-
| **Tools** | 7 (shapeshift, shiftback, search, inspect, call, key, status) | All 17 |
|
|
185
|
-
| **Token overhead** | ~650 tokens | ~1,700 tokens |
|
|
186
|
-
| **Use when** | Agents mounting per task, minimal token budget | Discovering, testing, benchmarking, prototyping |
|
|
194
|
+
Because tool context is opt-in, you can wire agents to carry only the surface they ever need:
|
|
187
195
|
|
|
188
|
-
|
|
196
|
+
### Research agent — `search + fetch, ~700 tokens`
|
|
197
|
+
```json
|
|
198
|
+
{ "command": "kitsune-mcp", "env": { "KITSUNE_TOOLS": "search,shapeshift,call,auth,status" } }
|
|
199
|
+
```
|
|
200
|
+
```python
|
|
201
|
+
shapeshift("brave-search", tools=["web_search"])
|
|
202
|
+
shapeshift("firecrawl-mcp", tools=["scrape"])
|
|
203
|
+
# Total in-context: ~700 tokens at peak. A GPT-4o request at 700 tokens costs ~$0.0021.
|
|
204
|
+
```
|
|
189
205
|
|
|
190
|
-
|
|
206
|
+
### Code agent — `github + filesystem + git`
|
|
207
|
+
```python
|
|
208
|
+
shapeshift("@modelcontextprotocol/server-github", tools=["create_issue", "search_repositories"])
|
|
209
|
+
shapeshift("@modelcontextprotocol/server-filesystem", tools=["read_file", "write_file"])
|
|
210
|
+
shapeshift("@modelcontextprotocol/server-git", tools=["git_log", "git_diff"])
|
|
211
|
+
# Each loaded separately when needed — never all 60+ tools at once
|
|
212
|
+
```
|
|
191
213
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
214
|
+
### Notes agent — `notion + memory, lean`
|
|
215
|
+
```python
|
|
216
|
+
shapeshift("notion-hosted", tools=["notion-search", "notion-append-block-children"])
|
|
217
|
+
shapeshift("mem0", tools=["add_memory", "search_memory"])
|
|
218
|
+
# ~3,000 tokens peak vs ~22,000 for both always-on
|
|
197
219
|
```
|
|
198
220
|
|
|
199
221
|
---
|
|
@@ -206,7 +228,7 @@ Both modes from the same package:
|
|
|
206
228
|
|
|
207
229
|
`shapeshift()` injects tools directly at runtime via FastMCP's live API. Token overhead stays flat regardless of how many servers you explore.
|
|
208
230
|
|
|
209
|
-
Need the full evaluation suite? `kitsune-forge` adds
|
|
231
|
+
Need the full evaluation suite? `kitsune-forge` adds `inspect`, `test`, `bench`, `craft`, `compare`, and more:
|
|
210
232
|
|
|
211
233
|
<div align="center">
|
|
212
234
|
<img src="https://raw.githubusercontent.com/kaiser-data/kitsune-mcp/main/docs/architecture-forge.svg" alt="Protean Forge — extended suite" width="700"/>
|
|
@@ -243,18 +265,31 @@ Works with Claude Desktop, Claude Code, Cursor, Cline, OpenClaw, Continue.dev, Z
|
|
|
243
265
|
| Cline / Continue.dev | VS Code settings / `~/.continue/config.json` |
|
|
244
266
|
| OpenClaw | MCP config in OpenClaw settings |
|
|
245
267
|
|
|
268
|
+
```
|
|
269
|
+
# One-shot: describe task + pin the server
|
|
270
|
+
auto("current time in Tokyo", server_hint="mcp-server-time")
|
|
271
|
+
auto("search: anthropic news May 2026", server_hint="exa")
|
|
272
|
+
|
|
273
|
+
# Multi-step: inspect / lean-mount / hold mount for several calls
|
|
274
|
+
shapeshift("mcp-server-time")
|
|
275
|
+
call("get_current_time", {"timezone": "Asia/Tokyo"})
|
|
276
|
+
shapeshift()
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
Use `auto()` with `server_hint` for single-call flows. Use `shapeshift + call` when you want to inspect first, mount specific tools, or run multiple calls on the same server.
|
|
280
|
+
|
|
246
281
|
### Using Kitsune alongside existing servers
|
|
247
282
|
|
|
248
|
-
You can add Kitsune to a config that already has other servers — it works without touching anything else.
|
|
283
|
+
You can add Kitsune to a config that already has other servers — it works without touching anything else.
|
|
249
284
|
|
|
250
|
-
**Kitsune never deletes or modifies your existing configs without explicit confirmation.** Config changes are always backed up and reversible
|
|
285
|
+
**Kitsune never deletes or modifies your existing configs without explicit confirmation.** Config changes are always backed up and reversible.
|
|
251
286
|
|
|
252
287
|
### Run Kitsune and standard MCP side-by-side (Claude Code)
|
|
253
288
|
|
|
254
289
|
Claude Code supports per-project MCP configs that override the global one. This means you can run a Kitsune session and a standard multi-server session **simultaneously, with no config changes**:
|
|
255
290
|
|
|
256
291
|
```bash
|
|
257
|
-
# Terminal A — Kitsune-only project (
|
|
292
|
+
# Terminal A — Kitsune-only project (6 tools, clean context)
|
|
258
293
|
mkdir ~/projects/kitsune-session
|
|
259
294
|
echo '{"mcpServers":{"kitsune":{"command":"kitsune-mcp"}}}' > ~/projects/kitsune-session/.claude/mcp.json
|
|
260
295
|
cd ~/projects/kitsune-session && claude
|
|
@@ -263,7 +298,7 @@ cd ~/projects/kitsune-session && claude
|
|
|
263
298
|
cd ~/projects/any-other-project && claude # uses global ~/.claude/mcp.json
|
|
264
299
|
```
|
|
265
300
|
|
|
266
|
-
Both sessions run in parallel.
|
|
301
|
+
Both sessions run in parallel. Terminal A sees 5 tools; Terminal B sees everything in your global config. No restarts, no toggling, no risk to either session. Easy to compare workflows or run specialised agent tasks in one terminal while using familiar tools in another.
|
|
267
302
|
|
|
268
303
|
---
|
|
269
304
|
|
|
@@ -314,7 +349,7 @@ Kitsune MCP ← the one entry in your config
|
|
|
314
349
|
|
|
315
350
|
The AI sees `read_file`, `write_file`, `list_directory` as if they were always there. There's no wrapper or `call_tool("filesystem", ...)` indirection — the tools are first-class.
|
|
316
351
|
|
|
317
|
-
`
|
|
352
|
+
`shapeshift()` with no args reverses all of it: deregisters the proxy closures, clears resources and prompts, notifies the client.
|
|
318
353
|
|
|
319
354
|
### Resources and prompts
|
|
320
355
|
|
|
@@ -339,9 +374,21 @@ Template URIs (e.g. `file:///{path}`) are skipped — they require parameter bin
|
|
|
339
374
|
| Smithery hosted | HTTP+SSE (requires `SMITHERY_API_KEY`) |
|
|
340
375
|
| WebSocket server | `ws://` / `wss://` |
|
|
341
376
|
|
|
342
|
-
###
|
|
377
|
+
### Cold start latency (typical ranges)
|
|
343
378
|
|
|
344
|
-
|
|
379
|
+
| Transport | First call | Subsequent calls |
|
|
380
|
+
|---|---|---|
|
|
381
|
+
| Smithery HTTP / WebSocket | ~100–300 ms | ~50–150 ms |
|
|
382
|
+
| npm (`npx`) — cached | ~1–3 s | reused from pool |
|
|
383
|
+
| npm (`npx`) — cold download | ~5–15 s | cached after first |
|
|
384
|
+
| pip (`uvx`) — cached | ~1–2 s | reused from pool |
|
|
385
|
+
| Docker | ~3–8 s | reused from pool |
|
|
386
|
+
|
|
387
|
+
Kitsune keeps a **persistent process pool** — once a server is started, subsequent `shapeshift()` calls reattach in milliseconds. `shapeshift("brave-search")` the second time is fast.
|
|
388
|
+
|
|
389
|
+
### Why use `inspect()` before shapeshift()
|
|
390
|
+
|
|
391
|
+
`inspect()` (available in `kitsune-forge`) connects to the server and fetches its schemas — but does **not** register anything. Zero tools added to context, zero tokens consumed by the AI.
|
|
345
392
|
|
|
346
393
|
Use it to:
|
|
347
394
|
- See exact parameter names and types before committing
|
|
@@ -353,11 +400,11 @@ Use it to:
|
|
|
353
400
|
inspect("mcp-server-brave-search")
|
|
354
401
|
# → CREDENTIALS
|
|
355
402
|
# → ✗ missing BRAVE_API_KEY — Brave Search API key
|
|
356
|
-
# → Add
|
|
403
|
+
# → Add: auth("BRAVE_API_KEY", "your-value")
|
|
357
404
|
# → Token cost: ~99 tokens (measured)
|
|
358
405
|
|
|
359
|
-
# Add the key
|
|
360
|
-
|
|
406
|
+
# Add the key — picked up immediately, no restart needed
|
|
407
|
+
auth("BRAVE_API_KEY", "your-value")
|
|
361
408
|
shapeshift("mcp-server-brave-search")
|
|
362
409
|
call("brave_web_search", arguments={"query": "MCP protocol 2025"})
|
|
363
410
|
```
|
|
@@ -366,11 +413,9 @@ call("brave_web_search", arguments={"query": "MCP protocol 2025"})
|
|
|
366
413
|
|
|
367
414
|
## Security
|
|
368
415
|
|
|
369
|
-
Kitsune MCP introduces a trust model for servers you haven't personally audited.
|
|
370
|
-
|
|
371
416
|
### Trust tiers
|
|
372
417
|
|
|
373
|
-
Every `shapeshift()
|
|
418
|
+
Every `shapeshift()` and `call()` result shows where the server comes from:
|
|
374
419
|
|
|
375
420
|
| Tier | Sources | Indicator |
|
|
376
421
|
|---|---|---|
|
|
@@ -378,7 +423,7 @@ Every `shapeshift()`, `call()`, and `connect()` result shows where the server co
|
|
|
378
423
|
| Medium | `mcpregistry`, `glama`, `smithery` | `✓ Source: smithery` |
|
|
379
424
|
| Community | `npm`, `pypi`, `github` | `⚠️ Source: npm (community — not verified)` |
|
|
380
425
|
|
|
381
|
-
Community servers and `source="local"` installs require `confirm=True` — you're explicitly acknowledging you've reviewed the server before running arbitrary code. To bypass this for servers you already trust, set `KITSUNE_TRUST=community` (via `
|
|
426
|
+
Community servers and `source="local"` installs require `confirm=True` — you're explicitly acknowledging you've reviewed the server before running arbitrary code. To bypass this for servers you already trust, set `KITSUNE_TRUST=community` (via `auth("KITSUNE_TRUST", "community")` or your `.env`). This persists across sessions so power users and agents never see the gate again.
|
|
382
427
|
|
|
383
428
|
### Install command validation
|
|
384
429
|
|
|
@@ -390,10 +435,10 @@ Arguments are passed directly to `asyncio.create_subprocess_exec` (never a shell
|
|
|
390
435
|
|
|
391
436
|
### OAuth 2.1 for hosted MCP servers
|
|
392
437
|
|
|
393
|
-
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
|
|
438
|
+
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:
|
|
394
439
|
|
|
395
440
|
```python
|
|
396
|
-
|
|
441
|
+
auth("https://mcp.notion.com/mcp")
|
|
397
442
|
# First use: browser opens, you approve, tokens are cached.
|
|
398
443
|
# Subsequent runs: cached token loaded silently, refreshed when expired.
|
|
399
444
|
|
|
@@ -412,7 +457,7 @@ Headless or no-browser environments: set `KITSUNE_NO_BROWSER=1` to have Kitsune
|
|
|
412
457
|
```
|
|
413
458
|
⚠️ Credentials may be required — add to .env:
|
|
414
459
|
BRAVE_API_KEY=your-value
|
|
415
|
-
Or:
|
|
460
|
+
Or: auth("BRAVE_API_KEY", "your-value")
|
|
416
461
|
```
|
|
417
462
|
|
|
418
463
|
### Process isolation and sandboxing
|
|
@@ -442,30 +487,24 @@ The same pattern works for all of them:
|
|
|
442
487
|
```
|
|
443
488
|
shapeshift("brave") # web search in 2 tools
|
|
444
489
|
call("brave_web_search", arguments={"query": "…"})
|
|
490
|
+
shapeshift()
|
|
445
491
|
|
|
446
492
|
shapeshift("firecrawl-mcp", tools=["scrape","search"]) # scraping, lean (2 of 9 tools)
|
|
447
493
|
call("scrape", arguments={"url": "https://…"})
|
|
494
|
+
shapeshift()
|
|
448
495
|
|
|
449
496
|
shapeshift("@modelcontextprotocol/server-github", tools=["create_issue","search_repositories"])
|
|
450
497
|
call("create_issue", arguments={"owner": "…", "repo": "…", "title": "…"})
|
|
498
|
+
shapeshift()
|
|
451
499
|
```
|
|
452
500
|
|
|
453
501
|
**Token cost scales with what you load**, not what exists. A 26-tool GitHub server costs ~500 tokens if you only mount 3 tools. See [.env.example](.env.example) for the full key catalog with lean mount hints.
|
|
454
502
|
|
|
455
|
-
### Security note on `.env`
|
|
456
|
-
|
|
457
|
-
Kitsune MCP re-reads `.env` on every call — which means adding a key instantly activates it. That convenience comes with a responsibility: **`.env` is the single place all your API keys live**. A few practices worth following:
|
|
458
|
-
|
|
459
|
-
- Add `.env` to `.gitignore` — never commit real keys
|
|
460
|
-
- Use project-level `.env` for project-specific keys; `~/.kitsune/.env` for personal global keys
|
|
461
|
-
- Prefer minimal OAuth scopes and fine-grained tokens (e.g. GitHub fine-grained tokens with per-repo permissions)
|
|
462
|
-
- Rotate keys that get exposed; Kitsune MCP picks up the new value immediately without restart
|
|
463
|
-
|
|
464
503
|
---
|
|
465
504
|
|
|
466
505
|
## Why Not Just X?
|
|
467
506
|
|
|
468
|
-
**"Can't I just add more servers to `mcp.json`?"** — Every configured server starts at launch and exposes all tools constantly. You can't add or remove mid-session without a restart. With 5+ servers you're burning thousands of tokens on every request for tools rarely needed. Kitsune MCP keeps the tool list minimal — shapeshift into what you need,
|
|
507
|
+
**"Can't I just add more servers to `mcp.json`?"** — Every configured server starts at launch and exposes all tools constantly. You can't add or remove mid-session without a restart. With 5+ servers you're burning thousands of tokens on every request for tools rarely needed. Kitsune MCP keeps the tool list minimal — shapeshift into what you need, release when done.
|
|
469
508
|
|
|
470
509
|
**"What about MCP Inspector?"** — MCP Inspector is a standalone web UI that connects to one server and lets you inspect schemas and call tools manually. It's useful for basic debugging but isolated from real AI workflows. Kitsune MCP tests servers inside actual Claude or Cursor sessions — how an AI really uses them. It adds `test()` scoring, `bench()` latency numbers, side-by-side server comparison, and `craft()` for live endpoint prototyping. It also discovers and installs servers on demand; Inspector requires you to already have one running.
|
|
471
510
|
|
|
@@ -479,7 +518,7 @@ Kitsune MCP re-reads `.env` on every call — which means adding a key instantly
|
|
|
479
518
|
| Load tools at runtime | ✅ (write code) | ✅ `shapeshift()` |
|
|
480
519
|
| Search registries to discover servers | ❌ | ✅ npm · official · Glama · Smithery |
|
|
481
520
|
| Install npm / PyPI / GitHub packages on demand | ❌ | ✅ |
|
|
482
|
-
| Atomic
|
|
521
|
+
| Atomic release — retract all shapeshifted tools at once | ❌ | ✅ `shapeshift()` |
|
|
483
522
|
| Persistent stdio process pool | ❌ | ✅ |
|
|
484
523
|
| Zero boilerplate — works after `pip install` | ❌ | ✅ |
|
|
485
524
|
|
|
@@ -492,7 +531,7 @@ Kitsune MCP re-reads `.env` on every call — which means adding a key instantly
|
|
|
492
531
|
```json
|
|
493
532
|
{
|
|
494
533
|
"mcpServers": {
|
|
495
|
-
"
|
|
534
|
+
"kitsune": { "command": "kitsune-mcp" }
|
|
496
535
|
}
|
|
497
536
|
}
|
|
498
537
|
```
|
|
@@ -512,50 +551,57 @@ Kitsune MCP re-reads `.env` on every call — which means adding a key instantly
|
|
|
512
551
|
|
|
513
552
|
Get a free key at [smithery.ai/account/api-keys](https://smithery.ai/account/api-keys). Without it, Kitsune MCP is fully functional via npm, PyPI, official registries, and GitHub.
|
|
514
553
|
|
|
515
|
-
**Frictionless credentials** — Kitsune MCP re-reads `.env` on every `
|
|
554
|
+
**Frictionless credentials** — Kitsune MCP re-reads `.env` on every `shapeshift()` and `call()`. Add a key mid-session and it takes effect immediately — no restart:
|
|
516
555
|
|
|
517
556
|
```
|
|
518
|
-
# .env (CWD, ~/.env, or ~/.kitsune/.env — all checked,
|
|
557
|
+
# .env (CWD, ~/.env, or ~/.kitsune/.env — all checked, ~/.kitsune/.env wins)
|
|
519
558
|
BRAVE_API_KEY=your-key
|
|
520
559
|
GITHUB_TOKEN=ghp_...
|
|
521
560
|
```
|
|
522
561
|
|
|
523
|
-
Or use `
|
|
562
|
+
Or use `auth()` to write to `.env` and activate in one step:
|
|
524
563
|
|
|
525
564
|
```
|
|
526
|
-
|
|
565
|
+
auth("BRAVE_API_KEY", "your-key") # writes to ~/.kitsune/.env, active immediately
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
### Custom tool surface
|
|
569
|
+
|
|
570
|
+
```json
|
|
571
|
+
{ "command": "kitsune-mcp",
|
|
572
|
+
"env": { "KITSUNE_TOOLS": "shapeshift,call,auth" } } ← three tools only
|
|
527
573
|
```
|
|
528
574
|
|
|
529
575
|
---
|
|
530
576
|
|
|
531
577
|
## All Tools
|
|
532
578
|
|
|
533
|
-
### `kitsune-mcp` — lean profile (
|
|
579
|
+
### `kitsune-mcp` — lean profile (6 tools, ~420 token overhead)
|
|
534
580
|
|
|
535
581
|
| Tool | Description |
|
|
536
582
|
|---|---|
|
|
537
|
-
| `
|
|
538
|
-
| `
|
|
583
|
+
| `auto(task, tool, args)` | Intent router: describe any task → finds server → calls tool in one step. Category-aware routing. |
|
|
584
|
+
| `shapeshift(server_id, tools, source, confirm)` | Load a server's tools live. `shapeshift()` with no args unmounts. `tools=[...]` for lean load. `source="local"` forces npx/uvx install; `source="smithery"` forces HTTP. |
|
|
539
585
|
| `search(query, registry)` | Search MCP servers across registries. |
|
|
540
|
-
| `
|
|
586
|
+
| `auth(target, value)` | Store an API key (`auth("VAR", "val")`) or trigger OAuth 2.1 (`auth("https://...")`). Writes to `~/.kitsune/.env`, active immediately. |
|
|
541
587
|
| `call(tool_name, server_id, args)` | Call a tool. `server_id` optional when shapeshifted — current form used. |
|
|
542
|
-
| `key(env_var, value)` | Save an API key to `.env` and load it immediately. |
|
|
543
588
|
| `status()` | Show current form, active connections (PID + RAM), token stats. |
|
|
544
589
|
|
|
545
|
-
### `kitsune-forge` — full suite (
|
|
590
|
+
### `kitsune-forge` — full suite (~1,700 token overhead)
|
|
546
591
|
|
|
547
592
|
Everything above, plus:
|
|
548
593
|
|
|
549
594
|
| Tool | Description |
|
|
550
595
|
|---|---|
|
|
551
|
-
| `
|
|
596
|
+
| `shiftback(kill, uninstall)` | Explicit unmount. `kill=True` terminates the process. `uninstall=True` also removes a locally installed package. |
|
|
597
|
+
| `inspect(server_id)` | Show tools, schemas, and live credential status (✓/✗ per key). Measures token cost. |
|
|
552
598
|
| `run(package, tool, args)` | Run from npm/pip directly. `uvx:pkg-name` for Python. |
|
|
553
|
-
| `auto(task, tool, args)` | Search → pick best server → call in one step. |
|
|
554
599
|
| `fetch(url, intent)` | Fetch a URL, return compressed text (~17x smaller than raw HTML). |
|
|
555
|
-
| `craft(name, description, params, url)` | Register a custom tool backed by your HTTP endpoint. `
|
|
600
|
+
| `craft(name, description, params, url)` | Register a custom tool backed by your HTTP endpoint. `shapeshift()` removes it. |
|
|
556
601
|
| `connect(command, name)` | Start a persistent server. Accepts server_id or shell command. |
|
|
557
602
|
| `release(name)` | Kill a persistent connection by name. |
|
|
558
603
|
| `setup(name)` | Step-by-step setup wizard for a connected server. |
|
|
604
|
+
| `compare(query)` | Compare servers matching a query — token cost, tool count, trust tier, credential status. |
|
|
559
605
|
| `test(server_id, level)` | Quality-score a server 0–100. |
|
|
560
606
|
| `bench(server_id, tool, args)` | Benchmark tool latency — p50, p95, min, max. |
|
|
561
607
|
| `skill(qualified_name)` | Load a skill into context. Persisted across sessions. |
|
|
@@ -570,24 +616,24 @@ Everything above, plus:
|
|
|
570
616
|
# Task 1: read some files
|
|
571
617
|
shapeshift("@modelcontextprotocol/server-filesystem", tools=["read_file"])
|
|
572
618
|
read_file(path="/tmp/data.csv")
|
|
573
|
-
|
|
619
|
+
shapeshift() # unmount
|
|
574
620
|
|
|
575
621
|
# Task 2: search the web
|
|
576
622
|
shapeshift("mcp-server-brave-search")
|
|
577
623
|
brave_web_search(query="latest MCP servers 2025")
|
|
578
|
-
|
|
624
|
+
shapeshift()
|
|
579
625
|
|
|
580
626
|
# Task 3: run a git query
|
|
581
627
|
shapeshift("@modelcontextprotocol/server-git", tools=["git_log"])
|
|
582
628
|
git_log(repo_path=".", max_count=5)
|
|
583
|
-
|
|
629
|
+
shapeshift()
|
|
584
630
|
# Three different servers. One session. Zero config edits.
|
|
585
631
|
```
|
|
586
632
|
|
|
587
633
|
### MCP developer workflow — test your server
|
|
588
634
|
|
|
589
635
|
```
|
|
590
|
-
# Evaluate your server before publishing
|
|
636
|
+
# Evaluate your server before publishing (kitsune-forge)
|
|
591
637
|
inspect("my-server") # review schemas and credentials
|
|
592
638
|
test("my-server") # quality score 0–100
|
|
593
639
|
bench("my-server", "my_tool", {}) # p50, p95 latency
|
|
@@ -600,40 +646,25 @@ craft(
|
|
|
600
646
|
url="http://localhost:8080/rank"
|
|
601
647
|
)
|
|
602
648
|
my_tool(query="test") # call it natively inside Claude
|
|
603
|
-
|
|
649
|
+
shapeshift()
|
|
604
650
|
```
|
|
605
651
|
|
|
606
|
-
###
|
|
607
|
-
|
|
608
|
-
After `shapeshift()`, use `call()` immediately — no restart, no server_id needed:
|
|
652
|
+
### Auth then mount in the same session
|
|
609
653
|
|
|
610
654
|
```
|
|
611
|
-
|
|
612
|
-
# → "In this session: call('tool_name', arguments={...})"
|
|
613
|
-
|
|
614
|
-
call("list_directory", arguments={"path": "/Users/me/project"})
|
|
615
|
-
call("read_file", arguments={"path": "/Users/me/project/README.md"})
|
|
616
|
-
shiftback()
|
|
617
|
-
```
|
|
618
|
-
|
|
619
|
-
### Search, shapeshift, use, shiftback
|
|
620
|
-
|
|
621
|
-
```
|
|
622
|
-
search("web search")
|
|
655
|
+
auth("BRAVE_API_KEY", "your-key") # written to ~/.kitsune/.env immediately
|
|
623
656
|
shapeshift("mcp-server-brave-search")
|
|
624
|
-
key("BRAVE_API_KEY", "your-key") # picked up immediately
|
|
625
657
|
call("brave_web_search", arguments={"query": "MCP protocol 2025"})
|
|
626
|
-
|
|
658
|
+
shapeshift()
|
|
627
659
|
```
|
|
628
660
|
|
|
629
|
-
###
|
|
661
|
+
### OAuth-authenticated hosted server
|
|
630
662
|
|
|
631
663
|
```
|
|
632
|
-
#
|
|
633
|
-
shapeshift("
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
shiftback(uninstall=True) # remove tools AND uninstall the package
|
|
664
|
+
auth("https://mcp.notion.com/mcp") # browser opens, you approve
|
|
665
|
+
shapeshift("https://mcp.notion.com/mcp", tools=["notion-search"])
|
|
666
|
+
call("notion-search", arguments={"query": "roadmap"})
|
|
667
|
+
shapeshift()
|
|
637
668
|
```
|
|
638
669
|
|
|
639
670
|
### Persistent server with setup guidance
|
|
@@ -641,11 +672,11 @@ shiftback(uninstall=True) # remove tools AND uninstall the package
|
|
|
641
672
|
```
|
|
642
673
|
connect("uvx voice-mode", name="voice")
|
|
643
674
|
setup("voice") # shows missing env vars
|
|
644
|
-
|
|
675
|
+
auth("DEEPGRAM_API_KEY", "your-key")
|
|
645
676
|
setup("voice") # confirms ready
|
|
646
677
|
shapeshift("voice-mode")
|
|
647
678
|
speak(text="Hello from Kitsune MCP!")
|
|
648
|
-
|
|
679
|
+
shapeshift()
|
|
649
680
|
```
|
|
650
681
|
|
|
651
682
|
---
|
|
@@ -666,6 +697,36 @@ npx kitsune-mcp # if you prefer npm (delegates to uvx internally)
|
|
|
666
697
|
|
|
667
698
|
---
|
|
668
699
|
|
|
700
|
+
## Built for two audiences
|
|
701
|
+
|
|
702
|
+
### Adaptive agents
|
|
703
|
+
|
|
704
|
+
An agent that loads everything upfront burns tokens on tools it never calls — and makes worse decisions because it sees too many options at once. An agent that mounts on demand is leaner, faster, and more focused:
|
|
705
|
+
|
|
706
|
+
- Shapeshift into only what the current task needs — release when done
|
|
707
|
+
- `shapeshift(server_id, tools=[...])` to cherry-pick — load 2 tools from a server that has 20
|
|
708
|
+
- Chain across multiple servers in one session without touching config or restarting
|
|
709
|
+
- Token overhead stays flat: ~400 base + only what you load
|
|
710
|
+
|
|
711
|
+
Kitsune MCP is designed around the real economics of an agent loop.
|
|
712
|
+
|
|
713
|
+
### MCP developers
|
|
714
|
+
|
|
715
|
+
Beyond MCP Inspector's basic schema viewer, Kitsune MCP gives you a full development workflow inside your actual AI client:
|
|
716
|
+
|
|
717
|
+
| Need | Tool |
|
|
718
|
+
|---|---|
|
|
719
|
+
| Explore a server's tools and schemas | `inspect(server_id)` |
|
|
720
|
+
| Quality-score your server end-to-end | `test(server_id)` → score 0–100 |
|
|
721
|
+
| Benchmark tool latency | `bench(server_id, tool, args)` → p50, p95, min, max |
|
|
722
|
+
| Prototype endpoint-backed tools live | `craft(name, description, params, url)` |
|
|
723
|
+
| Test inside real Claude/Cursor workflows | `shapeshift()` → call tools natively → `shapeshift()` |
|
|
724
|
+
| Compare two servers side by side | `compare("notion")` — token cost, tool count, trust, cred status |
|
|
725
|
+
|
|
726
|
+
No separate web UI. No isolated test environment. Test how your server actually behaves when an AI uses it.
|
|
727
|
+
|
|
728
|
+
---
|
|
729
|
+
|
|
669
730
|
## Contributing
|
|
670
731
|
|
|
671
732
|
```bash
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kitsune-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.1",
|
|
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": {
|