Skip to main content

outfitter-mcp

Deep patterns for @outfitter/mcp including tool registration, Zod schemas, resources, and server configuration. Use when building MCP servers, registering tools, defining resources, or when "MCP server", "MCP tool", "registerTool", or "@outfitter/mcp" are mentioned.

معلومات المصدر

المستودع
outfitter-dev/outfitter
آخر نشاط في المصدر
١٨ مارس ٢٠٢٦ في ٢٢:٣٠
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٦
التفرعات
١

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
outfitter-mcp
version
0.1.0
description
Deep patterns for @outfitter/mcp including tool registration, Zod schemas, resources, and server configuration. Use when building MCP servers, registering tools, defining resources, or when "MCP server", "MCP tool", "registerTool", or "@outfitter/mcp" are mentioned.
allowed-tools
Read Write Edit Glob Grep
# MCP Server Patterns Deep dive into @outfitter/mcp patterns. ## Creating a Server ```typescript import { createMcpServer } from "@outfitter/mcp"; const server = createMcpServer({ name: "my-server", version: "0.1.0", description: "Server for AI agents", }); // Register tools before start server.registerTool(searchTool); server.registerTool(createTool); // Start server server.start(); ``` ## Tool Definition ### Basic Tool ```typescript import { Result, ValidationError } from "@outfitter/contracts"; import { z } from "zod"; const InputSchema = z.object({ query: z.string().min(1).describe("Search query"), limit: z.number().int().positive().default(10).describe("Max results"), }); export const searchTool = { name: "search", description: "Search for items. Use when user asks to find or search.", inputSchema: InputSchema, handler: async ( input: z.infer<typeof InputSchema> ): Promise<Result<SearchOutput, ValidationError>> => { const results = await performSearch(input.query, input.limit); return Result.ok({ results, total: results.length }); }, }; ``` ### Schema Best Practices ```typescript const InputSchema = z.object({ // Always use .describe() for AI understanding query: z.string().describe("The search term to look for"), // Provide defaults where sensible limit: z.number().default(10).describe("Maximum number of results"), // Use enums for fixed choices sortBy: z .enum(["name", "date", "relevance"]) .default("relevance") .describe("Field to sort results by"), // Mark optional fields explicitly tags: z.array(z.string()).optional().describe("Filter by tags"), }); ``` ### Tool with Context ```typescript export const myTool = { name: "my_tool", description: "Tool description", inputSchema: InputSchema, handler: async (input, ctx) => { ctx.logger.debug("Tool invoked", { input }); const result = await myHandler(input, ctx); if (result.isErr()) { ctx.logger.error("Tool failed", { error: result.error }); } return result; }, }; ``` ## Resources ### Static Resource ```typescript server.registerResource({ uri: "config://settings", name: "Configuration", description: "Current server configuration", mimeType: "application/json", read: async () => { return JSON.stringify(config, null, 2); }, }); ``` ### Dynamic Resource ```typescript server.registerResource({ uri: "data://users/{id}", name: "User Data", description: "User information by ID", mimeType: "application/json", read: async (uri) => { const id = uri.split("/").pop(); const user = await getUser(id); return JSON.stringify(user); }, }); ``` ### Resource List ```typescript server.registerResourceList({ uri: "data://users", name: "Users", description: "List of all users", list: async () => { const users = await getAllUsers(); return users.map((u) => ({ uri: `data://users/${u.id}`, name: u.name, description: u.email, })); }, }); ``` ## Prompts ```typescript server.registerPrompt({ name: "analyze", description: "Analyze data with specific focus", arguments: [ { name: "focus", description: "What to focus on", required: true }, { name: "depth", description: "Analysis depth", required: false }, ], get: async (args) => { return { messages: [ { role: "user", content: { type: "text", text: `Analyze with focus on: ${args.focus}. Depth: ${args.depth || "normal"}`, }, }, ], }; }, }); ``` ## Error Handling ### Returning Errors ```typescript handler: async (input) => { if (!input.query) { return Result.err(ValidationError.create("query", "is required")); } const item = await findItem(input.id); if (!item) { return Result.err(NotFoundError.create("item", input.id)); } return Result.ok(item); }; ``` ### Error Categories in MCP | Category | MCP Behavior | | ---------- | ------------------------------------------- | | validation | Tool returns error with details | | not_found | Tool returns error with resource info | | internal | Tool returns generic error, logs full error | ## Server Configuration ### Claude Desktop Add to `~/Library/Application Support/Claude/claude_desktop_config.json`: ```json { "mcpServers": { "my-server": { "command": "bun", "args": ["run", "/path/to/server.ts"] } } } ``` ### With Environment Variables ```json { "mcpServers": { "my-server": { "command": "bun", "args": ["run", "/path/to/server.ts"], "env": { "API_KEY": "secret", "LOG_LEVEL": "debug" } } } } ``` ## Deferred Tool Loading For tools that are expensive to load: ```typescript server.registerDeferredTool({ name: "heavy_tool", description: "Expensive tool loaded on demand", load: async () => { const { heavyTool } = await import("./heavy-tool.js"); return heavyTool; }, }); ``` ## Testing MCP Servers ```typescript import { createMcpHarness } from "@outfitter/testing"; // Pass the full McpServer instance, not individual tools const harness = createMcpHarness(server); test("tool returns results", async () => { const result = await harness.callTool("my-tool", { query: "test" }); expect(result.isOk()).toBe(true); expect(result.value.results).toHaveLength(3); }); ``` ## Best Practices 1. **Descriptive schemas** — Use `.describe()` on every field 2. **Sensible defaults** — Provide `.default()` where appropriate 3. **Error categories** — Use taxonomy errors for proper handling 4. **Logging** — Log tool invocations for debugging 5. **Deferred loading** — Lazy load expensive tools 6. **Test harnesses** — Use `createMcpHarness` for testing ## Related Skills - `stack:patterns` — Handler contract - `stack:scaffold` — MCP tool template - `stack:debug` — Troubleshooting MCP issues
عرض على GitHub