@sammorrowdrums/mcpi-ext 0.2.0 → 1.0.0
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/LICENSE +21 -0
- package/README.md +137 -47
- package/dist/code-mode/eligibility.d.ts +35 -0
- package/dist/code-mode/eligibility.js +64 -0
- package/dist/code-mode/executor.d.ts +53 -0
- package/dist/code-mode/executor.js +185 -0
- package/dist/code-mode/index.d.ts +107 -0
- package/dist/code-mode/index.js +267 -0
- package/dist/code-mode/isolated-vm.d.ts +65 -0
- package/dist/code-mode/isolated-vm.js +116 -0
- package/dist/code-mode/tools.d.ts +48 -0
- package/dist/code-mode/tools.js +73 -0
- package/dist/code-mode/type-hints.d.ts +20 -0
- package/dist/code-mode/type-hints.js +205 -0
- package/dist/docker-e2e.d.ts +54 -0
- package/dist/docker-e2e.js +234 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +227 -0
- package/dist/mcp/call-tool-result.d.ts +10 -0
- package/dist/mcp/call-tool-result.js +70 -0
- package/dist/mcp/client-factory.d.ts +59 -0
- package/dist/mcp/client-factory.js +76 -0
- package/dist/mcp/client-manager.d.ts +88 -0
- package/dist/mcp/client-manager.js +307 -0
- package/dist/mcp/config-loader.d.ts +7 -0
- package/dist/mcp/config-loader.js +42 -0
- package/dist/mcp/config.d.ts +56 -0
- package/dist/mcp/config.js +42 -0
- package/dist/mcp/gateway-defaults.d.ts +14 -0
- package/dist/mcp/gateway-defaults.js +21 -0
- package/dist/mcp/host-approval.d.ts +16 -0
- package/dist/mcp/host-approval.js +19 -0
- package/dist/mcp/host-elicitation.d.ts +19 -0
- package/dist/mcp/host-elicitation.js +94 -0
- package/dist/mcp/index.d.ts +8 -0
- package/dist/mcp/index.js +7 -0
- package/dist/mcp/policy.d.ts +314 -0
- package/dist/mcp/policy.js +848 -0
- package/dist/routing/facilities.d.ts +109 -0
- package/dist/routing/facilities.js +175 -0
- package/dist/routing/format.d.ts +24 -0
- package/dist/routing/format.js +64 -0
- package/dist/routing/index.d.ts +4 -0
- package/dist/routing/index.js +4 -0
- package/dist/routing/seam.d.ts +35 -0
- package/dist/routing/seam.js +28 -0
- package/dist/routing/tripwire.d.ts +42 -0
- package/dist/routing/tripwire.js +80 -0
- package/dist/skills/discover.d.ts +12 -0
- package/dist/skills/discover.js +85 -0
- package/dist/skills/format.d.ts +13 -0
- package/dist/skills/format.js +42 -0
- package/dist/skills/index.d.ts +6 -0
- package/dist/skills/index.js +6 -0
- package/dist/skills/load-skill-tool.d.ts +56 -0
- package/dist/skills/load-skill-tool.js +183 -0
- package/dist/skills/mcp-tool-proxy.d.ts +7 -0
- package/dist/skills/mcp-tool-proxy.js +41 -0
- package/dist/skills/sep2640/client.d.ts +91 -0
- package/dist/skills/sep2640/client.js +160 -0
- package/dist/skills/sep2640/discover.d.ts +33 -0
- package/dist/skills/sep2640/discover.js +82 -0
- package/dist/skills/sep2640/index.d.ts +13 -0
- package/dist/skills/sep2640/index.js +13 -0
- package/dist/skills/sep2640/integrity.d.ts +58 -0
- package/dist/skills/sep2640/integrity.js +185 -0
- package/dist/skills/sep2640/load.d.ts +61 -0
- package/dist/skills/sep2640/load.js +90 -0
- package/dist/skills/sep2640/protocol.d.ts +146 -0
- package/dist/skills/sep2640/protocol.js +214 -0
- package/dist/skills/sep2640/spec.d.ts +76 -0
- package/dist/skills/sep2640/spec.js +88 -0
- package/dist/skills/skill-registry.d.ts +85 -0
- package/dist/skills/skill-registry.js +85 -0
- package/dist/tool-cli/bridge.d.ts +14 -0
- package/dist/tool-cli/bridge.js +196 -0
- package/dist/tool-cli/format.d.ts +20 -0
- package/dist/tool-cli/format.js +73 -0
- package/dist/tool-cli/index.d.ts +7 -0
- package/dist/tool-cli/index.js +5 -0
- package/dist/tool-cli/provider.d.ts +21 -0
- package/dist/tool-cli/provider.js +114 -0
- package/dist/tool-cli/startup.d.ts +22 -0
- package/dist/tool-cli/startup.js +47 -0
- package/package.json +78 -26
- package/.dockerignore +0 -6
- package/.github/dependabot.yml +0 -25
- package/.github/workflows/ci.yml +0 -50
- package/.hadolint.yaml +0 -6
- package/.prettierignore +0 -4
- package/.prettierrc +0 -7
- package/AGENTS.md +0 -118
- package/DECISIONS.md +0 -99
- package/Dockerfile +0 -39
- package/aube-lock.yaml +0 -4146
- package/docs/code-mode.md +0 -38
- package/docs/skills.md +0 -57
- package/docs/tool-cli.md +0 -54
- package/eslint.config.js +0 -27
- package/images/banner.webp +0 -0
- package/images/code-c-maude.webp +0 -0
- package/images/code-mode-histogram.png +0 -0
- package/images/nuclear-mcp-football.webp +0 -0
- package/images/skills-enabling-mcp-tools.png +0 -0
- package/images/the-skill-dealer.webp +0 -0
- package/images/tool-cli-grep.png +0 -0
- package/mise.toml +0 -53
- package/scripts/docker-entrypoint.sh +0 -29
- package/scripts/test-echo-server.mjs +0 -28
- package/scripts/test-mcp-integration.mjs +0 -59
- package/scripts/test-tool-cli-smoke.mjs +0 -93
- package/src/code-mode/code-mode-integration.test.ts +0 -135
- package/src/code-mode/eligibility.test.ts +0 -60
- package/src/code-mode/eligibility.ts +0 -16
- package/src/code-mode/executor.test.ts +0 -168
- package/src/code-mode/executor.ts +0 -163
- package/src/code-mode/index.ts +0 -208
- package/src/code-mode/tools.ts +0 -110
- package/src/code-mode/type-hints.test.ts +0 -187
- package/src/code-mode/type-hints.ts +0 -249
- package/src/docker-e2e.test.ts +0 -195
- package/src/docker-e2e.ts +0 -277
- package/src/index.test.ts +0 -8
- package/src/index.ts +0 -179
- package/src/mcp/client-manager.test.ts +0 -250
- package/src/mcp/client-manager.ts +0 -199
- package/src/mcp/config-loader.test.ts +0 -115
- package/src/mcp/config-loader.ts +0 -46
- package/src/mcp/config.ts +0 -40
- package/src/mcp/index.ts +0 -4
- package/src/skills/discover.ts +0 -81
- package/src/skills/format.test.ts +0 -70
- package/src/skills/format.ts +0 -42
- package/src/skills/index.ts +0 -9
- package/src/skills/load-skill-tool.ts +0 -136
- package/src/skills/mcp-tool-proxy.ts +0 -143
- package/src/skills/skill-integration.test.ts +0 -139
- package/src/skills/skill-registry.test.ts +0 -83
- package/src/skills/skill-registry.ts +0 -69
- package/src/test-servers/weather-server.ts +0 -171
- package/src/test-servers/weather-stdio.ts +0 -11
- package/src/tool-cli/format.test.ts +0 -33
- package/src/tool-cli/format.ts +0 -56
- package/src/tool-cli/index.ts +0 -3
- package/tsconfig.json +0 -21
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { SkillRegistry, type McpSkillMetadata } from "./skill-registry.js";
|
|
3
|
-
|
|
4
|
-
function makeSkill(overrides: Partial<McpSkillMetadata> = {}): McpSkillMetadata {
|
|
5
|
-
return {
|
|
6
|
-
name: "test-skill",
|
|
7
|
-
description: "A test skill",
|
|
8
|
-
uri: "skill://test/SKILL.md",
|
|
9
|
-
serverName: "test-server",
|
|
10
|
-
allowedTools: ["tool_a"],
|
|
11
|
-
...overrides,
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
describe("SkillRegistry", () => {
|
|
16
|
-
it("registers and retrieves a skill", () => {
|
|
17
|
-
const reg = new SkillRegistry();
|
|
18
|
-
const skill = makeSkill();
|
|
19
|
-
reg.register(skill);
|
|
20
|
-
|
|
21
|
-
expect(reg.get("test-skill")).toEqual(skill);
|
|
22
|
-
expect(reg.size).toBe(1);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it("getAll returns all registered skills", () => {
|
|
26
|
-
const reg = new SkillRegistry();
|
|
27
|
-
reg.register(makeSkill({ name: "a" }));
|
|
28
|
-
reg.register(makeSkill({ name: "b" }));
|
|
29
|
-
|
|
30
|
-
expect(reg.getAll()).toHaveLength(2);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it("overwrites on duplicate name", () => {
|
|
34
|
-
const reg = new SkillRegistry();
|
|
35
|
-
reg.register(makeSkill({ description: "first" }));
|
|
36
|
-
reg.register(makeSkill({ description: "second" }));
|
|
37
|
-
|
|
38
|
-
expect(reg.size).toBe(1);
|
|
39
|
-
expect(reg.get("test-skill")?.description).toBe("second");
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it("unregister removes by name", () => {
|
|
43
|
-
const reg = new SkillRegistry();
|
|
44
|
-
reg.register(makeSkill());
|
|
45
|
-
|
|
46
|
-
expect(reg.unregister("test-skill")).toBe(true);
|
|
47
|
-
expect(reg.get("test-skill")).toBeUndefined();
|
|
48
|
-
expect(reg.unregister("test-skill")).toBe(false);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it("unregisterByServer removes all skills from a server", () => {
|
|
52
|
-
const reg = new SkillRegistry();
|
|
53
|
-
reg.register(makeSkill({ name: "a", serverName: "srv1" }));
|
|
54
|
-
reg.register(makeSkill({ name: "b", serverName: "srv1" }));
|
|
55
|
-
reg.register(makeSkill({ name: "c", serverName: "srv2" }));
|
|
56
|
-
|
|
57
|
-
reg.unregisterByServer("srv1");
|
|
58
|
-
|
|
59
|
-
expect(reg.size).toBe(1);
|
|
60
|
-
expect(reg.get("c")).toBeDefined();
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it("registerAll registers multiple skills", () => {
|
|
64
|
-
const reg = new SkillRegistry();
|
|
65
|
-
reg.registerAll([makeSkill({ name: "x" }), makeSkill({ name: "y" })]);
|
|
66
|
-
|
|
67
|
-
expect(reg.size).toBe(2);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it("clear removes everything", () => {
|
|
71
|
-
const reg = new SkillRegistry();
|
|
72
|
-
reg.registerAll([makeSkill({ name: "a" }), makeSkill({ name: "b" })]);
|
|
73
|
-
|
|
74
|
-
reg.clear();
|
|
75
|
-
expect(reg.size).toBe(0);
|
|
76
|
-
expect(reg.getAll()).toEqual([]);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it("get returns undefined for unknown name", () => {
|
|
80
|
-
const reg = new SkillRegistry();
|
|
81
|
-
expect(reg.get("nonexistent")).toBeUndefined();
|
|
82
|
-
});
|
|
83
|
-
});
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
/** Metadata for a skill discovered from an MCP server. */
|
|
2
|
-
export interface McpSkillMetadata {
|
|
3
|
-
/** Skill name from SKILL.md frontmatter. */
|
|
4
|
-
name: string;
|
|
5
|
-
/** Short description from SKILL.md frontmatter. */
|
|
6
|
-
description: string;
|
|
7
|
-
/** The skill:// URI for the SKILL.md resource. */
|
|
8
|
-
uri: string;
|
|
9
|
-
/** Which MCP server this skill came from. */
|
|
10
|
-
serverName: string;
|
|
11
|
-
/** Tool names this skill gates via allowed-tools frontmatter. */
|
|
12
|
-
allowedTools: string[];
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Registry for MCP-discovered skills.
|
|
17
|
-
*
|
|
18
|
-
* Holds skill metadata discovered from MCP servers. Skills are registered
|
|
19
|
-
* during MCP connection and looked up when the model invokes load_skill.
|
|
20
|
-
*/
|
|
21
|
-
export class SkillRegistry {
|
|
22
|
-
private skills = new Map<string, McpSkillMetadata>();
|
|
23
|
-
|
|
24
|
-
/** Register a skill. Overwrites any existing skill with the same name. */
|
|
25
|
-
register(skill: McpSkillMetadata): void {
|
|
26
|
-
this.skills.set(skill.name, skill);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/** Register multiple skills at once. */
|
|
30
|
-
registerAll(skills: McpSkillMetadata[]): void {
|
|
31
|
-
for (const skill of skills) {
|
|
32
|
-
this.register(skill);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/** Get a skill by name. */
|
|
37
|
-
get(name: string): McpSkillMetadata | undefined {
|
|
38
|
-
return this.skills.get(name);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/** Get all registered skills. */
|
|
42
|
-
getAll(): McpSkillMetadata[] {
|
|
43
|
-
return [...this.skills.values()];
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/** Remove a skill by name. */
|
|
47
|
-
unregister(name: string): boolean {
|
|
48
|
-
return this.skills.delete(name);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/** Remove all skills from a specific MCP server. */
|
|
52
|
-
unregisterByServer(serverName: string): void {
|
|
53
|
-
for (const [name, skill] of this.skills) {
|
|
54
|
-
if (skill.serverName === serverName) {
|
|
55
|
-
this.skills.delete(name);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/** Remove all skills. */
|
|
61
|
-
clear(): void {
|
|
62
|
-
this.skills.clear();
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/** Number of registered skills. */
|
|
66
|
-
get size(): number {
|
|
67
|
-
return this.skills.size;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Test MCP weather server — exposes a weather skill with gated tools.
|
|
3
|
-
*
|
|
4
|
-
* Registers:
|
|
5
|
-
* - skill://weather/SKILL.md — a skill resource with frontmatter
|
|
6
|
-
* - check_weather_for_city — current weather (gated by skill)
|
|
7
|
-
* - check_weekly_forecast_for_city — 7-day forecast (gated by skill)
|
|
8
|
-
* - echo — ungated baseline tool
|
|
9
|
-
*/
|
|
10
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
11
|
-
import { z } from "zod";
|
|
12
|
-
|
|
13
|
-
const SKILL_CONTENT = `---
|
|
14
|
-
name: weather
|
|
15
|
-
description: Check current weather and weekly forecasts for any city
|
|
16
|
-
allowed-tools:
|
|
17
|
-
- check_weather_for_city
|
|
18
|
-
- check_weekly_forecast_for_city
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
# Weather Forecasting Skill
|
|
22
|
-
|
|
23
|
-
Use the weather tools to look up conditions for any city.
|
|
24
|
-
|
|
25
|
-
- **check_weather_for_city** — returns current temperature, conditions, and humidity
|
|
26
|
-
- **check_weekly_forecast_for_city** — returns a 7-day forecast summary
|
|
27
|
-
|
|
28
|
-
Always confirm the city name with the user before calling.
|
|
29
|
-
`;
|
|
30
|
-
|
|
31
|
-
const WEATHER_DATA: Record<string, { temp: number; conditions: string; humidity: number }> = {
|
|
32
|
-
london: { temp: 14, conditions: "Cloudy", humidity: 78 },
|
|
33
|
-
tokyo: { temp: 26, conditions: "Sunny", humidity: 55 },
|
|
34
|
-
"new york": { temp: 22, conditions: "Partly cloudy", humidity: 62 },
|
|
35
|
-
sydney: { temp: 19, conditions: "Clear", humidity: 45 },
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const FORECAST_DATA: Record<string, string> = {
|
|
39
|
-
london:
|
|
40
|
-
"Mon 13°C Rain | Tue 14°C Cloudy | Wed 15°C Cloudy | Thu 12°C Rain | Fri 14°C Sunny | Sat 16°C Sunny | Sun 15°C Cloudy",
|
|
41
|
-
tokyo:
|
|
42
|
-
"Mon 27°C Sunny | Tue 28°C Sunny | Wed 25°C Rain | Thu 24°C Cloudy | Fri 26°C Sunny | Sat 27°C Sunny | Sun 26°C Partly cloudy",
|
|
43
|
-
"new york":
|
|
44
|
-
"Mon 23°C Sunny | Tue 24°C Sunny | Wed 20°C Thunderstorms | Thu 18°C Cloudy | Fri 21°C Sunny | Sat 22°C Sunny | Sun 23°C Clear",
|
|
45
|
-
sydney:
|
|
46
|
-
"Mon 18°C Clear | Tue 20°C Sunny | Wed 19°C Cloudy | Thu 17°C Rain | Fri 18°C Cloudy | Sat 21°C Sunny | Sun 20°C Clear",
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
export function createWeatherServer(): McpServer {
|
|
50
|
-
const server = new McpServer(
|
|
51
|
-
{ name: "test-weather-server", version: "0.1.0" },
|
|
52
|
-
{ capabilities: { resources: {} } },
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
// Skill resource
|
|
56
|
-
server.registerResource(
|
|
57
|
-
"weather-skill",
|
|
58
|
-
"skill://weather/SKILL.md",
|
|
59
|
-
{
|
|
60
|
-
description: "Weather forecasting skill instructions",
|
|
61
|
-
mimeType: "text/markdown",
|
|
62
|
-
},
|
|
63
|
-
async () => ({
|
|
64
|
-
contents: [
|
|
65
|
-
{
|
|
66
|
-
uri: "skill://weather/SKILL.md",
|
|
67
|
-
text: SKILL_CONTENT,
|
|
68
|
-
mimeType: "text/markdown",
|
|
69
|
-
},
|
|
70
|
-
],
|
|
71
|
-
}),
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
// Tool: current weather (gated by skill)
|
|
75
|
-
server.registerTool(
|
|
76
|
-
"check_weather_for_city",
|
|
77
|
-
{
|
|
78
|
-
description: "Get current weather conditions for a city",
|
|
79
|
-
inputSchema: { city: z.string().describe("City name, e.g. 'London'") },
|
|
80
|
-
outputSchema: {
|
|
81
|
-
temperature: z.number().describe("Temperature in Celsius"),
|
|
82
|
-
conditions: z.string().describe("Weather conditions description"),
|
|
83
|
-
humidity: z.number().describe("Humidity percentage"),
|
|
84
|
-
city: z.string().describe("City name"),
|
|
85
|
-
},
|
|
86
|
-
annotations: { readOnlyHint: true },
|
|
87
|
-
},
|
|
88
|
-
async ({ city }) => {
|
|
89
|
-
const data = WEATHER_DATA[city.toLowerCase()];
|
|
90
|
-
if (!data) {
|
|
91
|
-
return {
|
|
92
|
-
content: [
|
|
93
|
-
{
|
|
94
|
-
type: "text" as const,
|
|
95
|
-
text: `No weather data available for "${city}". Try: London, Tokyo, New York, or Sydney.`,
|
|
96
|
-
},
|
|
97
|
-
],
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
const structuredContent = {
|
|
101
|
-
temperature: data.temp,
|
|
102
|
-
conditions: data.conditions,
|
|
103
|
-
humidity: data.humidity,
|
|
104
|
-
city,
|
|
105
|
-
};
|
|
106
|
-
return {
|
|
107
|
-
content: [
|
|
108
|
-
{
|
|
109
|
-
type: "text" as const,
|
|
110
|
-
text: `Weather in ${city}: ${data.conditions}, ${data.temp}°C, humidity ${data.humidity}%`,
|
|
111
|
-
},
|
|
112
|
-
],
|
|
113
|
-
structuredContent,
|
|
114
|
-
};
|
|
115
|
-
},
|
|
116
|
-
);
|
|
117
|
-
|
|
118
|
-
// Tool: weekly forecast (gated by skill)
|
|
119
|
-
server.registerTool(
|
|
120
|
-
"check_weekly_forecast_for_city",
|
|
121
|
-
{
|
|
122
|
-
description: "Get a 7-day weather forecast for a city",
|
|
123
|
-
inputSchema: { city: z.string().describe("City name, e.g. 'Tokyo'") },
|
|
124
|
-
outputSchema: {
|
|
125
|
-
city: z.string().describe("City name"),
|
|
126
|
-
forecast: z.string().describe("7-day forecast summary"),
|
|
127
|
-
},
|
|
128
|
-
annotations: { readOnlyHint: true },
|
|
129
|
-
},
|
|
130
|
-
async ({ city }) => {
|
|
131
|
-
const forecast = FORECAST_DATA[city.toLowerCase()];
|
|
132
|
-
if (!forecast) {
|
|
133
|
-
return {
|
|
134
|
-
content: [
|
|
135
|
-
{
|
|
136
|
-
type: "text" as const,
|
|
137
|
-
text: `No forecast data available for "${city}". Try: London, Tokyo, New York, or Sydney.`,
|
|
138
|
-
},
|
|
139
|
-
],
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
const structuredContent = { city, forecast };
|
|
143
|
-
return {
|
|
144
|
-
content: [{ type: "text" as const, text: `Forecast for ${city}: ${forecast}` }],
|
|
145
|
-
structuredContent,
|
|
146
|
-
};
|
|
147
|
-
},
|
|
148
|
-
);
|
|
149
|
-
|
|
150
|
-
// Ungated tool (always available, not behind a skill)
|
|
151
|
-
server.registerTool(
|
|
152
|
-
"echo",
|
|
153
|
-
{
|
|
154
|
-
description: "Echoes back the input message",
|
|
155
|
-
inputSchema: { message: z.string() },
|
|
156
|
-
outputSchema: {
|
|
157
|
-
echo: z.string().describe("The echoed message"),
|
|
158
|
-
},
|
|
159
|
-
annotations: { readOnlyHint: true },
|
|
160
|
-
},
|
|
161
|
-
async ({ message }) => {
|
|
162
|
-
const structuredContent = { echo: message };
|
|
163
|
-
return {
|
|
164
|
-
content: [{ type: "text" as const, text: `Echo: ${message}` }],
|
|
165
|
-
structuredContent,
|
|
166
|
-
};
|
|
167
|
-
},
|
|
168
|
-
);
|
|
169
|
-
|
|
170
|
-
return server;
|
|
171
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* stdio entrypoint for the test weather server.
|
|
3
|
-
* Run with: node dist/test-servers/weather-stdio.js
|
|
4
|
-
*/
|
|
5
|
-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6
|
-
import { createWeatherServer } from "./weather-server.js";
|
|
7
|
-
|
|
8
|
-
const server = createWeatherServer();
|
|
9
|
-
const transport = new StdioServerTransport();
|
|
10
|
-
await server.connect(transport);
|
|
11
|
-
console.error("Test weather server running on stdio");
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { formatToolCliForPrompt } from "./format.js";
|
|
3
|
-
|
|
4
|
-
describe("formatToolCliForPrompt", () => {
|
|
5
|
-
it("returns empty string when no servers connected", () => {
|
|
6
|
-
expect(formatToolCliForPrompt(0)).toBe("");
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
it("includes tool-cli usage instructions when servers are connected", () => {
|
|
10
|
-
const result = formatToolCliForPrompt(2);
|
|
11
|
-
expect(result).toContain("tool-cli");
|
|
12
|
-
expect(result).toContain("<tool_cli>");
|
|
13
|
-
expect(result).toContain("</tool_cli>");
|
|
14
|
-
expect(result).toContain("--help");
|
|
15
|
-
expect(result).toContain("<server>");
|
|
16
|
-
expect(result).toContain("<tool>");
|
|
17
|
-
expect(result).toContain("2 MCP server(s) currently connected");
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it("advises preferring skills over tool-cli", () => {
|
|
21
|
-
const result = formatToolCliForPrompt(1);
|
|
22
|
-
expect(result).toContain("prefer the skill");
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it("includes shell chaining and piping examples", () => {
|
|
26
|
-
const result = formatToolCliForPrompt(1);
|
|
27
|
-
expect(result).toContain("grep");
|
|
28
|
-
expect(result).toContain("|");
|
|
29
|
-
expect(result).toContain("jq");
|
|
30
|
-
expect(result).toContain("xargs");
|
|
31
|
-
expect(result).toContain("Prefer piping and chaining");
|
|
32
|
-
});
|
|
33
|
-
});
|
package/src/tool-cli/format.ts
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Format system prompt section advising the agent when and how to use tool-cli.
|
|
3
|
-
*
|
|
4
|
-
* Only included when MCP servers are connected. Tells the agent about
|
|
5
|
-
* progressive discovery via tool-cli as an alternative to skill-based access.
|
|
6
|
-
*/
|
|
7
|
-
export function formatToolCliForPrompt(serverCount: number): string {
|
|
8
|
-
if (serverCount === 0) return "";
|
|
9
|
-
|
|
10
|
-
return `
|
|
11
|
-
|
|
12
|
-
<tool_cli>
|
|
13
|
-
You have access to \`tool-cli\`, a CLI for discovering and calling MCP server tools progressively.
|
|
14
|
-
|
|
15
|
-
Use tool-cli when:
|
|
16
|
-
- No skill covers the task you need to do
|
|
17
|
-
- You want to explore what tools are available on a server
|
|
18
|
-
- You need ad-hoc access to an MCP tool without loading a full skill
|
|
19
|
-
|
|
20
|
-
If a skill exists for the task, prefer the skill — it provides workflow instructions and curated tool access.
|
|
21
|
-
|
|
22
|
-
Discovery (progressive — only fetch what you need):
|
|
23
|
-
tool-cli --help # List MCP servers with tool counts
|
|
24
|
-
tool-cli <server> # List all tools on a server
|
|
25
|
-
tool-cli <server> <tool> # Show full schema for a tool
|
|
26
|
-
|
|
27
|
-
Calling tools:
|
|
28
|
-
tool-cli <server> <tool> '{"key":"value"}' # Call a tool with JSON arguments
|
|
29
|
-
tool-cli <server> <tool> '{}' --out /tmp/result.json # Save large output to file
|
|
30
|
-
|
|
31
|
-
tool-cli outputs plain text or JSON. When a tool provides structured output (typed JSON),
|
|
32
|
-
tool-cli returns it directly as JSON — use \`jq\` to query fields.
|
|
33
|
-
Chain calls, filter, and transform results using pipes and bash idioms:
|
|
34
|
-
|
|
35
|
-
# Search across tool results
|
|
36
|
-
tool-cli myserver search_docs '{"query":"auth"}' | grep -i "token"
|
|
37
|
-
|
|
38
|
-
# Query structured JSON output with jq
|
|
39
|
-
tool-cli myserver list_issues '{"repo":"owner/repo"}' | jq '.[].title'
|
|
40
|
-
|
|
41
|
-
# Chain tool calls — feed one result into another
|
|
42
|
-
tool-cli myserver list_items '{}' | jq -r '.[0].id' | xargs -I{} tool-cli myserver get_item '{"id":"{}"}'
|
|
43
|
-
|
|
44
|
-
# Process multiple items
|
|
45
|
-
for city in London Tokyo Paris; do
|
|
46
|
-
echo "=== $city ==="; tool-cli weather check_weather '{"city":"'$city'"}';
|
|
47
|
-
done
|
|
48
|
-
|
|
49
|
-
# Combine with standard tools
|
|
50
|
-
tool-cli myserver export_csv '{"table":"users"}' | sort -t, -k2 | head -20
|
|
51
|
-
|
|
52
|
-
Prefer piping and chaining over multiple separate tool calls when processing collections or filtering results.
|
|
53
|
-
Errors go to stderr with exit code 1 — use \`&&\` or \`set -e\` for safe chaining.
|
|
54
|
-
${serverCount} MCP server(s) currently connected.
|
|
55
|
-
</tool_cli>`;
|
|
56
|
-
}
|
package/src/tool-cli/index.ts
DELETED
package/tsconfig.json
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"module": "Node16",
|
|
5
|
-
"moduleResolution": "Node16",
|
|
6
|
-
"lib": ["ES2022"],
|
|
7
|
-
"outDir": "dist",
|
|
8
|
-
"rootDir": "src",
|
|
9
|
-
"strict": true,
|
|
10
|
-
"esModuleInterop": true,
|
|
11
|
-
"skipLibCheck": true,
|
|
12
|
-
"forceConsistentCasingInFileNames": true,
|
|
13
|
-
"declaration": true,
|
|
14
|
-
"declarationMap": true,
|
|
15
|
-
"sourceMap": true,
|
|
16
|
-
"resolveJsonModule": true,
|
|
17
|
-
"types": ["node"]
|
|
18
|
-
},
|
|
19
|
-
"include": ["src"],
|
|
20
|
-
"exclude": ["node_modules", "dist"]
|
|
21
|
-
}
|