container/skills/mcp-builder/SKILL.md
Build, register, and use custom MCP servers within this environment. Use this when asked to create a new tool, capability, or integration as an MCP server.
npx skillsauth add sskarz/nanoclawbster mcp-builderInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
MCP (Model Context Protocol) servers extend what I can do by exposing new tools. I can write, register, and use them across sessions.
/workspace/group/mcp-servers/<server-name>/index.js/workspace/group/mcp-servers/package.json/workspace/group/.mcp.jsonAll paths under /workspace/group/ persist across container restarts.
All MCP servers share a single node_modules at the mcp-servers/ root. Only do this once:
mkdir -p /workspace/group/mcp-servers
cd /workspace/group/mcp-servers
if [ ! -f package.json ]; then
npm init -y
# Add "type": "module" for ES module support
node -e "const p=require('./package.json'); p.type='module'; require('fs').writeFileSync('package.json', JSON.stringify(p, null, 2)+'\n')"
npm install @modelcontextprotocol/sdk zod
fi
Create /workspace/group/mcp-servers/<name>/index.js:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new McpServer({ name: "<name>", version: "1.0.0" });
server.tool(
"tool-name",
"Description of what this tool does",
{ param: z.string().describe("A parameter") },
async ({ param }) => ({
content: [{ type: "text", text: `Result: ${param}` }],
})
);
const transport = new StdioServerTransport();
await server.connect(transport);
Node resolves imports from the shared node_modules up the directory tree — no per-server install needed.
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"capabilities":{},"clientInfo":{"name":"test"},"protocolVersion":"2024-11-05"}}' | node /workspace/group/mcp-servers/<name>/index.js
Should return a JSON response without errors.
.mcp.jsonAdd the server to /workspace/group/.mcp.json. If the file doesn't exist, create it:
{
"mcpServers": {
"<name>": {
"command": "node",
"args": ["/workspace/group/mcp-servers/<name>/index.js"]
}
}
}
If .mcp.json already exists, merge the new entry into the existing mcpServers object — don't overwrite other servers.
After creating and registering the server, tell the user:
I've created the
<name>MCP server. It will be available as a tool next time you message me.
The current session cannot pick up newly registered MCP servers. They take effect on the next container invocation.
server.tool("get-time", "Get current time", {}, async () => ({
content: [{ type: "text", text: new Date().toISOString() }],
}));
server.tool(
"fetch-weather",
"Get weather for a city",
{ city: z.string() },
async ({ city }) => {
const res = await fetch(`https://wttr.in/${city}?format=3`);
return { content: [{ type: "text", text: await res.text() }] };
}
);
import { readFileSync, writeFileSync } from "fs";
server.tool("read-notes", "Read saved notes", {}, async () => ({
content: [{ type: "text", text: readFileSync("/workspace/group/notes.md", "utf8") }],
}));
server.tool(
"save-note",
"Save a note",
{ text: z.string() },
async ({ text }) => {
writeFileSync("/workspace/group/notes.md", text);
return { content: [{ type: "text", text: "Saved." }] };
}
);
import { execSync } from "child_process";
server.tool(
"run-command",
"Run a shell command",
{ command: z.string() },
async ({ command }) => {
try {
const output = execSync(command, { timeout: 30000 }).toString();
return { content: [{ type: "text", text: output || "(no output)" }] };
} catch (err) {
return { content: [{ type: "text", text: `Error: ${err.message}` }] };
}
}
);
Group related tools into a single server rather than creating one server per tool:
const server = new McpServer({ name: "project-tools", version: "1.0.0" });
server.tool("lint", "Run linter", {}, async () => { /* ... */ });
server.tool("test", "Run tests", {}, async () => { /* ... */ });
server.tool("deploy", "Deploy to staging", {}, async () => { /* ... */ });
/workspace/group/.mcp.json is valid JSON. A trailing comma or syntax error silently breaks registration.package.json has "type": "module" and that node_modules exists at /workspace/group/mcp-servers/.console.error() for debug output. Stdout is reserved for the JSON-RPC protocol — anything else on stdout breaks communication.# /workspace/group/mcp-servers/<name>/server.py
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("<name>")
@mcp.tool()
def my_tool(param: str) -> str:
"""Description of the tool"""
return f"Result: {param}"
if __name__ == "__main__":
mcp.run()
Install: pip install mcp
Register in /workspace/group/.mcp.json:
{
"mcpServers": {
"<name>": {
"command": "python3",
"args": ["/workspace/group/mcp-servers/<name>/server.py"]
}
}
}
development
Write features, fix bugs, and create PRs for the NanoClawbster codebase. Works in an isolated dev workspace, pushes via Composio (CI validates on GitHub Actions), and deploys after user approval.
development
Browse the web for any task — research topics, read articles, interact with web apps, fill forms, take screenshots, extract data, and test web pages. Use whenever a browser would be useful, not just when the user explicitly asks.
tools
Use when work should span one or more detached tasks but still behave like one job with a single owner context. TaskFlow is the durable flow substrate under authoring layers like Lobster, ACPX, plugins, or plain code. Keep conditional logic in the caller; use TaskFlow for flow identity, child-task linkage, waiting state, revision-checked mutations, and user-facing emergence.
tools
# Lobster Lobster executes multi-step workflows with approval checkpoints. Use it when: - User wants a repeatable automation (triage, monitor, sync) - Actions need human approval before executing (send, post, delete) - Multiple tool calls should run as one deterministic operation ## When to use Lobster | User intent | Use Lobster? | | ------------------------------------------------------ | --------------------------