toolnexus 0.1.0 → 0.1.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 +81 -81
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
|
-
# toolnexus
|
|
1
|
+
# toolnexus
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/toolnexus)
|
|
4
|
+
[](https://github.com/muthuishere/toolnexus/blob/main/LICENSE)
|
|
5
|
+
|
|
6
|
+
**Build an agent in a few lines.** Point at an `mcp.json` and a `skills/` folder, call `run()`,
|
|
7
|
+
and you have a working agent — MCP servers, agent skills, your own functions, and HTTP endpoints
|
|
8
|
+
unified as one tool set, driving any LLM.
|
|
9
|
+
|
|
10
|
+
> **Right-sized.** Not a framework (no builders, advisors, runnables, config), not a toy that
|
|
11
|
+
> falls over the moment you need streaming or a retry. Everything a real agent needs — the loop,
|
|
12
|
+
> hooks, streaming, retries, memory — and nothing it doesn't.
|
|
13
|
+
|
|
14
|
+
The JS/TypeScript port of [toolnexus](https://github.com/muthuishere/toolnexus) — the same
|
|
15
|
+
library, byte-identical, also in **Python, Go, Java, and C#**. Built on
|
|
16
|
+
`@modelcontextprotocol/sdk` (the MCP SDK opencode uses).
|
|
6
17
|
|
|
7
18
|
## Install
|
|
8
19
|
|
|
@@ -10,107 +21,96 @@ Dynamic MCP servers + agent skills as a uniform tool list for any LLM. Built on
|
|
|
10
21
|
npm install toolnexus
|
|
11
22
|
```
|
|
12
23
|
|
|
13
|
-
##
|
|
24
|
+
## An agent in 3 steps
|
|
14
25
|
|
|
15
26
|
```ts
|
|
16
|
-
import { createToolkit } from "toolnexus"
|
|
27
|
+
import { createToolkit, createClient } from "toolnexus"
|
|
17
28
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
29
|
+
// 1. tools from an mcp.json + a skills/ folder
|
|
30
|
+
const tk = await createToolkit({ mcpConfig: "./mcp.json", skillsDir: "./skills" })
|
|
31
|
+
|
|
32
|
+
// 2. point at any OpenAI- or Anthropic-style endpoint
|
|
33
|
+
const agent = createClient({
|
|
34
|
+
baseUrl: "https://openrouter.ai/api/v1",
|
|
35
|
+
style: "openai", // or "anthropic"
|
|
36
|
+
model: "openai/gpt-4o-mini",
|
|
22
37
|
})
|
|
23
38
|
|
|
24
|
-
//
|
|
25
|
-
const
|
|
26
|
-
|
|
39
|
+
// 3. run — skills are injected into the system prompt, tools are called for you, looped to an answer
|
|
40
|
+
const { text } = await agent.run("Refund order 1234 for the customer.", { toolkit: tk })
|
|
41
|
+
console.log(text)
|
|
42
|
+
await tk.close()
|
|
43
|
+
```
|
|
27
44
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
45
|
+
`createClient` reads the key from `OPENROUTER_API_KEY` / `OPENAI_API_KEY` / `ANTHROPIC_API_KEY`
|
|
46
|
+
by default. The loop runs call → execute tools → feed back → repeat (up to `maxTurns`, default 10),
|
|
47
|
+
with hooks, streaming (`agent.stream(...)`), retries/backoff, and conversation memory available.
|
|
31
48
|
|
|
32
|
-
|
|
33
|
-
|
|
49
|
+
## Add your own tools
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import { defineTool, httpTool } from "toolnexus"
|
|
53
|
+
|
|
54
|
+
tk.register(
|
|
55
|
+
// a plain function → a tool
|
|
56
|
+
defineTool({
|
|
57
|
+
name: "add", description: "Add two numbers",
|
|
58
|
+
inputSchema: { type: "object", properties: { a: { type: "number" }, b: { type: "number" } }, required: ["a", "b"] },
|
|
59
|
+
run: ({ a, b }) => `${(a as number) + (b as number)}`,
|
|
60
|
+
}),
|
|
61
|
+
// a REST endpoint → a tool
|
|
62
|
+
httpTool({
|
|
63
|
+
name: "create_ticket", description: "Create a ticket", method: "POST",
|
|
64
|
+
url: "https://api.example.com/tickets",
|
|
65
|
+
headers: { Authorization: "Bearer ${API_TOKEN}" }, // ${ENV} expands from process.env, never logged
|
|
66
|
+
inputSchema: { type: "object", properties: { title: { type: "string" } }, required: ["title"] },
|
|
67
|
+
}),
|
|
68
|
+
)
|
|
34
69
|
```
|
|
35
70
|
|
|
36
|
-
|
|
71
|
+
URL `{placeholders}` are filled from args; `query` args go to the querystring; the rest become
|
|
72
|
+
the JSON body. Non-2xx → `{ isError: true, output: "HTTP <status>: <body>" }`.
|
|
37
73
|
|
|
38
|
-
|
|
39
|
-
npm install && npm run build
|
|
74
|
+
## Bring your own loop
|
|
40
75
|
|
|
41
|
-
|
|
42
|
-
node --experimental-strip-types examples/basic.ts
|
|
76
|
+
Don't want the host loop? Use the schema adapters and execute calls yourself:
|
|
43
77
|
|
|
44
|
-
|
|
45
|
-
|
|
78
|
+
```ts
|
|
79
|
+
const tools = tk.toOpenAI() // or tk.toAnthropic() / tk.toGemini()
|
|
80
|
+
const system = tk.skillsPrompt() // markdown skills catalog for your system prompt
|
|
81
|
+
// when the model returns a tool call { name, arguments }:
|
|
82
|
+
const res = await tk.execute(name, args) // -> { output, isError, metadata }
|
|
46
83
|
```
|
|
47
84
|
|
|
85
|
+
## The four sources
|
|
86
|
+
|
|
87
|
+
| Source | How |
|
|
88
|
+
|--------|-----|
|
|
89
|
+
| **MCP servers** | an `mcp.json` (`mcpServers`/`servers`/`mcp`); local stdio + remote streamable-HTTP, `headers` for auth |
|
|
90
|
+
| **Agent skills** | a folder of `<name>/SKILL.md`; a `skill` tool loads each on demand + a system-prompt catalog |
|
|
91
|
+
| **Native tools** | `defineTool({...})` — a function becomes a tool |
|
|
92
|
+
| **HTTP / REST** | `httpTool({...})` — an endpoint becomes a tool, `${ENV}` headers |
|
|
93
|
+
|
|
94
|
+
All four appear as one uniform `Tool` in `tk.tools()`. Each is à la carte — use just `loadMcp(config)`
|
|
95
|
+
or `loadSkills(dir)` if that's all you need.
|
|
96
|
+
|
|
48
97
|
## API
|
|
49
98
|
|
|
50
99
|
| Member | Description |
|
|
51
100
|
|--------|-------------|
|
|
52
101
|
| `createToolkit(opts)` | async factory → `Toolkit` |
|
|
53
|
-
| `
|
|
54
|
-
| `tk.get(name)` |
|
|
102
|
+
| `createClient(opts)` | the unified host loop (`run` / `stream`) |
|
|
103
|
+
| `tk.tools()` / `tk.get(name)` | the uniform tools |
|
|
55
104
|
| `tk.execute(name, args, ctx?)` | run a tool → `ToolResult` |
|
|
56
105
|
| `tk.skillsPrompt()` | system-prompt skill catalog |
|
|
57
106
|
| `tk.mcpStatus()` | per-server connection status |
|
|
58
107
|
| `tk.toOpenAI()` / `toAnthropic()` / `toGemini()` | provider tool schemas |
|
|
59
|
-
| `tk.register(...tools)` | add native/http/custom tools
|
|
108
|
+
| `tk.register(...tools)` | add native/http/custom tools |
|
|
60
109
|
| `tk.close()` | disconnect MCP servers |
|
|
61
110
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
## Native tools (a function → a tool)
|
|
65
|
-
|
|
66
|
-
```ts
|
|
67
|
-
import { defineTool } from "toolnexus"
|
|
68
|
-
|
|
69
|
-
const add = defineTool({
|
|
70
|
-
name: "add", description: "Add two numbers",
|
|
71
|
-
inputSchema: { type: "object", properties: { a: { type: "number" }, b: { type: "number" } }, required: ["a", "b"] },
|
|
72
|
-
run: ({ a, b }) => `${(a as number) + (b as number)}`, // string or ToolResult
|
|
73
|
-
})
|
|
74
|
-
tk.register(add)
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
## HTTP / REST tools (an endpoint → a tool)
|
|
78
|
-
|
|
79
|
-
```ts
|
|
80
|
-
import { httpTool } from "toolnexus"
|
|
81
|
-
|
|
82
|
-
tk.register(httpTool({
|
|
83
|
-
name: "create_ticket", description: "Create a ticket", method: "POST",
|
|
84
|
-
url: "https://api.example.com/tickets",
|
|
85
|
-
headers: { Authorization: "Bearer ${API_TOKEN}" }, // ${ENV} expands from process.env, never logged
|
|
86
|
-
inputSchema: { type: "object", properties: { title: { type: "string" } }, required: ["title"] },
|
|
87
|
-
}))
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
URL `{placeholders}` are filled from args; `query` args go to the querystring; the rest
|
|
91
|
-
become the JSON body. Non-2xx → `{ isError: true, output: "HTTP <status>: <body>" }`.
|
|
92
|
-
|
|
93
|
-
## Unified client (the host loop)
|
|
94
|
-
|
|
95
|
-
```ts
|
|
96
|
-
import { createClient } from "toolnexus"
|
|
97
|
-
|
|
98
|
-
const agent = createClient({
|
|
99
|
-
baseUrl: "https://openrouter.ai/api/v1", // any OpenAI- or Anthropic-style endpoint
|
|
100
|
-
style: "openai", // or "anthropic"
|
|
101
|
-
model: "openai/gpt-4o-mini",
|
|
102
|
-
// apiKey defaults to OPENROUTER_API_KEY / OPENAI_API_KEY / ANTHROPIC_API_KEY
|
|
103
|
-
systemPrompt: "You are a helpful agent.",
|
|
104
|
-
})
|
|
105
|
-
|
|
106
|
-
const { text, toolCalls } = await agent.run("do the thing", { toolkit: tk })
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
It injects `tk.skillsPrompt()` into the system message and runs the full
|
|
110
|
-
call → execute tools → feed back → repeat loop (up to `maxTurns`, default 10).
|
|
111
|
+
## More
|
|
111
112
|
|
|
112
|
-
|
|
113
|
+
Full docs, the other four language ports, the shared behavior spec, and runnable examples:
|
|
114
|
+
**https://github.com/muthuishere/toolnexus**
|
|
113
115
|
|
|
114
|
-
|
|
115
|
-
- `examples/agent.ts` — native + http tools driven by the unified client (live with `OPENROUTER_API_KEY`).
|
|
116
|
-
- `examples/openrouter_test.ts` — minimal live tool-calling round trip.
|
|
116
|
+
MIT licensed.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "toolnexus",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Dynamic MCP servers + agent skills as uniform tools for any LLM (opencode-style).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -19,6 +19,9 @@
|
|
|
19
19
|
},
|
|
20
20
|
"keywords": ["mcp", "llm", "agent", "skills", "tools", "openai", "anthropic", "gemini"],
|
|
21
21
|
"license": "MIT",
|
|
22
|
+
"repository": { "type": "git", "url": "git+https://github.com/muthuishere/toolnexus.git" },
|
|
23
|
+
"homepage": "https://github.com/muthuishere/toolnexus#readme",
|
|
24
|
+
"bugs": { "url": "https://github.com/muthuishere/toolnexus/issues" },
|
|
22
25
|
"dependencies": {
|
|
23
26
|
"@modelcontextprotocol/sdk": "^1.12.0"
|
|
24
27
|
},
|