pi-mcp-py 0.1.0__tar.gz

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.
@@ -0,0 +1,34 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .eggs/
5
+ dist/
6
+ build/
7
+ !tui/crates/build/
8
+ .pytest_cache/
9
+ .pytest-audit/
10
+ .mypy_cache/
11
+ .ruff_cache/
12
+ .venv/
13
+ .venv-*/
14
+ venv/
15
+ .env
16
+ # Rust TUI workspace (Apache-2.0 fork under tui/)
17
+ tui/target/
18
+ **/*.rs.bk
19
+
20
+ # Benchmark evaluation cache and trial artifacts
21
+ .cache/
22
+ .pi-eval/
23
+
24
+ # Temporary files, coverage and logs
25
+ *.log
26
+ *.tmp
27
+ *.bak
28
+ *.swp
29
+ *.orig
30
+ .coverage
31
+ .coverage.*
32
+ coverage.xml
33
+ htmlcov/
34
+
@@ -0,0 +1,83 @@
1
+ Metadata-Version: 2.5
2
+ Name: pi-mcp-py
3
+ Version: 0.1.0
4
+ Summary: Connects the MCP servers an ACP client passes to the pi-python agent (an extension)
5
+ Project-URL: Homepage, https://github.com/zy1233/pi-python
6
+ Project-URL: Repository, https://github.com/zy1233/pi-python
7
+ Author-email: zy1233 <zy1233@users.noreply.github.com>
8
+ License-Expression: MIT
9
+ Keywords: acp,agent,extension,mcp,pi
10
+ Requires-Python: >=3.11
11
+ Requires-Dist: anyio>=4.5
12
+ Requires-Dist: httpx>=0.27
13
+ Requires-Dist: langchain-mcp-adapters>=0.3.2
14
+ Requires-Dist: mcp<2,>=1.30
15
+ Requires-Dist: pi-agent-core-lc>=0.6.0
16
+ Description-Content-Type: text/markdown
17
+
18
+ # pi-mcp-py
19
+
20
+ An extension for [pi-python](https://github.com/zy1233/pi-python). It connects the MCP servers that an
21
+ ACP client (an editor such as Zed) passes to the agent, and gives their tools to the model.
22
+
23
+ The agent itself has no MCP client. Without this package, the servers that the editor passes are not
24
+ connected, and the agent says so. With it, the agent connects them.
25
+
26
+ Install it into the environment of the agent:
27
+
28
+ ```bash
29
+ pip install pi-mcp-py
30
+ ```
31
+
32
+ The package is on PyPI from the 0.6.0 release of pi-python. In a checkout of the repository, use
33
+ `pip install -e ./packages/pi-mcp`.
34
+
35
+ Nothing else to set up. The servers come from the editor (Zed: `context_servers` in the settings).
36
+ It needs `pi-agent-core-lc` 0.6.0 or later: an older core does not hand over the servers of the
37
+ client, and then the package logs a warning and does nothing.
38
+
39
+ ## What it does
40
+
41
+ - Connects `stdio`, `http` (Streamable HTTP) and `sse` servers. One connection for each server and
42
+ session. A server that does not start does not stop the session, nor the other servers.
43
+ - Gives each tool to the model as `mcp__<server>__<tool>`. The prefix keeps an MCP tool from replacing a
44
+ built-in tool of the same name. A name longer than 64 characters is cut and gets a hash at the end.
45
+ - Tells the user when a server fails to start or is slow. It says nothing when all is well.
46
+ - Connects a server again when it has stopped: the next tool call does it, at most 3 times in a row (a
47
+ call that gets an answer starts the count again). A call that was already sent when the server died
48
+ is not sent again, because the server may have run it. It fails with the reason.
49
+ - `/mcp` shows the servers, their state and the number of tools. `/mcp reconnect <name>` connects one
50
+ again, with no limit.
51
+ - Ends every server process when the session ends (Windows and Linux).
52
+ - Limits: a server may take 60 s to start and a call 120 s (see **Settings**). The first turn waits at
53
+ most 10 s for a server that still starts. A tool result of more than 50 KB of text is cut, and a note
54
+ says so.
55
+
56
+ ## Things to know
57
+
58
+ - **Permissions.** A tool call is asked about in the `ask` mode of the CLI, unless the server marks the
59
+ tool with a hint that says it is harmless (`readOnlyHint`). The hints are taken as the server gives
60
+ them: you chose the server.
61
+ - **Environment of a stdio server.** It gets the safe list of the MCP SDK, the proxy and certificate
62
+ variables of the agent (`HTTP_PROXY`, `SSL_CERT_FILE`, ...), and the `env` of the editor. It does not
63
+ get the other variables of the agent, the LLM keys among them. `${VAR}` in a value is not expanded.
64
+ - **Secrets.** The `env`, `headers`, `args` and `url` of a server are not written to a log, a notice, the
65
+ `/mcp` output or an error text.
66
+ - **Logs.** The stderr of a stdio server goes to `<PI_HOME>/logs/mcp/<name>.log` (`PI_HOME` is
67
+ `~/.pi-python` when it is not set). The file is appended to, and started over when it is larger than
68
+ 512 KB. The text of the file is what the server wrote: it may hold what the server was given.
69
+ - **Servers on this machine.** An `http` or `sse` server at `localhost`, `127.0.0.1` or `::1` is
70
+ reached directly, not through the proxy of the system (`httpx` would send it there).
71
+ - **Not supported:** MCP resources, prompts, sampling, roots, elicitation, OAuth, `tools/list_changed`,
72
+ websocket servers.
73
+
74
+ ## Settings
75
+
76
+ Environment variables only:
77
+
78
+ | Variable | Default | Meaning |
79
+ |----------|---------|---------|
80
+ | `PI_MCP_STARTUP_TIMEOUT` | 60 | Seconds a server may take to start. Then it counts as failed. |
81
+ | `PI_MCP_CALL_TIMEOUT` | 120 | Seconds a tool call may take. |
82
+
83
+ The design is in `docs/specs/2026-10-23-mcp-extension-design.md` of the repository.
@@ -0,0 +1,66 @@
1
+ # pi-mcp-py
2
+
3
+ An extension for [pi-python](https://github.com/zy1233/pi-python). It connects the MCP servers that an
4
+ ACP client (an editor such as Zed) passes to the agent, and gives their tools to the model.
5
+
6
+ The agent itself has no MCP client. Without this package, the servers that the editor passes are not
7
+ connected, and the agent says so. With it, the agent connects them.
8
+
9
+ Install it into the environment of the agent:
10
+
11
+ ```bash
12
+ pip install pi-mcp-py
13
+ ```
14
+
15
+ The package is on PyPI from the 0.6.0 release of pi-python. In a checkout of the repository, use
16
+ `pip install -e ./packages/pi-mcp`.
17
+
18
+ Nothing else to set up. The servers come from the editor (Zed: `context_servers` in the settings).
19
+ It needs `pi-agent-core-lc` 0.6.0 or later: an older core does not hand over the servers of the
20
+ client, and then the package logs a warning and does nothing.
21
+
22
+ ## What it does
23
+
24
+ - Connects `stdio`, `http` (Streamable HTTP) and `sse` servers. One connection for each server and
25
+ session. A server that does not start does not stop the session, nor the other servers.
26
+ - Gives each tool to the model as `mcp__<server>__<tool>`. The prefix keeps an MCP tool from replacing a
27
+ built-in tool of the same name. A name longer than 64 characters is cut and gets a hash at the end.
28
+ - Tells the user when a server fails to start or is slow. It says nothing when all is well.
29
+ - Connects a server again when it has stopped: the next tool call does it, at most 3 times in a row (a
30
+ call that gets an answer starts the count again). A call that was already sent when the server died
31
+ is not sent again, because the server may have run it. It fails with the reason.
32
+ - `/mcp` shows the servers, their state and the number of tools. `/mcp reconnect <name>` connects one
33
+ again, with no limit.
34
+ - Ends every server process when the session ends (Windows and Linux).
35
+ - Limits: a server may take 60 s to start and a call 120 s (see **Settings**). The first turn waits at
36
+ most 10 s for a server that still starts. A tool result of more than 50 KB of text is cut, and a note
37
+ says so.
38
+
39
+ ## Things to know
40
+
41
+ - **Permissions.** A tool call is asked about in the `ask` mode of the CLI, unless the server marks the
42
+ tool with a hint that says it is harmless (`readOnlyHint`). The hints are taken as the server gives
43
+ them: you chose the server.
44
+ - **Environment of a stdio server.** It gets the safe list of the MCP SDK, the proxy and certificate
45
+ variables of the agent (`HTTP_PROXY`, `SSL_CERT_FILE`, ...), and the `env` of the editor. It does not
46
+ get the other variables of the agent, the LLM keys among them. `${VAR}` in a value is not expanded.
47
+ - **Secrets.** The `env`, `headers`, `args` and `url` of a server are not written to a log, a notice, the
48
+ `/mcp` output or an error text.
49
+ - **Logs.** The stderr of a stdio server goes to `<PI_HOME>/logs/mcp/<name>.log` (`PI_HOME` is
50
+ `~/.pi-python` when it is not set). The file is appended to, and started over when it is larger than
51
+ 512 KB. The text of the file is what the server wrote: it may hold what the server was given.
52
+ - **Servers on this machine.** An `http` or `sse` server at `localhost`, `127.0.0.1` or `::1` is
53
+ reached directly, not through the proxy of the system (`httpx` would send it there).
54
+ - **Not supported:** MCP resources, prompts, sampling, roots, elicitation, OAuth, `tools/list_changed`,
55
+ websocket servers.
56
+
57
+ ## Settings
58
+
59
+ Environment variables only:
60
+
61
+ | Variable | Default | Meaning |
62
+ |----------|---------|---------|
63
+ | `PI_MCP_STARTUP_TIMEOUT` | 60 | Seconds a server may take to start. Then it counts as failed. |
64
+ | `PI_MCP_CALL_TIMEOUT` | 120 | Seconds a tool call may take. |
65
+
66
+ The design is in `docs/specs/2026-10-23-mcp-extension-design.md` of the repository.
@@ -0,0 +1,71 @@
1
+ """pi-mcp: connect the MCP servers that an ACP client passes (design: docs/specs/2026-10-23-mcp-
2
+ extension-design.md).
3
+
4
+ An editor such as Zed hands the agent its configured MCP servers in ``session/new``,
5
+ ``session/load`` and ``session/resume``. The agent has no MCP client of its own. This extension
6
+ connects them: stdio, http and sse servers, one connection per server and session. Their tools
7
+ reach the model as ``mcp__<server>__<tool>``; ``/mcp`` shows the state of the servers.
8
+
9
+ Install: ``pip install pi-mcp-py`` (or ``pip install -e ./packages/pi-mcp`` from a checkout of the
10
+ repository). Nothing is configured here: the servers come from the editor.
11
+
12
+ Environment variables:
13
+ - ``PI_MCP_STARTUP_TIMEOUT`` -- seconds a server may take to start (default 60)
14
+ - ``PI_MCP_CALL_TIMEOUT`` -- seconds a tool call may take (default 120)
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import logging
20
+ from typing import TYPE_CHECKING, Any
21
+
22
+ if TYPE_CHECKING:
23
+ from pi_agent_core.extensions import ExtensionAPI
24
+
25
+ __all__ = ["activate"]
26
+
27
+ logger = logging.getLogger(__name__)
28
+
29
+
30
+ def activate(pi: ExtensionAPI) -> None:
31
+ """Extension entry point: take over the servers the client passed, start them later.
32
+
33
+ No I/O happens here (a failing ``activate`` is rolled back, and a started child process
34
+ would not be). The servers start in the ``session_start`` hook, each in a task of its own.
35
+ """
36
+ try:
37
+ servers = tuple(pi.client_mcp_servers)
38
+ except AttributeError:
39
+ logger.warning(
40
+ "pi-mcp needs a newer pi-agent-core-lc (0.6.0 or later): this one does not hand over "
41
+ "the MCP servers of the client. pi-mcp does nothing."
42
+ )
43
+ return
44
+ except RuntimeError: # no harness behind this API (a test, a bare registry)
45
+ servers = ()
46
+
47
+ from pi_mcp.manager import Manager
48
+ from pi_mcp.settings import Settings
49
+
50
+ manager = Manager(pi, servers, settings=Settings.from_env())
51
+ if servers:
52
+ pi.claim_client_mcp_servers([server.name for server in servers])
53
+
54
+ def on_session_start(_event: Any) -> None:
55
+ try:
56
+ manager.start()
57
+ except Exception: # a handler that raises would fail the load of every extension
58
+ logger.warning("pi-mcp could not start the MCP servers", exc_info=True)
59
+
60
+ pi.on("session_start", on_session_start)
61
+ pi.add_turn_barrier(manager.wait_started)
62
+ pi.register_cleanup(manager.close)
63
+
64
+ async def mcp_command(args: str) -> None:
65
+ pi.send_message(await manager.command(args))
66
+
67
+ pi.register_command(
68
+ "mcp",
69
+ description="Show the MCP servers of this session (/mcp reconnect <name> to reconnect)",
70
+ handler=mcp_command,
71
+ )