@isolo/trinity 1.0.2
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.
- package/README.md +180 -0
- package/docs/TOOLS.md +604 -0
- package/package.json +49 -0
- package/src/Config.ts +89 -0
- package/src/Logger.ts +52 -0
- package/src/Server.ts +274 -0
- package/src/Tools.ts +165 -0
- package/src/index.ts +36 -0
package/README.md
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Trinity MCP
|
|
2
|
+
|
|
3
|
+
A lightweight [MCP](https://modelcontextprotocol.io/) server framework for [Bun](https://bun.sh) with dynamic tool loading, hot reload, and stdio/HTTP transport modes.
|
|
4
|
+
|
|
5
|
+
**Write simple functions. Trinity handles the protocol.**
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Zero boilerplate** — tools are plain TypeScript files that export a schema and a function
|
|
10
|
+
- **Hot reload** — tools update instantly without restarting the server
|
|
11
|
+
- **Simple returns** — return primitives, objects, or arrays; Trinity wraps them into MCP format
|
|
12
|
+
- **Stdio & HTTP** — works as a VS Code MCP server or as an HTTP endpoint
|
|
13
|
+
- **Zod schemas** — type-safe input validation with auto-generated JSON Schema for clients
|
|
14
|
+
- **Error handling** — throw errors or return `{ isError: true }` objects, both are handled
|
|
15
|
+
- **File watching** — automatically detects new, changed, and deleted tools
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
### Install
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
bun add @isolo/trinity
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Create a tool
|
|
26
|
+
|
|
27
|
+
Create a `tools/` directory and add a tool file:
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
// tools/hello.ts
|
|
31
|
+
import { z } from "zod";
|
|
32
|
+
|
|
33
|
+
export const description = "Says hello to a person by name";
|
|
34
|
+
|
|
35
|
+
export const inputSchema = z.object({
|
|
36
|
+
name: z.string().describe("The person's name to greet"),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
export default async ({ name }: z.infer<typeof inputSchema>) => {
|
|
40
|
+
return `Hello, ${name}!`;
|
|
41
|
+
};
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Run the server
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Stdio mode (for VS Code, Claude Desktop, etc.)
|
|
48
|
+
bunx @isolo/trinity --target ./tools
|
|
49
|
+
|
|
50
|
+
# HTTP mode
|
|
51
|
+
MCP_MODE=http bunx @isolo/trinity --target ./tools --port 3000
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## VS Code Integration
|
|
55
|
+
|
|
56
|
+
Add to `.vscode/mcp.json`:
|
|
57
|
+
|
|
58
|
+
```jsonc
|
|
59
|
+
{
|
|
60
|
+
"servers": {
|
|
61
|
+
"my-tools": {
|
|
62
|
+
"type": "stdio",
|
|
63
|
+
"command": "bunx",
|
|
64
|
+
"args": ["@isolo/trinity", "--target", "./tools"],
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Tool Structure
|
|
71
|
+
|
|
72
|
+
Every tool is a `.ts` file with three exports:
|
|
73
|
+
|
|
74
|
+
| Export | Type | Description |
|
|
75
|
+
| ------------- | --------------------- | ---------------------------------------------- |
|
|
76
|
+
| `description` | `string` | What the tool does (shown to LLM) |
|
|
77
|
+
| `inputSchema` | `z.object(...)` | Zod schema for input validation |
|
|
78
|
+
| `default` | `async (args) => any` | The function that runs when the tool is called |
|
|
79
|
+
|
|
80
|
+
### Return Values
|
|
81
|
+
|
|
82
|
+
Just return what makes sense — Trinity converts it to MCP format automatically:
|
|
83
|
+
|
|
84
|
+
| You return | MCP result |
|
|
85
|
+
| --------------------------------- | -------------------------- |
|
|
86
|
+
| `string` | Text content |
|
|
87
|
+
| `number` / `boolean` | Text content (stringified) |
|
|
88
|
+
| `object` | Text + structured content |
|
|
89
|
+
| `array` | Multiple content items |
|
|
90
|
+
| `{ isError: true, error: "..." }` | Error response |
|
|
91
|
+
| `throw new Error(...)` | Error response |
|
|
92
|
+
|
|
93
|
+
## Examples
|
|
94
|
+
|
|
95
|
+
### Calculator
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
import { z } from "zod";
|
|
99
|
+
|
|
100
|
+
export const description = "Performs basic arithmetic operations";
|
|
101
|
+
|
|
102
|
+
export const inputSchema = z.object({
|
|
103
|
+
operation: z.enum(["add", "subtract", "multiply", "divide"]),
|
|
104
|
+
a: z.number().describe("First operand"),
|
|
105
|
+
b: z.number().describe("Second operand"),
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
export default async ({ operation, a, b }: z.infer<typeof inputSchema>) => {
|
|
109
|
+
switch (operation) {
|
|
110
|
+
case "add":
|
|
111
|
+
return a + b;
|
|
112
|
+
case "subtract":
|
|
113
|
+
return a - b;
|
|
114
|
+
case "multiply":
|
|
115
|
+
return a * b;
|
|
116
|
+
case "divide":
|
|
117
|
+
if (b === 0) return { isError: true, error: "Division by zero" };
|
|
118
|
+
return a / b;
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Structured Data
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
import { z } from "zod";
|
|
127
|
+
|
|
128
|
+
export const description = "Returns weather data for a location";
|
|
129
|
+
|
|
130
|
+
export const inputSchema = z.object({
|
|
131
|
+
location: z.string().describe("City name"),
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
export default async ({ location }: z.infer<typeof inputSchema>) => {
|
|
135
|
+
// Return an object → becomes text + structuredContent in MCP
|
|
136
|
+
return {
|
|
137
|
+
location,
|
|
138
|
+
temperature: 22.5,
|
|
139
|
+
conditions: "Partly cloudy",
|
|
140
|
+
humidity: 65,
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## CLI Options
|
|
146
|
+
|
|
147
|
+
| Option | Env Variable | Default | Description |
|
|
148
|
+
| ------------------ | ------------ | -------------------- | --------------------------------- |
|
|
149
|
+
| `--target <path>` | — | _required_ | Folder containing tool files |
|
|
150
|
+
| `--glob <pattern>` | `MCP_GLOB` | `**/*.ts` | Glob pattern for tool discovery |
|
|
151
|
+
| `--port <number>` | — | `3000` | HTTP server port |
|
|
152
|
+
| — | `MCP_MODE` | `stdio` | Transport mode: `stdio` or `http` |
|
|
153
|
+
| — | `LOG_FILE` | `<target>/debug.log` | Log file path |
|
|
154
|
+
|
|
155
|
+
## Development
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# Clone and install
|
|
159
|
+
git clone https://github.com/Sujimoshi/trinity.git
|
|
160
|
+
cd trinity
|
|
161
|
+
bun install
|
|
162
|
+
|
|
163
|
+
# Run with example tools (watch mode)
|
|
164
|
+
bun start
|
|
165
|
+
|
|
166
|
+
# Run in HTTP mode
|
|
167
|
+
bun run start:http
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## How It Works
|
|
171
|
+
|
|
172
|
+
1. Trinity scans the `--target` folder for `.ts` files matching `--glob`
|
|
173
|
+
2. Each file is dynamically imported — Zod schemas are converted to JSON Schema for MCP
|
|
174
|
+
3. When a tool is called, Trinity executes the default export and wraps the return value
|
|
175
|
+
4. File watcher detects changes and sends `tools/listChanged` notification to clients
|
|
176
|
+
5. In stdio mode, uses MCP stdio transport; in HTTP mode, uses Streamable HTTP on `/mcp`
|
|
177
|
+
|
|
178
|
+
## License
|
|
179
|
+
|
|
180
|
+
MIT
|