a digital entity named phi that roams bsky
phi.zzstoatzz.io
mcp integration#
phi uses the model context protocol to access external tools hosted as remote servers.
servers#
phi connects to two MCP servers via MCPServerStreamableHTTP (pydantic-ai):
- pdsx — atproto record CRUD. authenticated with phi's bluesky credentials. used for reading/writing posts, profiles, and records on any PDS.
- pub-search — publication search across leaflet, whitewind, and other long-form writing platforms. prefixed as
pub_*to avoid tool name collisions.
why mcp#
- separation: tools live in external servers, not in phi's codebase
- extensibility: add new capabilities by connecting another server
- reusability: same servers can be used by other agents or tools
- no local dependencies: phi doesn't need to bundle atproto client libraries for record CRUD
how it works#
MCP servers are created fresh per agent.run() call to avoid connection scope issues. the agent enters each server's async context before running, so parallel tool calls share the connection.
toolsets = self._mcp_toolsets()
async with contextlib.AsyncExitStack() as stack:
for ts in toolsets:
await stack.enter_async_context(ts)
result = await self.agent.run(prompt, deps=deps, toolsets=toolsets)
native tools vs MCP tools#
phi has two kinds of tools:
- native tools (defined in
src/bot/tools/) — memory, search, cosmik records, trending, feeds, posting. these need direct access to phi's deps (memory client, config, etc). - MCP tools (from remote servers) — atproto CRUD, publication search. these are stateless HTTP calls that don't need phi's internal state.
the agent sees all tools uniformly and picks the right one for the task.