+52
-52
Diff
round #6
+1
-1
CLAUDE.md
+1
-1
CLAUDE.md
···
68
68
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
69
69
```
70
70
71
-
The protocol is defined in `crates/ein-proto/proto/ein.proto`. The client streams `UserInput` messages; the server streams back `AgentEvent` messages (`SessionStarted`, `ContentDelta`, `ToolCallStart`, `ToolCallEnd`, `ToolOutputChunk`, `AgentFinished`, `AgentError`, `TokenUsage`).
71
+
The protocol is defined in `crates/ein_proto/proto/ein.proto`. The client streams `UserInput` messages; the server streams back `AgentEvent` messages (`SessionStarted`, `ContentDelta`, `ToolCallStart`, `ToolCallEnd`, `ToolOutputChunk`, `AgentFinished`, `AgentError`, `TokenUsage`).
72
72
73
73
### Session lifecycle
74
74
+21
-21
Cargo.lock
+21
-21
Cargo.lock
···
979
979
"clap",
980
980
"crossterm",
981
981
"dirs",
982
-
"ein-proto",
982
+
"ein_proto",
983
983
"notify",
984
984
"ratatui",
985
985
"reqwest",
···
997
997
]
998
998
999
999
[[package]]
1000
-
name = "ein-agent"
1000
+
name = "ein_agent"
1001
1001
version = "0.1.8"
1002
1002
dependencies = [
1003
1003
"anyhow",
1004
1004
"async-trait",
1005
-
"ein-core",
1005
+
"ein_core",
1006
1006
"futures",
1007
1007
"serde",
1008
1008
"serde_json",
···
1012
1012
]
1013
1013
1014
1014
[[package]]
1015
-
name = "ein-core"
1015
+
name = "ein_anthropic"
1016
1016
version = "0.1.8"
1017
1017
dependencies = [
1018
+
"anyhow",
1019
+
"ein_plugin",
1018
1020
"serde",
1019
1021
"serde_json",
1022
+
"wit-bindgen 0.53.1",
1020
1023
]
1021
1024
1022
1025
[[package]]
1023
-
name = "ein-proto"
1024
-
version = "0.1.8"
1025
-
dependencies = [
1026
-
"prost",
1027
-
"tonic",
1028
-
"tonic-build",
1029
-
]
1030
-
1031
-
[[package]]
1032
-
name = "ein_anthropic"
1026
+
name = "ein_bash"
1033
1027
version = "0.1.8"
1034
1028
dependencies = [
1035
1029
"anyhow",
···
1040
1034
]
1041
1035
1042
1036
[[package]]
1043
-
name = "ein_bash"
1037
+
name = "ein_core"
1044
1038
version = "0.1.8"
1045
1039
dependencies = [
1046
-
"anyhow",
1047
-
"ein_plugin",
1048
1040
"serde",
1049
1041
"serde_json",
1050
-
"wit-bindgen 0.53.1",
1051
1042
]
1052
1043
1053
1044
[[package]]
···
1110
1101
version = "0.1.8"
1111
1102
dependencies = [
1112
1103
"anyhow",
1113
-
"ein-core",
1104
+
"ein_core",
1114
1105
"ein_http",
1115
1106
"serde",
1116
1107
"serde_json",
1117
1108
"wit-bindgen 0.53.1",
1118
1109
]
1119
1110
1111
+
[[package]]
1112
+
name = "ein_proto"
1113
+
version = "0.1.8"
1114
+
dependencies = [
1115
+
"prost",
1116
+
"tonic",
1117
+
"tonic-build",
1118
+
]
1119
+
1120
1120
[[package]]
1121
1121
name = "ein_read"
1122
1122
version = "0.1.8"
···
1149
1149
"async-trait",
1150
1150
"clap",
1151
1151
"dirs",
1152
-
"ein-agent",
1153
-
"ein-proto",
1152
+
"ein_agent",
1154
1153
"ein_plugin",
1154
+
"ein_proto",
1155
1155
"futures",
1156
1156
"hyper",
1157
1157
"reqwest",
+6
-6
Cargo.toml
+6
-6
Cargo.toml
···
2
2
members = [
3
3
"eind",
4
4
"ein",
5
-
"crates/ein-proto",
6
-
"crates/ein-agent",
7
-
"crates/ein-core",
5
+
"crates/ein_proto",
6
+
"crates/ein_agent",
7
+
"crates/ein_core",
8
8
"crates/ein_http",
9
9
"crates/ein_plugin",
10
10
"packages/*",
···
12
12
default-members = [
13
13
"eind",
14
14
"ein",
15
-
"crates/ein-proto",
16
-
"crates/ein-agent",
17
-
"crates/ein-core",
15
+
"crates/ein_proto",
16
+
"crates/ein_agent",
17
+
"crates/ein_core",
18
18
]
19
19
resolver = "2"
20
20
+2
-2
README.md
+2
-2
README.md
···
269
269
270
270
```
271
271
crates/
272
-
ein-proto/ Protocol Buffer definitions (gRPC service + message types)
272
+
ein_proto/ Protocol Buffer definitions (gRPC service + message types)
273
273
ein/ Terminal UI client
274
274
eind/ gRPC server โ agent loop, WASM plugin host, session persistence
275
275
packages/
···
288
288
289
289
### Protocol
290
290
291
-
The protocol (`crates/ein-proto/proto/ein.proto`) defines a bidirectional streaming RPC (`AgentSession`), a unary `ListSessions` RPC, and a unary `DeleteSession` RPC. Each session opens with a `SessionConfig` message (global sandbox constraints + per-plugin config map + optional `session_id` for resume), followed by `UserInput` prompt messages. The server streams back `AgentEvent` messages as the agent thinks, calls tools, and produces output โ starting with a `SessionStarted` event carrying the session's UUID, a `resumed` boolean, and the prior conversation history when resuming.
291
+
The protocol (`crates/ein_proto/proto/ein.proto`) defines a bidirectional streaming RPC (`AgentSession`), a unary `ListSessions` RPC, and a unary `DeleteSession` RPC. Each session opens with a `SessionConfig` message (global sandbox constraints + per-plugin config map + optional `session_id` for resume), followed by `UserInput` prompt messages. The server streams back `AgentEvent` messages as the agent thinks, calls tools, and produces output โ starting with a `SessionStarted` event carrying the session's UUID, a `resumed` boolean, and the prior conversation history when resuming.
292
292
293
293
`UserInput` variants after `init`:
294
294
- `prompt` โ a user message driving `run_agent`
+2
-2
crates/ein-agent/Cargo.toml
crates/ein_agent/Cargo.toml
+2
-2
crates/ein-agent/Cargo.toml
crates/ein_agent/Cargo.toml
···
1
1
[package]
2
-
name = "ein-agent"
2
+
name = "ein_agent"
3
3
version.workspace = true
4
4
edition.workspace = true
5
5
authors.workspace = true
···
8
8
[dependencies]
9
9
anyhow = { workspace = true }
10
10
async-trait = "0.1"
11
-
ein-core = { path = "../ein-core" }
11
+
ein_core = { path = "../ein_core" }
12
12
futures = { workspace = true }
13
13
serde = { workspace = true }
14
14
serde_json = { workspace = true }
crates/ein-agent/src/agents.rs
crates/ein_agent/src/agents.rs
crates/ein-agent/src/agents.rs
crates/ein_agent/src/agents.rs
crates/ein-agent/src/errors.rs
crates/ein_agent/src/errors.rs
crates/ein-agent/src/errors.rs
crates/ein_agent/src/errors.rs
crates/ein-agent/src/lib.rs
crates/ein_agent/src/lib.rs
crates/ein-agent/src/lib.rs
crates/ein_agent/src/lib.rs
crates/ein-agent/src/model_clients/mod.rs
crates/ein_agent/src/model_clients/mod.rs
crates/ein-agent/src/model_clients/mod.rs
crates/ein_agent/src/model_clients/mod.rs
crates/ein-agent/src/tools/mod.rs
crates/ein_agent/src/tools/mod.rs
crates/ein-agent/src/tools/mod.rs
crates/ein_agent/src/tools/mod.rs
crates/ein-agent/src/tools/native.rs
crates/ein_agent/src/tools/native.rs
crates/ein-agent/src/tools/native.rs
crates/ein_agent/src/tools/native.rs
+1
-1
crates/ein-core/Cargo.toml
crates/ein_core/Cargo.toml
+1
-1
crates/ein-core/Cargo.toml
crates/ein_core/Cargo.toml
crates/ein-core/src/lib.rs
crates/ein_core/src/lib.rs
crates/ein-core/src/lib.rs
crates/ein_core/src/lib.rs
crates/ein-core/src/types.rs
crates/ein_core/src/types.rs
crates/ein-core/src/types.rs
crates/ein_core/src/types.rs
+1
-1
crates/ein_plugin/Cargo.toml
+1
-1
crates/ein_plugin/Cargo.toml
+1
-1
crates/ein-proto/Cargo.toml
crates/ein_proto/Cargo.toml
+1
-1
crates/ein-proto/Cargo.toml
crates/ein_proto/Cargo.toml
crates/ein-proto/build.rs
crates/ein_proto/build.rs
crates/ein-proto/build.rs
crates/ein_proto/build.rs
crates/ein-proto/proto/ein.proto
crates/ein_proto/proto/ein.proto
crates/ein-proto/proto/ein.proto
crates/ein_proto/proto/ein.proto
crates/ein-proto/src/lib.rs
crates/ein_proto/src/lib.rs
crates/ein-proto/src/lib.rs
crates/ein_proto/src/lib.rs
+1
-1
ein/Cargo.toml
+1
-1
ein/Cargo.toml
···
23
23
crossterm = { version = "0.28", features = ["event-stream"] }
24
24
notify = "6"
25
25
dirs = "6.0.0"
26
-
ein-proto = { path = "../crates/ein-proto" }
26
+
ein_proto = { path = "../crates/ein_proto" }
27
27
ratatui = { version = "0.29", features = ["unstable-rendered-line-info"] }
28
28
serde = { workspace = true }
29
29
serde_json = { workspace = true }
+2
-2
eind/Cargo.toml
+2
-2
eind/Cargo.toml
···
21
21
async-trait = "0.1"
22
22
clap = { version = "4.3.14", features = ["derive"] }
23
23
dirs = "6.0.0"
24
-
ein-agent = { path = "../crates/ein-agent" }
25
-
ein-proto = { path = "../crates/ein-proto" }
24
+
ein_agent = { path = "../crates/ein_agent" }
25
+
ein_proto = { path = "../crates/ein_proto" }
26
26
ein_plugin = { path = "../crates/ein_plugin" }
27
27
futures = { workspace = true }
28
28
serde = { workspace = true }
+4
-4
notes/ein-agent-mcp-fit-analysis.md
+4
-4
notes/ein-agent-mcp-fit-analysis.md
···
1
-
# `ein-agent` Architecture Fit for MCP Server Building
1
+
# `ein_agent` Architecture Fit for MCP Server Building
2
2
3
3
_Evaluation Date: 2026-04-20_
4
4
···
6
6
7
7
## Summary
8
8
9
-
The `ein-agent` architecture maps well onto the *client* side of MCP but is missing the abstractions needed to be a proper MCP *server* framework. It is well-positioned to grow in that direction, but there are meaningful gaps.
9
+
The `ein_agent` architecture maps well onto the *client* side of MCP but is missing the abstractions needed to be a proper MCP *server* framework. It is well-positioned to grow in that direction, but there are meaningful gaps.
10
10
11
11
---
12
12
13
13
## What Maps Cleanly
14
14
15
-
### `Tool` / `ToolSet` traits (`crates/ein-agent/src/tools/mod.rs`)
15
+
### `Tool` / `ToolSet` traits (`crates/ein_agent/src/tools/mod.rs`)
16
16
17
17
The best fit. MCP's core concept is a server that exposes named tools with JSON schemas โ that is exactly what `Tool` and `ToolSet` model. An MCP server implementation would be a new `ToolSet` adapter that routes calls to MCP rather than local functions.
18
18
19
-
### `ToolDef` / `ToolFunction` / `ToolFunctionParams` (`crates/ein-core/src/types.rs`)
19
+
### `ToolDef` / `ToolFunction` / `ToolFunctionParams` (`crates/ein_core/src/types.rs`)
20
20
21
21
Already serialize to OpenAI function-calling format, which is structurally identical to MCP's tool definition schema. Very little translation needed.
22
22
+10
-10
notes/mcp-server-roadmap.md
+10
-10
notes/mcp-server-roadmap.md
···
1
-
# Roadmap: MCP Server Support for `ein-agent`
1
+
# Roadmap: MCP Server Support for `ein_agent`
2
2
3
3
_Date: 2026-04-20_
4
4
···
6
6
7
7
## Goal
8
8
9
-
Make `ein-agent` a competitive Rust SDK for building MCP servers. The primary differentiator is WASM-sandboxed tool execution โ deny-by-default filesystem and network access per tool, with explicit per-tool capability grants. The Vercel/Context.ai incident (April 2026) demonstrated that the current generation of MCP tools has no answer to a compromised server exfiltrating OAuth tokens. Ein's existing WASM runtime directly addresses this, and the timing is good.
9
+
Make `ein_agent` a competitive Rust SDK for building MCP servers. The primary differentiator is WASM-sandboxed tool execution โ deny-by-default filesystem and network access per tool, with explicit per-tool capability grants. The Vercel/Context.ai incident (April 2026) demonstrated that the current generation of MCP tools has no answer to a compromised server exfiltrating OAuth tokens. Ein's existing WASM runtime directly addresses this, and the timing is good.
10
10
11
11
The target bar is parity with the official `rmcp` SDK on protocol coverage and ergonomics, with WASM sandboxing as a clear security advantage over everything in the ecosystem.
12
12
···
27
27
28
28
## Phases
29
29
30
-
### Phase 1: `ein-agent` trait improvements (prerequisite)
30
+
### Phase 1: `ein_agent` trait improvements (prerequisite)
31
31
32
32
These changes are required before any MCP work begins. They unblock concurrent MCP calls and remove constraints that don't make sense for a server use case.
33
33
···
84
84
- Error codes and error objects
85
85
- Notification types (`notifications/cancelled`, etc.)
86
86
87
-
Use `serde` for serialization. Keep these types in `ein-core` so they can be shared with a future MCP client.
87
+
Use `serde` for serialization. Keep these types in `ein_core` so they can be shared with a future MCP client.
88
88
89
89
**Capability negotiation**
90
90
···
296
296
297
297
---
298
298
299
-
### Phase 7: MCP client in `ein-agent`
299
+
### Phase 7: MCP client in `ein_agent`
300
300
301
301
Close the loop: let Ein agents consume tools from any MCP server, not just tools registered locally. This makes Ein bidirectional.
302
302
···
321
321
322
322
```
323
323
crates/
324
-
ein-core/ existing โ add MCP JSON-RPC types here
325
-
ein-agent/ existing โ Phase 1 trait improvements
326
-
ein-mcp/ new โ McpServer, transports, auth middleware
327
-
ein-mcp-macros/ new โ #[mcp_tool], #[mcp_server] proc macros
324
+
ein_core/ existing โ add MCP JSON-RPC types here
325
+
ein_agent/ existing โ Phase 1 trait improvements
326
+
ein_mcp/ new โ McpServer, transports, auth middleware
327
+
ein_mcp_macros/ new โ #[mcp_tool], #[mcp_server] proc macros
328
328
```
329
329
330
-
`ein-mcp` depends on `ein-agent` (for `ToolSet`) and `ein-core` (for shared types). The macro crate is a separate proc-macro crate depended on by `ein-mcp`.
330
+
`ein_mcp` depends on `ein-agent` (for `ToolSet`) and `ein_core` (for shared types). The macro crate is a separate proc-macro crate depended on by `ein_mcp`.
331
331
332
332
---
333
333
History
7 rounds
0 comments
mstallmo.com
submitted
#6
1 commit
expand
collapse
Make internal crate naming consistent
merge conflicts detected
expand
collapse
expand
collapse
- CLAUDE.md:4
- Cargo.lock:970
- Cargo.toml:1
- README.md:4
expand 0 comments
mstallmo.com
submitted
#5
1 commit
expand
collapse
Make internal crate naming consistent
expand 0 comments
mstallmo.com
submitted
#4
1 commit
expand
collapse
Make internal crate naming consistent
expand 0 comments
mstallmo.com
submitted
#3
1 commit
expand
collapse
Make internal crate naming consistent
expand 0 comments
mstallmo.com
submitted
#2
1 commit
expand
collapse
Make internal crate naming consistent
expand 0 comments
mstallmo.com
submitted
#1
1 commit
expand
collapse
Make internal crate naming consistent
expand 0 comments
mstallmo.com
submitted
#0
1 commit
expand
collapse
Make internal crate naming consistent