kitsune-mcp 0.15.0 → 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 +245 -162
- 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
|
-
##
|
|
31
|
+
## The problem: static tool loading
|
|
36
32
|
|
|
37
|
-
|
|
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.
|
|
38
34
|
|
|
39
|
-
|
|
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.
|
|
40
36
|
|
|
41
|
-
|
|
42
|
-
|
|
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
|
+
```
|
|
43
42
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
> *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.*
|
|
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
|
|
70
|
+
|
|
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.
|
|
68
105
|
|
|
69
|
-
|
|
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
|
|
169
|
+
## The 6-tool surface
|
|
135
170
|
|
|
136
|
-
|
|
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
|
|
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:
|
|
142
172
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
### MCP developers
|
|
146
|
-
|
|
147
|
-
Beyond MCP Inspector's basic schema viewer, Kitsune MCP gives you a full development workflow inside your actual AI client:
|
|
148
|
-
|
|
149
|
-
| Need | Tool |
|
|
173
|
+
| Tool | What it does |
|
|
150
174
|
|---|---|
|
|
151
|
-
|
|
|
152
|
-
|
|
|
153
|
-
|
|
|
154
|
-
|
|
|
155
|
-
|
|
|
156
|
-
|
|
|
157
|
-
|
|
158
|
-
No separate web UI. No isolated test environment. Test how your server actually behaves when an AI uses it.
|
|
159
|
-
|
|
160
|
-
---
|
|
161
|
-
|
|
162
|
-
## Why MCP — not a CLI skill
|
|
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. |
|
|
163
181
|
|
|
164
|
-
|
|
182
|
+
**Overhead at rest: ~420 tokens.** Each mount adds only what you load — `tools=["web_search"]` is ~300 tokens, not 1,500.
|
|
165
183
|
|
|
166
|
-
|
|
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,6 +265,41 @@ 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
|
+
|
|
281
|
+
### Using Kitsune alongside existing servers
|
|
282
|
+
|
|
283
|
+
You can add Kitsune to a config that already has other servers — it works without touching anything else.
|
|
284
|
+
|
|
285
|
+
**Kitsune never deletes or modifies your existing configs without explicit confirmation.** Config changes are always backed up and reversible.
|
|
286
|
+
|
|
287
|
+
### Run Kitsune and standard MCP side-by-side (Claude Code)
|
|
288
|
+
|
|
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**:
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
# Terminal A — Kitsune-only project (6 tools, clean context)
|
|
293
|
+
mkdir ~/projects/kitsune-session
|
|
294
|
+
echo '{"mcpServers":{"kitsune":{"command":"kitsune-mcp"}}}' > ~/projects/kitsune-session/.claude/mcp.json
|
|
295
|
+
cd ~/projects/kitsune-session && claude
|
|
296
|
+
|
|
297
|
+
# Terminal B — standard workflow (all your configured servers)
|
|
298
|
+
cd ~/projects/any-other-project && claude # uses global ~/.claude/mcp.json
|
|
299
|
+
```
|
|
300
|
+
|
|
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.
|
|
302
|
+
|
|
246
303
|
---
|
|
247
304
|
|
|
248
305
|
## Server Sources
|
|
@@ -292,7 +349,7 @@ Kitsune MCP ← the one entry in your config
|
|
|
292
349
|
|
|
293
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.
|
|
294
351
|
|
|
295
|
-
`
|
|
352
|
+
`shapeshift()` with no args reverses all of it: deregisters the proxy closures, clears resources and prompts, notifies the client.
|
|
296
353
|
|
|
297
354
|
### Resources and prompts
|
|
298
355
|
|
|
@@ -317,9 +374,21 @@ Template URIs (e.g. `file:///{path}`) are skipped — they require parameter bin
|
|
|
317
374
|
| Smithery hosted | HTTP+SSE (requires `SMITHERY_API_KEY`) |
|
|
318
375
|
| WebSocket server | `ws://` / `wss://` |
|
|
319
376
|
|
|
320
|
-
###
|
|
377
|
+
### Cold start latency (typical ranges)
|
|
378
|
+
|
|
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()
|
|
321
390
|
|
|
322
|
-
`inspect()` connects to the server and fetches its schemas — but does **not** register anything. Zero tools added to context, zero tokens consumed by the AI.
|
|
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.
|
|
323
392
|
|
|
324
393
|
Use it to:
|
|
325
394
|
- See exact parameter names and types before committing
|
|
@@ -331,11 +400,11 @@ Use it to:
|
|
|
331
400
|
inspect("mcp-server-brave-search")
|
|
332
401
|
# → CREDENTIALS
|
|
333
402
|
# → ✗ missing BRAVE_API_KEY — Brave Search API key
|
|
334
|
-
# → Add
|
|
403
|
+
# → Add: auth("BRAVE_API_KEY", "your-value")
|
|
335
404
|
# → Token cost: ~99 tokens (measured)
|
|
336
405
|
|
|
337
|
-
# Add the key
|
|
338
|
-
|
|
406
|
+
# Add the key — picked up immediately, no restart needed
|
|
407
|
+
auth("BRAVE_API_KEY", "your-value")
|
|
339
408
|
shapeshift("mcp-server-brave-search")
|
|
340
409
|
call("brave_web_search", arguments={"query": "MCP protocol 2025"})
|
|
341
410
|
```
|
|
@@ -344,11 +413,9 @@ call("brave_web_search", arguments={"query": "MCP protocol 2025"})
|
|
|
344
413
|
|
|
345
414
|
## Security
|
|
346
415
|
|
|
347
|
-
Kitsune MCP introduces a trust model for servers you haven't personally audited.
|
|
348
|
-
|
|
349
416
|
### Trust tiers
|
|
350
417
|
|
|
351
|
-
Every `shapeshift()
|
|
418
|
+
Every `shapeshift()` and `call()` result shows where the server comes from:
|
|
352
419
|
|
|
353
420
|
| Tier | Sources | Indicator |
|
|
354
421
|
|---|---|---|
|
|
@@ -356,7 +423,7 @@ Every `shapeshift()`, `call()`, and `connect()` result shows where the server co
|
|
|
356
423
|
| Medium | `mcpregistry`, `glama`, `smithery` | `✓ Source: smithery` |
|
|
357
424
|
| Community | `npm`, `pypi`, `github` | `⚠️ Source: npm (community — not verified)` |
|
|
358
425
|
|
|
359
|
-
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.
|
|
360
427
|
|
|
361
428
|
### Install command validation
|
|
362
429
|
|
|
@@ -368,10 +435,10 @@ Arguments are passed directly to `asyncio.create_subprocess_exec` (never a shell
|
|
|
368
435
|
|
|
369
436
|
### OAuth 2.1 for hosted MCP servers
|
|
370
437
|
|
|
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
|
|
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:
|
|
372
439
|
|
|
373
440
|
```python
|
|
374
|
-
|
|
441
|
+
auth("https://mcp.notion.com/mcp")
|
|
375
442
|
# First use: browser opens, you approve, tokens are cached.
|
|
376
443
|
# Subsequent runs: cached token loaded silently, refreshed when expired.
|
|
377
444
|
|
|
@@ -390,7 +457,7 @@ Headless or no-browser environments: set `KITSUNE_NO_BROWSER=1` to have Kitsune
|
|
|
390
457
|
```
|
|
391
458
|
⚠️ Credentials may be required — add to .env:
|
|
392
459
|
BRAVE_API_KEY=your-value
|
|
393
|
-
Or:
|
|
460
|
+
Or: auth("BRAVE_API_KEY", "your-value")
|
|
394
461
|
```
|
|
395
462
|
|
|
396
463
|
### Process isolation and sandboxing
|
|
@@ -420,30 +487,24 @@ The same pattern works for all of them:
|
|
|
420
487
|
```
|
|
421
488
|
shapeshift("brave") # web search in 2 tools
|
|
422
489
|
call("brave_web_search", arguments={"query": "…"})
|
|
490
|
+
shapeshift()
|
|
423
491
|
|
|
424
492
|
shapeshift("firecrawl-mcp", tools=["scrape","search"]) # scraping, lean (2 of 9 tools)
|
|
425
493
|
call("scrape", arguments={"url": "https://…"})
|
|
494
|
+
shapeshift()
|
|
426
495
|
|
|
427
496
|
shapeshift("@modelcontextprotocol/server-github", tools=["create_issue","search_repositories"])
|
|
428
497
|
call("create_issue", arguments={"owner": "…", "repo": "…", "title": "…"})
|
|
498
|
+
shapeshift()
|
|
429
499
|
```
|
|
430
500
|
|
|
431
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.
|
|
432
502
|
|
|
433
|
-
### Security note on `.env`
|
|
434
|
-
|
|
435
|
-
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:
|
|
436
|
-
|
|
437
|
-
- Add `.env` to `.gitignore` — never commit real keys
|
|
438
|
-
- Use project-level `.env` for project-specific keys; `~/.kitsune/.env` for personal global keys
|
|
439
|
-
- Prefer minimal OAuth scopes and fine-grained tokens (e.g. GitHub fine-grained tokens with per-repo permissions)
|
|
440
|
-
- Rotate keys that get exposed; Kitsune MCP picks up the new value immediately without restart
|
|
441
|
-
|
|
442
503
|
---
|
|
443
504
|
|
|
444
505
|
## Why Not Just X?
|
|
445
506
|
|
|
446
|
-
**"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.
|
|
447
508
|
|
|
448
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.
|
|
449
510
|
|
|
@@ -457,7 +518,7 @@ Kitsune MCP re-reads `.env` on every call — which means adding a key instantly
|
|
|
457
518
|
| Load tools at runtime | ✅ (write code) | ✅ `shapeshift()` |
|
|
458
519
|
| Search registries to discover servers | ❌ | ✅ npm · official · Glama · Smithery |
|
|
459
520
|
| Install npm / PyPI / GitHub packages on demand | ❌ | ✅ |
|
|
460
|
-
| Atomic
|
|
521
|
+
| Atomic release — retract all shapeshifted tools at once | ❌ | ✅ `shapeshift()` |
|
|
461
522
|
| Persistent stdio process pool | ❌ | ✅ |
|
|
462
523
|
| Zero boilerplate — works after `pip install` | ❌ | ✅ |
|
|
463
524
|
|
|
@@ -470,7 +531,7 @@ Kitsune MCP re-reads `.env` on every call — which means adding a key instantly
|
|
|
470
531
|
```json
|
|
471
532
|
{
|
|
472
533
|
"mcpServers": {
|
|
473
|
-
"
|
|
534
|
+
"kitsune": { "command": "kitsune-mcp" }
|
|
474
535
|
}
|
|
475
536
|
}
|
|
476
537
|
```
|
|
@@ -490,50 +551,57 @@ Kitsune MCP re-reads `.env` on every call — which means adding a key instantly
|
|
|
490
551
|
|
|
491
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.
|
|
492
553
|
|
|
493
|
-
**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:
|
|
494
555
|
|
|
495
556
|
```
|
|
496
|
-
# .env (CWD, ~/.env, or ~/.kitsune/.env — all checked,
|
|
557
|
+
# .env (CWD, ~/.env, or ~/.kitsune/.env — all checked, ~/.kitsune/.env wins)
|
|
497
558
|
BRAVE_API_KEY=your-key
|
|
498
559
|
GITHUB_TOKEN=ghp_...
|
|
499
560
|
```
|
|
500
561
|
|
|
501
|
-
Or use `
|
|
562
|
+
Or use `auth()` to write to `.env` and activate in one step:
|
|
502
563
|
|
|
503
564
|
```
|
|
504
|
-
|
|
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
|
|
505
573
|
```
|
|
506
574
|
|
|
507
575
|
---
|
|
508
576
|
|
|
509
577
|
## All Tools
|
|
510
578
|
|
|
511
|
-
### `kitsune-mcp` — lean profile (
|
|
579
|
+
### `kitsune-mcp` — lean profile (6 tools, ~420 token overhead)
|
|
512
580
|
|
|
513
581
|
| Tool | Description |
|
|
514
582
|
|---|---|
|
|
515
|
-
| `
|
|
516
|
-
| `
|
|
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. |
|
|
517
585
|
| `search(query, registry)` | Search MCP servers across registries. |
|
|
518
|
-
| `
|
|
586
|
+
| `auth(target, value)` | Store an API key (`auth("VAR", "val")`) or trigger OAuth 2.1 (`auth("https://...")`). Writes to `~/.kitsune/.env`, active immediately. |
|
|
519
587
|
| `call(tool_name, server_id, args)` | Call a tool. `server_id` optional when shapeshifted — current form used. |
|
|
520
|
-
| `key(env_var, value)` | Save an API key to `.env` and load it immediately. |
|
|
521
588
|
| `status()` | Show current form, active connections (PID + RAM), token stats. |
|
|
522
589
|
|
|
523
|
-
### `kitsune-forge` — full suite (
|
|
590
|
+
### `kitsune-forge` — full suite (~1,700 token overhead)
|
|
524
591
|
|
|
525
592
|
Everything above, plus:
|
|
526
593
|
|
|
527
594
|
| Tool | Description |
|
|
528
595
|
|---|---|
|
|
529
|
-
| `
|
|
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. |
|
|
530
598
|
| `run(package, tool, args)` | Run from npm/pip directly. `uvx:pkg-name` for Python. |
|
|
531
|
-
| `auto(task, tool, args)` | Search → pick best server → call in one step. |
|
|
532
599
|
| `fetch(url, intent)` | Fetch a URL, return compressed text (~17x smaller than raw HTML). |
|
|
533
|
-
| `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. |
|
|
534
601
|
| `connect(command, name)` | Start a persistent server. Accepts server_id or shell command. |
|
|
535
602
|
| `release(name)` | Kill a persistent connection by name. |
|
|
536
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. |
|
|
537
605
|
| `test(server_id, level)` | Quality-score a server 0–100. |
|
|
538
606
|
| `bench(server_id, tool, args)` | Benchmark tool latency — p50, p95, min, max. |
|
|
539
607
|
| `skill(qualified_name)` | Load a skill into context. Persisted across sessions. |
|
|
@@ -548,24 +616,24 @@ Everything above, plus:
|
|
|
548
616
|
# Task 1: read some files
|
|
549
617
|
shapeshift("@modelcontextprotocol/server-filesystem", tools=["read_file"])
|
|
550
618
|
read_file(path="/tmp/data.csv")
|
|
551
|
-
|
|
619
|
+
shapeshift() # unmount
|
|
552
620
|
|
|
553
621
|
# Task 2: search the web
|
|
554
622
|
shapeshift("mcp-server-brave-search")
|
|
555
623
|
brave_web_search(query="latest MCP servers 2025")
|
|
556
|
-
|
|
624
|
+
shapeshift()
|
|
557
625
|
|
|
558
626
|
# Task 3: run a git query
|
|
559
627
|
shapeshift("@modelcontextprotocol/server-git", tools=["git_log"])
|
|
560
628
|
git_log(repo_path=".", max_count=5)
|
|
561
|
-
|
|
629
|
+
shapeshift()
|
|
562
630
|
# Three different servers. One session. Zero config edits.
|
|
563
631
|
```
|
|
564
632
|
|
|
565
633
|
### MCP developer workflow — test your server
|
|
566
634
|
|
|
567
635
|
```
|
|
568
|
-
# Evaluate your server before publishing
|
|
636
|
+
# Evaluate your server before publishing (kitsune-forge)
|
|
569
637
|
inspect("my-server") # review schemas and credentials
|
|
570
638
|
test("my-server") # quality score 0–100
|
|
571
639
|
bench("my-server", "my_tool", {}) # p50, p95 latency
|
|
@@ -578,40 +646,25 @@ craft(
|
|
|
578
646
|
url="http://localhost:8080/rank"
|
|
579
647
|
)
|
|
580
648
|
my_tool(query="test") # call it natively inside Claude
|
|
581
|
-
|
|
649
|
+
shapeshift()
|
|
582
650
|
```
|
|
583
651
|
|
|
584
|
-
###
|
|
585
|
-
|
|
586
|
-
After `shapeshift()`, use `call()` immediately — no restart, no server_id needed:
|
|
652
|
+
### Auth then mount in the same session
|
|
587
653
|
|
|
588
654
|
```
|
|
589
|
-
|
|
590
|
-
# → "In this session: call('tool_name', arguments={...})"
|
|
591
|
-
|
|
592
|
-
call("list_directory", arguments={"path": "/Users/me/project"})
|
|
593
|
-
call("read_file", arguments={"path": "/Users/me/project/README.md"})
|
|
594
|
-
shiftback()
|
|
595
|
-
```
|
|
596
|
-
|
|
597
|
-
### Search, shapeshift, use, shiftback
|
|
598
|
-
|
|
599
|
-
```
|
|
600
|
-
search("web search")
|
|
655
|
+
auth("BRAVE_API_KEY", "your-key") # written to ~/.kitsune/.env immediately
|
|
601
656
|
shapeshift("mcp-server-brave-search")
|
|
602
|
-
key("BRAVE_API_KEY", "your-key") # picked up immediately
|
|
603
657
|
call("brave_web_search", arguments={"query": "MCP protocol 2025"})
|
|
604
|
-
|
|
658
|
+
shapeshift()
|
|
605
659
|
```
|
|
606
660
|
|
|
607
|
-
###
|
|
661
|
+
### OAuth-authenticated hosted server
|
|
608
662
|
|
|
609
663
|
```
|
|
610
|
-
#
|
|
611
|
-
shapeshift("
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
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()
|
|
615
668
|
```
|
|
616
669
|
|
|
617
670
|
### Persistent server with setup guidance
|
|
@@ -619,11 +672,11 @@ shiftback(uninstall=True) # remove tools AND uninstall the package
|
|
|
619
672
|
```
|
|
620
673
|
connect("uvx voice-mode", name="voice")
|
|
621
674
|
setup("voice") # shows missing env vars
|
|
622
|
-
|
|
675
|
+
auth("DEEPGRAM_API_KEY", "your-key")
|
|
623
676
|
setup("voice") # confirms ready
|
|
624
677
|
shapeshift("voice-mode")
|
|
625
678
|
speak(text="Hello from Kitsune MCP!")
|
|
626
|
-
|
|
679
|
+
shapeshift()
|
|
627
680
|
```
|
|
628
681
|
|
|
629
682
|
---
|
|
@@ -644,6 +697,36 @@ npx kitsune-mcp # if you prefer npm (delegates to uvx internally)
|
|
|
644
697
|
|
|
645
698
|
---
|
|
646
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
|
+
|
|
647
730
|
## Contributing
|
|
648
731
|
|
|
649
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": {
|