使用说明
编码模式
与其一次调用一个工具,不如让LLM编写代码,在一次更有效的令牌传递中编排Python工具。
Codemode通过以下方式在进程内V8隔离中运行该代码 jsrun。隔离在5ms内启动,运行时性能与Node.js相同,默认情况下没有网络或文件系统访问权限,除非通过您明确提供的函数,否则无法访问主机。
实验性:这个项目处于早期开发阶段
安装
pip install py-codemode[mcp]
# or
uv add py-codemode[mcp]
对于没有MCP的核心执行器: pip install py-codemode
快速开始
创建具有内置功能和自定义工具的MCP服务器:
from codemode import EnvCapability, FsCapability, HttpCapability
from codemode.mcp import CodeModeServer
server = CodeModeServer(
name="example",
capabilities=[
EnvCapability(allowed_keys=["USER"]),
FsCapability(allowed_paths=["./examples"]),
HttpCapability(allowed_hosts=["httpbin.org"]),
],
enable_search=True,
)
@server.tool()
def add(a: int, b: int) -> int:
"""Add two numbers"""
return a + b
if __name__ == "__main__":
server.mcp.run(transport="streamable-http")
奔跑 uv run python examples/mcp_server.py 并连接任何MCP客户端。
这 codemode[mcp] extra将执行器包装为MCP服务器,公开:
execute--运行调用Python函数的JavaScript。TypeScript声明是根据你的类型提示自动生成的,并嵌入在工具描述中,这样LLM就知道什么是可调用的。search(可选,通过enable_search=True)--按名称或描述搜索已注册的功能和工具。
运作原理
┌─────────────────────┐ ┌──────────────────────┐
│ V8 isolate (jsrun) │ │ Python host │
│ │ │ │
│ LLM-generated JS │ │ Executor │
│ runs in async IIFE │ │ │
│ │ bridge │ │
│ codemode.fn({...}) ├────────►│ _dispatch() │
│ │◄────────┤ -> your_fn(**kwargs)│
│ │ result │ │
└─────────────────────┘ └──────────────────────┘
执行器将代码封装在一个线束中,该线束捕获控制台输出并设置 codemode 代理对象。代理拦截每个 codemode.*() 调用,将其序列化为JSON,并桥接回Python,其中 _dispatch() 将其路由到匹配的主机函数。MCP服务器使用 Executor 引擎盖下。
主机功能
宿主函数仅使用带有类型提示的关键字参数:
async def read(*, path: str) -> str:
return open(path).read()
从JavaScript调用为 await codemode.read({ path: "/tmp/f" })类型提示用于生成TypeScript存根(str 成为 string, int/float 成为 number, list[T] 成为 T[]等等)。
内置功能
功能是具有基于满列表安全性的命名空间主机函数。默认情况下,沙盒没有文件系统、网络或环境访问权限。
| 能力 | 命名空间 | 描述 |
|---|---|---|
FsCapability(allowed_paths=[...]) |
codemode.fs |
在允许的路径内进行沙盒读/写 |
EnvCapability(allowed_keys=[...]) |
codemode.env |
从满列表中读取环境变量 |
HttpCapability(allowed_hosts=[...]) |
codemode.http |
仅向允许的主机发送HTTP请求 |
局限性
- V8运行时,不是Node,所以没有Node内置模块。仅限JavaScript。
- 没有顶级
import或require沙盒代码
高级
要逐步控制主机调用,请直接使用会话API:
import asyncio
from codemode import Executor, HostCallRequest, RunCompleted, RunFailed
async def main():
executor = Executor(timeout_s=5)
session = await executor.start("""
async () => {
const a = await codemode.double({ n: 3 });
const b = await codemode.double({ n: a });
return b;
}
""")
while True:
event = await session.next_event()
if isinstance(event, HostCallRequest):
result = event.input["n"] * 2
await session.submit_result(event.call_id, result)
elif isinstance(event, (RunCompleted, RunFailed)):
break
await session.cancel()
executor.close()
asyncio.run(main())
这使您可以完全控制每个主机调用,这对于记录、审批流或路由到外部服务非常有用。
jsrun还支持通过以下方式将其他JavaScript库加载到隔离中 Runtime.add_static_module() 或者自定义模块加载器、用于更快冷启动的V8堆快照、堆大小限制和每次调用执行超时。请参阅 jsrun文档 了解详情。
延伸阅读
- jsrun --V8隔离运行时,为codemode提供动力
- src/code模式 --执行器、功能和存根生成源
- src/codemode/mcp --MCP服务器和注册表源
- 示例/ --可运行的示例
许可证
麻省理工学院