mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-04-27 01:16:23 +02:00
Cli to dev (#309)
* add workspace access guidelines to instructions * updated example * removed incorrect example * add --example to add the examples from rowboat * changed --example to --sync-example * rename sync-examples option to sync-example in CLI * fix: sync-example implementation * refactor example import * fix yargs * fix: - remove changes to package-lock - remove output messages from app.js and moved them into importExample * fix: restore package-lock.json to match main (remove diff) * fix: naming of the commands * update: made import-example into import and it can import example workflows or user made workflows * update: added export capability * delete: remove misplaced podcast.json file * removed incomplete gemini3-test example json * remove: eliminate gemini3-test example from exports * Fix: better prompting around MCP config Add: copilot tool to add MCP servers * clean up prompt --------- Co-authored-by: Ramnique Singh <30795890+ramnique@users.noreply.github.com>
This commit is contained in:
parent
255bc9c48d
commit
e47518b98f
12 changed files with 1420 additions and 171 deletions
|
|
@ -27,17 +27,27 @@ Always consult this catalog first so you load the right skills before taking act
|
|||
- Use relative paths (no \${BASE_DIR} prefixes) when running commands or referencing files.
|
||||
- Keep user data safe—double-check before editing or deleting important resources.
|
||||
|
||||
## Workspace access & scope
|
||||
- You have full read/write access inside \`${BASE_DIR}\` (this resolves to the user's \`~/.rowboat\` directory). Create folders, files, and agents there using builtin tools or allowed shell commands—don't wait for the user to do it manually.
|
||||
- If a user mentions a different root (e.g., \`~/.rowboatx\` or another path), clarify whether they meant the Rowboat workspace and propose the equivalent path you can act on. Only refuse if they explicitly insist on an inaccessible location.
|
||||
- Prefer builtin file tools (\`createFile\`, \`updateFile\`, \`deleteFile\`, \`exploreDirectory\`) for workspace changes. Reserve refusal or "you do it" responses for cases that are truly outside the Rowboat sandbox.
|
||||
|
||||
## Builtin Tools vs Shell Commands
|
||||
|
||||
**IMPORTANT**: Rowboat provides builtin tools that are internal and do NOT require security allowlist entries:
|
||||
- \`deleteFile\`, \`createFile\`, \`updateFile\`, \`readFile\` - File operations
|
||||
- \`listFiles\`, \`exploreDirectory\` - Directory exploration
|
||||
- \`analyzeAgent\` - Agent analysis
|
||||
- \`listMcpServers\`, \`listMcpTools\` - MCP server management
|
||||
- \`addMcpServer\`, \`listMcpServers\`, \`listMcpTools\` - MCP server management
|
||||
- \`loadSkill\` - Skill loading
|
||||
|
||||
These tools work directly and are NOT filtered by \`.rowboat/config/security.json\`.
|
||||
|
||||
**CRITICAL: MCP Server Configuration**
|
||||
- ALWAYS use the \`addMcpServer\` builtin tool to add or update MCP servers—it validates the configuration before saving
|
||||
- NEVER manually edit \`config/mcp.json\` using \`createFile\` or \`updateFile\` for MCP servers
|
||||
- Invalid MCP configs will prevent the agent from starting with validation errors
|
||||
|
||||
**Only \`executeCommand\` (shell/bash commands) is filtered** by the security allowlist. If you need to delete a file, use the \`deleteFile\` builtin tool, not \`executeCommand\` with \`rm\`. If you need to create a file, use \`createFile\`, not \`executeCommand\` with \`touch\` or \`echo >\`.
|
||||
|
||||
The security allowlist in \`security.json\` only applies to shell commands executed via \`executeCommand\`, not to Rowboat's internal builtin tools.
|
||||
|
|
|
|||
|
|
@ -1,22 +1,225 @@
|
|||
export const skill = String.raw`
|
||||
# MCP Integration Guidance
|
||||
|
||||
Load this skill whenever a user asks about external tools, MCP servers, or how to extend an agent’s capabilities.
|
||||
Load this skill whenever a user asks about external tools, MCP servers, or how to extend an agent's capabilities.
|
||||
|
||||
## Key concepts
|
||||
- MCP servers expose tools (web scraping, APIs, databases, etc.) declared in \`config/mcp.json\`.
|
||||
- Agents reference MCP tools through the \`"tools"\` block by specifying \`type\`, \`name\`, \`description\`, \`mcpServerName\`, and a full \`inputSchema\`.
|
||||
- Tool schemas can include optional property descriptions; only include \`"required"\` when parameters are mandatory.
|
||||
|
||||
## CRITICAL: Adding MCP Servers
|
||||
|
||||
**ALWAYS use the \`addMcpServer\` builtin tool** to add or update MCP server configurations. This tool validates the configuration before saving and prevents startup errors.
|
||||
|
||||
**NEVER manually create or edit \`config/mcp.json\`** using \`createFile\` or \`updateFile\` for MCP servers—this bypasses validation and will cause errors.
|
||||
|
||||
### MCP Server Configuration Schema
|
||||
|
||||
There are TWO types of MCP servers:
|
||||
|
||||
#### 1. STDIO (Command-based) Servers
|
||||
For servers that run as local processes (Node.js, Python, etc.):
|
||||
|
||||
**Required fields:**
|
||||
- \`command\`: string (e.g., "npx", "node", "python", "uvx")
|
||||
|
||||
**Optional fields:**
|
||||
- \`args\`: array of strings (command arguments)
|
||||
- \`env\`: object with string key-value pairs (environment variables)
|
||||
- \`type\`: "stdio" (optional, inferred from presence of \`command\`)
|
||||
|
||||
**Schema:**
|
||||
\`\`\`json
|
||||
{
|
||||
"type": "stdio",
|
||||
"command": "string (REQUIRED)",
|
||||
"args": ["string", "..."],
|
||||
"env": {
|
||||
"KEY": "value"
|
||||
}
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
**Valid STDIO examples:**
|
||||
\`\`\`json
|
||||
{
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/data"]
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
\`\`\`json
|
||||
{
|
||||
"command": "python",
|
||||
"args": ["-m", "mcp_server_git"],
|
||||
"env": {
|
||||
"GIT_REPO_PATH": "/path/to/repo"
|
||||
}
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
\`\`\`json
|
||||
{
|
||||
"command": "uvx",
|
||||
"args": ["mcp-server-fetch"]
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
#### 2. HTTP/SSE Servers
|
||||
For servers that expose HTTP or Server-Sent Events endpoints:
|
||||
|
||||
**Required fields:**
|
||||
- \`url\`: string (complete URL including protocol and path)
|
||||
|
||||
**Optional fields:**
|
||||
- \`headers\`: object with string key-value pairs (HTTP headers)
|
||||
- \`type\`: "http" (optional, inferred from presence of \`url\`)
|
||||
|
||||
**Schema:**
|
||||
\`\`\`json
|
||||
{
|
||||
"type": "http",
|
||||
"url": "string (REQUIRED)",
|
||||
"headers": {
|
||||
"Authorization": "Bearer token",
|
||||
"Custom-Header": "value"
|
||||
}
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
**Valid HTTP examples:**
|
||||
\`\`\`json
|
||||
{
|
||||
"url": "http://localhost:3000/sse"
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
\`\`\`json
|
||||
{
|
||||
"url": "https://api.example.com/mcp",
|
||||
"headers": {
|
||||
"Authorization": "Bearer sk-1234567890"
|
||||
}
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
### Common Validation Errors to Avoid
|
||||
|
||||
❌ **WRONG - Missing required field:**
|
||||
\`\`\`json
|
||||
{
|
||||
"args": ["some-arg"]
|
||||
}
|
||||
\`\`\`
|
||||
Error: Missing \`command\` for stdio OR \`url\` for http
|
||||
|
||||
❌ **WRONG - Empty object:**
|
||||
\`\`\`json
|
||||
{}
|
||||
\`\`\`
|
||||
Error: Must have either \`command\` (stdio) or \`url\` (http)
|
||||
|
||||
❌ **WRONG - Mixed types:**
|
||||
\`\`\`json
|
||||
{
|
||||
"command": "npx",
|
||||
"url": "http://localhost:3000"
|
||||
}
|
||||
\`\`\`
|
||||
Error: Cannot have both \`command\` and \`url\`
|
||||
|
||||
✅ **CORRECT - Minimal stdio:**
|
||||
\`\`\`json
|
||||
{
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-time"]
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
✅ **CORRECT - Minimal http:**
|
||||
\`\`\`json
|
||||
{
|
||||
"url": "http://localhost:3000/sse"
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
### Using addMcpServer Tool
|
||||
|
||||
**Example 1: Add stdio server**
|
||||
\`\`\`json
|
||||
{
|
||||
"serverName": "filesystem",
|
||||
"serverType": "stdio",
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/data"]
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
**Example 2: Add HTTP server**
|
||||
\`\`\`json
|
||||
{
|
||||
"serverName": "custom-api",
|
||||
"serverType": "http",
|
||||
"url": "https://api.example.com/mcp",
|
||||
"headers": {
|
||||
"Authorization": "Bearer token123"
|
||||
}
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
**Example 3: Add Python MCP server**
|
||||
\`\`\`json
|
||||
{
|
||||
"serverName": "github",
|
||||
"serverType": "stdio",
|
||||
"command": "python",
|
||||
"args": ["-m", "mcp_server_github"],
|
||||
"env": {
|
||||
"GITHUB_TOKEN": "ghp_xxxxx"
|
||||
}
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
## Operator actions
|
||||
1. Use \`listMcpServers\` to enumerate configured servers.
|
||||
2. Use \`listMcpTools\` for a server to understand the available operations and schemas.
|
||||
3. Explain which MCP tools match the user’s needs before editing agent definitions.
|
||||
4. When adding a tool to an agent, document what it does and ensure the schema mirrors the MCP definition.
|
||||
2. Use \`addMcpServer\` to add or update MCP server configurations (with validation).
|
||||
3. Use \`listMcpTools\` for a server to understand the available operations and schemas.
|
||||
4. Explain which MCP tools match the user's needs before editing agent definitions.
|
||||
5. When adding a tool to an agent, document what it does and ensure the schema mirrors the MCP definition.
|
||||
|
||||
## Example snippets to reference
|
||||
- Firecrawl search (required param):
|
||||
## Adding MCP Tools to Agents
|
||||
|
||||
Once an MCP server is configured, add its tools to agent definitions:
|
||||
|
||||
### MCP Tool Format in Agent
|
||||
\`\`\`json
|
||||
"tools": {
|
||||
"descriptive_key": {
|
||||
"type": "mcp",
|
||||
"name": "actual_tool_name_from_server",
|
||||
"description": "What the tool does",
|
||||
"mcpServerName": "server_name_from_config",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"param1": {"type": "string", "description": "What param1 means"}
|
||||
},
|
||||
"required": ["param1"]
|
||||
}
|
||||
}
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
### Tool Schema Rules
|
||||
- Use \`listMcpTools\` to get the exact \`inputSchema\` from the server
|
||||
- Copy the schema exactly as provided by the MCP server
|
||||
- Only include \`"required"\` array if parameters are truly mandatory
|
||||
- Add descriptions to help the agent understand parameter usage
|
||||
|
||||
### Example snippets to reference
|
||||
- Firecrawl search (required param):
|
||||
\`\`\`json
|
||||
"tools": {
|
||||
"search": {
|
||||
"type": "mcp",
|
||||
|
|
@ -34,8 +237,9 @@ Load this skill whenever a user asks about external tools, MCP servers, or how t
|
|||
}
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
- ElevenLabs text-to-speech (no required array):
|
||||
\`\`\`
|
||||
\`\`\`json
|
||||
"tools": {
|
||||
"text_to_speech": {
|
||||
"type": "mcp",
|
||||
|
|
@ -52,9 +256,13 @@ Load this skill whenever a user asks about external tools, MCP servers, or how t
|
|||
}
|
||||
\`\`\`
|
||||
|
||||
|
||||
## Safety reminders
|
||||
- Only recommend MCP tools that are actually configured.
|
||||
- Clarify any missing details (required parameters, server names) before modifying files.
|
||||
- ALWAYS use \`addMcpServer\` to configure MCP servers—never manually edit config files
|
||||
- Only recommend MCP tools that are actually configured (use \`listMcpServers\` first)
|
||||
- Clarify any missing details (required parameters, server names) before modifying files
|
||||
- Test server connection with \`listMcpTools\` after adding a new server
|
||||
- Invalid MCP configs prevent agents from starting—validation is critical
|
||||
`;
|
||||
|
||||
export default skill;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,45 @@ Load this skill whenever a user wants to inspect, create, or update agents insid
|
|||
3. The orchestrator calls other agents as tools when needed
|
||||
4. Data flows through tool call parameters and responses
|
||||
|
||||
## Agent format
|
||||
## Agent File Schema
|
||||
|
||||
Agent files MUST conform to this exact schema. Invalid agents will fail to load.
|
||||
|
||||
### Complete Agent Schema
|
||||
\`\`\`json
|
||||
{
|
||||
"name": "string (REQUIRED, must match filename without .json)",
|
||||
"description": "string (REQUIRED, what this agent does)",
|
||||
"instructions": "string (REQUIRED, detailed instructions for the agent)",
|
||||
"model": "string (OPTIONAL, e.g., 'gpt-5.1', 'claude-sonnet-4-5')",
|
||||
"provider": "string (OPTIONAL, provider alias from models.json)",
|
||||
"tools": {
|
||||
"descriptive_key": {
|
||||
"type": "builtin | mcp | agent (REQUIRED)",
|
||||
"name": "string (REQUIRED)",
|
||||
// Additional fields depend on type - see below
|
||||
}
|
||||
}
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
### Required Fields
|
||||
- \`name\`: Agent identifier (must exactly match the filename without .json)
|
||||
- \`description\`: Brief description of agent's purpose
|
||||
- \`instructions\`: Detailed instructions for how the agent should behave
|
||||
|
||||
### Optional Fields
|
||||
- \`model\`: Model to use (defaults to model config if not specified)
|
||||
- \`provider\`: Provider alias from models.json (optional)
|
||||
- \`tools\`: Object containing tool definitions (can be empty or omitted)
|
||||
|
||||
### Naming Rules
|
||||
- Agent filename MUST match the \`name\` field exactly
|
||||
- Example: If \`name\` is "summariser_agent", file must be "summariser_agent.json"
|
||||
- Use lowercase with underscores for multi-word names
|
||||
- No spaces or special characters in names
|
||||
|
||||
### Agent Format Example
|
||||
\`\`\`json
|
||||
{
|
||||
"name": "agent_name",
|
||||
|
|
@ -43,9 +81,26 @@ Load this skill whenever a user wants to inspect, create, or update agents insid
|
|||
}
|
||||
\`\`\`
|
||||
|
||||
## Tool types
|
||||
## Tool Types & Schemas
|
||||
|
||||
### Builtin tools
|
||||
Tools in agents must follow one of three types. Each has specific required fields.
|
||||
|
||||
### 1. Builtin Tools
|
||||
Internal Rowboat tools (executeCommand, file operations, MCP queries, etc.)
|
||||
|
||||
**Schema:**
|
||||
\`\`\`json
|
||||
{
|
||||
"type": "builtin",
|
||||
"name": "tool_name"
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
**Required fields:**
|
||||
- \`type\`: Must be "builtin"
|
||||
- \`name\`: Builtin tool name (e.g., "executeCommand", "readFile")
|
||||
|
||||
**Example:**
|
||||
\`\`\`json
|
||||
"bash": {
|
||||
"type": "builtin",
|
||||
|
|
@ -53,7 +108,42 @@ Load this skill whenever a user wants to inspect, create, or update agents insid
|
|||
}
|
||||
\`\`\`
|
||||
|
||||
### MCP tools
|
||||
**Available builtin tools:**
|
||||
- \`executeCommand\` - Execute shell commands
|
||||
- \`readFile\`, \`createFile\`, \`updateFile\`, \`deleteFile\` - File operations
|
||||
- \`listFiles\`, \`exploreDirectory\` - Directory operations
|
||||
- \`analyzeAgent\` - Analyze agent structure
|
||||
- \`addMcpServer\`, \`listMcpServers\`, \`listMcpTools\` - MCP management
|
||||
- \`loadSkill\` - Load skill guidance
|
||||
|
||||
### 2. MCP Tools
|
||||
Tools from external MCP servers (APIs, databases, web scraping, etc.)
|
||||
|
||||
**Schema:**
|
||||
\`\`\`json
|
||||
{
|
||||
"type": "mcp",
|
||||
"name": "tool_name_from_server",
|
||||
"description": "What the tool does",
|
||||
"mcpServerName": "server_name_from_config",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"param": {"type": "string", "description": "Parameter description"}
|
||||
},
|
||||
"required": ["param"]
|
||||
}
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
**Required fields:**
|
||||
- \`type\`: Must be "mcp"
|
||||
- \`name\`: Exact tool name from MCP server
|
||||
- \`description\`: What the tool does (helps agent understand when to use it)
|
||||
- \`mcpServerName\`: Server name from config/mcp.json
|
||||
- \`inputSchema\`: Full JSON Schema object for tool parameters
|
||||
|
||||
**Example:**
|
||||
\`\`\`json
|
||||
"search": {
|
||||
"type": "mcp",
|
||||
|
|
@ -70,17 +160,40 @@ Load this skill whenever a user wants to inspect, create, or update agents insid
|
|||
}
|
||||
\`\`\`
|
||||
|
||||
### Agent tools (for chaining agents)
|
||||
**Important:**
|
||||
- Use \`listMcpTools\` to get the exact inputSchema from the server
|
||||
- Copy the schema exactly—don't modify property types or structure
|
||||
- Only include \`"required"\` array if parameters are mandatory
|
||||
|
||||
### 3. Agent Tools (for chaining agents)
|
||||
Reference other agents as tools to build multi-agent workflows
|
||||
|
||||
**Schema:**
|
||||
\`\`\`json
|
||||
{
|
||||
"type": "agent",
|
||||
"name": "target_agent_name"
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
**Required fields:**
|
||||
- \`type\`: Must be "agent"
|
||||
- \`name\`: Name of the target agent (must exist in agents/ directory)
|
||||
|
||||
**Example:**
|
||||
\`\`\`json
|
||||
"summariser": {
|
||||
"type": "agent",
|
||||
"name": "summariser_agent"
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
**How it works:**
|
||||
- Use \`"type": "agent"\` to call other agents as tools
|
||||
- The target agent will be invoked with the parameters you pass
|
||||
- Results are returned as tool output
|
||||
- This is how you build multi-agent workflows
|
||||
- The referenced agent file must exist (e.g., agents/summariser_agent.json)
|
||||
|
||||
## Complete Multi-Agent Workflow Example
|
||||
|
||||
|
|
@ -156,13 +269,88 @@ Load this skill whenever a user wants to inspect, create, or update agents insid
|
|||
5. **Tool naming**: Use descriptive tool keys (e.g., "summariser", "fetch_data", "analyze")
|
||||
6. **Orchestration**: Create a top-level agent that coordinates the workflow
|
||||
|
||||
## Validation & Best Practices
|
||||
|
||||
### CRITICAL: Schema Compliance
|
||||
- Agent files MUST have \`name\`, \`description\`, and \`instructions\` fields
|
||||
- Agent filename MUST exactly match the \`name\` field
|
||||
- Tools MUST have valid \`type\` ("builtin", "mcp", or "agent")
|
||||
- MCP tools MUST have all required fields: name, description, mcpServerName, inputSchema
|
||||
- Agent tools MUST reference existing agent files
|
||||
- Invalid agents will fail to load and prevent workflow execution
|
||||
|
||||
### File Creation/Update Process
|
||||
1. When creating an agent, use \`createFile\` with complete, valid JSON
|
||||
2. When updating an agent, read it first with \`readFile\`, modify, then use \`updateFile\`
|
||||
3. Validate JSON syntax before writing—malformed JSON breaks the agent
|
||||
4. Test agent loading after creation/update by using \`analyzeAgent\`
|
||||
|
||||
### Common Validation Errors to Avoid
|
||||
|
||||
❌ **WRONG - Missing required fields:**
|
||||
\`\`\`json
|
||||
{
|
||||
"name": "my_agent"
|
||||
// Missing description and instructions
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
❌ **WRONG - Filename mismatch:**
|
||||
- File: agents/my_agent.json
|
||||
- Content: {"name": "myagent", ...}
|
||||
|
||||
❌ **WRONG - Invalid tool type:**
|
||||
\`\`\`json
|
||||
"tool1": {
|
||||
"type": "custom", // Invalid type
|
||||
"name": "something"
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
❌ **WRONG - MCP tool missing required fields:**
|
||||
\`\`\`json
|
||||
"search": {
|
||||
"type": "mcp",
|
||||
"name": "firecrawl_search"
|
||||
// Missing: description, mcpServerName, inputSchema
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
✅ **CORRECT - Minimal valid agent:**
|
||||
\`\`\`json
|
||||
{
|
||||
"name": "simple_agent",
|
||||
"description": "A simple agent",
|
||||
"instructions": "Do simple tasks"
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
✅ **CORRECT - Complete MCP tool:**
|
||||
\`\`\`json
|
||||
"search": {
|
||||
"type": "mcp",
|
||||
"name": "firecrawl_search",
|
||||
"description": "Search the web",
|
||||
"mcpServerName": "firecrawl",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"query": {"type": "string"}
|
||||
}
|
||||
}
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
## Capabilities checklist
|
||||
1. Explore \`agents/\` directory to understand existing agents before editing
|
||||
2. Update files carefully to maintain schema validity
|
||||
3. When creating multi-agent workflows, create an orchestrator agent
|
||||
4. Add other agents as tools with \`"type": "agent"\` for chaining
|
||||
5. List and explore MCP servers/tools when users need new capabilities
|
||||
6. Confirm work done and outline next steps once changes are complete
|
||||
2. Read existing agents with \`readFile\` before making changes
|
||||
3. Validate all required fields are present before creating/updating agents
|
||||
4. Ensure filename matches the \`name\` field exactly
|
||||
5. Use \`analyzeAgent\` to verify agent structure after creation/update
|
||||
6. When creating multi-agent workflows, create an orchestrator agent
|
||||
7. Add other agents as tools with \`"type": "agent"\` for chaining
|
||||
8. Use \`listMcpServers\` and \`listMcpTools\` when adding MCP integrations
|
||||
9. Confirm work done and outline next steps once changes are complete
|
||||
`;
|
||||
|
||||
export default skill;
|
||||
|
|
|
|||
|
|
@ -12,19 +12,6 @@ let modelConfig: z.infer<typeof ModelConfig> | null = null;
|
|||
|
||||
const baseMcpConfig: z.infer<typeof McpServerConfig> = {
|
||||
mcpServers: {
|
||||
firecrawl: {
|
||||
command: "npx",
|
||||
args: ["-y", "supergateway", "--stdio", "npx -y firecrawl-mcp"],
|
||||
env: {
|
||||
FIRECRAWL_API_KEY: "fc-aaacee4bdd164100a4d83af85bef6fdc",
|
||||
},
|
||||
},
|
||||
test: {
|
||||
url: "http://localhost:3000",
|
||||
headers: {
|
||||
"Authorization": "Bearer test",
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
12
apps/cli/src/application/entities/example.ts
Normal file
12
apps/cli/src/application/entities/example.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import z from "zod"
|
||||
import { Agent } from "./agent.js"
|
||||
import { McpServerDefinition } from "./mcp.js"
|
||||
|
||||
export const Example = z.object({
|
||||
id: z.string(),
|
||||
instructions: z.string().optional(),
|
||||
description: z.string().optional(),
|
||||
entryAgent: z.string().optional(),
|
||||
agents: z.array(Agent).optional(),
|
||||
mcpServers: z.record(z.string(), McpServerDefinition).optional(),
|
||||
});
|
||||
|
|
@ -1,16 +1,20 @@
|
|||
import z from "zod";
|
||||
import { z } from "zod";
|
||||
|
||||
const StdioMcpServerConfig = z.object({
|
||||
export const StdioMcpServerConfig = z.object({
|
||||
type: z.literal("stdio").optional(),
|
||||
command: z.string(),
|
||||
args: z.array(z.string()).optional(),
|
||||
env: z.record(z.string(), z.string()).optional(),
|
||||
});
|
||||
|
||||
const HttpMcpServerConfig = z.object({
|
||||
export const HttpMcpServerConfig = z.object({
|
||||
type: z.literal("http").optional(),
|
||||
url: z.string(),
|
||||
headers: z.record(z.string(), z.string()).optional(),
|
||||
});
|
||||
|
||||
export const McpServerDefinition = z.union([StdioMcpServerConfig, HttpMcpServerConfig]);
|
||||
|
||||
export const McpServerConfig = z.object({
|
||||
mcpServers: z.record(z.string(), z.union([StdioMcpServerConfig, HttpMcpServerConfig])),
|
||||
});
|
||||
mcpServers: z.record(z.string(), McpServerDefinition),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/
|
|||
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
||||
import { Client } from "@modelcontextprotocol/sdk/client";
|
||||
import { resolveSkill, availableSkills } from "../assistant/skills/index.js";
|
||||
import { McpServerDefinition, McpServerConfig } from "../entities/mcp.js";
|
||||
|
||||
const BuiltinToolsSchema = z.record(z.string(), z.object({
|
||||
description: z.string(),
|
||||
|
|
@ -305,6 +306,118 @@ export const BuiltinTools: z.infer<typeof BuiltinToolsSchema> = {
|
|||
},
|
||||
},
|
||||
|
||||
addMcpServer: {
|
||||
description: 'Add or update an MCP server in the configuration with validation. This ensures the server definition is valid before saving.',
|
||||
inputSchema: z.object({
|
||||
serverName: z.string().describe('Name/alias for the MCP server'),
|
||||
serverType: z.enum(['stdio', 'http']).describe('Type of MCP server: "stdio" for command-based or "http" for HTTP/SSE-based'),
|
||||
command: z.string().optional().describe('Command to execute (required for stdio type, e.g., "npx", "python", "node")'),
|
||||
args: z.array(z.string()).optional().describe('Command arguments (optional, for stdio type)'),
|
||||
env: z.record(z.string(), z.string()).optional().describe('Environment variables (optional, for stdio type)'),
|
||||
url: z.string().optional().describe('HTTP/SSE endpoint URL (required for http type)'),
|
||||
headers: z.record(z.string(), z.string()).optional().describe('HTTP headers (optional, for http type)'),
|
||||
}),
|
||||
execute: async ({ serverName, serverType, command, args, env, url, headers }: {
|
||||
serverName: string;
|
||||
serverType: 'stdio' | 'http';
|
||||
command?: string;
|
||||
args?: string[];
|
||||
env?: Record<string, string>;
|
||||
url?: string;
|
||||
headers?: Record<string, string>;
|
||||
}) => {
|
||||
try {
|
||||
// Build server definition based on type
|
||||
let serverDef: any;
|
||||
if (serverType === 'stdio') {
|
||||
if (!command) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'For stdio type servers, "command" is required. Example: "npx" or "python"',
|
||||
validationErrors: ['Missing required field: command'],
|
||||
};
|
||||
}
|
||||
serverDef = {
|
||||
type: 'stdio',
|
||||
command,
|
||||
...(args ? { args } : {}),
|
||||
...(env ? { env } : {}),
|
||||
};
|
||||
} else if (serverType === 'http') {
|
||||
if (!url) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'For http type servers, "url" is required. Example: "http://localhost:3000/sse"',
|
||||
validationErrors: ['Missing required field: url'],
|
||||
};
|
||||
}
|
||||
serverDef = {
|
||||
type: 'http',
|
||||
url,
|
||||
...(headers ? { headers } : {}),
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
success: false,
|
||||
message: `Invalid serverType: ${serverType}. Must be "stdio" or "http"`,
|
||||
validationErrors: [`Invalid serverType: ${serverType}`],
|
||||
};
|
||||
}
|
||||
|
||||
// Validate against Zod schema
|
||||
const validationResult = McpServerDefinition.safeParse(serverDef);
|
||||
if (!validationResult.success) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Server definition failed validation. Check the errors below.',
|
||||
validationErrors: validationResult.error.issues.map((e: any) => `${e.path.join('.')}: ${e.message}`),
|
||||
providedDefinition: serverDef,
|
||||
};
|
||||
}
|
||||
|
||||
// Read existing config
|
||||
const configPath = path.join(BASE_DIR, 'config', 'mcp.json');
|
||||
let currentConfig: z.infer<typeof McpServerConfig> = { mcpServers: {} };
|
||||
try {
|
||||
const content = await fs.readFile(configPath, 'utf-8');
|
||||
currentConfig = McpServerConfig.parse(JSON.parse(content));
|
||||
} catch (error: any) {
|
||||
if (error?.code !== 'ENOENT') {
|
||||
return {
|
||||
success: false,
|
||||
message: `Failed to read existing MCP config: ${error.message}`,
|
||||
};
|
||||
}
|
||||
// File doesn't exist, use empty config
|
||||
}
|
||||
|
||||
// Check if server already exists
|
||||
const isUpdate = !!currentConfig.mcpServers[serverName];
|
||||
|
||||
// Add/update server
|
||||
currentConfig.mcpServers[serverName] = validationResult.data;
|
||||
|
||||
// Write back to file
|
||||
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
||||
await fs.writeFile(configPath, JSON.stringify(currentConfig, null, 2), 'utf-8');
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: `MCP server '${serverName}' ${isUpdate ? 'updated' : 'added'} successfully`,
|
||||
serverName,
|
||||
serverType,
|
||||
isUpdate,
|
||||
configuration: validationResult.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
message: `Failed to add MCP server: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
listMcpServers: {
|
||||
description: 'List all available MCP servers from the configuration',
|
||||
inputSchema: z.object({}),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue