Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion extensions/cate.mcp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Built directly on the official [`@modelcontextprotocol/sdk`](https://www.npmjs.c

- **Unified MCP endpoint at `/mcp`**: the extension server itself is an MCP server (streamable HTTP) aggregating every tool/resource/prompt of every enabled and running managed server, deterministically namespaced `<server>__<name>`. Upstream failures come back as tool errors, never protocol crashes; `listChanged` fires when upstreams change. Auth is the same bearer token Cate injects. The panel's Endpoint card shows the URL and header with copy buttons; point any MCP client (including a coding agent) at it.

- **One-click install into coding agents**: the Endpoint screen writes this endpoint into each agent's workspace-local config — Cate Agent (`.pi/mcp.json`, read by the `pi-mcp-adapter` package), Claude Code (`.mcp.json`), Cursor (`.cursor/mcp.json`), OpenCode (`opencode.json`), and Codex (`.codex/config.toml`), each in that agent's own shape, preserving every other key. Antigravity (global-only config) and PI (no MCP) are listed but disabled with the reason. The endpoint's port/token are reminted each Cate session, so an install is a snapshot: a stale entry is flagged with an Update button, and the endpoint only serves while the panel is open.
- **One-click install into coding agents**: the Endpoint screen writes this endpoint into each agent's workspace-local config — Agent panel (`.pi/mcp.json`, read by the `pi-mcp-adapter` package), Claude Code (`.mcp.json`), Cursor (`.cursor/mcp.json`), OpenCode (`opencode.json`), and Codex (`.codex/config.toml`), each in that agent's own shape, preserving every other key. Antigravity (global-only config) and PI (no MCP) are listed but disabled with the reason. The endpoint's port/token are reminted each Cate session, so an install is a snapshot: a stale entry is flagged with an Update button, and the endpoint only serves while the panel is open.

- **Discover tab**: searches the official registry at `registry.modelcontextprotocol.io` (`GET /v0/servers?search=…` with cursor pagination) and one-click prefills the add-server form from a registry entry's npm/pypi/oci package or remote URL. Registry failures stay inside that tab.

Expand Down
2 changes: 1 addition & 1 deletion extensions/cate.mcp/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "cate.mcp",
"name": "MCP Servers",
"version": "1.3.0",
"version": "1.3.1",
"description": "Native MCP server manager. Configure stdio and remote MCP servers in .cate/mcp.json, supervise them with health checks and auto-restart, browse their tools/resources/prompts, invoke tools from a playground, discover servers in the official MCP registry, and expose everything through one aggregated MCP endpoint any client can connect to.",
"panels": [
{
Expand Down
2 changes: 1 addition & 1 deletion extensions/cate.mcp/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "cate-mcp-extension",
"private": true,
"version": "1.3.0",
"version": "1.3.1",
"description": "Native MCP server manager, a server-backed Cate extension.",
"scripts": {
"clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
Expand Down
10 changes: 5 additions & 5 deletions extensions/cate.mcp/src/server/agent-install.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ describe('AgentInstaller.list', () => {
it('lists all agents; two are unsupported with a reason', () => {
const agents = new AgentInstaller(tmp).list(EP)
expect(agents.map((a) => a.id).sort()).toEqual(
['antigravity', 'cate-agent', 'claude-code', 'codex', 'cursor', 'opencode', 'pi'].sort(),
['agent-panel', 'antigravity', 'claude-code', 'codex', 'cursor', 'opencode', 'pi'].sort(),
)
const anti = agents.find((a) => a.id === 'antigravity')!
const pi = agents.find((a) => a.id === 'pi')!
expect(anti.supported).toBe(false)
expect(anti.reason).toBeTruthy()
expect(pi.supported).toBe(false)
expect(agents.filter((a) => a.supported).map((a) => a.id).sort()).toEqual(
['cate-agent', 'claude-code', 'codex', 'cursor', 'opencode'],
['agent-panel', 'claude-code', 'codex', 'cursor', 'opencode'],
)
})

Expand Down Expand Up @@ -99,13 +99,13 @@ describe('Claude Code (.mcp.json)', () => {
})
})

describe('Cate Agent (.pi/mcp.json, read by pi-mcp-adapter)', () => {
describe('Agent panel (.pi/mcp.json, read by pi-mcp-adapter)', () => {
it('installs a url entry the adapter can read', () => {
const inst = new AgentInstaller(tmp)
expect(inst.install('cate-agent', EP)).toEqual({ ok: true })
expect(inst.install('agent-panel', EP)).toEqual({ ok: true })
const entry = JSON.parse(read('.pi/mcp.json')).mcpServers[ENTRY_NAME]
expect(entry).toEqual({ url: EP.url, headers: { Authorization: `Bearer ${EP.token}` } })
expect(statusOf(inst, 'cate-agent').installed).toBe(true)
expect(statusOf(inst, 'agent-panel').installed).toBe(true)
})
})

Expand Down
6 changes: 3 additions & 3 deletions extensions/cate.mcp/src/server/agent-install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,13 +228,13 @@ function unsupported(id: string, label: string, relPath: string, reason: string)
// --- registry ---------------------------------------------------------------

const ADAPTERS: Adapter[] = [
// Cate's own in-app agent (pi). pi has no native MCP, so this targets the
// The in-app agent panel (pi). pi has no native MCP, so this targets the
// `pi-mcp-adapter` package's project-local pi config (`.pi/mcp.json`): a
// top-level mcpServers map where a remote server is `url` + `headers`. The
// adapter reads it on session start and proxies each server's tools.
jsonAdapter({
id: 'cate-agent',
label: 'Cate Agent',
id: 'agent-panel',
label: 'Agent panel',
relPath: '.pi/mcp.json',
sectionKey: 'mcpServers',
buildEntry: (ep) => ({ url: ep.url, headers: bearer(ep.token) }),
Expand Down
Loading